diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c0e18e1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,36 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "npm" + + - name: Install dependencies + run: npm ci + + - name: Run Lint + run: npm run lint + + - name: Build + run: npm run build + env: + NEXT_PUBLIC_TAMBO_API_KEY: "dummy-key-for-build" + NEXT_PUBLIC_TAMBO_URL: "https://api.tambo.co" diff --git a/.gitignore b/.gitignore index 5ef6a52..7be1c20 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# claude code local settings +.claude/settings.local.json diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..2312dc5 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/package-lock.json b/package-lock.json index 8d0c8ab..070d813 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,11 +13,13 @@ "@dnd-kit/utilities": "^3.2.2", "@modelcontextprotocol/sdk": "^1.25.2", "@radix-ui/react-dropdown-menu": "2.1.16", + "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-tooltip": "1.2.8", - "@tailwindcss/oxide": "^4.1.17", - "@tambo-ai/react": "^0.65.2", - "@tambo-ai/typescript-sdk": "^0.79.0", + "@tailwindcss/oxide": "^4.1.18", + "@tambo-ai/react": "^0.69.1", + "@tambo-ai/typescript-sdk": "^0.84.0", "@tiptap/extension-document": "^3.12.1", + "@tiptap/extension-hard-break": "^3.16.0", "@tiptap/extension-mention": "^3.12.1", "@tiptap/extension-paragraph": "^3.12.1", "@tiptap/extension-placeholder": "^3.12.1", @@ -25,34 +27,35 @@ "@tiptap/react": "^3.12.1", "@tiptap/suggestion": "^3.12.1", "class-variance-authority": "^0.7.1", - "dompurify": "^3.3.0", - "framer-motion": "^12.23.25", + "dompurify": "^3.3.1", + "framer-motion": "^12.29.0", "highlight.js": "^11.11.1", "json-stringify-pretty-compact": "^4.0.0", - "lucide-react": "^0.555.0", - "next": "15.5.9", + "lucide-react": "^0.562.0", + "next": "^15.5.10", "radix-ui": "^1.4.3", "react": "^19.1.1", "react-dom": "^19.1.1", "react-markdown": "^10.1.0", - "recharts": "^3.5.1", - "streamdown": "^1.6.10", + "recharts": "^3.7.0", + "streamdown": "^2.1.0", "tippy.js": "^6.3.7", + "use-debounce": "^10.1.0", "zod": "^3.25.76", "zustand": "^5.0.8" }, "devDependencies": { "@eslint/eslintrc": "^3", - "@tailwindcss/postcss": "^4.1.17", - "@types/dompurify": "^3.2.0", + "@tailwindcss/postcss": "^4.1.18", "@types/node": "^24", "@types/react": "^19", "@types/react-dom": "^19", - "@types/recharts": "^2.0.1", - "autoprefixer": "^10.4.22", + "autoprefixer": "^10.4.23", "clsx": "^2.1.1", "eslint": "^9", - "eslint-config-next": "16.0.7", + "eslint-config-next": "16.1.4", + "husky": "^9.1.7", + "lint-staged": "^16.2.7", "postcss": "^8.5.6", "tailwind-merge": "^3.4.0", "tailwindcss": "^4", @@ -71,19 +74,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@antfu/install-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", - "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", - "license": "MIT", - "dependencies": { - "package-manager-detector": "^1.3.0", - "tinyexec": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -115,7 +105,6 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -378,51 +367,6 @@ "node": ">=6.9.0" } }, - "node_modules/@braintree/sanitize-url": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz", - "integrity": "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==", - "license": "MIT" - }, - "node_modules/@chevrotain/cst-dts-gen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", - "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/gast": "11.0.3", - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" - } - }, - "node_modules/@chevrotain/gast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", - "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" - } - }, - "node_modules/@chevrotain/regexp-to-ast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", - "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", - "license": "Apache-2.0" - }, - "node_modules/@chevrotain/types": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", - "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", - "license": "Apache-2.0" - }, - "node_modules/@chevrotain/utils": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", - "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", - "license": "Apache-2.0" - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -452,7 +396,6 @@ "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", "license": "MIT", - "peer": true, "dependencies": { "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", @@ -493,7 +436,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.3.1.tgz", "integrity": "sha512-pVGjBIt1Y6gg3EJN8jTcfpP/+uuRksIo055oE/OBkDNcjZqVbfkWCksG1Jp4yZnj3iKWyWX8fdG/j6UDYPbFog==", - "dev": true, "optional": true, "dependencies": { "@emnapi/wasi-threads": "1.0.1", @@ -514,7 +456,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", - "dev": true, "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -561,12 +502,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -575,19 +517,24 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", - "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -596,10 +543,11 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", - "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -607,7 +555,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -619,30 +567,36 @@ } }, "node_modules/@eslint/js": { - "version": "9.22.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", - "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", - "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.12.0", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -663,7 +617,6 @@ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", "license": "MIT", - "peer": true, "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" @@ -761,23 +714,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@iconify/types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", - "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", - "license": "MIT" - }, - "node_modules/@iconify/utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", - "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", - "license": "MIT", - "dependencies": { - "@antfu/install-pkg": "^1.1.0", - "@iconify/types": "^2.0.0", - "mlly": "^1.8.0" - } - }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.34.3", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", @@ -1265,15 +1201,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@mermaid-js/parser": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", - "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", - "license": "MIT", - "dependencies": { - "langium": "3.3.1" - } - }, "node_modules/@modelcontextprotocol/sdk": { "version": "1.25.2", "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.2.tgz", @@ -1339,7 +1266,6 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.7.tgz", "integrity": "sha512-5yximcFK5FNompXfJFoWanu5l8v1hNGqNHh9du1xETp9HWk/B/PzvchX55WYOPaIeNglG8++68AAiauBAtbnzw==", - "dev": true, "optional": true, "dependencies": { "@emnapi/core": "^1.3.1", @@ -1348,15 +1274,15 @@ } }, "node_modules/@next/env": { - "version": "15.5.9", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.9.tgz", - "integrity": "sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==", + "version": "15.5.10", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.10.tgz", + "integrity": "sha512-plg+9A/KoZcTS26fe15LHg+QxReTazrIOoKKUC3Uz4leGGeNPgLHdevVraAAOX0snnUs3WkRx3eUQpj9mreG6A==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "16.0.7", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.0.7.tgz", - "integrity": "sha512-hFrTNZcMEG+k7qxVxZJq3F32Kms130FAhG8lvw2zkKBgAcNOJIxlljNiCjGygvBshvaGBdf88q2CqWtnqezDHA==", + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.1.4.tgz", + "integrity": "sha512-38WMjGP8y+1MN4bcZFs+GTcBe0iem5GGTzFE5GWW/dWdRKde7LOXH3lQT2QuoquVWyfl2S0fQRchGmeacGZ4Wg==", "dev": true, "license": "MIT", "dependencies": { @@ -3076,7 +3002,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@rtsao/scc": { "version": "1.1.0", @@ -3084,77 +3011,55 @@ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", "dev": true }, - "node_modules/@shikijs/core": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.19.0.tgz", - "integrity": "sha512-L7SrRibU7ZoYi1/TrZsJOFAnnHyLTE1SwHG1yNWjZIVCqjOEmCSuK2ZO9thnRbJG6TOkPp+Z963JmpCNw5nzvA==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.19.0", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.5" - } - }, - "node_modules/@shikijs/engine-javascript": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.19.0.tgz", - "integrity": "sha512-ZfWJNm2VMhKkQIKT9qXbs76RRcT0SF/CAvEz0+RkpUDAoDaCx0uFdCGzSRiD9gSlhm6AHkjdieOBJMaO2eC1rQ==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.19.0", - "@shikijs/vscode-textmate": "^10.0.2", - "oniguruma-to-es": "^4.3.4" - } - }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.19.0.tgz", - "integrity": "sha512-1hRxtYIJfJSZeM5ivbUXv9hcJP3PWRo5prG/V2sWwiubUKTa+7P62d2qxCW8jiVFX4pgRHhnHNp+qeR7Xl+6kg==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.19.0", - "@shikijs/vscode-textmate": "^10.0.2" - } - }, - "node_modules/@shikijs/langs": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.19.0.tgz", - "integrity": "sha512-dBMFzzg1QiXqCVQ5ONc0z2ebyoi5BKz+MtfByLm0o5/nbUu3Iz8uaTCa5uzGiscQKm7lVShfZHU1+OG3t5hgwg==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.19.0" - } - }, - "node_modules/@shikijs/themes": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.19.0.tgz", - "integrity": "sha512-H36qw+oh91Y0s6OlFfdSuQ0Ld+5CgB/VE6gNPK+Hk4VRbVG/XQgkjnt4KzfnnoO6tZPtKJKHPjwebOCfjd6F8A==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.19.0" - } - }, - "node_modules/@shikijs/types": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.19.0.tgz", - "integrity": "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ==", + "node_modules/@standard-community/standard-json": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@standard-community/standard-json/-/standard-json-0.3.5.tgz", + "integrity": "sha512-4+ZPorwDRt47i+O7RjyuaxHRK/37QY/LmgxlGrRrSTLYoFatEOzvqIc85GTlM18SFZ5E91C+v0o/M37wZPpUHA==", "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "peerDependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/json-schema": "^7.0.15", + "@valibot/to-json-schema": "^1.3.0", + "arktype": "^2.1.20", + "effect": "^3.16.8", + "quansync": "^0.2.11", + "sury": "^10.0.0", + "typebox": "^1.0.17", + "valibot": "^1.1.0", + "zod": "^3.25.0 || ^4.0.0", + "zod-to-json-schema": "^3.24.5" + }, + "peerDependenciesMeta": { + "@valibot/to-json-schema": { + "optional": true + }, + "arktype": { + "optional": true + }, + "effect": { + "optional": true + }, + "sury": { + "optional": true + }, + "typebox": { + "optional": true + }, + "valibot": { + "optional": true + }, + "zod": { + "optional": true + }, + "zod-to-json-schema": { + "optional": true + } } }, - "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "license": "MIT" - }, "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "license": "MIT" }, "node_modules/@standard-schema/utils": { @@ -3172,9 +3077,9 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.17.tgz", - "integrity": "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", + "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3184,36 +3089,36 @@ "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.17" + "tailwindcss": "4.1.18" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.17.tgz", - "integrity": "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", + "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", "license": "MIT", "engines": { "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.17", - "@tailwindcss/oxide-darwin-arm64": "4.1.17", - "@tailwindcss/oxide-darwin-x64": "4.1.17", - "@tailwindcss/oxide-freebsd-x64": "4.1.17", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.17", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.17", - "@tailwindcss/oxide-linux-x64-musl": "4.1.17", - "@tailwindcss/oxide-wasm32-wasi": "4.1.17", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.17" + "@tailwindcss/oxide-android-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-x64": "4.1.18", + "@tailwindcss/oxide-freebsd-x64": "4.1.18", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-x64-musl": "4.1.18", + "@tailwindcss/oxide-wasm32-wasi": "4.1.18", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.17.tgz", - "integrity": "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", + "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", "cpu": [ "arm64" ], @@ -3227,9 +3132,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.17.tgz", - "integrity": "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", + "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", "cpu": [ "arm64" ], @@ -3243,9 +3148,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.17.tgz", - "integrity": "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", + "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", "cpu": [ "x64" ], @@ -3259,9 +3164,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.17.tgz", - "integrity": "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", + "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", "cpu": [ "x64" ], @@ -3275,9 +3180,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.17.tgz", - "integrity": "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", + "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", "cpu": [ "arm" ], @@ -3291,9 +3196,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.17.tgz", - "integrity": "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", + "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", "cpu": [ "arm64" ], @@ -3307,9 +3212,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.17.tgz", - "integrity": "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", + "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", "cpu": [ "arm64" ], @@ -3323,9 +3228,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.17.tgz", - "integrity": "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", + "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", "cpu": [ "x64" ], @@ -3339,9 +3244,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.17.tgz", - "integrity": "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", + "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", "cpu": [ "x64" ], @@ -3355,9 +3260,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.17.tgz", - "integrity": "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", + "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -3372,10 +3277,10 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.6.0", - "@emnapi/runtime": "^1.6.0", + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.0.7", + "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, @@ -3383,64 +3288,10 @@ "node": ">=14.0.0" } }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.6.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.6.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.0.7", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.5.0", - "@emnapi/runtime": "^1.5.0", - "@tybys/wasm-util": "^0.10.1" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { - "version": "2.8.1", - "inBundle": true, - "license": "0BSD", - "optional": true - }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz", - "integrity": "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", + "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", "cpu": [ "arm64" ], @@ -3454,9 +3305,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.17.tgz", - "integrity": "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", + "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", "cpu": [ "x64" ], @@ -3470,52 +3321,59 @@ } }, "node_modules/@tailwindcss/postcss": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.17.tgz", - "integrity": "sha512-+nKl9N9mN5uJ+M7dBOOCzINw94MPstNR/GtIhz1fpZysxL/4a+No64jCBD6CPN+bIHWFx3KWuu8XJRrj/572Dw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz", + "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==", "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.17", - "@tailwindcss/oxide": "4.1.17", + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", "postcss": "^8.4.41", - "tailwindcss": "4.1.17" + "tailwindcss": "4.1.18" } }, "node_modules/@tambo-ai/react": { - "version": "0.65.2", - "resolved": "https://registry.npmjs.org/@tambo-ai/react/-/react-0.65.2.tgz", - "integrity": "sha512-V8YlVSCFGGdyCJSL3EmnPIaDgtASGz6ua52/HWPFrRObLLHeRLLUEJ0C4T524iRcgmYOa+MJJHfRM4nELZf3zg==", + "version": "0.69.1", + "resolved": "https://registry.npmjs.org/@tambo-ai/react/-/react-0.69.1.tgz", + "integrity": "sha512-YlBgRLSywFmpO+QgQ1KmjZkgFvfYf+bTZW2AK2LoqjoMCSyI0BO/w+uK/gDOxgutubB9tJPf0kmqfF+FynbkBw==", + "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.22.0", - "@tambo-ai/typescript-sdk": "^0.77.0", - "@tanstack/react-query": "^5.90.10", + "@standard-community/standard-json": "^0.3.5", + "@standard-schema/spec": "^1.1.0", + "@tambo-ai/typescript-sdk": "^0.80.0", + "@tanstack/react-query": "^5.90.16", "fast-equals": "^5.3.3", "partial-json": "^0.1.7", "react-fast-compare": "^3.2.2", "react-media-recorder": "^1.7.2", "ts-essentials": "^10.1.1", "ts-node": "^10.9.2", - "use-debounce": "^10.0.6", - "zod": "^3.25.76", - "zod-to-json-schema": "^3.24.6" - }, - "engines": { - "node": ">=22", - "npm": ">=11" + "use-debounce": "^10.0.6" }, "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.1", "@types/react": "^18.0.0 || ^19.0.0", "@types/react-dom": "^18.0.0 || ^19.0.0", "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "react-dom": "^18.0.0 || ^19.0.0", + "zod": "^3.25.76 || ~4.0.0", + "zod-to-json-schema": "^3.25.1" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + }, + "zod-to-json-schema": { + "optional": true + } } }, "node_modules/@tambo-ai/react/node_modules/@tambo-ai/typescript-sdk": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@tambo-ai/typescript-sdk/-/typescript-sdk-0.77.0.tgz", - "integrity": "sha512-KNND3ULzpuEvBZSDOCuwE8Aw7oYC4tOQUEnN0n8vTLCl7yuK6BLtfUk3ClS5hqsBfK5nCURlNTZ5CRhyURFheA==", + "version": "0.80.0", + "resolved": "https://registry.npmjs.org/@tambo-ai/typescript-sdk/-/typescript-sdk-0.80.0.tgz", + "integrity": "sha512-bH/+/VYD7HD6xj0+UDihn13psyKmxonpOrNbqMutokS7B7LvvixqPkIjwB+rAjg7jJ5VtLBH8RnY1H7qzs4qvg==", "license": "Apache-2.0", "bin": { "tambo-ai-typescript-sdk": "bin/cli" @@ -3565,18 +3423,18 @@ } }, "node_modules/@tambo-ai/typescript-sdk": { - "version": "0.79.0", - "resolved": "https://registry.npmjs.org/@tambo-ai/typescript-sdk/-/typescript-sdk-0.79.0.tgz", - "integrity": "sha512-DMh/bLyMfnmPsJ7CjnE0YUi2sJu271yf2gwdQPqSac9aY3eIMZM3UJgYXAWGcN7lS5OIVPmDofXXtwXcftjKJA==", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@tambo-ai/typescript-sdk/-/typescript-sdk-0.84.0.tgz", + "integrity": "sha512-1Quu++jrnJcCdnfZPvEYpys3/ZThfZiQO7gxA/CTc+y2jVkk+nL6jdohFsaNDswRJ/f4KLbiZ85PfwP0jYMkFg==", "license": "Apache-2.0", "bin": { "tambo-ai-typescript-sdk": "bin/cli" } }, "node_modules/@tanstack/query-core": { - "version": "5.90.12", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.12.tgz", - "integrity": "sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg==", + "version": "5.90.19", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.19.tgz", + "integrity": "sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA==", "license": "MIT", "funding": { "type": "github", @@ -3584,12 +3442,12 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.90.12", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.12.tgz", - "integrity": "sha512-graRZspg7EoEaw0a8faiUASCyJrqjKPdqJ9EwuDRUF9mEYJ1YPczI9H+/agJ0mOJkPCJDk0lsz5QTrLZ/jQ2rg==", + "version": "5.90.19", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.19.tgz", + "integrity": "sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ==", "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.90.12" + "@tanstack/query-core": "5.90.19" }, "funding": { "type": "github", @@ -3600,9 +3458,9 @@ } }, "node_modules/@tiptap/core": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.12.1.tgz", - "integrity": "sha512-dn5uTnsTUjMze26iRhcus8+2auW9+/vOpk6suXg/lhBp+UzOM+EALKE3S5086ANJNgBh1PDHoBX+r1T7wEmheg==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.16.0.tgz", + "integrity": "sha512-XegRaNuoQ/guzBQU2xHxOwFXXrtoXW9tiyXDhssSqylvZmBVSlRIPNHA6ArkHBKm6ehLf6+6Y9fF3uky1yCXYQ==", "license": "MIT", "peer": true, "funding": { @@ -3610,7 +3468,7 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/pm": "^3.12.1" + "@tiptap/pm": "^3.16.0" } }, "node_modules/@tiptap/extension-bubble-menu": { @@ -3660,6 +3518,19 @@ "@tiptap/pm": "^3.12.1" } }, + "node_modules/@tiptap/extension-hard-break": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.16.0.tgz", + "integrity": "sha512-nwUTixlHYo9V1lfOYsRi2JiAYCRC7pObB3Kt7rEeMxB3XmcRcSpHtxYs6r+TvifsLFys8RG5wOFXIV/YXZHcDg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.16.0" + } + }, "node_modules/@tiptap/extension-mention": { "version": "3.12.1", "resolved": "https://registry.npmjs.org/@tiptap/extension-mention/-/extension-mention-3.12.1.tgz", @@ -3730,9 +3601,9 @@ } }, "node_modules/@tiptap/pm": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.12.1.tgz", - "integrity": "sha512-YGv8uZrTraXzB3DPQYsyIB90Girx5QZdZOBSDj0R2bWSXc2Huqdb9PaulXqDQjEv/dp9x6w6+Q2VNIagCPUQwA==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.16.0.tgz", + "integrity": "sha512-FMxZ6Tc5ONKa/EByDV8lswct6YW2lF/wn11zqXmrfBZhdG7UQPTijpSwb6TCqaO5GOHmixaIaDPj+zimUREHQA==", "license": "MIT", "peer": true, "dependencies": { @@ -3792,7 +3663,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/suggestion/-/suggestion-3.12.1.tgz", "integrity": "sha512-LXuWF1Ow5aoynOBy9YMb89RBJNRzKa9Vy3s90Hve7wtMDV7PlXb5apiNWQsYe+CGXc5bvLYjMFDMbE6ahWcUyA==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -3830,165 +3700,29 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", - "dev": true, "optional": true, "dependencies": { "tslib": "^2.4.0" } }, - "node_modules/@types/d3": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", - "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", - "license": "MIT", - "dependencies": { - "@types/d3-array": "*", - "@types/d3-axis": "*", - "@types/d3-brush": "*", - "@types/d3-chord": "*", - "@types/d3-color": "*", - "@types/d3-contour": "*", - "@types/d3-delaunay": "*", - "@types/d3-dispatch": "*", - "@types/d3-drag": "*", - "@types/d3-dsv": "*", - "@types/d3-ease": "*", - "@types/d3-fetch": "*", - "@types/d3-force": "*", - "@types/d3-format": "*", - "@types/d3-geo": "*", - "@types/d3-hierarchy": "*", - "@types/d3-interpolate": "*", - "@types/d3-path": "*", - "@types/d3-polygon": "*", - "@types/d3-quadtree": "*", - "@types/d3-random": "*", - "@types/d3-scale": "*", - "@types/d3-scale-chromatic": "*", - "@types/d3-selection": "*", - "@types/d3-shape": "*", - "@types/d3-time": "*", - "@types/d3-time-format": "*", - "@types/d3-timer": "*", - "@types/d3-transition": "*", - "@types/d3-zoom": "*" - } - }, "node_modules/@types/d3-array": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", "license": "MIT" }, - "node_modules/@types/d3-axis": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", - "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", - "license": "MIT", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-brush": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", - "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", - "license": "MIT", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-chord": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", - "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", - "license": "MIT" - }, "node_modules/@types/d3-color": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", "license": "MIT" }, - "node_modules/@types/d3-contour": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", - "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", - "license": "MIT", - "dependencies": { - "@types/d3-array": "*", - "@types/geojson": "*" - } - }, - "node_modules/@types/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", - "license": "MIT" - }, - "node_modules/@types/d3-dispatch": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", - "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", - "license": "MIT" - }, - "node_modules/@types/d3-drag": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", - "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", - "license": "MIT", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-dsv": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", - "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", - "license": "MIT" - }, "node_modules/@types/d3-ease": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", "license": "MIT" }, - "node_modules/@types/d3-fetch": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", - "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", - "license": "MIT", - "dependencies": { - "@types/d3-dsv": "*" - } - }, - "node_modules/@types/d3-force": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", - "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", - "license": "MIT" - }, - "node_modules/@types/d3-format": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", - "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", - "license": "MIT" - }, - "node_modules/@types/d3-geo": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", - "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", - "license": "MIT", - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/d3-hierarchy": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", - "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", - "license": "MIT" - }, "node_modules/@types/d3-interpolate": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", @@ -4004,24 +3738,6 @@ "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", "license": "MIT" }, - "node_modules/@types/d3-polygon": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", - "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", - "license": "MIT" - }, - "node_modules/@types/d3-quadtree": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", - "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", - "license": "MIT" - }, - "node_modules/@types/d3-random": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", - "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", - "license": "MIT" - }, "node_modules/@types/d3-scale": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", @@ -4031,18 +3747,6 @@ "@types/d3-time": "*" } }, - "node_modules/@types/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", - "license": "MIT" - }, - "node_modules/@types/d3-selection": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", - "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", - "license": "MIT" - }, "node_modules/@types/d3-shape": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", @@ -4058,37 +3762,12 @@ "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", "license": "MIT" }, - "node_modules/@types/d3-time-format": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", - "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", - "license": "MIT" - }, "node_modules/@types/d3-timer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", "license": "MIT" }, - "node_modules/@types/d3-transition": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", - "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", - "license": "MIT", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-zoom": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", - "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", - "license": "MIT", - "dependencies": { - "@types/d3-interpolate": "*", - "@types/d3-selection": "*" - } - }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -4098,17 +3777,6 @@ "@types/ms": "*" } }, - "node_modules/@types/dompurify": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.2.0.tgz", - "integrity": "sha512-Fgg31wv9QbLDA0SpTOXO3MaxySc4DKGLi8sna4/Utjo4r3ZRPdCt4UQee8BWr+Q5z21yifghREPJGYaEOEIACg==", - "deprecated": "This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed.", - "dev": true, - "license": "MIT", - "dependencies": { - "dompurify": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -4123,12 +3791,6 @@ "@types/estree": "*" } }, - "node_modules/@types/geojson": { - "version": "7946.0.16", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", - "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", - "license": "MIT" - }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", @@ -4141,8 +3803,7 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/json5": { "version": "0.0.29", @@ -4150,23 +3811,19 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "node_modules/@types/katex": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", - "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", - "license": "MIT" - }, "node_modules/@types/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/markdown-it": { "version": "14.1.2", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "license": "MIT", + "peer": true, "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" @@ -4185,7 +3842,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/ms": { "version": "2.1.0", @@ -4198,7 +3856,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.10.0" } @@ -4207,7 +3864,6 @@ "version": "19.0.11", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.11.tgz", "integrity": "sha512-vrdxRZfo9ALXth6yPfV16PYTLZwsUWhVjjC+DkfE5t1suNSbBrWC9YqSuuxJZ8Ps6z1o2ycRpIqzZJIgklq4Tw==", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -4216,22 +3872,10 @@ "version": "19.0.4", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.4.tgz", "integrity": "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==", - "peer": true, "peerDependencies": { "@types/react": "^19.0.0" } }, - "node_modules/@types/recharts": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/recharts/-/recharts-2.0.1.tgz", - "integrity": "sha512-/cFs7oiafzByUwBSWA1IzE6FW+ppPwQAWsDTadSgVOwzveY9MESpyLHyyHY0SfPPKLW4+4qVNYHPXd0rFiC8vg==", - "deprecated": "This is a stub types definition. recharts provides its own type definitions, so you do not need this installed.", - "dev": true, - "license": "MIT", - "dependencies": { - "recharts": "*" - } - }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -4297,7 +3941,6 @@ "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.48.1", "@typescript-eslint/types": "8.48.1", @@ -4679,7 +4322,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4763,6 +4405,35 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/ansi-escapes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", + "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -4992,9 +4663,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.22", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", - "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "version": "10.4.23", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.23.tgz", + "integrity": "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==", "dev": true, "funding": [ { @@ -5012,10 +4683,9 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.27.0", - "caniuse-lite": "^1.0.30001754", + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001760", "fraction.js": "^5.3.4", - "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, @@ -5113,10 +4783,11 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5167,7 +4838,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -5246,9 +4916,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001759", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", - "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", + "version": "1.0.30001765", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001765.tgz", + "integrity": "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==", "funding": [ { "type": "opencollective", @@ -5331,43 +5001,49 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/chevrotain": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", - "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", "license": "Apache-2.0", - "peer": true, "dependencies": { - "@chevrotain/cst-dts-gen": "11.0.3", - "@chevrotain/gast": "11.0.3", - "@chevrotain/regexp-to-ast": "11.0.3", - "@chevrotain/types": "11.0.3", - "@chevrotain/utils": "11.0.3", - "lodash-es": "4.17.21" + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" } }, - "node_modules/chevrotain-allstar": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", - "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, "license": "MIT", "dependencies": { - "lodash-es": "^4.17.21" + "restore-cursor": "^5.0.0" }, - "peerDependencies": { - "chevrotain": "^11.0.0" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/class-variance-authority": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", - "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", - "license": "Apache-2.0", + "node_modules/cli-truncate": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz", + "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==", + "dev": true, + "license": "MIT", "dependencies": { - "clsx": "^2.1.1" + "slice-ansi": "^7.1.0", + "string-width": "^8.0.0" + }, + "engines": { + "node": ">=20" }, "funding": { - "url": "https://polar.sh/cva" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/client-only": { @@ -5427,6 +5103,13 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -5438,12 +5121,13 @@ } }, "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 12" + "node": ">=20" } }, "node_modules/compilerr": { @@ -5467,12 +5151,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "license": "MIT" - }, "node_modules/content-disposition": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", @@ -5533,15 +5211,6 @@ "node": ">= 0.10" } }, - "node_modules/cose-base": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", - "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", - "license": "MIT", - "dependencies": { - "layout-base": "^1.0.0" - } - }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -5552,7 +5221,8 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -5572,96 +5242,6 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, - "node_modules/cytoscape": { - "version": "3.33.1", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", - "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cytoscape-cose-bilkent": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", - "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", - "license": "MIT", - "dependencies": { - "cose-base": "^1.0.0" - }, - "peerDependencies": { - "cytoscape": "^3.2.0" - } - }, - "node_modules/cytoscape-fcose": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", - "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", - "license": "MIT", - "dependencies": { - "cose-base": "^2.2.0" - }, - "peerDependencies": { - "cytoscape": "^3.2.0" - } - }, - "node_modules/cytoscape-fcose/node_modules/cose-base": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", - "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", - "license": "MIT", - "dependencies": { - "layout-base": "^2.0.0" - } - }, - "node_modules/cytoscape-fcose/node_modules/layout-base": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", - "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", - "license": "MIT" - }, - "node_modules/d3": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", - "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", - "license": "ISC", - "dependencies": { - "d3-array": "3", - "d3-axis": "3", - "d3-brush": "3", - "d3-chord": "3", - "d3-color": "3", - "d3-contour": "4", - "d3-delaunay": "6", - "d3-dispatch": "3", - "d3-drag": "3", - "d3-dsv": "3", - "d3-ease": "3", - "d3-fetch": "3", - "d3-force": "3", - "d3-format": "3", - "d3-geo": "3", - "d3-hierarchy": "3", - "d3-interpolate": "3", - "d3-path": "3", - "d3-polygon": "3", - "d3-quadtree": "3", - "d3-random": "3", - "d3-scale": "4", - "d3-scale-chromatic": "3", - "d3-selection": "3", - "d3-shape": "3", - "d3-time": "3", - "d3-time-format": "4", - "d3-timer": "3", - "d3-transition": "3", - "d3-zoom": "3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/d3-array": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", @@ -5674,43 +5254,6 @@ "node": ">=12" } }, - "node_modules/d3-axis": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-brush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", - "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "3", - "d3-transition": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", - "license": "ISC", - "dependencies": { - "d3-path": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", @@ -5720,98 +5263,6 @@ "node": ">=12" } }, - "node_modules/d3-contour": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", - "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", - "license": "ISC", - "dependencies": { - "d3-array": "^3.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", - "license": "ISC", - "dependencies": { - "delaunator": "5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dsv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", - "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", - "license": "ISC", - "dependencies": { - "commander": "7", - "iconv-lite": "0.6", - "rw": "1" - }, - "bin": { - "csv2json": "bin/dsv2json.js", - "csv2tsv": "bin/dsv2dsv.js", - "dsv2dsv": "bin/dsv2dsv.js", - "dsv2json": "bin/dsv2json.js", - "json2csv": "bin/json2dsv.js", - "json2dsv": "bin/json2dsv.js", - "json2tsv": "bin/json2dsv.js", - "tsv2csv": "bin/dsv2dsv.js", - "tsv2json": "bin/dsv2json.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dsv/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/d3-dsv/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/d3-ease": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", @@ -5821,32 +5272,6 @@ "node": ">=12" } }, - "node_modules/d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", - "license": "ISC", - "dependencies": { - "d3-dsv": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/d3-format": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", @@ -5856,27 +5281,6 @@ "node": ">=12" } }, - "node_modules/d3-geo": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", - "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2.5.0 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/d3-interpolate": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", @@ -5898,67 +5302,6 @@ "node": ">=12" } }, - "node_modules/d3-polygon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-sankey": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", - "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "1 - 2", - "d3-shape": "^1.2.0" - } - }, - "node_modules/d3-sankey/node_modules/d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "license": "BSD-3-Clause", - "dependencies": { - "internmap": "^1.0.0" - } - }, - "node_modules/d3-sankey/node_modules/d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-sankey/node_modules/d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-path": "1" - } - }, "node_modules/d3-scale": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", @@ -5975,29 +5318,6 @@ "node": ">=12" } }, - "node_modules/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/d3-shape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", @@ -6043,51 +5363,6 @@ "node": ">=12" } }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dagre-d3-es": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", - "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", - "license": "MIT", - "dependencies": { - "d3": "^7.9.0", - "lodash-es": "^4.17.21" - } - }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -6154,12 +5429,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dayjs": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", - "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", - "license": "MIT" - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -6236,15 +5505,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delaunator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", - "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", - "license": "ISC", - "dependencies": { - "robust-predicates": "^3.0.2" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6293,9 +5553,9 @@ } }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -6314,9 +5574,9 @@ } }, "node_modules/dompurify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.0.tgz", - "integrity": "sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -6364,9 +5624,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6382,6 +5642,7 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=0.12" }, @@ -6389,6 +5650,19 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/es-abstract": { "version": "1.24.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", @@ -6594,33 +5868,32 @@ } }, "node_modules/eslint": { - "version": "9.22.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", - "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.2", - "@eslint/config-helpers": "^0.1.0", - "@eslint/core": "^0.12.0", - "@eslint/eslintrc": "^3.3.0", - "@eslint/js": "9.22.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -6655,13 +5928,13 @@ } }, "node_modules/eslint-config-next": { - "version": "16.0.7", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.0.7.tgz", - "integrity": "sha512-WubFGLFHfk2KivkdRGfx6cGSFhaQqhERRfyO8BRx+qiGPGp7WLKcPvYC4mdx1z3VhVRcrfFzczjjTrbJZOpnEQ==", + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.1.4.tgz", + "integrity": "sha512-iCrrNolUPpn/ythx0HcyNRfUBgTkaNBXByisKUbusPGCl8DMkDXXAu7exlSTSLGTIsH9lFE/c4s/3Qiyv2qwdA==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "16.0.7", + "@next/eslint-plugin-next": "16.1.4", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", @@ -6782,7 +6055,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -6937,10 +6209,11 @@ } }, "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -6966,14 +6239,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6999,6 +6273,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -7075,7 +6350,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -7271,9 +6545,9 @@ "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, "license": "ISC", "dependencies": { @@ -7400,13 +6674,13 @@ } }, "node_modules/framer-motion": { - "version": "12.23.25", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.25.tgz", - "integrity": "sha512-gUHGl2e4VG66jOcH0JHhuJQr6ZNwrET9g31ZG0xdXzT0CznP7fHX4P8Bcvuc4MiUB90ysNnWX2ukHRIggkl6hQ==", + "version": "12.29.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.29.0.tgz", + "integrity": "sha512-1gEFGXHYV2BD42ZPTFmSU9buehppU+bCuOnHU0AD18DKh9j4DuTx47MvqY5ax+NNWRtK32qIcJf1UxKo1WwjWg==", "license": "MIT", "dependencies": { - "motion-dom": "^12.23.23", - "motion-utils": "^12.23.6", + "motion-dom": "^12.29.0", + "motion-utils": "^12.27.2", "tslib": "^2.4.0" }, "peerDependencies": { @@ -7486,6 +6760,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -7632,12 +6907,6 @@ "dev": true, "license": "MIT" }, - "node_modules/hachure-fill": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", - "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", - "license": "MIT" - }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -7723,92 +6992,6 @@ "node": ">= 0.4" } }, - "node_modules/hast": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hast/-/hast-1.0.0.tgz", - "integrity": "sha512-vFUqlRV5C+xqP76Wwq2SrM0kipnmpxJm7OfvVXpB35Fp+Fn4MV+ozr+JZr5qFvyR1q/U+Foim2x+3P+x9S1PLA==", - "deprecated": "Renamed to rehype", - "license": "MIT" - }, - "node_modules/hast-util-from-dom": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", - "integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==", - "license": "ISC", - "dependencies": { - "@types/hast": "^3.0.0", - "hastscript": "^9.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-dom/node_modules/hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-dom/node_modules/hastscript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", - "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-html": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", - "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.1.0", - "hast-util-from-parse5": "^8.0.0", - "parse5": "^7.0.0", - "vfile": "^6.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-html-isomorphic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", - "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-from-dom": "^5.0.0", - "hast-util-from-html": "^2.0.0", - "unist-util-remove-position": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/hast-util-from-parse5": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", @@ -7859,19 +7042,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-is-element": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", - "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/hast-util-raw": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", @@ -7897,23 +7067,15 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-to-html": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", - "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "node_modules/hast-util-sanitize": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-5.0.2.tgz", + "integrity": "sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" + "@ungap/structured-clone": "^1.0.0", + "unist-util-position": "^5.0.0" }, "funding": { "type": "opencollective", @@ -7966,22 +7128,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-to-text": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", - "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "hast-util-is-element": "^3.0.0", - "unist-util-find-after": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -8022,9 +7168,9 @@ } }, "node_modules/hono": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.3.tgz", - "integrity": "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w==", + "version": "4.11.7", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz", + "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==", "license": "MIT", "peer": true, "engines": { @@ -8071,6 +7217,22 @@ "url": "https://opencollective.com/express" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/iconv-lite": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", @@ -8101,7 +7263,6 @@ "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -8380,6 +7541,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-generator-function": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", @@ -8761,50 +7938,13 @@ "node": ">=4.0" } }, - "node_modules/katex": { - "version": "0.16.22", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz", - "integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==", - "funding": [ - "https://opencollective.com/katex", - "https://github.com/sponsors/katex" - ], - "license": "MIT", - "dependencies": { - "commander": "^8.3.0" - }, - "bin": { - "katex": "cli.js" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/khroma": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", - "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" - }, - "node_modules/langium": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", - "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", - "license": "MIT", - "dependencies": { - "chevrotain": "~11.0.3", - "chevrotain-allstar": "~0.3.0", - "vscode-languageserver": "~9.0.1", - "vscode-languageserver-textdocument": "~1.0.11", - "vscode-uri": "~3.0.8" - }, - "engines": { - "node": ">=16.0.0" + "json-buffer": "3.0.1" } }, "node_modules/language-subtag-registry": { @@ -8825,12 +7965,6 @@ "node": ">=0.10" } }, - "node_modules/layout-base": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", - "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", - "license": "MIT" - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -9110,10 +8244,54 @@ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "license": "MIT", + "peer": true, "dependencies": { "uc.micro": "^2.0.0" } }, + "node_modules/lint-staged": { + "version": "16.2.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.7.tgz", + "integrity": "sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^14.0.2", + "listr2": "^9.0.5", + "micromatch": "^4.0.8", + "nano-spawn": "^2.0.0", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.8.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -9129,18 +8307,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -9174,9 +8366,9 @@ } }, "node_modules/lucide-react": { - "version": "0.555.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.555.0.tgz", - "integrity": "sha512-D8FvHUGbxWBRQM90NZeIyhAvkFfsh3u9ekrMvJ30Z6gnpBHS6HC6ldLg7tL45hwiIz/u66eKDtdA23gwwGsAHA==", + "version": "0.562.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.562.0.tgz", + "integrity": "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -9203,6 +8395,7 @@ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "license": "MIT", + "peer": true, "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -9226,9 +8419,9 @@ } }, "node_modules/marked": { - "version": "16.4.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", - "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.1.tgz", + "integrity": "sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==", "license": "MIT", "bin": { "marked": "bin/marked.js" @@ -9398,25 +8591,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-math": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", - "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "longest-streak": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.1.0", - "unist-util-remove-position": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdast-util-mdx-expression": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", @@ -9550,7 +8724,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/media-encoder-host": { "version": "8.1.0", @@ -9620,34 +8795,6 @@ "node": ">= 8" } }, - "node_modules/mermaid": { - "version": "11.12.2", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.2.tgz", - "integrity": "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==", - "license": "MIT", - "dependencies": { - "@braintree/sanitize-url": "^7.1.1", - "@iconify/utils": "^3.0.1", - "@mermaid-js/parser": "^0.6.3", - "@types/d3": "^7.4.3", - "cytoscape": "^3.29.3", - "cytoscape-cose-bilkent": "^4.1.0", - "cytoscape-fcose": "^2.2.0", - "d3": "^7.9.0", - "d3-sankey": "^0.12.3", - "dagre-d3-es": "7.0.13", - "dayjs": "^1.11.18", - "dompurify": "^3.2.5", - "katex": "^0.16.22", - "khroma": "^2.1.0", - "lodash-es": "^4.17.21", - "marked": "^16.2.1", - "roughjs": "^4.6.6", - "stylis": "^4.3.6", - "ts-dedent": "^2.2.0", - "uuid": "^11.1.0" - } - }, "node_modules/micromark": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", @@ -9663,7 +8810,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", @@ -9718,77 +8864,6 @@ "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-extension-cjk-friendly": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/micromark-extension-cjk-friendly/-/micromark-extension-cjk-friendly-1.2.3.tgz", - "integrity": "sha512-gRzVLUdjXBLX6zNPSnHGDoo+ZTp5zy+MZm0g3sv+3chPXY7l9gW+DnrcHcZh/jiPR6MjPKO4AEJNp4Aw6V9z5Q==", - "license": "MIT", - "dependencies": { - "devlop": "^1.1.0", - "micromark-extension-cjk-friendly-util": "2.1.1", - "micromark-util-chunked": "^2.0.1", - "micromark-util-resolve-all": "^2.0.1", - "micromark-util-symbol": "^2.0.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "micromark": "^4.0.0", - "micromark-util-types": "^2.0.0" - }, - "peerDependenciesMeta": { - "micromark-util-types": { - "optional": true - } - } - }, - "node_modules/micromark-extension-cjk-friendly-gfm-strikethrough": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/micromark-extension-cjk-friendly-gfm-strikethrough/-/micromark-extension-cjk-friendly-gfm-strikethrough-1.2.3.tgz", - "integrity": "sha512-gSPnxgHDDqXYOBvQRq6lerrq9mjDhdtKn+7XETuXjxWcL62yZEfUdA28Ml1I2vDIPfAOIKLa0h2XDSGkInGHFQ==", - "license": "MIT", - "dependencies": { - "devlop": "^1.1.0", - "get-east-asian-width": "^1.3.0", - "micromark-extension-cjk-friendly-util": "2.1.1", - "micromark-util-character": "^2.1.1", - "micromark-util-chunked": "^2.0.1", - "micromark-util-resolve-all": "^2.0.1", - "micromark-util-symbol": "^2.0.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "micromark": "^4.0.0", - "micromark-util-types": "^2.0.0" - }, - "peerDependenciesMeta": { - "micromark-util-types": { - "optional": true - } - } - }, - "node_modules/micromark-extension-cjk-friendly-util": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-cjk-friendly-util/-/micromark-extension-cjk-friendly-util-2.1.1.tgz", - "integrity": "sha512-egs6+12JU2yutskHY55FyR48ZiEcFOJFyk9rsiyIhcJ6IvWB6ABBqVrBw8IobqJTDZ/wdSr9eoXDPb5S2nW1bg==", - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.0", - "micromark-util-character": "^2.1.1", - "micromark-util-symbol": "^2.0.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependenciesMeta": { - "micromark-util-types": { - "optional": true - } - } - }, "node_modules/micromark-extension-gfm": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", @@ -9910,25 +8985,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/micromark-extension-math": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", - "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", - "license": "MIT", - "dependencies": { - "@types/katex": "^0.16.0", - "devlop": "^1.0.0", - "katex": "^0.16.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/micromark-factory-destination": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", @@ -10300,8 +9356,7 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.8", @@ -10342,6 +9397,19 @@ "url": "https://opencollective.com/express" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -10363,31 +9431,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mlly": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", - "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", - "license": "MIT", - "dependencies": { - "acorn": "^8.15.0", - "pathe": "^2.0.3", - "pkg-types": "^1.3.1", - "ufo": "^1.6.1" - } - }, "node_modules/motion-dom": { - "version": "12.23.23", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz", - "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==", + "version": "12.29.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.29.0.tgz", + "integrity": "sha512-3eiz9bb32yvY8Q6XNM4AwkSOBPgU//EIKTZwsSWgA9uzbPBhZJeScCVcBuwwYVqhfamewpv7ZNmVKTGp5qnzkA==", "license": "MIT", "dependencies": { - "motion-utils": "^12.23.6" + "motion-utils": "^12.27.2" } }, "node_modules/motion-utils": { - "version": "12.23.6", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", - "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", + "version": "12.27.2", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.27.2.tgz", + "integrity": "sha512-B55gcoL85Mcdt2IEStY5EEAsrMSVE2sI14xQ/uAdPL+mfQxhKKFaEag9JmfxedJOR4vZpBGoPeC/Gm13I/4g5Q==", "license": "MIT" }, "node_modules/ms": { @@ -10408,6 +9464,19 @@ "node": ">=12.20.1" } }, + "node_modules/nano-spawn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-2.0.0.tgz", + "integrity": "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -10442,12 +9511,12 @@ } }, "node_modules/next": { - "version": "15.5.9", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.9.tgz", - "integrity": "sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==", + "version": "15.5.10", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.10.tgz", + "integrity": "sha512-r0X65PNwyDDyOrWNKpQoZvOatw7BcsTPRKdwEqtc9cj3wv7mbBIk9tKed4klRaFXJdX0rugpuMTHslDrAU1bBg==", "license": "MIT", "dependencies": { - "@next/env": "15.5.9", + "@next/env": "15.5.10", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", @@ -10527,16 +9596,6 @@ "dev": true, "license": "MIT" }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -10671,21 +9730,20 @@ "wrappy": "1" } }, - "node_modules/oniguruma-parser": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", - "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", - "license": "MIT" - }, - "node_modules/oniguruma-to-es": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.4.tgz", - "integrity": "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==", + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, "license": "MIT", "dependencies": { - "oniguruma-parser": "^0.12.1", - "regex": "^6.0.1", - "regex-recursion": "^6.0.2" + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/optionator": { @@ -10709,7 +9767,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/own-keys": { "version": "1.0.1", @@ -10758,12 +9817,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-manager-detector": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", - "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", - "license": "MIT" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -10840,12 +9893,6 @@ "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", "license": "MIT" }, - "node_modules/path-data-parser": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", - "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", - "license": "MIT" - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -10879,12 +9926,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "license": "MIT" - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -10903,6 +9944,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pkce-challenge": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", @@ -10912,33 +9966,6 @@ "node": ">=16.20.0" } }, - "node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "node_modules/points-on-curve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", - "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", - "license": "MIT" - }, - "node_modules/points-on-path": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", - "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", - "license": "MIT", - "dependencies": { - "path-data-parser": "0.1.0", - "points-on-curve": "0.2.0" - } - }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -10968,7 +9995,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -11020,6 +10046,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz", "integrity": "sha512-j0kORIBm8ayJNl3zQvD1TTPHJX3g042et6y/KQhZhnPrruO8exkTgG8X+NRpj7kIyMMEx74Xb3DyMIBtO0IKkQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-transform": "^1.0.0" } @@ -11029,6 +10056,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.0.0" } @@ -11038,6 +10066,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", @@ -11049,6 +10078,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0", @@ -11060,6 +10090,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.0.tgz", "integrity": "sha512-z00qvurSdCEWUIulij/isHaqu4uLS8r/Fi61IbjdIPJEonQgggbJsLnstW7Lgdk4zQ68/yr6B6bf7sJXowIgdQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-keymap": "^1.0.0", "prosemirror-model": "^1.0.0", @@ -11072,6 +10103,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz", "integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.2.2", "prosemirror-transform": "^1.0.0", @@ -11084,6 +10116,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.1.tgz", "integrity": "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.0.0" @@ -11094,6 +10127,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.0.0", "w3c-keyname": "^2.2.0" @@ -11104,6 +10138,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.2.tgz", "integrity": "sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==", "license": "MIT", + "peer": true, "dependencies": { "@types/markdown-it": "^14.0.0", "markdown-it": "^14.0.0", @@ -11115,6 +10150,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.5.tgz", "integrity": "sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==", "license": "MIT", + "peer": true, "dependencies": { "crelt": "^1.0.0", "prosemirror-commands": "^1.0.0", @@ -11137,6 +10173,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz", "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.25.0" } @@ -11146,6 +10183,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", @@ -11169,6 +10207,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.3.tgz", "integrity": "sha512-wbqCR/RlRPRe41a4LFtmhKElzBEfBTdtAYWNIGHM6X2e24NN/MTNUKyXjjphfAfdQce37Kh/5yf765mLPYDe7Q==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-keymap": "^1.2.3", "prosemirror-model": "^1.25.4", @@ -11182,6 +10221,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", "license": "MIT", + "peer": true, "dependencies": { "@remirror/core-constants": "3.0.0", "escape-string-regexp": "^4.0.0" @@ -11197,6 +10237,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.5.tgz", "integrity": "sha512-RPDQCxIDhIBb1o36xxwsaeAvivO8VLJcgBtzmOwQ64bMtsVFh5SSuJ6dWSxO1UsHTiTXPCgQm3PDJt7p6IOLbw==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.21.0" } @@ -11240,6 +10281,7 @@ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "license": "MIT", + "peer": true, "engines": { "node": ">=6" } @@ -11259,6 +10301,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT", + "peer": true + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -11386,7 +10445,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -11396,7 +10454,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -11413,8 +10470,7 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "peer": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-markdown": { "version": "10.1.0", @@ -11458,7 +10514,6 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "license": "MIT", - "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -11547,9 +10602,9 @@ } }, "node_modules/recharts": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.5.1.tgz", - "integrity": "sha512-+v+HJojK7gnEgG6h+b2u7k8HH7FhyFUzAc4+cPrsjL4Otdgqr/ecXzAnHciqlzV1ko064eNcsdzrYOM78kankA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.7.0.tgz", + "integrity": "sha512-l2VCsy3XXeraxIID9fx23eCb6iCBsxUQDnE8tWm6DFdszVAO7WVY/ChAD9wVit01y6B2PMupYiMmQwhgPHc9Ew==", "license": "MIT", "workspaces": [ "www" @@ -11631,8 +10686,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -11665,30 +10719,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz", - "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==", - "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" - } - }, - "node_modules/regex-recursion": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", - "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", - "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" - } - }, - "node_modules/regex-utilities": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", - "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", - "license": "MIT" - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -11709,32 +10739,13 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rehype-harden": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/rehype-harden/-/rehype-harden-1.1.6.tgz", - "integrity": "sha512-5WyX6BFEWYmmbCF/S2gNRklfgPGTiGjviAjbseO4XlpqEilWBkvWwve6uU/JB3C0JvG/qxCZa3rBn8+ajy4i/A==", - "license": "MIT", - "dependencies": { - "unist-util-visit": "^5.0.0" - } - }, - "node_modules/rehype-katex": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", - "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/katex": "^0.16.0", - "hast-util-from-html-isomorphic": "^2.0.0", - "hast-util-to-text": "^4.0.0", - "katex": "^0.16.0", - "unist-util-visit-parents": "^6.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/rehype-harden": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/rehype-harden/-/rehype-harden-1.1.7.tgz", + "integrity": "sha512-j5DY0YSK2YavvNGV+qBHma15J9m0WZmRe8posT5AtKDS6TNWtMVTo6RiqF8SidfcASYz8f3k2J/1RWmq5zTXUw==", + "license": "MIT", + "dependencies": { + "unist-util-visit": "^5.0.0" } }, "node_modules/rehype-raw": { @@ -11752,46 +10763,18 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/remark-cjk-friendly": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/remark-cjk-friendly/-/remark-cjk-friendly-1.2.3.tgz", - "integrity": "sha512-UvAgxwlNk+l9Oqgl/9MWK2eWRS7zgBW/nXX9AthV7nd/3lNejF138E7Xbmk9Zs4WjTJGs721r7fAEc7tNFoH7g==", - "license": "MIT", - "dependencies": { - "micromark-extension-cjk-friendly": "1.2.3" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@types/mdast": "^4.0.0", - "unified": "^11.0.0" - }, - "peerDependenciesMeta": { - "@types/mdast": { - "optional": true - } - } - }, - "node_modules/remark-cjk-friendly-gfm-strikethrough": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/remark-cjk-friendly-gfm-strikethrough/-/remark-cjk-friendly-gfm-strikethrough-1.2.3.tgz", - "integrity": "sha512-bXfMZtsaomK6ysNN/UGRIcasQAYkC10NtPmP0oOHOV8YOhA2TXmwRXCku4qOzjIFxAPfish5+XS0eIug2PzNZA==", + "node_modules/rehype-sanitize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-sanitize/-/rehype-sanitize-6.0.0.tgz", + "integrity": "sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg==", "license": "MIT", "dependencies": { - "micromark-extension-cjk-friendly-gfm-strikethrough": "1.2.3" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@types/mdast": "^4.0.0", - "unified": "^11.0.0" + "@types/hast": "^3.0.0", + "hast-util-sanitize": "^5.0.0" }, - "peerDependenciesMeta": { - "@types/mdast": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/remark-gfm": { @@ -11812,22 +10795,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/remark-math": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", - "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-math": "^3.0.0", - "micromark-extension-math": "^3.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -11877,9 +10844,9 @@ } }, "node_modules/remend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/remend/-/remend-1.0.1.tgz", - "integrity": "sha512-152puVH0qMoRJQFnaMG+rVDdf01Jq/CaED+MBuXExurJgdbkLp0c3TIe4R12o28Klx8uyGsjvFNG05aFG69G9w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remend/-/remend-1.1.0.tgz", + "integrity": "sha512-JENGyuIhTwzUfCarW43X4r9cehoqTo9QyYxfNDZSud2AmqeuWjZ5pfybasTa4q0dxTJAj5m8NB+wR+YueAFpxQ==", "license": "Apache-2.0" }, "node_modules/require-from-string": { @@ -11935,6 +10902,23 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -11946,29 +10930,19 @@ "node": ">=0.10.0" } }, - "node_modules/robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", - "license": "Unlicense" + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" }, "node_modules/rope-sequence": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", - "license": "MIT" - }, - "node_modules/roughjs": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", - "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", "license": "MIT", - "dependencies": { - "hachure-fill": "^0.5.2", - "path-data-parser": "^0.1.0", - "points-on-curve": "^0.2.0", - "points-on-path": "^0.2.1" - } + "peer": true }, "node_modules/router": { "version": "2.2.0", @@ -12032,12 +11006,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", - "license": "BSD-3-Clause" - }, "node_modules/rxjs-interop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/rxjs-interop/-/rxjs-interop-2.0.0.tgz", @@ -12272,22 +11240,6 @@ "node": ">=8" } }, - "node_modules/shiki": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.19.0.tgz", - "integrity": "sha512-77VJr3OR/VUZzPiStyRhADmO2jApMM0V2b1qf0RpfWya8Zr1PeZev5AEpPGAAKWdiYUtcZGBE4F5QvJml1PvWA==", - "license": "MIT", - "dependencies": { - "@shikijs/core": "3.19.0", - "@shikijs/engine-javascript": "3.19.0", - "@shikijs/engine-oniguruma": "3.19.0", - "@shikijs/langs": "3.19.0", - "@shikijs/themes": "3.19.0", - "@shikijs/types": "3.19.0", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - } - }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -12356,6 +11308,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -12366,6 +11331,36 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -12425,31 +11420,23 @@ } }, "node_modules/streamdown": { - "version": "1.6.10", - "resolved": "https://registry.npmjs.org/streamdown/-/streamdown-1.6.10.tgz", - "integrity": "sha512-B4Y3Z/qiXl1Dc+LzAB5c52Cd1QGRiFjaDwP+ERoj1JtCykdRDM8X6HwQnn3YkpkSk0x3R7S/6LrGe1nQiElHQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/streamdown/-/streamdown-2.1.0.tgz", + "integrity": "sha512-u9gWd0AmjKg1d+74P44XaPlGrMeC21oDOSIhjGNEYMAttDMzCzlJO6lpTyJ9JkSinQQF65YcK4eOd3q9iTvULw==", "license": "Apache-2.0", "dependencies": { "clsx": "^2.1.1", - "hast": "^1.0.0", "hast-util-to-jsx-runtime": "^2.3.6", "html-url-attributes": "^3.0.1", - "katex": "^0.16.22", - "lucide-react": "^0.542.0", - "marked": "^16.2.1", - "mermaid": "^11.11.0", - "rehype-harden": "^1.1.6", - "rehype-katex": "^7.0.1", + "marked": "^17.0.1", + "rehype-harden": "^1.1.7", "rehype-raw": "^7.0.0", - "remark-cjk-friendly": "^1.2.3", - "remark-cjk-friendly-gfm-strikethrough": "^1.2.3", + "rehype-sanitize": "^6.0.0", "remark-gfm": "^4.0.1", - "remark-math": "^6.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", - "remend": "1.0.1", - "shiki": "^3.12.2", - "tailwind-merge": "^3.3.1", + "remend": "1.1.0", + "tailwind-merge": "^3.4.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0" }, @@ -12457,13 +11444,31 @@ "react": "^18.0.0 || ^19.0.0" } }, - "node_modules/streamdown/node_modules/lucide-react": { - "version": "0.542.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.542.0.tgz", - "integrity": "sha512-w3hD8/SQB7+lzU2r4VdFyzzOzKnUjTZIF/MQJGSSvni7Llewni4vuViRppfRAa2guOsY5k4jZyxw/i9DQHv+dw==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", + "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string.prototype.includes": { @@ -12587,6 +11592,22 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -12648,12 +11669,6 @@ } } }, - "node_modules/stylis": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", - "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", - "license": "MIT" - }, "node_modules/subscribable-things": { "version": "2.1.55", "resolved": "https://registry.npmjs.org/subscribable-things/-/subscribable-things-2.1.55.tgz", @@ -12700,9 +11715,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz", - "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", "dev": true, "license": "MIT" }, @@ -12726,15 +11741,6 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "license": "MIT" }, - "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -12776,7 +11782,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -12848,15 +11853,6 @@ "typescript": ">=4.8.4" } }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "license": "MIT", - "engines": { - "node": ">=6.10" - } - }, "node_modules/ts-essentials": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-10.1.1.tgz", @@ -12993,7 +11989,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13030,13 +12025,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "license": "MIT" - }, - "node_modules/ufo": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/unbox-primitive": { "version": "1.1.0", @@ -13067,7 +12057,6 @@ "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "license": "MIT", - "peer": true, "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", @@ -13082,20 +12071,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-find-after": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", - "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unist-util-is": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", @@ -13122,20 +12097,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-remove-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", - "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", @@ -13249,9 +12210,9 @@ } }, "node_modules/use-debounce": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.6.tgz", - "integrity": "sha512-C5OtPyhAZgVoteO9heXMTdW7v/IbFI+8bSVKYCJrSmiWWCLsbUxiBSp4t9v0hNBTGY97bT72ydDIDyGSFWfwXg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.1.0.tgz", + "integrity": "sha512-lu87Za35V3n/MyMoEpD5zJv0k7hCn0p+V/fK2kWD+3k2u3kOCwO593UArbczg1fhfs2rqPEnHpULJ3KmGdDzvg==", "license": "MIT", "engines": { "node": ">= 16.0.0" @@ -13291,19 +12252,6 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -13383,60 +12331,12 @@ "d3-timer": "^3.0.1" } }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/vscode-languageserver": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", - "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", - "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.17.5" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", - "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "license": "MIT" - }, - "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", - "license": "MIT" - }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/web-namespaces": { "version": "2.0.1", @@ -13567,6 +12467,62 @@ "tslib": "^2.8.1" } }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -13580,6 +12536,22 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -13606,15 +12578,14 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zod-to-json-schema": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", + "version": "3.25.1", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", "license": "ISC", "peerDependencies": { "zod": "^3.25 || ^4" diff --git a/package.json b/package.json index 429be81..7daae7e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,14 @@ "build": "next build", "start": "next start", "lint": "next lint", - "init": "npx tambo init" + "init": "npx tambo init", + "prepare": "husky" + }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "eslint --fix", + "eslint" + ] }, "dependencies": { "@dnd-kit/core": "^6.3.1", @@ -15,11 +22,13 @@ "@dnd-kit/utilities": "^3.2.2", "@modelcontextprotocol/sdk": "^1.25.2", "@radix-ui/react-dropdown-menu": "2.1.16", + "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-tooltip": "1.2.8", - "@tailwindcss/oxide": "^4.1.17", - "@tambo-ai/react": "^0.65.2", - "@tambo-ai/typescript-sdk": "^0.79.0", + "@tailwindcss/oxide": "^4.1.18", + "@tambo-ai/react": "^0.69.1", + "@tambo-ai/typescript-sdk": "^0.84.0", "@tiptap/extension-document": "^3.12.1", + "@tiptap/extension-hard-break": "^3.16.0", "@tiptap/extension-mention": "^3.12.1", "@tiptap/extension-paragraph": "^3.12.1", "@tiptap/extension-placeholder": "^3.12.1", @@ -27,34 +36,35 @@ "@tiptap/react": "^3.12.1", "@tiptap/suggestion": "^3.12.1", "class-variance-authority": "^0.7.1", - "dompurify": "^3.3.0", - "framer-motion": "^12.23.25", + "dompurify": "^3.3.1", + "framer-motion": "^12.29.0", "highlight.js": "^11.11.1", "json-stringify-pretty-compact": "^4.0.0", - "lucide-react": "^0.555.0", - "next": "15.5.9", + "lucide-react": "^0.562.0", + "next": "^15.5.10", "radix-ui": "^1.4.3", "react": "^19.1.1", "react-dom": "^19.1.1", "react-markdown": "^10.1.0", - "recharts": "^3.5.1", - "streamdown": "^1.6.10", + "recharts": "^3.7.0", + "streamdown": "^2.1.0", "tippy.js": "^6.3.7", + "use-debounce": "^10.1.0", "zod": "^3.25.76", "zustand": "^5.0.8" }, "devDependencies": { "@eslint/eslintrc": "^3", - "@tailwindcss/postcss": "^4.1.17", - "@types/dompurify": "^3.2.0", + "@tailwindcss/postcss": "^4.1.18", "@types/node": "^24", "@types/react": "^19", "@types/react-dom": "^19", - "@types/recharts": "^2.0.1", - "autoprefixer": "^10.4.22", + "autoprefixer": "^10.4.23", "clsx": "^2.1.1", "eslint": "^9", - "eslint-config-next": "16.0.7", + "eslint-config-next": "16.1.4", + "husky": "^9.1.7", + "lint-staged": "^16.2.7", "postcss": "^8.5.6", "tailwind-merge": "^3.4.0", "tailwindcss": "^4", diff --git a/src/app/chat/page.tsx b/src/app/chat/page.tsx index 6af947d..8b139c4 100644 --- a/src/app/chat/page.tsx +++ b/src/app/chat/page.tsx @@ -7,11 +7,47 @@ import { InteractableTabs } from "@/components/ui/interactable-tabs"; import { components, tools } from "@/lib/tambo"; import { TamboProvider } from "@tambo-ai/react"; import { TamboMcpProvider } from "@tambo-ai/react/mcp"; +import { useSyncExternalStore } from "react"; + +const STORAGE_KEY = "tambo-demo-context-key"; + +function getContextKey(): string { + let key = localStorage.getItem(STORAGE_KEY); + if (!key) { + key = crypto.randomUUID(); + localStorage.setItem(STORAGE_KEY, key); + } + return key; +} + +function subscribe(callback: () => void): () => void { + window.addEventListener("storage", callback); + return () => window.removeEventListener("storage", callback); +} + +/** + * Gets or creates a unique context key for thread isolation. + * + * NOTE: For production, use `userToken` prop instead of `contextKey`. + * The userToken integrates with your auth provider (e.g., Better Auth, Clerk) + * for proper user isolation with token refresh handling. + * + * Example: + * const userToken = useUserToken(); // from your auth provider + * + */ +function useContextKey(): string | null { + return useSyncExternalStore(subscribe, getContextKey, () => null); +} export default function Home() { const mcpServers = useMcpServers(); + const contextKey = useContextKey(); - // You can customize default suggestions via MessageThreadFull internals + // Wait for contextKey to be loaded from localStorage + if (!contextKey) { + return null; + } return (
@@ -21,11 +57,12 @@ export default function Home() { components={components} tools={tools} mcpServers={mcpServers} + contextKey={contextKey} >
- +
{/* Tabs interactable manages tabs state only */} diff --git a/src/components/tambo/dictation-button.tsx b/src/components/tambo/dictation-button.tsx index ce3d3e9..4ba0b46 100644 --- a/src/components/tambo/dictation-button.tsx +++ b/src/components/tambo/dictation-button.tsx @@ -50,7 +50,8 @@ export default function DictationButton() { @@ -60,7 +61,8 @@ export default function DictationButton() { diff --git a/src/components/tambo/elicitation-ui.tsx b/src/components/tambo/elicitation-ui.tsx index 44ad7bb..f62fcf6 100644 --- a/src/components/tambo/elicitation-ui.tsx +++ b/src/components/tambo/elicitation-ui.tsx @@ -8,49 +8,8 @@ import { import * as React from "react"; import { useMemo, useState } from "react"; -/** - * JSON Schema field types for elicitation - * Defined locally since the MCP SDK types requestedSchema as unknown - */ -interface BaseFieldSchema { - type: "string" | "number" | "integer" | "boolean"; - description?: string; - default?: unknown; -} - -interface StringFieldSchema extends BaseFieldSchema { - type: "string"; - enum?: string[]; - enumNames?: string[]; - minLength?: number; - maxLength?: number; - pattern?: string; - format?: "email" | "uri" | "date" | "date-time" | string; -} - -interface NumberFieldSchema extends BaseFieldSchema { - type: "number" | "integer"; - minimum?: number; - maximum?: number; -} - -interface BooleanFieldSchema extends BaseFieldSchema { - type: "boolean"; -} - -type FieldSchema = StringFieldSchema | NumberFieldSchema | BooleanFieldSchema; - -interface ElicitationSchema { - properties: Record; - required?: string[]; -} - -/** - * Type-safe accessor for elicitation request schema - */ -function getRequestSchema(request: TamboElicitationRequest): ElicitationSchema { - return request.requestedSchema as ElicitationSchema; -} +type FieldSchema = + TamboElicitationRequest["requestedSchema"]["properties"][string]; /** * Props for individual field components @@ -330,18 +289,16 @@ const Field: React.FC = (props) => { * (one field that is boolean or enum) */ function isSingleEntryMode(request: TamboElicitationRequest): boolean { - const schema = getRequestSchema(request); - const fields = Object.entries(schema.properties); + const fields = Object.entries(request.requestedSchema.properties); if (fields.length !== 1) { return false; } - const [, fieldSchema] = fields[0]; + const [, schema] = fields[0]; return ( - fieldSchema.type === "boolean" || - (fieldSchema.type === "string" && "enum" in fieldSchema) + schema.type === "boolean" || (schema.type === "string" && "enum" in schema) ); } @@ -492,14 +449,13 @@ export const ElicitationUI: React.FC = ({ className, }) => { const singleEntry = isSingleEntryMode(request); - const schema = getRequestSchema(request); const fields = useMemo( - () => Object.entries(schema.properties), - [schema.properties], + () => Object.entries(request.requestedSchema.properties), + [request.requestedSchema.properties], ); const requiredFields = useMemo( - () => schema.required ?? [], - [schema.required], + () => request.requestedSchema.required ?? [], + [request.requestedSchema.required], ); const [formData, setFormData] = useState>(() => { const initial: Record = {}; @@ -658,7 +614,7 @@ export const ElicitationUI: React.FC = ({ type="button" onClick={handleAccept} disabled={!isValid} - className="px-6 py-2 text-sm rounded-lg bg-black/80 text-white hover:bg-black/70 disabled:opacity-50 disabled:cursor-not-allowed transition-colors" + className="px-6 py-2 text-sm rounded-lg bg-foreground text-background hover:bg-foreground/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors" > Submit diff --git a/src/components/tambo/graph.tsx b/src/components/tambo/graph.tsx index 56a90d7..6910d41 100644 --- a/src/components/tambo/graph.tsx +++ b/src/components/tambo/graph.tsx @@ -4,7 +4,7 @@ import { cn } from "@/lib/utils"; import { cva } from "class-variance-authority"; import * as React from "react"; import * as RechartsCore from "recharts"; -import { z } from "zod"; +import { z } from "zod/v3"; /** * Type for graph variant @@ -156,7 +156,12 @@ export type GraphProps = z.infer; export type GraphDataType = z.infer; /** - * Default colors for the Graph component + * Default colors for the Graph component. + * + * Color handling: our v4 theme defines CSS variables like `--border`, + * `--muted-foreground`, and `--chart-1` as full OKLCH color values in + * `globals-v4.css`, so we pass them directly as `var(--token)` to + * Recharts/SVG props instead of wrapping them in `hsl()`/`oklch()`. */ const defaultColors = [ "hsl(220, 100%, 62%)", // Blue @@ -191,12 +196,15 @@ export const Graph = React.forwardRef( { className, variant, size, data, title, showLegend = true, ...props }, ref, ) => { + // Use larger size for pie charts by default to give them more room + const effectiveSize = size ?? (data?.type === "pie" ? "lg" : "default"); + // If no data received yet, show loading if (!data) { return (
@@ -227,7 +235,7 @@ export const Graph = React.forwardRef( return (
@@ -252,7 +260,7 @@ export const Graph = React.forwardRef( return (
@@ -460,10 +468,10 @@ export const Graph = React.forwardRef( }; return ( - +
diff --git a/src/components/tambo/markdown-components.tsx b/src/components/tambo/markdown-components.tsx index 441e8e6..ca31df3 100644 --- a/src/components/tambo/markdown-components.tsx +++ b/src/components/tambo/markdown-components.tsx @@ -1,11 +1,11 @@ "use client"; -import * as React from "react"; import { cn } from "@/lib/utils"; -import { Copy, Check, ExternalLink } from "lucide-react"; +import DOMPurify from "dompurify"; import hljs from "highlight.js"; import "highlight.js/styles/github.css"; -import DOMPurify from "dompurify"; +import { Check, Copy, ExternalLink, X } from "lucide-react"; +import * as React from "react"; /** * Markdown Components for Streamdown @@ -47,6 +47,22 @@ const looksLikeCode = (text: string): boolean => { return codeIndicators.some((pattern) => pattern.test(text)); }; +/** + * Resource mention component that displays resource names. + * Matches the styling from text-editor.tsx mention components. + */ +function ResourceMention({ name, uri }: { name: string; uri: string }) { + return ( + + @{name} + + ); +} + /** * Header component for code blocks with language display and copy functionality */ @@ -58,27 +74,48 @@ const CodeHeader = ({ code?: string; }) => { const [copied, setCopied] = React.useState(false); + const [error, setError] = React.useState(false); + const timeoutRef = React.useRef | null>(null); - const copyToClipboard = () => { + const copyToClipboard = async () => { if (!code) return; - void navigator.clipboard.writeText(code); - setCopied(true); - setTimeout(() => setCopied(false), 2000); + + // Clear any existing timeout to prevent race conditions + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + + try { + await navigator.clipboard.writeText(code); + setCopied(true); + setError(false); + } catch (err) { + console.error("Failed to copy code to clipboard:", err); + setError(true); + } + timeoutRef.current = setTimeout(() => setError(false), 2000); }; + const Icon = React.useMemo(() => { + if (error) { + return ; + } + if (copied) { + return ; + } + return ; + }, [copied, error]); + return (
{language}
); @@ -115,7 +152,7 @@ export const createMarkdownComponents = (): Record< className={cn( "overflow-x-auto rounded-b-md bg-background", "[&::-webkit-scrollbar]:w-[6px]", - "[&::-webkit-scrollbar-thumb]:bg-gray-300 [&::-webkit-scrollbar-thumb]:rounded-md", + "[&::-webkit-scrollbar-thumb]:bg-muted-foreground/30 [&::-webkit-scrollbar-thumb]:rounded-md", "[&::-webkit-scrollbar:horizontal]:h-[4px]", )} > @@ -209,20 +246,55 @@ export const createMarkdownComponents = (): Record< /** * Anchor component for links - * Opens links in new tab with security attributes - * Includes hover underline effect + * Detects tambo-resource:// URIs and renders them as ResourceMention components. + * Regular links open in new tab with security attributes. */ - a: ({ href, children }) => ( - - {children} - - - ), + a: ({ href, children }) => { + // Check if href uses tambo-resource:// protocol to signal it's a resource + if (href?.startsWith("tambo-resource://")) { + // Extract encoded URI (everything after tambo-resource://) + const encodedUri = href.slice("tambo-resource://".length); + // Decode the URI + let uri: string; + try { + uri = decodeURIComponent(encodedUri); + } catch { + // If decoding fails, use the encoded version as fallback + uri = encodedUri; + } + // Extract name from children (link text) + // Handle different children types (string, number, array, etc.) + let name: string; + if (typeof children === "string") { + name = children; + } else if (typeof children === "number") { + name = String(children); + } else if (Array.isArray(children)) { + // If children is an array, join string elements + name = children + .map((child) => + typeof child === "string" ? child : String(child ?? ""), + ) + .join(""); + } else { + name = String(children ?? uri); + } + return ; + } + + // Regular link rendering + return ( + + {children} + + + ); + }, /** * Horizontal rule component diff --git a/src/components/tambo/mcp-components.tsx b/src/components/tambo/mcp-components.tsx index cc448a5..e84e9e7 100644 --- a/src/components/tambo/mcp-components.tsx +++ b/src/components/tambo/mcp-components.tsx @@ -102,7 +102,7 @@ export const McpPromptButton = React.forwardRef< void; filteredResources: ReturnType["data"]; isLoading: boolean; - onSelectResource: (uri: string) => void; + onSelectResource: (id: string, label: string) => void; } /** @@ -209,7 +209,7 @@ const ResourceCombobox: React.FC = ({ return ( ["data"]; searchQuery: string; - onSelectResource: (uri: string) => void; + onSelectResource: (id: string, label: string) => void; }) { if (isLoading) { return ( @@ -288,10 +288,13 @@ function ResourceListContent({ <> {filteredResources.map((resourceEntry) => ( { - onSelectResource(resourceEntry.resource.uri); + onSelectResource( + resourceEntry.resource.uri, + resourceEntry.resource.name || resourceEntry.resource.uri, + ); }} >
@@ -320,7 +323,7 @@ function ResourceListContent({ */ export interface McpResourceButtonProps extends React.ButtonHTMLAttributes { /** Callback to insert text into the input */ - onInsertText: (text: string) => void; + onInsertResource: (id: string, label: string) => void; /** Current input value */ value: string; /** Optional custom className */ @@ -342,8 +345,7 @@ export interface McpResourceButtonProps extends React.ButtonHTMLAttributes(({ className, onInsertText, value, ...props }, ref) => { +>(({ className, onInsertResource, value: _value, ...props }, ref) => { const { data: resourceList, isLoading } = useTamboMcpResourceList(); const [isOpen, setIsOpen] = React.useState(false); const [searchQuery, setSearchQuery] = React.useState(""); @@ -368,10 +370,9 @@ export const McpResourceButton = React.forwardRef< }); }, [resourceList, searchQuery]); - const handleSelectResource = (resourceUri: string) => { - // Pass raw @resource string to caller; caller decides how to insert - const resourceRef = `@${resourceUri}`; - onInsertText(resourceRef); + const handleSelectResource = (id: string, label: string) => { + // Pass raw resource string to caller; caller decides how to insert + onInsertResource(id, label); setIsOpen(false); setSearchQuery(""); }; diff --git a/src/components/tambo/mcp-config-modal.tsx b/src/components/tambo/mcp-config-modal.tsx index b65446d..fdb3a82 100644 --- a/src/components/tambo/mcp-config-modal.tsx +++ b/src/components/tambo/mcp-config-modal.tsx @@ -142,14 +142,13 @@ export const McpConfigModal = ({ After configuring your MCP servers below, integrate them into your application. -#### 1. Import the required components +#### 1. Import the required hook \`\`\`tsx import { useMcpServers } from "@/components/tambo/mcp-config-modal"; -import { TamboMcpProvider } from "@tambo-ai/react/mcp"; \`\`\` -#### 2. Load MCP servers and wrap your components: +#### 2. Load MCP servers and pass to TamboProvider: \`\`\`tsx const mcpServers = useMcpServers(); @@ -162,10 +161,13 @@ function MyApp() { const mcpServers = useMcpServers(); // Reactive - updates when servers change return ( - - - {/* Your app components */} - + + {/* Your app components */} ); } @@ -469,9 +471,9 @@ export type McpServer = string | { url: string }; * // Returns: [{ url: "https://api.example.com" }, "https://api2.example.com"] * * return ( - * + * * {children} - * + * * ); * } * ``` diff --git a/src/components/tambo/message-input.tsx b/src/components/tambo/message-input.tsx index 2f6a20e..c067e5f 100644 --- a/src/components/tambo/message-input.tsx +++ b/src/components/tambo/message-input.tsx @@ -5,7 +5,7 @@ import { McpPromptButton, McpResourceButton, } from "@/components/tambo/mcp-components"; -import { McpConfigModal } from "@/components/tambo/mcp-config-modal"; +import { McpConfigModal } from "./mcp-config-modal"; import { Tooltip, TooltipProvider, @@ -17,28 +17,270 @@ import { useTamboThreadInput, type StagedImage, } from "@tambo-ai/react"; -import type { Editor } from "@tiptap/react"; -import { TextEditor, type ResourceItem } from "./text-editor"; import { useTamboElicitationContext, + useTamboMcpPrompt, + useTamboMcpPromptList, + useTamboMcpResourceList, type TamboElicitationRequest, type TamboElicitationResponse, } from "@tambo-ai/react/mcp"; import { cva, type VariantProps } from "class-variance-authority"; import { ArrowUp, + AtSign, + FileText, Image as ImageIcon, Paperclip, Square, X, } from "lucide-react"; -import dynamic from "next/dynamic"; -import Image from "next/image"; import * as React from "react"; +import { useDebounce } from "use-debounce"; +import { + getImageItems, + TextEditor, + type PromptItem, + type ResourceItem, + type TamboEditor, +} from "./text-editor"; -const DictationButton = dynamic(() => import("./dictation-button"), { - ssr: false, -}); +// Lazy load DictationButton for code splitting (framework-agnostic alternative to next/dynamic) +// eslint-disable-next-line @typescript-eslint/promise-function-async +const LazyDictationButton = React.lazy(() => import("./dictation-button")); + +/** + * Wrapper component that includes Suspense boundary for the lazy-loaded DictationButton. + * This ensures the component can be safely used without requiring consumers to add their own Suspense. + * Also handles SSR by only rendering on the client (DictationButton uses Web Audio APIs). + */ +const DictationButton = () => { + const [isMounted, setIsMounted] = React.useState(false); + + React.useEffect(() => { + setIsMounted(true); + }, []); + + if (!isMounted) { + return null; + } + + return ( + + + + ); +}; + +/** + * Provider interface for searching resources (for "@" mentions). + * Empty query string "" should return all available resources. + */ +export interface ResourceProvider { + /** Search for resources matching the query */ + search(query: string): Promise; +} + +/** + * Provider interface for searching and fetching prompts (for "/" commands). + * Empty query string "" should return all available prompts. + */ +export interface PromptProvider { + /** Search for prompts matching the query */ + search(query: string): Promise; + /** Get the full prompt details including text by ID */ + get(id: string): Promise; +} + +/** + * Removes duplicate resource items based on ID. + */ +const dedupeResourceItems = (resourceItems: ResourceItem[]) => { + const seen = new Set(); + return resourceItems.filter((item) => { + if (seen.has(item.id)) return false; + seen.add(item.id); + return true; + }); +}; + +/** + * Filters resource items by query string. + * Empty query returns all items. + */ +const filterResourceItems = ( + resourceItems: ResourceItem[], + query: string, +): ResourceItem[] => { + if (query === "") return resourceItems; + + const normalizedQuery = query.toLocaleLowerCase(); + return resourceItems.filter((item) => + item.name.toLocaleLowerCase().includes(normalizedQuery), + ); +}; + +/** + * Filters prompt items by query string. + * Empty query returns all items. + */ +const filterPromptItems = ( + promptItems: PromptItem[], + query: string, +): PromptItem[] => { + if (query === "") return promptItems; + + const normalizedQuery = query.toLocaleLowerCase(); + return promptItems.filter((item) => + item.name.toLocaleLowerCase().includes(normalizedQuery), + ); +}; + +const EXTERNAL_SEARCH_DEBOUNCE_MS = 200; + +/** + * Hook to get a combined resource list that merges MCP resources with an external provider. + * Returns the combined, filtered resource items. + * + * @param externalProvider - Optional external resource provider + * @param search - Search string to filter resources. For MCP servers, results are filtered locally. + * For registry dynamic sources, the search is passed to listResources(search). + */ +function useCombinedResourceList( + externalProvider: ResourceProvider | undefined, + search: string, +): ResourceItem[] { + const { data: mcpResources } = useTamboMcpResourceList(search); + const [debouncedSearch] = useDebounce(search, EXTERNAL_SEARCH_DEBOUNCE_MS); + + // Convert MCP resources to ResourceItems + const mcpItems: ResourceItem[] = React.useMemo( + () => + mcpResources + ? ( + mcpResources as { + resource: { uri: string; name?: string }; + }[] + ).map((entry) => ({ + // Use the full URI (already includes serverKey prefix from MCP hook) + // When inserted as @{id}, parseResourceReferences will strip serverKey before sending to backend + id: entry.resource.uri, + name: entry.resource.name ?? entry.resource.uri, + icon: React.createElement(AtSign, { className: "w-4 h-4" }), + componentData: { type: "mcp-resource", data: entry }, + })) + : [], + [mcpResources], + ); + + // Track external provider results with state + const [externalItems, setExternalItems] = React.useState([]); + + // Fetch external resources when search changes + React.useEffect(() => { + if (!externalProvider) { + setExternalItems([]); + return; + } + + let cancelled = false; + externalProvider + .search(debouncedSearch) + .then((items) => { + if (!cancelled) { + setExternalItems(items); + } + }) + .catch((error) => { + console.error("Failed to fetch external resources", error); + if (!cancelled) { + setExternalItems([]); + } + }); + + return () => { + cancelled = true; + }; + }, [externalProvider, debouncedSearch]); + + // Combine and dedupe - MCP resources are already filtered by the hook + // External items need to be filtered locally + const combined = React.useMemo(() => { + const filteredExternal = filterResourceItems(externalItems, search); + return dedupeResourceItems([...mcpItems, ...filteredExternal]); + }, [mcpItems, externalItems, search]); + + return combined; +} + +/** + * Hook to get a combined prompt list that merges MCP prompts with an external provider. + * Returns the combined, filtered prompt items. + * + * @param externalProvider - Optional external prompt provider + * @param search - Search string to filter prompts by name. MCP prompts are filtered via the hook. + */ +function useCombinedPromptList( + externalProvider: PromptProvider | undefined, + search: string, +): PromptItem[] { + // Pass search to MCP hook for filtering + const { data: mcpPrompts } = useTamboMcpPromptList(search); + const [debouncedSearch] = useDebounce(search, EXTERNAL_SEARCH_DEBOUNCE_MS); + + // Convert MCP prompts to PromptItems (mark with mcp-prompt: prefix for special handling) + const mcpItems: PromptItem[] = React.useMemo( + () => + mcpPrompts + ? (mcpPrompts as { prompt: { name: string } }[]).map((entry) => ({ + id: `mcp-prompt:${entry.prompt.name}`, + name: entry.prompt.name, + icon: React.createElement(FileText, { className: "w-4 h-4" }), + text: "", // Text will be fetched when selected via useTamboMcpPrompt + })) + : [], + [mcpPrompts], + ); + + // Track external provider results with state + const [externalItems, setExternalItems] = React.useState([]); + + // Fetch external prompts when search changes + React.useEffect(() => { + if (!externalProvider) { + setExternalItems([]); + return; + } + + let cancelled = false; + externalProvider + .search(debouncedSearch) + .then((items) => { + if (!cancelled) { + setExternalItems(items); + } + }) + .catch((error) => { + console.error("Failed to fetch external prompts", error); + if (!cancelled) { + setExternalItems([]); + } + }); + + return () => { + cancelled = true; + }; + }, [externalProvider, debouncedSearch]); + + // Combine - MCP prompts are already filtered by the hook + // External items need to be filtered locally + const combined = React.useMemo(() => { + const filteredExternal = filterPromptItems(externalItems, search); + return [...mcpItems, ...filteredExternal]; + }, [mcpItems, externalItems, search]); + + return combined; +} /** * CSS variants for the message input container @@ -81,10 +323,11 @@ const messageInputVariants = cva("w-full", { * @property {function} handleSubmit - Function to handle form submission * @property {boolean} isPending - Whether a submission is in progress * @property {Error|null} error - Any error from the submission - * @property {string|undefined} contextKey - The thread context key - * @property {Editor|null} editorRef - Reference to the TipTap editor instance + * @property {TamboEditor|null} editorRef - Reference to the TamboEditor instance * @property {string | null} submitError - Error from the submission * @property {function} setSubmitError - Function to set the submission error + * @property {string | null} imageError - Error related to image uploads + * @property {function} setImageError - Function to set the image upload error * @property {TamboElicitationRequest | null} elicitation - Current elicitation request (read-only) * @property {function} resolveElicitation - Function to resolve the elicitation promise (automatically clears state) */ @@ -92,16 +335,17 @@ interface MessageInputContextValue { value: string; setValue: (value: string) => void; submit: (options: { - contextKey?: string; streamResponse?: boolean; + resourceNames: Record; }) => Promise; handleSubmit: (e: React.FormEvent) => Promise; isPending: boolean; error: Error | null; - contextKey?: string; - editorRef: React.RefObject; + editorRef: React.RefObject; submitError: string | null; setSubmitError: React.Dispatch>; + imageError: string | null; + setImageError: React.Dispatch>; elicitation: TamboElicitationRequest | null; resolveElicitation: ((response: TamboElicitationResponse) => void) | null; } @@ -135,12 +379,10 @@ const useMessageInputContext = () => { * Extends standard HTMLFormElement attributes. */ export interface MessageInputProps extends React.HTMLAttributes { - /** The context key identifying which thread to send messages to. */ - contextKey?: string; /** Optional styling variant for the input container. */ variant?: VariantProps["variant"]; - /** Optional ref to forward to the TipTap editor instance. */ - inputRef?: React.RefObject; + /** Optional ref to forward to the TamboEditor instance. */ + inputRef?: React.RefObject; /** The child elements to render within the form container. */ children?: React.ReactNode; } @@ -151,7 +393,7 @@ export interface MessageInputProps extends React.HTMLAttributes * @component MessageInput * @example * ```tsx - * + * * * * @@ -159,12 +401,11 @@ export interface MessageInputProps extends React.HTMLAttributes * ``` */ const MessageInput = React.forwardRef( - ({ children, className, contextKey, variant, ...props }, ref) => { + ({ children, className, variant, ...props }, ref) => { return ( @@ -175,13 +416,37 @@ const MessageInput = React.forwardRef( ); MessageInput.displayName = "MessageInput"; +const STORAGE_KEY = "tambo.components.messageInput.draft"; + +const getStorageKey = (key: string) => `${STORAGE_KEY}.${key}`; + +const storeValueInSessionStorage = (key: string, value?: string) => { + const storageKey = getStorageKey(key); + if (value === undefined) { + sessionStorage.removeItem(storageKey); + return; + } + + sessionStorage.setItem(storageKey, JSON.stringify({ rawQuery: value })); +}; + +const getValueFromSessionStorage = (key: string): string => { + const storedValue = sessionStorage.getItem(getStorageKey(key)) ?? ""; + try { + const parsed = JSON.parse(storedValue); + return parsed.rawQuery ?? ""; + } catch { + return ""; + } +}; + /** * Internal MessageInput component that uses the TamboThreadInput context */ const MessageInputInternal = React.forwardRef< HTMLFormElement, MessageInputProps ->(({ children, className, contextKey, variant, inputRef, ...props }, ref) => { +>(({ children, className, variant, inputRef, ...props }, ref) => { const { value, setValue, @@ -190,53 +455,77 @@ const MessageInputInternal = React.forwardRef< error, images, addImages, - clearImages, + removeImage, } = useTamboThreadInput(); - const { cancel } = useTamboThread(); + const { cancel, thread } = useTamboThread(); const [displayValue, setDisplayValue] = React.useState(""); const [submitError, setSubmitError] = React.useState(null); + const [imageError, setImageError] = React.useState(null); const [isSubmitting, setIsSubmitting] = React.useState(false); const [isDragging, setIsDragging] = React.useState(false); - const editorRef = React.useRef(null); + const editorRef = React.useRef(null!); const dragCounter = React.useRef(0); // Use elicitation context (optional) const { elicitation, resolveElicitation } = useTamboElicitationContext(); + React.useEffect(() => { + // On mount, load any stored draft value, but only if current value is empty + const storedValue = getValueFromSessionStorage(thread.id); + if (!storedValue) return; + setValue((value) => value ?? storedValue); + }, [setValue, thread.id]); + React.useEffect(() => { setDisplayValue(value); + storeValueInSessionStorage(thread.id, value); if (value && editorRef.current) { - editorRef.current.commands.focus(); + editorRef.current.focus(); } - }, [value]); + }, [value, thread.id]); const handleSubmit = React.useCallback( async (e: React.FormEvent) => { e.preventDefault(); if ((!value.trim() && images.length === 0) || isSubmitting) return; + // Clear any previous errors setSubmitError(null); + setImageError(null); setDisplayValue(""); + storeValueInSessionStorage(thread.id); setIsSubmitting(true); - // Clear images in next tick for immediate UI feedback - if (images.length > 0) { - setTimeout(() => clearImages(), 0); + // Extract resource names directly from editor at submit time to ensure we have the latest + let latestResourceNames: Record = {}; + const editor = editorRef.current; + if (editor) { + const extracted = editor.getTextWithResourceURIs(); + latestResourceNames = extracted.resourceNames; } + const imageIdsAtSubmitTime = images.map((image) => image.id); + try { await submit({ - contextKey, streamResponse: true, + resourceNames: latestResourceNames, }); setValue(""); - // Images are cleared automatically by the TamboThreadInputProvider + // Clear only the images that were staged when submission started so + // any images added while the request was in-flight are preserved. + if (imageIdsAtSubmitTime.length > 0) { + imageIdsAtSubmitTime.forEach((id) => removeImage(id)); + } + // Refocus the editor after a successful submission setTimeout(() => { - editorRef.current?.commands.focus(); + editorRef.current?.focus(); }, 0); } catch (error) { console.error("Failed to submit message:", error); setDisplayValue(value); + // On submit failure, also clear image error + setImageError(null); setSubmitError( error instanceof Error ? error.message @@ -252,14 +541,15 @@ const MessageInputInternal = React.forwardRef< [ value, submit, - contextKey, setValue, setDisplayValue, setSubmitError, cancel, isSubmitting, images, - clearImages, + removeImage, + editorRef, + thread.id, ], ); @@ -303,14 +593,25 @@ const MessageInputInternal = React.forwardRef< ); if (files.length > 0) { + const totalImages = images.length + files.length; + if (totalImages > MAX_IMAGES) { + setImageError(`Max ${MAX_IMAGES} uploads at a time`); + return; + } + setImageError(null); // Clear previous error try { await addImages(files); } catch (error) { console.error("Failed to add dropped images:", error); + setImageError( + error instanceof Error + ? error.message + : "Failed to add images. Please try again.", + ); } } }, - [addImages], + [addImages, images, setImageError], ); const handleElicitationResponse = React.useCallback( @@ -334,10 +635,11 @@ const MessageInputInternal = React.forwardRef< handleSubmit, isPending: isPending ?? isSubmitting, error, - contextKey, editorRef: inputRef ?? editorRef, submitError, setSubmitError, + imageError, + setImageError, elicitation, resolveElicitation, }), @@ -349,10 +651,11 @@ const MessageInputInternal = React.forwardRef< isPending, isSubmitting, error, - contextKey, inputRef, editorRef, submitError, + imageError, + setImageError, elicitation, resolveElicitation, ], @@ -411,6 +714,9 @@ MessageInput.displayName = "MessageInput"; */ const IS_PASTED_IMAGE = Symbol.for("tambo-is-pasted-image"); +/** Maximum number of images that can be staged at once */ +const MAX_IMAGES = 10; + /** * Extend the File interface to include IS_PASTED_IMAGE symbol */ @@ -427,10 +733,12 @@ declare global { export interface MessageInputTextareaProps extends React.HTMLAttributes { /** Custom placeholder text. */ placeholder?: string; - /** Static mention items to include in @ suggestions. */ - staticMentionItems?: ResourceItem[]; - /** Async fetcher to load mention items (e.g., MCP resources). */ - mentionItemFetcher?: (query: string) => Promise; + /** Resource provider for @ mentions (optional - includes interactables by default) */ + resourceProvider?: ResourceProvider; + /** Prompt provider for / commands (optional) */ + promptProvider?: PromptProvider; + /** Callback when a resource is selected from @ mentions (optional) */ + onResourceSelect?: (item: ResourceItem) => void; } /** @@ -439,13 +747,23 @@ export interface MessageInputTextareaProps extends React.HTMLAttributes * { + * // Return custom resources + * return [{ id: "foo", name: "Foo" }]; + * } + * }} * /> * * ``` @@ -453,13 +771,105 @@ export interface MessageInputTextareaProps extends React.HTMLAttributes { - const { value, setValue, handleSubmit, editorRef } = useMessageInputContext(); + const { value, setValue, handleSubmit, editorRef, setImageError } = + useMessageInputContext(); const { isIdle } = useTamboThread(); + const { addImage, images } = useTamboThreadInput(); const isUpdatingToken = useIsTamboTokenUpdating(); + // Resource names are extracted from editor at submit time, no need to track in state + const setResourceNames = React.useCallback( + ( + _resourceNames: + | Record + | ((prev: Record) => Record), + ) => { + // No-op - we extract resource names directly from editor at submit time + }, + [], + ); + + // Track search state for resources (controlled by TextEditor) + const [resourceSearch, setResourceSearch] = React.useState(""); + + // Track search state for prompts (controlled by TextEditor) + const [promptSearch, setPromptSearch] = React.useState(""); + + // Get combined resource list (MCP + external provider), filtered by search + const resourceItems = useCombinedResourceList( + resourceProvider, + resourceSearch, + ); + + // Get combined prompt list (MCP + external provider), filtered by search + const promptItems = useCombinedPromptList(promptProvider, promptSearch); + + // State for MCP prompt fetching (since we can't call hooks inside get()) + const [selectedMcpPromptName, setSelectedMcpPromptName] = React.useState< + string | null + >(null); + const { data: selectedMcpPromptData } = useTamboMcpPrompt( + selectedMcpPromptName ?? "", + ); + + // Handle MCP prompt insertion when data is fetched + React.useEffect(() => { + if (selectedMcpPromptData && selectedMcpPromptName) { + const promptMessages = selectedMcpPromptData?.messages; + if (promptMessages) { + const promptText = promptMessages + .map((msg) => { + if (msg.content?.type === "text") { + return msg.content.text; + } + return ""; + }) + .filter(Boolean) + .join("\n"); + + const editor = editorRef.current; + if (editor) { + editor.setContent(promptText); + setValue(promptText); + editor.focus("end"); + } + } + setSelectedMcpPromptName(null); + } + }, [selectedMcpPromptData, selectedMcpPromptName, editorRef, setValue]); + + // Handle prompt selection - check if it's an MCP prompt + const handlePromptSelect = React.useCallback((item: PromptItem) => { + if (item.id.startsWith("mcp-prompt:")) { + const promptName = item.id.replace("mcp-prompt:", ""); + setSelectedMcpPromptName(promptName); + } + }, []); + + // Handle image paste - mark as pasted and add to thread + const pendingImagesRef = React.useRef(0); + + const handleAddImage = React.useCallback( + async (file: File) => { + if (images.length + pendingImagesRef.current >= MAX_IMAGES) { + setImageError(`Max ${MAX_IMAGES} uploads at a time`); + return; + } + setImageError(null); + pendingImagesRef.current += 1; + try { + file[IS_PASTED_IMAGE] = true; + await addImage(file); + } finally { + pendingImagesRef.current -= 1; + } + }, + [addImage, images, setImageError], + ); return (
{})} + onPromptSelect={handlePromptSelect} />
); @@ -504,9 +920,10 @@ const MessageInputPlainTextarea = ({ placeholder = "What do you want to do?", ...props }: MessageInputPlainTextareaProps) => { - const { value, setValue, handleSubmit } = useMessageInputContext(); + const { value, setValue, handleSubmit, setImageError } = + useMessageInputContext(); const { isIdle } = useTamboThread(); - const { addImage } = useTamboThreadInput(); + const { addImage, images } = useTamboThreadInput(); const isUpdatingToken = useIsTamboTokenUpdating(); const isPending = !isIdle; const textareaRef = React.useRef(null); @@ -525,11 +942,7 @@ const MessageInputPlainTextarea = ({ }; const handlePaste = async (e: React.ClipboardEvent) => { - const items = Array.from(e.clipboardData.items); - const imageItems = items.filter((item) => item.type.startsWith("image/")); - - // Allow default paste if there is text, even when images exist - const hasText = e.clipboardData.getData("text/plain").length > 0; + const { imageItems, hasText } = getImageItems(e.clipboardData); if (imageItems.length === 0) { return; // Allow default text paste @@ -539,16 +952,20 @@ const MessageInputPlainTextarea = ({ e.preventDefault(); // Only prevent when image-only paste } + const totalImages = images.length + imageItems.length; + if (totalImages > MAX_IMAGES) { + setImageError(`Max ${MAX_IMAGES} uploads at a time`); + return; + } + setImageError(null); + for (const item of imageItems) { - const file = item.getAsFile(); - if (file) { - try { - // Mark this file as pasted so we can show "Image 1", "Image 2", etc. - file[IS_PASTED_IMAGE] = true; - await addImage(file); - } catch (error) { - console.error("Failed to add pasted image:", error); - } + try { + // Mark this image as pasted so we can show "Image 1", "Image 2", etc. + item[IS_PASTED_IMAGE] = true; + await addImage(item); + } catch (error) { + console.error("Failed to add pasted image:", error); } } }; @@ -602,9 +1019,14 @@ const MessageInputSubmitButton = React.forwardRef< MessageInputSubmitButtonProps >(({ className, children, ...props }, ref) => { const { isPending } = useMessageInputContext(); - const { cancel } = useTamboThread(); + const { cancel, isIdle } = useTamboThread(); const isUpdatingToken = useIsTamboTokenUpdating(); + // Show cancel button if either: + // 1. A mutation is in progress (isPending), OR + // 2. Thread is stuck in a processing state (e.g., after browser refresh during tool execution) + const showCancelButton = isPending || !isIdle; + const handleCancel = async (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); @@ -612,23 +1034,25 @@ const MessageInputSubmitButton = React.forwardRef< }; const buttonClasses = cn( - "w-10 h-10 bg-black/80 text-white rounded-lg hover:bg-black/70 disabled:opacity-50 flex items-center justify-center enabled:cursor-pointer", + "w-10 h-10 bg-foreground text-background rounded-lg hover:bg-foreground/90 disabled:opacity-50 flex items-center justify-center enabled:cursor-pointer", className, ); return ( - -
- ) : canDrag ? ( + (canDrag ? (
-
+
- ))} -
+ !open && onClose()} + > + +
+ + e.preventDefault()} + onCloseAutoFocus={(e) => e.preventDefault()} + onEscapeKeyDown={(e) => { + e.preventDefault(); + onClose(); + }} + > + {state.items.length === 0 ? ( +
+ {emptyMessage} +
+ ) : ( +
+ {state.items.map((item, index) => ( + + ))} +
+ )} +
+ ); -}); -ResourceItemList.displayName = "ResourceItemList"; +} /** - * Checks if a mention with the given label already exists in the editor. - * Used to prevent duplicate mentions when inserting via @ command or EditableHint. - * - * @param editor - The TipTap editor instance - * @param label - The mention label to check for - * @returns true if a mention with the given label exists, false otherwise + * Internal helper to check if a mention exists in a raw TipTap Editor. */ -export function hasExistingMention(editor: Editor, label: string): boolean { - let hasMention = false; +function checkMentionExists(editor: Editor, label: string): boolean { + if (!editor.state?.doc) return false; + let exists = false; editor.state.doc.descendants((node) => { if (node.type.name === "mention") { const mentionLabel = node.attrs.label as string; if (mentionLabel === label) { - hasMention = true; - return false; // Stop traversing + exists = true; + return false; } } return true; }); - return hasMention; + return exists; } /** - * Creates a popup handler for the resource item dropdown using tippy.js. + * Creates the resource mention configuration for TipTap Mention extension. + * The items() function triggers the search - actual items come from props via stateRef. */ -function createResourceItemPopup() { - let itemListComponent: ReactRenderer | undefined; - let tippyPopup: TippyInstance | undefined; - - return { - /** - * Called when the user starts typing "@" and resource items should appear. - * Creates the React component and tippy popup. - */ - onStart(props: { - items: ResourceItem[]; - command: (item: ResourceItem) => void; - editor: Editor; - clientRect?: (() => DOMRect | null) | null; - }) { - itemListComponent = new ReactRenderer(ResourceItemList, { - props: { items: props.items, command: props.command }, - editor: props.editor, - }); - - if (!props.clientRect) return; - - tippyPopup = tippy("body", { - getReferenceClientRect: () => props.clientRect?.() ?? new DOMRect(), - appendTo: () => document.body, - content: itemListComponent.element, - showOnCreate: true, - interactive: true, - trigger: "manual", - placement: "bottom-start", - maxWidth: "24rem", - theme: "light-border", - })[0]; - }, - - /** - * Called when resource items change (user continues typing after "@"). - * Updates the resource item list and repositions the popup. - */ - onUpdate(props: { - items: ResourceItem[]; - command: (item: ResourceItem) => void; - clientRect?: (() => DOMRect | null) | null; - }) { - itemListComponent?.updateProps({ - items: props.items, - command: props.command, - }); - if (props.clientRect && tippyPopup) { - tippyPopup.setProps({ - getReferenceClientRect: () => props.clientRect?.() ?? new DOMRect(), - }); - } - }, - - /** - * Handles keyboard events in the resource item dropdown. - * - Escape: closes the popup - * - Arrow keys/Enter: delegated to the resource item list component - */ - onKeyDown({ event }: { event: KeyboardEvent }) { - if (event.key === "Escape") { - tippyPopup?.hide(); - return true; - } - const handled = itemListComponent?.ref?.onKeyDown({ event }) ?? false; - if (handled) event.preventDefault(); - return handled; - }, - - /** - * Called when the resource item popup should be closed. - * Cleans up the React component and tippy popup. - */ - onExit() { - tippyPopup?.destroy(); - itemListComponent?.destroy(); - }, - }; -} - -/** - * Creates the resource item configuration for TipTap Mention extension. - * Filters resource items as user types and handles dropdown lifecycle. - * Supports both static arrays and async fetching. - */ -function createResourceItemConfig( - items: ResourceItemSource, - triggerChar: string, - onSelect?: (item: ResourceItem) => void, - isMenuOpenRef?: React.MutableRefObject, +function createResourceMentionConfig( + onSearchChange: (query: string) => void, + onSelect: (item: ResourceItem) => void, + stateRef: React.MutableRefObject>, ): Omit { return { - char: triggerChar, - items: async ({ query }) => { - return await resolveResourceItems(items, query); + char: "@", + items: ({ query }) => { + onSearchChange(query); + return []; }, - /** - * Returns handlers for managing the resource item popup lifecycle. - * Called once when the mention system initializes (when editor is created). - */ render: () => { - const popupHandlers = createResourceItemPopup(); - - /** - * Creates a wrapped command that checks for duplicates before inserting. - * Must be created inside onStart/onUpdate where editor is available. - */ const createWrapCommand = - (editor: Editor) => - (tiptapCommand: (attrs: { id: string; label: string }) => void) => + ( + editor: Editor, + tiptapCommand: (attrs: { id: string; label: string }) => void, + ) => (item: ResourceItem) => { - // Check if mention already exists in the editor - if (hasExistingMention(editor, item.name)) { - // Don't insert duplicate mention - return; - } - - // Insert the command into the editor (e.g., "@ComponentName") + if (checkMentionExists(editor, item.name)) return; tiptapCommand({ id: item.id, label: item.name }); - // Run custom logic (e.g., add context attachment, insert table, etc.) - onSelect?.(item); + onSelect(item); }; return { - /** - * Called when user starts typing the trigger character (e.g., "@"). - * Shows the resource item dropdown. - */ onStart: (props) => { - if (props.items.length === 0) { - if (isMenuOpenRef) isMenuOpenRef.current = false; - return; - } - if (isMenuOpenRef) isMenuOpenRef.current = true; - popupHandlers.onStart({ - items: props.items, - editor: props.editor, - clientRect: props.clientRect, - command: createWrapCommand(props.editor)(props.command), + stateRef.current.setState({ + isOpen: true, + selectedIndex: 0, + position: getPositionFromClientRect(props.clientRect), + command: createWrapCommand(props.editor, props.command), }); }, - - /** - * Called as user continues typing after the trigger (e.g., "@jo" -> "@john"). - * Updates the filtered resource items in the dropdown. - */ onUpdate: (props) => { - if (props.items.length === 0) { - popupHandlers.onExit(); - if (isMenuOpenRef) isMenuOpenRef.current = false; - return; - } - popupHandlers.onUpdate({ - items: props.items, - clientRect: props.clientRect, - command: createWrapCommand(props.editor)(props.command), + stateRef.current.setState({ + position: getPositionFromClientRect(props.clientRect), + command: createWrapCommand(props.editor, props.command), + selectedIndex: 0, }); }, - - /** - * Handles keyboard events in the resource item dropdown. - * - ArrowUp/ArrowDown: Navigate through resource items - * - Enter: Select current resource item - * - Escape: Close dropdown - */ - onKeyDown: popupHandlers.onKeyDown, - - /** - * Called when the resource item dropdown should close. - * Cleans up the popup and updates the menu state. - */ + onKeyDown: ({ event }) => { + const { state, setState } = stateRef.current; + if (!state.isOpen) return false; + + const handlers: Record boolean> = { + ArrowUp: () => { + if (state.items.length === 0) return false; + setState({ + selectedIndex: + (state.selectedIndex - 1 + state.items.length) % + state.items.length, + }); + return true; + }, + ArrowDown: () => { + if (state.items.length === 0) return false; + setState({ + selectedIndex: (state.selectedIndex + 1) % state.items.length, + }); + return true; + }, + Enter: () => { + const item = state.items[state.selectedIndex]; + if (item && state.command) { + state.command(item); + return true; + } + return false; + }, + Escape: () => { + setState({ isOpen: false }); + return true; + }, + }; + + const handler = handlers[event.key]; + if (handler) { + event.preventDefault(); + return handler(); + } + return false; + }, onExit: () => { - // Delay setting menu to closed to give our handleKeyDown a chance to see it was open - // This prevents the form from submitting when Enter is used to select an item - setTimeout(() => { - if (isMenuOpenRef) isMenuOpenRef.current = false; - }, 100); - popupHandlers.onExit(); + stateRef.current.setState({ isOpen: false }); }, }; }, @@ -432,132 +380,290 @@ function createResourceItemConfig( } /** - * Text editor component with command support (e.g., "@" mentions). + * Creates a custom TipTap extension for prompt commands using the Suggestion plugin. + * The items() function triggers the search - actual items come from props via stateRef. + */ +function createPromptCommandExtension( + onSearchChange: (query: string) => void, + onSelect: (item: PromptItem) => void, + stateRef: React.MutableRefObject>, +) { + return Extension.create({ + name: "promptCommand", + + addProseMirrorPlugins() { + return [ + Suggestion({ + editor: this.editor, + char: "/", + items: ({ query, editor }) => { + // Only show prompts when editor is empty (except for the "/" and query) + const editorValue = editor.getText().replace("/", "").trim(); + if (editorValue.length > 0) { + stateRef.current.setState({ isOpen: false }); + return []; + } + // Trigger search - actual items come from props via stateRef + onSearchChange(query); + return []; + }, + render: () => { + // Store command creator that captures editor context + let createCommand: ((item: PromptItem) => void) | null = null; + + return { + onStart: (props) => { + createCommand = (item: PromptItem) => { + props.editor.commands.deleteRange({ + from: props.range.from, + to: props.range.to, + }); + onSelect(item); + }; + stateRef.current.setState({ + isOpen: true, + selectedIndex: 0, + position: getPositionFromClientRect(props.clientRect), + command: createCommand, + }); + }, + onUpdate: (props) => { + createCommand = (item: PromptItem) => { + props.editor.commands.deleteRange({ + from: props.range.from, + to: props.range.to, + }); + onSelect(item); + }; + stateRef.current.setState({ + position: getPositionFromClientRect(props.clientRect), + command: createCommand, + selectedIndex: 0, + }); + }, + onKeyDown: ({ event }) => { + const { state, setState } = stateRef.current; + if (!state.isOpen) return false; + + const handlers: Record boolean> = { + ArrowUp: () => { + if (state.items.length === 0) return false; + setState({ + selectedIndex: + (state.selectedIndex - 1 + state.items.length) % + state.items.length, + }); + return true; + }, + ArrowDown: () => { + if (state.items.length === 0) return false; + setState({ + selectedIndex: + (state.selectedIndex + 1) % state.items.length, + }); + return true; + }, + Enter: () => { + const item = state.items[state.selectedIndex]; + if (item && state.command) { + state.command(item); + return true; + } + return false; + }, + Escape: () => { + setState({ isOpen: false }); + return true; + }, + }; + + const handler = handlers[event.key]; + if (handler) { + event.preventDefault(); + return handler(); + } + return false; + }, + onExit: () => { + stateRef.current.setState({ isOpen: false }); + }, + }; + }, + }), + ]; + }, + }); +} + +/** + * Custom text extraction that serializes mention nodes with their ID (resource URI). + */ +function getTextWithResourceURIs(editor: Editor | null): { + text: string; + resourceNames: Record; +} { + if (!editor?.state?.doc) return { text: "", resourceNames: {} }; + + let text = ""; + const resourceNames: Record = {}; + + editor.state.doc.descendants((node) => { + if (node.type.name === "mention") { + const id = node.attrs.id ?? ""; + const label = node.attrs.label ?? ""; + text += `@${id}`; + if (label && id) { + resourceNames[id] = label; + } + } else if (node.type.name === "hardBreak") { + text += "\n"; + } else if (node.isText) { + text += node.text; + } + return true; + }); + + return { text, resourceNames }; +} + +/** + * Hook to create suggestion state with a ref for TipTap access. + */ +function useSuggestionState( + externalItems?: T[], +): [SuggestionState, React.MutableRefObject>] { + const [state, setStateInternal] = useState>({ + isOpen: false, + items: externalItems ?? [], + selectedIndex: 0, + position: null, + command: null, + }); + + const setState = React.useCallback((update: Partial>) => { + setStateInternal((prev) => ({ ...prev, ...update })); + }, []); + + const stateRef = React.useRef>({ state, setState }); + + // Keep ref in sync + React.useEffect(() => { + stateRef.current = { state, setState }; + }, [state, setState]); + + // Sync external items when provided + React.useEffect(() => { + if (externalItems !== undefined) { + setStateInternal((prev) => { + if (prev.items === externalItems) { + return prev; + } + + const previousMaxIndex = Math.max(prev.items.length - 1, 0); + const safePrevIndex = Math.min( + Math.max(prev.selectedIndex, 0), + previousMaxIndex, + ); + + const selectedItem = prev.items[safePrevIndex]; + const matchedIndex = selectedItem + ? externalItems.findIndex((item) => item.id === selectedItem.id) + : -1; + + const maxIndex = Math.max(externalItems.length - 1, 0); + const nextSelectedIndex = + matchedIndex >= 0 ? matchedIndex : Math.min(safePrevIndex, maxIndex); + + return { + ...prev, + items: externalItems, + selectedIndex: nextSelectedIndex, + }; + }); + } + }, [externalItems]); + + return [state, stateRef]; +} + +/** + * Text editor component with resource ("@") and prompt ("/") support. */ -export const TextEditor = React.forwardRef( +export const TextEditor = React.forwardRef( ( { value, onChange, + onResourceNamesChange, onKeyDown, placeholder = "What do you want to do?", disabled = false, className, - editorRef, - commands: providedCommands = [], onSubmit, - staticMentionItems = [], - mentionItemFetcher, + onAddImage, + onSearchResources, + resources, + onSearchPrompts, + prompts, + onResourceSelect, + onPromptSelect, }, ref, ) => { - // Use Tambo-specific hooks - must be called unconditionally per React rules - // These hooks will throw if not in Tambo context, which is expected when onSubmit is provided - const tamboThreadInput = useTamboThreadInput(); - const tamboContextAttachment = useTamboContextAttachment(); - const interactables = useCurrentInteractablesSnapshot(); - - // Ref to access the current interactables without capturing them in a closure - const interactablesRef = React.useRef(interactables); - useEffect(() => { - interactablesRef.current = interactables; - }, [interactables]); - - // Ref to access tamboContextAttachment without causing re-renders - const tamboContextAttachmentRef = React.useRef(tamboContextAttachment); - useEffect(() => { - tamboContextAttachmentRef.current = tamboContextAttachment; - }, [tamboContextAttachment]); - - const tamboCommands = React.useMemo((): CommandConfig[] => { - if (!onSubmit) return []; - - // Function to get the resource items for the @ mention dropdown - const getResourceItems = async ( - query: string, - ): Promise => { - // Get the current interactables via ref to get the current value - const interactableItems = interactablesRef.current.map((component) => ({ - id: component.id, - name: component.name, - icon: React.createElement(Cuboid, { className: "w-4 h-4" }), - componentData: component, - })); - - const filteredInteractables = filterResourceItems( - interactableItems, - query, - ); - const filteredStatic = filterResourceItems(staticMentionItems, query); - const fetchedItems = mentionItemFetcher - ? await mentionItemFetcher(query) - : []; - - return dedupeResourceItems([ - ...filteredInteractables, - ...filteredStatic, - ...fetchedItems, - ]); + // Suggestion states with refs for TipTap access + const [resourceState, resourceRef] = + useSuggestionState(resources); + const [promptState, promptRef] = useSuggestionState(prompts); + + // Consolidated ref for callbacks that TipTap needs to access + const callbacksRef = React.useRef({ + onSearchResources, + onResourceSelect, + onSearchPrompts, + onPromptSelect, + }); + + React.useEffect(() => { + callbacksRef.current = { + onSearchResources, + onResourceSelect, + onSearchPrompts, + onPromptSelect, }; + }, [onSearchResources, onResourceSelect, onSearchPrompts, onPromptSelect]); - // Create the @ command - return [ - { - triggerChar: "@", - items: getResourceItems, - onSelect: (item: ResourceItem) => { - // When a mention is selected, add it as a context attachment - // This will appear as a badge above the input - tamboContextAttachmentRef.current.addContextAttachment({ name: item.name }); - }, - renderLabel: ({ - node, - }: { - node: { attrs: Record }; - }) => `@${(node.attrs.label as string) ?? ""}`, - HTMLAttributes: { class: "mention" }, - }, - ]; - }, [ - mentionItemFetcher, - onSubmit, - staticMentionItems, - ]); + // Stable callbacks for TipTap + const stableSearchResources = React.useCallback( + (query: string) => callbacksRef.current.onSearchResources(query), + [], + ); - // Merge provided commands with Tambo-specific commands - const commands = React.useMemo( - () => [...providedCommands, ...tamboCommands], - [providedCommands, tamboCommands], + const stableSearchPrompts = React.useCallback( + (query: string) => callbacksRef.current.onSearchPrompts(query), + [], + ); + + const handleResourceSelect = React.useCallback( + (item: ResourceItem) => callbacksRef.current.onResourceSelect(item), + [], + ); + + const handlePromptSelect = React.useCallback( + (item: PromptItem) => callbacksRef.current.onPromptSelect(item), + [], ); - // Handle Enter key to submit message when onSubmit is provided const handleKeyDown = React.useCallback( - (e: React.KeyboardEvent, editor: Editor) => { - // Handle Tambo-specific Enter key behavior - if (onSubmit && e.key === "Enter" && !e.shiftKey && value.trim()) { + (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey && value.trim()) { e.preventDefault(); void onSubmit(e as React.FormEvent); return; } - - // Delegate to provided onKeyDown handler - if (onKeyDown) { - onKeyDown(e, editor); - } + onKeyDown?.(e); }, [onSubmit, value, onKeyDown], ); - // Initialize menu open refs for each command - // Use a stable ref that persists across renders to track menu state - const stableMenuOpenRef = React.useRef(false); - const commandRefs = React.useMemo( - () => - // eslint-disable-next-line react-hooks/refs -- Passing refs to config objects is intentional - commands.map((cmd) => ({ - isMenuOpenRef: cmd.isMenuOpenRef ?? stableMenuOpenRef, - })), - [commands], - ); const editor = useEditor({ immediatelyRender: false, @@ -565,27 +671,37 @@ export const TextEditor = React.forwardRef( Document, Paragraph, Text, + HardBreak, Placeholder.configure({ placeholder }), - // eslint-disable-next-line react-hooks/refs -- Refs are passed to config, not read during render - ...commands.map((cmd, index) => { - const ref = commandRefs[index]; - return Mention.configure({ - HTMLAttributes: cmd.HTMLAttributes ?? {}, - suggestion: createResourceItemConfig( - cmd.items, - cmd.triggerChar, - cmd.onSelect, - ref.isMenuOpenRef, - ), - renderLabel: cmd.renderLabel, - renderText: ({ node }) => - `${cmd.triggerChar}${(node.attrs.label as string) ?? ""}`, - }); + Mention.configure({ + HTMLAttributes: { + class: + "mention resource inline-flex items-center rounded-md bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground", + }, + suggestion: createResourceMentionConfig( + stableSearchResources, + handleResourceSelect, + resourceRef, + ), + renderLabel: ({ node }) => `@${(node.attrs.label as string) ?? ""}`, }), + createPromptCommandExtension( + stableSearchPrompts, + handlePromptSelect, + promptRef, + ), ], content: value, editable: !disabled, - onUpdate: ({ editor }) => onChange(editor.getText()), + onUpdate: ({ editor }) => { + const { text, resourceNames } = getTextWithResourceURIs(editor); + if (text !== value) { + onChange(text); + } + if (onResourceNamesChange) { + onResourceNamesChange((prev) => ({ ...prev, ...resourceNames })); + } + }, editorProps: { attributes: { class: cn( @@ -598,87 +714,133 @@ export const TextEditor = React.forwardRef( ), }, handlePaste: (_view, event) => { - if (!onSubmit) { - return false; - } - - const items = Array.from(event.clipboardData?.items ?? []); - const imageItems = items.filter((item) => - item.type.startsWith("image/"), - ); + const { imageItems, hasText } = getImageItems(event.clipboardData); - // If there are no images, let TipTap handle the paste normally - if (imageItems.length === 0) { - return false; - } - - const text = event.clipboardData?.getData("text/plain") ?? ""; - const hasText = text.length > 0; + if (imageItems.length === 0) return false; - // Only prevent default when it's an image-only paste so users can still - // paste mixed text + images and keep the text in the editor if (!hasText) { event.preventDefault(); } void (async () => { for (const item of imageItems) { - const file = item.getAsFile(); - if (!file) continue; try { - file[IS_PASTED_IMAGE] = true; - await tamboThreadInput.addImage(file); + await onAddImage(item); } catch (error) { console.error("Failed to add pasted image:", error); } } })(); - // For pure image pastes we've already prevented the default and - // signal that the event was handled. For mixed text+image pastes, - // return false so TipTap can still process the text payload. return !hasText; }, - handleKeyDown: (view, event) => { - // Check if any command menu is open - const anyMenuOpen = commandRefs.some( - (ref) => ref.isMenuOpenRef.current, - ); - - // Prevent Enter from submitting form when selecting from any resource item menu - if (event.key === "Enter" && !event.shiftKey && anyMenuOpen) { - // Prevent the DOM event from propagating - event.preventDefault(); - event.stopPropagation(); - // Return false to let the suggestion plugin handle the selection - return false; - } + handleKeyDown: (_view, event) => { + const anyMenuOpen = resourceState.isOpen || promptState.isOpen; + + if (anyMenuOpen) return false; - // Delegate to handleKeyDown (which handles both Tambo-specific and custom handlers) - if (editor) { + if (event.key === "Enter" && !event.shiftKey && editor) { const reactEvent = event as unknown as React.KeyboardEvent; - handleKeyDown(reactEvent, editor); + handleKeyDown(reactEvent); return reactEvent.defaultPrevented; } + return false; }, }, }); - // Sync external value changes and disabled state with editor + useImperativeHandle(ref, () => { + if (!editor) { + return { + focus: () => {}, + setContent: () => {}, + appendText: () => {}, + getTextWithResourceURIs: () => ({ text: "", resourceNames: {} }), + hasMention: () => false, + insertMention: () => {}, + setEditable: () => {}, + }; + } + + return { + focus: (position?: "start" | "end") => { + if (position) { + editor.commands.focus(position); + } else { + editor.commands.focus(); + } + }, + setContent: (content: string) => { + editor.commands.setContent(content); + }, + appendText: (text: string) => { + editor.chain().focus("end").insertContent(text).run(); + }, + getTextWithResourceURIs: () => getTextWithResourceURIs(editor), + hasMention: (id: string) => { + if (!editor.state?.doc) return false; + let exists = false; + editor.state.doc.descendants((node) => { + if (node.type.name === "mention") { + const mentionId = node.attrs.id as string; + if (mentionId === id) { + exists = true; + return false; + } + } + return true; + }); + return exists; + }, + insertMention: (id: string, label: string) => { + editor + .chain() + .focus() + .insertContent([ + { type: "mention", attrs: { id, label } }, + { type: "text", text: " " }, + ]) + .run(); + }, + setEditable: (editable: boolean) => { + editor.setEditable(editable); + }, + }; + }, [editor]); + + const lastSyncedValueRef = React.useRef(value); + React.useEffect(() => { if (!editor) return; - if (value !== editor.getText()) { + + const { text: currentText } = getTextWithResourceURIs(editor); + + if (value !== currentText && value !== lastSyncedValueRef.current) { editor.commands.setContent(value); + lastSyncedValueRef.current = value; + } else if (value === currentText) { + lastSyncedValueRef.current = value; } + editor.setEditable(!disabled); - if (editorRef) { - editorRef.current = editor; - } - }, [editor, value, disabled, editorRef]); + }, [editor, value, disabled]); return ( -
+
+ resourceRef.current.setState({ isOpen: false })} + defaultIcon={} + emptyMessage="No results found" + monoSecondary + /> + promptRef.current.setState({ isOpen: false })} + defaultIcon={} + emptyMessage="No prompts found" + />
); @@ -686,20 +848,3 @@ export const TextEditor = React.forwardRef( ); TextEditor.displayName = "TextEditor"; - -/** - * Symbol for marking pasted images. - * Using Symbol.for to create a global symbol that can be accessed across modules. - * @internal - */ -const IS_PASTED_IMAGE = Symbol.for("tambo-is-pasted-image"); - -/** - * Extend the File interface to include the IS_PASTED_IMAGE property. - * This is a type-safe way to mark pasted images without using a broad index signature. - */ -declare global { - interface File { - [IS_PASTED_IMAGE]?: boolean; - } -} diff --git a/src/components/tambo/thread-container.tsx b/src/components/tambo/thread-container.tsx index 0dcec9d..70acf0c 100644 --- a/src/components/tambo/thread-container.tsx +++ b/src/components/tambo/thread-container.tsx @@ -44,7 +44,7 @@ export const ThreadContainer = React.forwardRef< ref={mergedRef} className={cn( // Base layout and styling - "flex flex-col bg-white overflow-hidden bg-background", + "flex flex-col overflow-hidden bg-background", "h-full", // Add smooth transitions for layout changes diff --git a/src/components/tambo/thread-history.tsx b/src/components/tambo/thread-history.tsx index 362ff7c..f3daa14 100644 --- a/src/components/tambo/thread-history.tsx +++ b/src/components/tambo/thread-history.tsx @@ -34,7 +34,6 @@ interface ThreadHistoryContextValue { isCollapsed: boolean; setIsCollapsed: React.Dispatch>; onThreadChange?: () => void; - contextKey?: string; position?: "left" | "right"; updateThreadName: (newName: string, threadId?: string) => Promise; generateThreadName: (threadId: string) => Promise; @@ -57,7 +56,6 @@ const useThreadHistoryContext = () => { * Root component that provides context for thread history */ interface ThreadHistoryProps extends React.HTMLAttributes { - contextKey?: string; onThreadChange?: () => void; children?: React.ReactNode; defaultCollapsed?: boolean; @@ -68,7 +66,6 @@ const ThreadHistory = React.forwardRef( ( { className, - contextKey, onThreadChange, defaultCollapsed = true, position = "left", @@ -81,12 +78,7 @@ const ThreadHistory = React.forwardRef( const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed); const [shouldFocusSearch, setShouldFocusSearch] = React.useState(false); - const { - data: threads, - isLoading, - error, - refetch, - } = useTamboThreadList({ contextKey }); + const { data: threads, isLoading, error, refetch } = useTamboThreadList(); const { switchCurrentThread, @@ -126,7 +118,6 @@ const ThreadHistory = React.forwardRef( isCollapsed, setIsCollapsed, onThreadChange, - contextKey, position, updateThreadName, generateThreadName, @@ -142,7 +133,6 @@ const ThreadHistory = React.forwardRef( searchQuery, isCollapsed, onThreadChange, - contextKey, position, updateThreadName, generateThreadName, diff --git a/src/lib/thread-hooks.ts b/src/lib/thread-hooks.ts index b4b0f3d..59bd1e6 100644 --- a/src/lib/thread-hooks.ts +++ b/src/lib/thread-hooks.ts @@ -3,9 +3,11 @@ import * as React from "react"; import { useEffect, useState } from "react"; /** - * Custom hook to merge multiple refs into one callback ref - * @param refs - Array of refs to merge - * @returns A callback ref that updates all provided refs + * Merges multiple refs into a single callback ref. + * + * In React 19, callback refs may return cleanup functions; this hook fans out + * both assignments and cleanups to all provided refs and tracks the last + * cleanup so it runs when the instance changes. */ export function useMergeRefs( ...refs: (React.Ref | undefined)[] @@ -142,6 +144,11 @@ export function usePositioning( /** * Converts message content into a safely renderable format. * Handles text, resource references, and other content types. + * + * @deprecated This function is deprecated. Message rendering now uses a private + * `convertContentToMarkdown()` function within the message component. This function + * is kept for backward compatibility since it's exposed in the SDK. + * * @param content - The message content (string, element, array, etc.) * @returns A renderable string or React element. */