From 9c65d94aca28d7da644a8aa66cfffc169bf5e3a1 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Fri, 3 Apr 2026 17:01:20 -0400 Subject: [PATCH 01/21] feat(vscode-moss): phase 1 extension host spike --- .gitignore | 4 +- .vscode/launch.json | 17 + .vscode/tasks.json | 29 + packages/vscode-moss/.gitignore | 3 + packages/vscode-moss/.vscode/launch.json | 17 + packages/vscode-moss/.vscode/tasks.json | 24 + packages/vscode-moss/.vscodeignore | 9 + packages/vscode-moss/LICENSE | 25 + packages/vscode-moss/PHASE1_SPIKE.md | 20 + packages/vscode-moss/README.md | 47 + packages/vscode-moss/package-lock.json | 4975 ++++++++++++++++++++++ packages/vscode-moss/package.json | 63 + packages/vscode-moss/src/extension.ts | 162 + packages/vscode-moss/tsconfig.json | 15 + 14 files changed, 5409 insertions(+), 1 deletion(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 packages/vscode-moss/.gitignore create mode 100644 packages/vscode-moss/.vscode/launch.json create mode 100644 packages/vscode-moss/.vscode/tasks.json create mode 100644 packages/vscode-moss/.vscodeignore create mode 100644 packages/vscode-moss/LICENSE create mode 100644 packages/vscode-moss/PHASE1_SPIKE.md create mode 100644 packages/vscode-moss/README.md create mode 100644 packages/vscode-moss/package-lock.json create mode 100644 packages/vscode-moss/package.json create mode 100644 packages/vscode-moss/src/extension.ts create mode 100644 packages/vscode-moss/tsconfig.json diff --git a/.gitignore b/.gitignore index 1350413a..01efc853 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,6 @@ venv/ *CLAUDE.md *.egg-info -.moss-cache \ No newline at end of file +.moss-cache + +.docs/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..edc6ef64 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "vscode-moss: Run Extension", + "type": "extensionHost", + "request": "launch", + "args": ["--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-moss"], + "outFiles": ["${workspaceFolder}/packages/vscode-moss/out/**/*.js"], + "preLaunchTask": "vscode-moss: watch", + "env": { + "MOSS_PROJECT_ID": "0254fba9-3a96-4914-ac00-943f7893035c", + "MOSS_PROJECT_KEY": "moss_UxG3voqCV632Auc8kU7RSUrUb0ppJxfg" + } + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..176ccd5d --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,29 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "vscode-moss: watch", + "type": "npm", + "script": "watch", + "options": { + "cwd": "${workspaceFolder}/packages/vscode-moss" + }, + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "silent" + }, + "group": "build" + }, + { + "label": "vscode-moss: compile", + "type": "npm", + "script": "compile", + "options": { + "cwd": "${workspaceFolder}/packages/vscode-moss" + }, + "problemMatcher": "$tsc", + "group": "build" + } + ] +} diff --git a/packages/vscode-moss/.gitignore b/packages/vscode-moss/.gitignore new file mode 100644 index 00000000..d3e15b1e --- /dev/null +++ b/packages/vscode-moss/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +out/ +*.vsix diff --git a/packages/vscode-moss/.vscode/launch.json b/packages/vscode-moss/.vscode/launch.json new file mode 100644 index 00000000..0dd4da5e --- /dev/null +++ b/packages/vscode-moss/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension (open this folder as workspace)", + "type": "extensionHost", + "request": "launch", + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/out/**/*.js"], + "preLaunchTask": "npm: watch", + "env": { + "MOSS_PROJECT_ID": "", + "MOSS_PROJECT_KEY": "" + } + } + ] +} diff --git a/packages/vscode-moss/.vscode/tasks.json b/packages/vscode-moss/.vscode/tasks.json new file mode 100644 index 00000000..f537257e --- /dev/null +++ b/packages/vscode-moss/.vscode/tasks.json @@ -0,0 +1,24 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "watch", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { "reveal": "silent" }, + "group": { + "kind": "build", + "isDefault": true + }, + "label": "npm: watch" + }, + { + "type": "npm", + "script": "compile", + "problemMatcher": "$tsc", + "group": "build", + "label": "npm: compile" + } + ] +} diff --git a/packages/vscode-moss/.vscodeignore b/packages/vscode-moss/.vscodeignore new file mode 100644 index 00000000..6efe1478 --- /dev/null +++ b/packages/vscode-moss/.vscodeignore @@ -0,0 +1,9 @@ +.vscode/** +.vscode-test/** +src/** +**/*.map +**/*.ts +!out/**/*.js +tsconfig.json +.gitignore +**/.env* diff --git a/packages/vscode-moss/LICENSE b/packages/vscode-moss/LICENSE new file mode 100644 index 00000000..372ad0ad --- /dev/null +++ b/packages/vscode-moss/LICENSE @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2026, Moss Team +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/vscode-moss/PHASE1_SPIKE.md b/packages/vscode-moss/PHASE1_SPIKE.md new file mode 100644 index 00000000..be046a88 --- /dev/null +++ b/packages/vscode-moss/PHASE1_SPIKE.md @@ -0,0 +1,20 @@ +# Phase 1 spike — extension host notes + +## Purpose + +Confirm that **`@inferedge-rest/moss`** and **`@inferedge/moss`** both work inside the **VS Code extension host** (Node, ESM). The spike creates a throwaway index **`vscode-moss-phase1-spike`**, runs **`loadIndex` + `query`**, and records any failure. + +## If `loadIndex` or local `query` fails + +1. Read the full error in **Output → Moss Spike**. +2. Common causes: Node ABI / native addon constraints in the host, WASM path differences, or network/proxy blocking the download step. +3. The spike **automatically retries** with **`query` only** (cloud path), matching the idea of a **`queryMode: cloud`** fallback described in the implementation plan. +4. For product defaults: if local query is **unreliable** in the host after investigation, ship with **`moss.queryMode` default `cloud`** until fixed; keep the REST + SDK split so switching back to **`local`** is a small change. + +## Index cleanup + +The spike **deletes** index `vscode-moss-phase1-spike` before recreating it each run. You can also remove it from the Moss dashboard if needed. + +## ESM + +This extension uses **`"type": "module"`** because both Moss packages ship as ESM. The compiled **`out/extension.js`** is emitted as ESM (`NodeNext`). diff --git a/packages/vscode-moss/README.md b/packages/vscode-moss/README.md new file mode 100644 index 00000000..a56f8102 --- /dev/null +++ b/packages/vscode-moss/README.md @@ -0,0 +1,47 @@ +# vscode-moss + +VS Code extension for **semantic codebase search** with [Moss](https://moss.dev). This package is under active development. + +## Phase 1 — connectivity spike + +The command **Moss: Run Phase 1 connectivity spike** validates, from the extension host: + +1. `@inferedge-rest/moss` — `deleteIndex` (tolerate missing) + `createIndex` with three tiny documents on index `vscode-moss-phase1-spike`. +2. `@inferedge/moss` — `loadIndex` + `query` (local path). +3. If `loadIndex` / local `query` fails, a **cloud `query` fallback** runs so you still see end-to-end behavior. Check **Output → Moss Spike** for details. + +### Credentials + +Either: + +- Set **`MOSS_PROJECT_ID`** and **`MOSS_PROJECT_KEY`** in the environment (recommended for F5: edit `.vscode/launch.json` at the **repository root** under `env`, or use your OS environment), or +- Set **`moss.projectId`** and **`moss.projectKey`** in VS Code Settings (workspace or user). + +### Run the extension (monorepo) + +1. Open the **`moss` repository root** in VS Code. +2. **Terminal:** `cd packages/vscode-moss && npm install && npm run compile` (or rely on the watch task). +3. **Run and Debug** → **vscode-moss: Run Extension** (uses `packages/vscode-moss` as `extensionDevelopmentPath`). +4. In the Extension Development Host, **Command Palette** → **Moss: Run Phase 1 connectivity spike**. +5. Open **Output** panel → channel **Moss Spike** for the log. + +### Run the extension (this folder only) + +Open **`packages/vscode-moss`** as the workspace folder and use **Run Extension (open this folder as workspace)**. + +### Build + +```bash +npm install +npm run compile +npm run watch # during development +``` + +### Package VSIX + +```bash +npm run compile +npx vsce package +``` + +See [PHASE1_SPIKE.md](./PHASE1_SPIKE.md) for `loadIndex` troubleshooting and default **`moss.queryMode`** guidance. diff --git a/packages/vscode-moss/package-lock.json b/packages/vscode-moss/package-lock.json new file mode 100644 index 00000000..4fd216cb --- /dev/null +++ b/packages/vscode-moss/package-lock.json @@ -0,0 +1,4975 @@ +{ + "name": "vscode-moss", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "vscode-moss", + "version": "0.0.1", + "license": "BSD-2-Clause", + "dependencies": { + "@inferedge-rest/moss": "^1.0.0-beta.3", + "@inferedge/moss": "^1.0.0-beta.7" + }, + "devDependencies": { + "@types/node": "^22.10.0", + "@types/vscode": "^1.85.0", + "@vscode/vsce": "^3.2.2", + "typescript": "^5.7.2" + }, + "engines": { + "vscode": "^1.85.0" + } + }, + "node_modules/@azu/format-text": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@azu/format-text/-/format-text-1.0.2.tgz", + "integrity": "sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@azu/style-format": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@azu/style-format/-/style-format-1.0.1.tgz", + "integrity": "sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "@azu/format-text": "^1.0.1" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", + "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz", + "integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.23.0.tgz", + "integrity": "sha512-Evs1INHo+jUjwHi1T6SG6Ua/LHOQBCLuKEEE6efIpt4ZOoNonaT1kP32GoOcdNDbfqsD2445CPri3MubBy5DEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", + "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.1.tgz", + "integrity": "sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^5.5.0", + "@azure/msal-node": "^5.1.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", + "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.6.3.tgz", + "integrity": "sha512-sTjMtUm+bJpENU/1WlRzHEsgEHppZDZ1EtNyaOODg/sQBtMxxJzGB+MOCM+T2Q5Qe1fKBrdxUmjyRxm0r7Ez9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.4.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.4.1.tgz", + "integrity": "sha512-Bl8f+w37xkXsYh7QRkAKCFGYtWMYuOVO7Lv+BxILrvGz3HbIEF22Pt0ugyj0QPOl6NLrHcnNUQ9yeew98P/5iw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-5.1.2.tgz", + "integrity": "sha512-DoeSJ9U5KPAIZoHsPywvfEj2MhBniQe0+FSpjLUTdWoIkI999GB5USkW6nNEHnIaLVxROHXvprWA1KzdS1VQ4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.4.1", + "jsonwebtoken": "^9.0.0", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@huggingface/jinja": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.6.tgz", + "integrity": "sha512-MyMWyLnjqo+KRJYSH7oWNbsOn5onuIvfXYPcc0WOGxU0eHUV7oAYUoQTl2BMdu7ml+ea/bu11UM+EshbeHwtIA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@huggingface/transformers": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.8.1.tgz", + "integrity": "sha512-tsTk4zVjImqdqjS8/AOZg2yNLd1z9S5v+7oUPpXaasDRwEDhB+xnglK1k5cad26lL5/ZIaeREgWWy0bs9y9pPA==", + "license": "Apache-2.0", + "dependencies": { + "@huggingface/jinja": "^0.5.3", + "onnxruntime-node": "1.21.0", + "onnxruntime-web": "1.22.0-dev.20250409-89f8206ba4", + "sharp": "^0.34.1" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@inferedge-rest/moss": { + "version": "1.0.0-beta.3", + "resolved": "https://registry.npmjs.org/@inferedge-rest/moss/-/moss-1.0.0-beta.3.tgz", + "integrity": "sha512-0EsqtouvVlFtOpFKJvrNB/WDFVmWpA7AuCx8pXkJVa0tg3DDGOPglq8U0y6TLygi6ZAr91vOawnm5B8p0j/uLA==", + "license": "SEE LICENSE IN LICENSE" + }, + "node_modules/@inferedge/moss": { + "version": "1.0.0-beta.8", + "resolved": "https://registry.npmjs.org/@inferedge/moss/-/moss-1.0.0-beta.8.tgz", + "integrity": "sha512-FZn0DyUC192P/6CiUaZwgxj8AHxUKuYuJ5j6XGZJziAyRgYPPTPaiSrXbbMuAU9s/heP0rZRX5tCt/zHGkNFgw==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@huggingface/transformers": "^3.5.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@secretlint/config-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/config-creator/-/config-creator-10.2.2.tgz", + "integrity": "sha512-BynOBe7Hn3LJjb3CqCHZjeNB09s/vgf0baBaHVw67w7gHF0d25c3ZsZ5+vv8TgwSchRdUCRrbbcq5i2B1fJ2QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/config-loader": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/config-loader/-/config-loader-10.2.2.tgz", + "integrity": "sha512-ndjjQNgLg4DIcMJp4iaRD6xb9ijWQZVbd9694Ol2IszBIbGPPkwZHzJYKICbTBmh6AH/pLr0CiCaWdGJU7RbpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "ajv": "^8.17.1", + "debug": "^4.4.1", + "rc-config-loader": "^4.1.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/core": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/core/-/core-10.2.2.tgz", + "integrity": "sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "structured-source": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/formatter/-/formatter-10.2.2.tgz", + "integrity": "sha512-10f/eKV+8YdGKNQmoDUD1QnYL7TzhI2kzyx95vsJKbEa8akzLAR5ZrWIZ3LbcMmBLzxlSQMMccRmi05yDQ5YDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "@textlint/linter-formatter": "^15.2.0", + "@textlint/module-interop": "^15.2.0", + "@textlint/types": "^15.2.0", + "chalk": "^5.4.1", + "debug": "^4.4.1", + "pluralize": "^8.0.0", + "strip-ansi": "^7.1.0", + "table": "^6.9.0", + "terminal-link": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@secretlint/node": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/node/-/node-10.2.2.tgz", + "integrity": "sha512-eZGJQgcg/3WRBwX1bRnss7RmHHK/YlP/l7zOQsrjexYt6l+JJa5YhUmHbuGXS94yW0++3YkEJp0kQGYhiw1DMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-loader": "^10.2.2", + "@secretlint/core": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "@secretlint/source-creator": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "p-map": "^7.0.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/profiler": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/profiler/-/profiler-10.2.2.tgz", + "integrity": "sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/resolver": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/resolver/-/resolver-10.2.2.tgz", + "integrity": "sha512-3md0cp12e+Ae5V+crPQYGd6aaO7ahw95s28OlULGyclyyUtf861UoRGS2prnUrKh7MZb23kdDOyGCYb9br5e4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/secretlint-formatter-sarif": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-formatter-sarif/-/secretlint-formatter-sarif-10.2.2.tgz", + "integrity": "sha512-ojiF9TGRKJJw308DnYBucHxkpNovDNu1XvPh7IfUp0A12gzTtxuWDqdpuVezL7/IP8Ua7mp5/VkDMN9OLp1doQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-sarif-builder": "^3.2.0" + } + }, + "node_modules/@secretlint/secretlint-rule-no-dotenv": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-no-dotenv/-/secretlint-rule-no-dotenv-10.2.2.tgz", + "integrity": "sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/secretlint-rule-preset-recommend": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-preset-recommend/-/secretlint-rule-preset-recommend-10.2.2.tgz", + "integrity": "sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/source-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/source-creator/-/source-creator-10.2.2.tgz", + "integrity": "sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2", + "istextorbinary": "^9.5.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/types": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/types/-/types-10.2.2.tgz", + "integrity": "sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@textlint/ast-node-types": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-15.5.2.tgz", + "integrity": "sha512-fCaOxoup5LIyBEo7R1oYWE7V4bSX0KQeHh66twon9e9usaLE3ijgF8QjYsR6joCssdeCHVd0wHm7ppsEyTr6vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@textlint/linter-formatter/-/linter-formatter-15.5.2.tgz", + "integrity": "sha512-jAw7jWM8+wU9cG6Uu31jGyD1B+PAVePCvnPKC/oov+2iBPKk3ao30zc/Itmi7FvXo4oPaL9PmzPPQhyniPVgVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azu/format-text": "^1.0.2", + "@azu/style-format": "^1.0.1", + "@textlint/module-interop": "15.5.2", + "@textlint/resolver": "15.5.2", + "@textlint/types": "15.5.2", + "chalk": "^4.1.2", + "debug": "^4.4.3", + "js-yaml": "^4.1.1", + "lodash": "^4.17.23", + "pluralize": "^2.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "table": "^6.9.0", + "text-table": "^0.2.0" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/pluralize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-2.0.0.tgz", + "integrity": "sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/module-interop": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@textlint/module-interop/-/module-interop-15.5.2.tgz", + "integrity": "sha512-mg6rMQ3+YjwiXCYoQXbyVfDucpTa1q5mhspd/9qHBxUq4uY6W8GU42rmT3GW0V1yOfQ9z/iRrgPtkp71s8JzXg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/resolver": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@textlint/resolver/-/resolver-15.5.2.tgz", + "integrity": "sha512-YEITdjRiJaQrGLUWxWXl4TEg+d2C7+TNNjbGPHPH7V7CCnXm+S9GTjGAL7Q2WSGJyFEKt88Jvx6XdJffRv4HEA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/types": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@textlint/types/-/types-15.5.2.tgz", + "integrity": "sha512-sJOrlVLLXp4/EZtiWKWq9y2fWyZlI8GP+24rnU5avtPWBIMm/1w97yzKrAqYF8czx2MqR391z5akhnfhj2f/AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@textlint/ast-node-types": "15.5.2" + } + }, + "node_modules/@types/node": { + "version": "22.19.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", + "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sarif": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.7.tgz", + "integrity": "sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/vscode": { + "version": "1.110.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.110.0.tgz", + "integrity": "sha512-AGuxUEpU4F4mfuQjxPPaQVyuOMhs+VT/xRok1jiHVBubHK7lBRvCuOMZG0LKUwxncrPorJ5qq/uil3IdZBd5lA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.4.tgz", + "integrity": "sha512-CI0NhTrz4EBaa0U+HaaUZrJhPoso8sG7ZFya8uQoBA57fjzrjRSv87ekCjLZOFExN+gXE/z0xuN2QfH4H2HrLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@vscode/vsce": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.7.1.tgz", + "integrity": "sha512-OTm2XdMt2YkpSn2Nx7z2EJtSuhRHsTPYsSK59hr3v8jRArK+2UEoju4Jumn1CmpgoBLGI6ReHLJ/czYltNUW3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/identity": "^4.1.0", + "@secretlint/node": "^10.1.2", + "@secretlint/secretlint-formatter-sarif": "^10.1.2", + "@secretlint/secretlint-rule-no-dotenv": "^10.1.2", + "@secretlint/secretlint-rule-preset-recommend": "^10.1.2", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^4.1.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^12.1.0", + "form-data": "^4.0.0", + "glob": "^11.0.0", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^14.1.0", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "secretlint": "^10.1.2", + "semver": "^7.5.2", + "tmp": "^0.2.3", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/@vscode/vsce-sign": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.9.tgz", + "integrity": "sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==", + "dev": true, + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optionalDependencies": { + "@vscode/vsce-sign-alpine-arm64": "2.0.6", + "@vscode/vsce-sign-alpine-x64": "2.0.6", + "@vscode/vsce-sign-darwin-arm64": "2.0.6", + "@vscode/vsce-sign-darwin-x64": "2.0.6", + "@vscode/vsce-sign-linux-arm": "2.0.6", + "@vscode/vsce-sign-linux-arm64": "2.0.6", + "@vscode/vsce-sign-linux-x64": "2.0.6", + "@vscode/vsce-sign-win32-arm64": "2.0.6", + "@vscode/vsce-sign-win32-x64": "2.0.6" + } + }, + "node_modules/@vscode/vsce-sign-alpine-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz", + "integrity": "sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-alpine-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz", + "integrity": "sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz", + "integrity": "sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz", + "integrity": "sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz", + "integrity": "sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz", + "integrity": "sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz", + "integrity": "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-win32-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz", + "integrity": "sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce-sign-win32-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz", + "integrity": "sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/azure-devops-node-api": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", + "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "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==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/boundary": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz", + "integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "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==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" + }, + "engines": { + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flatbuffers": { + "version": "25.9.23", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", + "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", + "license": "Apache-2.0" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs-extra": { + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/guid-typescript": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", + "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==", + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/jackspeak": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^9.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-abi": { + "version": "3.89.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz", + "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-sarif-builder": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.4.0.tgz", + "integrity": "sha512-tGnJW6OKRii9u/b2WiUViTJS+h7Apxx17qsMUjsUeNDiMMX5ZFf8F8Fcz7PAQ6omvOxHZtvDTmOYKJQwmfpjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/sarif": "^2.1.7", + "fs-extra": "^11.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onnxruntime-common": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.21.0.tgz", + "integrity": "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ==", + "license": "MIT" + }, + "node_modules/onnxruntime-node": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.21.0.tgz", + "integrity": "sha512-NeaCX6WW2L8cRCSqy3bInlo5ojjQqu2fD3D+9W5qb5irwxhEyWKXeH2vZ8W9r6VxaMPUan+4/7NDwZMtouZxEw==", + "hasInstallScript": true, + "license": "MIT", + "os": [ + "win32", + "darwin", + "linux" + ], + "dependencies": { + "global-agent": "^3.0.0", + "onnxruntime-common": "1.21.0", + "tar": "^7.0.1" + } + }, + "node_modules/onnxruntime-web": { + "version": "1.22.0-dev.20250409-89f8206ba4", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz", + "integrity": "sha512-0uS76OPgH0hWCPrFKlL8kYVV7ckM7t/36HfbgoFw6Nd0CZVVbQC4PkrR8mBX8LtNUFZO25IQBqV2Hx2ho3FlbQ==", + "license": "MIT", + "dependencies": { + "flatbuffers": "^25.1.24", + "guid-typescript": "^1.0.9", + "long": "^5.2.3", + "onnxruntime-common": "1.22.0-dev.20250409-89f8206ba4", + "platform": "^1.3.6", + "protobufjs": "^7.2.4" + } + }, + "node_modules/onnxruntime-web/node_modules/onnxruntime-common": { + "version": "1.22.0-dev.20250409-89f8206ba4", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.22.0-dev.20250409-89f8206ba4.tgz", + "integrity": "sha512-vDJMkfCfb0b1A836rgHj+ORuZf4B4+cc2bASQtpeoJLueuFc5DuYwjIZUBrSvx/fO5IrLjLz+oTrB3pcGlhovQ==", + "license": "MIT" + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.1.0" + } + }, + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "license": "MIT" + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc-config-loader": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.4.tgz", + "integrity": "sha512-3GiwEzklkbXTDp52UR5nT8iXgYAx1V9ZG/kDZT7p60u2GCv2XTwQq4NzinMoMpNtXhmt3WkhYXcj6HH8HdwCEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "js-yaml": "^4.1.1", + "json5": "^2.2.3", + "require-from-string": "^2.0.2" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "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==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/secretlint": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/secretlint/-/secretlint-10.2.2.tgz", + "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-creator": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/node": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "debug": "^4.4.1", + "globby": "^14.1.0", + "read-pkg": "^9.0.1" + }, + "bin": { + "secretlint": "bin/secretlint.js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT" + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/structured-source": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", + "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boundary": "^2.0.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "7.5.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz", + "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/terminal-link": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", + "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "supports-hyperlinks": "^3.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "devOptional": true, + "license": "0BSD" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.7.tgz", + "integrity": "sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "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==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "dev": true, + "license": "Artistic-2.0", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "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==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + } + } +} diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json new file mode 100644 index 00000000..a9e8b503 --- /dev/null +++ b/packages/vscode-moss/package.json @@ -0,0 +1,63 @@ +{ + "name": "vscode-moss", + "displayName": "Moss", + "description": "Semantic codebase search powered by Moss (development / Phase 1 spike).", + "version": "0.0.1", + "publisher": "inferedge", + "license": "BSD-2-Clause", + "repository": { + "type": "git", + "url": "https://github.com/usemoss/moss.git", + "directory": "packages/vscode-moss" + }, + "engines": { + "vscode": "^1.85.0" + }, + "categories": [ + "Other" + ], + "type": "module", + "main": "./out/extension.js", + "activationEvents": [ + "onCommand:moss.spikeConnectivity" + ], + "contributes": { + "commands": [ + { + "command": "moss.spikeConnectivity", + "title": "Moss: Run Phase 1 connectivity spike" + } + ], + "configuration": { + "title": "Moss", + "properties": { + "moss.projectId": { + "type": "string", + "default": "", + "description": "Moss project ID (optional if MOSS_PROJECT_ID is set in the environment)." + }, + "moss.projectKey": { + "type": "string", + "default": "", + "description": "Moss project key (optional if MOSS_PROJECT_KEY is set in the environment)." + } + } + } + }, + "scripts": { + "compile": "tsc -p ./", + "watch": "tsc -watch -p ./", + "package": "vsce package", + "vscode:prepublish": "npm run compile" + }, + "dependencies": { + "@inferedge-rest/moss": "^1.0.0-beta.3", + "@inferedge/moss": "^1.0.0-beta.7" + }, + "devDependencies": { + "@types/node": "^22.10.0", + "@types/vscode": "^1.85.0", + "@vscode/vsce": "^3.2.2", + "typescript": "^5.7.2" + } +} diff --git a/packages/vscode-moss/src/extension.ts b/packages/vscode-moss/src/extension.ts new file mode 100644 index 00000000..7429803e --- /dev/null +++ b/packages/vscode-moss/src/extension.ts @@ -0,0 +1,162 @@ +import * as vscode from "vscode"; +import { MossRestClient } from "@inferedge-rest/moss"; +import { MossClient } from "@inferedge/moss"; + +const SPIKE_INDEX_NAME = "vscode-moss-phase1-spike"; +const SPIKE_MODEL_ID = "moss-minilm"; +const OUTPUT_CHANNEL_ID = "moss-spike"; + +const SPIKE_DOCS = [ + { + id: "spike-1", + text: "Moss VS Code extension Phase 1 connectivity spike document about semantic search.", + metadata: { kind: "spike", idx: "1" }, + }, + { + id: "spike-2", + text: "Refunds are processed within three to five business days according to policy.", + metadata: { kind: "spike", idx: "2" }, + }, + { + id: "spike-3", + text: "The vector runtime downloads embeddings for local sub-millisecond queries.", + metadata: { kind: "spike", idx: "3" }, + }, +]; + +function getCredentials(): { projectId: string; projectKey: string } | undefined { + const fromEnv = + process.env.MOSS_PROJECT_ID && process.env.MOSS_PROJECT_KEY + ? { + projectId: process.env.MOSS_PROJECT_ID, + projectKey: process.env.MOSS_PROJECT_KEY, + } + : undefined; + if (fromEnv) { + return fromEnv; + } + const cfg = vscode.workspace.getConfiguration("moss"); + const projectId = cfg.get("projectId")?.trim(); + const projectKey = cfg.get("projectKey")?.trim(); + if (projectId && projectKey) { + return { projectId, projectKey }; + } + return undefined; +} + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +async function tolerateDeleteIndex( + client: MossRestClient, + indexName: string, + log: vscode.OutputChannel +): Promise { + try { + await client.deleteIndex(indexName); + log.appendLine(`Deleted existing index "${indexName}" (if it existed).`); + } catch (err: unknown) { + const msg = err instanceof Error ? err.message : String(err); + if (/not found|does not exist/i.test(msg)) { + log.appendLine(`No existing index "${indexName}" to delete (ok).`); + } else { + log.appendLine(`deleteIndex warning: ${msg}`); + } + } +} + +export function activate(context: vscode.ExtensionContext): void { + const log = vscode.window.createOutputChannel(OUTPUT_CHANNEL_ID); + + const disposable = vscode.commands.registerCommand( + "moss.spikeConnectivity", + async () => { + log.clear(); + log.show(true); + log.appendLine("Moss Phase 1 spike — starting…"); + + const creds = getCredentials(); + if (!creds) { + const msg = + "Missing Moss credentials. Set MOSS_PROJECT_ID and MOSS_PROJECT_KEY in the environment " + + "(e.g. launch.json for F5), or add moss.projectId / moss.projectKey in Settings."; + log.appendLine(msg); + void vscode.window.showErrorMessage(msg); + return; + } + + const rest = new MossRestClient(creds.projectId, creds.projectKey); + const sdk = new MossClient(creds.projectId, creds.projectKey); + + try { + log.appendLine("Step 1: REST deleteIndex (tolerate missing)…"); + await tolerateDeleteIndex(rest, SPIKE_INDEX_NAME, log); + + log.appendLine("Step 2: REST createIndex with 3 documents…"); + await rest.createIndex(SPIKE_INDEX_NAME, SPIKE_DOCS, SPIKE_MODEL_ID); + log.appendLine("createIndex completed."); + + log.appendLine("Step 3: Brief pause for index readiness…"); + await sleep(2500); + + let localQueryMs: number | undefined; + let localError: string | undefined; + + log.appendLine("Step 4: SDK loadIndex…"); + try { + await sdk.loadIndex(SPIKE_INDEX_NAME); + log.appendLine("loadIndex succeeded."); + + log.appendLine('Step 5: SDK query (local) — "refund policy"…'); + const localResult = await sdk.query(SPIKE_INDEX_NAME, "refund policy", { + topK: 2, + }); + localQueryMs = localResult.timeTakenInMs; + log.appendLine( + `Local query: ${localResult.docs.length} docs in ${localQueryMs ?? "?"} ms` + ); + for (const d of localResult.docs) { + log.appendLine( + ` - id=${d.id} score=${d.score.toFixed(4)} text=${d.text.slice(0, 80)}…` + ); + } + } catch (e: unknown) { + localError = e instanceof Error ? e.message : String(e); + log.appendLine(`loadIndex/query (local path) failed: ${localError}`); + log.appendLine( + "Falling back to cloud query (no loadIndex) — see PHASE1_SPIKE.md if this persists." + ); + + log.appendLine('Step 5b: SDK query (cloud fallback) — "refund policy"…'); + const cloudResult = await sdk.query(SPIKE_INDEX_NAME, "refund policy", { + topK: 2, + }); + log.appendLine( + `Cloud query: ${cloudResult.docs.length} docs in ${cloudResult.timeTakenInMs ?? "?"} ms` + ); + for (const d of cloudResult.docs) { + log.appendLine( + ` - id=${d.id} score=${d.score.toFixed(4)} text=${d.text.slice(0, 80)}…` + ); + } + } + + const summary = + localError === undefined + ? "Moss Phase 1 spike succeeded (local loadIndex + query)." + : "Moss Phase 1 spike completed using cloud query fallback; check output for loadIndex error."; + log.appendLine(summary); + void vscode.window.showInformationMessage(summary); + } catch (e: unknown) { + const msg = e instanceof Error ? e.message : String(e); + log.appendLine(`SPIKE FAILED: ${msg}`); + void vscode.window.showErrorMessage(`Moss spike failed: ${msg}`); + } + } + ); + + context.subscriptions.push(disposable, log); +} + +export function deactivate(): void {} diff --git a/packages/vscode-moss/tsconfig.json b/packages/vscode-moss/tsconfig.json new file mode 100644 index 00000000..a4491503 --- /dev/null +++ b/packages/vscode-moss/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "target": "ES2022", + "outDir": "out", + "rootDir": "src", + "strict": true, + "lib": ["ES2022"], + "sourceMap": true, + "skipLibCheck": true, + "noEmitOnError": true + }, + "include": ["src/**/*.ts"] +} From 9a6f382c767eba2e8b6c9ab902ec069143e267e4 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Fri, 3 Apr 2026 18:02:07 -0400 Subject: [PATCH 02/21] feat(vscode-moss): phase 2 project scaffold vsce ready --- .vscode/launch.json | 8 +- .vscode/tasks.json | 9 +- packages/vscode-moss/.vscode/launch.json | 2 +- packages/vscode-moss/.vscode/tasks.json | 19 +- packages/vscode-moss/.vscodeignore | 1 + packages/vscode-moss/README.md | 14 +- packages/vscode-moss/esbuild.config.mjs | 23 ++ packages/vscode-moss/media/icon.png | Bin 0 -> 22216 bytes packages/vscode-moss/package-lock.json | 485 +++++++++++++++++++++++ packages/vscode-moss/package.json | 13 +- packages/vscode-moss/tsconfig.json | 5 +- 11 files changed, 555 insertions(+), 24 deletions(-) create mode 100644 packages/vscode-moss/esbuild.config.mjs create mode 100644 packages/vscode-moss/media/icon.png diff --git a/.vscode/launch.json b/.vscode/launch.json index edc6ef64..d5f8aae3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,11 +7,11 @@ "request": "launch", "args": ["--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-moss"], "outFiles": ["${workspaceFolder}/packages/vscode-moss/out/**/*.js"], - "preLaunchTask": "vscode-moss: watch", + "preLaunchTask": "vscode-moss: compile", "env": { - "MOSS_PROJECT_ID": "0254fba9-3a96-4914-ac00-943f7893035c", - "MOSS_PROJECT_KEY": "moss_UxG3voqCV632Auc8kU7RSUrUb0ppJxfg" + "MOSS_PROJECT_ID": "", + "MOSS_PROJECT_KEY": "" } } ] -} \ No newline at end of file +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 176ccd5d..fafb23e3 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -8,7 +8,7 @@ "options": { "cwd": "${workspaceFolder}/packages/vscode-moss" }, - "problemMatcher": "$tsc-watch", + "problemMatcher": [], "isBackground": true, "presentation": { "reveal": "silent" @@ -22,8 +22,11 @@ "options": { "cwd": "${workspaceFolder}/packages/vscode-moss" }, - "problemMatcher": "$tsc", - "group": "build" + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + } } ] } diff --git a/packages/vscode-moss/.vscode/launch.json b/packages/vscode-moss/.vscode/launch.json index 0dd4da5e..7c297510 100644 --- a/packages/vscode-moss/.vscode/launch.json +++ b/packages/vscode-moss/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "args": ["--extensionDevelopmentPath=${workspaceFolder}"], "outFiles": ["${workspaceFolder}/out/**/*.js"], - "preLaunchTask": "npm: watch", + "preLaunchTask": "npm: compile", "env": { "MOSS_PROJECT_ID": "", "MOSS_PROJECT_KEY": "" diff --git a/packages/vscode-moss/.vscode/tasks.json b/packages/vscode-moss/.vscode/tasks.json index f537257e..ab3ba025 100644 --- a/packages/vscode-moss/.vscode/tasks.json +++ b/packages/vscode-moss/.vscode/tasks.json @@ -3,22 +3,29 @@ "tasks": [ { "type": "npm", - "script": "watch", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "presentation": { "reveal": "silent" }, + "script": "compile", + "problemMatcher": [], "group": { "kind": "build", "isDefault": true }, + "label": "npm: compile" + }, + { + "type": "npm", + "script": "watch", + "problemMatcher": [], + "isBackground": true, + "presentation": { "reveal": "silent" }, + "group": "build", "label": "npm: watch" }, { "type": "npm", - "script": "compile", + "script": "check", "problemMatcher": "$tsc", "group": "build", - "label": "npm: compile" + "label": "npm: check" } ] } diff --git a/packages/vscode-moss/.vscodeignore b/packages/vscode-moss/.vscodeignore index 6efe1478..f5de64da 100644 --- a/packages/vscode-moss/.vscodeignore +++ b/packages/vscode-moss/.vscodeignore @@ -3,6 +3,7 @@ src/** **/*.map **/*.ts +esbuild.config.mjs !out/**/*.js tsconfig.json .gitignore diff --git a/packages/vscode-moss/README.md b/packages/vscode-moss/README.md index a56f8102..3f2ca531 100644 --- a/packages/vscode-moss/README.md +++ b/packages/vscode-moss/README.md @@ -31,17 +31,25 @@ Open **`packages/vscode-moss`** as the workspace folder and use **Run Extension ### Build +- **`npm run check`** — TypeScript (`tsc --noEmit`). +- **`npm run compile`** — bundles `src/extension.ts` → `out/extension.js` with **esbuild** (Moss packages stay **external** and load from `node_modules`). +- **`npm run watch`** — esbuild watch (no typecheck loop; run **`check`** in another terminal or before commit). + ```bash npm install -npm run compile -npm run watch # during development +npm run check && npm run compile +npm run watch # optional during development ``` ### Package VSIX ```bash -npm run compile +npm run check && npm run compile npx vsce package ``` +The VSIX is still **large** (~100MB+) because **`@inferedge/moss`** pulls **`@huggingface/transformers`** and related assets for local embeddings. Bundling only shrinks **our** entry file; trimming install size further would need a different query architecture or upstream packaging changes. + +**Marketplace:** `package.json` includes **`icon`** (`media/icon.png`, from the repo Moss logo) and **`galleryBanner`** for the listing. + See [PHASE1_SPIKE.md](./PHASE1_SPIKE.md) for `loadIndex` troubleshooting and default **`moss.queryMode`** guidance. diff --git a/packages/vscode-moss/esbuild.config.mjs b/packages/vscode-moss/esbuild.config.mjs new file mode 100644 index 00000000..fe58be4d --- /dev/null +++ b/packages/vscode-moss/esbuild.config.mjs @@ -0,0 +1,23 @@ +import * as esbuild from "esbuild"; + +const watch = process.argv.includes("--watch"); + +const buildOptions = { + entryPoints: ["src/extension.ts"], + bundle: true, + outfile: "out/extension.js", + platform: "node", + format: "esm", + target: "es2022", + sourcemap: true, + logLevel: "info", + /** Provided by the extension host; Moss packages pull large native/WASM stacks — keep resolvable from node_modules. */ + external: ["vscode", "@inferedge/moss", "@inferedge-rest/moss"], +}; + +if (watch) { + const ctx = await esbuild.context(buildOptions); + await ctx.watch(); +} else { + await esbuild.build(buildOptions); +} diff --git a/packages/vscode-moss/media/icon.png b/packages/vscode-moss/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..29d5613861af54dceeff11646e134020a5560d80 GIT binary patch literal 22216 zcmeHvd011|+V7%K1~o{uPGJy1p;`x2#4x9Tbw*FAm8xjOi7IMTR0Py5QjAu?qZO$W z;p?gMfI|@lH5MFBv5;0la12nC78FoHw2I&F-8<}5o_p_i|Gdw0PtJ3mvesVfoz^?= zwcR)|c%-zQyd7gqI(k&lXN;NKGS>EMOLNTF44WH||5&LGA30hK{b!2VHveY%Fl%ms50U zc1PjQ;_;EfA9H1(4nOY8JR*=WRo9bd{2!?!{-Dzb zc6Q!qrVgGUtM4vbDXU)=bWi%D&phk++s{0$8TXxa{WIUH$I-8XfB(y7Mjwwl*K33J zPnIpQm-+uI$&9O9rO~Vos#&d{`&Cj}#iH`c)Au&q8^%~v)$Q6qe*k(EJoBqO^X9_( zlcQz@#oY+|fE`(4EBn4<>FnKOE+p;j`C&a_S@tS6sK#f-#u*!>nhwk@txCD6;&ImM ztZ=xd!qq|dqF>sF=O)_Eu+I8MGof@U({_I6d27hrWbN8(*ZMrk?f4C28Fufw4DwH? zTyomBk4NOK&;Oj16Zc8OHYHOW+n~v64Dmg)G;a291LKk;OtorXdF5aFutuAL+8L)T z)N4WxWow$!>e_Z;Q<{1?JxyBc*uiz!j`PWych+eYjD_y+D678|a%gyIpu&Hr)VBO2 z1h&HANZx2W|7-WJjJ@#z3&}A<=5_8sg13Np{eJYK?m8^$No9F>xQ3i&tn~ad8Tt-VuAgP ztL64mwzc-sfzQ_7aJU>}Hz+&-?lPwC-yKyAh2FMa9y?-s$lmS7K{xq>*Y5LI6*&BK z3P(I5@7?TLxRK6YL3x!E^9xG@BXZ{i9!M&Dd4C?}n+;)2Z@*hyM<)>c%I}uv$@Ce+ zW%a#c+ps#h8&vJXnCiu`w!NK1d zzWX@FJaiRvyem(oPngxnnBjRN1%~8K+*Vtq4+q<9t`B#ms|4*sDu$h9I+|U0^E_GJepG+TgT+URh-!xxX za_vasgi>#))aB)kEO=yO)i?e}0lWUM;Y2YTwe&k*?xxJvYl)BNGs`|KG%dfz>~~MU zPsgf1V5%c)>LNG zvR@lt?GkIjSnuo`pcVVFZa5$cmdq*aclvUf`#*a)GH+6& zHRwtqHm0pCl|(#sae6Q(SzNfR`}|jZW7|BjJ0V|0>ch^s5E-TOI%>~VtBWuZ$q|lu z0QiWfYBx_OOl#E*hflmi4&5g01Oqxx5}aova4aIRGWEc43Ddp0-|@$LbCR`t58XN< zz|#PpdJT?u*Yo3$kt&2}dmf`M(w{waD__$@-jNyh@UwU3fR4ejfTlaQ5#S#`cfWP2 zkjLAt>@Xxy;)sA`h=a1a3;bUv^7dT2JSp&D(qw5G&(mxh2(BPETW*xmbtkMjv(oZp z`ht){wa(@Jh<+vIIob>NC+5RZ?>fIxv$E6~cux^mPoA8%&==GnF5}fl=|U@y-Azxq zRwHv?ZVzQ<+?LM3aYv4Idq|N~&x!sO(}qPY>et}qqCUy z$?Azn!1FYj=gHBD_I^P;Jq`nQHj)JShi}&WDp=GUxNJK6j1T$QC#Nj*_jm(Sjizlk zW90Ko=kfCXhL?Ap1+DvPi+C;>?)*l(X~SMTi7u+^%OBov#O8sDFzH)cUK{)WlTJy# z!N&Hy$Bx&2PRDsc8fUZ9QyvrNon^JBMuI-$^j|e*XO`v6&-yn{-sglR?rh)y*nGsF zUcBza5mdK_sV%w`_ce`^k0chrfsM@D0Jp)|Sd!9>ze(u_677ShYYtWpgr<)BVfxo3 zVQw**#{=k^a@hk?)Vg+r@vcuRF`4tTH6}3)ATiaxY^6wsB7Pc5)S_^^NF)y*8xE&0 zZt+sAI0)9&wgjg{|&;S!p3Qwzc(Q6=DA(a8{Fm; zJeimeU%un>PFQM9ZI%P{dB{W zr>92h3lMI}p))>jZ#oZpe_1sdrllK464}{WomTL(CUw&Cdh^&<`eV&$9@+>Vn!<{Z zJU1C!6`f(-Jd4TF)h55xo)#7697$g*DEdAU)7q$37B_)J?th1Jn`G^w-J0l~z8^5A zbtOuAzHf4iY3ajz)<60n!#E^(CiPNUxR|#S@&#Hm!us|5+T=@GGQ9?NDOibiGBzpm z-cHO9L+t#{=&so>MBtk8)$MbR5Tss!RC1npLQ1q*lT0Cs#gJl7J)19@?*q6bT}o>S zMFc}fG9yVZ1?C69%DH1+q?d3ZA-qEt=AIo-Y=&V1c4h!=sTqmv~DdI&gx@gV;7zLIno3LDM(4D$_TiSpR|>h#r)0IiXlm5q4jb3>lHcko4(~ass=~ed7`N?oSXhcphg z8TpS4N5WwHzI2+l5U{x>>AWFReDQm0XLJRzncIgr9Z`^taKO4!c#o+k=Mi#fr>uT3 zd0DoWmqv*g)L5D;(G}fFJQ<-x$$FBtpdC#^AnefW^+ysf+Mkg7&7ojo$fpy3BH9?c zNP1UX^S%lhXCsH-dbY!UrQl7RFlQ6rewU~_4?};gu zm`$l!aji&EFT0aciuY1tx^HFXu$!y&FK~0|m-e=#T^b_Zb-xKl-DSxG>WY@^f4BZjah1Wt4 z(#lgNbMqjr9MUTE>sH|ql!;+5a3QHtlVYhCO$Z!-vV?%i1Yp$IDp+WeP{CN5_~U&E z4Fd5BSCfRE6ZOkH6H4?y9=i2Xwqyr6El!v%Z57g5roqml&d7i8{+-#i`+s*xDO3do&onut{yU*pHU_oIh^wX8bE5Ka`Z80^#;U0@Jwf1vT!j^r;HFo!(k1qQ6kz%+G7&!4*6k*be73d0 z#qhJHT$@`?I(TALtN6xepmoDY%LT*CSVP42c`t|5y(VBgqbCQx6HKss!9W(yFa!T(OaC2D*JtlTL`hKcE6uR8paXO{S;>T zEYc83V~6+iq!McgBy*n0;37#W?=Ed^aPy#rx=fSfR(R9C)&`e}=)pbto59^hPO9^0 z?Uo!j5)SmUT7t#hJ|0Z@j?zfJXcZDARW|6YN`sJUz4(xF7c?jz!Y@Tq(+R&!*f)34 zm_`=VU(x&X<+|!FZM^FT#>4pD3InaLmwVrOmg*b-XdquFQ?B_I2d?f)jV7eYfaG^> zeo0cYX-JjK18Rj)X=ei^R3-}{U)|N8hs#+4aE!ZvBNNexy9kvb$_jYOU{Ex;3u9IK z3u=NP_XO@y+Y?rVpK3SJntORtZez4RtsYBwdh+=L8-AmSo&X`AX{>s(sA7inhSmzH~<}$(8P-GznwN5OShu#;Fd#l847`gOc(*zuu5H| z^Y^}ZsltQLnE8W$4FP0?4llb;0_;sH8YV~~bbm#*?Nz>xj!ec$R1cZkQB|5aWrb`> z8Xt}qLPRQGC`9xRN9q)Pu)P5G&Nb8>H=kbFr1&A<#tw6e&X9j`nN7Il;mm`TkE2)3 zbjPeaoV?DfCdvPp^@$a6HN}^xKg+ahVRA=vp%m4<6&S0nG4B6RsNajLyW2I-h~7Y& zu!STT2iA&fo2)nVbT01|+aA+ziK5bJ!_-6283`QV|7qUZxr-qs?I40f%J#O${2tEb zi)HmMfA5P8QAlmL%JV{xC@pES^<-K7iC$iK;#HYMvCww6?@gA!U=?O}L(sL3#8JAYsFV@3NWU!yHFBOQ|%V zbXVCXPFaKZAxWA`Bk~qLv*UXf+?;y!2e~ah=C67a7S$As>1aBrlnNXa)6KR2K6g^k zn*}*>9&NZHQVP!%*B&>0z%ph+8nPv_<8~}mM(by#5fO9HgZG>6`DSusR~Ai)Y)YAs z!b65bZY}LBd$$iNbCIlX4l*6ogX54VLO((kSp1A!pW#Rw3zmZVfs5nqsQ<&kihJmO zbA>om$J;_QKp_Mr@^W%OlSbzcAM1FV7edjwO`1T|UQLv0KjZBiQUBq~VJ?Mef`ER< zLf-PKkyW%$4*5X!3GD59eN^1#p7f@6Jj}d_IzFC!G(38@{-1kZqPBG;_2_`eiLU2$ zLPX8O>jujB_T<%{FQfJzG*LYrtvqP@fV4qoqe!t=3FeO&wIdDgh5XoKvCvBcXqc>J8dD)qh?`#ydzwN5Xvu4w|ZZ?s*9wFzt-M z0XU>Xpe3SKNG2G&?~S+3yf=>E!ssv2x|X{DXT2z$ zKnRh6gq$K1Tb;mGorjSva{RiN*?iJWa^(BOaYDP2>9*0*)qFFSy&-G5SO}McpN=}f zbuogMrim2t&$osAOz7~QcuuwoGoapf^j^3M{J0-Ff%>~*RAMQl1&dqueFutXtmGTf ztZq5zj@!#;Ml5bUJy}7K4-hGOHJuU)OCBhRBpq)RA+Xb|d*eba?p zgT_ax<1KA@YUI>FH zG%zNi80+o;NF?%4ddT-&r&bD54x)wggEem<~oi6u2JI2kUjlcMPlI{G z7(ozucLi`L{5S`p80W$B;}-C+WYrVFXnI34L$i&n9HYT$p*cajrUG@wTtUOgl8dX2 znlc1ZJX$1VR%{SGsS?5`HgR;e3yf!J7*2y_g280;rvYBd5bX9y;xb%#FOK#i5@gkQ zp@^o3P0(3x7|IKjdhR)3&-fz&3WJsAJq9 z;*Q=M&~L`e+i=TuUC3ezX5m_c(;A=V^NQxzb>CfT=;gG}x%{yvdb1`wJteL1qzqPs zrUcjLE=;Pbh%alsn$K_6tUU2%G{R`{AeqLbCQqY!U`t65qeRJp* zu2ncs|4DZ!AlE;(o9vxT_AYhI{hk%DN4+Oeg7!O8Y(b|cbhPE}_1N&75^{yw1-ZMOs-8&)2w)JgR5Ll;~&^9kMbgPDV!nQwO1jUTd4pK8wW znGkd>;%3?{+0EM7mCN7AdNjUR7L?qPoy9rg37$HLWUmv3(Y z2ofE4{3T}&9;+g<`Y4bVR6rO*-XeR|&I!n!j0BBEK&x@tu9N&JW$4Q9v4BNv*4H_b zDC9T*rVLC-+-`}^wZ1#WA9*kLJtK(QMDlrhmR{yW@^D80X58$6KpDT0YI~(q`pnMs zjNAZo+^Em!OV2t%N^Gk#;$Q$l=?zv`&A5nzV`$WdAB~DA`I-dhP5V@?0lCMC(h>?S z%-cr(84;5~0gLtPEdR`kMiPG1NxsXGxFF+XpF6p`^Mr09o(?J_BDN9G9Yl7<;Pmvb zh_ug%P+ej|;y@lKCF{(?$vukSC?!fW%+k}x($YwJoyi3R1m5PUp(K#CO-SrT8z)j@ zgllgl4U|D$wEVMfHu6N0sqSmSuh_14b0_u(@)&z0B=)6^YRYX`aBufuyA+N9T66Q%p9ZRRFTUuRDzHIDkns&)Yq zEB+a5jk)=xuM6V$5fj~a>6H?CmWcSk-1?`lOC&*cpthoFRDeWE2HBlD-#T@Ix!eU3 zcI!=4r&~&+h(DDg92Di+$g4DvjBX+^k?82I??p_^B;KPYL}+Ib!azb;wM(yKgz!8e z)DK8sw~i1-5kl?Q0EvVURuMww$^>(BLa3*gDco^O={Q2D^(KV(ZRDwhP&t_po_BP2 z;}I?*gzgg}RN;g$j1Wfb(lZ)7ArVHT=-DMY-iTdmou`cxk$o^jcz~os zAe{_dpV5s-Fz-$>)m1)9)=oXMBR+h{W(~msk~$tvEKwdeGJ-wrMM$V> z;!apfba&8QbM$>4!OwRpGBP;$HMtg~=?Z{l2OD}i0S%}ev zq%lqz!M5?wNKegO-PynSeS};BB^`s2uecag=QU-JCly?{v!Q`Zw9q3(k_sx3d z9t=Tsr>3l%O}bfC0(fwv@S(B^km!5hOjYy(S;rF0wIRd=xf-s(N~(NJ2+atgJrI6E z2@U76;k`15Yih+ChaU|PUXwg(R*>Tf}_`{Y>OB24jVaJ^mZvF9L_lC-GoAm6h)(1 zix+(nH>z__`4ysfr+dkRv`cCDDkulndh}Y?vgb0U9Sug6vB#auH`K`3me=(eM{g6L zCbD<^){2TxaG}*qpEVgtPzoXTCt4P++KV79nNa?`uN%c&@a$e5eYk88x)@&dr*C4( z6FQ?i_5G09%!^y}fe?WsbThw9`!uhRmOUR5%h2v8J{CrQ2XKKCtn*(Fq3WJU`k1HR;M-LxsBu(uD@J+o0Llz6*E=5wVgK1VJGpjqM0;U7)2`&ZxcpWS$37$_#E)~r zUiwX>C`-RhBnI~4X<#FsmJ$=M;zpZKd_8L`u(BG2xFs;YZ@X)jE?+SWn4 zx$qyzOL)pC1+)Jv>c@e@=>X=EyYHPnWoL5Pwg_%4ZKjSii?~AT_QvpiT+*N}7yC;T z4-eG6vSRu+G+{Qm`q|W=H?FZ3%6Sj$dycSRO1g8PwLgL4AnFm{IOoN_C2Pvg-I}Ih zSm^q|VZzsD$d_p0fZHUaB{*W^aZ5e-EsDkkSnZN`Q7CA&)DKd|;{NLaUS}3(Rp9o8 zCr!>eUR*gV=nZatX#e4F@9&D2ndId3+KP&Ao4>>C;I)^g?0m^<7~Lz-A3U=Bob}7$ z>|RXlj{_aj+A#e`M8d)oPUYyZakCenD6X7C*BqXbJlt!VrakKhU-i5b%3CkW4ak&T zT+rmD<|?b=3~U^%k5%z#tuC9TYV<(E+Zz0ln^`)b2NJ3C+E}Pm0r=wp8HTl$wT?@` zA4znUdpp^2>n!OH-nilLBrr2(P6(rb(2EduAcWn4kj$NRCxmX6m(8jOq2Ns%<0X1R zs8Rxb_b|pp@t3z1m6&0Z)l;TQyU9IfAGL&5WXfX-9!5fe2y_gX2)63+I#fo z(cm2~QCom}j*l|;Myrv`0b?Cq^Wi-bdENl^JX zyUEg8Ka8G@Coz85*^Y84#B?$%=Mi@&di=}L&ipThfFnaV+C~p$R!*m)Ydkkzm z$@m~2_1j%G+vNoO6DbFwRK@)haHaJkY7V!t7=c-pVP*zq;IN~7|}+0=fWIOi0mfxqv(jYV&8b$CnQoJ6tRYJ zF2v!#I@=kXh{Ioq>aZjzR zqX?m@J0T3Tv7^Y_l4AE#=y`-?gs{U1wRQ<13?zg|zm(q-!bC#o*8B3htAtR<=|kfs zTL@uyLa5WXvDilDHjZi*Rdl>$H0|5Z*9mPeuiMK%<7)_cyu_O%oSH=YK5t`zVi2Qk zG>XEAf5z7d-?p*vAb;XUcWSt=tgIu0h=~|t0;SbQBzz@N?Wj;A17$2J4>&C^uRBfH z>PXfssf`7yG=Qc{?hHkj&Y1|yqRuRPXk(YP0g^yH25t@3@sfwck->~G+zV72$bWGo z2}K>dJTry_!`me{($e}Ssh1&$mZCmG5d}E&csN1vx$cBSLGP|GXO~Dvp=(PND7G6= z8-cKayVyvJit~2QE2!B7?sO@w)y$5miIr%LcwF`OBlS|Rcij! zW)a;{^R))@=E}!JT2%=X5b~+9{#=rPa6KVZF?#`_IWJ(xi zL-b+8m6>182+BkAZt9h@v9_`kNHQ>7^udiHbY(YqchNb!hPcS-le|S?jlDgCq|q2Rl6&nYSgoI{@-4SNd$M zdx{sEOmUZ9)$za86y@;y-zAw4GLHsJJ|d#%H-e;&A74V!AOBOP`X3+=QmgF!KQj4$ zP9}~w>E$?nKa(57?>*Ju`Ue{2^s9vW4|z*f9n5AajQLByuw(g)sjPsJz&UKKG_Jf0 z7j%6oI@z>xA>7UERl*GzVbEl_NQT5Mp(m)U`DITqsCg0+oq%t+h4i7Z@%8*Lzq!fu zSVg&R?CTF5(&<&U8=765Z7#Xlr~{U36YSa}95{`Z8`6xTz@%3Cj7I zZqa;?vi&)35ZyozPu1}Ryx3~0aJrYAMrB8n+RU@4;asQ`?(lR31o8-RYvRqjN0zVp zjy|h!sY98|mcefvtmHj=gMCWFm;A@5+&Q4SRoCmyye`NeD-Qr7qFlz0_{6fDSb+EB zMuQB#$ezka+L0*jWitMr6nHsi3BhMvq8AKwzbQjX{&>X-pQ5^*xST^%6Ztq}M@6Cm z35=4`D%J^&g*o6@83^_V@E+-zQE}(CoAIsOAWLa)@8(}|U0_$YYiS4~t8hk{ZSY<|yHM2?ul~a6-vzK`Hu939 znP0BmRJb{&$PJ;Pi=+MokxU#Y%>KKTJ zB|<}PjE>MA&OJ4K!*v316Po|X*?rT1iby1GxiGT8lI!dNYk zt75Qw^Y{pDJ31-WgdEpxVEVd#Bx`1v3W8ICkB*;l**LHYnfxI7i1YEKa;-ks~_h(H|x^s#vOF*v6^ zBgKulm!kF(H?G9Suf&Zqu$U}v{1nISGp=Q0cf#o3vQg!ZjrUC(f$^bfBQVB^>ed|? z>ny~LQP?=I_QQ8gXzaJY$*piZssdJ9ABB6Re7@pzk1&2ApmA_)U-NV&;dU{Y^c zH%i>-KpWu%1dEN{gN;gYBZQ_G8RTwmlqw6wjRi373nE4Z?&Z8NVH|>uB8OZ)Hck*X z{;ZKI2bo5A)=?Z~;s}q4=Td^=`iyv>D!3YbKaq_m*!YdO@lP9DuGq3g*>8ci0iu>3 z#C6pvy;_ugA}Bp0vZ(4AF4-y`y~-aW(b82jFcO`KYAr^h`*4I$suA}&;!10cxX%$^ zFw}_q9D%P!+^3a>OD67aIZ~x}p1IaVWGNGp8PK9?43~yExyaxhMAWIGWFmkfQbeeQ zqsizZf@#D7cNI6%wfi4TBM7*UX#_X0Q#`{ea4{{QhK0sh%DR^VBBfi2#jY< zBRC#efMkaypGGc&ZxgrSQzEzF;t2N$-Newry~4;ef>nA&GPACXSG2xpizA zu{?8=88Q_1H$?s6pp>TA$PL0aQD*F79}iP(L>5va#>S?1jZaIm77cBmTUTH3=!-=4 zxh|xK|0N2m%6B zC341U#}+Uu+_`>X!Zti|Os5dt-VwCX!oa+K2e_T$HsQ zZ(<*b_*Bw7^XnqM3>EXCYZl?(< zLQu|T@stMG*cy--8QF+LR4+6w?GrAE+bb?TCbKonhYE6$emgx40k}9!1xeg)7sFfKb!zHo3TTWDk>yM2{ zKa9G*Z=_6cfh!ON zZ#a>c_#`^QSL-ZF6rTal^nN+!Q#%Q-PK-tw?Rj!$Y~zc5eMC;;dSYha)Q+JV6R@kEr^JnaP^4P;~x6UV()e$Z;m4)OOE58`Y4IX z+bnM0ij}wO)8CA!wjXMu(I+oaYI~q;pwpU#7n~8Bj9{P3Y&{n3Nj##-`szZ(4iSdi zpp!E#u6~uJX=saF%XktuCPbEO+|hQ!N+>+NctS-X56?|H+FNmN^G)?YcQ|$`LD-)f zsrRxD*6$WxsQ7q|_tW)XTJdpU;@HTN^d)k%1ZUL02upB?OVX@OzNs#avApZdJ1(W~ z$(aX$wC8~`cc(QAe9&JE#&AK-dfY)Hz^WeMxdrwoteSh|ugx!8?GrY1T9cooi=c|3 z1s#)s z0;hMn#=xLyBlDgpq#ghLuKhkLJaJojQ%MG5$-}7b`%h~WzRi2=-o3rE{vJyCzWW>+ z(OBGjyZ1?Y!3DCG=Ou1wimf(#QQP$M_t{s68om_#`*Q`B7vr?$qDM z&htp+LX6W$CENuHbshlNS(uJQaOzKu3CI{<3UMRs6aVNf;41kL{N0$D`XDH8q2OvW z;Px~Ah3fZEgC*@yO~+W1>vmy_=G~bGJl#+<_OtyZ=teY8FtrX-)Lky#r1fk!>VY4u zbECRW#~W)JgZUzu75&ZTgV^uzX>j2&`nH>~AHmaaBdU3@&@Z!(mUQ2b8hdQDJw2tF zgG(R8(BCWrk@6rCApCT}U~b3hVyYqW84Gfx8X%O*{4)gt`{N>2zddL83)QSY?hyCe zlliwn&R2Xdi-jUX{#;#3K$y1x8P})6d8lmb|7xO(!xVv!6r4-TK-C4lN`-rS6U)*Y zcwk?Yg;bl}AR<1(Jyv|yk{2e7=ME3%-#Rhf*yyA)(BFxbs|Dtxo>VBL)4vzyG6gW_ zAHDh&S2dMgF7+oU(FFwM@rG;Ht`*yITf92l#AV=HF?^@|{wqar?&xaSjcaox6aP4D z+#hv62DbrhxgizqFrdf9-UOzqU^&1bt3QlyUGOu!yTAEnoj#@wt(-r(>^vO?=bGkR zeyYLp5mLn;u71_@p=|NgT3W4bKl!*k^A95t_KFTS!-C%26NvaFuKR(qGYyvWv!D-4 zWz!GP`De`QcFbZT&Y2aXU%W2JG`i_lpBS4F~ zD5lMiai`5f@6AkwH`*zX{n1PK!ROfX_!OQfq}^moZVG6B@Jpz5uSv`|*Y@a!J4evC z<;&iz4_Wck9Etu$eYd2=3Yv_}uMNm;24%avJKS7F4kdZZ0eVmu16ITLB;G9!4BZDH z=PCwiw`-zrN4KM=C!P;<3QkCTyR?)=Rl1FvS07bbmz>G}!;;bK@HxC^aBf(2uQSm3 zFdWE;pqwq5H2DM)q2WZ3c{42I{EF`TZ^GMYo~xe_ME!60G;NFK$P&4Od~y0vSeN`- zow}>+z_p%}dF5K}7nJw5{_z(o1Fnr^#9XWOp>1xG6Q7n3%i|4>IaV${W_&|Z4fEoE p|3}6B&x-%Svi~EX|L+9!PLkH^N=8h#+xc|(qelb>9S=~&|2N0r#IXPX literal 0 HcmV?d00001 diff --git a/packages/vscode-moss/package-lock.json b/packages/vscode-moss/package-lock.json index 4fd216cb..e010d1ca 100644 --- a/packages/vscode-moss/package-lock.json +++ b/packages/vscode-moss/package-lock.json @@ -16,6 +16,7 @@ "@types/node": "^22.10.0", "@types/vscode": "^1.85.0", "@vscode/vsce": "^3.2.2", + "esbuild": "^0.27.2", "typescript": "^5.7.2" }, "engines": { @@ -243,6 +244,448 @@ "tslib": "^2.4.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@huggingface/jinja": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.6.tgz", @@ -2211,6 +2654,48 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "license": "MIT" }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json index a9e8b503..14a695f9 100644 --- a/packages/vscode-moss/package.json +++ b/packages/vscode-moss/package.json @@ -16,6 +16,11 @@ "categories": [ "Other" ], + "icon": "media/icon.png", + "galleryBanner": { + "color": "#2B1843", + "theme": "dark" + }, "type": "module", "main": "./out/extension.js", "activationEvents": [ @@ -45,10 +50,11 @@ } }, "scripts": { - "compile": "tsc -p ./", - "watch": "tsc -watch -p ./", + "check": "tsc --noEmit -p ./", + "compile": "node esbuild.config.mjs", + "watch": "node esbuild.config.mjs --watch", "package": "vsce package", - "vscode:prepublish": "npm run compile" + "vscode:prepublish": "npm run check && npm run compile" }, "dependencies": { "@inferedge-rest/moss": "^1.0.0-beta.3", @@ -58,6 +64,7 @@ "@types/node": "^22.10.0", "@types/vscode": "^1.85.0", "@vscode/vsce": "^3.2.2", + "esbuild": "^0.27.2", "typescript": "^5.7.2" } } diff --git a/packages/vscode-moss/tsconfig.json b/packages/vscode-moss/tsconfig.json index a4491503..b1ee69c6 100644 --- a/packages/vscode-moss/tsconfig.json +++ b/packages/vscode-moss/tsconfig.json @@ -3,13 +3,10 @@ "module": "NodeNext", "moduleResolution": "NodeNext", "target": "ES2022", - "outDir": "out", - "rootDir": "src", "strict": true, "lib": ["ES2022"], - "sourceMap": true, "skipLibCheck": true, - "noEmitOnError": true + "noEmit": true }, "include": ["src/**/*.ts"] } From a2c2245147d5e4b04deededdcfae3918a28b9815 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Sat, 4 Apr 2026 15:20:38 -0400 Subject: [PATCH 03/21] feat(vscode-moss) phase 4 core modules --- packages/vscode-moss/media/moss-icon.svg | 5 + packages/vscode-moss/package.json | 117 +++++++++- packages/vscode-moss/src/chunking.ts | 139 ++++++++++++ packages/vscode-moss/src/config.ts | 141 ++++++++++++ packages/vscode-moss/src/extension.ts | 214 +++++++++++++----- packages/vscode-moss/src/mossClients.ts | 11 + packages/vscode-moss/src/paths.ts | 52 +++++ .../vscode-moss/src/searchViewProvider.ts | 140 ++++++++++++ packages/vscode-moss/src/types.ts | 28 +++ 9 files changed, 788 insertions(+), 59 deletions(-) create mode 100644 packages/vscode-moss/media/moss-icon.svg create mode 100644 packages/vscode-moss/src/chunking.ts create mode 100644 packages/vscode-moss/src/config.ts create mode 100644 packages/vscode-moss/src/mossClients.ts create mode 100644 packages/vscode-moss/src/paths.ts create mode 100644 packages/vscode-moss/src/searchViewProvider.ts create mode 100644 packages/vscode-moss/src/types.ts diff --git a/packages/vscode-moss/media/moss-icon.svg b/packages/vscode-moss/media/moss-icon.svg new file mode 100644 index 00000000..94617ae4 --- /dev/null +++ b/packages/vscode-moss/media/moss-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json index 14a695f9..15424bbf 100644 --- a/packages/vscode-moss/package.json +++ b/packages/vscode-moss/package.json @@ -23,28 +23,135 @@ }, "type": "module", "main": "./out/extension.js", - "activationEvents": [ - "onCommand:moss.spikeConnectivity" - ], + "activationEvents": [], "contributes": { "commands": [ + { + "command": "moss.indexWorkspace", + "title": "Moss: Index Workspace" + }, + { + "command": "moss.search", + "title": "Moss: Search" + }, + { + "command": "moss.configureCredentials", + "title": "Moss: Configure credentials" + }, + { + "command": "moss.setApiKey", + "title": "Moss: Set API Key" + }, { "command": "moss.spikeConnectivity", "title": "Moss: Run Phase 1 connectivity spike" } ], + "viewsContainers": { + "activitybar": [ + { + "id": "mossContainer", + "title": "Moss", + "icon": "media/moss-icon.svg" + } + ] + }, + "views": { + "mossContainer": [ + { + "type": "webview", + "id": "moss.searchView", + "name": "Search" + } + ] + }, "configuration": { "title": "Moss", "properties": { "moss.projectId": { "type": "string", "default": "", - "description": "Moss project ID (optional if MOSS_PROJECT_ID is set in the environment)." + "description": "Moss project ID (required). Also accepted via MOSS_PROJECT_ID environment variable." }, "moss.projectKey": { "type": "string", "default": "", - "description": "Moss project key (optional if MOSS_PROJECT_KEY is set in the environment)." + "description": "Moss project key. Prefer 'Moss: Configure credentials' or 'Moss: Set API Key' for secure storage. Also accepted via MOSS_PROJECT_KEY environment variable." + }, + "moss.indexName": { + "type": "string", + "default": "", + "description": "Moss index name for this workspace. Leave empty to auto-generate from the workspace name.", + "scope": "resource" + }, + "moss.modelId": { + "type": "string", + "default": "moss-minilm", + "description": "Embedding model ID used when creating a Moss index." + }, + "moss.includeGlob": { + "type": [ + "string", + "array" + ], + "items": { + "type": "string" + }, + "default": "**/*", + "description": "Glob pattern(s) for files to include when indexing the workspace.", + "scope": "resource" + }, + "moss.excludeGlob": { + "type": [ + "string", + "array" + ], + "items": { + "type": "string" + }, + "default": [ + "**/node_modules/**", + "**/.git/**", + "**/dist/**", + "**/out/**", + "**/.next/**", + "**/build/**" + ], + "description": "Glob pattern(s) for files to exclude when indexing (merged with built-in defaults).", + "scope": "resource" + }, + "moss.maxFileSizeBytes": { + "type": "number", + "default": 1048576, + "description": "Maximum file size in bytes to index (default 1 MB). Larger files are skipped." + }, + "moss.topK": { + "type": "number", + "default": 10, + "description": "Number of results to return for each search query." + }, + "moss.queryMode": { + "type": "string", + "enum": [ + "local", + "cloud" + ], + "default": "local", + "description": "Query mode: 'local' downloads the index for fast in-process search; 'cloud' queries the Moss API directly.", + "enumDescriptions": [ + "Download index and query in-process (fast, recommended)", + "Query the Moss cloud API (higher latency, no local cache)" + ] + }, + "moss.chunkMaxLines": { + "type": "number", + "default": 100, + "description": "Maximum number of lines per chunk when indexing files." + }, + "moss.chunkOverlapLines": { + "type": "number", + "default": 12, + "description": "Number of overlapping lines between consecutive chunks." } } } diff --git a/packages/vscode-moss/src/chunking.ts b/packages/vscode-moss/src/chunking.ts new file mode 100644 index 00000000..64431a05 --- /dev/null +++ b/packages/vscode-moss/src/chunking.ts @@ -0,0 +1,139 @@ +import type { MossDocument, MossMetadata } from "./types.js"; + +const DEFAULT_MAX_CHARS = 12_000; +const DEFAULT_SMALL_FILE_LINES = 50; + +export interface ChunkOptions { + chunkMaxLines: number; + chunkOverlapLines: number; + /** Upper bound on embedded text length per chunk (Phase 0: ~12k). */ + maxCharsPerChunk?: number; + /** If total lines ≤ this, emit a single chunk for the whole file. */ + smallFileMaxLines?: number; + workspaceFolderIndex?: number; + workspaceFolderName?: string; +} + +function normalizeRelativePath(relativePath: string): string { + return relativePath.replace(/\\/g, "/"); +} + +function joinLines(lines: string[], startIdx: number, endIdxExclusive: number): string { + return lines.slice(startIdx, endIdxExclusive).join("\n"); +} + +function truncateToMaxChars( + lines: string[], + startIdx: number, + endIdxExclusive: number, + maxChars: number +): { text: string; endIdxExclusive: number } { + let end = endIdxExclusive; + let text = joinLines(lines, startIdx, end); + while (text.length > maxChars && end > startIdx + 1) { + end -= 1; + text = joinLines(lines, startIdx, end); + } + if (text.length > maxChars && end === startIdx + 1) { + const line = lines[startIdx] ?? ""; + text = line.slice(0, maxChars); + } + return { text, endIdxExclusive: end }; +} + +function buildMetadata( + pathNorm: string, + startLine1: number, + endLine1: number, + options: ChunkOptions +): MossMetadata { + const meta: MossMetadata = { + path: pathNorm, + startLine: String(startLine1), + endLine: String(endLine1), + }; + if (options.workspaceFolderIndex !== undefined) { + meta.workspaceFolderIndex = String(options.workspaceFolderIndex); + } + if (options.workspaceFolderName !== undefined) { + meta.workspaceFolderName = options.workspaceFolderName; + } + return meta; +} + +/** + * Split file text into Moss documents with stable ids `path:startLine-endLine`. + * Line numbers are 1-based inclusive in metadata. Pure — no VS Code API. + */ +export function chunkFileContent( + relativePath: string, + text: string, + options: ChunkOptions +): MossDocument[] { + const pathNorm = normalizeRelativePath(relativePath); + const lines = text.split(/\r?\n/); + const total = lines.length; + + const maxLines = Math.max(1, options.chunkMaxLines); + let overlap = Math.max(0, options.chunkOverlapLines); + if (overlap >= maxLines) { + overlap = Math.max(0, maxLines - 1); + } + const maxChars = options.maxCharsPerChunk ?? DEFAULT_MAX_CHARS; + const smallMax = options.smallFileMaxLines ?? DEFAULT_SMALL_FILE_LINES; + + const docs: MossDocument[] = []; + + if (total === 0) { + docs.push({ + id: `${pathNorm}:1-1`, + text: "", + metadata: buildMetadata(pathNorm, 1, 1, options), + }); + return docs; + } + + if (total <= smallMax) { + const { text: body, endIdxExclusive } = truncateToMaxChars( + lines, + 0, + total, + maxChars + ); + const endLine = endIdxExclusive; + docs.push({ + id: `${pathNorm}:1-${endLine}`, + text: body, + metadata: buildMetadata(pathNorm, 1, endLine, options), + }); + return docs; + } + + let startLine = 1; + while (startLine <= total) { + const startIdx = startLine - 1; + let endLine = Math.min(total, startLine + maxLines - 1); + let endIdxExclusive = endLine; + + const { text: body, endIdxExclusive: trimmedEnd } = truncateToMaxChars( + lines, + startIdx, + endIdxExclusive, + maxChars + ); + endIdxExclusive = trimmedEnd; + endLine = endIdxExclusive; + + docs.push({ + id: `${pathNorm}:${startLine}-${endLine}`, + text: body, + metadata: buildMetadata(pathNorm, startLine, endLine, options), + }); + + if (endLine >= total) break; + const nextStart = Math.max(startLine + 1, endLine - overlap + 1); + startLine = nextStart; + } + + return docs; +} diff --git a/packages/vscode-moss/src/config.ts b/packages/vscode-moss/src/config.ts new file mode 100644 index 00000000..79976f23 --- /dev/null +++ b/packages/vscode-moss/src/config.ts @@ -0,0 +1,141 @@ +import * as vscode from "vscode"; + +export const MOSS_SECRET_KEY_PROJECT_KEY = "moss.projectKey"; + +export type MossQueryMode = "local" | "cloud"; + +export interface ResolvedConfig { + projectId: string | undefined; + projectKey: string | undefined; + indexName: string; + modelId: string; + includeGlobs: string[]; + excludeGlobs: string[]; + maxFileSizeBytes: number; + topK: number; + queryMode: MossQueryMode; + chunkMaxLines: number; + chunkOverlapLines: number; + workspaceFolder: vscode.WorkspaceFolder; +} + +function toStringArray(value: unknown, fallback: string[]): string[] { + if (Array.isArray(value)) { + return value.filter((x): x is string => typeof x === "string" && x.length > 0); + } + if (typeof value === "string" && value.trim() !== "") { + return [value.trim()]; + } + return fallback; +} + +function sanitizeIndexNameSegment(name: string): string { + const s = name + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+|-+$/g, "") + .slice(0, 40); + return s.length > 0 ? s : "workspace"; +} + +/** Default index name when `moss.indexName` is empty: `vscode-moss-`. */ +export function defaultIndexNameForFolder(folder: vscode.WorkspaceFolder): string { + return `vscode-moss-${sanitizeIndexNameSegment(folder.name)}`; +} + +/** + * Project key precedence: SecretStorage → `moss.projectKey` → `MOSS_PROJECT_KEY`. + */ +export async function resolveProjectKey( + secrets: vscode.SecretStorage, + cfg: vscode.WorkspaceConfiguration +): Promise { + const fromSecret = await secrets.get(MOSS_SECRET_KEY_PROJECT_KEY); + if (fromSecret?.trim()) return fromSecret.trim(); + + const fromCfg = cfg.get("projectKey")?.trim(); + if (fromCfg) return fromCfg; + + const fromEnv = process.env.MOSS_PROJECT_KEY?.trim(); + if (fromEnv) return fromEnv; + + return undefined; +} + +function resolveProjectId(cfg: vscode.WorkspaceConfiguration): string | undefined { + const fromCfg = cfg.get("projectId")?.trim(); + if (fromCfg) return fromCfg; + return process.env.MOSS_PROJECT_ID?.trim(); +} + +/** + * Global Moss credentials (unscoped config), same precedence as Phase 0 / extension spike. + */ +export async function resolveCredentials( + context: vscode.ExtensionContext +): Promise<{ projectId: string; projectKey: string } | undefined> { + const cfg = vscode.workspace.getConfiguration("moss"); + const projectId = resolveProjectId(cfg); + if (!projectId) return undefined; + + const projectKey = await resolveProjectKey(context.secrets, cfg); + if (!projectKey) return undefined; + + return { projectId, projectKey }; +} + +/** + * Moss settings + credentials for one workspace folder (`moss.*` scoped to that folder's URI). + */ +export async function getMossConfig( + secrets: vscode.SecretStorage, + folder: vscode.WorkspaceFolder +): Promise { + const cfg = vscode.workspace.getConfiguration("moss", folder.uri); + + const projectId = resolveProjectId(cfg); + const projectKey = await resolveProjectKey(secrets, cfg); + + const configuredIndex = cfg.get("indexName")?.trim(); + const indexName = + configuredIndex && configuredIndex.length > 0 + ? configuredIndex + : defaultIndexNameForFolder(folder); + + const modelId = cfg.get("modelId")?.trim() || "moss-minilm"; + + const includeGlobs = toStringArray(cfg.get("includeGlob"), ["**/*"]); + const defaultExcludes = [ + "**/node_modules/**", + "**/.git/**", + "**/dist/**", + "**/out/**", + "**/.next/**", + "**/build/**", + ]; + const excludeGlobs = toStringArray(cfg.get("excludeGlob"), defaultExcludes); + + const maxFileSizeBytes = cfg.get("maxFileSizeBytes") ?? 1_048_576; + const topK = cfg.get("topK") ?? 10; + + const modeRaw = cfg.get("queryMode"); + const queryMode: MossQueryMode = modeRaw === "cloud" ? "cloud" : "local"; + + const chunkMaxLines = cfg.get("chunkMaxLines") ?? 100; + const chunkOverlapLines = cfg.get("chunkOverlapLines") ?? 12; + + return { + projectId, + projectKey, + indexName, + modelId, + includeGlobs, + excludeGlobs, + maxFileSizeBytes, + topK, + queryMode, + chunkMaxLines, + chunkOverlapLines, + workspaceFolder: folder, + }; +} diff --git a/packages/vscode-moss/src/extension.ts b/packages/vscode-moss/src/extension.ts index 7429803e..2bd01d0c 100644 --- a/packages/vscode-moss/src/extension.ts +++ b/packages/vscode-moss/src/extension.ts @@ -1,10 +1,142 @@ import * as vscode from "vscode"; -import { MossRestClient } from "@inferedge-rest/moss"; -import { MossClient } from "@inferedge/moss"; +import { + MOSS_SECRET_KEY_PROJECT_KEY, + resolveCredentials, +} from "./config.js"; +import { createRestClient, createSdkClient } from "./mossClients.js"; +import { MossSearchViewProvider } from "./searchViewProvider.js"; + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +// ── Activation ─────────────────────────────────────────────────────── + +export function activate(context: vscode.ExtensionContext): void { + const log = vscode.window.createOutputChannel("Moss"); + + // Sidebar search view + const searchProvider = new MossSearchViewProvider(context.extensionUri); + context.subscriptions.push( + vscode.window.registerWebviewViewProvider( + MossSearchViewProvider.viewId, + searchProvider + ) + ); + + // moss.indexWorkspace (placeholder — implementation in Phase 5) + context.subscriptions.push( + vscode.commands.registerCommand("moss.indexWorkspace", async () => { + void vscode.window.showInformationMessage( + "Moss: Index Workspace is not yet implemented." + ); + }) + ); + + // moss.search — focus the sidebar search view + context.subscriptions.push( + vscode.commands.registerCommand("moss.search", async () => { + await vscode.commands.executeCommand("moss.searchView.focus"); + }) + ); + + // moss.configureCredentials — project ID → settings; project key → SecretStorage + context.subscriptions.push( + vscode.commands.registerCommand("moss.configureCredentials", async () => { + const cfg = vscode.workspace.getConfiguration("moss"); + const currentId = cfg.get("projectId")?.trim() ?? ""; + + const projectId = await vscode.window.showInputBox({ + title: "Moss", + prompt: "Project ID", + value: currentId, + ignoreFocusOut: true, + placeHolder: "Your Moss project id", + }); + if (projectId === undefined) return; + + const trimmedId = projectId.trim(); + if (!trimmedId) { + void vscode.window.showWarningMessage( + "Moss: Project ID is required. Nothing was saved." + ); + return; + } + + const projectKey = await vscode.window.showInputBox({ + title: "Moss", + prompt: "Project key", + password: true, + ignoreFocusOut: true, + placeHolder: "Leave empty to keep the existing key in secure storage", + }); + if (projectKey === undefined) return; + + const configTarget = + vscode.workspace.workspaceFolders && + vscode.workspace.workspaceFolders.length > 0 + ? vscode.ConfigurationTarget.Workspace + : vscode.ConfigurationTarget.Global; + + try { + await cfg.update("projectId", trimmedId, configTarget); + } catch (e: unknown) { + const msg = e instanceof Error ? e.message : String(e); + void vscode.window.showErrorMessage( + `Moss: Could not save project ID: ${msg}` + ); + return; + } + + if (projectKey !== "") { + await context.secrets.store(MOSS_SECRET_KEY_PROJECT_KEY, projectKey); + } + + void vscode.window.showInformationMessage( + projectKey !== "" + ? "Moss: Project ID saved to settings and project key saved to secure storage." + : "Moss: Project ID saved to settings. Project key unchanged." + ); + }) + ); + + // moss.setApiKey — store / clear project key via SecretStorage + context.subscriptions.push( + vscode.commands.registerCommand("moss.setApiKey", async () => { + const key = await vscode.window.showInputBox({ + prompt: "Enter your Moss project key", + password: true, + ignoreFocusOut: true, + placeHolder: "pk_…", + }); + if (key !== undefined) { + if (key === "") { + await context.secrets.delete(MOSS_SECRET_KEY_PROJECT_KEY); + void vscode.window.showInformationMessage( + "Moss project key removed from secure storage." + ); + } else { + await context.secrets.store(MOSS_SECRET_KEY_PROJECT_KEY, key); + void vscode.window.showInformationMessage( + "Moss project key saved to secure storage." + ); + } + } + }) + ); + + // moss.spikeConnectivity (Phase 1 — retained for dev testing) + registerSpikeCommand(context, log); + + context.subscriptions.push(log); +} + +export function deactivate(): void {} + +// ── Phase 1 spike command (temporary) ──────────────────────────────── const SPIKE_INDEX_NAME = "vscode-moss-phase1-spike"; const SPIKE_MODEL_ID = "moss-minilm"; -const OUTPUT_CHANNEL_ID = "moss-spike"; const SPIKE_DOCS = [ { @@ -24,32 +156,8 @@ const SPIKE_DOCS = [ }, ]; -function getCredentials(): { projectId: string; projectKey: string } | undefined { - const fromEnv = - process.env.MOSS_PROJECT_ID && process.env.MOSS_PROJECT_KEY - ? { - projectId: process.env.MOSS_PROJECT_ID, - projectKey: process.env.MOSS_PROJECT_KEY, - } - : undefined; - if (fromEnv) { - return fromEnv; - } - const cfg = vscode.workspace.getConfiguration("moss"); - const projectId = cfg.get("projectId")?.trim(); - const projectKey = cfg.get("projectKey")?.trim(); - if (projectId && projectKey) { - return { projectId, projectKey }; - } - return undefined; -} - -function sleep(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - async function tolerateDeleteIndex( - client: MossRestClient, + client: ReturnType, indexName: string, log: vscode.OutputChannel ): Promise { @@ -66,28 +174,28 @@ async function tolerateDeleteIndex( } } -export function activate(context: vscode.ExtensionContext): void { - const log = vscode.window.createOutputChannel(OUTPUT_CHANNEL_ID); - - const disposable = vscode.commands.registerCommand( - "moss.spikeConnectivity", - async () => { +function registerSpikeCommand( + context: vscode.ExtensionContext, + log: vscode.OutputChannel +): void { + context.subscriptions.push( + vscode.commands.registerCommand("moss.spikeConnectivity", async () => { log.clear(); log.show(true); log.appendLine("Moss Phase 1 spike — starting…"); - const creds = getCredentials(); + const creds = await resolveCredentials(context); if (!creds) { const msg = - "Missing Moss credentials. Set MOSS_PROJECT_ID and MOSS_PROJECT_KEY in the environment " + - "(e.g. launch.json for F5), or add moss.projectId / moss.projectKey in Settings."; + "Missing Moss credentials. Run 'Moss: Configure credentials', or use 'Moss: Set API Key' " + + "with moss.projectId in Settings, or set MOSS_PROJECT_ID and MOSS_PROJECT_KEY in the environment."; log.appendLine(msg); void vscode.window.showErrorMessage(msg); return; } - const rest = new MossRestClient(creds.projectId, creds.projectKey); - const sdk = new MossClient(creds.projectId, creds.projectKey); + const rest = createRestClient(creds.projectId, creds.projectKey); + const sdk = createSdkClient(creds.projectId, creds.projectKey); try { log.appendLine("Step 1: REST deleteIndex (tolerate missing)…"); @@ -100,7 +208,6 @@ export function activate(context: vscode.ExtensionContext): void { log.appendLine("Step 3: Brief pause for index readiness…"); await sleep(2500); - let localQueryMs: number | undefined; let localError: string | undefined; log.appendLine("Step 4: SDK loadIndex…"); @@ -109,12 +216,13 @@ export function activate(context: vscode.ExtensionContext): void { log.appendLine("loadIndex succeeded."); log.appendLine('Step 5: SDK query (local) — "refund policy"…'); - const localResult = await sdk.query(SPIKE_INDEX_NAME, "refund policy", { - topK: 2, - }); - localQueryMs = localResult.timeTakenInMs; + const localResult = await sdk.query( + SPIKE_INDEX_NAME, + "refund policy", + { topK: 2 } + ); log.appendLine( - `Local query: ${localResult.docs.length} docs in ${localQueryMs ?? "?"} ms` + `Local query: ${localResult.docs.length} docs in ${localResult.timeTakenInMs ?? "?"} ms` ); for (const d of localResult.docs) { log.appendLine( @@ -125,13 +233,15 @@ export function activate(context: vscode.ExtensionContext): void { localError = e instanceof Error ? e.message : String(e); log.appendLine(`loadIndex/query (local path) failed: ${localError}`); log.appendLine( - "Falling back to cloud query (no loadIndex) — see PHASE1_SPIKE.md if this persists." + "Falling back to cloud query — see PHASE1_SPIKE.md if this persists." ); log.appendLine('Step 5b: SDK query (cloud fallback) — "refund policy"…'); - const cloudResult = await sdk.query(SPIKE_INDEX_NAME, "refund policy", { - topK: 2, - }); + const cloudResult = await sdk.query( + SPIKE_INDEX_NAME, + "refund policy", + { topK: 2 } + ); log.appendLine( `Cloud query: ${cloudResult.docs.length} docs in ${cloudResult.timeTakenInMs ?? "?"} ms` ); @@ -153,10 +263,6 @@ export function activate(context: vscode.ExtensionContext): void { log.appendLine(`SPIKE FAILED: ${msg}`); void vscode.window.showErrorMessage(`Moss spike failed: ${msg}`); } - } + }) ); - - context.subscriptions.push(disposable, log); } - -export function deactivate(): void {} diff --git a/packages/vscode-moss/src/mossClients.ts b/packages/vscode-moss/src/mossClients.ts new file mode 100644 index 00000000..9b3f27a8 --- /dev/null +++ b/packages/vscode-moss/src/mossClients.ts @@ -0,0 +1,11 @@ +import { MossRestClient } from "@inferedge-rest/moss"; +import { MossClient } from "@inferedge/moss"; + +/** Thin factory for tests and to keep Moss imports in one place. */ +export function createRestClient(projectId: string, projectKey: string): MossRestClient { + return new MossRestClient(projectId, projectKey); +} + +export function createSdkClient(projectId: string, projectKey: string): MossClient { + return new MossClient(projectId, projectKey); +} diff --git a/packages/vscode-moss/src/paths.ts b/packages/vscode-moss/src/paths.ts new file mode 100644 index 00000000..1dc820d0 --- /dev/null +++ b/packages/vscode-moss/src/paths.ts @@ -0,0 +1,52 @@ +import * as vscode from "vscode"; +import type { MossMetadata } from "./types.js"; + +function parsePositiveInt(s: string | undefined, fallback: number): number { + if (s === undefined || s === "") return fallback; + const n = parseInt(s, 10); + return Number.isFinite(n) && n > 0 ? n : fallback; +} + +/** 0-based folder index; missing or invalid → 0. */ +function parseWorkspaceFolderIndex(s: string | undefined): number { + if (s === undefined || s === "") return 0; + const n = parseInt(s, 10); + if (!Number.isFinite(n) || n < 0) return 0; + return n; +} + +/** + * Resolve workspace-relative `metadata.path` to a file URI using `workspaceFolderIndex` + * (0-based; default 0). Returns `undefined` if the folder index is out of range or path looks unsafe. + */ +export function metadataToUri( + workspaceFolders: readonly vscode.WorkspaceFolder[] | undefined, + metadata: MossMetadata +): vscode.Uri | undefined { + if (!workspaceFolders?.length) return undefined; + + const idx = parseWorkspaceFolderIndex(metadata.workspaceFolderIndex); + if (idx >= workspaceFolders.length) return undefined; + + const rel = metadata.path?.replace(/\\/g, "/") ?? ""; + if (rel === "" || rel.startsWith("/")) return undefined; + + const segments = rel.split("/").filter((p) => p.length > 0); + if (segments.some((p) => p === "..")) return undefined; + + const root = workspaceFolders[idx]!.uri; + return segments.length === 0 ? root : vscode.Uri.joinPath(root, ...segments); +} + +/** + * Map 1-based inclusive line metadata to a VS Code `Range` (0-based lines). + */ +export function metadataToRange(metadata: MossMetadata): vscode.Range { + const startLine = parsePositiveInt(metadata.startLine, 1); + let endLine = parsePositiveInt(metadata.endLine, startLine); + if (endLine < startLine) endLine = startLine; + + const start = startLine - 1; + const end = endLine - 1; + return new vscode.Range(start, 0, end, Number.MAX_SAFE_INTEGER); +} diff --git a/packages/vscode-moss/src/searchViewProvider.ts b/packages/vscode-moss/src/searchViewProvider.ts new file mode 100644 index 00000000..fedb53cd --- /dev/null +++ b/packages/vscode-moss/src/searchViewProvider.ts @@ -0,0 +1,140 @@ +import * as vscode from "vscode"; + +export class MossSearchViewProvider implements vscode.WebviewViewProvider { + public static readonly viewId = "moss.searchView"; + + private _view?: vscode.WebviewView; + + constructor(private readonly _extensionUri: vscode.Uri) {} + + public resolveWebviewView( + webviewView: vscode.WebviewView, + _context: vscode.WebviewViewResolveContext, + _token: vscode.CancellationToken + ): void { + this._view = webviewView; + + webviewView.webview.options = { + enableScripts: true, + localResourceRoots: [this._extensionUri], + }; + + webviewView.webview.html = this._getHtml(webviewView.webview); + + webviewView.webview.onDidReceiveMessage((message) => { + switch (message.type) { + case "query": + void vscode.window.showInformationMessage( + `Moss search for "${message.text}" — query execution not yet implemented.` + ); + break; + case "openResult": + break; + } + }); + } + + private _getHtml(webview: vscode.Webview): string { + const nonce = getNonce(); + + return /* html */ ` + + + + + + + + + +
+

+ Run Moss: Index Workspace to index your files,
+ then search here. +

+
+ + +`; + } +} + +function getNonce(): string { + const chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let result = ""; + for (let i = 0; i < 32; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; +} diff --git a/packages/vscode-moss/src/types.ts b/packages/vscode-moss/src/types.ts new file mode 100644 index 00000000..3deb9e4b --- /dev/null +++ b/packages/vscode-moss/src/types.ts @@ -0,0 +1,28 @@ +/** + * Moss REST/SDK documents use string-only metadata values. + */ +export type MossMetadata = Record; + +/** One chunk uploaded to Moss (aligned with @inferedge-rest/moss DocumentInfo). */ +export interface MossDocument { + id: string; + text: string; + metadata: MossMetadata; +} + +/** Chunk metadata we store for workspace indexing (all values are strings in Moss). */ +export interface ChunkMetadata { + path: string; + startLine: string; + endLine: string; + workspaceFolderIndex?: string; + workspaceFolderName?: string; +} + +/** Normalized search result for the webview / navigation (Phase 6–7). */ +export interface SearchHit { + id: string; + score: number; + text: string; + metadata: MossMetadata; +} From abb7ac5716bc456048f2eded916b4ee2493073bb Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Sat, 4 Apr 2026 15:31:17 -0400 Subject: [PATCH 04/21] index workspace working --- packages/vscode-moss/src/chunking.ts | 15 +- packages/vscode-moss/src/extension.ts | 6 +- packages/vscode-moss/src/indexWorkspace.ts | 414 +++++++++++++++++++++ 3 files changed, 428 insertions(+), 7 deletions(-) create mode 100644 packages/vscode-moss/src/indexWorkspace.ts diff --git a/packages/vscode-moss/src/chunking.ts b/packages/vscode-moss/src/chunking.ts index 64431a05..b7deb636 100644 --- a/packages/vscode-moss/src/chunking.ts +++ b/packages/vscode-moss/src/chunking.ts @@ -12,6 +12,10 @@ export interface ChunkOptions { smallFileMaxLines?: number; workspaceFolderIndex?: number; workspaceFolderName?: string; + /** + * Uniquifies doc ids across workspace roots (e.g. multi-root). Omitted for single-folder workspaces. + */ + chunkIdNamespace?: string; } function normalizeRelativePath(relativePath: string): string { @@ -84,9 +88,14 @@ export function chunkFileContent( const docs: MossDocument[] = []; + const idPrefix = + options.chunkIdNamespace !== undefined && options.chunkIdNamespace !== "" + ? `${options.chunkIdNamespace}:` + : ""; + if (total === 0) { docs.push({ - id: `${pathNorm}:1-1`, + id: `${idPrefix}${pathNorm}:1-1`, text: "", metadata: buildMetadata(pathNorm, 1, 1, options), }); @@ -102,7 +111,7 @@ export function chunkFileContent( ); const endLine = endIdxExclusive; docs.push({ - id: `${pathNorm}:1-${endLine}`, + id: `${idPrefix}${pathNorm}:1-${endLine}`, text: body, metadata: buildMetadata(pathNorm, 1, endLine, options), }); @@ -125,7 +134,7 @@ export function chunkFileContent( endLine = endIdxExclusive; docs.push({ - id: `${pathNorm}:${startLine}-${endLine}`, + id: `${idPrefix}${pathNorm}:${startLine}-${endLine}`, text: body, metadata: buildMetadata(pathNorm, startLine, endLine, options), }); diff --git a/packages/vscode-moss/src/extension.ts b/packages/vscode-moss/src/extension.ts index 2bd01d0c..01c1d215 100644 --- a/packages/vscode-moss/src/extension.ts +++ b/packages/vscode-moss/src/extension.ts @@ -3,6 +3,7 @@ import { MOSS_SECRET_KEY_PROJECT_KEY, resolveCredentials, } from "./config.js"; +import { runIndexWorkspace } from "./indexWorkspace.js"; import { createRestClient, createSdkClient } from "./mossClients.js"; import { MossSearchViewProvider } from "./searchViewProvider.js"; @@ -24,12 +25,9 @@ export function activate(context: vscode.ExtensionContext): void { ) ); - // moss.indexWorkspace (placeholder — implementation in Phase 5) context.subscriptions.push( vscode.commands.registerCommand("moss.indexWorkspace", async () => { - void vscode.window.showInformationMessage( - "Moss: Index Workspace is not yet implemented." - ); + await runIndexWorkspace(context, log); }) ); diff --git a/packages/vscode-moss/src/indexWorkspace.ts b/packages/vscode-moss/src/indexWorkspace.ts new file mode 100644 index 00000000..394d06df --- /dev/null +++ b/packages/vscode-moss/src/indexWorkspace.ts @@ -0,0 +1,414 @@ +import * as vscode from "vscode"; +import path from "node:path"; +import { getMossConfig, resolveCredentials } from "./config.js"; +import { chunkFileContent } from "./chunking.js"; +import { createRestClient, createSdkClient } from "./mossClients.js"; +import type { MossDocument } from "./types.js"; + +export const MOSS_LAST_INDEXED_KEY = "moss.lastIndexed"; + +export interface LastIndexedState { + indexName: string; + docCount: number; + fileCount: number; + timestamp: number; +} + +const MAX_FILE_SCAN = 80_000; +const MAX_MOSS_DOCUMENTS = 60_000; +const POST_CREATE_SETTLE_MS = 2500; + +/** Always applied on top of `moss.excludeGlob` (Phase 5 merge with safe defaults). */ +const EXTRA_SAFE_EXCLUDES = [ + "**/.svn/**", + "**/.hg/**", + "**/__pycache__/**", +]; + +const BINARY_EXT = new Set( + [ + ".zip", + ".tar", + ".gz", + ".tgz", + ".rar", + ".7z", + ".bz2", + ".xz", + ".png", + ".jpg", + ".jpeg", + ".gif", + ".webp", + ".ico", + ".bmp", + ".tif", + ".tiff", + ".heic", + ".pdf", + ".exe", + ".dll", + ".so", + ".dylib", + ".wasm", + ".mp3", + ".mp4", + ".mov", + ".avi", + ".mkv", + ".webm", + ".wmv", + ".bin", + ".sqlite", + ".sqlite3", + ".db", + ".woff", + ".woff2", + ".ttf", + ".eot", + ".otf", + ".class", + ".jar", + ".pyc", + ".pyo", + ".o", + ".a", + ".lib", + ".obj", + ".ilk", + ".pdb", + ".dmg", + ".iso", + ".img", + ].map((e) => e.toLowerCase()) +); + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +function uniqueSorted(values: string[]): string[] { + return [...new Set(values.filter(Boolean))].sort((a, b) => a.localeCompare(b)); +} + +function toBraceGlob(patterns: string[]): string { + const u = uniqueSorted(patterns); + if (u.length === 0) return "**/*"; + if (u.length === 1) return u[0]!; + return `{${u.join(",")}}`; +} + +function canBraceCombine(patterns: string[]): boolean { + return patterns.every((p) => !/[{}]/.test(p) && !p.includes(",")); +} + +async function tolerateDeleteIndex( + client: ReturnType, + indexName: string, + log: vscode.OutputChannel +): Promise { + try { + await client.deleteIndex(indexName); + log.appendLine(`Deleted existing index "${indexName}" (if it existed).`); + } catch (err: unknown) { + const msg = err instanceof Error ? err.message : String(err); + if (/not found|does not exist/i.test(msg)) { + log.appendLine(`No existing index "${indexName}" to delete (ok).`); + } else { + log.appendLine(`deleteIndex warning: ${msg}`); + } + } +} + +function isBinaryExt(fsPath: string): boolean { + return BINARY_EXT.has(path.extname(fsPath).toLowerCase()); +} + +async function findWorkspaceFiles( + includeGlobs: string[], + excludeGlobs: string[], + maxFiles: number, + token: vscode.CancellationToken +): Promise<{ uris: vscode.Uri[]; scanTruncated: boolean }> { + const includes = uniqueSorted(includeGlobs.length > 0 ? includeGlobs : ["**/*"]); + const excludePat = + excludeGlobs.length > 0 ? toBraceGlob(uniqueSorted(excludeGlobs)) : null; + + const dedupe = new Set(); + const out: vscode.Uri[] = []; + + const addBatch = (batch: readonly vscode.Uri[]) => { + for (const u of batch) { + const k = u.toString(); + if (dedupe.has(k)) continue; + dedupe.add(k); + out.push(u); + } + }; + + if (includes.length === 1) { + const batch = await vscode.workspace.findFiles( + includes[0]!, + excludePat, + maxFiles + 1, + token + ); + addBatch(batch); + } else if (canBraceCombine(includes)) { + const batch = await vscode.workspace.findFiles( + `{${includes.join(",")}}`, + excludePat, + maxFiles + 1, + token + ); + addBatch(batch); + } else { + for (const inc of includes) { + if (token.isCancellationRequested) break; + const batch = await vscode.workspace.findFiles( + inc, + excludePat, + maxFiles + 1 - out.length, + token + ); + addBatch(batch); + if (out.length > maxFiles) break; + } + } + + const scanTruncated = out.length > maxFiles; + return { uris: out.slice(0, maxFiles), scanTruncated }; +} + +async function readUtf8Text(uri: vscode.Uri): Promise { + try { + const bytes = await vscode.workspace.fs.readFile(uri); + if (bytes.includes(0)) return undefined; + const dec = new TextDecoder("utf-8", { fatal: true }); + return dec.decode(bytes); + } catch { + return undefined; + } +} + +function formatError(e: unknown): string { + return e instanceof Error ? e.message : String(e); +} + +/** + * Full workspace reindex: discover files, chunk, REST deleteIndex + createIndex, optional loadIndex. + */ +export async function runIndexWorkspace( + context: vscode.ExtensionContext, + log: vscode.OutputChannel +): Promise { + const folders = vscode.workspace.workspaceFolders; + if (!folders?.length) { + void vscode.window.showErrorMessage( + "Moss: Open a folder or workspace before indexing." + ); + return; + } + + const creds = await resolveCredentials(context); + if (!creds) { + void vscode.window.showErrorMessage( + "Moss: Missing credentials. Run “Moss: Configure credentials” or set MOSS_PROJECT_ID / MOSS_PROJECT_KEY." + ); + return; + } + + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: "Moss: Indexing workspace", + cancellable: true, + }, + async (progress, token) => { + log.appendLine("Moss: Index workspace — starting…"); + + const primary = folders[0]!; + const cfg = await getMossConfig(context.secrets, primary); + + const excludeGlobs = uniqueSorted([ + ...EXTRA_SAFE_EXCLUDES, + ...cfg.excludeGlobs, + ]); + + progress.report({ message: "Scanning files…" }); + const { uris, scanTruncated } = await findWorkspaceFiles( + cfg.includeGlobs, + excludeGlobs, + MAX_FILE_SCAN, + token + ); + + if (token.isCancellationRequested) { + log.appendLine("Indexing cancelled (after scan)."); + return; + } + + if (scanTruncated) { + const msg = `File scan stopped at ${MAX_FILE_SCAN} files. Narrow moss.includeGlob or add moss.excludeGlob to index a smaller set.`; + log.appendLine(msg); + void vscode.window.showWarningMessage(`Moss: ${msg}`); + } + + log.appendLine(`Found ${uris.length} file(s) to consider.`); + + uris.sort((a, b) => a.fsPath.localeCompare(b.fsPath)); + + const allDocs: MossDocument[] = []; + let filesIndexed = 0; + let skippedSize = 0; + let skippedBinary = 0; + let skippedDecode = 0; + let decodeLogged = false; + + const total = uris.length; + for (let i = 0; i < uris.length; i++) { + if (token.isCancellationRequested) { + log.appendLine("Indexing cancelled while reading files."); + return; + } + + const uri = uris[i]!; + progress.report({ + message: `Reading files (${i + 1}/${total})…`, + increment: total > 0 ? 100 / total : 0, + }); + + const folder = vscode.workspace.getWorkspaceFolder(uri); + if (!folder) continue; + + const folderIndex = folders.indexOf(folder); + if (folderIndex < 0) continue; + + if (isBinaryExt(uri.fsPath)) { + skippedBinary += 1; + continue; + } + + let stat: vscode.FileStat; + try { + stat = await vscode.workspace.fs.stat(uri); + } catch { + continue; + } + + if (stat.size > cfg.maxFileSizeBytes) { + skippedSize += 1; + continue; + } + + const text = await readUtf8Text(uri); + + if (text === undefined) { + skippedDecode += 1; + if (!decodeLogged) { + log.appendLine( + "One or more files were skipped (invalid UTF-8 or binary content)." + ); + decodeLogged = true; + } + continue; + } + + const relativePath = vscode.workspace.asRelativePath(uri, false); + if (relativePath === "") continue; + + const chunks = chunkFileContent(relativePath, text, { + chunkMaxLines: cfg.chunkMaxLines, + chunkOverlapLines: cfg.chunkOverlapLines, + workspaceFolderIndex: folderIndex, + workspaceFolderName: folder.name, + chunkIdNamespace: + folders.length > 1 ? String(folderIndex) : undefined, + }); + + allDocs.push(...chunks); + filesIndexed += 1; + + if (allDocs.length >= MAX_MOSS_DOCUMENTS) { + log.appendLine( + `Chunk limit reached (${MAX_MOSS_DOCUMENTS}); remaining files are skipped.` + ); + void vscode.window.showWarningMessage( + `Moss: Index truncated at ${MAX_MOSS_DOCUMENTS} chunks. Narrow include patterns or raise the limit in code.` + ); + break; + } + } + + if (token.isCancellationRequested) { + log.appendLine("Indexing cancelled before upload."); + return; + } + + if (allDocs.length === 0) { + const msg = + "No indexable documents were produced (empty workspace, filters, or unsupported files)."; + log.appendLine(msg); + void vscode.window.showWarningMessage(`Moss: ${msg}`); + return; + } + + progress.report({ message: "Uploading index to Moss…", increment: 0 }); + + const rest = createRestClient(creds.projectId, creds.projectKey); + + try { + await tolerateDeleteIndex(rest, cfg.indexName, log); + if (token.isCancellationRequested) { + log.appendLine("Indexing cancelled before createIndex."); + return; + } + + await rest.createIndex(cfg.indexName, allDocs, cfg.modelId); + log.appendLine( + `createIndex completed (${allDocs.length} chunks from ${filesIndexed} file(s)).` + ); + } catch (e: unknown) { + const msg = formatError(e); + log.appendLine(`createIndex failed: ${msg}`); + void vscode.window.showErrorMessage(`Moss: Indexing failed: ${msg}`); + return; + } + + await context.workspaceState.update(MOSS_LAST_INDEXED_KEY, { + indexName: cfg.indexName, + docCount: allDocs.length, + fileCount: filesIndexed, + timestamp: Date.now(), + } satisfies LastIndexedState); + + log.appendLine( + `Skipped: ${skippedSize} over size cap, ${skippedBinary} by extension/binary, ${skippedDecode} decode/binary.` + ); + + if (cfg.queryMode === "local") { + progress.report({ message: "Preparing local search cache…" }); + await sleep(POST_CREATE_SETTLE_MS); + if (token.isCancellationRequested) { + void vscode.window.showInformationMessage( + "Moss: Index uploaded. Local cache warm-up was cancelled." + ); + return; + } + try { + const sdk = createSdkClient(creds.projectId, creds.projectKey); + await sdk.loadIndex(cfg.indexName); + log.appendLine("loadIndex completed (local query cache warmed)."); + } catch (e: unknown) { + log.appendLine( + `loadIndex after indexing failed (you can still search in cloud mode): ${formatError(e)}` + ); + } + } + + void vscode.window.showInformationMessage( + `Moss: Indexed ${filesIndexed} file(s) → ${allDocs.length} chunk(s) (“${cfg.indexName}”).` + ); + } + ); +} From 6f6cd7b1f88649061bf216cff8fe3e99c5037978 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Sat, 4 Apr 2026 16:35:26 -0400 Subject: [PATCH 05/21] feat(vscode-moss): working --- .github/workflows/ci.yml | 26 + .gitignore | 3 +- packages/vscode-moss/PHASE1_SPIKE.md | 20 - packages/vscode-moss/README.md | 101 +- packages/vscode-moss/package-lock.json | 1109 ++++++++++++++++- packages/vscode-moss/package.json | 23 +- packages/vscode-moss/src/config.ts | 7 +- packages/vscode-moss/src/extension.ts | 243 ++-- packages/vscode-moss/src/indexWorkspace.ts | 84 +- packages/vscode-moss/src/lastIndexed.ts | 9 + packages/vscode-moss/src/mossConstants.ts | 5 + packages/vscode-moss/src/mossLog.ts | 17 + packages/vscode-moss/src/mossQueryState.ts | 52 + packages/vscode-moss/src/mossStatusBar.ts | 77 ++ packages/vscode-moss/src/runMossQuery.ts | 139 +++ .../vscode-moss/src/searchViewProvider.ts | 341 ++++- packages/vscode-moss/test/chunking.test.ts | 84 ++ packages/vscode-moss/test/config.test.ts | 154 +++ packages/vscode-moss/test/mossClients.test.ts | 52 + packages/vscode-moss/test/paths.test.ts | 117 ++ packages/vscode-moss/test/vscode-stub.ts | 68 + packages/vscode-moss/vitest.config.ts | 17 + 22 files changed, 2480 insertions(+), 268 deletions(-) delete mode 100644 packages/vscode-moss/PHASE1_SPIKE.md create mode 100644 packages/vscode-moss/src/lastIndexed.ts create mode 100644 packages/vscode-moss/src/mossConstants.ts create mode 100644 packages/vscode-moss/src/mossLog.ts create mode 100644 packages/vscode-moss/src/mossQueryState.ts create mode 100644 packages/vscode-moss/src/mossStatusBar.ts create mode 100644 packages/vscode-moss/src/runMossQuery.ts create mode 100644 packages/vscode-moss/test/chunking.test.ts create mode 100644 packages/vscode-moss/test/config.test.ts create mode 100644 packages/vscode-moss/test/mossClients.test.ts create mode 100644 packages/vscode-moss/test/paths.test.ts create mode 100644 packages/vscode-moss/test/vscode-stub.ts create mode 100644 packages/vscode-moss/vitest.config.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6958aa0b..7fce73ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,6 +131,32 @@ jobs: working-directory: packages/vercel-sdk run: npm test + vscode-moss-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: packages/vscode-moss/package-lock.json + - name: Install dependencies + working-directory: packages/vscode-moss + run: npm ci + - name: Typecheck + working-directory: packages/vscode-moss + run: npm run check + - name: Unit tests + working-directory: packages/vscode-moss + run: npm test + - name: Compile extension bundle + working-directory: packages/vscode-moss + run: npm run compile + - name: Package VSIX (publishability check) + working-directory: packages/vscode-moss + run: npx vsce package --out /tmp/vscode-moss-ci.vsix + vitepress-plugin-test: runs-on: ubuntu-latest steps: diff --git a/.gitignore b/.gitignore index 01efc853..e5032206 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ venv/ *.egg-info .moss-cache -.docs/ \ No newline at end of file +.docs/ +.vscode/settings.json \ No newline at end of file diff --git a/packages/vscode-moss/PHASE1_SPIKE.md b/packages/vscode-moss/PHASE1_SPIKE.md deleted file mode 100644 index be046a88..00000000 --- a/packages/vscode-moss/PHASE1_SPIKE.md +++ /dev/null @@ -1,20 +0,0 @@ -# Phase 1 spike — extension host notes - -## Purpose - -Confirm that **`@inferedge-rest/moss`** and **`@inferedge/moss`** both work inside the **VS Code extension host** (Node, ESM). The spike creates a throwaway index **`vscode-moss-phase1-spike`**, runs **`loadIndex` + `query`**, and records any failure. - -## If `loadIndex` or local `query` fails - -1. Read the full error in **Output → Moss Spike**. -2. Common causes: Node ABI / native addon constraints in the host, WASM path differences, or network/proxy blocking the download step. -3. The spike **automatically retries** with **`query` only** (cloud path), matching the idea of a **`queryMode: cloud`** fallback described in the implementation plan. -4. For product defaults: if local query is **unreliable** in the host after investigation, ship with **`moss.queryMode` default `cloud`** until fixed; keep the REST + SDK split so switching back to **`local`** is a small change. - -## Index cleanup - -The spike **deletes** index `vscode-moss-phase1-spike` before recreating it each run. You can also remove it from the Moss dashboard if needed. - -## ESM - -This extension uses **`"type": "module"`** because both Moss packages ship as ESM. The compiled **`out/extension.js`** is emitted as ESM (`NodeNext`). diff --git a/packages/vscode-moss/README.md b/packages/vscode-moss/README.md index 3f2ca531..677a53aa 100644 --- a/packages/vscode-moss/README.md +++ b/packages/vscode-moss/README.md @@ -2,15 +2,87 @@ VS Code extension for **semantic codebase search** with [Moss](https://moss.dev). This package is under active development. -## Phase 1 — connectivity spike +**Distribution:** install from a **`.vsix`** file only — this extension is **not** published on the VS Code Marketplace. -The command **Moss: Run Phase 1 connectivity spike** validates, from the extension host: +## Install from VSIX -1. `@inferedge-rest/moss` — `deleteIndex` (tolerate missing) + `createIndex` with three tiny documents on index `vscode-moss-phase1-spike`. -2. `@inferedge/moss` — `loadIndex` + `query` (local path). -3. If `loadIndex` / local `query` fails, a **cloud `query` fallback** runs so you still see end-to-end behavior. Check **Output → Moss Spike** for details. +1. Build the VSIX (or use one attached to a release): -### Credentials + ```bash + cd packages/vscode-moss + npm ci + npm run check && npm run compile + npx vsce package + ``` + + This produces **`vscode-moss-0.0.1.vsix`** (or whatever version is in `package.json`) in the current directory. The file is **large** (~100MB+) because **`@inferedge/moss`** bundles local embedding dependencies. + +2. In VS Code or Cursor: **Extensions** → **`…`** (Views and More Actions) → **Install from VSIX…** → choose the `.vsix` file. + +3. Reload the window if prompted, then configure Moss (**Moss: Configure credentials** or settings / env) and use **Moss: Index Workspace** as usual. + +## Search your workspace + +1. Set credentials: **Moss: Configure credentials** (pick **Project ID and project key** or **Project key only**; in key-only mode, an empty field removes the stored key), or set **`moss.projectId`** / **`moss.projectKey`** in settings, or **`MOSS_PROJECT_ID`** / **`MOSS_PROJECT_KEY`** in the environment. +2. Run **Moss: Index Workspace** (crawl + chunk + upload to Moss). +3. Open the **Moss** icon in the activity bar → **Search**, or run **Moss: Search** from the Command Palette. Enter a query; click a result to jump to the file and line range. + +To change Moss options without opening Search, run **Moss: Open Settings** from the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`). + +Indexing and search logs go to **View → Output** → channel **Moss**. Set **`moss.logVerbose`** to `true` for step-by-step indexing and search logs (default is a shorter summary). + +The **status bar** shows **Moss: not indexed** or **Moss: indexed … ago** (when a folder is open). Click it to run **Moss: Index Workspace**. + +### Privacy + +File paths and file contents you index are sent to **Moss** (cloud) for embedding and storage in your project’s index. Queries are also processed by Moss. Do not index secrets or data you are not allowed to send to a third-party service. See [moss.dev](https://moss.dev) for product terms and security expectations. + +### Settings (`moss.*`) + +| Setting | Purpose | +|--------|---------| +| `projectId` / `projectKey` | Moss project credentials (key: prefer SecretStorage via commands). | +| `indexName` | Index name (default derived from workspace folder name). | +| `modelId` | Embedding model for `createIndex`. | +| `includeGlob` / `excludeGlob` | Which files to crawl when indexing. | +| `maxFileSizeBytes` | Skip larger files. | +| `topK` | Number of search hits. | +| `queryMode` | `local` (download index) vs `cloud` (API-only queries). | +| `chunkMaxLines` / `chunkOverlapLines` | Line-based chunking when indexing. | +| `logVerbose` | Extra lines in **Output → Moss**. | + +## Development + +### Automated tests + +From `packages/vscode-moss`: + +```bash +npm ci +npm run check # TypeScript +npm test # Vitest (chunking, paths, config, moss client factories) +npm run compile +``` + +### Manual QA (before release) + +Use the **Extension Development Host** (F5 from repo root or this package) with real Moss credentials. + +1. **Happy path:** Open a small test folder → configure credentials → **Moss: Index Workspace** → **Moss: Search** for text you know exists → click a result → editor jumps to the right file and range. +2. **Cancel indexing:** Start **Moss: Index Workspace** on a larger tree → cancel from the notification → confirm no crash; **Output → Moss** notes cancellation. +3. **Multi-root:** Open a workspace with two folders → index → search → open a hit from each root (paths resolve via `workspaceFolderIndex`). + +### Troubleshooting (`loadIndex` / local search) + +**Moss: Index Workspace** and sidebar search use the same **`@inferedge-rest/moss`** (upload) and **`@inferedge/moss`** (`loadIndex` + `query`) stack as the rest of the product. + +- If **`loadIndex`** or local **`query`** fails, read the error in **Output → Moss**. Common causes: Node / native addon constraints in the extension host, WASM path differences, or network/proxy blocking the index download. +- Search still runs **`query`** after a failed `loadIndex`; the SDK falls back to **cloud** query (same idea as setting **`moss.queryMode`** to **`cloud`**). +- If local mode is **unreliable** in your environment, use **`moss.queryMode`: `cloud`** in settings. + +This extension uses **`"type": "module"`** (ESM); **`out/extension.js`** is built as ESM (`NodeNext`). + +### Credentials (F5 / dev) Either: @@ -22,8 +94,8 @@ Either: 1. Open the **`moss` repository root** in VS Code. 2. **Terminal:** `cd packages/vscode-moss && npm install && npm run compile` (or rely on the watch task). 3. **Run and Debug** → **vscode-moss: Run Extension** (uses `packages/vscode-moss` as `extensionDevelopmentPath`). -4. In the Extension Development Host, **Command Palette** → **Moss: Run Phase 1 connectivity spike**. -5. Open **Output** panel → channel **Moss Spike** for the log. +4. In the Extension Development Host, use **Moss: Configure credentials**, **Moss: Index Workspace**, and **Moss: Search** as needed. +5. Open **Output** → channel **Moss** for logs. ### Run the extension (this folder only) @@ -41,15 +113,10 @@ npm run check && npm run compile npm run watch # optional during development ``` -### Package VSIX - -```bash -npm run check && npm run compile -npx vsce package -``` +### Package VSIX (build only) -The VSIX is still **large** (~100MB+) because **`@inferedge/moss`** pulls **`@huggingface/transformers`** and related assets for local embeddings. Bundling only shrinks **our** entry file; trimming install size further would need a different query architecture or upstream packaging changes. +Same as [Install from VSIX](#install-from-vsix) step 1. You can also run **`npm run package`** (`vsce package`), which triggers **`vscode:prepublish`** (check + compile) first. -**Marketplace:** `package.json` includes **`icon`** (`media/icon.png`, from the repo Moss logo) and **`galleryBanner`** for the listing. +Bundling only shrinks **our** entry file; the VSIX stays large because of **`@inferedge/moss`** / **`@huggingface/transformers`**. Trimming size further would need a different query architecture or upstream packaging changes. -See [PHASE1_SPIKE.md](./PHASE1_SPIKE.md) for `loadIndex` troubleshooting and default **`moss.queryMode`** guidance. +`package.json` still includes **`icon`** and **`galleryBanner`** for consistency if you ever list the extension elsewhere; they are not required for VSIX install. diff --git a/packages/vscode-moss/package-lock.json b/packages/vscode-moss/package-lock.json index e010d1ca..bf251784 100644 --- a/packages/vscode-moss/package-lock.json +++ b/packages/vscode-moss/package-lock.json @@ -17,7 +17,9 @@ "@types/vscode": "^1.85.0", "@vscode/vsce": "^3.2.2", "esbuild": "^0.27.2", - "typescript": "^5.7.2" + "typescript": "^5.7.2", + "vitest": "^3.2.4", + "vscode-uri": "^3.1.0" }, "engines": { "vscode": "^1.85.0" @@ -1209,6 +1211,13 @@ "node": ">=18.0.0" } }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1311,6 +1320,356 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "license": "BSD-3-Clause" }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@secretlint/config-creator": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/@secretlint/config-creator/-/config-creator-10.2.2.tgz", @@ -1582,6 +1941,31 @@ "@textlint/ast-node-types": "15.5.2" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.19.17", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", @@ -1627,6 +2011,121 @@ "node": ">=20.0.0" } }, + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@vscode/vsce": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.7.1.tgz", @@ -1898,6 +2397,16 @@ "dev": true, "license": "Python-2.0" }, + "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": { + "node": ">=12" + } + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -2088,6 +2597,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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": { + "node": ">=8" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -2119,6 +2638,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2136,6 +2672,16 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/cheerio": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", @@ -2329,6 +2875,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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": { + "node": ">=6" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -2619,6 +3175,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -2708,6 +3271,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -2719,6 +3292,16 @@ "node": ">=6" } }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2856,6 +3439,21 @@ "node": ">=14.14" } }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -3630,6 +4228,13 @@ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "license": "Apache-2.0" }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -3643,6 +4248,16 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/markdown-it": { "version": "14.1.1", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", @@ -3831,6 +4446,25 @@ "dev": true, "license": "ISC" }, + "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": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/napi-build-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", @@ -4179,6 +4813,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -4222,6 +4873,35 @@ "node": ">=4" } }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -4464,6 +5144,51 @@ "node": ">=8.0" } }, + "node_modules/rollup": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", + "fsevents": "~2.3.2" + } + }, "node_modules/run-applescript": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", @@ -4749,6 +5474,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -4842,6 +5574,16 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -4884,6 +5626,20 @@ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "license": "BSD-3-Clause" }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4960,6 +5716,26 @@ "node": ">=0.10.0" } }, + "node_modules/strip-literal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, "node_modules/structured-source": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", @@ -5145,6 +5921,98 @@ "url": "https://bevry.me/fund" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "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": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmp": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", @@ -5340,6 +6208,228 @@ "url": "https://bevry.me/fund" } }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -5380,6 +6470,23 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json index 15424bbf..c9da0f7f 100644 --- a/packages/vscode-moss/package.json +++ b/packages/vscode-moss/package.json @@ -1,7 +1,7 @@ { "name": "vscode-moss", "displayName": "Moss", - "description": "Semantic codebase search powered by Moss (development / Phase 1 spike).", + "description": "Semantic codebase search powered by Moss — index your workspace and search from the sidebar.", "version": "0.0.1", "publisher": "inferedge", "license": "BSD-2-Clause", @@ -39,12 +39,8 @@ "title": "Moss: Configure credentials" }, { - "command": "moss.setApiKey", - "title": "Moss: Set API Key" - }, - { - "command": "moss.spikeConnectivity", - "title": "Moss: Run Phase 1 connectivity spike" + "command": "moss.openSettings", + "title": "Moss: Open Settings" } ], "viewsContainers": { @@ -76,7 +72,7 @@ "moss.projectKey": { "type": "string", "default": "", - "description": "Moss project key. Prefer 'Moss: Configure credentials' or 'Moss: Set API Key' for secure storage. Also accepted via MOSS_PROJECT_KEY environment variable." + "description": "Moss project key. Prefer 'Moss: Configure credentials' (project key only) for secure storage. Also accepted via MOSS_PROJECT_KEY environment variable." }, "moss.indexName": { "type": "string", @@ -152,6 +148,11 @@ "type": "number", "default": 12, "description": "Number of overlapping lines between consecutive chunks." + }, + "moss.logVerbose": { + "type": "boolean", + "default": false, + "description": "When true, the Moss output channel includes extra detail for indexing and search (default is a short summary)." } } } @@ -160,6 +161,8 @@ "check": "tsc --noEmit -p ./", "compile": "node esbuild.config.mjs", "watch": "node esbuild.config.mjs --watch", + "test": "vitest run", + "test:watch": "vitest", "package": "vsce package", "vscode:prepublish": "npm run check && npm run compile" }, @@ -172,6 +175,8 @@ "@types/vscode": "^1.85.0", "@vscode/vsce": "^3.2.2", "esbuild": "^0.27.2", - "typescript": "^5.7.2" + "typescript": "^5.7.2", + "vitest": "^3.2.4", + "vscode-uri": "^3.1.0" } } diff --git a/packages/vscode-moss/src/config.ts b/packages/vscode-moss/src/config.ts index 79976f23..331ccc45 100644 --- a/packages/vscode-moss/src/config.ts +++ b/packages/vscode-moss/src/config.ts @@ -4,6 +4,11 @@ export const MOSS_SECRET_KEY_PROJECT_KEY = "moss.projectKey"; export type MossQueryMode = "local" | "cloud"; +/** When true, Moss output includes extra indexing / spike / search detail (Phase 8). */ +export function getMossLogVerbose(): boolean { + return vscode.workspace.getConfiguration("moss").get("logVerbose") === true; +} + export interface ResolvedConfig { projectId: string | undefined; projectKey: string | undefined; @@ -69,7 +74,7 @@ function resolveProjectId(cfg: vscode.WorkspaceConfiguration): string | undefine } /** - * Global Moss credentials (unscoped config), same precedence as Phase 0 / extension spike. + * Global Moss credentials (unscoped config), same precedence as Phase 0. */ export async function resolveCredentials( context: vscode.ExtensionContext diff --git a/packages/vscode-moss/src/extension.ts b/packages/vscode-moss/src/extension.ts index 01c1d215..df56be45 100644 --- a/packages/vscode-moss/src/extension.ts +++ b/packages/vscode-moss/src/extension.ts @@ -1,23 +1,26 @@ import * as vscode from "vscode"; import { MOSS_SECRET_KEY_PROJECT_KEY, - resolveCredentials, } from "./config.js"; import { runIndexWorkspace } from "./indexWorkspace.js"; -import { createRestClient, createSdkClient } from "./mossClients.js"; +import { MOSS_EXTENSION_SETTINGS_QUERY } from "./mossConstants.js"; +import { invalidateSearchSdkCache } from "./mossQueryState.js"; +import { registerMossStatusBar } from "./mossStatusBar.js"; import { MossSearchViewProvider } from "./searchViewProvider.js"; -function sleep(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - // ── Activation ─────────────────────────────────────────────────────── export function activate(context: vscode.ExtensionContext): void { const log = vscode.window.createOutputChannel("Moss"); + registerMossStatusBar(context); + // Sidebar search view - const searchProvider = new MossSearchViewProvider(context.extensionUri); + const searchProvider = new MossSearchViewProvider( + context.extensionUri, + context, + log + ); context.subscriptions.push( vscode.window.registerWebviewViewProvider( MossSearchViewProvider.viewId, @@ -31,16 +34,76 @@ export function activate(context: vscode.ExtensionContext): void { }) ); + context.subscriptions.push( + vscode.commands.registerCommand("moss.openSettings", async () => { + await vscode.commands.executeCommand( + "workbench.action.openSettings", + MOSS_EXTENSION_SETTINGS_QUERY + ); + }) + ); + // moss.search — focus the sidebar search view context.subscriptions.push( vscode.commands.registerCommand("moss.search", async () => { + await vscode.commands.executeCommand( + "workbench.view.extension.mossContainer" + ); await vscode.commands.executeCommand("moss.searchView.focus"); }) ); - // moss.configureCredentials — project ID → settings; project key → SecretStorage + // moss.configureCredentials — QuickPick: full setup (ID + key) or key-only (empty clears) context.subscriptions.push( vscode.commands.registerCommand("moss.configureCredentials", async () => { + type CredAction = "idAndKey" | "keyOnly"; + interface CredPick extends vscode.QuickPickItem { + action: CredAction; + } + const items: CredPick[] = [ + { + label: "Project ID and project key", + description: "Save project ID to settings; optionally set a new key", + action: "idAndKey", + }, + { + label: "Project key only", + description: "Update or clear the key in secure storage (empty input removes it)", + action: "keyOnly", + }, + ]; + const choice = await vscode.window.showQuickPick(items, { + title: "Moss", + placeHolder: "What do you want to configure?", + ignoreFocusOut: true, + }); + if (!choice) return; + + if (choice.action === "keyOnly") { + const key = await vscode.window.showInputBox({ + title: "Moss", + prompt: "Project key", + password: true, + ignoreFocusOut: true, + placeHolder: "Leave empty to remove the key from secure storage", + }); + if (key === undefined) return; + if (key === "") { + await context.secrets.delete(MOSS_SECRET_KEY_PROJECT_KEY); + invalidateSearchSdkCache(); + void vscode.window.showInformationMessage( + "Moss: Project key removed from secure storage." + ); + } else { + await context.secrets.store(MOSS_SECRET_KEY_PROJECT_KEY, key); + invalidateSearchSdkCache(); + void vscode.window.showInformationMessage( + "Moss: Project key saved to secure storage." + ); + } + return; + } + const cfg = vscode.workspace.getConfiguration("moss"); const currentId = cfg.get("projectId")?.trim() ?? ""; @@ -90,6 +153,8 @@ export function activate(context: vscode.ExtensionContext): void { await context.secrets.store(MOSS_SECRET_KEY_PROJECT_KEY, projectKey); } + invalidateSearchSdkCache(); + void vscode.window.showInformationMessage( projectKey !== "" ? "Moss: Project ID saved to settings and project key saved to secure storage." @@ -98,169 +163,7 @@ export function activate(context: vscode.ExtensionContext): void { }) ); - // moss.setApiKey — store / clear project key via SecretStorage - context.subscriptions.push( - vscode.commands.registerCommand("moss.setApiKey", async () => { - const key = await vscode.window.showInputBox({ - prompt: "Enter your Moss project key", - password: true, - ignoreFocusOut: true, - placeHolder: "pk_…", - }); - if (key !== undefined) { - if (key === "") { - await context.secrets.delete(MOSS_SECRET_KEY_PROJECT_KEY); - void vscode.window.showInformationMessage( - "Moss project key removed from secure storage." - ); - } else { - await context.secrets.store(MOSS_SECRET_KEY_PROJECT_KEY, key); - void vscode.window.showInformationMessage( - "Moss project key saved to secure storage." - ); - } - } - }) - ); - - // moss.spikeConnectivity (Phase 1 — retained for dev testing) - registerSpikeCommand(context, log); - context.subscriptions.push(log); } export function deactivate(): void {} - -// ── Phase 1 spike command (temporary) ──────────────────────────────── - -const SPIKE_INDEX_NAME = "vscode-moss-phase1-spike"; -const SPIKE_MODEL_ID = "moss-minilm"; - -const SPIKE_DOCS = [ - { - id: "spike-1", - text: "Moss VS Code extension Phase 1 connectivity spike document about semantic search.", - metadata: { kind: "spike", idx: "1" }, - }, - { - id: "spike-2", - text: "Refunds are processed within three to five business days according to policy.", - metadata: { kind: "spike", idx: "2" }, - }, - { - id: "spike-3", - text: "The vector runtime downloads embeddings for local sub-millisecond queries.", - metadata: { kind: "spike", idx: "3" }, - }, -]; - -async function tolerateDeleteIndex( - client: ReturnType, - indexName: string, - log: vscode.OutputChannel -): Promise { - try { - await client.deleteIndex(indexName); - log.appendLine(`Deleted existing index "${indexName}" (if it existed).`); - } catch (err: unknown) { - const msg = err instanceof Error ? err.message : String(err); - if (/not found|does not exist/i.test(msg)) { - log.appendLine(`No existing index "${indexName}" to delete (ok).`); - } else { - log.appendLine(`deleteIndex warning: ${msg}`); - } - } -} - -function registerSpikeCommand( - context: vscode.ExtensionContext, - log: vscode.OutputChannel -): void { - context.subscriptions.push( - vscode.commands.registerCommand("moss.spikeConnectivity", async () => { - log.clear(); - log.show(true); - log.appendLine("Moss Phase 1 spike — starting…"); - - const creds = await resolveCredentials(context); - if (!creds) { - const msg = - "Missing Moss credentials. Run 'Moss: Configure credentials', or use 'Moss: Set API Key' " + - "with moss.projectId in Settings, or set MOSS_PROJECT_ID and MOSS_PROJECT_KEY in the environment."; - log.appendLine(msg); - void vscode.window.showErrorMessage(msg); - return; - } - - const rest = createRestClient(creds.projectId, creds.projectKey); - const sdk = createSdkClient(creds.projectId, creds.projectKey); - - try { - log.appendLine("Step 1: REST deleteIndex (tolerate missing)…"); - await tolerateDeleteIndex(rest, SPIKE_INDEX_NAME, log); - - log.appendLine("Step 2: REST createIndex with 3 documents…"); - await rest.createIndex(SPIKE_INDEX_NAME, SPIKE_DOCS, SPIKE_MODEL_ID); - log.appendLine("createIndex completed."); - - log.appendLine("Step 3: Brief pause for index readiness…"); - await sleep(2500); - - let localError: string | undefined; - - log.appendLine("Step 4: SDK loadIndex…"); - try { - await sdk.loadIndex(SPIKE_INDEX_NAME); - log.appendLine("loadIndex succeeded."); - - log.appendLine('Step 5: SDK query (local) — "refund policy"…'); - const localResult = await sdk.query( - SPIKE_INDEX_NAME, - "refund policy", - { topK: 2 } - ); - log.appendLine( - `Local query: ${localResult.docs.length} docs in ${localResult.timeTakenInMs ?? "?"} ms` - ); - for (const d of localResult.docs) { - log.appendLine( - ` - id=${d.id} score=${d.score.toFixed(4)} text=${d.text.slice(0, 80)}…` - ); - } - } catch (e: unknown) { - localError = e instanceof Error ? e.message : String(e); - log.appendLine(`loadIndex/query (local path) failed: ${localError}`); - log.appendLine( - "Falling back to cloud query — see PHASE1_SPIKE.md if this persists." - ); - - log.appendLine('Step 5b: SDK query (cloud fallback) — "refund policy"…'); - const cloudResult = await sdk.query( - SPIKE_INDEX_NAME, - "refund policy", - { topK: 2 } - ); - log.appendLine( - `Cloud query: ${cloudResult.docs.length} docs in ${cloudResult.timeTakenInMs ?? "?"} ms` - ); - for (const d of cloudResult.docs) { - log.appendLine( - ` - id=${d.id} score=${d.score.toFixed(4)} text=${d.text.slice(0, 80)}…` - ); - } - } - - const summary = - localError === undefined - ? "Moss Phase 1 spike succeeded (local loadIndex + query)." - : "Moss Phase 1 spike completed using cloud query fallback; check output for loadIndex error."; - log.appendLine(summary); - void vscode.window.showInformationMessage(summary); - } catch (e: unknown) { - const msg = e instanceof Error ? e.message : String(e); - log.appendLine(`SPIKE FAILED: ${msg}`); - void vscode.window.showErrorMessage(`Moss spike failed: ${msg}`); - } - }) - ); -} diff --git a/packages/vscode-moss/src/indexWorkspace.ts b/packages/vscode-moss/src/indexWorkspace.ts index 394d06df..b842dc34 100644 --- a/packages/vscode-moss/src/indexWorkspace.ts +++ b/packages/vscode-moss/src/indexWorkspace.ts @@ -2,18 +2,16 @@ import * as vscode from "vscode"; import path from "node:path"; import { getMossConfig, resolveCredentials } from "./config.js"; import { chunkFileContent } from "./chunking.js"; +import { + MOSS_LAST_INDEXED_KEY, + type LastIndexedState, +} from "./lastIndexed.js"; +import { mossLog } from "./mossLog.js"; +import { invalidateLoadedSearchIndex } from "./mossQueryState.js"; +import { notifyMossIndexed } from "./mossStatusBar.js"; import { createRestClient, createSdkClient } from "./mossClients.js"; import type { MossDocument } from "./types.js"; -export const MOSS_LAST_INDEXED_KEY = "moss.lastIndexed"; - -export interface LastIndexedState { - indexName: string; - docCount: number; - fileCount: number; - timestamp: number; -} - const MAX_FILE_SCAN = 80_000; const MAX_MOSS_DOCUMENTS = 60_000; const POST_CREATE_SETTLE_MS = 2500; @@ -109,13 +107,21 @@ async function tolerateDeleteIndex( ): Promise { try { await client.deleteIndex(indexName); - log.appendLine(`Deleted existing index "${indexName}" (if it existed).`); + mossLog( + log, + `Moss: Deleted existing index "${indexName}" (if it existed).`, + "verbose" + ); } catch (err: unknown) { const msg = err instanceof Error ? err.message : String(err); if (/not found|does not exist/i.test(msg)) { - log.appendLine(`No existing index "${indexName}" to delete (ok).`); + mossLog( + log, + `Moss: No existing index "${indexName}" to delete (ok).`, + "verbose" + ); } else { - log.appendLine(`deleteIndex warning: ${msg}`); + mossLog(log, `Moss: deleteIndex warning: ${msg}`); } } } @@ -225,7 +231,7 @@ export async function runIndexWorkspace( cancellable: true, }, async (progress, token) => { - log.appendLine("Moss: Index workspace — starting…"); + mossLog(log, "Moss: Index workspace — starting…"); const primary = folders[0]!; const cfg = await getMossConfig(context.secrets, primary); @@ -244,17 +250,17 @@ export async function runIndexWorkspace( ); if (token.isCancellationRequested) { - log.appendLine("Indexing cancelled (after scan)."); + mossLog(log, "Moss: Indexing cancelled (after scan)."); return; } if (scanTruncated) { const msg = `File scan stopped at ${MAX_FILE_SCAN} files. Narrow moss.includeGlob or add moss.excludeGlob to index a smaller set.`; - log.appendLine(msg); + mossLog(log, msg); void vscode.window.showWarningMessage(`Moss: ${msg}`); } - log.appendLine(`Found ${uris.length} file(s) to consider.`); + mossLog(log, `Moss: Found ${uris.length} file(s) to consider.`, "verbose"); uris.sort((a, b) => a.fsPath.localeCompare(b.fsPath)); @@ -268,7 +274,7 @@ export async function runIndexWorkspace( const total = uris.length; for (let i = 0; i < uris.length; i++) { if (token.isCancellationRequested) { - log.appendLine("Indexing cancelled while reading files."); + mossLog(log, "Moss: Indexing cancelled while reading files."); return; } @@ -306,8 +312,10 @@ export async function runIndexWorkspace( if (text === undefined) { skippedDecode += 1; if (!decodeLogged) { - log.appendLine( - "One or more files were skipped (invalid UTF-8 or binary content)." + mossLog( + log, + "Moss: One or more files were skipped (invalid UTF-8 or binary content).", + "verbose" ); decodeLogged = true; } @@ -330,8 +338,9 @@ export async function runIndexWorkspace( filesIndexed += 1; if (allDocs.length >= MAX_MOSS_DOCUMENTS) { - log.appendLine( - `Chunk limit reached (${MAX_MOSS_DOCUMENTS}); remaining files are skipped.` + mossLog( + log, + `Moss: Chunk limit reached (${MAX_MOSS_DOCUMENTS}); remaining files are skipped.` ); void vscode.window.showWarningMessage( `Moss: Index truncated at ${MAX_MOSS_DOCUMENTS} chunks. Narrow include patterns or raise the limit in code.` @@ -341,14 +350,14 @@ export async function runIndexWorkspace( } if (token.isCancellationRequested) { - log.appendLine("Indexing cancelled before upload."); + mossLog(log, "Moss: Indexing cancelled before upload."); return; } if (allDocs.length === 0) { const msg = "No indexable documents were produced (empty workspace, filters, or unsupported files)."; - log.appendLine(msg); + mossLog(log, msg); void vscode.window.showWarningMessage(`Moss: ${msg}`); return; } @@ -360,17 +369,19 @@ export async function runIndexWorkspace( try { await tolerateDeleteIndex(rest, cfg.indexName, log); if (token.isCancellationRequested) { - log.appendLine("Indexing cancelled before createIndex."); + mossLog(log, "Moss: Indexing cancelled before createIndex."); return; } await rest.createIndex(cfg.indexName, allDocs, cfg.modelId); - log.appendLine( - `createIndex completed (${allDocs.length} chunks from ${filesIndexed} file(s)).` + invalidateLoadedSearchIndex(); + mossLog( + log, + `Moss: createIndex finished — ${allDocs.length} chunks from ${filesIndexed} file(s), index “${cfg.indexName}”.` ); } catch (e: unknown) { const msg = formatError(e); - log.appendLine(`createIndex failed: ${msg}`); + mossLog(log, `Moss: createIndex failed: ${msg}`); void vscode.window.showErrorMessage(`Moss: Indexing failed: ${msg}`); return; } @@ -382,8 +393,12 @@ export async function runIndexWorkspace( timestamp: Date.now(), } satisfies LastIndexedState); - log.appendLine( - `Skipped: ${skippedSize} over size cap, ${skippedBinary} by extension/binary, ${skippedDecode} decode/binary.` + notifyMossIndexed(); + + mossLog( + log, + `Moss: Skipped while scanning — ${skippedSize} over size cap, ${skippedBinary} binary/ext, ${skippedDecode} decode/binary.`, + "verbose" ); if (cfg.queryMode === "local") { @@ -398,10 +413,15 @@ export async function runIndexWorkspace( try { const sdk = createSdkClient(creds.projectId, creds.projectKey); await sdk.loadIndex(cfg.indexName); - log.appendLine("loadIndex completed (local query cache warmed)."); + mossLog( + log, + "Moss: loadIndex completed (local query cache warmed).", + "verbose" + ); } catch (e: unknown) { - log.appendLine( - `loadIndex after indexing failed (you can still search in cloud mode): ${formatError(e)}` + mossLog( + log, + `Moss: loadIndex after indexing failed (try moss.queryMode "cloud"): ${formatError(e)}` ); } } diff --git a/packages/vscode-moss/src/lastIndexed.ts b/packages/vscode-moss/src/lastIndexed.ts new file mode 100644 index 00000000..8735f09d --- /dev/null +++ b/packages/vscode-moss/src/lastIndexed.ts @@ -0,0 +1,9 @@ +/** `workspaceState` key written after a successful **Moss: Index Workspace**. */ +export const MOSS_LAST_INDEXED_KEY = "moss.lastIndexed"; + +export interface LastIndexedState { + indexName: string; + docCount: number; + fileCount: number; + timestamp: number; +} diff --git a/packages/vscode-moss/src/mossConstants.ts b/packages/vscode-moss/src/mossConstants.ts new file mode 100644 index 00000000..ae943537 --- /dev/null +++ b/packages/vscode-moss/src/mossConstants.ts @@ -0,0 +1,5 @@ +/** + * Filter passed to `workbench.action.openSettings` for this extension. + * Must stay aligned with `publisher` + `name` in package.json (`inferedge` + `vscode-moss`). + */ +export const MOSS_EXTENSION_SETTINGS_QUERY = "@ext:inferedge.vscode-moss"; diff --git a/packages/vscode-moss/src/mossLog.ts b/packages/vscode-moss/src/mossLog.ts new file mode 100644 index 00000000..fbd350a2 --- /dev/null +++ b/packages/vscode-moss/src/mossLog.ts @@ -0,0 +1,17 @@ +import type * as vscode from "vscode"; +import { getMossLogVerbose } from "./config.js"; + +type LogSink = Pick; + +/** + * Append a line to the Moss output channel. Use **`verbose`** for optional detail when + * **`moss.logVerbose`** is enabled (Phase 8). + */ +export function mossLog( + sink: LogSink, + line: string, + level: "always" | "verbose" = "always" +): void { + if (level === "verbose" && !getMossLogVerbose()) return; + sink.appendLine(line); +} diff --git a/packages/vscode-moss/src/mossQueryState.ts b/packages/vscode-moss/src/mossQueryState.ts new file mode 100644 index 00000000..ed480bd0 --- /dev/null +++ b/packages/vscode-moss/src/mossQueryState.ts @@ -0,0 +1,52 @@ +import type { MossClient } from "@inferedge/moss"; +import { createSdkClient } from "./mossClients.js"; + +let cachedClient: + | { projectId: string; projectKey: string; client: MossClient } + | undefined; + +/** Which index `loadIndex` last completed successfully for `cachedClient` (local mode). */ +let loadedLocalIndexName: string | undefined; + +export function getOrCreateSdkClient( + projectId: string, + projectKey: string +): MossClient { + if ( + cachedClient?.projectId === projectId && + cachedClient.projectKey === projectKey + ) { + return cachedClient.client; + } + cachedClient = { + projectId, + projectKey, + client: createSdkClient(projectId, projectKey), + }; + loadedLocalIndexName = undefined; + return cachedClient.client; +} + +/** + * Drop the SDK instance (e.g. after API key changes). + */ +export function invalidateSearchSdkCache(): void { + cachedClient = undefined; + loadedLocalIndexName = undefined; +} + +/** + * Forget local `loadIndex` so the next local-mode search downloads again (e.g. after reindex). + */ +export function invalidateLoadedSearchIndex(): void { + loadedLocalIndexName = undefined; +} + +export async function ensureLocalIndexLoaded( + client: MossClient, + indexName: string +): Promise { + if (loadedLocalIndexName === indexName) return; + await client.loadIndex(indexName); + loadedLocalIndexName = indexName; +} diff --git a/packages/vscode-moss/src/mossStatusBar.ts b/packages/vscode-moss/src/mossStatusBar.ts new file mode 100644 index 00000000..1da42a05 --- /dev/null +++ b/packages/vscode-moss/src/mossStatusBar.ts @@ -0,0 +1,77 @@ +import * as vscode from "vscode"; +import { + MOSS_LAST_INDEXED_KEY, + type LastIndexedState, +} from "./lastIndexed.js"; + +const TICK_MS = 60_000; + +let refreshStatus: (() => void) | undefined; + +function formatIndexedAgo(timestamp: number): string { + const sec = Math.floor((Date.now() - timestamp) / 1000); + if (sec < 10) return "just now"; + if (sec < 60) return `${sec}s ago`; + const min = Math.floor(sec / 60); + if (min < 60) return `${min}m ago`; + const h = Math.floor(min / 60); + if (h < 48) return `${h}h ago`; + const d = Math.floor(h / 24); + return `${d}d ago`; +} + +/** + * Registers the status bar item (click → **Moss: Index Workspace**) and periodic refresh. + */ +export function registerMossStatusBar(context: vscode.ExtensionContext): void { + const item = vscode.window.createStatusBarItem( + vscode.StatusBarAlignment.Right, + 100 + ); + item.command = "moss.indexWorkspace"; + + const update = (): void => { + const folders = vscode.workspace.workspaceFolders; + if (!folders?.length) { + item.text = "$(search) Moss"; + item.tooltip = + "Moss semantic search — open a folder, then click to run Moss: Index Workspace."; + item.show(); + return; + } + + const state = context.workspaceState.get( + MOSS_LAST_INDEXED_KEY + ); + if (!state?.timestamp) { + item.text = "$(search) Moss: not indexed"; + item.tooltip = + "No Moss index for this workspace yet.\nClick to run Moss: Index Workspace."; + item.show(); + return; + } + + item.text = `$(search) Moss: indexed ${formatIndexedAgo(state.timestamp)}`; + item.tooltip = [ + `Last index: “${state.indexName}”`, + `${state.docCount} chunks · ${state.fileCount} files`, + "Click to run Moss: Index Workspace.", + ].join("\n"); + item.show(); + }; + + refreshStatus = update; + update(); + + const interval = setInterval(update, TICK_MS); + context.subscriptions.push( + { dispose: () => clearInterval(interval) }, + item, + vscode.workspace.onDidChangeWorkspaceFolders(() => update()) + ); +} + +/** Call after a successful index so “Xm ago” updates immediately. */ +export function notifyMossIndexed(): void { + refreshStatus?.(); +} diff --git a/packages/vscode-moss/src/runMossQuery.ts b/packages/vscode-moss/src/runMossQuery.ts new file mode 100644 index 00000000..57ac2cc9 --- /dev/null +++ b/packages/vscode-moss/src/runMossQuery.ts @@ -0,0 +1,139 @@ +import * as vscode from "vscode"; +import { getMossConfig, resolveCredentials } from "./config.js"; +import { + ensureLocalIndexLoaded, + getOrCreateSdkClient, +} from "./mossQueryState.js"; +import { mossLog } from "./mossLog.js"; +import type { SearchHit } from "./types.js"; + +export type SearchErrorCode = + | "NO_WORKSPACE" + | "NO_CREDENTIALS" + | "INDEX_NOT_FOUND" + | "QUERY_FAILED"; + +export interface SearchFailure { + code: SearchErrorCode; + message: string; +} + +function formatError(e: unknown): string { + return e instanceof Error ? e.message : String(e); +} + +function lineLabel(meta: Record): string { + const start = meta.startLine?.trim() ?? ""; + const end = meta.endLine?.trim() ?? ""; + if (start && end && start !== end) return `${start}–${end}`; + if (start) return start; + return "?"; +} + +/** + * Semantic search against the configured workspace index. + */ +export async function runMossQuery( + context: vscode.ExtensionContext, + queryText: string, + log: vscode.OutputChannel +): Promise< + | { ok: true; hits: SearchHit[]; timeMs?: number } + | { ok: false; error: SearchFailure } +> { + const folders = vscode.workspace.workspaceFolders; + if (!folders?.length) { + return { + ok: false, + error: { + code: "NO_WORKSPACE", + message: "Open a folder or workspace before searching.", + }, + }; + } + + const creds = await resolveCredentials(context); + if (!creds) { + return { + ok: false, + error: { + code: "NO_CREDENTIALS", + message: + "Missing Moss credentials. Run “Moss: Configure credentials” or set MOSS_PROJECT_ID / MOSS_PROJECT_KEY.", + }, + }; + } + + const primary = folders[0]!; + const cfg = await getMossConfig(context.secrets, primary); + const sdk = getOrCreateSdkClient(creds.projectId, creds.projectKey); + + if (cfg.queryMode === "local") { + try { + await ensureLocalIndexLoaded(sdk, cfg.indexName); + } catch (e: unknown) { + mossLog( + log, + `Moss: Search — loadIndex failed; continuing with cloud query. ${formatError(e)}`, + "verbose" + ); + } + } + + try { + const result = await sdk.query(cfg.indexName, queryText, { + topK: cfg.topK, + }); + + const hits: SearchHit[] = result.docs.map((d) => ({ + id: d.id, + score: d.score, + text: d.text, + metadata: { ...(d.metadata ?? {}) }, + })); + + return { ok: true, hits, timeMs: result.timeTakenInMs }; + } catch (e: unknown) { + const msg = formatError(e); + const lower = msg.toLowerCase(); + if ( + /not found|does not exist|no such index|unknown index|index.*missing/i.test( + lower + ) + ) { + return { + ok: false, + error: { + code: "INDEX_NOT_FOUND", + message: `Index “${cfg.indexName}” was not found. Run “Moss: Index Workspace” first.`, + }, + }; + } + return { + ok: false, + error: { code: "QUERY_FAILED", message: msg }, + }; + } +} + +export function hitToRowDto(hit: SearchHit): { + path: string; + lineLabel: string; + score: number; + snippet: string; +} { + const path = hit.metadata.path?.replace(/\\/g, "/") ?? hit.id; + const snippet = truncateSnippet(hit.text, 280); + return { + path, + lineLabel: lineLabel(hit.metadata), + score: hit.score, + snippet, + }; +} + +function truncateSnippet(text: string, maxLen: number): string { + const t = text.replace(/\s+/g, " ").trim(); + if (t.length <= maxLen) return t; + return `${t.slice(0, maxLen - 1)}…`; +} diff --git a/packages/vscode-moss/src/searchViewProvider.ts b/packages/vscode-moss/src/searchViewProvider.ts index fedb53cd..fd19f8b5 100644 --- a/packages/vscode-moss/src/searchViewProvider.ts +++ b/packages/vscode-moss/src/searchViewProvider.ts @@ -1,11 +1,20 @@ import * as vscode from "vscode"; +import { hitToRowDto, runMossQuery } from "./runMossQuery.js"; +import { metadataToRange, metadataToUri } from "./paths.js"; +import type { SearchHit } from "./types.js"; export class MossSearchViewProvider implements vscode.WebviewViewProvider { public static readonly viewId = "moss.searchView"; private _view?: vscode.WebviewView; + private _lastHits: SearchHit[] = []; + private _querySeq = 0; - constructor(private readonly _extensionUri: vscode.Uri) {} + constructor( + private readonly _extensionUri: vscode.Uri, + private readonly _context: vscode.ExtensionContext, + private readonly _log: vscode.OutputChannel + ) {} public resolveWebviewView( webviewView: vscode.WebviewView, @@ -24,25 +33,86 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { webviewView.webview.onDidReceiveMessage((message) => { switch (message.type) { case "query": - void vscode.window.showInformationMessage( - `Moss search for "${message.text}" — query execution not yet implemented.` - ); + if (typeof message.text === "string") { + void this._handleQuery(message.text.trim()); + } break; case "openResult": + if (typeof message.hitIndex === "number") { + void this._openHitAtIndex(message.hitIndex); + } + break; + case "openMossSettings": + void vscode.commands.executeCommand("moss.openSettings"); + break; + default: break; } }); } + private async _handleQuery(text: string): Promise { + const webview = this._view?.webview; + if (!webview) return; + + if (text === "") { + webview.postMessage({ + type: "error", + code: "QUERY_FAILED", + message: "Enter a search query.", + }); + return; + } + + const seq = ++this._querySeq; + webview.postMessage({ type: "loading", loading: true }); + webview.postMessage({ type: "clearError" }); + + const result = await runMossQuery(this._context, text, this._log); + + if (seq !== this._querySeq) return; + + webview.postMessage({ type: "loading", loading: false }); + + if (!result.ok) { + webview.postMessage({ + type: "error", + code: result.error.code, + message: result.error.message, + }); + return; + } + + this._lastHits = result.hits; + webview.postMessage({ + type: "results", + hits: result.hits.map((h, index) => ({ + index, + ...hitToRowDto(h), + })), + timeMs: result.timeMs, + }); + } + + private async _openHitAtIndex(hitIndex: number): Promise { + if (hitIndex < 0 || hitIndex >= this._lastHits.length) return; + const hit = this._lastHits[hitIndex]!; + await openSearchHit(hit); + } + private _getHtml(webview: vscode.Webview): string { const nonce = getNonce(); + const csp = [ + "default-src 'none'", + `style-src 'nonce-${nonce}' ${webview.cspSource}`, + `script-src 'nonce-${nonce}' ${webview.cspSource}`, + ].join("; "); return /* html */ ` - + @@ -101,34 +262,180 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { +
+
-

- Run Moss: Index Workspace to index your files,
- then search here. -

+
+

+ Run Moss: Index Workspace to index your files,
+ then search here. +

+

+ Open Moss settings +

+
+
`; } } +async function openSearchHit(hit: SearchHit): Promise { + const folders = vscode.workspace.workspaceFolders; + const uri = metadataToUri(folders, hit.metadata); + if (!uri) { + void vscode.window.showWarningMessage( + "Moss: Could not resolve file location for this result." + ); + return; + } + + try { + const doc = await vscode.workspace.openTextDocument(uri); + const editor = await vscode.window.showTextDocument(doc, { preview: true }); + const range = metadataToRange(hit.metadata); + const start = range.start; + editor.selection = new vscode.Selection(start, start); + editor.revealRange( + range, + vscode.TextEditorRevealType.InCenterIfOutsideViewport + ); + } catch (e: unknown) { + const msg = e instanceof Error ? e.message : String(e); + void vscode.window.showErrorMessage(`Moss: Could not open file: ${msg}`); + } +} + function getNonce(): string { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; diff --git a/packages/vscode-moss/test/chunking.test.ts b/packages/vscode-moss/test/chunking.test.ts new file mode 100644 index 00000000..678b96ff --- /dev/null +++ b/packages/vscode-moss/test/chunking.test.ts @@ -0,0 +1,84 @@ +import { describe, expect, it } from "vitest"; +import { chunkFileContent } from "../src/chunking.js"; + +describe("chunkFileContent", () => { + const baseOpts = { + chunkMaxLines: 10, + chunkOverlapLines: 2, + maxCharsPerChunk: 500, + smallFileMaxLines: 50, + }; + + it("returns one empty chunk for empty text", () => { + const docs = chunkFileContent("a.ts", "", baseOpts); + expect(docs).toHaveLength(1); + expect(docs[0]!.id).toBe("a.ts:1-1"); + expect(docs[0]!.text).toBe(""); + expect(docs[0]!.metadata.startLine).toBe("1"); + expect(docs[0]!.metadata.endLine).toBe("1"); + }); + + it("uses single chunk for small files (≤ smallFileMaxLines)", () => { + const lines = Array.from({ length: 20 }, (_, i) => `line ${i + 1}`); + const text = lines.join("\n"); + const docs = chunkFileContent("src/small.ts", text, baseOpts); + expect(docs).toHaveLength(1); + expect(docs[0]!.id).toBe("src/small.ts:1-20"); + expect(docs[0]!.metadata.path).toBe("src/small.ts"); + expect(docs[0]!.text.length).toBeLessThanOrEqual(500); + }); + + it("windows-style path is normalized in id and metadata", () => { + const docs = chunkFileContent("src\\win.ts", "one", baseOpts); + expect(docs[0]!.id.startsWith("src/win.ts:")).toBe(true); + expect(docs[0]!.metadata.path).toBe("src/win.ts"); + }); + + it("splits large files into overlapping windows", () => { + const lines = Array.from({ length: 30 }, (_, i) => `L${i + 1}`); + const text = lines.join("\n"); + const docs = chunkFileContent("big.txt", text, { + ...baseOpts, + smallFileMaxLines: 5, + }); + expect(docs.length).toBeGreaterThan(1); + const first = docs[0]!; + expect(first.metadata.startLine).toBe("1"); + expect(Number(first.metadata.endLine)).toBeLessThanOrEqual(10); + for (const d of docs) { + expect(d.text.length).toBeLessThanOrEqual(500); + expect(d.id).toMatch(/^big\.txt:\d+-\d+$/); + } + }); + + it("prefixes ids with chunkIdNamespace for multi-root", () => { + const docs = chunkFileContent("x.ts", "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk", { + ...baseOpts, + smallFileMaxLines: 3, + chunkIdNamespace: "1", + }); + expect(docs.every((d) => d.id.startsWith("1:"))).toBe(true); + }); + + it("includes workspace metadata when provided", () => { + const docs = chunkFileContent("f.ts", "x", { + ...baseOpts, + workspaceFolderIndex: 2, + workspaceFolderName: "backend", + }); + expect(docs[0]!.metadata.workspaceFolderIndex).toBe("2"); + expect(docs[0]!.metadata.workspaceFolderName).toBe("backend"); + }); + + it("clamps overlap when overlap >= chunkMaxLines", () => { + const lines = Array.from({ length: 25 }, (_, i) => `x${i}`); + const text = lines.join("\n"); + const docs = chunkFileContent("o.ts", text, { + chunkMaxLines: 5, + chunkOverlapLines: 99, + smallFileMaxLines: 5, + maxCharsPerChunk: 10_000, + }); + expect(docs.length).toBeGreaterThan(0); + }); +}); diff --git a/packages/vscode-moss/test/config.test.ts b/packages/vscode-moss/test/config.test.ts new file mode 100644 index 00000000..c5a3192d --- /dev/null +++ b/packages/vscode-moss/test/config.test.ts @@ -0,0 +1,154 @@ +import { afterEach, describe, expect, it } from "vitest"; +import type { SecretStorage, WorkspaceConfiguration } from "vscode"; +import { + MOSS_SECRET_KEY_PROJECT_KEY, + defaultIndexNameForFolder, + getMossConfig, + getMossLogVerbose, + resolveProjectKey, +} from "../src/config.js"; +import { + resetMossTestConfig, + setMossTestConfig, + Uri, + type WorkspaceFolder, +} from "./vscode-stub.js"; + +function memorySecrets(initial: Record = {}): SecretStorage { + const m = new Map(Object.entries(initial)); + return { + get: async (k) => m.get(k), + store: async (k, v) => { + m.set(k, v); + }, + delete: async (k) => { + m.delete(k); + }, + onDidChange: () => ({ dispose: () => {} }), + }; +} + +function cfgFrom(values: Record): WorkspaceConfiguration { + return { + get: (key: string) => values[key] as T, + has: () => false, + inspect: () => undefined, + update: async () => undefined, + }; +} + +describe("defaultIndexNameForFolder", () => { + it("sanitizes folder name into index segment", () => { + const f: WorkspaceFolder = { + uri: Uri.file("/x"), + name: "My Cool App!!!", + index: 0, + }; + expect(defaultIndexNameForFolder(f)).toBe("vscode-moss-my-cool-app"); + }); + + it("falls back when name sanitizes to empty", () => { + const f: WorkspaceFolder = { + uri: Uri.file("/x"), + name: "@@@", + index: 0, + }; + expect(defaultIndexNameForFolder(f)).toBe("vscode-moss-workspace"); + }); +}); + +describe("getMossLogVerbose", () => { + afterEach(() => { + resetMossTestConfig(); + }); + + it("is false by default", () => { + expect(getMossLogVerbose()).toBe(false); + }); + + it("is true when moss.logVerbose set", () => { + setMossTestConfig(undefined, { logVerbose: true }); + expect(getMossLogVerbose()).toBe(true); + }); +}); + +describe("resolveProjectKey", () => { + const prevKey = process.env.MOSS_PROJECT_KEY; + + afterEach(() => { + resetMossTestConfig(); + if (prevKey === undefined) delete process.env.MOSS_PROJECT_KEY; + else process.env.MOSS_PROJECT_KEY = prevKey; + }); + + it("prefers SecretStorage over settings and env", async () => { + process.env.MOSS_PROJECT_KEY = "env-key"; + const secrets = memorySecrets({ [MOSS_SECRET_KEY_PROJECT_KEY]: "secret-key" }); + const cfg = cfgFrom({ projectKey: "cfg-key" }); + expect(await resolveProjectKey(secrets, cfg)).toBe("secret-key"); + }); + + it("uses settings when no secret", async () => { + const secrets = memorySecrets(); + const cfg = cfgFrom({ projectKey: "cfg-key" }); + expect(await resolveProjectKey(secrets, cfg)).toBe("cfg-key"); + }); + + it("uses MOSS_PROJECT_KEY when no secret or cfg", async () => { + process.env.MOSS_PROJECT_KEY = "env-only"; + const secrets = memorySecrets(); + const cfg = cfgFrom({}); + expect(await resolveProjectKey(secrets, cfg)).toBe("env-only"); + }); + + it("returns undefined when nothing set", async () => { + delete process.env.MOSS_PROJECT_KEY; + const secrets = memorySecrets(); + const cfg = cfgFrom({}); + expect(await resolveProjectKey(secrets, cfg)).toBeUndefined(); + }); +}); + +describe("getMossConfig", () => { + afterEach(() => { + resetMossTestConfig(); + }); + + it("uses configured index name when set", async () => { + const ws = Uri.file("/repo"); + setMossTestConfig(ws.toString(), { + indexName: "my-custom-index", + projectId: "pid", + projectKey: "pk", + }); + const folder: WorkspaceFolder = { uri: ws, name: "repo", index: 0 }; + const c = await getMossConfig(memorySecrets(), folder); + expect(c.indexName).toBe("my-custom-index"); + expect(c.topK).toBe(10); + expect(c.queryMode).toBe("local"); + }); + + it("defaults index name from folder when indexName empty", async () => { + const ws = Uri.file("/repo"); + setMossTestConfig(ws.toString(), { + indexName: "", + projectId: "p", + projectKey: "k", + }); + const folder: WorkspaceFolder = { uri: ws, name: "alpha-beta", index: 0 }; + const c = await getMossConfig(memorySecrets(), folder); + expect(c.indexName).toBe("vscode-moss-alpha-beta"); + }); + + it("treats queryMode cloud only when exactly cloud", async () => { + const ws = Uri.file("/r"); + setMossTestConfig(ws.toString(), { + projectId: "p", + projectKey: "k", + queryMode: "cloud", + }); + const folder: WorkspaceFolder = { uri: ws, name: "r", index: 0 }; + const c = await getMossConfig(memorySecrets(), folder); + expect(c.queryMode).toBe("cloud"); + }); +}); diff --git a/packages/vscode-moss/test/mossClients.test.ts b/packages/vscode-moss/test/mossClients.test.ts new file mode 100644 index 00000000..59d6bec4 --- /dev/null +++ b/packages/vscode-moss/test/mossClients.test.ts @@ -0,0 +1,52 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +vi.mock("@inferedge-rest/moss", () => ({ + MossRestClient: vi.fn(), +})); + +vi.mock("@inferedge/moss", () => ({ + MossClient: vi.fn(), +})); + +import { MossClient } from "@inferedge/moss"; +import { MossRestClient } from "@inferedge-rest/moss"; +import { createRestClient, createSdkClient } from "../src/mossClients.js"; + +describe("mossClients factories", () => { + beforeEach(() => { + vi.mocked(MossRestClient).mockReset(); + vi.mocked(MossClient).mockReset(); + vi.mocked(MossRestClient).mockImplementation( + () => + ({ + deleteIndex: vi.fn().mockRejectedValue(new Error("network down")), + }) as unknown as InstanceType + ); + vi.mocked(MossClient).mockImplementation( + () => + ({ + loadIndex: vi.fn().mockResolvedValue("idx"), + }) as unknown as InstanceType + ); + }); + + it("createRestClient passes project id and key to MossRestClient", () => { + createRestClient("proj-1", "key-1"); + expect(MossRestClient).toHaveBeenCalledWith("proj-1", "key-1"); + }); + + it("createSdkClient passes project id and key to MossClient", () => { + createSdkClient("proj-2", "key-2"); + expect(MossClient).toHaveBeenCalledWith("proj-2", "key-2"); + }); + + it("rest client method errors propagate (wrapper is thin)", async () => { + const client = createRestClient("a", "b"); + await expect(client.deleteIndex("x")).rejects.toThrow("network down"); + }); + + it("sdk client returns mocked success path", async () => { + const client = createSdkClient("a", "b"); + await expect(client.loadIndex("i")).resolves.toBe("idx"); + }); +}); diff --git a/packages/vscode-moss/test/paths.test.ts b/packages/vscode-moss/test/paths.test.ts new file mode 100644 index 00000000..bb4f9321 --- /dev/null +++ b/packages/vscode-moss/test/paths.test.ts @@ -0,0 +1,117 @@ +import { describe, expect, it } from "vitest"; +import { Uri, type WorkspaceFolder } from "./vscode-stub.js"; +import { metadataToRange, metadataToUri } from "../src/paths.js"; + +function folder(fsPath: string, name = "ws"): WorkspaceFolder { + return { uri: Uri.file(fsPath), name, index: 0 }; +} + +describe("metadataToUri", () => { + it("joins path segments under workspace root", () => { + const roots = [folder("/projects/repo")]; + const u = metadataToUri(roots, { + path: "src/lib/foo.ts", + startLine: "1", + endLine: "5", + }); + expect(u).toBeDefined(); + expect(u!.fsPath.replace(/\\/g, "/")).toContain("src/lib/foo.ts"); + }); + + it("normalizes backslashes in metadata path", () => { + const roots = [folder("/ws")]; + const u = metadataToUri(roots, { + path: "pkg\\mod.go", + startLine: "1", + endLine: "1", + }); + expect(u).toBeDefined(); + expect(u!.fsPath.replace(/\\/g, "/")).toMatch(/pkg\/mod\.go$/); + }); + + it("uses workspaceFolderIndex for multi-root", () => { + const roots = [folder("/a", "A"), folder("/b", "B")]; + const u = metadataToUri(roots, { + path: "file.txt", + startLine: "1", + endLine: "1", + workspaceFolderIndex: "1", + }); + expect(u).toBeDefined(); + const expected = Uri.joinPath(roots[1]!.uri, "file.txt").toString(); + expect(u!.toString()).toBe(expected); + }); + + it("returns undefined for parent traversal", () => { + const roots = [folder("/ws")]; + expect( + metadataToUri(roots, { + path: "../etc/passwd", + startLine: "1", + endLine: "1", + }) + ).toBeUndefined(); + }); + + it("returns undefined for absolute-looking path", () => { + const roots = [folder("/ws")]; + expect( + metadataToUri(roots, { + path: "/abs/file.ts", + startLine: "1", + endLine: "1", + }) + ).toBeUndefined(); + }); + + it("returns undefined when folder index out of range", () => { + const roots = [folder("/only")]; + expect( + metadataToUri(roots, { + path: "x.ts", + startLine: "1", + endLine: "1", + workspaceFolderIndex: "9", + }) + ).toBeUndefined(); + }); + + it("returns undefined without workspace folders", () => { + expect( + metadataToUri(undefined, { + path: "a.ts", + startLine: "1", + endLine: "1", + }) + ).toBeUndefined(); + }); +}); + +describe("metadataToRange", () => { + it("maps 1-based inclusive lines to 0-based Range", () => { + const r = metadataToRange({ + path: "x", + startLine: "3", + endLine: "5", + }); + expect(r.start.line).toBe(2); + expect(r.end.line).toBe(4); + expect(r.start.character).toBe(0); + expect(r.end.character).toBe(Number.MAX_SAFE_INTEGER); + }); + + it("defaults missing startLine to line 1", () => { + const r = metadataToRange({ path: "x", startLine: "", endLine: "2" }); + expect(r.start.line).toBe(0); + }); + + it("repairs end before start", () => { + const r = metadataToRange({ + path: "x", + startLine: "10", + endLine: "3", + }); + expect(r.start.line).toBe(9); + expect(r.end.line).toBe(9); + }); +}); diff --git a/packages/vscode-moss/test/vscode-stub.ts b/packages/vscode-moss/test/vscode-stub.ts new file mode 100644 index 00000000..c191fe00 --- /dev/null +++ b/packages/vscode-moss/test/vscode-stub.ts @@ -0,0 +1,68 @@ +/** + * Minimal `vscode` surface for unit tests (Vitest resolves `vscode` here via alias). + * Supports `paths.ts`, `config.ts`, and any module that only needs Uri / Range / workspace config. + */ +import { URI, Utils } from "vscode-uri"; + +export class Position { + constructor( + public readonly line: number, + public readonly character: number + ) {} +} + +export class Range { + public readonly start: Position; + public readonly end: Position; + constructor(startLine: number, startChar: number, endLine: number, endChar: number) { + this.start = new Position(startLine, startChar); + this.end = new Position(endLine, endChar); + } +} + +export const Uri = { + file: (fsPath: string): URI => URI.file(fsPath), + joinPath: (base: URI, ...pathSegments: string[]): URI => + Utils.joinPath(base, ...pathSegments), +}; + +const mossConfigByScope = new Map>(); + +export function resetMossTestConfig(): void { + mossConfigByScope.clear(); +} + +/** Keys match `get("projectId")` etc. on the `moss` configuration section. */ +export function setMossTestConfig( + resourceUri: string | undefined, + values: Record +): void { + const key = resourceUri ?? "__global"; + const prev = mossConfigByScope.get(key) ?? {}; + mossConfigByScope.set(key, { ...prev, ...values }); +} + +function mergedMossConfig(resource?: { toString(): string }): Record { + const g = mossConfigByScope.get("__global") ?? {}; + if (!resource) return { ...g }; + const s = mossConfigByScope.get(resource.toString()) ?? {}; + return { ...g, ...s }; +} + +export const workspace = { + getConfiguration(section: string, resource?: { toString(): string }) { + if (section !== "moss") { + return { get: () => undefined }; + } + const data = mergedMossConfig(resource); + return { + get: (key: string) => data[key] as T, + }; + }, +}; + +export interface WorkspaceFolder { + readonly uri: URI; + readonly name: string; + readonly index: number; +} diff --git a/packages/vscode-moss/vitest.config.ts b/packages/vscode-moss/vitest.config.ts new file mode 100644 index 00000000..c7ec446a --- /dev/null +++ b/packages/vscode-moss/vitest.config.ts @@ -0,0 +1,17 @@ +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { defineConfig } from "vitest/config"; + +const root = path.dirname(fileURLToPath(import.meta.url)); + +export default defineConfig({ + test: { + environment: "node", + include: ["test/**/*.test.ts"], + }, + resolve: { + alias: { + vscode: path.resolve(root, "test/vscode-stub.ts"), + }, + }, +}); From e2c610f224d0b1aec67a7da97a8e46f843e31823 Mon Sep 17 00:00:00 2001 From: Ankit Mukherjee Date: Sat, 4 Apr 2026 22:42:56 -0400 Subject: [PATCH 06/21] Update packages/vscode-moss/package.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/vscode-moss/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json index c9da0f7f..eb9cab29 100644 --- a/packages/vscode-moss/package.json +++ b/packages/vscode-moss/package.json @@ -23,7 +23,6 @@ }, "type": "module", "main": "./out/extension.js", - "activationEvents": [], "contributes": { "commands": [ { From cb3306a2ef5668f10f467dc479215fada4d330db Mon Sep 17 00:00:00 2001 From: Ankit Mukherjee Date: Sat, 4 Apr 2026 22:43:05 -0400 Subject: [PATCH 07/21] Update packages/vscode-moss/src/searchViewProvider.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../vscode-moss/src/searchViewProvider.ts | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/packages/vscode-moss/src/searchViewProvider.ts b/packages/vscode-moss/src/searchViewProvider.ts index fd19f8b5..8ea5dc5a 100644 --- a/packages/vscode-moss/src/searchViewProvider.ts +++ b/packages/vscode-moss/src/searchViewProvider.ts @@ -30,25 +30,27 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { webviewView.webview.html = this._getHtml(webviewView.webview); - webviewView.webview.onDidReceiveMessage((message) => { - switch (message.type) { - case "query": - if (typeof message.text === "string") { - void this._handleQuery(message.text.trim()); - } - break; - case "openResult": - if (typeof message.hitIndex === "number") { - void this._openHitAtIndex(message.hitIndex); - } - break; - case "openMossSettings": - void vscode.commands.executeCommand("moss.openSettings"); - break; - default: - break; - } - }); + this._context.subscriptions.push( + webviewView.webview.onDidReceiveMessage((message) => { + switch (message.type) { + case "query": + if (typeof message.text === "string") { + void this._handleQuery(message.text.trim()); + } + break; + case "openResult": + if (typeof message.hitIndex === "number") { + void this._openHitAtIndex(message.hitIndex); + } + break; + case "openMossSettings": + void vscode.commands.executeCommand("moss.openSettings"); + break; + default: + break; + } + }) + ); } private async _handleQuery(text: string): Promise { From 2eb4cc4ccd4011618d219699efdd97e70ba3d281 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Sun, 5 Apr 2026 00:25:26 -0400 Subject: [PATCH 08/21] chunking strategy changed. tree-sitter support for major languages. warm up search implement so first search feels faster --- README.md | 1 + ROADMAP.md | 2 +- packages/vscode-moss/README.md | 6 +- packages/vscode-moss/esbuild.config.mjs | 7 +- packages/vscode-moss/package-lock.json | 1370 ++++++----------- packages/vscode-moss/package.json | 17 +- .../vscode-moss/scripts/probe-grammar.mjs | 20 + packages/vscode-moss/src/chunkCore.ts | 126 ++ packages/vscode-moss/src/chunking.ts | 204 ++- packages/vscode-moss/src/indexWorkspace.ts | 90 +- packages/vscode-moss/src/mossClients.ts | 7 +- packages/vscode-moss/src/mossConstants.ts | 4 +- packages/vscode-moss/src/mossQueryState.ts | 7 +- packages/vscode-moss/src/preloadLocalIndex.ts | 42 + packages/vscode-moss/src/runMossQuery.ts | 19 +- .../vscode-moss/src/searchViewProvider.ts | 47 +- packages/vscode-moss/src/structureChunking.ts | 508 ++++++ packages/vscode-moss/src/types.ts | 2 +- packages/vscode-moss/test/chunking.test.ts | 50 +- packages/vscode-moss/test/mossClients.test.ts | 21 +- .../test/structureChunking.test.ts | 102 ++ 21 files changed, 1552 insertions(+), 1100 deletions(-) create mode 100644 packages/vscode-moss/scripts/probe-grammar.mjs create mode 100644 packages/vscode-moss/src/chunkCore.ts create mode 100644 packages/vscode-moss/src/preloadLocalIndex.ts create mode 100644 packages/vscode-moss/src/structureChunking.ts create mode 100644 packages/vscode-moss/test/structureChunking.test.ts diff --git a/README.md b/README.md index 8d1ea1db..7fd3137f 100644 --- a/README.md +++ b/README.md @@ -242,6 +242,7 @@ const results = await client.query(name, "your query", { topK: 5 }); | [LiveKit](https://github.com/livekit/livekit) | Available | [`apps/livekit-moss-vercel/`](apps/livekit-moss-vercel/) | | [Next.js](https://nextjs.org) | Available | [`apps/next-js/`](apps/next-js/) | | [VitePress](https://vitepress.dev) | Available | [`packages/vitepress-plugin-moss/`](packages/vitepress-plugin-moss/) | +| VS Code / Cursor | Available | [`packages/vscode-moss/`](packages/vscode-moss/) (semantic search sidebar; install from VSIX) | | [Vercel AI SDK](https://sdk.vercel.ai) | Coming soon | — | | [CrewAI](https://github.com/crewAIInc/crewAI) | Coming soon | — | diff --git a/ROADMAP.md b/ROADMAP.md index 7c899f31..5d057f6f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -61,7 +61,7 @@ These are well-scoped and ready for contributors. Each one has (or will have) a ### Developer Tools - [ ] **Moss CLI** — manage indexes, run queries, import data, and inspect results from the terminal (`moss index create`, `moss query`, `moss import`) -- [ ] **VS Code extension** — semantic search over your codebase directly from the editor sidebar +- [x] **VS Code extension** — semantic search over your codebase from the editor sidebar ([`packages/vscode-moss/`](packages/vscode-moss/); VSIX install, no Marketplace listing) ### Search Quality diff --git a/packages/vscode-moss/README.md b/packages/vscode-moss/README.md index 677a53aa..69893de4 100644 --- a/packages/vscode-moss/README.md +++ b/packages/vscode-moss/README.md @@ -15,7 +15,7 @@ VS Code extension for **semantic codebase search** with [Moss](https://moss.dev) npx vsce package ``` - This produces **`vscode-moss-0.0.1.vsix`** (or whatever version is in `package.json`) in the current directory. The file is **large** (~100MB+) because **`@inferedge/moss`** bundles local embedding dependencies. + This produces **`vscode-moss-0.0.1.vsix`** (or whatever version is in `package.json`) in the current directory. Size depends on **`@moss-dev/moss`** and its **`@moss-dev/moss-core`** (N-API) dependency shipped in `node_modules`. 2. In VS Code or Cursor: **Extensions** → **`…`** (Views and More Actions) → **Install from VSIX…** → choose the `.vsix` file. @@ -74,7 +74,7 @@ Use the **Extension Development Host** (F5 from repo root or this package) with ### Troubleshooting (`loadIndex` / local search) -**Moss: Index Workspace** and sidebar search use the same **`@inferedge-rest/moss`** (upload) and **`@inferedge/moss`** (`loadIndex` + `query`) stack as the rest of the product. +**Moss: Index Workspace** and sidebar search use **`@moss-dev/moss`** (`createIndex`, `deleteIndex`, `loadIndex`, `query`) — one client for cloud mutations and local or cloud queries. - If **`loadIndex`** or local **`query`** fails, read the error in **Output → Moss**. Common causes: Node / native addon constraints in the extension host, WASM path differences, or network/proxy blocking the index download. - Search still runs **`query`** after a failed `loadIndex`; the SDK falls back to **cloud** query (same idea as setting **`moss.queryMode`** to **`cloud`**). @@ -117,6 +117,6 @@ npm run watch # optional during development Same as [Install from VSIX](#install-from-vsix) step 1. You can also run **`npm run package`** (`vsce package`), which triggers **`vscode:prepublish`** (check + compile) first. -Bundling only shrinks **our** entry file; the VSIX stays large because of **`@inferedge/moss`** / **`@huggingface/transformers`**. Trimming size further would need a different query architecture or upstream packaging changes. +Bundling only shrinks **our** entry file; **`@moss-dev/moss`** and **`@moss-dev/moss-core`** remain **external** and ship inside the VSIX via `node_modules`. `package.json` still includes **`icon`** and **`galleryBanner`** for consistency if you ever list the extension elsewhere; they are not required for VSIX install. diff --git a/packages/vscode-moss/esbuild.config.mjs b/packages/vscode-moss/esbuild.config.mjs index fe58be4d..6860ee20 100644 --- a/packages/vscode-moss/esbuild.config.mjs +++ b/packages/vscode-moss/esbuild.config.mjs @@ -12,7 +12,12 @@ const buildOptions = { sourcemap: true, logLevel: "info", /** Provided by the extension host; Moss packages pull large native/WASM stacks — keep resolvable from node_modules. */ - external: ["vscode", "@inferedge/moss", "@inferedge-rest/moss"], + external: [ + "vscode", + "@moss-dev/moss", + "@moss-dev/moss-core", + "web-tree-sitter", + ], }; if (watch) { diff --git a/packages/vscode-moss/package-lock.json b/packages/vscode-moss/package-lock.json index bf251784..ba174feb 100644 --- a/packages/vscode-moss/package-lock.json +++ b/packages/vscode-moss/package-lock.json @@ -9,8 +9,19 @@ "version": "0.0.1", "license": "BSD-2-Clause", "dependencies": { - "@inferedge-rest/moss": "^1.0.0-beta.3", - "@inferedge/moss": "^1.0.0-beta.7" + "@moss-dev/moss": "^1.0.0", + "tree-sitter-c": "^0.24.1", + "tree-sitter-c-sharp": "^0.23.1", + "tree-sitter-cpp": "^0.23.4", + "tree-sitter-go": "^0.25.0", + "tree-sitter-java": "^0.23.5", + "tree-sitter-javascript": "^0.25.0", + "tree-sitter-php": "^0.24.2", + "tree-sitter-python": "^0.25.0", + "tree-sitter-ruby": "^0.23.1", + "tree-sitter-rust": "^0.24.0", + "tree-sitter-typescript": "^0.23.2", + "web-tree-sitter": "^0.26.8" }, "devDependencies": { "@types/node": "^22.10.0", @@ -236,16 +247,6 @@ "node": ">=6.9.0" } }, - "node_modules/@emnapi/runtime": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", - "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.7", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", @@ -688,536 +689,111 @@ "node": ">=18" } }, - "node_modules/@huggingface/jinja": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.6.tgz", - "integrity": "sha512-MyMWyLnjqo+KRJYSH7oWNbsOn5onuIvfXYPcc0WOGxU0eHUV7oAYUoQTl2BMdu7ml+ea/bu11UM+EshbeHwtIA==", - "license": "MIT", + "node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "dev": true, + "license": "BlueOak-1.0.0", "engines": { "node": ">=18" } }, - "node_modules/@huggingface/transformers": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.8.1.tgz", - "integrity": "sha512-tsTk4zVjImqdqjS8/AOZg2yNLd1z9S5v+7oUPpXaasDRwEDhB+xnglK1k5cad26lL5/ZIaeREgWWy0bs9y9pPA==", - "license": "Apache-2.0", - "dependencies": { - "@huggingface/jinja": "^0.5.3", - "onnxruntime-node": "1.21.0", - "onnxruntime-web": "1.22.0-dev.20250409-89f8206ba4", - "sharp": "^0.34.1" - } - }, - "node_modules/@img/colour": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", - "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", - "license": "MIT", - "engines": { - "node": ">=18" - } + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" + "node_modules/@moss-dev/moss": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@moss-dev/moss/-/moss-1.0.0.tgz", + "integrity": "sha512-vRsRcQQibBCVmJmN4mESiLWqoef/ugrCuE6iU7OAfmtezZyTogOeEZnUGu1s/QbDp2nHXEVgkgFj0VeXZI1CeA==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@moss-dev/moss-core": "0.8.7" } }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@moss-dev/moss-core": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core/-/moss-core-0.8.7.tgz", + "integrity": "sha512-IxmJYNCBHhnjNj8o3H0T7XRCDVhSbwv+WmAc5KLDkAug9Ep74FK4/kpjiR32muZXTbvbktxYgB6iHL7oUMY2xw==", + "license": "Proprietary", "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">=20" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" + "@moss-dev/moss-core-darwin-arm64": "0.8.7", + "@moss-dev/moss-core-linux-arm64-gnu": "0.8.7", + "@moss-dev/moss-core-linux-x64-gnu": "0.8.7", + "@moss-dev/moss-core-win32-x64-msvc": "0.8.7" } }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "node_modules/@moss-dev/moss-core-darwin-arm64": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core-darwin-arm64/-/moss-core-darwin-arm64-0.8.7.tgz", + "integrity": "sha512-SxRD5vV5HSezJRr1GcIxQKOyX/nJ6RCgQYSDZTPsYbo49M0bRdAATKUpGIW5xHC7YZsZXZY8OiUVcw5lBQW0Lg==", "cpu": [ "arm64" ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", + "license": "Proprietary", "optional": true, "os": [ "darwin" ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", - "cpu": [ - "riscv64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", - "cpu": [ - "ppc64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", - "cpu": [ - "riscv64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" + "node": ">=20" } }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "node_modules/@moss-dev/moss-core-linux-arm64-gnu": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core-linux-arm64-gnu/-/moss-core-linux-arm64-gnu-0.8.7.tgz", + "integrity": "sha512-uRs/V6f0qvbStGSGNd/10cWJQKMPEumpQCAcjdRODiLbh5N+S6TIt2/bUHfc5uMxPFC9Bld7URglNmtfNXCKNA==", "cpu": [ "arm64" ], - "license": "Apache-2.0", + "license": "Proprietary", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + "node": ">=20" } }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "node_modules/@moss-dev/moss-core-linux-x64-gnu": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core-linux-x64-gnu/-/moss-core-linux-x64-gnu-0.8.7.tgz", + "integrity": "sha512-HgQgYN3ivLVNGJbQIBp6N2i+96y7cN/40sqzL0jqh2TzTziygoiSlwIkIqkkDZJ8DnSwJAMMQ9o2l1zPoMskCQ==", "cpu": [ "x64" ], - "license": "Apache-2.0", + "license": "Proprietary", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.7.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">=20" } }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "node_modules/@moss-dev/moss-core-win32-x64-msvc": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core-win32-x64-msvc/-/moss-core-win32-x64-msvc-0.8.7.tgz", + "integrity": "sha512-P49hUAuOXpMP1gVM+SMf0DyvXUU8OHLpppUsz7CRWJ4GkNY6JCnC3tHD1dEJQSnHMx9zOnS0hoAV6qzuhWuIrg==", "cpu": [ "x64" ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", + "license": "Proprietary", "optional": true, "os": [ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@inferedge-rest/moss": { - "version": "1.0.0-beta.3", - "resolved": "https://registry.npmjs.org/@inferedge-rest/moss/-/moss-1.0.0-beta.3.tgz", - "integrity": "sha512-0EsqtouvVlFtOpFKJvrNB/WDFVmWpA7AuCx8pXkJVa0tg3DDGOPglq8U0y6TLygi6ZAr91vOawnm5B8p0j/uLA==", - "license": "SEE LICENSE IN LICENSE" - }, - "node_modules/@inferedge/moss": { - "version": "1.0.0-beta.8", - "resolved": "https://registry.npmjs.org/@inferedge/moss/-/moss-1.0.0-beta.8.tgz", - "integrity": "sha512-FZn0DyUC192P/6CiUaZwgxj8AHxUKuYuJ5j6XGZJziAyRgYPPTPaiSrXbbMuAU9s/heP0rZRX5tCt/zHGkNFgw==", - "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "@huggingface/transformers": "^3.5.0" - } - }, - "node_modules/@isaacs/cliui": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", - "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" + "node": ">=20" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1256,70 +832,6 @@ "node": ">= 8" } }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", @@ -1970,6 +1482,7 @@ "version": "22.19.17", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -2500,13 +2013,6 @@ "dev": true, "license": "ISC" }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "MIT" - }, "node_modules/boundary": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz", @@ -2726,15 +2232,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/cockatiel": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", @@ -2926,23 +2423,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", @@ -2956,23 +2436,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2987,17 +2450,13 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, "license": "Apache-2.0", + "optional": true, "engines": { "node": ">=8" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "license": "MIT" - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -3161,6 +2620,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3170,6 +2630,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3211,12 +2672,6 @@ "node": ">= 0.4" } }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "license": "MIT" - }, "node_modules/esbuild": { "version": "0.27.7", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", @@ -3259,18 +2714,6 @@ "@esbuild/win32-x64": "0.27.7" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -3376,12 +2819,6 @@ "node": ">=8" } }, - "node_modules/flatbuffers": { - "version": "25.9.23", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", - "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", - "license": "Apache-2.0" - }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -3588,39 +3025,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "license": "BSD-3-Clause", - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/globby": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", @@ -3646,6 +3050,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3661,12 +3066,6 @@ "dev": true, "license": "ISC" }, - "node_modules/guid-typescript": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", - "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==", - "license": "ISC" - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3677,18 +3076,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -4041,12 +3428,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "license": "ISC" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -4222,12 +3603,6 @@ "dev": true, "license": "MIT" }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, "node_modules/loupe": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", @@ -4276,18 +3651,6 @@ "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -4407,23 +3770,12 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } }, - "node_modules/minizlib": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", - "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -4495,6 +3847,17 @@ "license": "MIT", "optional": true }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-sarif-builder": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.4.0.tgz", @@ -4570,15 +3933,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4590,49 +3944,6 @@ "wrappy": "1" } }, - "node_modules/onnxruntime-common": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.21.0.tgz", - "integrity": "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ==", - "license": "MIT" - }, - "node_modules/onnxruntime-node": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.21.0.tgz", - "integrity": "sha512-NeaCX6WW2L8cRCSqy3bInlo5ojjQqu2fD3D+9W5qb5irwxhEyWKXeH2vZ8W9r6VxaMPUan+4/7NDwZMtouZxEw==", - "hasInstallScript": true, - "license": "MIT", - "os": [ - "win32", - "darwin", - "linux" - ], - "dependencies": { - "global-agent": "^3.0.0", - "onnxruntime-common": "1.21.0", - "tar": "^7.0.1" - } - }, - "node_modules/onnxruntime-web": { - "version": "1.22.0-dev.20250409-89f8206ba4", - "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz", - "integrity": "sha512-0uS76OPgH0hWCPrFKlL8kYVV7ckM7t/36HfbgoFw6Nd0CZVVbQC4PkrR8mBX8LtNUFZO25IQBqV2Hx2ho3FlbQ==", - "license": "MIT", - "dependencies": { - "flatbuffers": "^25.1.24", - "guid-typescript": "^1.0.9", - "long": "^5.2.3", - "onnxruntime-common": "1.22.0-dev.20250409-89f8206ba4", - "platform": "^1.3.6", - "protobufjs": "^7.2.4" - } - }, - "node_modules/onnxruntime-web/node_modules/onnxruntime-common": { - "version": "1.22.0-dev.20250409-89f8206ba4", - "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.22.0-dev.20250409-89f8206ba4.tgz", - "integrity": "sha512-vDJMkfCfb0b1A836rgHj+ORuZf4B4+cc2bASQtpeoJLueuFc5DuYwjIZUBrSvx/fO5IrLjLz+oTrB3pcGlhovQ==", - "license": "MIT" - }, "node_modules/open": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", @@ -4857,12 +4168,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", - "license": "MIT" - }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -4931,30 +4236,6 @@ "node": ">=10" } }, - "node_modules/protobufjs": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", - "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/pump": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", @@ -5127,23 +4408,6 @@ "node": ">=0.10.0" } }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "license": "BSD-3-Clause", - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/rollup": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", @@ -5290,6 +4554,7 @@ "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -5298,83 +4563,6 @@ "node": ">=10" } }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "license": "MIT" - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "license": "MIT", - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.2", - "semver": "^7.7.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5620,12 +4808,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "license": "BSD-3-Clause" - }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -5816,22 +4998,6 @@ "node": ">=8" } }, - "node_modules/tar": { - "version": "7.5.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz", - "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", @@ -5872,15 +5038,6 @@ "node": ">=6" } }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/terminal-link": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", @@ -6036,11 +5193,359 @@ "node": ">=8.0" } }, + "node_modules/tree-sitter-c": { + "version": "0.24.1", + "resolved": "https://registry.npmjs.org/tree-sitter-c/-/tree-sitter-c-0.24.1.tgz", + "integrity": "sha512-lkYwWN3SRecpvaeqmFKkuPNR3ZbtnvHU+4XAEEkJdrp3JfSp2pBrhXOtvfsENUneye76g889Y0ddF2DM0gEDpA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.1", + "node-gyp-build": "^4.8.4" + }, + "peerDependencies": { + "tree-sitter": "^0.22.4" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-c-sharp": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/tree-sitter-c-sharp/-/tree-sitter-c-sharp-0.23.1.tgz", + "integrity": "sha512-9zZ4FlcTRWWfRf6f4PgGhG8saPls6qOOt75tDfX7un9vQZJmARjPrAC6yBNCX2T/VKcCjIDbgq0evFaB3iGhQw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" + }, + "peerDependencies": { + "tree-sitter": "^0.21.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-c-sharp/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-c/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-cpp": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/tree-sitter-cpp/-/tree-sitter-cpp-0.23.4.tgz", + "integrity": "sha512-qR5qUDyhZ5jJ6V8/umiBxokRbe89bCGmcq/dk94wI4kN86qfdV8k0GHIUEKaqWgcu42wKal5E97LKpLeVW8sKw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.2.1", + "node-gyp-build": "^4.8.2", + "tree-sitter-c": "^0.23.1" + }, + "peerDependencies": { + "tree-sitter": "^0.21.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-cpp/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-cpp/node_modules/tree-sitter-c": { + "version": "0.23.6", + "resolved": "https://registry.npmjs.org/tree-sitter-c/-/tree-sitter-c-0.23.6.tgz", + "integrity": "sha512-0dxXKznVyUA0s6PjNolJNs2yF87O5aL538A/eR6njA5oqX3C3vH4vnx3QdOKwuUdpKEcFdHuiDpRKLLCA/tjvQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "peerDependencies": { + "tree-sitter": "^0.22.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-go": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/tree-sitter-go/-/tree-sitter-go-0.25.0.tgz", + "integrity": "sha512-APBc/Dq3xz/e35Xpkhb1blu5UgW+2E3RyGWawZSCNcbGwa7jhSQPS8KsUupuzBla8PCo8+lz9W/JDJjmfRa2tw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.1", + "node-gyp-build": "^4.8.4" + }, + "peerDependencies": { + "tree-sitter": "^0.25.0" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-go/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-java": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/tree-sitter-java/-/tree-sitter-java-0.23.5.tgz", + "integrity": "sha512-Yju7oQ0Xx7GcUT01mUglPP+bYfvqjNCGdxqigTnew9nLGoII42PNVP3bHrYeMxswiCRM0yubWmN5qk+zsg0zMA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" + }, + "peerDependencies": { + "tree-sitter": "^0.21.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-java/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-javascript": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/tree-sitter-javascript/-/tree-sitter-javascript-0.25.0.tgz", + "integrity": "sha512-1fCbmzAskZkxcZzN41sFZ2br2iqTYP3tKls1b/HKGNPQUVOpsUxpmGxdN/wMqAk3jYZnYBR1dd/y/0avMeU7dw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.1", + "node-gyp-build": "^4.8.4" + }, + "peerDependencies": { + "tree-sitter": "^0.25.0" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-javascript/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-php": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/tree-sitter-php/-/tree-sitter-php-0.24.2.tgz", + "integrity": "sha512-zwgAePc/HozNaWOOfwRAA+3p8yhuehRw8Fb7vn5qd2XjiIc93uJPryDTMYTSjBRjVIUg/KY6pM3rRzs8dSwKfw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" + }, + "peerDependencies": { + "tree-sitter": "^0.22.4" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-php/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-python": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/tree-sitter-python/-/tree-sitter-python-0.25.0.tgz", + "integrity": "sha512-eCmJx6zQa35GxaCtQD+wXHOhYqBxEL+bp71W/s3fcDMu06MrtzkVXR437dRrCrbrDbyLuUDJpAgycs7ncngLXw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.5.0", + "node-gyp-build": "^4.8.4" + }, + "peerDependencies": { + "tree-sitter": "^0.25.0" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-python/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-ruby": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/tree-sitter-ruby/-/tree-sitter-ruby-0.23.1.tgz", + "integrity": "sha512-d9/RXgWjR6HanN7wTYhS5bpBQLz1VkH048Vm3CodPGyJVnamXMGb8oEhDypVCBq4QnHui9sTXuJBBP3WtCw5RA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" + }, + "peerDependencies": { + "tree-sitter": "^0.21.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-ruby/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-rust": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/tree-sitter-rust/-/tree-sitter-rust-0.24.0.tgz", + "integrity": "sha512-NWemUDf629Tfc90Y0Z55zuwPCAHkLxWnMf2RznYu4iBkkrQl2o/CHGB7Cr52TyN5F1DAx8FmUnDtCy9iUkXZEQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.4" + }, + "peerDependencies": { + "tree-sitter": "^0.22.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-rust/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-typescript": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/tree-sitter-typescript/-/tree-sitter-typescript-0.23.2.tgz", + "integrity": "sha512-e04JUUKxTT53/x3Uq1zIL45DoYKVfHH4CZqwgZhPg5qYROl5nQjV+85ruFzFGZxu+QeFVbRTPDRnqL9UbU4VeA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2", + "tree-sitter-javascript": "^0.23.1" + }, + "peerDependencies": { + "tree-sitter": "^0.21.0" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-typescript/node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/tree-sitter-typescript/node_modules/tree-sitter-javascript": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/tree-sitter-javascript/-/tree-sitter-javascript-0.23.1.tgz", + "integrity": "sha512-/bnhbrTD9frUYHQTiYnPcxyHORIw157ERBa6dqzaKxvR/x3PC4Yzd+D1pZIMS6zNg2v3a8BZ0oK7jHqsQo9fWA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" + }, + "peerDependencies": { + "tree-sitter": "^0.21.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "devOptional": true, + "dev": true, "license": "0BSD" }, "node_modules/tunnel": { @@ -6134,6 +5639,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, "license": "MIT" }, "node_modules/unicorn-magic": { @@ -6430,6 +5936,12 @@ "dev": true, "license": "MIT" }, + "node_modules/web-tree-sitter": { + "version": "0.26.8", + "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.26.8.tgz", + "integrity": "sha512-4sUwi7ZyOrIk5KLgYLkc2A/F0LFMQnBhfb+2Cdl7ik4ePJ6JD+fk4ofI2sA5eGawBKBaK4Vntt7Ww5KcEsay4A==", + "license": "MIT" + }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json index eb9cab29..3dbc63ff 100644 --- a/packages/vscode-moss/package.json +++ b/packages/vscode-moss/package.json @@ -3,7 +3,7 @@ "displayName": "Moss", "description": "Semantic codebase search powered by Moss — index your workspace and search from the sidebar.", "version": "0.0.1", - "publisher": "inferedge", + "publisher": "moss-dev", "license": "BSD-2-Clause", "repository": { "type": "git", @@ -166,8 +166,19 @@ "vscode:prepublish": "npm run check && npm run compile" }, "dependencies": { - "@inferedge-rest/moss": "^1.0.0-beta.3", - "@inferedge/moss": "^1.0.0-beta.7" + "@moss-dev/moss": "^1.0.0", + "tree-sitter-c": "^0.24.1", + "tree-sitter-c-sharp": "^0.23.1", + "tree-sitter-cpp": "^0.23.4", + "tree-sitter-go": "^0.25.0", + "tree-sitter-java": "^0.23.5", + "tree-sitter-javascript": "^0.25.0", + "tree-sitter-php": "^0.24.2", + "tree-sitter-python": "^0.25.0", + "tree-sitter-ruby": "^0.23.1", + "tree-sitter-rust": "^0.24.0", + "tree-sitter-typescript": "^0.23.2", + "web-tree-sitter": "^0.26.8" }, "devDependencies": { "@types/node": "^22.10.0", diff --git a/packages/vscode-moss/scripts/probe-grammar.mjs b/packages/vscode-moss/scripts/probe-grammar.mjs new file mode 100644 index 00000000..d6028f3c --- /dev/null +++ b/packages/vscode-moss/scripts/probe-grammar.mjs @@ -0,0 +1,20 @@ +import * as TS from "web-tree-sitter"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = path.join(path.dirname(fileURLToPath(import.meta.url)), ".."); +const nm = path.join(root, "node_modules"); +await TS.Parser.init({ + locateFile: (b) => path.join(nm, "web-tree-sitter", b), +}); +const c = await TS.Language.load( + path.join(nm, "tree-sitter-c", "tree-sitter-c.wasm") +); +const p = new TS.Parser(); +p.setLanguage(c); +const src = "#include \n#include \nint main(){return 0;}\n"; +const t = p.parse(src); +console.log(t.rootNode.type); +for (const ch of t.rootNode.namedChildren) console.log(" ", ch.type); +p.delete(); +t.delete(); diff --git a/packages/vscode-moss/src/chunkCore.ts b/packages/vscode-moss/src/chunkCore.ts new file mode 100644 index 00000000..81e3d74d --- /dev/null +++ b/packages/vscode-moss/src/chunkCore.ts @@ -0,0 +1,126 @@ +import type { MossDocument, MossMetadata } from "./types.js"; + +const DEFAULT_MAX_CHARS = 12_000; + +export interface ChunkOptions { + chunkMaxLines: number; + chunkOverlapLines: number; + /** Upper bound on embedded text length per chunk (Phase 0: ~12k). */ + maxCharsPerChunk?: number; + /** If total lines ≤ this, emit a single chunk for the whole file. */ + smallFileMaxLines?: number; + workspaceFolderIndex?: number; + workspaceFolderName?: string; + /** + * Uniquifies doc ids across workspace roots (e.g. multi-root). Omitted for single-folder workspaces. + */ + chunkIdNamespace?: string; +} + +export function normalizeRelativePath(relativePath: string): string { + return relativePath.replace(/\\/g, "/"); +} + +function joinLines( + lines: string[], + startIdx: number, + endIdxExclusive: number +): string { + return lines.slice(startIdx, endIdxExclusive).join("\n"); +} + +export function truncateToMaxChars( + lines: string[], + startIdx: number, + endIdxExclusive: number, + maxChars: number +): { text: string; endIdxExclusive: number } { + let end = endIdxExclusive; + let text = joinLines(lines, startIdx, end); + while (text.length > maxChars && end > startIdx + 1) { + end -= 1; + text = joinLines(lines, startIdx, end); + } + if (text.length > maxChars && end === startIdx + 1) { + const line = lines[startIdx] ?? ""; + text = line.slice(0, maxChars); + } + return { text, endIdxExclusive: end }; +} + +export function buildMetadata( + pathNorm: string, + startLine1: number, + endLine1: number, + options: ChunkOptions +): MossMetadata { + const meta: MossMetadata = { + path: pathNorm, + startLine: String(startLine1), + endLine: String(endLine1), + }; + if (options.workspaceFolderIndex !== undefined) { + meta.workspaceFolderIndex = String(options.workspaceFolderIndex); + } + if (options.workspaceFolderName !== undefined) { + meta.workspaceFolderName = options.workspaceFolderName; + } + return meta; +} + +/** + * Line-window chunking for lines [segmentStartLine1, segmentEndLine1] inclusive (1-based). + */ +export function chunkLineWindowSegment( + pathNorm: string, + lines: string[], + segmentStartLine1: number, + segmentEndLine1: number, + options: ChunkOptions, + idPrefix: string, + metaForRange: (startLine1: number, endLine1: number) => MossMetadata +): MossDocument[] { + const total = lines.length; + const segStart = Math.max(1, Math.min(segmentStartLine1, total || 1)); + const segEnd = Math.max(segStart, Math.min(segmentEndLine1, total || 1)); + const segLen = segEnd - segStart + 1; + + const maxLines = Math.max(1, options.chunkMaxLines); + let overlap = Math.max(0, options.chunkOverlapLines); + if (overlap >= maxLines) { + overlap = Math.max(0, maxLines - 1); + } + const maxChars = options.maxCharsPerChunk ?? DEFAULT_MAX_CHARS; + + const docs: MossDocument[] = []; + + if (segLen <= 0) return docs; + + let startLine = segStart; + while (startLine <= segEnd) { + const startIdx = startLine - 1; + let endLine = Math.min(segEnd, startLine + maxLines - 1); + let endIdxExclusive = endLine; + + const { text: body, endIdxExclusive: trimmedEnd } = truncateToMaxChars( + lines, + startIdx, + endIdxExclusive, + maxChars + ); + endIdxExclusive = trimmedEnd; + endLine = endIdxExclusive; + + docs.push({ + id: `${idPrefix}${pathNorm}:${startLine}-${endLine}`, + text: body, + metadata: metaForRange(startLine, endLine), + }); + + if (endLine >= segEnd) break; + const nextStart = Math.max(startLine + 1, endLine - overlap + 1); + startLine = nextStart; + } + + return docs; +} diff --git a/packages/vscode-moss/src/chunking.ts b/packages/vscode-moss/src/chunking.ts index b7deb636..0508a7ca 100644 --- a/packages/vscode-moss/src/chunking.ts +++ b/packages/vscode-moss/src/chunking.ts @@ -1,75 +1,26 @@ -import type { MossDocument, MossMetadata } from "./types.js"; +import { + supportsStructureChunking, + tryStructureAwareChunk, +} from "./structureChunking.js"; +import { + buildMetadata, + chunkLineWindowSegment, + normalizeRelativePath, + truncateToMaxChars, +} from "./chunkCore.js"; + +export type { ChunkOptions } from "./chunkCore.js"; + +import type { ChunkOptions } from "./chunkCore.js"; +import type { MossDocument } from "./types.js"; const DEFAULT_MAX_CHARS = 12_000; const DEFAULT_SMALL_FILE_LINES = 50; -export interface ChunkOptions { - chunkMaxLines: number; - chunkOverlapLines: number; - /** Upper bound on embedded text length per chunk (Phase 0: ~12k). */ - maxCharsPerChunk?: number; - /** If total lines ≤ this, emit a single chunk for the whole file. */ - smallFileMaxLines?: number; - workspaceFolderIndex?: number; - workspaceFolderName?: string; - /** - * Uniquifies doc ids across workspace roots (e.g. multi-root). Omitted for single-folder workspaces. - */ - chunkIdNamespace?: string; -} - -function normalizeRelativePath(relativePath: string): string { - return relativePath.replace(/\\/g, "/"); -} - -function joinLines(lines: string[], startIdx: number, endIdxExclusive: number): string { - return lines.slice(startIdx, endIdxExclusive).join("\n"); -} - -function truncateToMaxChars( - lines: string[], - startIdx: number, - endIdxExclusive: number, - maxChars: number -): { text: string; endIdxExclusive: number } { - let end = endIdxExclusive; - let text = joinLines(lines, startIdx, end); - while (text.length > maxChars && end > startIdx + 1) { - end -= 1; - text = joinLines(lines, startIdx, end); - } - if (text.length > maxChars && end === startIdx + 1) { - const line = lines[startIdx] ?? ""; - text = line.slice(0, maxChars); - } - return { text, endIdxExclusive: end }; -} - -function buildMetadata( - pathNorm: string, - startLine1: number, - endLine1: number, - options: ChunkOptions -): MossMetadata { - const meta: MossMetadata = { - path: pathNorm, - startLine: String(startLine1), - endLine: String(endLine1), - }; - if (options.workspaceFolderIndex !== undefined) { - meta.workspaceFolderIndex = String(options.workspaceFolderIndex); - } - if (options.workspaceFolderName !== undefined) { - meta.workspaceFolderName = options.workspaceFolderName; - } - return meta; -} - /** - * Split file text into Moss documents with stable ids `path:startLine-endLine`. - * Line numbers are 1-based inclusive in metadata. Pure — no VS Code API. + * Full-file line-window chunking (fallback when structure-aware path does not apply). */ -export function chunkFileContent( +export function chunkFileContentLineWindowsOnly( relativePath: string, text: string, options: ChunkOptions @@ -78,28 +29,22 @@ export function chunkFileContent( const lines = text.split(/\r?\n/); const total = lines.length; - const maxLines = Math.max(1, options.chunkMaxLines); - let overlap = Math.max(0, options.chunkOverlapLines); - if (overlap >= maxLines) { - overlap = Math.max(0, maxLines - 1); - } const maxChars = options.maxCharsPerChunk ?? DEFAULT_MAX_CHARS; const smallMax = options.smallFileMaxLines ?? DEFAULT_SMALL_FILE_LINES; - const docs: MossDocument[] = []; - const idPrefix = options.chunkIdNamespace !== undefined && options.chunkIdNamespace !== "" ? `${options.chunkIdNamespace}:` : ""; if (total === 0) { - docs.push({ - id: `${idPrefix}${pathNorm}:1-1`, - text: "", - metadata: buildMetadata(pathNorm, 1, 1, options), - }); - return docs; + return [ + { + id: `${idPrefix}${pathNorm}:1-1`, + text: "", + metadata: buildMetadata(pathNorm, 1, 1, options), + }, + ]; } if (total <= smallMax) { @@ -110,39 +55,86 @@ export function chunkFileContent( maxChars ); const endLine = endIdxExclusive; - docs.push({ - id: `${idPrefix}${pathNorm}:1-${endLine}`, - text: body, - metadata: buildMetadata(pathNorm, 1, endLine, options), - }); - return docs; + return [ + { + id: `${idPrefix}${pathNorm}:1-${endLine}`, + text: body, + metadata: buildMetadata(pathNorm, 1, endLine, options), + }, + ]; } - let startLine = 1; - while (startLine <= total) { - const startIdx = startLine - 1; - let endLine = Math.min(total, startLine + maxLines - 1); - let endIdxExclusive = endLine; + return chunkLineWindowSegment( + pathNorm, + lines, + 1, + total, + options, + idPrefix, + (sl, el) => buildMetadata(pathNorm, sl, el, options) + ); +} - const { text: body, endIdxExclusive: trimmedEnd } = truncateToMaxChars( +/** + * Split file text into Moss documents. Uses Markdown / JS / TS structure when applicable, + * otherwise the same overlapping line windows as before. + */ +export async function chunkFileContent( + relativePath: string, + text: string, + options: ChunkOptions, + languageId?: string +): Promise { + const pathNorm = normalizeRelativePath(relativePath); + const lines = text.split(/\r?\n/); + const total = lines.length; + const smallMax = options.smallFileMaxLines ?? DEFAULT_SMALL_FILE_LINES; + const maxChars = options.maxCharsPerChunk ?? DEFAULT_MAX_CHARS; + + const idPrefix = + options.chunkIdNamespace !== undefined && options.chunkIdNamespace !== "" + ? `${options.chunkIdNamespace}:` + : ""; + + if (total === 0) { + return [ + { + id: `${idPrefix}${pathNorm}:1-1`, + text: "", + metadata: buildMetadata(pathNorm, 1, 1, options), + }, + ]; + } + + if (supportsStructureChunking(languageId)) { + const structured = await tryStructureAwareChunk( + relativePath, + text, lines, - startIdx, - endIdxExclusive, - maxChars + options, + languageId ); - endIdxExclusive = trimmedEnd; - endLine = endIdxExclusive; - - docs.push({ - id: `${idPrefix}${pathNorm}:${startLine}-${endLine}`, - text: body, - metadata: buildMetadata(pathNorm, startLine, endLine, options), - }); + if (structured && structured.length > 0) { + return structured; + } + } - if (endLine >= total) break; - const nextStart = Math.max(startLine + 1, endLine - overlap + 1); - startLine = nextStart; + if (total <= smallMax) { + const { text: body, endIdxExclusive } = truncateToMaxChars( + lines, + 0, + total, + maxChars + ); + const endLine = endIdxExclusive; + return [ + { + id: `${idPrefix}${pathNorm}:1-${endLine}`, + text: body, + metadata: buildMetadata(pathNorm, 1, endLine, options), + }, + ]; } - return docs; + return chunkFileContentLineWindowsOnly(relativePath, text, options); } diff --git a/packages/vscode-moss/src/indexWorkspace.ts b/packages/vscode-moss/src/indexWorkspace.ts index b842dc34..4e7bd983 100644 --- a/packages/vscode-moss/src/indexWorkspace.ts +++ b/packages/vscode-moss/src/indexWorkspace.ts @@ -7,9 +7,13 @@ import { type LastIndexedState, } from "./lastIndexed.js"; import { mossLog } from "./mossLog.js"; -import { invalidateLoadedSearchIndex } from "./mossQueryState.js"; +import { + ensureLocalIndexLoaded, + getOrCreateSdkClient, + invalidateLoadedSearchIndex, +} from "./mossQueryState.js"; import { notifyMossIndexed } from "./mossStatusBar.js"; -import { createRestClient, createSdkClient } from "./mossClients.js"; +import { createRestClient } from "./mossClients.js"; import type { MossDocument } from "./types.js"; const MAX_FILE_SCAN = 80_000; @@ -23,6 +27,59 @@ const EXTRA_SAFE_EXCLUDES = [ "**/__pycache__/**", ]; +/** VS Code–style language id for structure-aware chunking (Markdown, JS/TS, and other Tree-sitter grammars). */ +function languageIdFromPath(fsPath: string): string | undefined { + switch (path.extname(fsPath).toLowerCase()) { + case ".md": + case ".mdx": + return "markdown"; + case ".ts": + case ".mts": + case ".cts": + return "typescript"; + case ".tsx": + return "typescriptreact"; + case ".js": + case ".mjs": + case ".cjs": + return "javascript"; + case ".jsx": + return "javascriptreact"; + case ".py": + case ".pyi": + case ".pyw": + return "python"; + case ".rs": + return "rust"; + case ".go": + return "go"; + case ".java": + return "java"; + case ".rb": + case ".rake": + case ".ru": + return "ruby"; + case ".php": + return "php"; + case ".c": + case ".h": + return "c"; + case ".cpp": + case ".cc": + case ".cxx": + case ".hpp": + case ".hh": + case ".hxx": + case ".inl": + case ".cu": + return "cpp"; + case ".cs": + return "csharp"; + default: + return undefined; + } +} + const BINARY_EXT = new Set( [ ".zip", @@ -325,14 +382,19 @@ export async function runIndexWorkspace( const relativePath = vscode.workspace.asRelativePath(uri, false); if (relativePath === "") continue; - const chunks = chunkFileContent(relativePath, text, { - chunkMaxLines: cfg.chunkMaxLines, - chunkOverlapLines: cfg.chunkOverlapLines, - workspaceFolderIndex: folderIndex, - workspaceFolderName: folder.name, - chunkIdNamespace: - folders.length > 1 ? String(folderIndex) : undefined, - }); + const chunks = await chunkFileContent( + relativePath, + text, + { + chunkMaxLines: cfg.chunkMaxLines, + chunkOverlapLines: cfg.chunkOverlapLines, + workspaceFolderIndex: folderIndex, + workspaceFolderName: folder.name, + chunkIdNamespace: + folders.length > 1 ? String(folderIndex) : undefined, + }, + languageIdFromPath(uri.fsPath) + ); allDocs.push(...chunks); filesIndexed += 1; @@ -373,7 +435,9 @@ export async function runIndexWorkspace( return; } - await rest.createIndex(cfg.indexName, allDocs, cfg.modelId); + await rest.createIndex(cfg.indexName, allDocs, { + modelId: cfg.modelId, + }); invalidateLoadedSearchIndex(); mossLog( log, @@ -411,8 +475,8 @@ export async function runIndexWorkspace( return; } try { - const sdk = createSdkClient(creds.projectId, creds.projectKey); - await sdk.loadIndex(cfg.indexName); + const sdk = getOrCreateSdkClient(creds.projectId, creds.projectKey); + await ensureLocalIndexLoaded(sdk, cfg.indexName); mossLog( log, "Moss: loadIndex completed (local query cache warmed).", diff --git a/packages/vscode-moss/src/mossClients.ts b/packages/vscode-moss/src/mossClients.ts index 9b3f27a8..72227fe1 100644 --- a/packages/vscode-moss/src/mossClients.ts +++ b/packages/vscode-moss/src/mossClients.ts @@ -1,9 +1,8 @@ -import { MossRestClient } from "@inferedge-rest/moss"; -import { MossClient } from "@inferedge/moss"; +import { MossClient } from "@moss-dev/moss"; /** Thin factory for tests and to keep Moss imports in one place. */ -export function createRestClient(projectId: string, projectKey: string): MossRestClient { - return new MossRestClient(projectId, projectKey); +export function createRestClient(projectId: string, projectKey: string): MossClient { + return new MossClient(projectId, projectKey); } export function createSdkClient(projectId: string, projectKey: string): MossClient { diff --git a/packages/vscode-moss/src/mossConstants.ts b/packages/vscode-moss/src/mossConstants.ts index ae943537..690be67f 100644 --- a/packages/vscode-moss/src/mossConstants.ts +++ b/packages/vscode-moss/src/mossConstants.ts @@ -1,5 +1,5 @@ /** * Filter passed to `workbench.action.openSettings` for this extension. - * Must stay aligned with `publisher` + `name` in package.json (`inferedge` + `vscode-moss`). + * Must stay aligned with `publisher` + `name` in package.json (`moss-dev` + `vscode-moss`). */ -export const MOSS_EXTENSION_SETTINGS_QUERY = "@ext:inferedge.vscode-moss"; +export const MOSS_EXTENSION_SETTINGS_QUERY = "@ext:moss-dev.vscode-moss"; diff --git a/packages/vscode-moss/src/mossQueryState.ts b/packages/vscode-moss/src/mossQueryState.ts index ed480bd0..ba6a159b 100644 --- a/packages/vscode-moss/src/mossQueryState.ts +++ b/packages/vscode-moss/src/mossQueryState.ts @@ -1,4 +1,4 @@ -import type { MossClient } from "@inferedge/moss"; +import type { MossClient } from "@moss-dev/moss"; import { createSdkClient } from "./mossClients.js"; let cachedClient: @@ -42,6 +42,11 @@ export function invalidateLoadedSearchIndex(): void { loadedLocalIndexName = undefined; } +/** True when `ensureLocalIndexLoaded` would skip calling `loadIndex` for this index on the cached SDK client. */ +export function isLocalSearchIndexCached(indexName: string): boolean { + return loadedLocalIndexName === indexName; +} + export async function ensureLocalIndexLoaded( client: MossClient, indexName: string diff --git a/packages/vscode-moss/src/preloadLocalIndex.ts b/packages/vscode-moss/src/preloadLocalIndex.ts new file mode 100644 index 00000000..b792eac7 --- /dev/null +++ b/packages/vscode-moss/src/preloadLocalIndex.ts @@ -0,0 +1,42 @@ +import * as vscode from "vscode"; +import { getMossConfig, resolveCredentials } from "./config.js"; +import { mossLog } from "./mossLog.js"; +import { ensureLocalIndexLoaded, getOrCreateSdkClient } from "./mossQueryState.js"; + +/** + * Best-effort `loadIndex` for local query mode so the first search is often faster. + * Uses the same SDK cache as search; overlapping preload + search may run `loadIndex` twice briefly. + */ +export async function preloadLocalMossIndex( + context: vscode.ExtensionContext, + log: vscode.OutputChannel, + token: vscode.CancellationToken +): Promise { + if (token.isCancellationRequested) return; + + const folders = vscode.workspace.workspaceFolders; + if (!folders?.length) return; + + const creds = await resolveCredentials(context); + if (!creds) return; + + const primary = folders[0]!; + const cfg = await getMossConfig(context.secrets, primary); + if (cfg.queryMode !== "local") return; + + if (token.isCancellationRequested) return; + + try { + const sdk = getOrCreateSdkClient(creds.projectId, creds.projectKey); + await ensureLocalIndexLoaded(sdk, cfg.indexName); + mossLog(log, "Moss: Background index preload finished.", "verbose"); + } catch (e: unknown) { + if (token.isCancellationRequested) return; + const msg = e instanceof Error ? e.message : String(e); + mossLog( + log, + `Moss: Background index preload failed (search will retry): ${msg}`, + "verbose" + ); + } +} diff --git a/packages/vscode-moss/src/runMossQuery.ts b/packages/vscode-moss/src/runMossQuery.ts index 57ac2cc9..5d278ae9 100644 --- a/packages/vscode-moss/src/runMossQuery.ts +++ b/packages/vscode-moss/src/runMossQuery.ts @@ -3,6 +3,7 @@ import { getMossConfig, resolveCredentials } from "./config.js"; import { ensureLocalIndexLoaded, getOrCreateSdkClient, + isLocalSearchIndexCached, } from "./mossQueryState.js"; import { mossLog } from "./mossLog.js"; import type { SearchHit } from "./types.js"; @@ -30,13 +31,21 @@ function lineLabel(meta: Record): string { return "?"; } +export interface RunMossQueryHooks { + /** Called immediately before a blocking `loadIndex` (first local search or after cache invalidation). */ + onAwaitingLocalIndexDownload?: () => void; + /** Called after `loadIndex` finishes or throws (before `query` runs). */ + onLocalIndexDownloadFinished?: () => void; +} + /** * Semantic search against the configured workspace index. */ export async function runMossQuery( context: vscode.ExtensionContext, queryText: string, - log: vscode.OutputChannel + log: vscode.OutputChannel, + hooks?: RunMossQueryHooks ): Promise< | { ok: true; hits: SearchHit[]; timeMs?: number } | { ok: false; error: SearchFailure } @@ -69,6 +78,10 @@ export async function runMossQuery( const sdk = getOrCreateSdkClient(creds.projectId, creds.projectKey); if (cfg.queryMode === "local") { + const needsLocalDownload = !isLocalSearchIndexCached(cfg.indexName); + if (needsLocalDownload) { + hooks?.onAwaitingLocalIndexDownload?.(); + } try { await ensureLocalIndexLoaded(sdk, cfg.indexName); } catch (e: unknown) { @@ -77,6 +90,10 @@ export async function runMossQuery( `Moss: Search — loadIndex failed; continuing with cloud query. ${formatError(e)}`, "verbose" ); + } finally { + if (needsLocalDownload) { + hooks?.onLocalIndexDownloadFinished?.(); + } } } diff --git a/packages/vscode-moss/src/searchViewProvider.ts b/packages/vscode-moss/src/searchViewProvider.ts index 8ea5dc5a..1260ec01 100644 --- a/packages/vscode-moss/src/searchViewProvider.ts +++ b/packages/vscode-moss/src/searchViewProvider.ts @@ -1,4 +1,5 @@ import * as vscode from "vscode"; +import { preloadLocalMossIndex } from "./preloadLocalIndex.js"; import { hitToRowDto, runMossQuery } from "./runMossQuery.js"; import { metadataToRange, metadataToUri } from "./paths.js"; import type { SearchHit } from "./types.js"; @@ -30,6 +31,14 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { webviewView.webview.html = this._getHtml(webviewView.webview); + const preloadCts = new vscode.CancellationTokenSource(); + webviewView.onDidDispose(() => preloadCts.dispose()); + void preloadLocalMossIndex( + this._context, + this._log, + preloadCts.token + ); + this._context.subscriptions.push( webviewView.webview.onDidReceiveMessage((message) => { switch (message.type) { @@ -70,7 +79,17 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { webview.postMessage({ type: "loading", loading: true }); webview.postMessage({ type: "clearError" }); - const result = await runMossQuery(this._context, text, this._log); + const result = await runMossQuery(this._context, text, this._log, { + onAwaitingLocalIndexDownload: () => { + webview.postMessage({ + type: "localIndexLoading", + text: "Downloading index for local search — first time can take a minute…", + }); + }, + onLocalIndexDownloadFinished: () => { + webview.postMessage({ type: "localIndexLoading", text: "" }); + }, + }); if (seq !== this._querySeq) return; @@ -178,6 +197,13 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { color: var(--vscode-descriptionForeground); min-height: 1.2em; } + .index-prep { + display: none; + font-size: 0.88em; + color: var(--vscode-descriptionForeground); + line-height: 1.45; + } + .index-prep.visible { display: block; } .error-banner { display: none; padding: 8px 10px; @@ -265,6 +291,7 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider {
+
@@ -283,6 +310,7 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { const input = document.getElementById('query'); const btn = document.getElementById('searchBtn'); const meta = document.getElementById('meta'); + const indexPrep = document.getElementById('indexPrep'); const errorBanner = document.getElementById('errorBanner'); const emptyBlock = document.getElementById('emptyBlock'); const emptyState = document.getElementById('emptyState'); @@ -342,6 +370,10 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { setLoading(!!msg.loading); if (msg.loading) { meta.textContent = ''; + if (indexPrep) { + indexPrep.textContent = ''; + indexPrep.classList.remove('visible'); + } resultList.innerHTML = ''; resultList.style.display = 'none'; emptyBlock.style.display = 'none'; @@ -349,6 +381,19 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { return; } + if (msg.type === 'localIndexLoading') { + if (!indexPrep) return; + const t = typeof msg.text === 'string' ? msg.text : ''; + if (t) { + indexPrep.textContent = t; + indexPrep.classList.add('visible'); + } else { + indexPrep.textContent = ''; + indexPrep.classList.remove('visible'); + } + return; + } + if (msg.type === 'clearError') { clearError(); return; diff --git a/packages/vscode-moss/src/structureChunking.ts b/packages/vscode-moss/src/structureChunking.ts new file mode 100644 index 00000000..83626121 --- /dev/null +++ b/packages/vscode-moss/src/structureChunking.ts @@ -0,0 +1,508 @@ +/** + * Structure-aware splitting: Markdown (headings) and tree-sitter top-level spans + * (JS/TS, Python, Rust, Go, Java, Ruby, PHP, C/C++, C#), then packing into Moss + * documents with line-window subdivision when a span is too large. + */ +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import type { Language, Node as TsNode } from "web-tree-sitter"; +import * as TreeSitter from "web-tree-sitter"; +import type { ChunkOptions } from "./chunkCore.js"; +import { + buildMetadata, + chunkLineWindowSegment, + normalizeRelativePath, +} from "./chunkCore.js"; +import type { MossDocument, MossMetadata } from "./types.js"; + +/** 1-based inclusive line range in the source file. */ +export interface LineRange1 { + startLine: number; + endLine: number; + /** Optional metadata for Moss (string values only). */ + extraMeta?: Record; +} + +interface GrammarProfile { + /** npm package folder under node_modules */ + wasmPackage: string; + wasmFile: string; + rootTypes: ReadonlySet; + importTypes: ReadonlySet; + strategyImports: string; + strategyTop: string; +} + +function moduleDir(): string { + return path.dirname(fileURLToPath(import.meta.url)); +} + +function nodeModulesRoot(): string { + const dir = moduleDir(); + return path.join(dir, "..", "node_modules"); +} + +let parserInit: Promise | undefined; +const languageCache = new Map(); + +const GRAMMAR_BY_LANGUAGE_ID = new Map(); + +function registerGrammar(languageIds: string[], profile: GrammarProfile): void { + for (const id of languageIds) { + GRAMMAR_BY_LANGUAGE_ID.set(id.toLowerCase(), profile); + } +} + +registerGrammar( + ["typescript"], + { + wasmPackage: "tree-sitter-typescript", + wasmFile: "tree-sitter-typescript.wasm", + rootTypes: new Set(["program"]), + importTypes: new Set(["import_statement"]), + strategyImports: "ts_imports", + strategyTop: "ts_top_level", + } +); + +registerGrammar( + ["typescriptreact", "jsx"], + { + wasmPackage: "tree-sitter-typescript", + wasmFile: "tree-sitter-tsx.wasm", + rootTypes: new Set(["program"]), + importTypes: new Set(["import_statement"]), + strategyImports: "ts_imports", + strategyTop: "ts_top_level", + } +); + +registerGrammar( + ["javascript"], + { + wasmPackage: "tree-sitter-javascript", + wasmFile: "tree-sitter-javascript.wasm", + rootTypes: new Set(["program"]), + importTypes: new Set(["import_statement"]), + strategyImports: "ts_imports", + strategyTop: "ts_top_level", + } +); + +registerGrammar( + ["javascriptreact"], + { + wasmPackage: "tree-sitter-typescript", + wasmFile: "tree-sitter-tsx.wasm", + rootTypes: new Set(["program"]), + importTypes: new Set(["import_statement"]), + strategyImports: "ts_imports", + strategyTop: "ts_top_level", + } +); + +registerGrammar( + ["python"], + { + wasmPackage: "tree-sitter-python", + wasmFile: "tree-sitter-python.wasm", + rootTypes: new Set(["module"]), + importTypes: new Set([ + "import_statement", + "import_from_statement", + "future_import_statement", + ]), + strategyImports: "toplevel_imports", + strategyTop: "toplevel", + } +); + +registerGrammar( + ["rust"], + { + wasmPackage: "tree-sitter-rust", + wasmFile: "tree-sitter-rust.wasm", + rootTypes: new Set(["source_file"]), + importTypes: new Set(["use_declaration", "extern_crate_declaration"]), + strategyImports: "toplevel_imports", + strategyTop: "toplevel", + } +); + +registerGrammar( + ["go", "golang"], + { + wasmPackage: "tree-sitter-go", + wasmFile: "tree-sitter-go.wasm", + rootTypes: new Set(["source_file"]), + importTypes: new Set(["package_clause", "import_declaration"]), + strategyImports: "toplevel_imports", + strategyTop: "toplevel", + } +); + +registerGrammar( + ["java"], + { + wasmPackage: "tree-sitter-java", + wasmFile: "tree-sitter-java.wasm", + rootTypes: new Set(["program"]), + importTypes: new Set(["package_declaration", "import_declaration"]), + strategyImports: "toplevel_imports", + strategyTop: "toplevel", + } +); + +registerGrammar( + ["ruby"], + { + wasmPackage: "tree-sitter-ruby", + wasmFile: "tree-sitter-ruby.wasm", + rootTypes: new Set(["program"]), + importTypes: new Set(), + strategyImports: "toplevel_imports", + strategyTop: "toplevel", + } +); + +registerGrammar( + ["php"], + { + wasmPackage: "tree-sitter-php", + wasmFile: "tree-sitter-php.wasm", + rootTypes: new Set(["program"]), + importTypes: new Set(["php_tag", "namespace_use_declaration"]), + strategyImports: "toplevel_imports", + strategyTop: "toplevel", + } +); + +registerGrammar( + ["c"], + { + wasmPackage: "tree-sitter-c", + wasmFile: "tree-sitter-c.wasm", + rootTypes: new Set(["translation_unit"]), + importTypes: new Set([ + "preproc_include", + "preproc_def", + "preproc_function_def", + "preproc_call", + ]), + strategyImports: "toplevel_imports", + strategyTop: "toplevel", + } +); + +registerGrammar( + ["cpp", "cuda-cpp"], + { + wasmPackage: "tree-sitter-cpp", + wasmFile: "tree-sitter-cpp.wasm", + rootTypes: new Set(["translation_unit"]), + importTypes: new Set([ + "preproc_include", + "preproc_def", + "preproc_function_def", + "preproc_call", + ]), + strategyImports: "toplevel_imports", + strategyTop: "toplevel", + } +); + +registerGrammar( + ["csharp", "c#"], + { + wasmPackage: "tree-sitter-c-sharp", + wasmFile: "tree-sitter-c_sharp.wasm", + rootTypes: new Set(["compilation_unit"]), + importTypes: new Set(["using_directive", "extern_alias_directive"]), + strategyImports: "toplevel_imports", + strategyTop: "toplevel", + } +); + +async function ensureParser(): Promise { + if (!parserInit) { + const nm = nodeModulesRoot(); + parserInit = TreeSitter.Parser.init({ + locateFile: (base: string) => path.join(nm, "web-tree-sitter", base), + }); + } + await parserInit; +} + +async function loadWasmLanguage( + wasmPackage: string, + wasmFile: string +): Promise { + const cacheKey = `${wasmPackage}/${wasmFile}`; + let lang = languageCache.get(cacheKey); + if (!lang) { + await ensureParser(); + const nm = nodeModulesRoot(); + lang = await TreeSitter.Language.load( + path.join(nm, wasmPackage, wasmFile) + ); + languageCache.set(cacheKey, lang); + } + return lang; +} + +function isAtxHeadingLine(line: string): boolean { + return /^(#{1,6})\s+/.test(line.trimStart()); +} + +/** + * Split Markdown on ATX headings (# …). Lines before the first heading are one section. + */ +export function markdownStructuralRanges(lines: string[]): LineRange1[] { + if (lines.length === 0) return []; + const ranges: LineRange1[] = []; + let secStart = 1; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]!; + if (i > 0 && isAtxHeadingLine(line)) { + const prevEnd = i; + if (secStart <= prevEnd) { + ranges.push({ + startLine: secStart, + endLine: prevEnd, + extraMeta: { chunkStrategy: "markdown" }, + }); + } + secStart = i + 1; + } + } + if (secStart <= lines.length) { + ranges.push({ + startLine: secStart, + endLine: lines.length, + extraMeta: { chunkStrategy: "markdown" }, + }); + } + return ranges; +} + +function nodeToLineRange1(node: TsNode, strategy: string): LineRange1 { + return { + startLine: node.startPosition.row + 1, + endLine: node.endPosition.row + 1, + extraMeta: { chunkStrategy: strategy }, + }; +} + +function resolveBodyRoot( + root: TsNode, + rootTypes: ReadonlySet +): TsNode | undefined { + if (rootTypes.has(root.type)) return root; + for (const c of root.namedChildren) { + if (rootTypes.has(c.type)) return c; + } + return undefined; +} + +function collectBodyTopLevelRanges( + body: TsNode, + importTypes: ReadonlySet, + strategyImports: string, + strategyTop: string +): LineRange1[] { + const ranges: LineRange1[] = []; + const children = body.namedChildren; + let i = 0; + while (i < children.length) { + const n = children[i]!; + if (importTypes.has(n.type)) { + let j = i; + while ( + j + 1 < children.length && + importTypes.has(children[j + 1]!.type) + ) { + j += 1; + } + const last = children[j]!; + ranges.push({ + startLine: n.startPosition.row + 1, + endLine: last.endPosition.row + 1, + extraMeta: { chunkStrategy: strategyImports }, + }); + i = j + 1; + continue; + } + ranges.push(nodeToLineRange1(n, strategyTop)); + i += 1; + } + return ranges; +} + +export async function treeSitterStructuralRanges( + text: string, + languageId: string +): Promise { + try { + const id = languageId.toLowerCase(); + const profile = GRAMMAR_BY_LANGUAGE_ID.get(id); + if (!profile) return undefined; + + const lang = await loadWasmLanguage(profile.wasmPackage, profile.wasmFile); + const parser = new TreeSitter.Parser(); + parser.setLanguage(lang); + const tree = parser.parse(text); + parser.delete(); + if (!tree) return undefined; + + const root = tree.rootNode; + const body = resolveBodyRoot(root, profile.rootTypes); + if (!body) { + tree.delete(); + return undefined; + } + + const ranges = collectBodyTopLevelRanges( + body, + profile.importTypes, + profile.strategyImports, + profile.strategyTop + ); + tree.delete(); + return ranges.length > 0 ? ranges : undefined; + } catch { + return undefined; + } +} + +function mergeMeta( + base: ChunkOptions, + pathNorm: string, + startLine: number, + endLine: number, + extra?: Record +): MossMetadata { + const m = buildMetadata(pathNorm, startLine, endLine, base); + if (extra) { + for (const [k, v] of Object.entries(extra)) { + m[k] = v; + } + } + return m; +} + +function sortRanges(ranges: LineRange1[]): LineRange1[] { + return [...ranges].sort((a, b) => a.startLine - b.startLine); +} + +/** + * Fill gaps between structural ranges with 1-based gap ranges (inclusive). + */ +function gapRanges( + sorted: LineRange1[], + totalLines: number +): LineRange1[] { + const gaps: LineRange1[] = []; + let cursor = 1; + for (const r of sorted) { + if (cursor < r.startLine) { + gaps.push({ + startLine: cursor, + endLine: r.startLine - 1, + extraMeta: { chunkStrategy: "line_window" }, + }); + } + cursor = Math.max(cursor, r.endLine + 1); + } + if (cursor <= totalLines) { + gaps.push({ + startLine: cursor, + endLine: totalLines, + extraMeta: { chunkStrategy: "line_window" }, + }); + } + return gaps.filter((g) => g.startLine <= g.endLine); +} + +/** + * Turn structural + gap ranges into Moss documents, subdividing large spans with line windows. + */ +export function packStructuralRanges( + pathNorm: string, + lines: string[], + structural: LineRange1[], + options: ChunkOptions +): MossDocument[] { + const total = lines.length; + if (total === 0) return []; + + const sorted = sortRanges(structural); + const gaps = gapRanges(sorted, total); + const combined = sortRanges([...sorted, ...gaps]); + + const idPrefix = + options.chunkIdNamespace !== undefined && options.chunkIdNamespace !== "" + ? `${options.chunkIdNamespace}:` + : ""; + + const out: MossDocument[] = []; + + for (const r of combined) { + const sub = chunkLineWindowSegment( + pathNorm, + lines, + r.startLine, + r.endLine, + options, + idPrefix, + r.extraMeta + ? (sl, el) => mergeMeta(options, pathNorm, sl, el, r.extraMeta) + : (sl, el) => buildMetadata(pathNorm, sl, el, options) + ); + out.push(...sub); + } + + return out; +} + +const STRUCTURE_TREE_SITTER_IDS = [ + ...new Set(GRAMMAR_BY_LANGUAGE_ID.keys()), +].sort((a, b) => a.localeCompare(b)); + +/** + * Structure-aware chunking when `languageId` is supported; returns `undefined` to use full-file line windows. + */ +export async function tryStructureAwareChunk( + relativePath: string, + text: string, + lines: string[], + options: ChunkOptions, + languageId: string | undefined +): Promise { + const id = languageId?.toLowerCase(); + const pathNorm = normalizeRelativePath(relativePath); + + if (id === "markdown" || id === "mdx") { + const ranges = markdownStructuralRanges(lines); + if (ranges.length <= 1) return undefined; + return packStructuralRanges(pathNorm, lines, ranges, options); + } + + if (id && GRAMMAR_BY_LANGUAGE_ID.has(id)) { + const ranges = await treeSitterStructuralRanges(text, id); + if (!ranges || ranges.length <= 1) return undefined; + return packStructuralRanges(pathNorm, lines, ranges, options); + } + + return undefined; +} + +/** Languages that may use Markdown or tree-sitter structural chunking. */ +export function supportsStructureChunking(languageId: string | undefined): boolean { + if (!languageId) return false; + const id = languageId.toLowerCase(); + return ( + id === "markdown" || + id === "mdx" || + STRUCTURE_TREE_SITTER_IDS.includes(id) + ); +} diff --git a/packages/vscode-moss/src/types.ts b/packages/vscode-moss/src/types.ts index 3deb9e4b..8adc819e 100644 --- a/packages/vscode-moss/src/types.ts +++ b/packages/vscode-moss/src/types.ts @@ -3,7 +3,7 @@ */ export type MossMetadata = Record; -/** One chunk uploaded to Moss (aligned with @inferedge-rest/moss DocumentInfo). */ +/** One chunk uploaded to Moss (aligned with @moss-dev/moss DocumentInfo). */ export interface MossDocument { id: string; text: string; diff --git a/packages/vscode-moss/test/chunking.test.ts b/packages/vscode-moss/test/chunking.test.ts index 678b96ff..bee2b888 100644 --- a/packages/vscode-moss/test/chunking.test.ts +++ b/packages/vscode-moss/test/chunking.test.ts @@ -9,8 +9,8 @@ describe("chunkFileContent", () => { smallFileMaxLines: 50, }; - it("returns one empty chunk for empty text", () => { - const docs = chunkFileContent("a.ts", "", baseOpts); + it("returns one empty chunk for empty text", async () => { + const docs = await chunkFileContent("a.ts", "", baseOpts); expect(docs).toHaveLength(1); expect(docs[0]!.id).toBe("a.ts:1-1"); expect(docs[0]!.text).toBe(""); @@ -18,26 +18,26 @@ describe("chunkFileContent", () => { expect(docs[0]!.metadata.endLine).toBe("1"); }); - it("uses single chunk for small files (≤ smallFileMaxLines)", () => { + it("uses single chunk for small files (≤ smallFileMaxLines)", async () => { const lines = Array.from({ length: 20 }, (_, i) => `line ${i + 1}`); const text = lines.join("\n"); - const docs = chunkFileContent("src/small.ts", text, baseOpts); + const docs = await chunkFileContent("src/small.ts", text, baseOpts); expect(docs).toHaveLength(1); expect(docs[0]!.id).toBe("src/small.ts:1-20"); expect(docs[0]!.metadata.path).toBe("src/small.ts"); expect(docs[0]!.text.length).toBeLessThanOrEqual(500); }); - it("windows-style path is normalized in id and metadata", () => { - const docs = chunkFileContent("src\\win.ts", "one", baseOpts); + it("windows-style path is normalized in id and metadata", async () => { + const docs = await chunkFileContent("src\\win.ts", "one", baseOpts); expect(docs[0]!.id.startsWith("src/win.ts:")).toBe(true); expect(docs[0]!.metadata.path).toBe("src/win.ts"); }); - it("splits large files into overlapping windows", () => { + it("splits large files into overlapping windows when language is not structure-aware", async () => { const lines = Array.from({ length: 30 }, (_, i) => `L${i + 1}`); const text = lines.join("\n"); - const docs = chunkFileContent("big.txt", text, { + const docs = await chunkFileContent("big.txt", text, { ...baseOpts, smallFileMaxLines: 5, }); @@ -51,17 +51,21 @@ describe("chunkFileContent", () => { } }); - it("prefixes ids with chunkIdNamespace for multi-root", () => { - const docs = chunkFileContent("x.ts", "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk", { - ...baseOpts, - smallFileMaxLines: 3, - chunkIdNamespace: "1", - }); + it("prefixes ids with chunkIdNamespace for multi-root", async () => { + const docs = await chunkFileContent( + "x.ts", + "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk", + { + ...baseOpts, + smallFileMaxLines: 3, + chunkIdNamespace: "1", + } + ); expect(docs.every((d) => d.id.startsWith("1:"))).toBe(true); }); - it("includes workspace metadata when provided", () => { - const docs = chunkFileContent("f.ts", "x", { + it("includes workspace metadata when provided", async () => { + const docs = await chunkFileContent("f.ts", "x", { ...baseOpts, workspaceFolderIndex: 2, workspaceFolderName: "backend", @@ -70,10 +74,10 @@ describe("chunkFileContent", () => { expect(docs[0]!.metadata.workspaceFolderName).toBe("backend"); }); - it("clamps overlap when overlap >= chunkMaxLines", () => { + it("clamps overlap when overlap >= chunkMaxLines", async () => { const lines = Array.from({ length: 25 }, (_, i) => `x${i}`); const text = lines.join("\n"); - const docs = chunkFileContent("o.ts", text, { + const docs = await chunkFileContent("o.ts", text, { chunkMaxLines: 5, chunkOverlapLines: 99, smallFileMaxLines: 5, @@ -81,4 +85,14 @@ describe("chunkFileContent", () => { }); expect(docs.length).toBeGreaterThan(0); }); + + it("splits markdown on headings when languageId is markdown", async () => { + const md = "# A\nline\n\n## B\nmore\n"; + const docs = await chunkFileContent("doc.md", md, baseOpts, "markdown"); + expect(docs.length).toBeGreaterThanOrEqual(2); + const strategies = docs.map((d) => d.metadata.chunkStrategy); + expect(strategies.every((s) => s === "markdown" || s === "line_window")).toBe( + true + ); + }); }); diff --git a/packages/vscode-moss/test/mossClients.test.ts b/packages/vscode-moss/test/mossClients.test.ts index 59d6bec4..8de0a551 100644 --- a/packages/vscode-moss/test/mossClients.test.ts +++ b/packages/vscode-moss/test/mossClients.test.ts @@ -1,38 +1,27 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -vi.mock("@inferedge-rest/moss", () => ({ - MossRestClient: vi.fn(), -})); - -vi.mock("@inferedge/moss", () => ({ +vi.mock("@moss-dev/moss", () => ({ MossClient: vi.fn(), })); -import { MossClient } from "@inferedge/moss"; -import { MossRestClient } from "@inferedge-rest/moss"; +import { MossClient } from "@moss-dev/moss"; import { createRestClient, createSdkClient } from "../src/mossClients.js"; describe("mossClients factories", () => { beforeEach(() => { - vi.mocked(MossRestClient).mockReset(); vi.mocked(MossClient).mockReset(); - vi.mocked(MossRestClient).mockImplementation( - () => - ({ - deleteIndex: vi.fn().mockRejectedValue(new Error("network down")), - }) as unknown as InstanceType - ); vi.mocked(MossClient).mockImplementation( () => ({ + deleteIndex: vi.fn().mockRejectedValue(new Error("network down")), loadIndex: vi.fn().mockResolvedValue("idx"), }) as unknown as InstanceType ); }); - it("createRestClient passes project id and key to MossRestClient", () => { + it("createRestClient passes project id and key to MossClient", () => { createRestClient("proj-1", "key-1"); - expect(MossRestClient).toHaveBeenCalledWith("proj-1", "key-1"); + expect(MossClient).toHaveBeenCalledWith("proj-1", "key-1"); }); it("createSdkClient passes project id and key to MossClient", () => { diff --git a/packages/vscode-moss/test/structureChunking.test.ts b/packages/vscode-moss/test/structureChunking.test.ts new file mode 100644 index 00000000..11ae8473 --- /dev/null +++ b/packages/vscode-moss/test/structureChunking.test.ts @@ -0,0 +1,102 @@ +import { describe, expect, it } from "vitest"; +import { + markdownStructuralRanges, + packStructuralRanges, + treeSitterStructuralRanges, +} from "../src/structureChunking.js"; +import type { ChunkOptions } from "../src/chunkCore.js"; + +describe("markdownStructuralRanges", () => { + it("returns one range when there is no heading", () => { + const r = markdownStructuralRanges(["a", "b"]); + expect(r).toHaveLength(1); + expect(r[0]!.startLine).toBe(1); + expect(r[0]!.endLine).toBe(2); + }); + + it("splits on ATX headings after the first line", () => { + const r = markdownStructuralRanges(["intro", "## H", "body"]); + expect(r).toHaveLength(2); + expect(r[0]!.startLine).toBe(1); + expect(r[0]!.endLine).toBe(1); + expect(r[1]!.startLine).toBe(2); + expect(r[1]!.endLine).toBe(3); + }); +}); + +describe("packStructuralRanges", () => { + const opts: ChunkOptions = { + chunkMaxLines: 5, + chunkOverlapLines: 1, + maxCharsPerChunk: 200, + smallFileMaxLines: 50, + }; + + it("fills gaps between sections with line_window strategy", () => { + const lines = ["a", "b", "", "c", "d", "e"]; + const structural = [ + { startLine: 1, endLine: 2, extraMeta: { chunkStrategy: "markdown" } }, + { startLine: 4, endLine: 6, extraMeta: { chunkStrategy: "markdown" } }, + ]; + const docs = packStructuralRanges("x.md", lines, structural, opts); + const gapChunk = docs.find((d) => d.metadata.chunkStrategy === "line_window"); + expect(gapChunk).toBeDefined(); + expect(gapChunk!.text.trim()).toBe(""); + }); +}); + +describe("treeSitterStructuralRanges", () => { + it("returns multiple ranges for two top-level functions in TypeScript", async () => { + const src = `export function a() { + return 1; +} +export function b() { + return 2; +} +`; + const ranges = await treeSitterStructuralRanges(src, "typescript"); + expect(ranges).toBeDefined(); + expect(ranges!.length).toBeGreaterThanOrEqual(2); + }); + + it("groups consecutive imports", async () => { + const src = `import x from "a"; +import y from "b"; +export const z = 1; +`; + const ranges = await treeSitterStructuralRanges(src, "typescript"); + expect(ranges).toBeDefined(); + const importRanges = ranges!.filter( + (r) => r.extraMeta?.chunkStrategy === "ts_imports" + ); + expect(importRanges.length).toBe(1); + expect(importRanges[0]!.startLine).toBe(1); + expect(importRanges[0]!.endLine).toBeGreaterThanOrEqual(2); + }); + + it("returns multiple ranges for two top-level defs in Python", async () => { + const src = `import os + +def a(): + return 1 + +def b(): + return 2 +`; + const ranges = await treeSitterStructuralRanges(src, "python"); + expect(ranges).toBeDefined(); + expect(ranges!.length).toBeGreaterThanOrEqual(2); + }); + + it("returns multiple ranges for two functions in Rust", async () => { + const src = `use std::io; + +fn a() -> i32 { 1 } + +fn b() -> i32 { 2 } +`; + const ranges = await treeSitterStructuralRanges(src, "rust"); + expect(ranges).toBeDefined(); + expect(ranges!.length).toBeGreaterThanOrEqual(2); + }); +}); From 109453232986c398882e5d3b5d0c0d3761d06f4a Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Sun, 5 Apr 2026 00:43:14 -0400 Subject: [PATCH 09/21] made improvements to search UI and added alpha parameter tweaking --- packages/vscode-moss/README.md | 1 + packages/vscode-moss/package.json | 7 + packages/vscode-moss/src/config.ts | 14 ++ packages/vscode-moss/src/runMossQuery.ts | 1 + .../vscode-moss/src/searchViewProvider.ts | 193 +++++++++++++++++- packages/vscode-moss/test/config.test.ts | 35 ++++ 6 files changed, 240 insertions(+), 11 deletions(-) diff --git a/packages/vscode-moss/README.md b/packages/vscode-moss/README.md index 69893de4..4771006a 100644 --- a/packages/vscode-moss/README.md +++ b/packages/vscode-moss/README.md @@ -47,6 +47,7 @@ File paths and file contents you index are sent to **Moss** (cloud) for embeddin | `includeGlob` / `excludeGlob` | Which files to crawl when indexing. | | `maxFileSizeBytes` | Skip larger files. | | `topK` | Number of search hits. | +| `alpha` | Hybrid search blend: `1.0` = semantic only, `0.0` = keyword only (default `0.8`). | | `queryMode` | `local` (download index) vs `cloud` (API-only queries). | | `chunkMaxLines` / `chunkOverlapLines` | Line-based chunking when indexing. | | `logVerbose` | Extra lines in **Output → Moss**. | diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json index 3dbc63ff..a34a40b1 100644 --- a/packages/vscode-moss/package.json +++ b/packages/vscode-moss/package.json @@ -125,6 +125,13 @@ "default": 10, "description": "Number of results to return for each search query." }, + "moss.alpha": { + "type": "number", + "default": 0.8, + "minimum": 0, + "maximum": 1, + "description": "Hybrid search blend: 1.0 = semantic (embedding) only, 0.0 = keyword only; values in between mix both. Default 0.8 is semantic-heavy." + }, "moss.queryMode": { "type": "string", "enum": [ diff --git a/packages/vscode-moss/src/config.ts b/packages/vscode-moss/src/config.ts index 331ccc45..22634ce2 100644 --- a/packages/vscode-moss/src/config.ts +++ b/packages/vscode-moss/src/config.ts @@ -9,6 +9,9 @@ export function getMossLogVerbose(): boolean { return vscode.workspace.getConfiguration("moss").get("logVerbose") === true; } +/** Default hybrid-search blend (semantic-heavy), aligned with Moss SDK defaults. */ +export const DEFAULT_QUERY_ALPHA = 0.8; + export interface ResolvedConfig { projectId: string | undefined; projectKey: string | undefined; @@ -18,12 +21,21 @@ export interface ResolvedConfig { excludeGlobs: string[]; maxFileSizeBytes: number; topK: number; + /** Hybrid search: 1.0 = semantic only, 0.0 = keyword only; clamped to [0, 1]. */ + alpha: number; queryMode: MossQueryMode; chunkMaxLines: number; chunkOverlapLines: number; workspaceFolder: vscode.WorkspaceFolder; } +/** Parse `moss.alpha`: finite number in [0, 1], else default. */ +export function resolveQueryAlpha(raw: unknown): number { + const n = typeof raw === "number" ? raw : Number(raw); + if (!Number.isFinite(n)) return DEFAULT_QUERY_ALPHA; + return Math.min(1, Math.max(0, n)); +} + function toStringArray(value: unknown, fallback: string[]): string[] { if (Array.isArray(value)) { return value.filter((x): x is string => typeof x === "string" && x.length > 0); @@ -122,6 +134,7 @@ export async function getMossConfig( const maxFileSizeBytes = cfg.get("maxFileSizeBytes") ?? 1_048_576; const topK = cfg.get("topK") ?? 10; + const alpha = resolveQueryAlpha(cfg.get("alpha")); const modeRaw = cfg.get("queryMode"); const queryMode: MossQueryMode = modeRaw === "cloud" ? "cloud" : "local"; @@ -138,6 +151,7 @@ export async function getMossConfig( excludeGlobs, maxFileSizeBytes, topK, + alpha, queryMode, chunkMaxLines, chunkOverlapLines, diff --git a/packages/vscode-moss/src/runMossQuery.ts b/packages/vscode-moss/src/runMossQuery.ts index 5d278ae9..95a077f0 100644 --- a/packages/vscode-moss/src/runMossQuery.ts +++ b/packages/vscode-moss/src/runMossQuery.ts @@ -100,6 +100,7 @@ export async function runMossQuery( try { const result = await sdk.query(cfg.indexName, queryText, { topK: cfg.topK, + alpha: cfg.alpha, }); const hits: SearchHit[] = result.docs.map((d) => ({ diff --git a/packages/vscode-moss/src/searchViewProvider.ts b/packages/vscode-moss/src/searchViewProvider.ts index 1260ec01..24018cd8 100644 --- a/packages/vscode-moss/src/searchViewProvider.ts +++ b/packages/vscode-moss/src/searchViewProvider.ts @@ -107,6 +107,7 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { this._lastHits = result.hits; webview.postMessage({ type: "results", + query: text, hits: result.hits.map((h, index) => ({ index, ...hitToRowDto(h), @@ -246,18 +247,28 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { color: var(--vscode-list-hoverForeground, var(--vscode-foreground)); } .result-path { - font-weight: 600; font-size: 0.92em; + line-height: 1.35; word-break: break-all; margin-bottom: 4px; } + .result-dir { + font-weight: 400; + color: var(--vscode-descriptionForeground); + font-size: 0.92em; + } + .result-base { + font-weight: 600; + color: var(--vscode-foreground); + } .result-sub { font-size: 0.82em; color: var(--vscode-descriptionForeground); margin-bottom: 6px; } .result-snippet { - font-size: 0.88em; + font-family: var(--vscode-editor-font-family); + font-size: calc(var(--vscode-font-size) * 0.92); line-height: 1.45; color: var(--vscode-foreground); opacity: 0.95; @@ -266,6 +277,19 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { -webkit-box-orient: vertical; overflow: hidden; } + mark.query-hit { + background: var( + --vscode-editor-findMatchHighlightBackground, + rgba(234, 92, 0, 0.28) + ); + color: inherit; + padding: 0 0.05em; + border-radius: 2px; + } + .result-row--selected { + outline: 1px solid var(--vscode-focusBorder); + outline-offset: -1px; + } .settings-hint { margin-top: 14px; text-align: center; @@ -303,7 +327,7 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { Open Moss settings

- +
+ `; } From ee10e59c275290dbb2e5e56febc57209e973d5a5 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Mon, 6 Apr 2026 23:21:35 -0400 Subject: [PATCH 13/21] made an improvement to tree-sitter reliability --- packages/vscode-moss/media/searchView.js | 18 +++++- packages/vscode-moss/src/chunkCore.ts | 3 +- packages/vscode-moss/src/chunking.ts | 2 +- packages/vscode-moss/src/config.ts | 57 +++++++++++++++++-- packages/vscode-moss/src/formatError.ts | 4 ++ packages/vscode-moss/src/indexWorkspace.ts | 14 ++--- packages/vscode-moss/src/runMossQuery.ts | 5 +- .../vscode-moss/src/searchViewProvider.ts | 4 +- packages/vscode-moss/src/structureChunking.ts | 3 + packages/vscode-moss/test/config.test.ts | 17 ++++++ 10 files changed, 104 insertions(+), 23 deletions(-) create mode 100644 packages/vscode-moss/src/formatError.ts diff --git a/packages/vscode-moss/media/searchView.js b/packages/vscode-moss/media/searchView.js index c3ff94de..6030a868 100644 --- a/packages/vscode-moss/media/searchView.js +++ b/packages/vscode-moss/media/searchView.js @@ -14,6 +14,19 @@ const resultList = document.getElementById("resultList"); const mossSettingsLink = document.getElementById("mossSettingsLink"); + if ( + !input || + !btn || + !meta || + !errorBanner || + !emptyBlock || + !emptyState || + !resultList || + !mossSettingsLink + ) { + return; + } + const DEFAULT_EMPTY_HTML = "Run Moss: Index Workspace to index your files,
then search here."; @@ -140,9 +153,8 @@ } function openHitIndex(idx) { - if (!Number.isNaN(idx)) { - vscode.postMessage({ type: "openResult", hitIndex: idx }); - } + if (typeof idx !== "number" || !Number.isInteger(idx) || idx < 0) return; + vscode.postMessage({ type: "openResult", hitIndex: idx }); } function flushLiveQuery() { diff --git a/packages/vscode-moss/src/chunkCore.ts b/packages/vscode-moss/src/chunkCore.ts index d3cc1fa7..cde7b906 100644 --- a/packages/vscode-moss/src/chunkCore.ts +++ b/packages/vscode-moss/src/chunkCore.ts @@ -1,7 +1,8 @@ import type { DocumentInfo } from "@moss-dev/moss"; import type { MossMetadata } from "./types.js"; -const DEFAULT_MAX_CHARS = 12_000; +/** Upper bound on embedded text length per chunk (shared with line-window chunking entry). */ +export const DEFAULT_MAX_CHARS = 12_000; export interface ChunkOptions { chunkMaxLines: number; diff --git a/packages/vscode-moss/src/chunking.ts b/packages/vscode-moss/src/chunking.ts index a2febff4..75e1fb9e 100644 --- a/packages/vscode-moss/src/chunking.ts +++ b/packages/vscode-moss/src/chunking.ts @@ -5,6 +5,7 @@ import { import { buildMetadata, chunkLineWindowSegment, + DEFAULT_MAX_CHARS, normalizeRelativePath, truncateToMaxChars, } from "./chunkCore.js"; @@ -14,7 +15,6 @@ import type { ChunkOptions } from "./chunkCore.js"; export type { ChunkOptions }; -const DEFAULT_MAX_CHARS = 12_000; const DEFAULT_SMALL_FILE_LINES = 50; /** diff --git a/packages/vscode-moss/src/config.ts b/packages/vscode-moss/src/config.ts index 382a98c5..c0b0c001 100644 --- a/packages/vscode-moss/src/config.ts +++ b/packages/vscode-moss/src/config.ts @@ -10,6 +10,47 @@ export function getMossLogVerbose(): boolean { /** Default hybrid-search blend (semantic-heavy), aligned with Moss SDK defaults. */ export const DEFAULT_QUERY_ALPHA = 0.8; +const DEFAULT_MAX_FILE_SIZE_BYTES = 1_048_576; +const MAX_FILE_SIZE_BYTES_CAP = 50 * 1024 * 1024; +const DEFAULT_TOP_K = 10; +const TOP_K_CAP = 100; +const DEFAULT_CHUNK_MAX_LINES = 100; +const CHUNK_MAX_LINES_CAP = 10_000; +const DEFAULT_CHUNK_OVERLAP_LINES = 12; +const CHUNK_OVERLAP_CAP = 10_000; + +function clampPositiveInt( + value: unknown, + fallback: number, + max: number +): number { + const n = typeof value === "number" ? value : Number(value); + if (!Number.isFinite(n)) return fallback; + const i = Math.trunc(n); + if (i < 1) return fallback; + return Math.min(i, max); +} + +function clampNonNegativeInt( + value: unknown, + fallback: number, + max: number +): number { + const n = typeof value === "number" ? value : Number(value); + if (!Number.isFinite(n)) return fallback; + const i = Math.trunc(n); + if (i < 0) return fallback; + return Math.min(i, max); +} + +function clampMaxFileSizeBytes(value: unknown): number { + const n = typeof value === "number" ? value : Number(value); + if (!Number.isFinite(n)) return DEFAULT_MAX_FILE_SIZE_BYTES; + const i = Math.trunc(n); + if (i < 1024) return DEFAULT_MAX_FILE_SIZE_BYTES; + return Math.min(i, MAX_FILE_SIZE_BYTES_CAP); +} + export interface ResolvedConfig { projectId: string | undefined; projectKey: string | undefined; @@ -129,12 +170,20 @@ export async function getMossConfig( ]; const excludeGlobs = toStringArray(cfg.get("excludeGlob"), defaultExcludes); - const maxFileSizeBytes = cfg.get("maxFileSizeBytes") ?? 1_048_576; - const topK = cfg.get("topK") ?? 10; + const maxFileSizeBytes = clampMaxFileSizeBytes(cfg.get("maxFileSizeBytes")); + const topK = clampPositiveInt(cfg.get("topK"), DEFAULT_TOP_K, TOP_K_CAP); const alpha = resolveQueryAlpha(cfg.get("alpha")); - const chunkMaxLines = cfg.get("chunkMaxLines") ?? 100; - const chunkOverlapLines = cfg.get("chunkOverlapLines") ?? 12; + const chunkMaxLines = clampPositiveInt( + cfg.get("chunkMaxLines"), + DEFAULT_CHUNK_MAX_LINES, + CHUNK_MAX_LINES_CAP + ); + const chunkOverlapLines = clampNonNegativeInt( + cfg.get("chunkOverlapLines"), + DEFAULT_CHUNK_OVERLAP_LINES, + CHUNK_OVERLAP_CAP + ); return { projectId, diff --git a/packages/vscode-moss/src/formatError.ts b/packages/vscode-moss/src/formatError.ts new file mode 100644 index 00000000..03aa44a3 --- /dev/null +++ b/packages/vscode-moss/src/formatError.ts @@ -0,0 +1,4 @@ +/** Stable string for logging and user-facing error messages. */ +export function formatError(e: unknown): string { + return e instanceof Error ? e.message : String(e); +} diff --git a/packages/vscode-moss/src/indexWorkspace.ts b/packages/vscode-moss/src/indexWorkspace.ts index 19a359a3..9bee1794 100644 --- a/packages/vscode-moss/src/indexWorkspace.ts +++ b/packages/vscode-moss/src/indexWorkspace.ts @@ -3,6 +3,7 @@ import path from "node:path"; import { MossClient } from "@moss-dev/moss"; import { getMossConfig, resolveCredentials } from "./config.js"; import { chunkFileContent } from "./chunking.js"; +import { formatError } from "./formatError.js"; import { MOSS_LAST_INDEXED_KEY, type LastIndexedState, @@ -250,10 +251,6 @@ async function readUtf8Text(uri: vscode.Uri): Promise { } } -function formatError(e: unknown): string { - return e instanceof Error ? e.message : String(e); -} - /** * Full workspace reindex: discover files, chunk, REST deleteIndex + createIndex, optional loadIndex. */ @@ -422,16 +419,16 @@ export async function runIndexWorkspace( progress.report({ message: "Uploading index to Moss…", increment: 0 }); - const rest = new MossClient(creds.projectId, creds.projectKey); + const client = new MossClient(creds.projectId, creds.projectKey); try { - await tolerateDeleteIndex(rest, cfg.indexName, log); + await tolerateDeleteIndex(client, cfg.indexName, log); if (token.isCancellationRequested) { mossLog(log, "Moss: Indexing cancelled before createIndex."); return; } - await rest.createIndex(cfg.indexName, allDocs, { + await client.createIndex(cfg.indexName, allDocs, { modelId: cfg.modelId, }); notifySearchIndexStale(); @@ -470,9 +467,8 @@ export async function runIndexWorkspace( return; } try { - const sdk = new MossClient(creds.projectId, creds.projectKey); const localState: { loadedIndexName?: string } = {}; - await ensureLocalIndexLoaded(sdk, cfg.indexName, localState); + await ensureLocalIndexLoaded(client, cfg.indexName, localState); mossLog( log, "Moss: loadIndex completed (local query cache warmed).", diff --git a/packages/vscode-moss/src/runMossQuery.ts b/packages/vscode-moss/src/runMossQuery.ts index 4ad1377f..b4ecb946 100644 --- a/packages/vscode-moss/src/runMossQuery.ts +++ b/packages/vscode-moss/src/runMossQuery.ts @@ -1,6 +1,7 @@ import type { MossClient, QueryResultDocumentInfo } from "@moss-dev/moss"; import * as vscode from "vscode"; import { getMossConfig, resolveCredentials } from "./config.js"; +import { formatError } from "./formatError.js"; import { ensureLocalIndexLoaded, type LocalIndexLoadState } from "./mossQueryState.js"; import { mossLog } from "./mossLog.js"; @@ -15,10 +16,6 @@ export interface SearchFailure { message: string; } -function formatError(e: unknown): string { - return e instanceof Error ? e.message : String(e); -} - function lineLabel(meta: Record): string { const start = meta.startLine?.trim() ?? ""; const end = meta.endLine?.trim() ?? ""; diff --git a/packages/vscode-moss/src/searchViewProvider.ts b/packages/vscode-moss/src/searchViewProvider.ts index 36b22727..72782910 100644 --- a/packages/vscode-moss/src/searchViewProvider.ts +++ b/packages/vscode-moss/src/searchViewProvider.ts @@ -1,4 +1,5 @@ import { MossClient, type QueryResultDocumentInfo } from "@moss-dev/moss"; +import { randomBytes } from "node:crypto"; import * as vscode from "vscode"; import { getMossConfig, resolveCredentials } from "./config.js"; import { ensureLocalIndexLoaded, clearLocalIndexLoadState, type LocalIndexLoadState } from "./mossQueryState.js"; @@ -443,9 +444,10 @@ async function openSearchHit(hit: QueryResultDocumentInfo): Promise { function getNonce(): string { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + const bytes = randomBytes(32); let result = ""; for (let i = 0; i < 32; i++) { - result += chars.charAt(Math.floor(Math.random() * chars.length)); + result += chars[bytes[i]! % chars.length]!; } return result; } diff --git a/packages/vscode-moss/src/structureChunking.ts b/packages/vscode-moss/src/structureChunking.ts index 7df9260f..7f8df7b7 100644 --- a/packages/vscode-moss/src/structureChunking.ts +++ b/packages/vscode-moss/src/structureChunking.ts @@ -229,6 +229,9 @@ async function ensureParser(): Promise { const nm = nodeModulesRoot(); parserInit = TreeSitter.Parser.init({ locateFile: (base: string) => path.join(nm, "web-tree-sitter", base), + }).catch((err: unknown) => { + parserInit = undefined; + return Promise.reject(err); }); } await parserInit; diff --git a/packages/vscode-moss/test/config.test.ts b/packages/vscode-moss/test/config.test.ts index d92207c8..1dd6c4c2 100644 --- a/packages/vscode-moss/test/config.test.ts +++ b/packages/vscode-moss/test/config.test.ts @@ -174,4 +174,21 @@ describe("getMossConfig", () => { expect(c.indexName).toBe("vscode-moss-alpha-beta"); }); + it("clamps invalid numeric settings to safe defaults or caps", async () => { + const ws = Uri.file("/repo"); + setMossTestConfig(ws.toString(), { + projectId: "p", + projectKey: "k", + maxFileSizeBytes: -1, + topK: 9999, + chunkMaxLines: 0, + chunkOverlapLines: -5, + }); + const folder: WorkspaceFolder = { uri: ws, name: "r", index: 0 }; + const c = await getMossConfig(memorySecrets(), folder); + expect(c.maxFileSizeBytes).toBe(1_048_576); + expect(c.topK).toBe(100); + expect(c.chunkMaxLines).toBe(100); + expect(c.chunkOverlapLines).toBe(12); + }); }); From 5884a6f41c0eb7b3d50b68f971e8aa0a86ee0c49 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Mon, 6 Apr 2026 23:44:31 -0400 Subject: [PATCH 14/21] made some further improvements --- packages/vscode-moss/media/searchView.js | 20 ++++++- packages/vscode-moss/package.json | 7 +++ packages/vscode-moss/src/runMossQuery.ts | 42 +++++++++++++-- .../vscode-moss/src/searchViewProvider.ts | 52 +++++++++++++++---- 4 files changed, 104 insertions(+), 17 deletions(-) diff --git a/packages/vscode-moss/media/searchView.js b/packages/vscode-moss/media/searchView.js index 6030a868..51b9e03f 100644 --- a/packages/vscode-moss/media/searchView.js +++ b/packages/vscode-moss/media/searchView.js @@ -124,12 +124,17 @@ .join(""); } + function hitRowDomId(hitIndex) { + return "moss-hit-" + hitIndex; + } + function getResultRows() { return [...resultList.querySelectorAll(".result-row")]; } function clearResultSelection() { selectedHitIndex = -1; + resultList.removeAttribute("aria-activedescendant"); getResultRows().forEach((el) => { el.classList.remove("result-row--selected"); el.setAttribute("aria-selected", "false"); @@ -150,6 +155,12 @@ el.scrollIntoView({ block: "nearest" }); } }); + if (selectedHitIndex >= 0 && rows[selectedHitIndex]) { + const id = rows[selectedHitIndex].id; + if (id) resultList.setAttribute("aria-activedescendant", id); + } else { + resultList.removeAttribute("aria-activedescendant"); + } } function openHitIndex(idx) { @@ -250,6 +261,7 @@ indexPrep.classList.remove("visible"); } resultList.innerHTML = ""; + resultList.removeAttribute("aria-activedescendant"); resultList.style.display = "none"; emptyBlock.style.display = "none"; } @@ -283,6 +295,7 @@ indexPrep.classList.remove("visible"); } resultList.innerHTML = ""; + resultList.removeAttribute("aria-activedescendant"); resultList.style.display = "none"; emptyBlock.style.display = "block"; emptyState.innerHTML = DEFAULT_EMPTY_HTML; @@ -294,6 +307,7 @@ showError(msg.message || "Search failed."); resultList.style.display = "none"; resultList.innerHTML = ""; + resultList.removeAttribute("aria-activedescendant"); emptyBlock.style.display = "block"; emptyState.innerHTML = "Could not complete this search. Fix the issue above, then try again."; @@ -310,6 +324,7 @@ "No results. Try different wording or run Moss: Index Workspace."; resultList.style.display = "none"; resultList.innerHTML = ""; + resultList.removeAttribute("aria-activedescendant"); const t = typeof msg.timeMs === "number" ? msg.timeMs + " ms" : ""; meta.textContent = t ? "0 results · " + t : "0 results"; return; @@ -332,8 +347,11 @@ const score = typeof h.score === "number" ? h.score.toFixed(3) : ""; const snippet = highlightSnippet(h.snippet || "", queryText); + const domId = hitRowDomId(h.index); return ( - '
  • ' + '
    ' + diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json index a2520b4a..85a3e754 100644 --- a/packages/vscode-moss/package.json +++ b/packages/vscode-moss/package.json @@ -23,6 +23,13 @@ }, "type": "module", "main": "./out/extension.js", + "activationEvents": [ + "onView:moss.searchView", + "onCommand:moss.indexWorkspace", + "onCommand:moss.search", + "onCommand:moss.configureCredentials", + "onCommand:moss.openSettings" + ], "contributes": { "commands": [ { diff --git a/packages/vscode-moss/src/runMossQuery.ts b/packages/vscode-moss/src/runMossQuery.ts index b4ecb946..8a815c95 100644 --- a/packages/vscode-moss/src/runMossQuery.ts +++ b/packages/vscode-moss/src/runMossQuery.ts @@ -9,7 +9,8 @@ export type SearchErrorCode = | "NO_WORKSPACE" | "NO_CREDENTIALS" | "INDEX_NOT_FOUND" - | "QUERY_FAILED"; + | "QUERY_FAILED" + | "CANCELLED"; export interface SearchFailure { code: SearchErrorCode; @@ -31,6 +32,14 @@ export interface RunMossQueryHooks { onLocalIndexDownloadFinished?: () => void; } +export type RunMossQueryOptions = RunMossQueryHooks & { + token?: vscode.CancellationToken; + /** + * When set, skips `resolveCredentials` (caller already validated credentials). + */ + credentials?: { projectId: string; projectKey: string }; +}; + export interface MossQuerySession { client: MossClient; localIndexState: LocalIndexLoadState; @@ -40,16 +49,22 @@ export interface MossQuerySession { * Semantic search against the configured workspace index. * Uses `session` for the Moss client and local `loadIndex` state (sidebar search lifetime). */ +function cancelledFailure(): SearchFailure { + return { code: "CANCELLED", message: "" }; +} + export async function runMossQuery( context: vscode.ExtensionContext, queryText: string, log: vscode.OutputChannel, session: MossQuerySession, - hooks?: RunMossQueryHooks + options?: RunMossQueryOptions ): Promise< | { ok: true; hits: QueryResultDocumentInfo[]; timeMs?: number } | { ok: false; error: SearchFailure } > { + const token = options?.token; + const folders = vscode.workspace.workspaceFolders; if (!folders?.length) { return { @@ -61,7 +76,12 @@ export async function runMossQuery( }; } - const creds = await resolveCredentials(context); + if (token?.isCancellationRequested) { + return { ok: false, error: cancelledFailure() }; + } + + const creds = + options?.credentials ?? (await resolveCredentials(context)); if (!creds) { return { ok: false, @@ -73,17 +93,25 @@ export async function runMossQuery( }; } + if (token?.isCancellationRequested) { + return { ok: false, error: cancelledFailure() }; + } + const primary = folders[0]!; const cfg = await getMossConfig(context.secrets, primary); const sdk = session.client; + if (token?.isCancellationRequested) { + return { ok: false, error: cancelledFailure() }; + } + const state = session.localIndexState; const willAttemptLocalLoad = state.loadedIndexName !== cfg.indexName && state.localLoadFailedIndex !== cfg.indexName; if (willAttemptLocalLoad) { - hooks?.onAwaitingLocalIndexDownload?.(); + options?.onAwaitingLocalIndexDownload?.(); } try { await ensureLocalIndexLoaded(sdk, cfg.indexName, state); @@ -95,10 +123,14 @@ export async function runMossQuery( ); } finally { if (willAttemptLocalLoad) { - hooks?.onLocalIndexDownloadFinished?.(); + options?.onLocalIndexDownloadFinished?.(); } } + if (token?.isCancellationRequested) { + return { ok: false, error: cancelledFailure() }; + } + try { const result = await sdk.query(cfg.indexName, queryText, { topK: cfg.topK, diff --git a/packages/vscode-moss/src/searchViewProvider.ts b/packages/vscode-moss/src/searchViewProvider.ts index 72782910..4eb837dc 100644 --- a/packages/vscode-moss/src/searchViewProvider.ts +++ b/packages/vscode-moss/src/searchViewProvider.ts @@ -20,6 +20,7 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { }; private _localIndexState: LocalIndexLoadState = {}; private _webviewMessageDisposable?: vscode.Disposable; + private _queryCts?: vscode.CancellationTokenSource; constructor( private readonly _extensionUri: vscode.Uri, @@ -29,10 +30,17 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { /** Drop Moss client + local `loadIndex` state (sidebar closed, credentials changed, or index rebuilt). */ public resetSearchSession(): void { + this._disposeQueryCancellation(); this._session = undefined; clearLocalIndexLoadState(this._localIndexState); } + private _disposeQueryCancellation(): void { + this._queryCts?.cancel(); + this._queryCts?.dispose(); + this._queryCts = undefined; + } + private _clientFor(projectId: string, projectKey: string): MossClient { if ( this._session?.projectId === projectId && @@ -90,6 +98,7 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { webviewView.onDidDispose(() => { this._webviewMessageDisposable?.dispose(); this._webviewMessageDisposable = undefined; + this._disposeQueryCancellation(); this._view = undefined; warmCts.cancel(); warmCts.dispose(); @@ -127,19 +136,34 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { if (!webview) return; if (text === "") { - webview.postMessage({ type: "clearResults" }); + this._disposeQueryCancellation(); + this._querySeq += 1; + if (this._view?.webview === webview) { + webview.postMessage({ type: "clearResults" }); + } return; } + this._disposeQueryCancellation(); + this._queryCts = new vscode.CancellationTokenSource(); + const queryToken = this._queryCts.token; + const seq = ++this._querySeq; - webview.postMessage({ type: "loading", loading: true }); - webview.postMessage({ type: "clearError" }); + + const post = (message: unknown): void => { + if (seq !== this._querySeq) return; + if (this._view?.webview !== webview) return; + webview.postMessage(message); + }; + + post({ type: "loading", loading: true }); + post({ type: "clearError" }); const creds = await resolveCredentials(this._context); if (!creds) { if (seq !== this._querySeq) return; - webview.postMessage({ type: "loading", loading: false }); - webview.postMessage({ + post({ type: "loading", loading: false }); + post({ type: "error", code: "NO_CREDENTIALS", message: @@ -155,24 +179,30 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { this._log, { client, localIndexState: this._localIndexState }, { + token: queryToken, + credentials: creds, onAwaitingLocalIndexDownload: () => { - webview.postMessage({ + post({ type: "localIndexLoading", text: "Downloading index for local search — first time can take a minute…", }); }, onLocalIndexDownloadFinished: () => { - webview.postMessage({ type: "localIndexLoading", text: "" }); + post({ type: "localIndexLoading", text: "" }); }, } ); + if (!result.ok && result.error.code === "CANCELLED") { + return; + } + if (seq !== this._querySeq) return; - webview.postMessage({ type: "loading", loading: false }); + post({ type: "loading", loading: false }); if (!result.ok) { - webview.postMessage({ + post({ type: "error", code: result.error.code, message: result.error.message, @@ -181,7 +211,7 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { } this._lastHits = result.hits; - webview.postMessage({ + post({ type: "results", query: text, hits: result.hits.map((h, index) => ({ @@ -406,7 +436,7 @@ export class MossSearchViewProvider implements vscode.WebviewViewProvider { Open Moss settings

    - + From e756a89ca422761fedaff3ed3f4abcb4d0ef4c74 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Wed, 8 Apr 2026 20:48:29 -0400 Subject: [PATCH 15/21] added a doc explaining indexing flow --- packages/vscode-moss/INDEXING.md | 117 +++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 packages/vscode-moss/INDEXING.md diff --git a/packages/vscode-moss/INDEXING.md b/packages/vscode-moss/INDEXING.md new file mode 100644 index 00000000..cd28ddaa --- /dev/null +++ b/packages/vscode-moss/INDEXING.md @@ -0,0 +1,117 @@ +# Indexing flow in vscode-moss + +This document describes **how workspace indexing works** inside the Moss VS Code extension: entry point, file discovery, chunking, upload, and what happens afterward. For a shorter checklist and code map, see [`WORKFLOW.md`](./WORKFLOW.md). For a Markdown-documentation–oriented pipeline (render → HTML → heading-aware chunks), see the repo’s [**moss-md-indexer** workflow](https://github.com/usemoss/moss/blob/main/packages/moss-md-indexer/INDEXER-WORKFLOW.md). + +## Entry point + +Indexing runs when the user triggers **`Moss: Index Workspace`** (command `moss.indexWorkspace`), including from the status bar item registered in `extension.ts`. The implementation lives in **`runIndexWorkspace`** in [`src/indexWorkspace.ts`](./src/indexWorkspace.ts). + + Preconditions: + +- At least one **workspace folder** must be open; otherwise the command shows an error and returns. +- **Credentials** must resolve via `resolveCredentials` (settings, SecretStorage, or `MOSS_PROJECT_ID` / `MOSS_PROJECT_KEY`). If missing, the user sees an error and indexing does not start. + +The work runs inside **`vscode.window.withProgress`** (notification area, **cancellable**). + +## Configuration resolution + +Before any I/O, the extension loads **`getMossConfig`** for the **first workspace folder** (`workspaceFolders[0]`). That yields: + +- **`indexName`** — from `moss.indexName` or auto-generated from the workspace name when empty. +- **`includeGlobs` / `excludeGlobs`** — merged with extra safe excludes (`EXTRA_SAFE_EXCLUDES`, e.g. `**/.svn/**`) so dangerous paths are always filtered. +- **`maxFileSizeBytes`**, **`chunkMaxLines`**, **`chunkOverlapLines`**, **`modelId`**, etc. + +Multi-root workspaces: **all roots are scanned**, but **settings** (globs, index name, chunk options) come from the **primary** folder only, consistent with the extension README. + +## Step 1 — Discover files + +**`findWorkspaceFiles`** uses `vscode.workspace.findFiles` with: + +- **Includes** — from config (default effectively `**/*` if nothing is set). +- **Excludes** — brace-combined when possible, or multiple scans per include pattern. +- **Cap** — at most **`MAX_FILE_SCAN` (80,000)** URIs; if the scan hits the cap, indexing continues with a **warning** so users can narrow `moss.includeGlob` / `moss.excludeGlob`. + +Files are **deduped** and **sorted** by `fsPath` for stable ordering. + +## Step 2 — Read, filter, and chunk per file + +For each URI (with cancellation checks between files): + +1. **Workspace membership** — Skip if the file is not under any `WorkspaceFolder`. +2. **Binary extension** — Skip paths whose extension is in a fixed denylist (archives, images, binaries, fonts, etc.). +3. **Size** — Skip if `stat.size > maxFileSizeBytes`. +4. **Text** — Read bytes and decode as **UTF-8** with `fatal: true`; skip if decode fails or a `NUL` byte appears (treated as non-text). +5. **Relative path** — `asRelativePath` must be non-empty. +6. **Chunking** — **`chunkFileContent`** ([`chunking.ts`](./src/chunking.ts)) with: + - `languageId` from the file extension where supported (Markdown, JS/TS, Python, Rust, Go, Java, Ruby, PHP, C/C++, C#, etc.). + - **Structure-aware** chunks when the language is wired for Tree-sitter in [`structureChunking.ts`](./src/structureChunking.ts). + - **Line-window fallback** in [`chunkCore.ts`](./src/chunkCore.ts) when structure-aware splitting is not used. + +Each chunk becomes a Moss **`DocumentInfo`**: stable **`id`**, **`text`**, and string **`metadata`** (e.g. `path`, `startLine`, `endLine`; in multi-root, `workspaceFolderIndex` / `workspaceFolderName`). + +**Chunk budget** — The in-memory list **`allDocs`** is capped at **`MAX_MOSS_DOCUMENTS` (60,000)**. When the limit is reached, remaining files are skipped and a **warning** is shown. + +If no documents are produced (everything skipped or empty), indexing stops with a warning and **no** API upload. + +## Step 3 — Upload to Moss + +Progress shows **“Uploading index to Moss…”**. + +1. Construct **`MossClient(projectId, projectKey)`**. +2. **`deleteIndex(indexName)`** — Wrapped in **`tolerateDeleteIndex`**: “not found” style errors are treated as OK; other failures are logged as warnings but do not necessarily abort (see implementation for exact behavior). +3. **`createIndex(indexName, allDocs, { modelId })`** — Full replace of the remote index content for that name. + +On **success**: + +- **`notifySearchIndexStale()`** — Tells sidebar search to **`resetSearchSession()`** so stale `loadIndex` / client state is cleared after a full reindex. +- **`workspaceState`** is updated under **`MOSS_LAST_INDEXED_KEY`** with index name, chunk count, file count, and timestamp (drives the status bar “indexed Xm ago” text). +- **`notifyMossIndexed()`** refreshes the status bar immediately. + +On **`createIndex` failure**, the user sees an error message; workspace last-indexed state is **not** updated for this run. + +## Step 4 — Local search cache warm-up (optional) + +After upload, progress shows **“Preparing local search cache…”** and the code **`await sleep(POST_CREATE_SETTLE_MS)`** (**2.5s**) to let the service settle before downloading. + +Then **`ensureLocalIndexLoaded(client, cfg.indexName, localState)`** runs on the **same** `MossClient` used for upload. The `localState` object is **fresh** for this call only (not shared with the sidebar session). + +- If **`loadIndex`** succeeds, verbose logs note that the local query cache is warmed. +- If it **fails**, indexing still **succeeded**; search falls back to **cloud** `query` until a later successful `loadIndex` (for example from the sidebar). A non-cancellation cancel after upload may skip warm-up and show an informational message. + +Finally, an information message summarizes files indexed and chunk count. + +## Cancellation + +The user can cancel from the progress notification. The implementation checks **`token.isCancellationRequested`** after the scan, during the per-file loop, before upload, before `createIndex`, and before / after the settle delay. Partial work is not uploaded unless `createIndex` already completed. + +## Code reference summary + +| Concern | Location | +|--------|-----------| +| Command registration | `src/extension.ts` | +| Orchestration, scan, upload, warm-up | `src/indexWorkspace.ts` (`runIndexWorkspace`, `findWorkspaceFiles`, `tolerateDeleteIndex`) | +| Credentials and `moss.*` resolution | `src/config.ts` | +| Chunking | `src/chunking.ts`, `src/chunkCore.ts`, `src/structureChunking.ts` | +| Last-indexed persistence (status bar) | `src/lastIndexed.ts`, `src/mossStatusBar.ts` | +| Invalidate sidebar search after reindex | `src/mossQueryState.ts` (`notifySearchIndexStale`) | +| Local index helper | `src/mossQueryState.ts` (`ensureLocalIndexLoaded`) | + +## Diagram (high level) + +```mermaid +flowchart TD + A[Moss: Index Workspace] --> B{Open folder + credentials?} + B -->|no| Z[Show error] + B -->|yes| C[Resolve moss config for workspaceFolders0] + C --> D[findWorkspaceFiles capped at 80k] + D --> E[For each file: filter, UTF-8 read, chunkFileContent] + E --> F{Any documents?} + F -->|no| W[Warning and stop] + F -->|yes| G[deleteIndex tolerate missing] + G --> H[createIndex] + H -->|fail| E2[Error and stop] + H -->|ok| I[notifySearchIndexStale + save last indexed + status bar] + I --> J[Sleep 2.5s] + J --> K[ensureLocalIndexLoaded optional] + K --> L[Success message] +``` From 48f3ca4c1cf79106b93f39896e16725067b17079 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Wed, 8 Apr 2026 21:20:51 -0400 Subject: [PATCH 16/21] fixed bug where you have to re-select the bar after a keystroke --- packages/vscode-moss/media/searchView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vscode-moss/media/searchView.js b/packages/vscode-moss/media/searchView.js index 51b9e03f..b6ed6c8d 100644 --- a/packages/vscode-moss/media/searchView.js +++ b/packages/vscode-moss/media/searchView.js @@ -53,7 +53,8 @@ }); function setLoading(loading) { - input.disabled = loading; + // Do not disable the query input while loading: disabling removes focus in the + // webview, so live search would force a click back into the field after each query. btn.disabled = loading; btn.textContent = loading ? "Searching…" : "Search"; } @@ -173,7 +174,6 @@ clearTimeout(searchDebounceId); searchDebounceId = null; } - if (input.disabled) return; const text = input.value.trim(); clearError(); persistQuery(); From 3bc77e10e46d3e4d7cd80001873283d469a0637b Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Wed, 8 Apr 2026 22:25:38 -0400 Subject: [PATCH 17/21] made an audit fix --- packages/vscode-moss/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/vscode-moss/package-lock.json b/packages/vscode-moss/package-lock.json index 8eb92ad7..0da8b419 100644 --- a/packages/vscode-moss/package-lock.json +++ b/packages/vscode-moss/package-lock.json @@ -5715,9 +5715,9 @@ } }, "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", + "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", "dev": true, "license": "MIT", "dependencies": { From f7b8d5bb9d5686a65b5e936ee3a6f68da58d568f Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Wed, 8 Apr 2026 22:51:58 -0400 Subject: [PATCH 18/21] added some logging --- packages/vscode-moss/src/indexWorkspace.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/vscode-moss/src/indexWorkspace.ts b/packages/vscode-moss/src/indexWorkspace.ts index 9bee1794..f79b0fa5 100644 --- a/packages/vscode-moss/src/indexWorkspace.ts +++ b/packages/vscode-moss/src/indexWorkspace.ts @@ -292,6 +292,7 @@ export async function runIndexWorkspace( ]); progress.report({ message: "Scanning files…" }); + mossLog(log, "Moss: Scanning workspace for files…"); const { uris, scanTruncated } = await findWorkspaceFiles( cfg.includeGlobs, excludeGlobs, @@ -311,6 +312,10 @@ export async function runIndexWorkspace( } mossLog(log, `Moss: Found ${uris.length} file(s) to consider.`, "verbose"); + mossLog( + log, + `Moss: Reading and chunking ${uris.length} file(s) — progress is shown in the notification…` + ); uris.sort((a, b) => a.fsPath.localeCompare(b.fsPath)); @@ -418,6 +423,10 @@ export async function runIndexWorkspace( } progress.report({ message: "Uploading index to Moss…", increment: 0 }); + mossLog( + log, + `Moss: Uploading ${allDocs.length} chunk(s) to Moss (createIndex)…` + ); const client = new MossClient(creds.projectId, creds.projectKey); From 38de39769103fcd7a04514957a510ef742597e67 Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Sat, 11 Apr 2026 02:09:39 -0400 Subject: [PATCH 19/21] added logging for progress incase workspace is large --- packages/vscode-moss/src/indexWorkspace.ts | 29 +++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/vscode-moss/src/indexWorkspace.ts b/packages/vscode-moss/src/indexWorkspace.ts index f79b0fa5..2ca810ee 100644 --- a/packages/vscode-moss/src/indexWorkspace.ts +++ b/packages/vscode-moss/src/indexWorkspace.ts @@ -11,7 +11,7 @@ import { import { mossLog } from "./mossLog.js"; import { ensureLocalIndexLoaded, notifySearchIndexStale } from "./mossQueryState.js"; import { notifyMossIndexed } from "./mossStatusBar.js"; -import type { DocumentInfo } from "@moss-dev/moss"; +import type { DocumentInfo, JobProgress } from "@moss-dev/moss"; const MAX_FILE_SCAN = 80_000; const MAX_MOSS_DOCUMENTS = 60_000; @@ -427,9 +427,30 @@ export async function runIndexWorkspace( log, `Moss: Uploading ${allDocs.length} chunk(s) to Moss (createIndex)…` ); + if (allDocs.length >= 5_000) { + mossLog( + log, + "Moss: Large index — upload and server-side embedding can take many minutes; progress updates appear below.", + "verbose" + ); + } const client = new MossClient(creds.projectId, creds.projectKey); + const reportCreateProgress = (p: JobProgress) => { + const phase = + p.currentPhase != null ? ` · ${p.currentPhase}` : ""; + progress.report({ + message: `Uploading index to Moss… ${p.status} ${p.progress}%${phase}`, + increment: 0, + }); + mossLog( + log, + `Moss: createIndex progress — ${p.status} ${p.progress}%${phase} (job ${p.jobId})`, + "verbose" + ); + }; + try { await tolerateDeleteIndex(client, cfg.indexName, log); if (token.isCancellationRequested) { @@ -437,8 +458,14 @@ export async function runIndexWorkspace( return; } + progress.report({ + message: "Uploading index to Moss… starting", + increment: 0, + }); + await client.createIndex(cfg.indexName, allDocs, { modelId: cfg.modelId, + onProgress: reportCreateProgress, }); notifySearchIndexStale(); mossLog( From fb025a0eb85ded45ef0e47ae25a1f3e880519e4b Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Sat, 18 Apr 2026 13:31:07 -0400 Subject: [PATCH 20/21] moss now respects .gitignores by default --- packages/vscode-moss/INDEXING.md | 3 ++ packages/vscode-moss/README.md | 1 + packages/vscode-moss/package-lock.json | 2 +- packages/vscode-moss/package.json | 7 ++++ packages/vscode-moss/src/config.ts | 6 +++ packages/vscode-moss/src/extension.ts | 1 + packages/vscode-moss/src/gitignoreFilter.ts | 46 +++++++++++++++++++++ packages/vscode-moss/src/indexWorkspace.ts | 16 ++++++- packages/vscode-moss/test/config.test.ts | 23 +++++++++++ 9 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 packages/vscode-moss/src/gitignoreFilter.ts diff --git a/packages/vscode-moss/INDEXING.md b/packages/vscode-moss/INDEXING.md index cd28ddaa..72dfc70e 100644 --- a/packages/vscode-moss/INDEXING.md +++ b/packages/vscode-moss/INDEXING.md @@ -19,6 +19,7 @@ Before any I/O, the extension loads **`getMossConfig`** for the **first workspac - **`indexName`** — from `moss.indexName` or auto-generated from the workspace name when empty. - **`includeGlobs` / `excludeGlobs`** — merged with extra safe excludes (`EXTRA_SAFE_EXCLUDES`, e.g. `**/.svn/**`) so dangerous paths are always filtered. +- **`respectGitignore`** — when true (default), apply each folder’s root `.gitignore` after the glob scan (see Step 1 below). - **`maxFileSizeBytes`**, **`chunkMaxLines`**, **`chunkOverlapLines`**, **`modelId`**, etc. Multi-root workspaces: **all roots are scanned**, but **settings** (globs, index name, chunk options) come from the **primary** folder only, consistent with the extension README. @@ -33,6 +34,8 @@ Multi-root workspaces: **all roots are scanned**, but **settings** (globs, index Files are **deduped** and **sorted** by `fsPath` for stable ordering. +When **`moss.respectGitignore`** is true (default), **`filterUrisByRootGitignore`** drops URIs that match each workspace folder’s **root** `.gitignore` (via the [`ignore`](https://www.npmjs.com/package/ignore) package, same semantics as Git for that file). **Nested** `.gitignore` files are not loaded. Set **`moss.respectGitignore`** to false to index ignored paths (for example build output). + ## Step 2 — Read, filter, and chunk per file For each URI (with cancellation checks between files): diff --git a/packages/vscode-moss/README.md b/packages/vscode-moss/README.md index 83cedb41..02e0efe8 100644 --- a/packages/vscode-moss/README.md +++ b/packages/vscode-moss/README.md @@ -45,6 +45,7 @@ File paths and file contents you index are sent to **Moss** (cloud) for embeddin | `indexName` | Index name (default derived from workspace folder name). | | `modelId` | Embedding model for `createIndex`. | | `includeGlob` / `excludeGlob` | Which files to crawl when indexing. | +| `respectGitignore` | When `true` (default), skip paths matched by each workspace folder’s **root** `.gitignore`. | | `maxFileSizeBytes` | Skip larger files. | | `topK` | Number of search hits. | | `alpha` | Hybrid search blend: `1.0` = semantic only, `0.0` = keyword only (default `0.8`). | diff --git a/packages/vscode-moss/package-lock.json b/packages/vscode-moss/package-lock.json index 0da8b419..d4935f63 100644 --- a/packages/vscode-moss/package-lock.json +++ b/packages/vscode-moss/package-lock.json @@ -10,6 +10,7 @@ "license": "BSD-2-Clause", "dependencies": { "@moss-dev/moss": "^1.0.0", + "ignore": "^7.0.5", "tree-sitter-c": "^0.24.1", "tree-sitter-c-sharp": "^0.23.1", "tree-sitter-cpp": "^0.23.4", @@ -3231,7 +3232,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4" diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json index 85a3e754..949bc404 100644 --- a/packages/vscode-moss/package.json +++ b/packages/vscode-moss/package.json @@ -122,6 +122,12 @@ "description": "Glob pattern(s) for files to exclude when indexing (merged with built-in defaults).", "scope": "resource" }, + "moss.respectGitignore": { + "type": "boolean", + "default": true, + "description": "Exclude files that match each workspace folder's root `.gitignore` when discovering files for indexing. Set false to include ignored paths (for example generated output). Nested `.gitignore` files below the root file are not applied.", + "scope": "resource" + }, "moss.maxFileSizeBytes": { "type": "number", "default": 1048576, @@ -169,6 +175,7 @@ }, "dependencies": { "@moss-dev/moss": "^1.0.0", + "ignore": "^7.0.5", "tree-sitter-c": "^0.24.1", "tree-sitter-c-sharp": "^0.23.1", "tree-sitter-cpp": "^0.23.4", diff --git a/packages/vscode-moss/src/config.ts b/packages/vscode-moss/src/config.ts index c0b0c001..c2d282d5 100644 --- a/packages/vscode-moss/src/config.ts +++ b/packages/vscode-moss/src/config.ts @@ -64,6 +64,8 @@ export interface ResolvedConfig { alpha: number; chunkMaxLines: number; chunkOverlapLines: number; + /** When true, paths matching the workspace folder root `.gitignore` are excluded from indexing. */ + respectGitignore: boolean; workspaceFolder: vscode.WorkspaceFolder; } @@ -185,6 +187,9 @@ export async function getMossConfig( CHUNK_OVERLAP_CAP ); + const respectGitignoreRaw = cfg.get("respectGitignore"); + const respectGitignore = respectGitignoreRaw !== false; + return { projectId, projectKey, @@ -197,6 +202,7 @@ export async function getMossConfig( alpha, chunkMaxLines, chunkOverlapLines, + respectGitignore, workspaceFolder: folder, }; } diff --git a/packages/vscode-moss/src/extension.ts b/packages/vscode-moss/src/extension.ts index 5f9aaaf9..fc8889cd 100644 --- a/packages/vscode-moss/src/extension.ts +++ b/packages/vscode-moss/src/extension.ts @@ -35,6 +35,7 @@ export function activate(context: vscode.ExtensionContext): void { "moss.modelId", "moss.includeGlob", "moss.excludeGlob", + "moss.respectGitignore", "moss.maxFileSizeBytes", "moss.chunkMaxLines", "moss.chunkOverlapLines", diff --git a/packages/vscode-moss/src/gitignoreFilter.ts b/packages/vscode-moss/src/gitignoreFilter.ts new file mode 100644 index 00000000..c31cecf1 --- /dev/null +++ b/packages/vscode-moss/src/gitignoreFilter.ts @@ -0,0 +1,46 @@ +import ignore from "ignore"; +import * as vscode from "vscode"; + +/** + * Drop URIs whose path matches the **workspace-folder root** `.gitignore`, + * using the same matching rules as Git for that file (via the `ignore` package). + * Nested `.gitignore` files in subdirectories are not read (same patterns often + * appear in the root file in monorepos). + */ +export async function filterUrisByRootGitignore( + uris: vscode.Uri[], + folders: readonly vscode.WorkspaceFolder[] +): Promise { + if (uris.length === 0) return uris; + + const igByFolderUri = new Map>(); + await Promise.all( + folders.map(async (folder) => { + let ig = ignore(); + try { + const giUri = vscode.Uri.joinPath(folder.uri, ".gitignore"); + const bytes = await vscode.workspace.fs.readFile(giUri); + let text = new TextDecoder("utf-8").decode(bytes); + if (text.charCodeAt(0) === 0xfeff) { + text = text.slice(1); + } + ig = ignore().add(text); + } catch { + // Missing or unreadable `.gitignore` → no extra excludes. + } + igByFolderUri.set(folder.uri.toString(), ig); + }) + ); + + return uris.filter((uri) => { + const folder = vscode.workspace.getWorkspaceFolder(uri); + if (!folder) return true; + const ig = igByFolderUri.get(folder.uri.toString()); + if (!ig) return true; + + const rel = vscode.workspace.asRelativePath(uri, false); + if (!rel) return true; + const posix = rel.replace(/\\/g, "/"); + return !ig.ignores(posix); + }); +} diff --git a/packages/vscode-moss/src/indexWorkspace.ts b/packages/vscode-moss/src/indexWorkspace.ts index 2ca810ee..16414263 100644 --- a/packages/vscode-moss/src/indexWorkspace.ts +++ b/packages/vscode-moss/src/indexWorkspace.ts @@ -8,6 +8,7 @@ import { MOSS_LAST_INDEXED_KEY, type LastIndexedState, } from "./lastIndexed.js"; +import { filterUrisByRootGitignore } from "./gitignoreFilter.js"; import { mossLog } from "./mossLog.js"; import { ensureLocalIndexLoaded, notifySearchIndexStale } from "./mossQueryState.js"; import { notifyMossIndexed } from "./mossStatusBar.js"; @@ -293,7 +294,7 @@ export async function runIndexWorkspace( progress.report({ message: "Scanning files…" }); mossLog(log, "Moss: Scanning workspace for files…"); - const { uris, scanTruncated } = await findWorkspaceFiles( + let { uris, scanTruncated } = await findWorkspaceFiles( cfg.includeGlobs, excludeGlobs, MAX_FILE_SCAN, @@ -305,6 +306,19 @@ export async function runIndexWorkspace( return; } + if (cfg.respectGitignore) { + const before = uris.length; + uris = await filterUrisByRootGitignore(uris, folders); + const dropped = before - uris.length; + if (dropped > 0) { + mossLog( + log, + `Moss: Skipped ${dropped} file(s) matched by root .gitignore (moss.respectGitignore).`, + "verbose" + ); + } + } + if (scanTruncated) { const msg = `File scan stopped at ${MAX_FILE_SCAN} files. Narrow moss.includeGlob or add moss.excludeGlob to index a smaller set.`; mossLog(log, msg); diff --git a/packages/vscode-moss/test/config.test.ts b/packages/vscode-moss/test/config.test.ts index 1dd6c4c2..fb5eadb3 100644 --- a/packages/vscode-moss/test/config.test.ts +++ b/packages/vscode-moss/test/config.test.ts @@ -174,6 +174,29 @@ describe("getMossConfig", () => { expect(c.indexName).toBe("vscode-moss-alpha-beta"); }); + it("defaults respectGitignore to true when unset", async () => { + const ws = Uri.file("/repo"); + setMossTestConfig(ws.toString(), { + projectId: "p", + projectKey: "k", + }); + const folder: WorkspaceFolder = { uri: ws, name: "r", index: 0 }; + const c = await getMossConfig(memorySecrets(), folder); + expect(c.respectGitignore).toBe(true); + }); + + it("respectGitignore false when configured", async () => { + const ws = Uri.file("/repo"); + setMossTestConfig(ws.toString(), { + projectId: "p", + projectKey: "k", + respectGitignore: false, + }); + const folder: WorkspaceFolder = { uri: ws, name: "r", index: 0 }; + const c = await getMossConfig(memorySecrets(), folder); + expect(c.respectGitignore).toBe(false); + }); + it("clamps invalid numeric settings to safe defaults or caps", async () => { const ws = Uri.file("/repo"); setMossTestConfig(ws.toString(), { From 6701a99741620629590361aaf6b5d4f2b8100d8a Mon Sep 17 00:00:00 2001 From: ankitmukherjee101 Date: Wed, 22 Apr 2026 19:37:04 -0400 Subject: [PATCH 21/21] single truth for credentials --- packages/vscode-moss/INDEXING.md | 2 +- packages/vscode-moss/README.md | 9 +- packages/vscode-moss/WORKFLOW.md | 2 +- packages/vscode-moss/package.json | 19 +-- packages/vscode-moss/src/config.ts | 148 +++++++++++++++---- packages/vscode-moss/src/extension.ts | 175 ++++++++++++----------- packages/vscode-moss/test/config.test.ts | 161 +++++++++++++++------ packages/vscode-moss/test/vscode-stub.ts | 2 +- 8 files changed, 345 insertions(+), 173 deletions(-) diff --git a/packages/vscode-moss/INDEXING.md b/packages/vscode-moss/INDEXING.md index 72dfc70e..c8c9739e 100644 --- a/packages/vscode-moss/INDEXING.md +++ b/packages/vscode-moss/INDEXING.md @@ -9,7 +9,7 @@ Indexing runs when the user triggers **`Moss: Index Workspace`** (command `moss. Preconditions: - At least one **workspace folder** must be open; otherwise the command shows an error and returns. -- **Credentials** must resolve via `resolveCredentials` (settings, SecretStorage, or `MOSS_PROJECT_ID` / `MOSS_PROJECT_KEY`). If missing, the user sees an error and indexing does not start. +- **Credentials** must resolve via `resolveCredentials` / `resolveCredentialsForWorkspace`: **per-workspace credentials blob** (Secret Storage, keyed by workspace folder URI), then environment pair (`MOSS_PROJECT_ID` + `MOSS_PROJECT_KEY`), then migration from the legacy global key + `MOSS_PROJECT_ID`, then env project ID + legacy/`MOSS_PROJECT_KEY`. If missing, the user sees an error and indexing does not start. The work runs inside **`vscode.window.withProgress`** (notification area, **cancellable**). diff --git a/packages/vscode-moss/README.md b/packages/vscode-moss/README.md index 02e0efe8..74a7eafd 100644 --- a/packages/vscode-moss/README.md +++ b/packages/vscode-moss/README.md @@ -23,7 +23,7 @@ VS Code extension for **semantic codebase search** with [Moss](https://moss.dev) ## Search your workspace -1. Set credentials: **Moss: Configure credentials** (pick **Project ID and project key** or **Project key only**; in key-only mode, an empty field removes the stored key), or set **`moss.projectId`** / **`moss.projectKey`** in settings, or **`MOSS_PROJECT_ID`** / **`MOSS_PROJECT_KEY`** in the environment. +1. Set credentials: **Moss: Configure credentials** (prompts for project ID and project key — stored together per workspace). To remove stored credentials, run **Moss: Clear credentials**. Alternatively set **`MOSS_PROJECT_ID`** and **`MOSS_PROJECT_KEY`** in the environment (credentials are not Moss settings — they live in Secret Storage or env). 2. Run **Moss: Index Workspace** (crawl + chunk + upload to Moss). 3. Open the **Moss** icon in the activity bar → **Search**, or run **Moss: Search** from the Command Palette. Type a query (search runs as you pause typing, ~320ms debounce; **Enter** or **Search** runs immediately); click a result to jump to the file and line range. @@ -41,7 +41,7 @@ File paths and file contents you index are sent to **Moss** (cloud) for embeddin | Setting | Purpose | |--------|---------| -| `projectId` / `projectKey` | Moss project credentials (key: prefer SecretStorage via commands). | +| Credentials | **Moss: Configure credentials** (per-workspace Secret Storage) or **`MOSS_PROJECT_ID`** / **`MOSS_PROJECT_KEY`** env — not user settings. | | `indexName` | Index name (default derived from workspace folder name). | | `modelId` | Embedding model for `createIndex`. | | `includeGlob` / `excludeGlob` | Which files to crawl when indexing. | @@ -93,10 +93,7 @@ This extension uses **`"type": "module"`** (ESM); **`out/extension.js`** is buil ### Credentials (F5 / dev) -Either: - -- Set **`MOSS_PROJECT_ID`** and **`MOSS_PROJECT_KEY`** in the environment (recommended for F5: add `env` in **`packages/vscode-moss/.vscode/launch.json`**, or use your OS environment), or -- Set **`moss.projectId`** and **`moss.projectKey`** in VS Code Settings (workspace or user). +Set **`MOSS_PROJECT_ID`** and **`MOSS_PROJECT_KEY`** in the Extension Development Host environment (recommended: `env` in **`packages/vscode-moss/.vscode/launch.json`**) or use your OS environment. Project credentials are not Moss settings keys. ### Run the extension (monorepo) diff --git a/packages/vscode-moss/WORKFLOW.md b/packages/vscode-moss/WORKFLOW.md index 4283e0f8..3c4e28e8 100644 --- a/packages/vscode-moss/WORKFLOW.md +++ b/packages/vscode-moss/WORKFLOW.md @@ -4,7 +4,7 @@ This document describes how **vscode-moss** turns workspace files into a Moss in ## 1. High-level flow -1. **Configure** — Resolve Moss `projectId` / `projectKey` (settings, SecretStorage, or env). **`moss.*` for indexing/search is resolved against the first workspace folder** (`workspaceFolders[0]`); multi-root workspaces still index all roots, but include/exclude, `indexName`, chunk options, and search `topK` / `alpha` come from that folder’s effective settings only (see README). +1. **Configure** — Resolve Moss credentials (per-workspace Secret Storage blob keyed by folder URI; then env pair; legacy migration). Credentials are **not** `moss.*` settings. **`moss.*` for indexing/search is resolved against the first workspace folder** (`workspaceFolders[0]`); multi-root workspaces still index all roots, but include/exclude, `indexName`, chunk options, and search `topK` / `alpha` come from that folder’s effective settings only (see README). 2. **Discover** — Scan the workspace with `vscode.workspace.findFiles`, merging the primary folder’s `moss.includeGlob`, `moss.excludeGlob`, and extra safe excludes (e.g. `.git`, `node_modules`). Caps apply (`MAX_FILE_SCAN`, `MAX_MOSS_DOCUMENTS`). 3. **Filter** — Skip binary-by-extension files, oversize files, and paths that fail UTF-8 decode. 4. **Chunk** — For each file, read text and call `chunkFileContent` (`chunking.ts`): diff --git a/packages/vscode-moss/package.json b/packages/vscode-moss/package.json index 949bc404..be61e350 100644 --- a/packages/vscode-moss/package.json +++ b/packages/vscode-moss/package.json @@ -28,6 +28,7 @@ "onCommand:moss.indexWorkspace", "onCommand:moss.search", "onCommand:moss.configureCredentials", + "onCommand:moss.clearCredentials", "onCommand:moss.openSettings" ], "contributes": { @@ -44,6 +45,10 @@ "command": "moss.configureCredentials", "title": "Moss: Configure credentials" }, + { + "command": "moss.clearCredentials", + "title": "Moss: Clear credentials" + }, { "command": "moss.openSettings", "title": "Moss: Open Settings" @@ -70,16 +75,6 @@ "configuration": { "title": "Moss", "properties": { - "moss.projectId": { - "type": "string", - "default": "", - "description": "Moss project ID (required). Also accepted via MOSS_PROJECT_ID environment variable." - }, - "moss.projectKey": { - "type": "string", - "default": "", - "description": "Moss project key. Prefer 'Moss: Configure credentials' (project key only) for secure storage. Also accepted via MOSS_PROJECT_KEY environment variable." - }, "moss.indexName": { "type": "string", "default": "", @@ -148,12 +143,12 @@ "moss.chunkMaxLines": { "type": "number", "default": 100, - "description": "Maximum number of lines per chunk when indexing files." + "description": "Maximum lines per indexed chunk (each Moss document). Structure-aware indexing splits large logical spans into overlapping windows of at most this size; plain text and unsupported languages use sliding line windows only." }, "moss.chunkOverlapLines": { "type": "number", "default": 12, - "description": "Number of overlapping lines between consecutive chunks." + "description": "Lines of overlap between consecutive windows when a span is subdivided (structure-aware split or full-file line-window fallback)." }, "moss.logVerbose": { "type": "boolean", diff --git a/packages/vscode-moss/src/config.ts b/packages/vscode-moss/src/config.ts index c2d282d5..56afae72 100644 --- a/packages/vscode-moss/src/config.ts +++ b/packages/vscode-moss/src/config.ts @@ -1,6 +1,13 @@ +import { createHash } from "node:crypto"; import * as vscode from "vscode"; -export const MOSS_SECRET_KEY_PROJECT_KEY = "moss.projectKey"; +/** Legacy global SecretStorage key for project key only (pre–workspace blobs). Used for migration + fallback. */ +export const MOSS_LEGACY_GLOBAL_PROJECT_KEY = "moss.projectKey"; + +/** @deprecated Use {@link MOSS_LEGACY_GLOBAL_PROJECT_KEY}. */ +export const MOSS_SECRET_KEY_PROJECT_KEY = MOSS_LEGACY_GLOBAL_PROJECT_KEY; + +const MOSS_CREDENTIALS_SECRET_PREFIX = "moss.credentials.v1"; /** When true, Moss output includes extra indexing / spike / search detail (Phase 8). */ export function getMossLogVerbose(): boolean { @@ -101,17 +108,79 @@ export function defaultIndexNameForFolder(folder: vscode.WorkspaceFolder): strin } /** - * Project key precedence: SecretStorage → `moss.projectKey` → `MOSS_PROJECT_KEY`. + * Stable SecretStorage key for this workspace folder’s Moss credentials JSON blob. */ -export async function resolveProjectKey( +export function workspaceCredentialsSecretKey(folder: vscode.WorkspaceFolder): string { + const digest = createHash("sha256").update(folder.uri.toString()).digest("hex"); + return `${MOSS_CREDENTIALS_SECRET_PREFIX}.${digest}`; +} + +export interface MossCredentialsPayload { + projectId: string; + projectKey: string; +} + +function parseCredentialsBlob(raw: string): MossCredentialsPayload | undefined { + try { + const data: unknown = JSON.parse(raw); + if (typeof data !== "object" || data === null || Array.isArray(data)) return undefined; + const rec = data as Record; + const projectId = + typeof rec.projectId === "string" ? rec.projectId.trim() : ""; + const projectKey = + typeof rec.projectKey === "string" ? rec.projectKey.trim() : ""; + if (!projectId || !projectKey) return undefined; + return { projectId, projectKey }; + } catch { + return undefined; + } +} + +export async function readCredentialsBlob( secrets: vscode.SecretStorage, - cfg: vscode.WorkspaceConfiguration -): Promise { - const fromSecret = await secrets.get(MOSS_SECRET_KEY_PROJECT_KEY); - if (fromSecret?.trim()) return fromSecret.trim(); + folder: vscode.WorkspaceFolder +): Promise { + const raw = await secrets.get(workspaceCredentialsSecretKey(folder)); + if (!raw) return undefined; + return parseCredentialsBlob(raw); +} + +export async function storeCredentialsForWorkspace( + secrets: vscode.SecretStorage, + folder: vscode.WorkspaceFolder, + creds: MossCredentialsPayload +): Promise { + const payload: MossCredentialsPayload = { + projectId: creds.projectId.trim(), + projectKey: creds.projectKey.trim(), + }; + await secrets.store( + workspaceCredentialsSecretKey(folder), + JSON.stringify(payload) + ); +} - const fromCfg = cfg.get("projectKey")?.trim(); - if (fromCfg) return fromCfg; +export async function deleteCredentialsForWorkspace( + secrets: vscode.SecretStorage, + folder: vscode.WorkspaceFolder +): Promise { + await secrets.delete(workspaceCredentialsSecretKey(folder)); +} + +function resolveProjectIdFromEnv(): string | undefined { + return process.env.MOSS_PROJECT_ID?.trim(); +} + +/** + * Fallback when no workspace credentials blob exists: legacy global SecretStorage entry + * (see {@link MOSS_LEGACY_GLOBAL_PROJECT_KEY}) → `MOSS_PROJECT_KEY`. + * Project ID / key are not read from `settings.json` — use the configure command or env. + */ +export async function resolveProjectKey( + secrets: vscode.SecretStorage +): Promise { + const fromLegacy = await secrets.get(MOSS_LEGACY_GLOBAL_PROJECT_KEY); + if (fromLegacy?.trim()) return fromLegacy.trim(); const fromEnv = process.env.MOSS_PROJECT_KEY?.trim(); if (fromEnv) return fromEnv; @@ -119,28 +188,56 @@ export async function resolveProjectKey( return undefined; } -function resolveProjectId(cfg: vscode.WorkspaceConfiguration): string | undefined { - const fromCfg = cfg.get("projectId")?.trim(); - if (fromCfg) return fromCfg; - return process.env.MOSS_PROJECT_ID?.trim(); -} - /** - * Global Moss credentials (unscoped config), same precedence as Phase 0. + * Moss credentials for one workspace folder. Precedence: + * 1. Workspace credentials blob (SecretStorage, per folder URI) + * 2. Environment pair: both `MOSS_PROJECT_ID` and `MOSS_PROJECT_KEY` + * 3. Migration: legacy global project-key secret + `MOSS_PROJECT_ID` → persisted as workspace blob + * 4. Assemble `MOSS_PROJECT_ID` (env) + {@link resolveProjectKey} (legacy secret or `MOSS_PROJECT_KEY`) */ -export async function resolveCredentials( - context: vscode.ExtensionContext -): Promise<{ projectId: string; projectKey: string } | undefined> { - const cfg = vscode.workspace.getConfiguration("moss"); - const projectId = resolveProjectId(cfg); +export async function resolveCredentialsForWorkspace( + secrets: vscode.SecretStorage, + folder: vscode.WorkspaceFolder +): Promise { + const fromBlob = await readCredentialsBlob(secrets, folder); + if (fromBlob) return fromBlob; + + const envId = process.env.MOSS_PROJECT_ID?.trim(); + const envKey = process.env.MOSS_PROJECT_KEY?.trim(); + if (envId && envKey) { + return { projectId: envId, projectKey: envKey }; + } + + const projectId = resolveProjectIdFromEnv(); + const legacyGlobalKey = await secrets.get(MOSS_LEGACY_GLOBAL_PROJECT_KEY); + if (projectId && legacyGlobalKey?.trim()) { + const migrated: MossCredentialsPayload = { + projectId, + projectKey: legacyGlobalKey.trim(), + }; + await storeCredentialsForWorkspace(secrets, folder, migrated); + return migrated; + } + if (!projectId) return undefined; - const projectKey = await resolveProjectKey(context.secrets, cfg); + const projectKey = await resolveProjectKey(secrets); if (!projectKey) return undefined; return { projectId, projectKey }; } +/** + * Credentials for the first workspace folder (sidebar / search / index entry points). + */ +export async function resolveCredentials( + context: vscode.ExtensionContext +): Promise { + const folder = vscode.workspace.workspaceFolders?.[0]; + if (!folder) return undefined; + return resolveCredentialsForWorkspace(context.secrets, folder); +} + /** * Moss settings + credentials for one workspace folder (`moss.*` scoped to that folder's URI). */ @@ -150,8 +247,7 @@ export async function getMossConfig( ): Promise { const cfg = vscode.workspace.getConfiguration("moss", folder.uri); - const projectId = resolveProjectId(cfg); - const projectKey = await resolveProjectKey(secrets, cfg); + const creds = await resolveCredentialsForWorkspace(secrets, folder); const configuredIndex = cfg.get("indexName")?.trim(); const indexName = @@ -191,8 +287,8 @@ export async function getMossConfig( const respectGitignore = respectGitignoreRaw !== false; return { - projectId, - projectKey, + projectId: creds?.projectId, + projectKey: creds?.projectKey, indexName, modelId, includeGlobs, diff --git a/packages/vscode-moss/src/extension.ts b/packages/vscode-moss/src/extension.ts index fc8889cd..d713a95b 100644 --- a/packages/vscode-moss/src/extension.ts +++ b/packages/vscode-moss/src/extension.ts @@ -1,12 +1,55 @@ import * as vscode from "vscode"; import { - MOSS_SECRET_KEY_PROJECT_KEY, + deleteCredentialsForWorkspace, + readCredentialsBlob, + storeCredentialsForWorkspace, } from "./config.js"; import { runIndexWorkspace } from "./indexWorkspace.js"; import { registerSearchIndexStaleHandler } from "./mossQueryState.js"; import { registerMossStatusBar } from "./mossStatusBar.js"; import { MossSearchViewProvider } from "./searchViewProvider.js"; +/** + * Focus the Settings UI on Moss options. Cursor (and some VS Code builds) ignore the + * **string** query passed to `openSettings2`; the supported shape is `{ query: string }`. + * See https://github.com/microsoft/vscode/issues/226071 + * Fallback: `vscode://settings/` reveals a contributed setting (same scheme in Cursor). + */ +async function revealMossSettings(): Promise { + try { + await vscode.commands.executeCommand("workbench.action.openSettings2", { + query: "moss.", + }); + return; + } catch { + /* fall through */ + } + try { + await vscode.commands.executeCommand( + "workbench.action.openSettings2", + "moss." + ); + return; + } catch { + /* fall through */ + } + try { + await vscode.commands.executeCommand( + "workbench.action.openSettings", + "moss." + ); + return; + } catch { + /* fall through */ + } + const opened = await vscode.env.openExternal( + vscode.Uri.parse("vscode://settings/moss.indexName") + ); + if (!opened) { + await vscode.commands.executeCommand("workbench.action.openSettings"); + } +} + // ── Activation ─────────────────────────────────────────────────────── export function activate(context: vscode.ExtensionContext): void { @@ -27,8 +70,6 @@ export function activate(context: vscode.ExtensionContext): void { context.subscriptions.push( vscode.workspace.onDidChangeConfiguration((e) => { const mossKeysAffectingSession = [ - "moss.projectId", - "moss.projectKey", "moss.indexName", "moss.topK", "moss.alpha", @@ -60,12 +101,8 @@ export function activate(context: vscode.ExtensionContext): void { ); context.subscriptions.push( - vscode.commands.registerCommand("moss.openSettings", async () => { - // Filter must match package.json publisher + name (moss-dev / vscode-moss). - await vscode.commands.executeCommand( - "workbench.action.openSettings", - "@ext:moss-dev.vscode-moss" - ); + vscode.commands.registerCommand("moss.openSettings", () => { + void revealMossSettings(); }) ); @@ -79,112 +116,84 @@ export function activate(context: vscode.ExtensionContext): void { }) ); - // moss.configureCredentials — QuickPick: full setup (ID + key) or key-only (empty clears) + // moss.configureCredentials — prompt project ID then key (one pair per workspace blob) context.subscriptions.push( vscode.commands.registerCommand("moss.configureCredentials", async () => { - type CredAction = "idAndKey" | "keyOnly"; - interface CredPick extends vscode.QuickPickItem { - action: CredAction; - } - const items: CredPick[] = [ - { - label: "Project ID and project key", - description: "Save project ID to settings; optionally set a new key", - action: "idAndKey", - }, - { - label: "Project key only", - description: "Update or clear the key in secure storage (empty input removes it)", - action: "keyOnly", - }, - ]; - const choice = await vscode.window.showQuickPick(items, { - title: "Moss", - placeHolder: "What do you want to configure?", - ignoreFocusOut: true, - }); - if (!choice) return; - - if (choice.action === "keyOnly") { - const key = await vscode.window.showInputBox({ - title: "Moss", - prompt: "Project key", - password: true, - ignoreFocusOut: true, - placeHolder: "Leave empty to remove the key from secure storage", - }); - if (key === undefined) return; - if (key === "") { - await context.secrets.delete(MOSS_SECRET_KEY_PROJECT_KEY); - searchProvider.resetSearchSession(); - void vscode.window.showInformationMessage( - "Moss: Project key removed from secure storage." - ); - } else { - await context.secrets.store(MOSS_SECRET_KEY_PROJECT_KEY, key); - searchProvider.resetSearchSession(); - void vscode.window.showInformationMessage( - "Moss: Project key saved to secure storage." - ); - } + const folders = vscode.workspace.workspaceFolders; + if (!folders?.length) { + void vscode.window.showWarningMessage( + "Moss: Open a folder or workspace before configuring credentials." + ); return; } + const primary = folders[0]!; - const cfg = vscode.workspace.getConfiguration("moss"); - const currentId = cfg.get("projectId")?.trim() ?? ""; + const currentId = + (await readCredentialsBlob(context.secrets, primary))?.projectId ?? + process.env.MOSS_PROJECT_ID?.trim() ?? + ""; const projectId = await vscode.window.showInputBox({ - title: "Moss", + title: "Moss — project credentials", prompt: "Project ID", value: currentId, ignoreFocusOut: true, - placeHolder: "Your Moss project id", + placeHolder: "Your Moss project ID", }); if (projectId === undefined) return; const trimmedId = projectId.trim(); if (!trimmedId) { void vscode.window.showWarningMessage( - "Moss: Project ID is required. Nothing was saved." + "Moss: Project ID is required." ); return; } - const projectKey = await vscode.window.showInputBox({ - title: "Moss", + const projectKeyInput = await vscode.window.showInputBox({ + title: "Moss — project credentials", prompt: "Project key", password: true, ignoreFocusOut: true, - placeHolder: "Leave empty to keep the existing key in secure storage", + placeHolder: "Your Moss project key", }); - if (projectKey === undefined) return; - - const configTarget = - vscode.workspace.workspaceFolders && - vscode.workspace.workspaceFolders.length > 0 - ? vscode.ConfigurationTarget.Workspace - : vscode.ConfigurationTarget.Global; - - try { - await cfg.update("projectId", trimmedId, configTarget); - } catch (e: unknown) { - const msg = e instanceof Error ? e.message : String(e); - void vscode.window.showErrorMessage( - `Moss: Could not save project ID: ${msg}` + if (projectKeyInput === undefined) return; + + const trimmedKey = projectKeyInput.trim(); + if (!trimmedKey) { + void vscode.window.showWarningMessage( + "Moss: Project key is required. Run “Moss: Clear credentials” to remove stored credentials." ); return; } - if (projectKey !== "") { - await context.secrets.store(MOSS_SECRET_KEY_PROJECT_KEY, projectKey); - } + await storeCredentialsForWorkspace(context.secrets, primary, { + projectId: trimmedId, + projectKey: trimmedKey, + }); searchProvider.resetSearchSession(); void vscode.window.showInformationMessage( - projectKey !== "" - ? "Moss: Project ID saved to settings and project key saved to secure storage." - : "Moss: Project ID saved to settings. Project key unchanged." + "Moss: Credentials saved for this workspace (secure storage)." + ); + }) + ); + + context.subscriptions.push( + vscode.commands.registerCommand("moss.clearCredentials", async () => { + const folders = vscode.workspace.workspaceFolders; + if (!folders?.length) { + void vscode.window.showWarningMessage( + "Moss: Open a folder or workspace first." + ); + return; + } + const primary = folders[0]!; + await deleteCredentialsForWorkspace(context.secrets, primary); + searchProvider.resetSearchSession(); + void vscode.window.showInformationMessage( + "Moss: Workspace credentials removed from secure storage." ); }) ); diff --git a/packages/vscode-moss/test/config.test.ts b/packages/vscode-moss/test/config.test.ts index fb5eadb3..345c23d6 100644 --- a/packages/vscode-moss/test/config.test.ts +++ b/packages/vscode-moss/test/config.test.ts @@ -1,13 +1,15 @@ import { afterEach, describe, expect, it } from "vitest"; -import type { SecretStorage, WorkspaceConfiguration } from "vscode"; +import type { SecretStorage } from "vscode"; import { DEFAULT_QUERY_ALPHA, - MOSS_SECRET_KEY_PROJECT_KEY, + MOSS_LEGACY_GLOBAL_PROJECT_KEY, defaultIndexNameForFolder, getMossConfig, getMossLogVerbose, + resolveCredentialsForWorkspace, resolveProjectKey, resolveQueryAlpha, + workspaceCredentialsSecretKey, } from "../src/config.js"; import { resetMossTestConfig, @@ -30,13 +32,16 @@ function memorySecrets(initial: Record = {}): SecretStorage { }; } -function cfgFrom(values: Record): WorkspaceConfiguration { - return { - get: (key: string) => values[key] as T, - has: () => false, - inspect: () => undefined, - update: async () => undefined, - }; +/** Seed workspace blob so getMossConfig resolves credentials without env. */ +function secretsWithWorkspaceCreds( + folder: WorkspaceFolder, + projectId: string, + projectKey: string +): SecretStorage { + const key = workspaceCredentialsSecretKey(folder); + return memorySecrets({ + [key]: JSON.stringify({ projectId, projectKey }), + }); } describe("defaultIndexNameForFolder", () => { @@ -83,31 +88,108 @@ describe("resolveProjectKey", () => { else process.env.MOSS_PROJECT_KEY = prevKey; }); - it("prefers SecretStorage over settings and env", async () => { + it("prefers legacy global SecretStorage over MOSS_PROJECT_KEY", async () => { process.env.MOSS_PROJECT_KEY = "env-key"; - const secrets = memorySecrets({ [MOSS_SECRET_KEY_PROJECT_KEY]: "secret-key" }); - const cfg = cfgFrom({ projectKey: "cfg-key" }); - expect(await resolveProjectKey(secrets, cfg)).toBe("secret-key"); + const secrets = memorySecrets({ + [MOSS_LEGACY_GLOBAL_PROJECT_KEY]: "secret-key", + }); + expect(await resolveProjectKey(secrets)).toBe("secret-key"); }); - it("uses settings when no secret", async () => { + it("uses MOSS_PROJECT_KEY when no legacy secret", async () => { + process.env.MOSS_PROJECT_KEY = "env-only"; const secrets = memorySecrets(); - const cfg = cfgFrom({ projectKey: "cfg-key" }); - expect(await resolveProjectKey(secrets, cfg)).toBe("cfg-key"); + expect(await resolveProjectKey(secrets)).toBe("env-only"); }); - it("uses MOSS_PROJECT_KEY when no secret or cfg", async () => { - process.env.MOSS_PROJECT_KEY = "env-only"; + it("returns undefined when nothing set", async () => { + delete process.env.MOSS_PROJECT_KEY; const secrets = memorySecrets(); - const cfg = cfgFrom({}); - expect(await resolveProjectKey(secrets, cfg)).toBe("env-only"); + expect(await resolveProjectKey(secrets)).toBeUndefined(); }); +}); - it("returns undefined when nothing set", async () => { +describe("resolveCredentialsForWorkspace", () => { + const prevId = process.env.MOSS_PROJECT_ID; + const prevKey = process.env.MOSS_PROJECT_KEY; + + afterEach(() => { + resetMossTestConfig(); + if (prevId === undefined) delete process.env.MOSS_PROJECT_ID; + else process.env.MOSS_PROJECT_ID = prevId; + if (prevKey === undefined) delete process.env.MOSS_PROJECT_KEY; + else process.env.MOSS_PROJECT_KEY = prevKey; + }); + + it("prefers workspace blob over legacy secret and env", async () => { + process.env.MOSS_PROJECT_ID = "env-pid"; + process.env.MOSS_PROJECT_KEY = "env-pkey"; + const ws = Uri.file("/alpha"); + const folder: WorkspaceFolder = { uri: ws, name: "alpha", index: 0 }; + const blobKey = workspaceCredentialsSecretKey(folder); + const secrets = memorySecrets({ + [blobKey]: JSON.stringify({ + projectId: "blob-pid", + projectKey: "blob-pkey", + }), + [MOSS_LEGACY_GLOBAL_PROJECT_KEY]: "legacy-key", + }); + const r = await resolveCredentialsForWorkspace(secrets, folder); + expect(r).toEqual({ projectId: "blob-pid", projectKey: "blob-pkey" }); + }); + + it("migrates legacy global key + MOSS_PROJECT_ID into workspace blob", async () => { delete process.env.MOSS_PROJECT_KEY; + process.env.MOSS_PROJECT_ID = "m-pid"; + const ws = Uri.file("/migrate"); + const folder: WorkspaceFolder = { uri: ws, name: "migrate", index: 0 }; + const blobKey = workspaceCredentialsSecretKey(folder); + const secrets = memorySecrets({ + [MOSS_LEGACY_GLOBAL_PROJECT_KEY]: "legacy-k", + }); + const r = await resolveCredentialsForWorkspace(secrets, folder); + expect(r).toEqual({ projectId: "m-pid", projectKey: "legacy-k" }); + const stored = await secrets.get(blobKey); + expect(stored).toBe( + JSON.stringify({ projectId: "m-pid", projectKey: "legacy-k" }) + ); + }); + + it("uses env pair when no blob", async () => { + process.env.MOSS_PROJECT_ID = "eid"; + process.env.MOSS_PROJECT_KEY = "ekey"; + const ws = Uri.file("/envonly"); + const folder: WorkspaceFolder = { uri: ws, name: "envonly", index: 0 }; const secrets = memorySecrets(); - const cfg = cfgFrom({}); - expect(await resolveProjectKey(secrets, cfg)).toBeUndefined(); + const r = await resolveCredentialsForWorkspace(secrets, folder); + expect(r).toEqual({ projectId: "eid", projectKey: "ekey" }); + }); + + it("isolates credentials by workspace folder URI", async () => { + delete process.env.MOSS_PROJECT_ID; + delete process.env.MOSS_PROJECT_KEY; + const wsA = Uri.file("/proj-a"); + const wsB = Uri.file("/proj-b"); + const folderA: WorkspaceFolder = { uri: wsA, name: "a", index: 0 }; + const folderB: WorkspaceFolder = { uri: wsB, name: "b", index: 1 }; + const secrets = memorySecrets({ + [workspaceCredentialsSecretKey(folderA)]: JSON.stringify({ + projectId: "ida", + projectKey: "ka", + }), + [workspaceCredentialsSecretKey(folderB)]: JSON.stringify({ + projectId: "idb", + projectKey: "kb", + }), + }); + expect(await resolveCredentialsForWorkspace(secrets, folderA)).toEqual({ + projectId: "ida", + projectKey: "ka", + }); + expect(await resolveCredentialsForWorkspace(secrets, folderB)).toEqual({ + projectId: "idb", + projectKey: "kb", + }); }); }); @@ -140,11 +222,10 @@ describe("getMossConfig", () => { const ws = Uri.file("/repo"); setMossTestConfig(ws.toString(), { indexName: "my-custom-index", - projectId: "pid", - projectKey: "pk", }); const folder: WorkspaceFolder = { uri: ws, name: "repo", index: 0 }; - const c = await getMossConfig(memorySecrets(), folder); + const secrets = secretsWithWorkspaceCreds(folder, "pid", "pk"); + const c = await getMossConfig(secrets, folder); expect(c.indexName).toBe("my-custom-index"); expect(c.topK).toBe(10); expect(c.alpha).toBe(DEFAULT_QUERY_ALPHA); @@ -153,12 +234,11 @@ describe("getMossConfig", () => { it("uses configured alpha when set", async () => { const ws = Uri.file("/repo"); setMossTestConfig(ws.toString(), { - projectId: "pid", - projectKey: "pk", alpha: 0.35, }); const folder: WorkspaceFolder = { uri: ws, name: "repo", index: 0 }; - const c = await getMossConfig(memorySecrets(), folder); + const secrets = secretsWithWorkspaceCreds(folder, "pid", "pk"); + const c = await getMossConfig(secrets, folder); expect(c.alpha).toBe(0.35); }); @@ -166,49 +246,44 @@ describe("getMossConfig", () => { const ws = Uri.file("/repo"); setMossTestConfig(ws.toString(), { indexName: "", - projectId: "p", - projectKey: "k", }); const folder: WorkspaceFolder = { uri: ws, name: "alpha-beta", index: 0 }; - const c = await getMossConfig(memorySecrets(), folder); + const secrets = secretsWithWorkspaceCreds(folder, "p", "k"); + const c = await getMossConfig(secrets, folder); expect(c.indexName).toBe("vscode-moss-alpha-beta"); }); it("defaults respectGitignore to true when unset", async () => { const ws = Uri.file("/repo"); - setMossTestConfig(ws.toString(), { - projectId: "p", - projectKey: "k", - }); + setMossTestConfig(ws.toString(), {}); const folder: WorkspaceFolder = { uri: ws, name: "r", index: 0 }; - const c = await getMossConfig(memorySecrets(), folder); + const secrets = secretsWithWorkspaceCreds(folder, "p", "k"); + const c = await getMossConfig(secrets, folder); expect(c.respectGitignore).toBe(true); }); it("respectGitignore false when configured", async () => { const ws = Uri.file("/repo"); setMossTestConfig(ws.toString(), { - projectId: "p", - projectKey: "k", respectGitignore: false, }); const folder: WorkspaceFolder = { uri: ws, name: "r", index: 0 }; - const c = await getMossConfig(memorySecrets(), folder); + const secrets = secretsWithWorkspaceCreds(folder, "p", "k"); + const c = await getMossConfig(secrets, folder); expect(c.respectGitignore).toBe(false); }); it("clamps invalid numeric settings to safe defaults or caps", async () => { const ws = Uri.file("/repo"); setMossTestConfig(ws.toString(), { - projectId: "p", - projectKey: "k", maxFileSizeBytes: -1, topK: 9999, chunkMaxLines: 0, chunkOverlapLines: -5, }); const folder: WorkspaceFolder = { uri: ws, name: "r", index: 0 }; - const c = await getMossConfig(memorySecrets(), folder); + const secrets = secretsWithWorkspaceCreds(folder, "p", "k"); + const c = await getMossConfig(secrets, folder); expect(c.maxFileSizeBytes).toBe(1_048_576); expect(c.topK).toBe(100); expect(c.chunkMaxLines).toBe(100); diff --git a/packages/vscode-moss/test/vscode-stub.ts b/packages/vscode-moss/test/vscode-stub.ts index c191fe00..f9f82201 100644 --- a/packages/vscode-moss/test/vscode-stub.ts +++ b/packages/vscode-moss/test/vscode-stub.ts @@ -32,7 +32,7 @@ export function resetMossTestConfig(): void { mossConfigByScope.clear(); } -/** Keys match `get("projectId")` etc. on the `moss` configuration section. */ +/** Keys match `get("indexName")` etc. on the `moss` configuration section (no credential keys). */ export function setMossTestConfig( resourceUri: string | undefined, values: Record