Repository: vizhub-core/vzcode
Pull request #917: Integrate ESLint for enhanced code linting
Author: login: fantong11
Created: 2025-05-10T10:36:16Z | Merged: 2025-05-19T16:17:16Z

Introduce ESLint support with asynchronous linting capabilities, enabling `.jsx` and `.js` linting.


Diff:
diff --git a/package-lock.json b/package-lock.json
index 6eca0d1f..9388169b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
         "@codemirror/lang-javascript": "^6.2.3",
         "@codemirror/lang-json": "^6.0.1",
         "@codemirror/lang-markdown": "^6.3.2",
+        "@codemirror/lint": "^6.8.5",
         "@codemirror/state": "^6.5.2",
         "@codemirror/theme-one-dark": "^6.1.2",
         "@codemirror/view": "^6.36.5",
@@ -27,7 +28,6 @@
         "@replit/codemirror-lang-svelte": "^6.0.0",
         "@replit/codemirror-vscode-keymap": "^6.0.2",
         "@teamwork/websocket-json-stream": "^2.0.0",
-        "@typescript/vfs": "^1.6.1",
         "@uiw/codemirror-theme-abcdef": "^4.23.10",
         "@uiw/codemirror-theme-dracula": "^4.23.10",
         "@uiw/codemirror-theme-eclipse": "^4.23.10",
@@ -46,7 +46,10 @@
         "d3-array": "^3.2.4",
         "diff-match-patch": "^1.0.5",
         "dotenv": "^16.4.7",
+        "eslint": "^9.26.0",
+        "eslint-linter-browserify": "^9.26.0",
         "express": "^5.1.0",
+        "globals": "^16.1.0",
         "ignore": "^7.0.3",
         "json0-ot-diff": "^1.1.2",
         "livekit-server-sdk": "^2.11.0",
@@ -330,6 +333,16 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/@babel/traverse/node_modules/globals": {
+      "version": "11.12.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/@babel/types": {
       "version": "7.26.9",
       "dev": true,
@@ -344,14 +357,10 @@
     },
     "node_modules/@bufbuild/protobuf": {
       "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.0.tgz",
-      "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==",
       "license": "(Apache-2.0 AND BSD-3-Clause)"
     },
     "node_modules/@cfworker/json-schema": {
       "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz",
-      "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==",
       "license": "MIT"
     },
     "node_modules/@codemirror/autocomplete": {
@@ -447,7 +456,7 @@
       }
     },
     "node_modules/@codemirror/lint": {
-      "version": "6.8.4",
+      "version": "6.8.5",
       "license": "MIT",
       "dependencies": {
         "@codemirror/state": "^6.0.0",
@@ -483,8 +492,6 @@
     },
     "node_modules/@codemirror/view": {
       "version": "6.36.5",
-      "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.5.tgz",
-      "integrity": "sha512-cd+FZEUlu3GQCYnguYm3EkhJ8KJVisqqUsCOKedBoAt/d9c76JUUap6U0UrpElln5k6VyrEOYliMuDAKIeDQLg==",
       "license": "MIT",
       "dependencies": {
         "@codemirror/state": "^6.5.0",
@@ -492,61 +499,8 @@
         "w3c-keyname": "^2.2.4"
       }
     },
-    "node_modules/@esbuild/aix-ppc64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz",
-      "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "aix"
-      ],
-      "engines": {
-        "node": ">=18"
-      }
-    },
-    "node_modules/@esbuild/android-arm": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz",
-      "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=18"
-      }
-    },
-    "node_modules/@esbuild/android-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz",
-      "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=18"
-      }
-    },
-    "node_modules/@esbuild/android-x64": {
+    "node_modules/@esbuild/win32-x64": {
       "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz",
-      "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==",
       "cpu": [
         "x64"
       ],
@@ -554,394 +508,207 @@
       "license": "MIT",
       "optional": true,
       "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=18"
-      }
-    },
-    "node_modules/@esbuild/darwin-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz",
-      "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "darwin"
+        "win32"
       ],
       "engines": {
         "node": ">=18"
       }
     },
-    "node_modules/@esbuild/darwin-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz",
-      "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
+    "node_modules/@eslint-community/eslint-utils": {
+      "version": "4.7.0",
       "license": "MIT",
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
+      "dependencies": {
+        "eslint-visitor-keys": "^3.4.3"
+      },
       "engines": {
-        "node": ">=18"
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
       }
     },
-    "node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz",
-      "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
+    "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+      "version": "3.4.3",
+      "license": "Apache-2.0",
       "engines": {
-        "node": ">=18"
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
       }
     },
-    "node_modules/@esbuild/freebsd-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz",
-      "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
+    "node_modules/@eslint-community/regexpp": {
+      "version": "4.12.1",
       "license": "MIT",
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
       "engines": {
-        "node": ">=18"
+        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
       }
     },
-    "node_modules/@esbuild/linux-arm": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz",
-      "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+    "node_modules/@eslint/config-array": {
+      "version": "0.20.0",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@eslint/object-schema": "^2.1.6",
+        "debug": "^4.3.1",
+        "minimatch": "^3.1.2"
+      },
       "engines": {
-        "node": ">=18"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       }
     },
-    "node_modules/@esbuild/linux-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz",
-      "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+    "node_modules/@eslint/config-helpers": {
+      "version": "0.2.2",
+      "license": "Apache-2.0",
       "engines": {
-        "node": ">=18"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       }
     },
-    "node_modules/@esbuild/linux-ia32": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz",
-      "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+    "node_modules/@eslint/core": {
+      "version": "0.13.0",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@types/json-schema": "^7.0.15"
+      },
       "engines": {
-        "node": ">=18"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       }
     },
-    "node_modules/@esbuild/linux-loong64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz",
-      "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==",
-      "cpu": [
-        "loong64"
-      ],
-      "dev": true,
+    "node_modules/@eslint/eslintrc": {
+      "version": "3.3.1",
       "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+      "dependencies": {
+        "ajv": "^6.12.4",
+        "debug": "^4.3.2",
+        "espree": "^10.0.1",
+        "globals": "^14.0.0",
+        "ignore": "^5.2.0",
+        "import-fresh": "^3.2.1",
+        "js-yaml": "^4.1.0",
+        "minimatch": "^3.1.2",
+        "strip-json-comments": "^3.1.1"
+      },
       "engines": {
-        "node": ">=18"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
       }
     },
-    "node_modules/@esbuild/linux-mips64el": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz",
-      "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==",
-      "cpu": [
-        "mips64el"
-      ],
-      "dev": true,
+    "node_modules/@eslint/eslintrc/node_modules/globals": {
+      "version": "14.0.0",
       "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
       "engines": {
         "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@esbuild/linux-ppc64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz",
-      "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
+    "node_modules/@eslint/eslintrc/node_modules/ignore": {
+      "version": "5.3.2",
       "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
       "engines": {
-        "node": ">=18"
+        "node": ">= 4"
       }
     },
-    "node_modules/@esbuild/linux-riscv64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz",
-      "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==",
-      "cpu": [
-        "riscv64"
-      ],
-      "dev": true,
+    "node_modules/@eslint/js": {
+      "version": "9.26.0",
       "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
       "engines": {
-        "node": ">=18"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       }
     },
-    "node_modules/@esbuild/linux-s390x": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz",
-      "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==",
-      "cpu": [
-        "s390x"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+    "node_modules/@eslint/object-schema": {
+      "version": "2.1.6",
+      "license": "Apache-2.0",
       "engines": {
-        "node": ">=18"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       }
     },
-    "node_modules/@esbuild/linux-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz",
-      "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+    "node_modules/@eslint/plugin-kit": {
+      "version": "0.2.8",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@eslint/core": "^0.13.0",
+        "levn": "^0.4.1"
+      },
       "engines": {
-        "node": ">=18"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       }
     },
-    "node_modules/@esbuild/netbsd-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz",
-      "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
+    "node_modules/@floating-ui/core": {
+      "version": "1.6.9",
       "license": "MIT",
-      "optional": true,
-      "os": [
-        "netbsd"
-      ],
-      "engines": {
-        "node": ">=18"
+      "dependencies": {
+        "@floating-ui/utils": "^0.2.9"
       }
     },
-    "node_modules/@esbuild/netbsd-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz",
-      "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
+    "node_modules/@floating-ui/dom": {
+      "version": "1.6.13",
       "license": "MIT",
-      "optional": true,
-      "os": [
-        "netbsd"
-      ],
-      "engines": {
-        "node": ">=18"
+      "dependencies": {
+        "@floating-ui/core": "^1.6.0",
+        "@floating-ui/utils": "^0.2.9"
       }
     },
-    "node_modules/@esbuild/openbsd-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz",
-      "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "openbsd"
-      ],
-      "engines": {
-        "node": ">=18"
-      }
+    "node_modules/@floating-ui/utils": {
+      "version": "0.2.9",
+      "license": "MIT"
     },
-    "node_modules/@esbuild/openbsd-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz",
-      "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "openbsd"
-      ],
+    "node_modules/@humanfs/core": {
+      "version": "0.19.1",
+      "license": "Apache-2.0",
       "engines": {
-        "node": ">=18"
+        "node": ">=18.18.0"
       }
     },
-    "node_modules/@esbuild/sunos-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz",
-      "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "sunos"
-      ],
+    "node_modules/@humanfs/node": {
+      "version": "0.16.6",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@humanfs/core": "^0.19.1",
+        "@humanwhocodes/retry": "^0.3.0"
+      },
       "engines": {
-        "node": ">=18"
+        "node": ">=18.18.0"
       }
     },
-    "node_modules/@esbuild/win32-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz",
-      "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "win32"
-      ],
+    "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+      "version": "0.3.1",
+      "license": "Apache-2.0",
       "engines": {
-        "node": ">=18"
+        "node": ">=18.18"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
       }
     },
-    "node_modules/@esbuild/win32-ia32": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz",
-      "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "win32"
-      ],
+    "node_modules/@humanwhocodes/module-importer": {
+      "version": "1.0.1",
+      "license": "Apache-2.0",
       "engines": {
-        "node": ">=18"
+        "node": ">=12.22"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
       }
     },
-    "node_modules/@esbuild/win32-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz",
-      "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "win32"
-      ],
+    "node_modules/@humanwhocodes/retry": {
+      "version": "0.4.2",
+      "license": "Apache-2.0",
       "engines": {
-        "node": ">=18"
-      }
-    },
-    "node_modules/@floating-ui/core": {
-      "version": "1.6.9",
-      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
-      "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==",
-      "license": "MIT",
-      "dependencies": {
-        "@floating-ui/utils": "^0.2.9"
-      }
-    },
-    "node_modules/@floating-ui/dom": {
-      "version": "1.6.13",
-      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz",
-      "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==",
-      "license": "MIT",
-      "dependencies": {
-        "@floating-ui/core": "^1.6.0",
-        "@floating-ui/utils": "^0.2.9"
+        "node": ">=18.18"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
       }
     },
-    "node_modules/@floating-ui/utils": {
-      "version": "0.2.9",
-      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
-      "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
-      "license": "MIT"
-    },
     "node_modules/@jridgewell/gen-mapping": {
       "version": "0.3.8",
       "license": "MIT",
@@ -982,8 +749,6 @@
     },
     "node_modules/@langchain/core": {
       "version": "0.3.43",
-      "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.43.tgz",
-      "integrity": "sha512-DwiSUwmZqcuOn7j8SFdeOH1nvaUqG7q8qn3LhobdQYEg5PmjLgd2yLr2KzuT/YWMBfjkOR+Di5K6HEdFmouTxg==",
       "license": "MIT",
       "dependencies": {
         "@cfworker/json-schema": "^4.0.2",
@@ -1005,8 +770,6 @@
     },
     "node_modules/@langchain/core/node_modules/ansi-styles": {
       "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
-      "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
       "license": "MIT",
       "engines": {
         "node": ">=10"
@@ -1017,8 +780,6 @@
     },
     "node_modules/@langchain/core/node_modules/camelcase": {
       "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
-      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
       "license": "MIT",
       "engines": {
         "node": ">=10"
@@ -1029,8 +790,6 @@
     },
     "node_modules/@langchain/core/node_modules/uuid": {
       "version": "10.0.0",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
-      "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
       "funding": [
         "https://github.com/sponsors/broofa",
         "https://github.com/sponsors/ctavan"
@@ -1042,8 +801,6 @@
     },
     "node_modules/@langchain/openai": {
       "version": "0.5.4",
-      "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.5.4.tgz",
-      "integrity": "sha512-fBIEgaAMs1OHHjSuOwtonhtFTlRyFETAS9y/4SZxlXV5lLdwEU5OAbfaBTcCR0A58rrlmgt8iPnm2IWn4Onjjw==",
       "license": "MIT",
       "dependencies": {
         "js-tiktoken": "^1.0.12",
@@ -1123,8 +880,6 @@
     },
     "node_modules/@livekit/components-core": {
       "version": "0.12.2",
-      "resolved": "https://registry.npmjs.org/@livekit/components-core/-/components-core-0.12.2.tgz",
-      "integrity": "sha512-lSNEyWuJ94PNVR7uycpqxV5XG+GmPpRCRPFEiVnAKG8xbTKlBrlu6ruPgg3/dZG4oHCPOpTN7VPV4jbcUjFAoA==",
       "license": "Apache-2.0",
       "dependencies": {
         "@floating-ui/dom": "1.6.13",
@@ -1141,8 +896,6 @@
     },
     "node_modules/@livekit/components-react": {
       "version": "2.9.0",
-      "resolved": "https://registry.npmjs.org/@livekit/components-react/-/components-react-2.9.0.tgz",
-      "integrity": "sha512-HAY1d1N2n5e8KP3ogTGgvHpO4afDSKAt1pqDsHPumTYcNTGKuMtIfMc4CfUMrtVMQAggzouOTYfb/gC4gnaYiQ==",
       "license": "Apache-2.0",
       "dependencies": {
         "@livekit/components-core": "0.12.2",
@@ -1167,15 +920,11 @@
     },
     "node_modules/@livekit/mutex": {
       "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@livekit/mutex/-/mutex-1.1.1.tgz",
-      "integrity": "sha512-EsshAucklmpuUAfkABPxJNhzj9v2sG7JuzFDL4ML1oJQSV14sqrpTYnsaOudMAw9yOaW53NU3QQTlUQoRs4czw==",
       "license": "Apache-2.0",
       "peer": true
     },
     "node_modules/@livekit/protocol": {
       "version": "1.34.0",
-      "resolved": "https://registry.npmjs.org/@livekit/protocol/-/protocol-1.34.0.tgz",
-      "integrity": "sha512-bU7pCLAMRVTVZb1KSxA46q55bhOc4iATrY/gccy2/oX1D57tiZEI+8wGRWHeDwBb0UwnABu6JXzC4tTFkdsaOg==",
       "license": "Apache-2.0",
       "peer": true,
       "dependencies": {
@@ -1198,6 +947,25 @@
       "version": "1.0.2",
       "license": "MIT"
     },
+    "node_modules/@modelcontextprotocol/sdk": {
+      "version": "1.11.0",
+      "license": "MIT",
+      "dependencies": {
+        "content-type": "^1.0.5",
+        "cors": "^2.8.5",
+        "cross-spawn": "^7.0.3",
+        "eventsource": "^3.0.2",
+        "express": "^5.0.1",
+        "express-rate-limit": "^7.5.0",
+        "pkce-challenge": "^5.0.0",
+        "raw-body": "^3.0.0",
+        "zod": "^3.23.8",
+        "zod-to-json-schema": "^3.24.1"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
     "node_modules/@parcel/watcher": {
       "version": "2.5.1",
       "dev": true,
@@ -1233,25 +1001,6 @@
         "@parcel/watcher-win32-x64": "2.5.1"
       }
     },
-    "node_modules/@parcel/watcher-linux-x64-glibc": {
-      "version": "2.5.1",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">= 10.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
     "node_modules/@popperjs/core": {
       "version": "2.11.8",
       "license": "MIT",
@@ -1398,9 +1147,9 @@
       ]
     },
     "node_modules/@rollup/rollup-darwin-arm64": {
-      "version": "4.39.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.39.0.tgz",
-      "integrity": "sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz",
+      "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==",
       "cpu": [
         "arm64"
       ],
@@ -1566,6 +1315,8 @@
     },
     "node_modules/@rollup/rollup-linux-x64-gnu": {
       "version": "4.34.8",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz",
+      "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==",
       "cpu": [
         "x64"
       ],
@@ -1619,9 +1370,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-x64-msvc": {
-      "version": "4.39.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.39.0.tgz",
-      "integrity": "sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz",
+      "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==",
       "cpu": [
         "x64"
       ],
@@ -1633,8 +1384,6 @@
     },
     "node_modules/@sindresorhus/is": {
       "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
-      "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
       "license": "MIT",
       "engines": {
         "node": ">=10"
@@ -1652,8 +1401,6 @@
     },
     "node_modules/@szmarczak/http-timer": {
       "version": "4.0.6",
-      "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
-      "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
       "license": "MIT",
       "dependencies": {
         "defer-to-connect": "^2.0.0"
@@ -1705,8 +1452,6 @@
     },
     "node_modules/@types/cacheable-request": {
       "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
-      "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
       "license": "MIT",
       "dependencies": {
         "@types/http-cache-semantics": "*",
@@ -1717,8 +1462,6 @@
     },
     "node_modules/@types/cookie": {
       "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
-      "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
       "license": "MIT"
     },
     "node_modules/@types/estree": {
@@ -1727,14 +1470,14 @@
     },
     "node_modules/@types/http-cache-semantics": {
       "version": "4.0.4",
-      "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
-      "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
+      "license": "MIT"
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.15",
       "license": "MIT"
     },
     "node_modules/@types/keyv": {
       "version": "3.1.4",
-      "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
-      "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
       "license": "MIT",
       "dependencies": {
         "@types/node": "*"
@@ -1788,8 +1531,6 @@
     },
     "node_modules/@types/responselike": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
-      "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
       "license": "MIT",
       "dependencies": {
         "@types/node": "*"
@@ -1797,14 +1538,10 @@
     },
     "node_modules/@types/retry": {
       "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
-      "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
       "license": "MIT"
     },
     "node_modules/@types/uuid": {
       "version": "10.0.0",
-      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
-      "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
       "license": "MIT"
     },
     "node_modules/@types/warning": {
@@ -1813,28 +1550,14 @@
     },
     "node_modules/@types/yauzl": {
       "version": "2.10.3",
-      "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
-      "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
       "license": "MIT",
       "optional": true,
       "dependencies": {
         "@types/node": "*"
       }
     },
-    "node_modules/@typescript/vfs": {
-      "version": "1.6.1",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "^4.1.1"
-      },
-      "peerDependencies": {
-        "typescript": "*"
-      }
-    },
     "node_modules/@uiw/codemirror-theme-abcdef": {
       "version": "4.23.10",
-      "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-abcdef/-/codemirror-theme-abcdef-4.23.10.tgz",
-      "integrity": "sha512-OXvzM2bR1EvZfLBnm/ndM1rujplJ9zV4nd7IV0fKU+RsVu94mPeKX71+fag0AQVllU7BGslg6zw8YPG4FVqLBA==",
       "license": "MIT",
       "dependencies": {
         "@uiw/codemirror-themes": "4.23.10"
@@ -1845,8 +1568,6 @@
     },
     "node_modules/@uiw/codemirror-theme-dracula": {
       "version": "4.23.10",
-      "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-dracula/-/codemirror-theme-dracula-4.23.10.tgz",
-      "integrity": "sha512-2xTLHT+QwKrY1NKXcbpB3wPoOdR1JVCeCQIT0f4dupudIcJp+XuIDwUX28fHqc5mwk/9pSbiopW2f+hMwL5Cfw==",
       "license": "MIT",
       "dependencies": {
         "@uiw/codemirror-themes": "4.23.10"
@@ -1857,8 +1578,6 @@
     },
     "node_modules/@uiw/codemirror-theme-eclipse": {
       "version": "4.23.10",
-      "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-eclipse/-/codemirror-theme-eclipse-4.23.10.tgz",
-      "integrity": "sha512-5ka+NiAknu7NIPerDMkoRrO7p5g6SIkuN0V51A5gjW6wDZtGTHzsLTbU0HwLVaYqm8tKxb0RHhtgnCTPlrN8XQ==",
       "license": "MIT",
       "dependencies": {
         "@uiw/codemirror-themes": "4.23.10"
@@ -1869,8 +1588,6 @@
     },
     "node_modules/@uiw/codemirror-theme-github": {
       "version": "4.23.10",
-      "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.23.10.tgz",
-      "integrity": "sha512-jTg2sHAcU1d+8x0O+EBDI71rtJ8PWKIW8gzy+SW4wShQTAdsqGHk5y1ynt3KIeoaUkqngLqAK4SkhPaUKlqZqg==",
       "license": "MIT",
       "dependencies": {
         "@uiw/codemirror-themes": "4.23.10"
@@ -1881,8 +1598,6 @@
     },
     "node_modules/@uiw/codemirror-theme-material": {
       "version": "4.23.10",
-      "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-material/-/codemirror-theme-material-4.23.10.tgz",
-      "integrity": "sha512-RN+K7Vc/qea+ky5w0KVCtfwfVqtedicOMKxeBu/fs82tyU5Q5oQ2UlS5Y94Sv05BRkHYluOvMwypUwWkSq2q6g==",
       "license": "MIT",
       "dependencies": {
         "@uiw/codemirror-themes": "4.23.10"
@@ -1893,8 +1608,6 @@
     },
     "node_modules/@uiw/codemirror-theme-nord": {
       "version": "4.23.10",
-      "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-nord/-/codemirror-theme-nord-4.23.10.tgz",
-      "integrity": "sha512-GUGzb0eUZLPzneTmbfk7qWz812B1ak97XOUhRZUPnzVHztgqIVZcwYRf2XkoAySNHU23szZsxxyNZeQ2nAZs6A==",
       "license": "MIT",
       "dependencies": {
         "@uiw/codemirror-themes": "4.23.10"
@@ -1905,8 +1618,6 @@
     },
     "node_modules/@uiw/codemirror-theme-okaidia": {
       "version": "4.23.10",
-      "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-okaidia/-/codemirror-theme-okaidia-4.23.10.tgz",
-      "integrity": "sha512-9Ccb96a9HPz4a3U0iH6CTHpLVfAeVCSlorp+McBp2QcoJIo1kwZ3hu34MDupW0m9jfdLddAlCEUuK3Kmre8ClQ==",
       "license": "MIT",
       "dependencies": {
         "@uiw/codemirror-themes": "4.23.10"
@@ -1917,8 +1628,6 @@
     },
     "node_modules/@uiw/codemirror-theme-xcode": {
       "version": "4.23.10",
-      "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-xcode/-/codemirror-theme-xcode-4.23.10.tgz",
-      "integrity": "sha512-meYMRLr0mTqGZerihSTKpjceRkxbFfpnXX9RyDZFwloydxzWY/6iGEt1/RMY+cWoxgjBYSiunqtU0qgQH0WAuA==",
       "license": "MIT",
       "dependencies": {
         "@uiw/codemirror-themes": "4.23.10"
@@ -1929,8 +1638,6 @@
     },
     "node_modules/@uiw/codemirror-themes": {
       "version": "4.23.10",
-      "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.23.10.tgz",
-      "integrity": "sha512-dU0UgEEgEXCAYpxuVDQ6fovE82XsqgHZckTJOH6Bs8xCi3Z7dwBKO4pXuiA8qGDwTOXOMjSzfi+pRViDm7OfWw==",
       "license": "MIT",
       "dependencies": {
         "@codemirror/language": "^6.0.0",
@@ -1966,8 +1673,6 @@
     },
     "node_modules/@vitest/expect": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz",
-      "integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1982,8 +1687,6 @@
     },
     "node_modules/@vitest/mocker": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz",
-      "integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2009,8 +1712,6 @@
     },
     "node_modules/@vitest/pretty-format": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz",
-      "integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2022,8 +1723,6 @@
     },
     "node_modules/@vitest/runner": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz",
-      "integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2036,8 +1735,6 @@
     },
     "node_modules/@vitest/snapshot": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz",
-      "integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2051,8 +1748,6 @@
     },
     "node_modules/@vitest/spy": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz",
-      "integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2064,8 +1759,6 @@
     },
     "node_modules/@vitest/utils": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz",
-      "integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2079,8 +1772,6 @@
     },
     "node_modules/@vizhub/viz-types": {
       "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/@vizhub/viz-types/-/viz-types-0.1.0.tgz",
-      "integrity": "sha512-g1J3t5WPILUSfM+Pjq/CsSkvQMB5yh9RQmWsIFESq5BEwFK7zR6Zy4h6t5VPTP8iktLyiXtvYOuvDGcUb+LiCw==",
       "license": "MIT"
     },
     "node_modules/abort-controller": {
@@ -2095,8 +1786,6 @@
     },
     "node_modules/accepts": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
-      "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
       "license": "MIT",
       "dependencies": {
         "mime-types": "^3.0.0",
@@ -2108,8 +1797,6 @@
     },
     "node_modules/accepts/node_modules/mime-db": {
       "version": "1.54.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
-      "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.6"
@@ -2117,8 +1804,6 @@
     },
     "node_modules/accepts/node_modules/mime-types": {
       "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
-      "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
       "license": "MIT",
       "dependencies": {
         "mime-db": "^1.54.0"
@@ -2137,6 +1822,13 @@
         "node": ">=0.4.0"
       }
     },
+    "node_modules/acorn-jsx": {
+      "version": "5.3.2",
+      "license": "MIT",
+      "peerDependencies": {
+        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
     "node_modules/acorn-typescript": {
       "version": "1.4.13",
       "license": "MIT",
@@ -2165,6 +1857,20 @@
         "node": ">= 8.0.0"
       }
     },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "license": "MIT",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
     "node_modules/ansi-regex": {
       "version": "5.0.1",
       "dev": true,
@@ -2186,6 +1892,10 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
+    "node_modules/argparse": {
+      "version": "2.0.1",
+      "license": "Python-2.0"
+    },
     "node_modules/aria-query": {
       "version": "5.3.2",
       "license": "Apache-2.0",
@@ -2200,8 +1910,6 @@
     },
     "node_modules/assertion-error": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
-      "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2224,10 +1932,12 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "license": "MIT"
+    },
     "node_modules/base64-js": {
       "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
-      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
       "funding": [
         {
           "type": "github",
@@ -2246,8 +1956,6 @@
     },
     "node_modules/body-parser": {
       "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
-      "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
       "license": "MIT",
       "dependencies": {
         "bytes": "^3.1.2",
@@ -2264,6 +1972,14 @@
         "node": ">=18"
       }
     },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/braces": {
       "version": "3.0.3",
       "dev": true,
@@ -2309,8 +2025,6 @@
     },
     "node_modules/buffer-crc32": {
       "version": "0.2.13",
-      "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-      "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
       "license": "MIT",
       "engines": {
         "node": "*"
@@ -2331,8 +2045,6 @@
     },
     "node_modules/bytes": {
       "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
-      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.8"
@@ -2340,8 +2052,6 @@
     },
     "node_modules/cac": {
       "version": "6.7.14",
-      "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
-      "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2350,8 +2060,6 @@
     },
     "node_modules/cacheable-lookup": {
       "version": "5.0.4",
-      "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
-      "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
       "license": "MIT",
       "engines": {
         "node": ">=10.6.0"
@@ -2359,8 +2067,6 @@
     },
     "node_modules/cacheable-request": {
       "version": "7.0.4",
-      "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
-      "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
       "license": "MIT",
       "dependencies": {
         "clone-response": "^1.0.2",
@@ -2416,10 +2122,15 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/callsites": {
+      "version": "3.1.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/camelcase": {
       "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz",
-      "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==",
       "license": "MIT",
       "engines": {
         "node": ">=16"
@@ -2430,8 +2141,6 @@
     },
     "node_modules/camelcase-keys": {
       "version": "9.1.3",
-      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-9.1.3.tgz",
-      "integrity": "sha512-Rircqi9ch8AnZscQcsA1C47NFdaO3wukpmIRzYcDOrmvgt78hM/sj5pZhZNec2NM12uk5vTwRHZ4anGcrC4ZTg==",
       "license": "MIT",
       "dependencies": {
         "camelcase": "^8.0.0",
@@ -2448,8 +2157,6 @@
     },
     "node_modules/camelcase-keys/node_modules/quick-lru": {
       "version": "6.1.2",
-      "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz",
-      "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==",
       "license": "MIT",
       "engines": {
         "node": ">=12"
@@ -2479,8 +2186,6 @@
     },
     "node_modules/chai": {
       "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz",
-      "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2520,8 +2225,6 @@
     },
     "node_modules/check-error": {
       "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
-      "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2561,8 +2264,6 @@
     },
     "node_modules/clone-response": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
-      "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
       "license": "MIT",
       "dependencies": {
         "mimic-response": "^1.0.0"
@@ -2638,6 +2339,10 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "license": "MIT"
+    },
     "node_modules/concurrently": {
       "version": "9.1.2",
       "dev": true,
@@ -2664,8 +2369,6 @@
     },
     "node_modules/console-table-printer": {
       "version": "2.12.1",
-      "resolved": "https://registry.npmjs.org/console-table-printer/-/console-table-printer-2.12.1.tgz",
-      "integrity": "sha512-wKGOQRRvdnd89pCeH96e2Fn4wkbenSP6LMHfjfyNLMbGuHEFbMqQNuxXqd0oXG9caIOQ1FTvc5Uijp9/4jujnQ==",
       "license": "MIT",
       "dependencies": {
         "simple-wcswidth": "^1.0.1"
@@ -2673,8 +2376,6 @@
     },
     "node_modules/content-disposition": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
-      "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
       "license": "MIT",
       "dependencies": {
         "safe-buffer": "5.2.1"
@@ -2704,13 +2405,22 @@
     },
     "node_modules/cookie-signature": {
       "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
-      "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
       "license": "MIT",
       "engines": {
         "node": ">=6.6.0"
       }
     },
+    "node_modules/cors": {
+      "version": "2.8.5",
+      "license": "MIT",
+      "dependencies": {
+        "object-assign": "^4",
+        "vary": "^1"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
     "node_modules/crelt": {
       "version": "1.0.6",
       "license": "MIT"
@@ -2734,7 +2444,6 @@
     },
     "node_modules/cross-spawn": {
       "version": "7.0.6",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "path-key": "^3.1.0",
@@ -2776,8 +2485,6 @@
     },
     "node_modules/decamelize": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
       "license": "MIT",
       "engines": {
         "node": ">=0.10.0"
@@ -2785,8 +2492,6 @@
     },
     "node_modules/decompress-response": {
       "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
-      "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
       "license": "MIT",
       "dependencies": {
         "mimic-response": "^3.1.0"
@@ -2800,8 +2505,6 @@
     },
     "node_modules/decompress-response/node_modules/mimic-response": {
       "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
-      "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
       "license": "MIT",
       "engines": {
         "node": ">=10"
@@ -2812,8 +2515,6 @@
     },
     "node_modules/deep-eql": {
       "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
-      "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2838,6 +2539,10 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/deep-is": {
+      "version": "0.1.4",
+      "license": "MIT"
+    },
     "node_modules/default-browser": {
       "version": "5.2.1",
       "license": "MIT",
@@ -2864,8 +2569,6 @@
     },
     "node_modules/defer-to-connect": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
-      "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
       "license": "MIT",
       "engines": {
         "node": ">=10"
@@ -2994,8 +2697,6 @@
     },
     "node_modules/encodeurl": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
-      "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.8"
@@ -3003,8 +2704,6 @@
     },
     "node_modules/end-of-stream": {
       "version": "1.4.4",
-      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
-      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
       "license": "MIT",
       "dependencies": {
         "once": "^1.4.0"
@@ -3026,8 +2725,6 @@
     },
     "node_modules/es-module-lexer": {
       "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
-      "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==",
       "dev": true,
       "license": "MIT"
     },
@@ -3056,8 +2753,6 @@
     },
     "node_modules/esbuild": {
       "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz",
-      "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==",
       "dev": true,
       "hasInstallScript": true,
       "license": "MIT",
@@ -3105,15 +2800,143 @@
     },
     "node_modules/escape-html": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
       "license": "MIT"
     },
+    "node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint": {
+      "version": "9.26.0",
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.2.0",
+        "@eslint-community/regexpp": "^4.12.1",
+        "@eslint/config-array": "^0.20.0",
+        "@eslint/config-helpers": "^0.2.1",
+        "@eslint/core": "^0.13.0",
+        "@eslint/eslintrc": "^3.3.1",
+        "@eslint/js": "9.26.0",
+        "@eslint/plugin-kit": "^0.2.8",
+        "@humanfs/node": "^0.16.6",
+        "@humanwhocodes/module-importer": "^1.0.1",
+        "@humanwhocodes/retry": "^0.4.2",
+        "@modelcontextprotocol/sdk": "^1.8.0",
+        "@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",
+        "esquery": "^1.5.0",
+        "esutils": "^2.0.2",
+        "fast-deep-equal": "^3.1.3",
+        "file-entry-cache": "^8.0.0",
+        "find-up": "^5.0.0",
+        "glob-parent": "^6.0.2",
+        "ignore": "^5.2.0",
+        "imurmurhash": "^0.1.4",
+        "is-glob": "^4.0.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "lodash.merge": "^4.6.2",
+        "minimatch": "^3.1.2",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.9.3",
+        "zod": "^3.24.2"
+      },
+      "bin": {
+        "eslint": "bin/eslint.js"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://eslint.org/donate"
+      },
+      "peerDependencies": {
+        "jiti": "*"
+      },
+      "peerDependenciesMeta": {
+        "jiti": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/eslint-linter-browserify": {
+      "version": "9.26.0",
+      "license": "MIT"
+    },
+    "node_modules/eslint-scope": {
+      "version": "8.3.0",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-visitor-keys": {
+      "version": "4.2.0",
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint/node_modules/ignore": {
+      "version": "5.3.2",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
     "node_modules/esm-env": {
       "version": "1.2.2",
       "license": "MIT",
       "peer": true
     },
+    "node_modules/espree": {
+      "version": "10.3.0",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "acorn": "^8.14.0",
+        "acorn-jsx": "^5.3.2",
+        "eslint-visitor-keys": "^4.2.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/esquery": {
+      "version": "1.6.0",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "estraverse": "^5.1.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
     "node_modules/esrap": {
       "version": "1.4.5",
       "license": "MIT",
@@ -3122,20 +2945,40 @@
         "@jridgewell/sourcemap-codec": "^1.4.15"
       }
     },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "5.3.0",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
     "node_modules/estree-walker": {
       "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
-      "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@types/estree": "^1.0.0"
       }
     },
+    "node_modules/esutils": {
+      "version": "2.0.3",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/etag": {
       "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.6"
@@ -3150,24 +2993,35 @@
     },
     "node_modules/eventemitter3": {
       "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
-      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
       "license": "MIT"
     },
     "node_modules/events": {
       "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
-      "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
       "license": "MIT",
       "peer": true,
       "engines": {
         "node": ">=0.8.x"
       }
     },
+    "node_modules/eventsource": {
+      "version": "3.0.6",
+      "license": "MIT",
+      "dependencies": {
+        "eventsource-parser": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/eventsource-parser": {
+      "version": "3.0.1",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
     "node_modules/expect-type": {
       "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz",
-      "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==",
       "dev": true,
       "license": "Apache-2.0",
       "engines": {
@@ -3176,8 +3030,6 @@
     },
     "node_modules/express": {
       "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
-      "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
       "license": "MIT",
       "dependencies": {
         "accepts": "^2.0.0",
@@ -3216,10 +3068,21 @@
         "url": "https://opencollective.com/express"
       }
     },
+    "node_modules/express-rate-limit": {
+      "version": "7.5.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/express-rate-limit"
+      },
+      "peerDependencies": {
+        "express": "^4.11 || 5 || ^5.0.0-beta.1"
+      }
+    },
     "node_modules/express/node_modules/mime-db": {
       "version": "1.54.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
-      "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.6"
@@ -3227,8 +3090,6 @@
     },
     "node_modules/express/node_modules/mime-types": {
       "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
-      "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
       "license": "MIT",
       "dependencies": {
         "mime-db": "^1.54.0"
@@ -3239,8 +3100,6 @@
     },
     "node_modules/extract-zip": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
-      "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
       "license": "BSD-2-Clause",
       "dependencies": {
         "debug": "^4.1.1",
@@ -3261,15 +3120,31 @@
       "version": "3.1.3",
       "license": "MIT"
     },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "license": "MIT"
+    },
+    "node_modules/fast-levenshtein": {
+      "version": "2.0.6",
+      "license": "MIT"
+    },
     "node_modules/fd-slicer": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
-      "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
       "license": "MIT",
       "dependencies": {
         "pend": "~1.2.0"
       }
     },
+    "node_modules/file-entry-cache": {
+      "version": "8.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "flat-cache": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      }
+    },
     "node_modules/fill-range": {
       "version": "7.1.1",
       "dev": true,
@@ -3284,8 +3159,6 @@
     },
     "node_modules/finalhandler": {
       "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
-      "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
       "license": "MIT",
       "dependencies": {
         "debug": "^4.4.0",
@@ -3299,6 +3172,35 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/find-up": {
+      "version": "5.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/flat-cache": {
+      "version": "4.0.1",
+      "license": "MIT",
+      "dependencies": {
+        "flatted": "^3.2.9",
+        "keyv": "^4.5.4"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/flatted": {
+      "version": "3.3.3",
+      "license": "ISC"
+    },
     "node_modules/form-data": {
       "version": "4.0.2",
       "license": "MIT",
@@ -3336,8 +3238,6 @@
     },
     "node_modules/fresh": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
-      "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.8"
@@ -3422,8 +3322,6 @@
     },
     "node_modules/get-stream": {
       "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
-      "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
       "license": "MIT",
       "dependencies": {
         "pump": "^3.0.0"
@@ -3435,12 +3333,26 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/glob-parent": {
+      "version": "6.0.2",
+      "license": "ISC",
+      "dependencies": {
+        "is-glob": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
     "node_modules/globals": {
-      "version": "11.12.0",
-      "dev": true,
+      "version": "16.1.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
+      "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
       "license": "MIT",
       "engines": {
-        "node": ">=4"
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/gopd": {
@@ -3455,8 +3367,6 @@
     },
     "node_modules/got": {
       "version": "11.8.6",
-      "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
-      "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
       "license": "MIT",
       "dependencies": {
         "@sindresorhus/is": "^4.0.0",
@@ -3534,15 +3444,11 @@
     },
     "node_modules/hpagent": {
       "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-0.1.2.tgz",
-      "integrity": "sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ==",
       "license": "MIT",
       "optional": true
     },
     "node_modules/http-cache-semantics": {
       "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
-      "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
       "license": "BSD-2-Clause"
     },
     "node_modules/http-errors": {
@@ -3561,8 +3467,6 @@
     },
     "node_modules/http2-wrapper": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
-      "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
       "license": "MIT",
       "dependencies": {
         "quick-lru": "^5.1.1",
@@ -3581,8 +3485,6 @@
     },
     "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"
@@ -3603,6 +3505,27 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/import-fresh": {
+      "version": "3.3.1",
+      "license": "MIT",
+      "dependencies": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/imurmurhash": {
+      "version": "0.1.4",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8.19"
+      }
+    },
     "node_modules/inherits": {
       "version": "2.0.4",
       "license": "ISC"
@@ -3671,9 +3594,7 @@
     },
     "node_modules/is-extglob": {
       "version": "2.1.1",
-      "dev": true,
       "license": "MIT",
-      "optional": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -3688,9 +3609,7 @@
     },
     "node_modules/is-glob": {
       "version": "4.0.3",
-      "dev": true,
       "license": "MIT",
-      "optional": true,
       "dependencies": {
         "is-extglob": "^2.1.1"
       },
@@ -3725,8 +3644,6 @@
     },
     "node_modules/is-promise": {
       "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
-      "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
       "license": "MIT"
     },
     "node_modules/is-reference": {
@@ -3768,13 +3685,10 @@
     },
     "node_modules/isexe": {
       "version": "2.0.0",
-      "dev": true,
       "license": "ISC"
     },
     "node_modules/jose": {
       "version": "5.10.0",
-      "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz",
-      "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
       "license": "MIT",
       "funding": {
         "url": "https://github.com/sponsors/panva"
@@ -3782,8 +3696,6 @@
     },
     "node_modules/js-tiktoken": {
       "version": "1.0.19",
-      "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.19.tgz",
-      "integrity": "sha512-XC63YQeEcS47Y53gg950xiZ4IWmkfMe4p2V9OSaBt26q+p47WHn18izuXzSclCI73B7yGqtfRsT6jcZQI0y08g==",
       "license": "MIT",
       "dependencies": {
         "base64-js": "^1.5.1"
@@ -3793,6 +3705,16 @@
       "version": "4.0.0",
       "license": "MIT"
     },
+    "node_modules/js-yaml": {
+      "version": "4.1.0",
+      "license": "MIT",
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
     "node_modules/jsesc": {
       "version": "3.1.0",
       "dev": true,
@@ -3806,8 +3728,14 @@
     },
     "node_modules/json-buffer": {
       "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
-      "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+      "license": "MIT"
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "license": "MIT"
+    },
+    "node_modules/json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
       "license": "MIT"
     },
     "node_modules/json0-ot-diff": {
@@ -3830,8 +3758,6 @@
     },
     "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==",
       "license": "MIT",
       "dependencies": {
         "json-buffer": "3.0.1"
@@ -3839,8 +3765,6 @@
     },
     "node_modules/langsmith": {
       "version": "0.3.10",
-      "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.3.10.tgz",
-      "integrity": "sha512-V6SnJhxKt9AbdVfl86OrEBl8uGwO0/WE2qqDcRXxHxzdCDnj+sV7nstr5VL0a6zxZmyMaw6eBbYwB4PTYKRvvQ==",
       "license": "MIT",
       "dependencies": {
         "@types/uuid": "^10.0.0",
@@ -3862,8 +3786,6 @@
     },
     "node_modules/langsmith/node_modules/semver": {
       "version": "7.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
-      "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
       "license": "ISC",
       "bin": {
         "semver": "bin/semver.js"
@@ -3874,8 +3796,6 @@
     },
     "node_modules/langsmith/node_modules/uuid": {
       "version": "10.0.0",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
-      "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
       "funding": [
         "https://github.com/sponsors/broofa",
         "https://github.com/sponsors/ctavan"
@@ -3885,10 +3805,19 @@
         "uuid": "dist/bin/uuid"
       }
     },
+    "node_modules/levn": {
+      "version": "0.4.1",
+      "license": "MIT",
+      "dependencies": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
     "node_modules/livekit-client": {
       "version": "2.9.9",
-      "resolved": "https://registry.npmjs.org/livekit-client/-/livekit-client-2.9.9.tgz",
-      "integrity": "sha512-Mrm9Z/kPmJP5r4EMbzXPfB27gRP+tZtU7Zzen2o8u6w5N6FxaqXerRFqtXddGXaVzZouJOAg51/5A9u3saC/2A==",
       "license": "Apache-2.0",
       "peer": true,
       "dependencies": {
@@ -3905,8 +3834,6 @@
     },
     "node_modules/livekit-client/node_modules/loglevel": {
       "version": "1.9.2",
-      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz",
-      "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==",
       "license": "MIT",
       "peer": true,
       "engines": {
@@ -3919,8 +3846,6 @@
     },
     "node_modules/livekit-server-sdk": {
       "version": "2.11.0",
-      "resolved": "https://registry.npmjs.org/livekit-server-sdk/-/livekit-server-sdk-2.11.0.tgz",
-      "integrity": "sha512-SmUkVHwO9lYUstsJgt3rw9aC4E3dFBfreTLGXqxEWWegjaqcVDxropfYX57Tfs8eRiawd8ndk+AavF5QJGiWpg==",
       "license": "Apache-2.0",
       "dependencies": {
         "@bufbuild/protobuf": "^1.7.2",
@@ -3934,8 +3859,6 @@
     },
     "node_modules/livekit-server-sdk/node_modules/@livekit/protocol": {
       "version": "1.36.1",
-      "resolved": "https://registry.npmjs.org/@livekit/protocol/-/protocol-1.36.1.tgz",
-      "integrity": "sha512-nN3QnITAQ5yXk7UKfotH7CRWIlEozNWeKVyFJ0/+dtSzvWP/ib+10l1DDnRYi3A1yICJOGAKFgJ5d6kmi1HCUA==",
       "license": "Apache-2.0",
       "dependencies": {
         "@bufbuild/protobuf": "^1.10.0"
@@ -3946,6 +3869,19 @@
       "license": "MIT",
       "peer": true
     },
+    "node_modules/locate-path": {
+      "version": "6.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/lodash": {
       "version": "4.17.21",
       "dev": true,
@@ -3953,20 +3889,18 @@
     },
     "node_modules/lodash.clonedeep": {
       "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
-      "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
       "license": "MIT"
     },
     "node_modules/lodash.debounce": {
       "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
-      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.merge": {
+      "version": "4.6.2",
       "license": "MIT"
     },
     "node_modules/loglevel": {
       "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz",
-      "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.6.0"
@@ -3988,15 +3922,11 @@
     },
     "node_modules/loupe": {
       "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz",
-      "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==",
       "dev": true,
       "license": "MIT"
     },
     "node_modules/lowercase-keys": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
-      "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
       "license": "MIT",
       "engines": {
         "node": ">=8"
@@ -4019,8 +3949,6 @@
     },
     "node_modules/map-obj": {
       "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-5.0.0.tgz",
-      "integrity": "sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA==",
       "license": "MIT",
       "engines": {
         "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
@@ -4038,8 +3966,6 @@
     },
     "node_modules/media-typer": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
-      "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.8"
@@ -4047,8 +3973,6 @@
     },
     "node_modules/merge-descriptors": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
-      "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
       "license": "MIT",
       "engines": {
         "node": ">=18"
@@ -4089,21 +4013,27 @@
     },
     "node_modules/mimic-response": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
-      "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
       "license": "MIT",
       "engines": {
         "node": ">=4"
       }
     },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/ms": {
       "version": "2.1.3",
       "license": "MIT"
     },
     "node_modules/mustache": {
       "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
-      "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
       "license": "MIT",
       "bin": {
         "mustache": "bin/mustache"
@@ -4111,8 +4041,6 @@
     },
     "node_modules/nanoid": {
       "version": "3.3.11",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
-      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
       "dev": true,
       "funding": [
         {
@@ -4128,10 +4056,12 @@
         "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
       }
     },
+    "node_modules/natural-compare": {
+      "version": "1.4.0",
+      "license": "MIT"
+    },
     "node_modules/negotiator": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
-      "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.6"
@@ -4139,8 +4069,6 @@
     },
     "node_modules/ngrok": {
       "version": "5.0.0-beta.2",
-      "resolved": "https://registry.npmjs.org/ngrok/-/ngrok-5.0.0-beta.2.tgz",
-      "integrity": "sha512-UzsyGiJ4yTTQLCQD11k1DQaMwq2/SsztBg2b34zAqcyjS25qjDpogMKPaCKHwe/APRTHeel3iDXcVctk5CNaCQ==",
       "hasInstallScript": true,
       "license": "BSD-2-Clause",
       "dependencies": {
@@ -4162,8 +4090,6 @@
     },
     "node_modules/ngrok/node_modules/uuid": {
       "version": "8.3.2",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
-      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
       "license": "MIT",
       "bin": {
         "uuid": "dist/bin/uuid"
@@ -4217,8 +4143,6 @@
     },
     "node_modules/normalize-url": {
       "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
-      "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
       "license": "MIT",
       "engines": {
         "node": ">=10"
@@ -4229,8 +4153,6 @@
     },
     "node_modules/npm": {
       "version": "11.2.0",
-      "resolved": "https://registry.npmjs.org/npm/-/npm-11.2.0.tgz",
-      "integrity": "sha512-PcnFC6gTo9VDkxVaQ1/mZAS3JoWrDjAI+a6e2NgfYQSGDwftJlbdV0jBMi2V8xQPqbGcWaa7p3UP0SKF+Bhm2g==",
       "bundleDependencies": [
         "@isaacs/string-locale-compare",
         "@npmcli/arborist",
@@ -4385,8 +4307,6 @@
     },
     "node_modules/npm-check-updates": {
       "version": "17.1.16",
-      "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.16.tgz",
-      "integrity": "sha512-9nohkfjLRzLfsLVGbO34eXBejvrOOTuw5tvNammH73KEFG5XlFoi3G2TgjTExHtnrKWCbZ+mTT+dbNeSjASIPw==",
       "dev": true,
       "license": "Apache-2.0",
       "bin": {
@@ -6694,8 +6614,6 @@
     },
     "node_modules/object-inspect": {
       "version": "1.13.4",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
-      "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.4"
@@ -6737,8 +6655,6 @@
     },
     "node_modules/once": {
       "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
       "license": "ISC",
       "dependencies": {
         "wrappy": "1"
@@ -6762,8 +6678,6 @@
     },
     "node_modules/openai": {
       "version": "4.91.1",
-      "resolved": "https://registry.npmjs.org/openai/-/openai-4.91.1.tgz",
-      "integrity": "sha512-DbjrR0hIMQFbxz8+3qBsfPJnh3+I/skPgoSlT7f9eiZuhGBUissPQULNgx6gHNkLoZ3uS0uYS6eXPUdtg4nHzw==",
       "license": "Apache-2.0",
       "dependencies": {
         "@types/node": "^18.11.18",
@@ -6801,14 +6715,27 @@
       "version": "5.26.5",
       "license": "MIT"
     },
+    "node_modules/optionator": {
+      "version": "0.9.4",
+      "license": "MIT",
+      "dependencies": {
+        "deep-is": "^0.1.3",
+        "fast-levenshtein": "^2.0.6",
+        "levn": "^0.4.1",
+        "prelude-ls": "^1.2.1",
+        "type-check": "^0.4.0",
+        "word-wrap": "^1.2.5"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
     "node_modules/ot-json0": {
       "version": "1.1.0",
       "license": "ISC"
     },
     "node_modules/p-cancelable": {
       "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
-      "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
       "license": "MIT",
       "engines": {
         "node": ">=8"
@@ -6816,17 +6743,39 @@
     },
     "node_modules/p-finally": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
-      "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
       "license": "MIT",
       "engines": {
         "node": ">=4"
       }
     },
+    "node_modules/p-limit": {
+      "version": "3.1.0",
+      "license": "MIT",
+      "dependencies": {
+        "yocto-queue": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "5.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "p-limit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/p-queue": {
       "version": "6.6.2",
-      "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
-      "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
       "license": "MIT",
       "dependencies": {
         "eventemitter3": "^4.0.4",
@@ -6841,8 +6790,6 @@
     },
     "node_modules/p-retry": {
       "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
-      "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
       "license": "MIT",
       "dependencies": {
         "@types/retry": "0.12.0",
@@ -6854,8 +6801,6 @@
     },
     "node_modules/p-timeout": {
       "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
-      "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
       "license": "MIT",
       "dependencies": {
         "p-finally": "^1.0.0"
@@ -6864,18 +6809,32 @@
         "node": ">=8"
       }
     },
+    "node_modules/parent-module": {
+      "version": "1.0.1",
+      "license": "MIT",
+      "dependencies": {
+        "callsites": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/parseurl": {
       "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
-      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.8"
       }
     },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/path-key": {
       "version": "3.1.1",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=8"
@@ -6883,8 +6842,6 @@
     },
     "node_modules/path-to-regexp": {
       "version": "8.2.0",
-      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
-      "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
       "license": "MIT",
       "engines": {
         "node": ">=16"
@@ -6892,15 +6849,11 @@
     },
     "node_modules/pathe": {
       "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
-      "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
       "dev": true,
       "license": "MIT"
     },
     "node_modules/pathval": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
-      "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -6909,8 +6862,6 @@
     },
     "node_modules/pend": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
-      "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
       "license": "MIT"
     },
     "node_modules/picocolors": {
@@ -6930,10 +6881,15 @@
         "url": "https://github.com/sponsors/jonschlinkert"
       }
     },
+    "node_modules/pkce-challenge": {
+      "version": "5.0.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">=16.20.0"
+      }
+    },
     "node_modules/postcss": {
       "version": "8.5.3",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
-      "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
       "dev": true,
       "funding": [
         {
@@ -6959,10 +6915,15 @@
         "node": "^10 || ^12 || >=14"
       }
     },
+    "node_modules/prelude-ls": {
+      "version": "1.2.1",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
     "node_modules/prettier": {
       "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
-      "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
       "license": "MIT",
       "bin": {
         "prettier": "bin/prettier.cjs"
@@ -7015,18 +6976,21 @@
     },
     "node_modules/pump": {
       "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
-      "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
       "license": "MIT",
       "dependencies": {
         "end-of-stream": "^1.1.0",
         "once": "^1.3.1"
       }
     },
+    "node_modules/punycode": {
+      "version": "2.3.1",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/qs": {
       "version": "6.14.0",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
-      "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
       "license": "BSD-3-Clause",
       "dependencies": {
         "side-channel": "^1.1.0"
@@ -7040,8 +7004,6 @@
     },
     "node_modules/quick-lru": {
       "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
-      "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
       "license": "MIT",
       "engines": {
         "node": ">=10"
@@ -7052,8 +7014,6 @@
     },
     "node_modules/range-parser": {
       "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
-      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.6"
@@ -7061,8 +7021,6 @@
     },
     "node_modules/raw-body": {
       "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
-      "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
       "license": "MIT",
       "dependencies": {
         "bytes": "3.1.2",
@@ -7142,8 +7100,6 @@
     },
     "node_modules/react-router": {
       "version": "7.5.0",
-      "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.5.0.tgz",
-      "integrity": "sha512-estOHrRlDMKdlQa6Mj32gIks4J+AxNsYoE0DbTTxiMy2mPzZuWSDU+N85/r1IlNR7kGfznF3VCUlvc5IUO+B9g==",
       "license": "MIT",
       "dependencies": {
         "@types/cookie": "^0.6.0",
@@ -7166,8 +7122,6 @@
     },
     "node_modules/react-router-dom": {
       "version": "7.5.0",
-      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.5.0.tgz",
-      "integrity": "sha512-fFhGFCULy4vIseTtH5PNcY/VvDJK5gvOWcwJVHQp8JQcWVr85ENhJ3UpuF/zP1tQOIFYNRJHzXtyhU1Bdgw0RA==",
       "license": "MIT",
       "dependencies": {
         "react-router": "7.5.0"
@@ -7182,8 +7136,6 @@
     },
     "node_modules/react-router/node_modules/cookie": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
-      "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
       "license": "MIT",
       "engines": {
         "node": ">=18"
@@ -7247,14 +7199,17 @@
     },
     "node_modules/resolve-alpn": {
       "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
-      "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
       "license": "MIT"
     },
+    "node_modules/resolve-from": {
+      "version": "4.0.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/responselike": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
-      "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
       "license": "MIT",
       "dependencies": {
         "lowercase-keys": "^2.0.0"
@@ -7265,8 +7220,6 @@
     },
     "node_modules/retry": {
       "version": "0.13.1",
-      "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
-      "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
       "license": "MIT",
       "engines": {
         "node": ">= 4"
@@ -7308,8 +7261,6 @@
     },
     "node_modules/router": {
       "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
-      "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
       "license": "MIT",
       "dependencies": {
         "debug": "^4.4.0",
@@ -7334,8 +7285,6 @@
     },
     "node_modules/rxjs": {
       "version": "7.8.2",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
-      "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
       "license": "Apache-2.0",
       "dependencies": {
         "tslib": "^2.1.0"
@@ -7343,8 +7292,6 @@
     },
     "node_modules/safe-buffer": {
       "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
       "funding": [
         {
           "type": "github",
@@ -7363,14 +7310,10 @@
     },
     "node_modules/safer-buffer": {
       "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
       "license": "MIT"
     },
     "node_modules/sass": {
       "version": "1.86.3",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.3.tgz",
-      "integrity": "sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -7397,15 +7340,11 @@
     },
     "node_modules/sdp": {
       "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.0.tgz",
-      "integrity": "sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==",
       "license": "MIT",
       "peer": true
     },
     "node_modules/sdp-transform": {
       "version": "2.15.0",
-      "resolved": "https://registry.npmjs.org/sdp-transform/-/sdp-transform-2.15.0.tgz",
-      "integrity": "sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw==",
       "license": "MIT",
       "peer": true,
       "bin": {
@@ -7422,8 +7361,6 @@
     },
     "node_modules/send": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
-      "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
       "license": "MIT",
       "dependencies": {
         "debug": "^4.3.5",
@@ -7444,8 +7381,6 @@
     },
     "node_modules/send/node_modules/mime-db": {
       "version": "1.54.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
-      "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.6"
@@ -7453,8 +7388,6 @@
     },
     "node_modules/send/node_modules/mime-types": {
       "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
-      "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
       "license": "MIT",
       "dependencies": {
         "mime-db": "^1.54.0"
@@ -7465,8 +7398,6 @@
     },
     "node_modules/serve-static": {
       "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
-      "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
       "license": "MIT",
       "dependencies": {
         "encodeurl": "^2.0.0",
@@ -7480,8 +7411,6 @@
     },
     "node_modules/set-cookie-parser": {
       "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
-      "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
       "license": "MIT"
     },
     "node_modules/set-function-length": {
@@ -7518,8 +7447,6 @@
     },
     "node_modules/sharedb": {
       "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/sharedb/-/sharedb-5.2.1.tgz",
-      "integrity": "sha512-CAZhU7Y9kR9LreuCkN9BIy9Y5u8e5suGTLSSFjXi6SiGhNuWPnVUZfZOKVnu03FYADs2lLhcj3vaa6kEcd2pxQ==",
       "license": "MIT",
       "dependencies": {
         "arraydiff": "^0.1.3",
@@ -7535,7 +7462,6 @@
     },
     "node_modules/shebang-command": {
       "version": "2.0.0",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "shebang-regex": "^3.0.0"
@@ -7546,7 +7472,6 @@
     },
     "node_modules/shebang-regex": {
       "version": "3.0.0",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=8"
@@ -7565,8 +7490,6 @@
     },
     "node_modules/side-channel": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
-      "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
       "license": "MIT",
       "dependencies": {
         "es-errors": "^1.3.0",
@@ -7584,8 +7507,6 @@
     },
     "node_modules/side-channel-list": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
-      "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
       "license": "MIT",
       "dependencies": {
         "es-errors": "^1.3.0",
@@ -7600,8 +7521,6 @@
     },
     "node_modules/side-channel-map": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
-      "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
       "license": "MIT",
       "dependencies": {
         "call-bound": "^1.0.2",
@@ -7618,8 +7537,6 @@
     },
     "node_modules/side-channel-weakmap": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
-      "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
       "license": "MIT",
       "dependencies": {
         "call-bound": "^1.0.2",
@@ -7642,8 +7559,6 @@
     },
     "node_modules/simple-wcswidth": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz",
-      "integrity": "sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg==",
       "license": "MIT"
     },
     "node_modules/source-map-js": {
@@ -7668,8 +7583,6 @@
     },
     "node_modules/std-env": {
       "version": "3.8.1",
-      "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz",
-      "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==",
       "dev": true,
       "license": "MIT"
     },
@@ -7697,6 +7610,16 @@
         "node": ">=8"
       }
     },
+    "node_modules/strip-json-comments": {
+      "version": "3.1.1",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/style-mod": {
       "version": "4.1.2",
       "license": "MIT"
@@ -7759,8 +7682,6 @@
     },
     "node_modules/tinyrainbow": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
-      "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -7769,8 +7690,6 @@
     },
     "node_modules/tinyspy": {
       "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz",
-      "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -7810,8 +7729,6 @@
     },
     "node_modules/ts-debounce": {
       "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/ts-debounce/-/ts-debounce-4.0.0.tgz",
-      "integrity": "sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==",
       "license": "MIT",
       "peer": true
     },
@@ -7821,14 +7738,20 @@
     },
     "node_modules/turbo-stream": {
       "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
-      "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
       "license": "ISC"
     },
+    "node_modules/type-check": {
+      "version": "0.4.0",
+      "license": "MIT",
+      "dependencies": {
+        "prelude-ls": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
     "node_modules/type-fest": {
       "version": "4.39.1",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.39.1.tgz",
-      "integrity": "sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==",
       "license": "(MIT OR CC0-1.0)",
       "engines": {
         "node": ">=16"
@@ -7839,8 +7762,6 @@
     },
     "node_modules/type-is": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
-      "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
       "license": "MIT",
       "dependencies": {
         "content-type": "^1.0.5",
@@ -7853,8 +7774,6 @@
     },
     "node_modules/type-is/node_modules/mime-db": {
       "version": "1.54.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
-      "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.6"
@@ -7862,8 +7781,6 @@
     },
     "node_modules/type-is/node_modules/mime-types": {
       "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
-      "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
       "license": "MIT",
       "dependencies": {
         "mime-db": "^1.54.0"
@@ -7874,8 +7791,6 @@
     },
     "node_modules/typed-emitter": {
       "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz",
-      "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==",
       "license": "MIT",
       "peer": true,
       "optionalDependencies": {
@@ -7884,8 +7799,6 @@
     },
     "node_modules/typescript": {
       "version": "5.8.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
-      "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
       "license": "Apache-2.0",
       "bin": {
         "tsc": "bin/tsc",
@@ -7914,8 +7827,6 @@
     },
     "node_modules/unpipe": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
       "license": "MIT",
       "engines": {
         "node": ">= 0.8"
@@ -7950,10 +7861,15 @@
         "browserslist": ">= 4.21.0"
       }
     },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
     "node_modules/usehooks-ts": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.1.1.tgz",
-      "integrity": "sha512-I4diPp9Cq6ieSUH2wu+fDAVQO43xwtulo+fKEidHUwZPnYImbtkTjzIJYcDcJqxgmX31GVqNFURodvcgHcW0pA==",
       "license": "MIT",
       "dependencies": {
         "lodash.debounce": "^4.0.8"
@@ -7967,8 +7883,6 @@
     },
     "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"
@@ -7987,8 +7901,6 @@
     },
     "node_modules/vite": {
       "version": "6.2.5",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz",
-      "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -8059,8 +7971,6 @@
     },
     "node_modules/vite-node": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz",
-      "integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -8096,8 +8006,6 @@
     },
     "node_modules/vite/node_modules/@rollup/rollup-win32-x64-msvc": {
       "version": "4.34.8",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz",
-      "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==",
       "cpu": [
         "x64"
       ],
@@ -8147,8 +8055,6 @@
     },
     "node_modules/vitest": {
       "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz",
-      "integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -8243,8 +8149,6 @@
     },
     "node_modules/webrtc-adapter": {
       "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-9.0.1.tgz",
-      "integrity": "sha512-1AQO+d4ElfVSXyzNVTOewgGT/tAomwwztX/6e3totvyyzXPvXIIuUUjAmyZGbKBKbZOXauuJooZm3g6IuFuiNQ==",
       "license": "BSD-3-Clause",
       "peer": true,
       "dependencies": {
@@ -8265,7 +8169,6 @@
     },
     "node_modules/which": {
       "version": "2.0.2",
-      "dev": true,
       "license": "ISC",
       "dependencies": {
         "isexe": "^2.0.0"
@@ -8292,6 +8195,13 @@
         "node": ">=8"
       }
     },
+    "node_modules/word-wrap": {
+      "version": "1.2.5",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/wrap-ansi": {
       "version": "7.0.0",
       "dev": true,
@@ -8310,14 +8220,10 @@
     },
     "node_modules/wrappy": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
       "license": "ISC"
     },
     "node_modules/ws": {
       "version": "8.18.1",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
-      "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
       "license": "MIT",
       "engines": {
         "node": ">=10.0.0"
@@ -8385,14 +8291,22 @@
     },
     "node_modules/yauzl": {
       "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
-      "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
       "license": "MIT",
       "dependencies": {
         "buffer-crc32": "~0.2.3",
         "fd-slicer": "~1.1.0"
       }
     },
+    "node_modules/yocto-queue": {
+      "version": "0.1.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/zimmerframe": {
       "version": "1.1.2",
       "license": "MIT",
@@ -8400,8 +8314,6 @@
     },
     "node_modules/zod": {
       "version": "3.24.2",
-      "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz",
-      "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==",
       "license": "MIT",
       "funding": {
         "url": "https://github.com/sponsors/colinhacks"
@@ -8409,8 +8321,6 @@
     },
     "node_modules/zod-to-json-schema": {
       "version": "3.24.3",
-      "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.3.tgz",
-      "integrity": "sha512-HIAfWdYIt1sssHfYZFCXp4rU1w2r8hVVXYIlmoa0r0gABLs5di3RCqPU5DDROogVz1pAdYBaz7HK5n9pSUNs3A==",
       "license": "ISC",
       "peerDependencies": {
         "zod": "^3.24.1"
diff --git a/package.json b/package.json
index cae63bf9..0f38329f 100644
--- a/package.json
+++ b/package.json
@@ -110,6 +110,7 @@
     "@codemirror/lang-javascript": "^6.2.3",
     "@codemirror/lang-json": "^6.0.1",
     "@codemirror/lang-markdown": "^6.3.2",
+    "@codemirror/lint": "^6.8.5",
     "@codemirror/state": "^6.5.2",
     "@codemirror/theme-one-dark": "^6.1.2",
     "@codemirror/view": "^6.36.5",
@@ -140,7 +141,10 @@
     "d3-array": "^3.2.4",
     "diff-match-patch": "^1.0.5",
     "dotenv": "^16.4.7",
+    "eslint": "^9.26.0",
+    "eslint-linter-browserify": "^9.26.0",
     "express": "^5.1.0",
+    "globals": "^16.1.0",
     "ignore": "^7.0.3",
     "json0-ot-diff": "^1.1.2",
     "livekit-server-sdk": "^2.11.0",
diff --git a/src/client/App/index.tsx b/src/client/App/index.tsx
index 62958b71..61923fd3 100644
--- a/src/client/App/index.tsx
+++ b/src/client/App/index.tsx
@@ -25,6 +25,7 @@ import {
 } from '../usernameLocalStorage';
 import './style.scss';
 import { useShareDB } from './useShareDB';
+import { useESLint } from '../useESLint';
 
 // Instantiate the Prettier worker.
 const prettierWorker = new PrettierWorker();
@@ -75,6 +76,7 @@ function App() {
     useState(v4()); //default room name will be an arbitrary uuid
   const [liveKitConnection, setLiveKitConnection] =
     useState(false);
+  const { esLintSource } = useESLint();
   // Get the initial username from localStorage.
   const initialUsername: Username = useInitialUsername();
 
@@ -129,6 +131,7 @@ function App() {
               aiCopilotEndpoint={
                 enableCopilot ? '/ai-copilot' : null
               }
+              esLintSource={esLintSource}
             />
             {enableRightPanel ? <VZRight /> : null}
             <VZResizer side="left" />
diff --git a/src/client/CodeEditor/getOrCreateEditor.ts b/src/client/CodeEditor/getOrCreateEditor.ts
index b420b197..0261cdac 100644
--- a/src/client/CodeEditor/getOrCreateEditor.ts
+++ b/src/client/CodeEditor/getOrCreateEditor.ts
@@ -2,6 +2,7 @@ import { EditorView } from 'codemirror';
 import {
   Compartment,
   EditorState,
+  StateField,
 } from '@codemirror/state';
 import { javascript } from '@codemirror/lang-javascript';
 import { svelte } from '@replit/codemirror-lang-svelte';
@@ -15,7 +16,11 @@ import { autocompletion } from '@codemirror/autocomplete';
 import { indentationMarkers } from '@replit/codemirror-indentation-markers';
 // import { showMinimap } from '@replit/codemirror-minimap';
 import { vscodeKeymap } from '@replit/codemirror-vscode-keymap';
-import { Diagnostic, linter } from '@codemirror/lint';
+import {
+  Diagnostic,
+  linter,
+  lintGutter,
+} from '@codemirror/lint';
 
 import { json1Presence, textUnicode } from '../../ot';
 import {
@@ -48,6 +53,15 @@ import { copilot } from './Copilot';
 
 const DEBUG = false;
 
+// Define a StateField to store the file name.
+// This should be defined at the module level if it's to be imported by other modules.
+export const fileNameStateField = StateField.define<string>(
+  {
+    create: () => '', // Default initial value
+    update: (value, tr) => value, // Typically set once at creation for a given editor instance
+  },
+);
+
 // Enables TypeScript +JSX support in CodeMirror.
 const tsx = () =>
   javascript({ jsx: true, typescript: true });
@@ -126,6 +140,7 @@ export const getOrCreateEditor = ({
   enableAutoFollowRef,
   openTab,
   aiCopilotEndpoint,
+  esLintSource,
   rainbowBracketsEnabled = true,
 }: {
   // TODO pass this in from the outside
@@ -162,6 +177,9 @@ export const getOrCreateEditor = ({
   enableAutoFollowRef: React.MutableRefObject<boolean>;
   openTab: (tabState: TabState) => void;
   aiCopilotEndpoint?: string;
+  esLintSource: (
+    view: EditorView,
+  ) => Promise<readonly Diagnostic[]>;
   rainbowBracketsEnabled?: boolean; // New parameter type
 }): ExtendedEditorCacheValue => {
   // Cache hit
@@ -194,6 +212,9 @@ export const getOrCreateEditor = ({
   // const extensions = [autocompletion(), html(htmlConfig)]
   const extensions = [];
 
+  // Initialize the fileNameStateField with the actual file name
+  extensions.push(fileNameStateField.init(() => name));
+
   // This plugin implements multiplayer editing,
   // real-time synchronozation of changes across clients.
   // Does not deal with showing others' cursors.
@@ -244,6 +265,16 @@ export const getOrCreateEditor = ({
   // https://github.com/vizhub-core/vzcode/issues/134
   extensions.push(basicSetup);
 
+  if (esLintSource) {
+    extensions.push(lintGutter()); // Show lint icons in the gutter
+    extensions.push(
+      linter(esLintSource, {
+        // You can configure linter options here, e.g., delay
+        delay: 750,
+      }),
+    );
+  }
+
   // This supports dynamic changing of the theme.
   extensions.push(
     themeCompartment.of(themeOptionsByLabel[theme].value),
diff --git a/src/client/CodeEditor/index.tsx b/src/client/CodeEditor/index.tsx
index 2c2d9a0a..7269493f 100644
--- a/src/client/CodeEditor/index.tsx
+++ b/src/client/CodeEditor/index.tsx
@@ -12,6 +12,8 @@ import { getOrCreateEditor } from './getOrCreateEditor';
 import { VZCodeContext } from '../VZCodeContext';
 import { InteractRule } from '@replit/codemirror-interact';
 import './style.scss';
+import { EditorView } from 'codemirror'; // Import EditorView
+import { Diagnostic } from '@codemirror/lint'; // Import Diagnostic
 
 // The path in the ShareDB document where the files live.
 const filesPath = ['files'];
@@ -19,9 +21,13 @@ const filesPath = ['files'];
 export const CodeEditor = ({
   customInteractRules,
   aiCopilotEndpoint,
+  esLintSource,
 }: {
   customInteractRules?: Array<InteractRule>;
   aiCopilotEndpoint?: string;
+  esLintSource: (
+    view: EditorView,
+  ) => Promise<readonly Diagnostic[]>;
 }) => {
   const {
     activePane,
@@ -97,6 +103,7 @@ export const CodeEditor = ({
         enableAutoFollowRef,
         openTab,
         aiCopilotEndpoint,
+        esLintSource,
       }),
     [
       activePane,
@@ -109,6 +116,7 @@ export const CodeEditor = ({
       editorCache,
       usernameRef,
       aiCopilotEndpoint,
+      esLintSource,
     ],
   );
 
diff --git a/src/client/VZMiddle.tsx b/src/client/VZMiddle.tsx
index 399cfd5c..c987a2a8 100644
--- a/src/client/VZMiddle.tsx
+++ b/src/client/VZMiddle.tsx
@@ -8,6 +8,10 @@ import { AIAssistWidget } from './AIAssist/AIAssistWidget';
 import { VZCodeContext } from './VZCodeContext';
 import { RunCodeWidget } from './RunCodeWidget';
 import { InteractRule } from '@replit/codemirror-interact';
+import { EditorView } from '@codemirror/view';
+import { Diagnostic } from '@codemirror/lint';
+import { VizContent } from '@vizhub/viz-types';
+import { LeafPane } from '../types';
 
 // TODO modify this to handle the SplitPane type
 // Recursive structure?
@@ -23,6 +27,7 @@ const PaneView = ({
   aiAssistTooltipText,
   aiAssistClickOverride,
   aiCopilotEndpoint,
+  esLintSource,
 }) => {
   // This prevents the CodeEditor from rendering
   // during SSR.
@@ -49,6 +54,7 @@ const PaneView = ({
         <CodeEditor
           customInteractRules={customInteractRules}
           aiCopilotEndpoint={aiCopilotEndpoint}
+          esLintSource={esLintSource}
         />
       )}
       {isClient &&
@@ -84,6 +90,7 @@ export const VZMiddle = ({
   aiAssistClickOverride,
   aiCopilotEndpoint,
   customInteractRules,
+  esLintSource,
 }: {
   enableAIAssist?: boolean;
   aiAssistEndpoint?: string;
@@ -92,6 +99,9 @@ export const VZMiddle = ({
   aiAssistClickOverride?: () => void;
   aiCopilotEndpoint?: string;
   customInteractRules?: Array<InteractRule>;
+  esLintSource: (
+    view: EditorView,
+  ) => Promise<readonly Diagnostic[]>;
 }) => {
   const { codeEditorWidth } = useContext(
     SplitPaneResizeContext,
@@ -128,6 +138,7 @@ export const VZMiddle = ({
         aiAssistTooltipText={aiAssistTooltipText}
         aiAssistClickOverride={aiAssistClickOverride}
         aiCopilotEndpoint={aiCopilotEndpoint}
+        esLintSource={esLintSource}
       />
       <CodeErrorOverlay
         errorMessage={errorMessage}
diff --git a/src/client/useESLint/index.ts b/src/client/useESLint/index.ts
new file mode 100644
index 00000000..bde66cc8
--- /dev/null
+++ b/src/client/useESLint/index.ts
@@ -0,0 +1,69 @@
+import { useState, useEffect, useCallback } from 'react';
+import { EditorView } from '@codemirror/view';
+import { Diagnostic } from '@codemirror/lint';
+// @ts-ignore - Worker import
+import ESLintWorker from './worker?worker';
+import { enableESLint } from '../../server/featureFlags';
+import { fileNameStateField } from '../CodeEditor/getOrCreateEditor';
+
+let requestCounter = 0;
+const pendingRequests = new Map();
+
+export const useESLint = () => {
+  const [worker, setWorker] = useState(null);
+  
+  // Initialize the work in an effect so it does not run during SSR.
+  useEffect(() => {
+    setWorker(new ESLintWorker());
+  }, []);
+
+  useEffect(() => {
+    const handleMessage = (event) => {
+      const { diagnostics, requestId, error } = event.data;
+
+      if (error) {
+        console.error('[ESLint] Error:', error);
+      }
+
+      const resolve = pendingRequests.get(requestId);
+      if (resolve) {
+        resolve(diagnostics);
+        pendingRequests.delete(requestId);
+      }
+    };
+
+    worker.addEventListener('message', handleMessage);
+
+    return () => {
+      worker.removeEventListener('message', handleMessage);
+      worker.terminate();
+    };
+  }, [worker]);
+
+  const esLintSource = useCallback(
+    async (
+      view: EditorView,
+    ): Promise<readonly Diagnostic[]> => {
+      if (!enableESLint) return [];
+
+      // Retrieve the file name from the editor's state
+      const fileName = view.state.field(fileNameStateField);
+
+      try {
+        const code = view.state.doc.toString();
+        const requestId = requestCounter++;
+
+        return new Promise<Diagnostic[]>((resolve) => {
+          pendingRequests.set(requestId, resolve);
+          worker.postMessage({ code, requestId, fileName });
+        });
+      } catch (e) {
+        console.error('[ESLint] Error in linter:', e);
+        return [];
+      }
+    },
+    [worker],
+  );
+
+  return { esLintSource };
+};
diff --git a/src/client/useESLint/worker.ts b/src/client/useESLint/worker.ts
new file mode 100644
index 00000000..6560cfe1
--- /dev/null
+++ b/src/client/useESLint/worker.ts
@@ -0,0 +1,99 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
+
+const linter = new eslint.Linter();
+
+const config = {
+  languageOptions: {
+    globals: {
+      ...globals.browser, 
+      ...globals.es2021,
+    },
+    parserOptions: {
+      ecmaVersion: 2022, 
+      sourceType: 'module',
+      ecmaFeatures: {
+        // Add this to enable JSX parsing
+        jsx: true,
+      },
+    },
+  },
+  rules: {
+    'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
+    'no-undef': 'error',
+    semi: 'off',
+  },
+};
+
+// Helper function to convert line/column to character offset
+function getOffset(
+  docLines: string[],
+  line: number,
+  column: number,
+): number {
+  let offset = 0;
+  for (let i = 0; i < line - 1; i++) {
+    offset += (docLines[i] ? docLines[i].length : 0) + 1; // +1 for newline
+  }
+  return offset + column - 1;
+}
+
+self.onmessage = (event) => {
+  const { code, requestId, fileName } = event.data;
+  if (typeof code !== 'string') {
+    self.postMessage({
+      diagnostics: [],
+      requestId,
+      error: 'Invalid code received',
+    });
+    return;
+  }
+
+  // Only lint .js or .jsx files
+  if (!fileName || !/\.(js|jsx)$/i.test(fileName)) {
+    self.postMessage({ diagnostics: [], requestId });
+    return;
+  }
+
+  try {
+    const messages = linter.verify(code, config as any);
+    const docLines = code.split('\n');
+
+    const diagnostics = messages.map((msg) => {
+      const from = getOffset(
+        docLines,
+        msg.line,
+        msg.column,
+      );
+      // endLine and endColumn may not always exist
+      const to =
+        msg.endLine && msg.endColumn
+          ? getOffset(docLines, msg.endLine, msg.endColumn)
+          : from +
+            (msg.fix?.range[1] - msg.fix?.range[0] || 1);
+
+      return {
+        from,
+        to,
+        severity:
+          msg.severity === 2
+            ? 'error'
+            : msg.severity === 1
+              ? 'warning'
+              : 'info',
+        message: msg.message,
+        source: msg.ruleId
+          ? `eslint(${msg.ruleId})`
+          : 'eslint',
+      };
+    });
+    self.postMessage({ diagnostics, requestId });
+  } catch (e: any) {
+    console.error('Error linting in ESLint worker:', e);
+    self.postMessage({
+      error: e.message,
+      diagnostics: [],
+      requestId,
+    });
+  }
+};
diff --git a/src/server/featureFlags.js b/src/server/featureFlags.js
index e27ae882..ce8022ff 100644
--- a/src/server/featureFlags.js
+++ b/src/server/featureFlags.js
@@ -4,3 +4,5 @@ export const enableDirectories = true;
 export const debugDirectories = false;
 
 export const debugIgnore = false;
+
+export const enableESLint = true;


Reviews:
user: login: curran
body: This is amazing! Thank you so much for this contribution.

I left some comments inline.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T15:22:57Z
user: login: fantong11
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T09:46:23Z
user: login: fantong11
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T09:47:54Z
user: login: fantong11
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T09:48:53Z
user: login: fantong11
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T09:50:44Z
user: login: fantong11
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T09:51:06Z
user: login: fantong11
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T09:54:20Z
user: login: fantong11
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T10:54:55Z
user: login: curran
body: LGTM! Thank you so much.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T16:16:51Z

Review comments:
diff_hunk: @@ -156,6 +159,7 @@
     "sharedb-client-browser": "^5.1.1",
     "uuid": "^11.1.0",
     "vizhub-ui": "^3.23.0",
+    "vzcode": "file:",
path: package.json
user: login: curran
body: Not sure about this change here. What is the purpose of this? Perhaps let's revert this if it's not needed.
```suggestion
```
created_at: 2025-05-12T14:54:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -172,7 +176,6 @@
     "vitest": "^3.1.1"
   },
   "optionalDependencies": {
-    "@rollup/rollup-darwin-arm64": "^4.39.0",
-    "@rollup/rollup-win32-x64-msvc": "^4.39.0"
path: package.json
user: login: curran
body: This is here so that people using various operating systems can develop on VZCode. Was this optional dependency causing issues for you? I would prefer to keep this as it was, so folks on Windows don't need to struggle with the dependencies.

created_at: 2025-05-12T14:55:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -172,7 +176,6 @@
     "vitest": "^3.1.1"
   },
   "optionalDependencies": {
-    "@rollup/rollup-darwin-arm64": "^4.39.0",
-    "@rollup/rollup-win32-x64-msvc": "^4.39.0"
+    "@rollup/rollup-darwin-arm64": "^4.39.0"
path: package.json
user: login: curran
body: ```suggestion
    "@rollup/rollup-darwin-arm64": "^4.39.0",
    "@rollup/rollup-win32-x64-msvc": "^4.39.0"
```
created_at: 2025-05-12T14:56:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
path: src/client/useESLint/worker.ts
user: login: curran
body: We might need an `npm install -S globals`, I don't think this is in the `package.json` dependencies.
created_at: 2025-05-12T15:04:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
+
+const linter = new eslint.Linter();
+
+// Helper function to trim keys of an object
+function trimGlobalKeys(
+  obj: Record<string, unknown>,
+): Record<string, unknown> {
+  if (!obj || typeof obj !== 'object') {
+    return obj;
+  }
+  const newObj: Record<string, unknown> = {};
+  for (const key in obj) {
+    if (Object.prototype.hasOwnProperty.call(obj, key)) {
+      newObj[key.trim()] = obj[key];
+    }
+  }
+  return newObj;
+}
+
+// Define the configuration without explicit types that don't exist
+const config = {
+  languageOptions: {
+    globals: {
+      ...trimGlobalKeys(globals.browser), // Apply trimming to browser globals
+      ...globals.es2021, // Assuming es2021 globals are fine, or trim them too if needed
+    },
+    parserOptions: {
+      ecmaVersion: 2022, // Use number instead of enum type
+      sourceType: 'module',
+      ecmaFeatures: {
+        // Add this to enable JSX parsing
+        jsx: true,
+      },
+    },
+  },
+  rules: {
+    'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
+    'no-undef': 'error',
+    semi: 'off',
+  },
+};
+
+// Helper function to convert line/column to character offset
+function getOffset(
+  docLines: string[],
+  line: number,
+  column: number,
+): number {
+  let offset = 0;
+  for (let i = 0; i < line - 1; i++) {
+    offset += (docLines[i] ? docLines[i].length : 0) + 1; // +1 for newline
+  }
+  return offset + column - 1;
+}
+
+self.onmessage = (event) => {
+  const { code, requestId, fileName } = event.data;
+  if (typeof code !== 'string') {
+    self.postMessage({
+      diagnostics: [],
+      requestId,
+      error: 'Invalid code received',
+    });
+    return;
+  }
+
+  // Only lint .js or .jsx files
+  if (!fileName || !/\.(js|jsx)$/i.test(fileName)) {
path: src/client/useESLint/worker.ts
user: login: curran
body: Aha! So this is why the `fileName` is needed. I wonder if we could move this test to be outside of the Worker, where we just don't send the message at all if we are not in .js or .jsx files.
created_at: 2025-05-12T15:08:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
+
+const linter = new eslint.Linter();
+
+// Helper function to trim keys of an object
+function trimGlobalKeys(
+  obj: Record<string, unknown>,
+): Record<string, unknown> {
+  if (!obj || typeof obj !== 'object') {
+    return obj;
+  }
+  const newObj: Record<string, unknown> = {};
+  for (const key in obj) {
+    if (Object.prototype.hasOwnProperty.call(obj, key)) {
+      newObj[key.trim()] = obj[key];
+    }
+  }
+  return newObj;
+}
+
+// Define the configuration without explicit types that don't exist
+const config = {
+  languageOptions: {
+    globals: {
+      ...trimGlobalKeys(globals.browser), // Apply trimming to browser globals
+      ...globals.es2021, // Assuming es2021 globals are fine, or trim them too if needed
+    },
+    parserOptions: {
+      ecmaVersion: 2022, // Use number instead of enum type
+      sourceType: 'module',
+      ecmaFeatures: {
+        // Add this to enable JSX parsing
+        jsx: true,
+      },
+    },
+  },
+  rules: {
+    'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
+    'no-undef': 'error',
+    semi: 'off',
+  },
+};
+
+// Helper function to convert line/column to character offset
+function getOffset(
+  docLines: string[],
+  line: number,
+  column: number,
+): number {
+  let offset = 0;
+  for (let i = 0; i < line - 1; i++) {
+    offset += (docLines[i] ? docLines[i].length : 0) + 1; // +1 for newline
+  }
+  return offset + column - 1;
+}
+
+self.onmessage = (event) => {
+  const { code, requestId, fileName } = event.data;
+  if (typeof code !== 'string') {
+    self.postMessage({
+      diagnostics: [],
+      requestId,
+      error: 'Invalid code received',
+    });
+    return;
+  }
+
+  // Only lint .js or .jsx files
+  if (!fileName || !/\.(js|jsx)$/i.test(fileName)) {
+    self.postMessage({ diagnostics: [], requestId });
+    return;
+  }
+
+  try {
+    // Use as any to bypass type checking for the config if necessary,
+    // but the config should be valid after trimming keys.
+    const messages = linter.verify(code, config as any, {
+      filename: 'file.js',
path: src/client/useESLint/worker.ts
user: login: curran
body: We could potentially pass the correct file name in here. I'm not sure where that is surfaced later, but might be a good idea in case this file name is used in the UI or messages.
created_at: 2025-05-12T15:09:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
+
+const linter = new eslint.Linter();
+
+// Helper function to trim keys of an object
+function trimGlobalKeys(
path: src/client/useESLint/worker.ts
user: login: curran
body: Why is this needed?

I don't see any keys here that have leading or trailing white space:

https://github.com/sindresorhus/globals/blob/main/globals.json

I would suggest to remove this logic if there's no clear reason to have it.
created_at: 2025-05-12T15:13:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
+
+const linter = new eslint.Linter();
+
+// Helper function to trim keys of an object
+function trimGlobalKeys(
+  obj: Record<string, unknown>,
+): Record<string, unknown> {
+  if (!obj || typeof obj !== 'object') {
+    return obj;
+  }
+  const newObj: Record<string, unknown> = {};
+  for (const key in obj) {
+    if (Object.prototype.hasOwnProperty.call(obj, key)) {
+      newObj[key.trim()] = obj[key];
+    }
+  }
+  return newObj;
+}
+
+// Define the configuration without explicit types that don't exist
+const config = {
+  languageOptions: {
+    globals: {
+      ...trimGlobalKeys(globals.browser), // Apply trimming to browser globals
path: src/client/useESLint/worker.ts
user: login: curran
body: ```suggestion
      ...globals.browser
```
created_at: 2025-05-12T15:14:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,64 @@
+import { useState, useEffect, useCallback } from 'react';
+import { EditorView } from '@codemirror/view';
+import { Diagnostic } from '@codemirror/lint';
+// @ts-ignore - Worker import
+import ESLintWorker from './worker?worker';
+import { enableESLint } from '../../server/featureFlags';
+import { fileNameStateField } from '../CodeEditor/getOrCreateEditor';
+
+let requestCounter = 0;
+const pendingRequests = new Map();
+
+export const useESLint = () => {
+  const [worker] = useState(() => new ESLintWorker());
path: src/client/useESLint/index.ts
user: login: curran
body: Nice pattern! I have never seen this before.
created_at: 2025-05-12T15:16:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
+
+const linter = new eslint.Linter();
+
+// Helper function to trim keys of an object
+function trimGlobalKeys(
+  obj: Record<string, unknown>,
+): Record<string, unknown> {
+  if (!obj || typeof obj !== 'object') {
+    return obj;
+  }
+  const newObj: Record<string, unknown> = {};
+  for (const key in obj) {
+    if (Object.prototype.hasOwnProperty.call(obj, key)) {
+      newObj[key.trim()] = obj[key];
+    }
+  }
+  return newObj;
+}
+
+// Define the configuration without explicit types that don't exist
+const config = {
+  languageOptions: {
+    globals: {
+      ...trimGlobalKeys(globals.browser), // Apply trimming to browser globals
+      ...globals.es2021, // Assuming es2021 globals are fine, or trim them too if needed
+    },
+    parserOptions: {
+      ecmaVersion: 2022, // Use number instead of enum type
+      sourceType: 'module',
+      ecmaFeatures: {
+        // Add this to enable JSX parsing
+        jsx: true,
+      },
+    },
+  },
+  rules: {
+    'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
+    'no-undef': 'error',
+    semi: 'off',
+  },
+};
+
+// Helper function to convert line/column to character offset
+function getOffset(
path: src/client/useESLint/worker.ts
user: login: curran
body: I'm a bit confused on why this logic is needed, because in the original example here

https://github.com/UziTech/eslint-linter-browserify/blob/master/example/script.js

there is no additional logic for conversions like this. I'm curious, is this logic coming from some other reference example you are looking at as an example?
created_at: 2025-05-12T15:20:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
+
+const linter = new eslint.Linter();
+
+// Helper function to trim keys of an object
+function trimGlobalKeys(
+  obj: Record<string, unknown>,
+): Record<string, unknown> {
+  if (!obj || typeof obj !== 'object') {
+    return obj;
+  }
+  const newObj: Record<string, unknown> = {};
+  for (const key in obj) {
+    if (Object.prototype.hasOwnProperty.call(obj, key)) {
+      newObj[key.trim()] = obj[key];
+    }
+  }
+  return newObj;
+}
+
+// Define the configuration without explicit types that don't exist
+const config = {
+  languageOptions: {
+    globals: {
+      ...trimGlobalKeys(globals.browser), // Apply trimming to browser globals
+      ...globals.es2021, // Assuming es2021 globals are fine, or trim them too if needed
+    },
+    parserOptions: {
+      ecmaVersion: 2022, // Use number instead of enum type
+      sourceType: 'module',
+      ecmaFeatures: {
+        // Add this to enable JSX parsing
+        jsx: true,
+      },
+    },
+  },
+  rules: {
+    'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
+    'no-undef': 'error',
+    semi: 'off',
+  },
+};
+
+// Helper function to convert line/column to character offset
+function getOffset(
path: src/client/useESLint/worker.ts
user: login: fantong11
body: ESLint only gives you "line + column" instead of a "string position", so I used a offset function to handle

https://codemirror.net/examples/lint/
created_at: 2025-05-17T09:46:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -156,6 +159,7 @@
     "sharedb-client-browser": "^5.1.1",
     "uuid": "^11.1.0",
     "vizhub-ui": "^3.23.0",
+    "vzcode": "file:",
path: package.json
user: login: fantong11
body: My vscode extension settings have some problem, it automatically add the dependencies.
created_at: 2025-05-17T09:47:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -172,7 +176,6 @@
     "vitest": "^3.1.1"
   },
   "optionalDependencies": {
-    "@rollup/rollup-darwin-arm64": "^4.39.0",
-    "@rollup/rollup-win32-x64-msvc": "^4.39.0"
path: package.json
user: login: fantong11
body: vscode extension settings issue, too.
created_at: 2025-05-17T09:48:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -172,7 +176,6 @@
     "vitest": "^3.1.1"
   },
   "optionalDependencies": {
-    "@rollup/rollup-darwin-arm64": "^4.39.0",
-    "@rollup/rollup-win32-x64-msvc": "^4.39.0"
+    "@rollup/rollup-darwin-arm64": "^4.39.0"
path: package.json
user: login: fantong11
body: vscode extension settings issue.
created_at: 2025-05-17T09:50:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
path: src/client/useESLint/worker.ts
user: login: fantong11
body: Added
created_at: 2025-05-17T09:51:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
+
+const linter = new eslint.Linter();
+
+// Helper function to trim keys of an object
+function trimGlobalKeys(
path: src/client/useESLint/worker.ts
user: login: fantong11
body: I will remove this logic.
This piece of code was accidentally added because I was using AI. 
I thought this code is necessary.
created_at: 2025-05-17T09:54:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,120 @@
+import * as eslint from 'eslint-linter-browserify';
+import globals from 'globals';
+
+const linter = new eslint.Linter();
+
+// Helper function to trim keys of an object
+function trimGlobalKeys(
+  obj: Record<string, unknown>,
+): Record<string, unknown> {
+  if (!obj || typeof obj !== 'object') {
+    return obj;
+  }
+  const newObj: Record<string, unknown> = {};
+  for (const key in obj) {
+    if (Object.prototype.hasOwnProperty.call(obj, key)) {
+      newObj[key.trim()] = obj[key];
+    }
+  }
+  return newObj;
+}
+
+// Define the configuration without explicit types that don't exist
+const config = {
+  languageOptions: {
+    globals: {
+      ...trimGlobalKeys(globals.browser), // Apply trimming to browser globals
+      ...globals.es2021, // Assuming es2021 globals are fine, or trim them too if needed
+    },
+    parserOptions: {
+      ecmaVersion: 2022, // Use number instead of enum type
+      sourceType: 'module',
+      ecmaFeatures: {
+        // Add this to enable JSX parsing
+        jsx: true,
+      },
+    },
+  },
+  rules: {
+    'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
+    'no-undef': 'error',
+    semi: 'off',
+  },
+};
+
+// Helper function to convert line/column to character offset
+function getOffset(
+  docLines: string[],
+  line: number,
+  column: number,
+): number {
+  let offset = 0;
+  for (let i = 0; i < line - 1; i++) {
+    offset += (docLines[i] ? docLines[i].length : 0) + 1; // +1 for newline
+  }
+  return offset + column - 1;
+}
+
+self.onmessage = (event) => {
+  const { code, requestId, fileName } = event.data;
+  if (typeof code !== 'string') {
+    self.postMessage({
+      diagnostics: [],
+      requestId,
+      error: 'Invalid code received',
+    });
+    return;
+  }
+
+  // Only lint .js or .jsx files
+  if (!fileName || !/\.(js|jsx)$/i.test(fileName)) {
+    self.postMessage({ diagnostics: [], requestId });
+    return;
+  }
+
+  try {
+    // Use as any to bypass type checking for the config if necessary,
+    // but the config should be valid after trimming keys.
+    const messages = linter.verify(code, config as any, {
+      filename: 'file.js',
path: src/client/useESLint/worker.ts
user: login: fantong11
body: This option is not necessary, I will remove.
created_at: 2025-05-17T10:54:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,64 @@
+import { useState, useEffect, useCallback } from 'react';
+import { EditorView } from '@codemirror/view';
+import { Diagnostic } from '@codemirror/lint';
+// @ts-ignore - Worker import
+import ESLintWorker from './worker?worker';
+import { enableESLint } from '../../server/featureFlags';
+import { fileNameStateField } from '../CodeEditor/getOrCreateEditor';
+
+let requestCounter = 0;
+const pendingRequests = new Map();
+
+export const useESLint = () => {
+  const [worker] = useState(() => new ESLintWorker());
path: src/client/useESLint/index.ts
user: login: curran
body: This implementation is problematic for server-side rendering, which is happening in the VizHub app but not in the VZCode development example app (so it works fine there).

```suggestion
  const [worker, setWorker] = useState(null);
  
  // Initialize the work in an effect so it does not run during SSR.
  useEffect(() => {
    setWorker(new ESLintWorker());
  }, []);
```
created_at: 2025-05-19T15:55:30Z
author_association: CONTRIBUTOR

PR comments:
user: login: curran
created_at: 2025-05-14T17:24:47Z
body: Maybe have a quick look @Darmin-Geek . Thanks!
author_association: CONTRIBUTOR
user: login: fantong11
created_at: 2025-05-17T10:13:49Z
body: I’ve made some minor fixes to the code you thought was problematic.
author_association: CONTRIBUTOR