@angri450/zvec-grep 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +319 -0
- package/README_CN.md +297 -0
- package/dist/authorization/index.d.ts +7 -0
- package/dist/authorization/index.js +7 -0
- package/dist/authorization/index.js.map +1 -0
- package/dist/authorization/manager.d.ts +8 -0
- package/dist/authorization/manager.js +19 -0
- package/dist/authorization/manager.js.map +1 -0
- package/dist/authorization/operation.d.ts +7 -0
- package/dist/authorization/operation.js +50 -0
- package/dist/authorization/operation.js.map +1 -0
- package/dist/authorization/planner.d.ts +21 -0
- package/dist/authorization/planner.js +97 -0
- package/dist/authorization/planner.js.map +1 -0
- package/dist/authorization/prompt.d.ts +12 -0
- package/dist/authorization/prompt.js +63 -0
- package/dist/authorization/prompt.js.map +1 -0
- package/dist/authorization/store.d.ts +20 -0
- package/dist/authorization/store.js +251 -0
- package/dist/authorization/store.js.map +1 -0
- package/dist/authorization/target.d.ts +15 -0
- package/dist/authorization/target.js +49 -0
- package/dist/authorization/target.js.map +1 -0
- package/dist/authorization/types.d.ts +61 -0
- package/dist/authorization/types.js +2 -0
- package/dist/authorization/types.js.map +1 -0
- package/dist/cli/args.d.ts +6 -0
- package/dist/cli/args.js +1255 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/auth.d.ts +21 -0
- package/dist/cli/auth.js +209 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/commands.d.ts +4 -0
- package/dist/cli/commands.js +801 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/errors.d.ts +9 -0
- package/dist/cli/errors.js +131 -0
- package/dist/cli/errors.js.map +1 -0
- package/dist/cli/format/context.d.ts +9 -0
- package/dist/cli/format/context.js +786 -0
- package/dist/cli/format/context.js.map +1 -0
- package/dist/cli/format/debug.d.ts +4 -0
- package/dist/cli/format/debug.js +60 -0
- package/dist/cli/format/debug.js.map +1 -0
- package/dist/cli/format/highlight.d.ts +3 -0
- package/dist/cli/format/highlight.js +106 -0
- package/dist/cli/format/highlight.js.map +1 -0
- package/dist/cli/format/progress.d.ts +13 -0
- package/dist/cli/format/progress.js +290 -0
- package/dist/cli/format/progress.js.map +1 -0
- package/dist/cli/format/range.d.ts +3 -0
- package/dist/cli/format/range.js +24 -0
- package/dist/cli/format/range.js.map +1 -0
- package/dist/cli/format/status.d.ts +83 -0
- package/dist/cli/format/status.js +530 -0
- package/dist/cli/format/status.js.map +1 -0
- package/dist/cli/help.d.ts +1 -0
- package/dist/cli/help.js +546 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +40 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/install.d.ts +4 -0
- package/dist/cli/install.js +1735 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/managed-rg.d.ts +10 -0
- package/dist/cli/managed-rg.js +337 -0
- package/dist/cli/managed-rg.js.map +1 -0
- package/dist/cli/server-search.d.ts +3 -0
- package/dist/cli/server-search.js +12 -0
- package/dist/cli/server-search.js.map +1 -0
- package/dist/cli/types.d.ts +87 -0
- package/dist/cli/types.js +10 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/version.d.ts +1 -0
- package/dist/cli/version.js +13 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/client/daemon-client.d.ts +31 -0
- package/dist/client/daemon-client.js +203 -0
- package/dist/client/daemon-client.js.map +1 -0
- package/dist/client/mode-router.d.ts +9 -0
- package/dist/client/mode-router.js +28 -0
- package/dist/client/mode-router.js.map +1 -0
- package/dist/client/search-policy.d.ts +11 -0
- package/dist/client/search-policy.js +15 -0
- package/dist/client/search-policy.js.map +1 -0
- package/dist/daemon/backend.d.ts +78 -0
- package/dist/daemon/backend.js +1118 -0
- package/dist/daemon/backend.js.map +1 -0
- package/dist/daemon/change-set.d.ts +30 -0
- package/dist/daemon/change-set.js +163 -0
- package/dist/daemon/change-set.js.map +1 -0
- package/dist/daemon/config.d.ts +27 -0
- package/dist/daemon/config.js +107 -0
- package/dist/daemon/config.js.map +1 -0
- package/dist/daemon/errors.d.ts +5 -0
- package/dist/daemon/errors.js +11 -0
- package/dist/daemon/errors.js.map +1 -0
- package/dist/daemon/http-server.d.ts +30 -0
- package/dist/daemon/http-server.js +307 -0
- package/dist/daemon/http-server.js.map +1 -0
- package/dist/daemon/index-coordinator.d.ts +22 -0
- package/dist/daemon/index-coordinator.js +55 -0
- package/dist/daemon/index-coordinator.js.map +1 -0
- package/dist/daemon/job-scheduler.d.ts +85 -0
- package/dist/daemon/job-scheduler.js +492 -0
- package/dist/daemon/job-scheduler.js.map +1 -0
- package/dist/daemon/logger.d.ts +10 -0
- package/dist/daemon/logger.js +101 -0
- package/dist/daemon/logger.js.map +1 -0
- package/dist/daemon/model-pool.d.ts +48 -0
- package/dist/daemon/model-pool.js +190 -0
- package/dist/daemon/model-pool.js.map +1 -0
- package/dist/daemon/root-lease.d.ts +14 -0
- package/dist/daemon/root-lease.js +197 -0
- package/dist/daemon/root-lease.js.map +1 -0
- package/dist/daemon/root-runtime.d.ts +80 -0
- package/dist/daemon/root-runtime.js +340 -0
- package/dist/daemon/root-runtime.js.map +1 -0
- package/dist/daemon/runtime-manager.d.ts +47 -0
- package/dist/daemon/runtime-manager.js +252 -0
- package/dist/daemon/runtime-manager.js.map +1 -0
- package/dist/daemon/runtime.d.ts +12 -0
- package/dist/daemon/runtime.js +105 -0
- package/dist/daemon/runtime.js.map +1 -0
- package/dist/daemon/server-controller.d.ts +38 -0
- package/dist/daemon/server-controller.js +327 -0
- package/dist/daemon/server-controller.js.map +1 -0
- package/dist/daemon/watch-manager.d.ts +62 -0
- package/dist/daemon/watch-manager.js +415 -0
- package/dist/daemon/watch-manager.js.map +1 -0
- package/dist/daemon/workspace-read-session-cache.d.ts +31 -0
- package/dist/daemon/workspace-read-session-cache.js +115 -0
- package/dist/daemon/workspace-read-session-cache.js.map +1 -0
- package/dist/engine/code-formats.d.ts +3 -0
- package/dist/engine/code-formats.js +14 -0
- package/dist/engine/code-formats.js.map +1 -0
- package/dist/engine/config.d.ts +57 -0
- package/dist/engine/config.js +351 -0
- package/dist/engine/config.js.map +1 -0
- package/dist/engine/errors.d.ts +20 -0
- package/dist/engine/errors.js +51 -0
- package/dist/engine/errors.js.map +1 -0
- package/dist/engine/extraction/code/adapter.d.ts +19 -0
- package/dist/engine/extraction/code/adapter.js +24 -0
- package/dist/engine/extraction/code/adapter.js.map +1 -0
- package/dist/engine/extraction/code/extractor.d.ts +13 -0
- package/dist/engine/extraction/code/extractor.js +696 -0
- package/dist/engine/extraction/code/extractor.js.map +1 -0
- package/dist/engine/extraction/code/families/c-family.d.ts +2 -0
- package/dist/engine/extraction/code/families/c-family.js +122 -0
- package/dist/engine/extraction/code/families/c-family.js.map +1 -0
- package/dist/engine/extraction/code/families/js-ts.d.ts +12 -0
- package/dist/engine/extraction/code/families/js-ts.js +118 -0
- package/dist/engine/extraction/code/families/js-ts.js.map +1 -0
- package/dist/engine/extraction/code/families/metadata.d.ts +8 -0
- package/dist/engine/extraction/code/families/metadata.js +86 -0
- package/dist/engine/extraction/code/families/metadata.js.map +1 -0
- package/dist/engine/extraction/code/families/name-field.d.ts +3 -0
- package/dist/engine/extraction/code/families/name-field.js +22 -0
- package/dist/engine/extraction/code/families/name-field.js.map +1 -0
- package/dist/engine/extraction/code/languages/c.d.ts +1 -0
- package/dist/engine/extraction/code/languages/c.js +12 -0
- package/dist/engine/extraction/code/languages/c.js.map +1 -0
- package/dist/engine/extraction/code/languages/cpp.d.ts +1 -0
- package/dist/engine/extraction/code/languages/cpp.js +18 -0
- package/dist/engine/extraction/code/languages/cpp.js.map +1 -0
- package/dist/engine/extraction/code/languages/go.d.ts +2 -0
- package/dist/engine/extraction/code/languages/go.js +70 -0
- package/dist/engine/extraction/code/languages/go.js.map +1 -0
- package/dist/engine/extraction/code/languages/java.d.ts +1 -0
- package/dist/engine/extraction/code/languages/java.js +17 -0
- package/dist/engine/extraction/code/languages/java.js.map +1 -0
- package/dist/engine/extraction/code/languages/javascript.d.ts +2 -0
- package/dist/engine/extraction/code/languages/javascript.js +23 -0
- package/dist/engine/extraction/code/languages/javascript.js.map +1 -0
- package/dist/engine/extraction/code/languages/python.d.ts +2 -0
- package/dist/engine/extraction/code/languages/python.js +52 -0
- package/dist/engine/extraction/code/languages/python.js.map +1 -0
- package/dist/engine/extraction/code/languages/rust.d.ts +2 -0
- package/dist/engine/extraction/code/languages/rust.js +25 -0
- package/dist/engine/extraction/code/languages/rust.js.map +1 -0
- package/dist/engine/extraction/code/languages/typescript.d.ts +2 -0
- package/dist/engine/extraction/code/languages/typescript.js +37 -0
- package/dist/engine/extraction/code/languages/typescript.js.map +1 -0
- package/dist/engine/extraction/code/tree-sitter/grammar.d.ts +4 -0
- package/dist/engine/extraction/code/tree-sitter/grammar.js +49 -0
- package/dist/engine/extraction/code/tree-sitter/grammar.js.map +1 -0
- package/dist/engine/extraction/code/tree-sitter/nodes.d.ts +3 -0
- package/dist/engine/extraction/code/tree-sitter/nodes.js +27 -0
- package/dist/engine/extraction/code/tree-sitter/nodes.js.map +1 -0
- package/dist/engine/extraction/code/tree-sitter/parser.d.ts +2 -0
- package/dist/engine/extraction/code/tree-sitter/parser.js +31 -0
- package/dist/engine/extraction/code/tree-sitter/parser.js.map +1 -0
- package/dist/engine/extraction/ids.d.ts +1 -0
- package/dist/engine/extraction/ids.js +5 -0
- package/dist/engine/extraction/ids.js.map +1 -0
- package/dist/engine/extraction/image/extractor.d.ts +5 -0
- package/dist/engine/extraction/image/extractor.js +35 -0
- package/dist/engine/extraction/image/extractor.js.map +1 -0
- package/dist/engine/extraction/index.d.ts +4 -0
- package/dist/engine/extraction/index.js +3 -0
- package/dist/engine/extraction/index.js.map +1 -0
- package/dist/engine/extraction/markdown/extractor.d.ts +7 -0
- package/dist/engine/extraction/markdown/extractor.js +362 -0
- package/dist/engine/extraction/markdown/extractor.js.map +1 -0
- package/dist/engine/extraction/runtime.d.ts +9 -0
- package/dist/engine/extraction/runtime.js +37 -0
- package/dist/engine/extraction/runtime.js.map +1 -0
- package/dist/engine/extraction/source.d.ts +18 -0
- package/dist/engine/extraction/source.js +22 -0
- package/dist/engine/extraction/source.js.map +1 -0
- package/dist/engine/extraction/text/extractor.d.ts +7 -0
- package/dist/engine/extraction/text/extractor.js +168 -0
- package/dist/engine/extraction/text/extractor.js.map +1 -0
- package/dist/engine/extraction/types.d.ts +4 -0
- package/dist/engine/extraction/types.js +2 -0
- package/dist/engine/extraction/types.js.map +1 -0
- package/dist/engine/extraction/vector-content.d.ts +5 -0
- package/dist/engine/extraction/vector-content.js +83 -0
- package/dist/engine/extraction/vector-content.js.map +1 -0
- package/dist/engine/file-size-policy.d.ts +6 -0
- package/dist/engine/file-size-policy.js +20 -0
- package/dist/engine/file-size-policy.js.map +1 -0
- package/dist/engine/file-type.d.ts +15 -0
- package/dist/engine/file-type.js +152 -0
- package/dist/engine/file-type.js.map +1 -0
- package/dist/engine/index-status.d.ts +9 -0
- package/dist/engine/index-status.js +38 -0
- package/dist/engine/index-status.js.map +1 -0
- package/dist/engine/manifest.d.ts +13 -0
- package/dist/engine/manifest.js +124 -0
- package/dist/engine/manifest.js.map +1 -0
- package/dist/engine/models/artifact-cache-lock.d.ts +16 -0
- package/dist/engine/models/artifact-cache-lock.js +228 -0
- package/dist/engine/models/artifact-cache-lock.js.map +1 -0
- package/dist/engine/models/artifact-downloader.d.ts +77 -0
- package/dist/engine/models/artifact-downloader.js +766 -0
- package/dist/engine/models/artifact-downloader.js.map +1 -0
- package/dist/engine/models/backends/llama-cpp.d.ts +100 -0
- package/dist/engine/models/backends/llama-cpp.js +567 -0
- package/dist/engine/models/backends/llama-cpp.js.map +1 -0
- package/dist/engine/models/backends/model2vec-runtime.d.ts +63 -0
- package/dist/engine/models/backends/model2vec-runtime.js +112 -0
- package/dist/engine/models/backends/model2vec-runtime.js.map +1 -0
- package/dist/engine/models/backends/model2vec-tokenizer.d.ts +2 -0
- package/dist/engine/models/backends/model2vec-tokenizer.js +42 -0
- package/dist/engine/models/backends/model2vec-tokenizer.js.map +1 -0
- package/dist/engine/models/backends/model2vec-worker-pool.d.ts +25 -0
- package/dist/engine/models/backends/model2vec-worker-pool.js +264 -0
- package/dist/engine/models/backends/model2vec-worker-pool.js.map +1 -0
- package/dist/engine/models/backends/model2vec-worker.d.ts +1 -0
- package/dist/engine/models/backends/model2vec-worker.js +41 -0
- package/dist/engine/models/backends/model2vec-worker.js.map +1 -0
- package/dist/engine/models/backends/model2vec.d.ts +38 -0
- package/dist/engine/models/backends/model2vec.js +344 -0
- package/dist/engine/models/backends/model2vec.js.map +1 -0
- package/dist/engine/models/backends/qwen.d.ts +44 -0
- package/dist/engine/models/backends/qwen.js +411 -0
- package/dist/engine/models/backends/qwen.js.map +1 -0
- package/dist/engine/models/backends/transformers-js.d.ts +90 -0
- package/dist/engine/models/backends/transformers-js.js +411 -0
- package/dist/engine/models/backends/transformers-js.js.map +1 -0
- package/dist/engine/models/catalog.d.ts +490 -0
- package/dist/engine/models/catalog.js +522 -0
- package/dist/engine/models/catalog.js.map +1 -0
- package/dist/engine/models/download-progress.d.ts +16 -0
- package/dist/engine/models/download-progress.js +47 -0
- package/dist/engine/models/download-progress.js.map +1 -0
- package/dist/engine/models/embeddings.d.ts +73 -0
- package/dist/engine/models/embeddings.js +125 -0
- package/dist/engine/models/embeddings.js.map +1 -0
- package/dist/engine/models/factory.d.ts +2 -0
- package/dist/engine/models/factory.js +51 -0
- package/dist/engine/models/factory.js.map +1 -0
- package/dist/engine/models/index.d.ts +5 -0
- package/dist/engine/models/index.js +6 -0
- package/dist/engine/models/index.js.map +1 -0
- package/dist/engine/models/local-embedding-parallelism.d.ts +15 -0
- package/dist/engine/models/local-embedding-parallelism.js +63 -0
- package/dist/engine/models/local-embedding-parallelism.js.map +1 -0
- package/dist/engine/models/local-embedding-queue.d.ts +12 -0
- package/dist/engine/models/local-embedding-queue.js +65 -0
- package/dist/engine/models/local-embedding-queue.js.map +1 -0
- package/dist/engine/models/ranking.d.ts +19 -0
- package/dist/engine/models/ranking.js +2 -0
- package/dist/engine/models/ranking.js.map +1 -0
- package/dist/engine/models/resolution.d.ts +8 -0
- package/dist/engine/models/resolution.js +22 -0
- package/dist/engine/models/resolution.js.map +1 -0
- package/dist/engine/pipeline/indexing/index.d.ts +14 -0
- package/dist/engine/pipeline/indexing/index.js +1219 -0
- package/dist/engine/pipeline/indexing/index.js.map +1 -0
- package/dist/engine/pipeline/indexing/input-budget.d.ts +2 -0
- package/dist/engine/pipeline/indexing/input-budget.js +51 -0
- package/dist/engine/pipeline/indexing/input-budget.js.map +1 -0
- package/dist/engine/pipeline/indexing/root-paths.d.ts +7 -0
- package/dist/engine/pipeline/indexing/root-paths.js +148 -0
- package/dist/engine/pipeline/indexing/root-paths.js.map +1 -0
- package/dist/engine/pipeline/indexing/scanner/index.d.ts +14 -0
- package/dist/engine/pipeline/indexing/scanner/index.js +776 -0
- package/dist/engine/pipeline/indexing/scanner/index.js.map +1 -0
- package/dist/engine/pipeline/search/index.d.ts +12 -0
- package/dist/engine/pipeline/search/index.js +811 -0
- package/dist/engine/pipeline/search/index.js.map +1 -0
- package/dist/engine/service/index.d.ts +3 -0
- package/dist/engine/service/index.js +2 -0
- package/dist/engine/service/index.js.map +1 -0
- package/dist/engine/service/lexical.d.ts +28 -0
- package/dist/engine/service/lexical.js +446 -0
- package/dist/engine/service/lexical.js.map +1 -0
- package/dist/engine/service/root.d.ts +15 -0
- package/dist/engine/service/root.js +57 -0
- package/dist/engine/service/root.js.map +1 -0
- package/dist/engine/service/structure-enrichment.d.ts +8 -0
- package/dist/engine/service/structure-enrichment.js +178 -0
- package/dist/engine/service/structure-enrichment.js.map +1 -0
- package/dist/engine/service/types.d.ts +212 -0
- package/dist/engine/service/types.js +2 -0
- package/dist/engine/service/types.js.map +1 -0
- package/dist/engine/service/workspace-index.d.ts +26 -0
- package/dist/engine/service/workspace-index.js +157 -0
- package/dist/engine/service/workspace-index.js.map +1 -0
- package/dist/engine/service/zvec-grep.d.ts +15 -0
- package/dist/engine/service/zvec-grep.js +1520 -0
- package/dist/engine/service/zvec-grep.js.map +1 -0
- package/dist/engine/storage/index.d.ts +53 -0
- package/dist/engine/storage/index.js +3 -0
- package/dist/engine/storage/index.js.map +1 -0
- package/dist/engine/storage/layout.d.ts +10 -0
- package/dist/engine/storage/layout.js +29 -0
- package/dist/engine/storage/layout.js.map +1 -0
- package/dist/engine/storage/zvec.d.ts +4 -0
- package/dist/engine/storage/zvec.js +976 -0
- package/dist/engine/storage/zvec.js.map +1 -0
- package/dist/engine/types.d.ts +303 -0
- package/dist/engine/types.js +14 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/engine/utils/atomic-file.d.ts +3 -0
- package/dist/engine/utils/atomic-file.js +39 -0
- package/dist/engine/utils/atomic-file.js.map +1 -0
- package/dist/engine/utils/daemon-lease.d.ts +17 -0
- package/dist/engine/utils/daemon-lease.js +175 -0
- package/dist/engine/utils/daemon-lease.js.map +1 -0
- package/dist/engine/utils/file-selection.d.ts +10 -0
- package/dist/engine/utils/file-selection.js +157 -0
- package/dist/engine/utils/file-selection.js.map +1 -0
- package/dist/engine/utils/glob.d.ts +9 -0
- package/dist/engine/utils/glob.js +208 -0
- package/dist/engine/utils/glob.js.map +1 -0
- package/dist/engine/utils/hash.d.ts +2 -0
- package/dist/engine/utils/hash.js +8 -0
- package/dist/engine/utils/hash.js.map +1 -0
- package/dist/engine/utils/json.d.ts +8 -0
- package/dist/engine/utils/json.js +83 -0
- package/dist/engine/utils/json.js.map +1 -0
- package/dist/engine/utils/lock.d.ts +19 -0
- package/dist/engine/utils/lock.js +254 -0
- package/dist/engine/utils/lock.js.map +1 -0
- package/dist/engine/utils/path.d.ts +4 -0
- package/dist/engine/utils/path.js +18 -0
- package/dist/engine/utils/path.js.map +1 -0
- package/dist/engine/utils/timing.d.ts +19 -0
- package/dist/engine/utils/timing.js +87 -0
- package/dist/engine/utils/timing.js.map +1 -0
- package/dist/index-progress.d.ts +10 -0
- package/dist/index-progress.js +159 -0
- package/dist/index-progress.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/http-transport.d.ts +27 -0
- package/dist/mcp/http-transport.js +182 -0
- package/dist/mcp/http-transport.js.map +1 -0
- package/dist/mcp/input-normalization.d.ts +38 -0
- package/dist/mcp/input-normalization.js +104 -0
- package/dist/mcp/input-normalization.js.map +1 -0
- package/dist/mcp/progress-heartbeat.d.ts +17 -0
- package/dist/mcp/progress-heartbeat.js +46 -0
- package/dist/mcp/progress-heartbeat.js.map +1 -0
- package/dist/mcp/request-metadata.d.ts +2 -0
- package/dist/mcp/request-metadata.js +11 -0
- package/dist/mcp/request-metadata.js.map +1 -0
- package/dist/mcp/request-state.d.ts +40 -0
- package/dist/mcp/request-state.js +210 -0
- package/dist/mcp/request-state.js.map +1 -0
- package/dist/mcp/result-format.d.ts +13 -0
- package/dist/mcp/result-format.js +75 -0
- package/dist/mcp/result-format.js.map +1 -0
- package/dist/mcp/schemas.d.ts +668 -0
- package/dist/mcp/schemas.js +512 -0
- package/dist/mcp/schemas.js.map +1 -0
- package/dist/mcp/stdio-bridge.d.ts +15 -0
- package/dist/mcp/stdio-bridge.js +190 -0
- package/dist/mcp/stdio-bridge.js.map +1 -0
- package/dist/mcp/tools.d.ts +153 -0
- package/dist/mcp/tools.js +488 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/toolset.d.ts +5 -0
- package/dist/mcp/toolset.js +12 -0
- package/dist/mcp/toolset.js.map +1 -0
- package/dist/observability/trace-context.d.ts +11 -0
- package/dist/observability/trace-context.js +138 -0
- package/dist/observability/trace-context.js.map +1 -0
- package/dist/prompts/zvec-grep-guidance.d.ts +2 -0
- package/dist/prompts/zvec-grep-guidance.js +9 -0
- package/dist/prompts/zvec-grep-guidance.js.map +1 -0
- package/docs/01-agents.md +217 -0
- package/docs/02-cli.md +259 -0
- package/docs/03-mcp.md +185 -0
- package/docs/04-pipeline.md +234 -0
- package/docs/05-architecture.md +86 -0
- package/docs/06-server.md +279 -0
- package/docs/07-embedding.md +227 -0
- package/docs/08-roadmap.md +85 -0
- package/docs/README.md +53 -0
- package/package.json +87 -0
|
@@ -0,0 +1,1118 @@
|
|
|
1
|
+
import { createZvecGrep, resolveIndexEmbeddingConcurrency, } from "../engine/service/index.js";
|
|
2
|
+
import { isEngineError } from "../engine/errors.js";
|
|
3
|
+
import { readGlobalConfig, resolveEmbeddingRuntimeOptions, } from "../engine/config.js";
|
|
4
|
+
import { readWorkspaceManifest } from "../engine/manifest.js";
|
|
5
|
+
import { workspaceIndexLocation } from "../engine/service/root.js";
|
|
6
|
+
import { resolveEmbeddingReference } from "../engine/models/index.js";
|
|
7
|
+
import { indexCompletionForJob, indexCompletionFromStatus, } from "../engine/index-status.js";
|
|
8
|
+
import { contextOptionsFromRgInput, normalizePlainStringList, } from "../mcp/input-normalization.js";
|
|
9
|
+
import { DaemonError } from "./errors.js";
|
|
10
|
+
import { JobScheduler, } from "./job-scheduler.js";
|
|
11
|
+
import { EmbeddingModelPool, } from "./model-pool.js";
|
|
12
|
+
import { IndexCoordinator, } from "./index-coordinator.js";
|
|
13
|
+
import { inspectRoot, resolveRequestedRoot, RuntimeManager, } from "./runtime-manager.js";
|
|
14
|
+
import { WatchManager } from "./watch-manager.js";
|
|
15
|
+
import { rootIdentity } from "./logger.js";
|
|
16
|
+
import { RemoteEmbeddingAuthorizationManager, RemoteEmbeddingAuthorizationStore, planRemoteIndexAuthorization, planRemoteSearchAuthorization, withRemoteEmbeddingOperationPermit, } from "../authorization/index.js";
|
|
17
|
+
const DEFAULT_LOCAL_EMBEDDING = "local/potion-code-16m-v2";
|
|
18
|
+
export class DaemonBackend {
|
|
19
|
+
options;
|
|
20
|
+
modelPool;
|
|
21
|
+
runtimeManager;
|
|
22
|
+
scheduler;
|
|
23
|
+
startedAt = Date.now();
|
|
24
|
+
statusCache = new Map();
|
|
25
|
+
lastScanDiagnostics = new Map();
|
|
26
|
+
workspaceRuntimeCache = new Map();
|
|
27
|
+
watchers = new Map();
|
|
28
|
+
indexCoordinators = new Map();
|
|
29
|
+
droppingRoots = new Set();
|
|
30
|
+
authorizationManager;
|
|
31
|
+
shuttingDown = false;
|
|
32
|
+
closePromise;
|
|
33
|
+
constructor(options) {
|
|
34
|
+
this.options = options;
|
|
35
|
+
this.authorizationManager = new RemoteEmbeddingAuthorizationManager(options.authorizationStore ??
|
|
36
|
+
new RemoteEmbeddingAuthorizationStore({
|
|
37
|
+
signingKeyPath: options.serviceOptions?.authorizationSigningKeyPath,
|
|
38
|
+
}));
|
|
39
|
+
this.modelPool = new EmbeddingModelPool({
|
|
40
|
+
...options.modelPoolOptions,
|
|
41
|
+
serviceOptions: options.serviceOptions,
|
|
42
|
+
logger: options.logger,
|
|
43
|
+
});
|
|
44
|
+
this.runtimeManager = new RuntimeManager({
|
|
45
|
+
modelPool: this.modelPool,
|
|
46
|
+
serviceOptions: options.serviceOptions,
|
|
47
|
+
readSessionIdleTtlMs: options.readSessionIdleTtlMs,
|
|
48
|
+
runtimeIdleTtlMs: options.runtimeIdleTtlMs,
|
|
49
|
+
onRuntimeEvicted: async (root) => {
|
|
50
|
+
this.statusCache.delete(root);
|
|
51
|
+
this.lastScanDiagnostics.delete(root);
|
|
52
|
+
this.workspaceRuntimeCache.delete(root);
|
|
53
|
+
this.scheduler.forgetRoot(root);
|
|
54
|
+
await this.closeWatcher(root);
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
this.scheduler = new JobScheduler({
|
|
58
|
+
...options.schedulerOptions,
|
|
59
|
+
logger: options.logger,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async planIndexAuthorization(input) {
|
|
63
|
+
if (input.drop === true) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const requestedRoot = await resolveRequestedRoot(input.root, false);
|
|
67
|
+
if (input.rebuild !== true && this.scheduler.hasActiveRoot(requestedRoot)) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
const info = await inspectRoot(input.root, this.options.serviceOptions, input.rebuild !== true);
|
|
71
|
+
let modelLoadRequest;
|
|
72
|
+
try {
|
|
73
|
+
modelLoadRequest = this.indexModelLoadRequest(info, input);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error instanceof DaemonError && error.code === "MODEL_LOAD_FAILED") {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
let lease;
|
|
82
|
+
try {
|
|
83
|
+
lease = await this.modelPool.acquire(modelLoadRequest);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (isEngineError(error)) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
let schema;
|
|
92
|
+
let modelInfo;
|
|
93
|
+
try {
|
|
94
|
+
schema = embeddingSchema(lease.model);
|
|
95
|
+
modelInfo = lease.model.info;
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
lease.release();
|
|
99
|
+
}
|
|
100
|
+
const existing = info.workspaceIndex?.embedding;
|
|
101
|
+
if (existing &&
|
|
102
|
+
input.embedding &&
|
|
103
|
+
input.rebuild !== true &&
|
|
104
|
+
(existing.provider !== schema.provider || existing.model !== schema.model)) {
|
|
105
|
+
throw new DaemonError("EMBEDDING_MODEL_MISMATCH", `Existing model ${existing.provider}/${existing.model} does not match requested model ${schema.provider}/${schema.model}; use rebuild to change models.`);
|
|
106
|
+
}
|
|
107
|
+
return await planRemoteIndexAuthorization({
|
|
108
|
+
info,
|
|
109
|
+
model: modelInfo,
|
|
110
|
+
rebuild: input.rebuild,
|
|
111
|
+
store: this.authorizationManager.store,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
async planSearchAuthorization(input) {
|
|
115
|
+
const requestedRoot = await resolveRequestedRoot(input.root, false);
|
|
116
|
+
let activeRuntime = this.runtimeManager.getByRequestedRoot(requestedRoot);
|
|
117
|
+
if (activeRuntime?.embeddingProvider() &&
|
|
118
|
+
activeRuntime.embeddingProvider() !== "qwen") {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
let canonicalRoot = activeRuntime?.canonicalRoot;
|
|
122
|
+
let discoveredInfo;
|
|
123
|
+
if (!canonicalRoot) {
|
|
124
|
+
discoveredInfo = await this.inspectRoot(input.root, false);
|
|
125
|
+
canonicalRoot = await resolveRequestedRoot(discoveredInfo.root, false);
|
|
126
|
+
activeRuntime = this.runtimeManager.getByCanonicalRoot(canonicalRoot);
|
|
127
|
+
const provider = activeRuntime?.embeddingProvider() ??
|
|
128
|
+
discoveredInfo.workspaceIndex?.embedding?.provider;
|
|
129
|
+
if (provider && provider !== "qwen") {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const cachedInfo = activeRuntime
|
|
134
|
+
? this.statusCache.get(canonicalRoot)
|
|
135
|
+
: undefined;
|
|
136
|
+
let info;
|
|
137
|
+
if (cachedInfo) {
|
|
138
|
+
info = cachedInfo;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
try {
|
|
142
|
+
info = await this.inspectRoot(canonicalRoot, true);
|
|
143
|
+
this.statusCache.set(canonicalRoot, info);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
const cached = this.statusCache.get(canonicalRoot);
|
|
147
|
+
if (!cached ||
|
|
148
|
+
!isEngineError(error) ||
|
|
149
|
+
error.code !== "ZVEC_GREP.ENGINE.LOCK.BUSY") {
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
info = cached;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const schema = info.workspaceIndex?.embedding;
|
|
156
|
+
if (!info.indexed || !schema || schema.provider !== "qwen") {
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
const modelLoadRequest = this.searchModelLoadRequest(info, input);
|
|
160
|
+
const modelInfo = await this.loadEmbeddingModelInfo(modelLoadRequest);
|
|
161
|
+
return await planRemoteSearchAuthorization({
|
|
162
|
+
info,
|
|
163
|
+
model: modelInfo,
|
|
164
|
+
search: input,
|
|
165
|
+
runtimeNeedsReconciliation: this.runtimeManager
|
|
166
|
+
.getByCanonicalRoot(canonicalRoot)
|
|
167
|
+
?.needsReconciliation() ?? false,
|
|
168
|
+
store: this.authorizationManager.store,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
async existingRemoteEmbeddingPermit(plan) {
|
|
172
|
+
return await this.authorizationManager.existingWorkspacePermit(plan);
|
|
173
|
+
}
|
|
174
|
+
async grantRemoteEmbedding(plan, scope) {
|
|
175
|
+
return await this.authorizationManager.grant(plan, scope);
|
|
176
|
+
}
|
|
177
|
+
async index(input, options = {}) {
|
|
178
|
+
if (input.drop === true) {
|
|
179
|
+
assertDropOnlyInput(input);
|
|
180
|
+
const result = await this.dropIndex(input);
|
|
181
|
+
return {
|
|
182
|
+
root: result.root,
|
|
183
|
+
jobId: "drop",
|
|
184
|
+
state: "succeeded",
|
|
185
|
+
reused: false,
|
|
186
|
+
action: "drop",
|
|
187
|
+
dropped: result.removed,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const requestedRoot = await resolveRequestedRoot(input.root, true);
|
|
191
|
+
this.assertRootNotDropping(requestedRoot);
|
|
192
|
+
const runtime = await this.runtimeManager.activateForIndex(requestedRoot);
|
|
193
|
+
this.ensureWatcher(runtime);
|
|
194
|
+
const activeJob = this.scheduler.getByRoot(runtime.canonicalRoot);
|
|
195
|
+
const followsNarrowJob = activeJob?.state === "queued" || activeJob?.state === "running"
|
|
196
|
+
? activeJob.reason === "watch"
|
|
197
|
+
: false;
|
|
198
|
+
const createsWork = !this.scheduler.hasActiveRoot(runtime.canonicalRoot) ||
|
|
199
|
+
input.rebuild === true ||
|
|
200
|
+
followsNarrowJob;
|
|
201
|
+
if (createsWork) {
|
|
202
|
+
this.lastScanDiagnostics.delete(runtime.canonicalRoot);
|
|
203
|
+
}
|
|
204
|
+
const targetRevision = createsWork
|
|
205
|
+
? runtime.markDirty()
|
|
206
|
+
: runtime.snapshot().dirtyRevision;
|
|
207
|
+
const submitted = this.scheduler.submit({
|
|
208
|
+
canonicalRoot: runtime.canonicalRoot,
|
|
209
|
+
reason: "manual",
|
|
210
|
+
followupIfRunning: input.rebuild === true || followsNarrowJob,
|
|
211
|
+
run: async (report, signal) => {
|
|
212
|
+
const proof = await this.runIndex(runtime, input, report, options.authorization, signal);
|
|
213
|
+
this.lastScanDiagnostics.set(runtime.canonicalRoot, proof.scanDiagnostics);
|
|
214
|
+
if (proof.reconciled) {
|
|
215
|
+
runtime.markReconciled(targetRevision, proof.reconciliationEpoch);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
runtime.markIndexed(targetRevision);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
const job = input.wait
|
|
223
|
+
? await this.scheduler.wait(submitted.job.id, options.onProgress)
|
|
224
|
+
: submitted.job;
|
|
225
|
+
if (input.wait) {
|
|
226
|
+
await this.settleKnownChanges(runtime);
|
|
227
|
+
}
|
|
228
|
+
this.options.logger?.event("job.submitted", {
|
|
229
|
+
root_id: rootIdentity(runtime.canonicalRoot),
|
|
230
|
+
job_id: job.id,
|
|
231
|
+
reason: "manual",
|
|
232
|
+
state: job.state,
|
|
233
|
+
reused: submitted.reused,
|
|
234
|
+
});
|
|
235
|
+
return {
|
|
236
|
+
root: runtime.canonicalRoot,
|
|
237
|
+
jobId: job.id,
|
|
238
|
+
state: job.state,
|
|
239
|
+
reused: submitted.reused,
|
|
240
|
+
action: "index",
|
|
241
|
+
error: job.error,
|
|
242
|
+
...(input.debug === true && input.wait === true
|
|
243
|
+
? {
|
|
244
|
+
scanDiagnostics: this.lastScanDiagnostics.get(runtime.canonicalRoot),
|
|
245
|
+
}
|
|
246
|
+
: {}),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
async dropIndex(input) {
|
|
250
|
+
const canonicalRoot = await resolveRequestedRoot(input.root, true);
|
|
251
|
+
if (this.droppingRoots.has(canonicalRoot)) {
|
|
252
|
+
throw new DaemonError("INDEX_DROP_IN_PROGRESS", "The Workspace index is already being dropped.");
|
|
253
|
+
}
|
|
254
|
+
this.droppingRoots.add(canonicalRoot);
|
|
255
|
+
try {
|
|
256
|
+
await this.closeWatcher(canonicalRoot);
|
|
257
|
+
this.scheduler.cancelRoot(canonicalRoot);
|
|
258
|
+
await this.scheduler.waitForRootIdle(canonicalRoot);
|
|
259
|
+
const runtime = this.runtimeManager.getByCanonicalRoot(canonicalRoot);
|
|
260
|
+
const drop = async () => {
|
|
261
|
+
const service = await (this.options.createService ?? createZvecGrep)({
|
|
262
|
+
...this.options.serviceOptions,
|
|
263
|
+
root: canonicalRoot,
|
|
264
|
+
daemonInstanceToken: this.runtimeManager.instanceToken,
|
|
265
|
+
});
|
|
266
|
+
try {
|
|
267
|
+
return await service.dropIndex({ root: canonicalRoot });
|
|
268
|
+
}
|
|
269
|
+
finally {
|
|
270
|
+
await service.close();
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
const removed = runtime ? await runtime.withWrite(drop) : await drop();
|
|
274
|
+
this.options.logger?.event("index.dropped", {
|
|
275
|
+
root_id: rootIdentity(canonicalRoot),
|
|
276
|
+
dropped: removed,
|
|
277
|
+
});
|
|
278
|
+
return { root: canonicalRoot, removed };
|
|
279
|
+
}
|
|
280
|
+
finally {
|
|
281
|
+
this.statusCache.delete(canonicalRoot);
|
|
282
|
+
this.lastScanDiagnostics.delete(canonicalRoot);
|
|
283
|
+
this.workspaceRuntimeCache.delete(canonicalRoot);
|
|
284
|
+
try {
|
|
285
|
+
await this.runtimeManager.evict(canonicalRoot);
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
this.droppingRoots.delete(canonicalRoot);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
async search(input, options = {}) {
|
|
293
|
+
const startedAt = Date.now();
|
|
294
|
+
const requestedRoot = await resolveRequestedRoot(input.root, false);
|
|
295
|
+
this.assertRootNotDropping(requestedRoot);
|
|
296
|
+
const runtime = await this.runtimeManager.activate(requestedRoot);
|
|
297
|
+
const releaseRuntimeActivity = runtime.beginActivity();
|
|
298
|
+
try {
|
|
299
|
+
const searchInfo = await this.inspectRootWithCache(runtime.canonicalRoot);
|
|
300
|
+
const currentModelLoadRequest = runtime.currentModelLoadRequest();
|
|
301
|
+
const defaultModelLoadRequest = searchInfo.indexed
|
|
302
|
+
? this.searchModelLoadRequest(searchInfo, {})
|
|
303
|
+
: currentModelLoadRequest
|
|
304
|
+
? this.overrideActiveModelLoadRequest(currentModelLoadRequest, {})
|
|
305
|
+
: undefined;
|
|
306
|
+
if (!defaultModelLoadRequest) {
|
|
307
|
+
throw new DaemonError("INDEX_MISSING", "Search requires an existing workspace index.");
|
|
308
|
+
}
|
|
309
|
+
const searchModelLoadRequest = searchInfo.indexed
|
|
310
|
+
? this.searchModelLoadRequest(searchInfo, input)
|
|
311
|
+
: this.overrideActiveModelLoadRequest(defaultModelLoadRequest, input);
|
|
312
|
+
runtime.updateModelLoadRequest(defaultModelLoadRequest);
|
|
313
|
+
this.ensureWatcher(runtime);
|
|
314
|
+
await runtime.probeInitialFreshness(async () => {
|
|
315
|
+
const info = await this.inspectRoot(runtime.canonicalRoot, true);
|
|
316
|
+
this.statusCache.set(runtime.canonicalRoot, info);
|
|
317
|
+
return indexStatusIsFresh(info);
|
|
318
|
+
}, (initialFreshness) => {
|
|
319
|
+
this.options.logger?.event(`runtime.initial_probe_${initialFreshness}`, {
|
|
320
|
+
root_id: rootIdentity(runtime.canonicalRoot),
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
let updateJob;
|
|
324
|
+
const executeSearch = () => withRemoteEmbeddingOperationPermit(options.authorization, () => runtime.search({
|
|
325
|
+
queries: input.queries,
|
|
326
|
+
routes: input.routes,
|
|
327
|
+
fuse: input.fuse,
|
|
328
|
+
limit: input.limit,
|
|
329
|
+
trace: input.trace,
|
|
330
|
+
preferSymbol: input.preferSymbol,
|
|
331
|
+
symbolTypes: input.symbolTypes,
|
|
332
|
+
globs: normalizePlainStringList(input.globs),
|
|
333
|
+
insensitiveGlobs: normalizePlainStringList(input.insensitiveGlobs),
|
|
334
|
+
fileTypes: normalizePlainStringList(input.fileTypes),
|
|
335
|
+
excludedFileTypes: normalizePlainStringList(input.excludedFileTypes),
|
|
336
|
+
hidden: input.hidden,
|
|
337
|
+
noIgnore: input.noIgnore,
|
|
338
|
+
ignoreFiles: input.ignoreFiles,
|
|
339
|
+
maxDepth: input.maxDepth,
|
|
340
|
+
maxFileSizeBytes: input.maxFileSizeBytes,
|
|
341
|
+
follow: input.follow,
|
|
342
|
+
modifiedAfter: input.modifiedAfter,
|
|
343
|
+
modifiedBefore: input.modifiedBefore,
|
|
344
|
+
autoUpdate: false,
|
|
345
|
+
}, searchModelLoadRequest));
|
|
346
|
+
let result;
|
|
347
|
+
if (input.freshness === "wait_for_fresh") {
|
|
348
|
+
while (true) {
|
|
349
|
+
updateJob =
|
|
350
|
+
(await this.waitForFresh(runtime, options.authorization, input)) ??
|
|
351
|
+
updateJob;
|
|
352
|
+
const beforeSearch = runtime.snapshot();
|
|
353
|
+
result = await executeSearch();
|
|
354
|
+
const afterSearch = runtime.snapshot();
|
|
355
|
+
if (!afterSearch.watcherPending &&
|
|
356
|
+
afterSearch.watcherEpoch === beforeSearch.watcherEpoch &&
|
|
357
|
+
!runtime.needsReconciliation()) {
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
result = await executeSearch();
|
|
364
|
+
}
|
|
365
|
+
if (runtime.needsReconciliation() &&
|
|
366
|
+
input.autoUpdate &&
|
|
367
|
+
(runtime.requiresFullReconciliation() ||
|
|
368
|
+
!this.scheduler.hasActiveRoot(runtime.canonicalRoot))) {
|
|
369
|
+
const currentJob = this.scheduler.getByRoot(runtime.canonicalRoot);
|
|
370
|
+
const terminalKnownPathJob = !runtime.requiresFullReconciliation() &&
|
|
371
|
+
(currentJob?.state === "failed" || currentJob?.state === "cancelled");
|
|
372
|
+
if (runtime.needsReconciliation() && !terminalKnownPathJob) {
|
|
373
|
+
updateJob = await this.submitIndex(runtime, {
|
|
374
|
+
root: runtime.canonicalRoot,
|
|
375
|
+
apiKey: input.apiKey,
|
|
376
|
+
device: input.device,
|
|
377
|
+
embeddingConcurrency: input.embeddingConcurrency,
|
|
378
|
+
runtimeOverridesAreEphemeral: true,
|
|
379
|
+
}, "background_reconcile", false, options.authorization);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
const job = updateJob ?? this.scheduler.getByRoot(runtime.canonicalRoot);
|
|
383
|
+
const runtimeSnapshot = runtime.snapshot();
|
|
384
|
+
const activeKnownChangeJob = job?.reason !== "background_reconcile" &&
|
|
385
|
+
(job?.state === "queued" || job?.state === "running");
|
|
386
|
+
const freshness = runtime.hasKnownChanges() ||
|
|
387
|
+
runtimeSnapshot.watcherPending ||
|
|
388
|
+
activeKnownChangeJob
|
|
389
|
+
? "possibly_stale"
|
|
390
|
+
: "fresh";
|
|
391
|
+
const response = {
|
|
392
|
+
root: runtime.canonicalRoot,
|
|
393
|
+
freshness,
|
|
394
|
+
indexing: freshness === "possibly_stale"
|
|
395
|
+
? searchIndexingSnapshot(job, this.currentIndexCompletion(runtime.canonicalRoot, job, runtime))
|
|
396
|
+
: undefined,
|
|
397
|
+
result,
|
|
398
|
+
};
|
|
399
|
+
this.options.logger?.event("search.completed", {
|
|
400
|
+
root_id: rootIdentity(runtime.canonicalRoot),
|
|
401
|
+
duration_ms: Date.now() - startedAt,
|
|
402
|
+
freshness: response.freshness,
|
|
403
|
+
result_count: result.items.length,
|
|
404
|
+
});
|
|
405
|
+
return response;
|
|
406
|
+
}
|
|
407
|
+
finally {
|
|
408
|
+
releaseRuntimeActivity();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
currentIndexCompletion(canonicalRoot, job, runtime) {
|
|
412
|
+
// Narrow watcher updates skip the status scan, so the cached completion
|
|
413
|
+
// still describes the previous fresh snapshot rather than the active job.
|
|
414
|
+
if (job?.reason === "watch" &&
|
|
415
|
+
runtime.needsReconciliation() &&
|
|
416
|
+
!runtime.requiresFullReconciliation()) {
|
|
417
|
+
return undefined;
|
|
418
|
+
}
|
|
419
|
+
return indexCompletionFromStatus(this.statusCache.get(canonicalRoot)?.status);
|
|
420
|
+
}
|
|
421
|
+
async indexStatus(input) {
|
|
422
|
+
const requestedCanonicalRoot = await resolveRequestedRoot(input.root, false);
|
|
423
|
+
let info;
|
|
424
|
+
try {
|
|
425
|
+
info = await inspectRoot(input.root, this.options.serviceOptions);
|
|
426
|
+
this.statusCache.set(requestedCanonicalRoot, info);
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
const cached = this.statusCache.get(requestedCanonicalRoot);
|
|
430
|
+
if (!cached ||
|
|
431
|
+
!isEngineError(error) ||
|
|
432
|
+
error.code !== "ZVEC_GREP.ENGINE.LOCK.BUSY") {
|
|
433
|
+
throw error;
|
|
434
|
+
}
|
|
435
|
+
info = cached;
|
|
436
|
+
}
|
|
437
|
+
const canonicalRoot = await resolveRequestedRoot(info.root, false);
|
|
438
|
+
const runtime = this.runtimeManager.getByCanonicalRoot(canonicalRoot);
|
|
439
|
+
const runtimeSnapshot = runtime?.snapshot();
|
|
440
|
+
const job = this.scheduler.getByRoot(canonicalRoot);
|
|
441
|
+
return {
|
|
442
|
+
root: canonicalRoot,
|
|
443
|
+
indexed: info.indexed,
|
|
444
|
+
indexPolicy: info.indexPolicy,
|
|
445
|
+
source: info.source,
|
|
446
|
+
persistent: persistentStatus(info),
|
|
447
|
+
runtime: runtimeSnapshot
|
|
448
|
+
? {
|
|
449
|
+
watcherActive: runtimeSnapshot.watcherActive,
|
|
450
|
+
dirtyRevision: runtimeSnapshot.dirtyRevision,
|
|
451
|
+
indexedRevision: runtimeSnapshot.indexedRevision,
|
|
452
|
+
activeJobId: job?.id,
|
|
453
|
+
jobState: job?.state,
|
|
454
|
+
progress: job?.progress ? formatProgress(job) : undefined,
|
|
455
|
+
completion: indexCompletionForJob(indexCompletionFromStatus(info.status), job?.state, job?.progress),
|
|
456
|
+
error: job?.error,
|
|
457
|
+
}
|
|
458
|
+
: undefined,
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
async serverStatus() {
|
|
462
|
+
const runtime = this.runtimeManager.snapshot();
|
|
463
|
+
const models = this.modelPool.snapshot();
|
|
464
|
+
const jobs = this.scheduler.snapshot();
|
|
465
|
+
return {
|
|
466
|
+
version: this.options.version,
|
|
467
|
+
uptimeMs: Date.now() - this.startedAt,
|
|
468
|
+
shuttingDown: this.shuttingDown,
|
|
469
|
+
activeRuntimes: runtime.activeRuntimes,
|
|
470
|
+
queuedJobs: jobs.queued,
|
|
471
|
+
runningJobs: jobs.running,
|
|
472
|
+
models,
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
async rg(input) {
|
|
476
|
+
const startedAt = Date.now();
|
|
477
|
+
const canonicalRoot = await resolveRequestedRoot(input.root, false);
|
|
478
|
+
const service = await (this.options.createService ?? createZvecGrep)({
|
|
479
|
+
...this.options.serviceOptions,
|
|
480
|
+
root: canonicalRoot,
|
|
481
|
+
daemonInstanceToken: this.runtimeManager.instanceToken,
|
|
482
|
+
});
|
|
483
|
+
try {
|
|
484
|
+
const result = await service.context({
|
|
485
|
+
...contextOptionsFromRgInput({ ...input, root: canonicalRoot }),
|
|
486
|
+
root: canonicalRoot,
|
|
487
|
+
autoUpdate: false,
|
|
488
|
+
});
|
|
489
|
+
this.options.logger?.event("rg.completed", {
|
|
490
|
+
root_id: rootIdentity(canonicalRoot),
|
|
491
|
+
duration_ms: Date.now() - startedAt,
|
|
492
|
+
result_count: result.items.length,
|
|
493
|
+
});
|
|
494
|
+
return {
|
|
495
|
+
root: canonicalRoot,
|
|
496
|
+
result,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
finally {
|
|
500
|
+
await service.close();
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
async close() {
|
|
504
|
+
if (this.closePromise) {
|
|
505
|
+
return this.closePromise;
|
|
506
|
+
}
|
|
507
|
+
this.shuttingDown = true;
|
|
508
|
+
this.closePromise = (async () => {
|
|
509
|
+
await Promise.all([...this.watchers.values()].map((watcher) => watcher.close()));
|
|
510
|
+
for (const root of this.watchers.keys()) {
|
|
511
|
+
this.runtimeManager.getByCanonicalRoot(root)?.setWatcherActive(false);
|
|
512
|
+
}
|
|
513
|
+
this.watchers.clear();
|
|
514
|
+
this.indexCoordinators.clear();
|
|
515
|
+
await this.scheduler.close();
|
|
516
|
+
await this.runtimeManager.close();
|
|
517
|
+
await this.modelPool.close();
|
|
518
|
+
this.lastScanDiagnostics.clear();
|
|
519
|
+
this.workspaceRuntimeCache.clear();
|
|
520
|
+
})();
|
|
521
|
+
return this.closePromise;
|
|
522
|
+
}
|
|
523
|
+
async runIndex(runtime, input, report, authorization, signal) {
|
|
524
|
+
const releaseRuntimeActivity = runtime.beginActivity();
|
|
525
|
+
try {
|
|
526
|
+
return await this.runIndexOperation(runtime, input, report, authorization, signal);
|
|
527
|
+
}
|
|
528
|
+
finally {
|
|
529
|
+
releaseRuntimeActivity();
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
async runIndexOperation(runtime, input, report, authorization, signal) {
|
|
533
|
+
const startedAt = Date.now();
|
|
534
|
+
// Watcher path updates already identify their indexing scope. Uncertain
|
|
535
|
+
// watcher reconciliations are verified by the final status scan, so neither
|
|
536
|
+
// path needs another workspace-wide status scan before indexing starts.
|
|
537
|
+
const includeInitialStatus = input.skipInitialStatus !== true &&
|
|
538
|
+
input.rebuild !== true &&
|
|
539
|
+
input.changedPaths === undefined;
|
|
540
|
+
const includeFinalStatus = input.changedPaths === undefined;
|
|
541
|
+
const before = await this.inspectRoot(runtime.canonicalRoot, includeInitialStatus);
|
|
542
|
+
if (includeInitialStatus) {
|
|
543
|
+
this.statusCache.set(runtime.canonicalRoot, before);
|
|
544
|
+
}
|
|
545
|
+
const modelLoadRequest = this.indexModelLoadRequest(before, input);
|
|
546
|
+
const model = modelLoadRequest.model;
|
|
547
|
+
runtime.updateModelLoadRequest(modelLoadRequest);
|
|
548
|
+
let lease;
|
|
549
|
+
try {
|
|
550
|
+
lease = await this.modelPool.acquire(modelLoadRequest);
|
|
551
|
+
}
|
|
552
|
+
catch (error) {
|
|
553
|
+
if (isEngineError(error)) {
|
|
554
|
+
throw error;
|
|
555
|
+
}
|
|
556
|
+
throw new DaemonError("MODEL_LOAD_FAILED", `Embedding model ${embeddingModelReference(model)} could not be created: ${error instanceof Error ? error.message : String(error)}`);
|
|
557
|
+
}
|
|
558
|
+
let service;
|
|
559
|
+
let scanDiagnostics;
|
|
560
|
+
let cleanupPromise;
|
|
561
|
+
const cleanup = () => (cleanupPromise ??= (async () => {
|
|
562
|
+
try {
|
|
563
|
+
await service?.close();
|
|
564
|
+
}
|
|
565
|
+
finally {
|
|
566
|
+
lease.release();
|
|
567
|
+
}
|
|
568
|
+
})());
|
|
569
|
+
try {
|
|
570
|
+
service = await (this.options.createService ?? createZvecGrep)({
|
|
571
|
+
...this.options.serviceOptions,
|
|
572
|
+
root: runtime.canonicalRoot,
|
|
573
|
+
embeddingModel: lease.model,
|
|
574
|
+
embeddingModelOwnership: "borrowed",
|
|
575
|
+
embedding: input.runtimeOverridesAreEphemeral
|
|
576
|
+
? undefined
|
|
577
|
+
: input.embedding,
|
|
578
|
+
apiKey: input.runtimeOverridesAreEphemeral ? undefined : input.apiKey,
|
|
579
|
+
endpoint: input.runtimeOverridesAreEphemeral
|
|
580
|
+
? undefined
|
|
581
|
+
: input.endpoint,
|
|
582
|
+
device: input.runtimeOverridesAreEphemeral ? undefined : input.device,
|
|
583
|
+
embeddingConcurrency: modelLoadRequest.embeddingConcurrency,
|
|
584
|
+
daemonInstanceToken: this.runtimeManager.instanceToken,
|
|
585
|
+
});
|
|
586
|
+
const result = await runtime.withWrite(async () => {
|
|
587
|
+
try {
|
|
588
|
+
// The closed read generation has now released its lease. Recheck
|
|
589
|
+
// capacity before lazy inference loads a different native model.
|
|
590
|
+
await this.modelPool.trimIdleEntries(lease.key);
|
|
591
|
+
return await withRemoteEmbeddingOperationPermit(authorization, () => service.index({
|
|
592
|
+
root: runtime.canonicalRoot,
|
|
593
|
+
rebuild: input.rebuild,
|
|
594
|
+
resetPaths: input.resetPaths,
|
|
595
|
+
globs: normalizePlainStringList(input.globs),
|
|
596
|
+
insensitiveGlobs: normalizePlainStringList(input.insensitiveGlobs),
|
|
597
|
+
fileTypes: normalizePlainStringList(input.fileTypes),
|
|
598
|
+
excludedFileTypes: normalizePlainStringList(input.excludedFileTypes),
|
|
599
|
+
hidden: input.hidden,
|
|
600
|
+
noIgnore: input.noIgnore,
|
|
601
|
+
ignoreFiles: normalizePlainStringList(input.ignoreFiles),
|
|
602
|
+
maxDepth: input.maxDepth,
|
|
603
|
+
maxFileSizeBytes: input.maxFileSizeBytes,
|
|
604
|
+
follow: input.follow,
|
|
605
|
+
embeddingConcurrency: modelLoadRequest.embeddingConcurrency,
|
|
606
|
+
changedPaths: input.changedPaths,
|
|
607
|
+
signal,
|
|
608
|
+
onProgress: report,
|
|
609
|
+
onWriterContext: (context) => runtime.setWriterContext(context, lease.key),
|
|
610
|
+
}));
|
|
611
|
+
}
|
|
612
|
+
finally {
|
|
613
|
+
// Release the writer model before queued query models can acquire.
|
|
614
|
+
await cleanup();
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
scanDiagnostics = result.scanDiagnostics;
|
|
618
|
+
}
|
|
619
|
+
finally {
|
|
620
|
+
await cleanup();
|
|
621
|
+
}
|
|
622
|
+
if (includeFinalStatus) {
|
|
623
|
+
await this.watchers.get(runtime.canonicalRoot)?.flushPending();
|
|
624
|
+
}
|
|
625
|
+
const proofReconciliationEpoch = runtime.reconciliationEpoch();
|
|
626
|
+
const after = await this.inspectRoot(runtime.canonicalRoot, includeFinalStatus);
|
|
627
|
+
if (includeFinalStatus) {
|
|
628
|
+
this.statusCache.set(runtime.canonicalRoot, after);
|
|
629
|
+
await this.watchers.get(runtime.canonicalRoot)?.refreshPaths?.();
|
|
630
|
+
}
|
|
631
|
+
if (!after.workspaceIndex?.embedding) {
|
|
632
|
+
throw new DaemonError("INDEX_MISSING", "Index completed without an embedding schema.");
|
|
633
|
+
}
|
|
634
|
+
runtime.updateModelLoadRequest(this.searchModelLoadRequest(after, {}));
|
|
635
|
+
this.options.logger?.event("index.completed", {
|
|
636
|
+
root_id: rootIdentity(runtime.canonicalRoot),
|
|
637
|
+
duration_ms: Date.now() - startedAt,
|
|
638
|
+
scope: input.changedPaths ? "paths" : "reconcile",
|
|
639
|
+
changed_paths: input.changedPaths?.length,
|
|
640
|
+
});
|
|
641
|
+
const reconciled = includeFinalStatus && indexStatusIsFresh(after);
|
|
642
|
+
if (includeFinalStatus && !reconciled) {
|
|
643
|
+
runtime.requireFullReconciliation(true);
|
|
644
|
+
}
|
|
645
|
+
return {
|
|
646
|
+
reconciled,
|
|
647
|
+
reconciliationEpoch: proofReconciliationEpoch,
|
|
648
|
+
scanDiagnostics,
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
async submitIndex(runtime, input, reason, wait, authorization) {
|
|
652
|
+
const createsWork = !this.scheduler.hasActiveRoot(runtime.canonicalRoot) ||
|
|
653
|
+
input.rebuild === true;
|
|
654
|
+
const probeBeforeUpdate = reason === "background_reconcile" && runtime.canProbeFullReconciliation();
|
|
655
|
+
let targetRevision = createsWork && !probeBeforeUpdate
|
|
656
|
+
? runtime.markDirty()
|
|
657
|
+
: runtime.snapshot().dirtyRevision;
|
|
658
|
+
const followsNarrowWatch = this.scheduler.getByRoot(runtime.canonicalRoot)?.reason === "watch";
|
|
659
|
+
const submitted = this.scheduler.submit({
|
|
660
|
+
canonicalRoot: runtime.canonicalRoot,
|
|
661
|
+
reason,
|
|
662
|
+
followupIfRunning: followsNarrowWatch,
|
|
663
|
+
run: async (report, signal) => {
|
|
664
|
+
if (probeBeforeUpdate) {
|
|
665
|
+
if ((await this.probeCurrentFreshness(runtime)) === "fresh") {
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
if (createsWork) {
|
|
669
|
+
targetRevision = runtime.markDirty();
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
const proof = await this.runIndex(runtime, input, report, authorization, signal);
|
|
673
|
+
if (proof.reconciled) {
|
|
674
|
+
runtime.markReconciled(targetRevision, proof.reconciliationEpoch);
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
runtime.markIndexed(targetRevision);
|
|
678
|
+
}
|
|
679
|
+
},
|
|
680
|
+
});
|
|
681
|
+
if (!wait)
|
|
682
|
+
return submitted.job;
|
|
683
|
+
const job = await this.scheduler.wait(submitted.job.id);
|
|
684
|
+
await this.scheduler.waitForRootIdle(runtime.canonicalRoot);
|
|
685
|
+
return job;
|
|
686
|
+
}
|
|
687
|
+
ensureWatcher(runtime) {
|
|
688
|
+
if (this.watchers.has(runtime.canonicalRoot) || this.shuttingDown) {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
const coordinator = new IndexCoordinator({
|
|
692
|
+
runtime,
|
|
693
|
+
scheduler: this.scheduler,
|
|
694
|
+
run: async (changes, report, signal) => {
|
|
695
|
+
const changedPaths = [
|
|
696
|
+
...changes.touchedFiles,
|
|
697
|
+
...changes.rescanDirectories,
|
|
698
|
+
...changes.deletedPrefixes,
|
|
699
|
+
];
|
|
700
|
+
if (!changes.forceFullReconcile && changedPaths.length === 0) {
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
const automaticAuthorization = await this.automaticIndexAuthorization(runtime);
|
|
704
|
+
if (!automaticAuthorization.allowed) {
|
|
705
|
+
throw new DaemonError("REMOTE_EMBEDDING_AUTH_REQUIRED", "A Workspace Remote Embedding grant is required for file-watcher index updates.");
|
|
706
|
+
}
|
|
707
|
+
return await this.runIndex(runtime, {
|
|
708
|
+
root: runtime.canonicalRoot,
|
|
709
|
+
changedPaths: changes.forceFullReconcile ? undefined : changedPaths,
|
|
710
|
+
skipInitialStatus: changes.forceFullReconcile,
|
|
711
|
+
}, report, automaticAuthorization.authorization, signal);
|
|
712
|
+
},
|
|
713
|
+
});
|
|
714
|
+
const watcher = (this.options.watchManagerFactory ??
|
|
715
|
+
((options) => new WatchManager(options)))({
|
|
716
|
+
root: runtime.canonicalRoot,
|
|
717
|
+
onChanges: async (changes, reason) => {
|
|
718
|
+
const pathCount = changes.touchedFiles.length +
|
|
719
|
+
changes.rescanDirectories.length +
|
|
720
|
+
changes.deletedPrefixes.length;
|
|
721
|
+
if (changes.forceFullReconcile && pathCount === 0) {
|
|
722
|
+
runtime.requireFullReconciliation(true);
|
|
723
|
+
this.options.logger?.event("watcher.reconciliation_probe_requested", {
|
|
724
|
+
root_id: rootIdentity(runtime.canonicalRoot),
|
|
725
|
+
reason,
|
|
726
|
+
active_job: this.scheduler.hasActiveRoot(runtime.canonicalRoot),
|
|
727
|
+
});
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
const automaticAuthorization = await this.automaticIndexAuthorization(runtime);
|
|
731
|
+
if (!automaticAuthorization.allowed) {
|
|
732
|
+
runtime.markDirty();
|
|
733
|
+
runtime.requireFullReconciliation();
|
|
734
|
+
this.options.logger?.event("watcher.authorization_required", {
|
|
735
|
+
root_id: rootIdentity(runtime.canonicalRoot),
|
|
736
|
+
reason,
|
|
737
|
+
});
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
this.options.logger?.event(changes.forceFullReconcile ? "watcher.overflow" : "watcher.changes", {
|
|
741
|
+
root_id: rootIdentity(runtime.canonicalRoot),
|
|
742
|
+
reason,
|
|
743
|
+
touched_files: changes.touchedFiles.length,
|
|
744
|
+
rescan_directories: changes.rescanDirectories.length,
|
|
745
|
+
deleted_prefixes: changes.deletedPrefixes.length,
|
|
746
|
+
});
|
|
747
|
+
coordinator.enqueue(changes, reason);
|
|
748
|
+
},
|
|
749
|
+
onPendingChange: (pending) => runtime.setWatcherPending(pending),
|
|
750
|
+
onActivity: () => runtime.recordWatcherActivity(),
|
|
751
|
+
onActiveChange: (active) => runtime.setWatcherActive(active),
|
|
752
|
+
getRootPaths: () => this.statusCache.get(runtime.canonicalRoot)?.workspaceIndex?.rootPaths,
|
|
753
|
+
});
|
|
754
|
+
watcher.start();
|
|
755
|
+
this.indexCoordinators.set(runtime.canonicalRoot, coordinator);
|
|
756
|
+
this.watchers.set(runtime.canonicalRoot, watcher);
|
|
757
|
+
}
|
|
758
|
+
async settleKnownChanges(runtime) {
|
|
759
|
+
const watcher = this.watchers.get(runtime.canonicalRoot);
|
|
760
|
+
while (true) {
|
|
761
|
+
await watcher?.flushPending();
|
|
762
|
+
await this.scheduler.waitForRootIdle(runtime.canonicalRoot);
|
|
763
|
+
const job = this.scheduler.getByRoot(runtime.canonicalRoot);
|
|
764
|
+
const snapshot = runtime.snapshot();
|
|
765
|
+
if (job?.state === "failed" ||
|
|
766
|
+
job?.state === "cancelled" ||
|
|
767
|
+
!snapshot.watcherPending) {
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
async automaticIndexAuthorization(runtime) {
|
|
773
|
+
const knownProvider = runtime.embeddingProvider();
|
|
774
|
+
if (knownProvider && knownProvider !== "qwen")
|
|
775
|
+
return { allowed: true };
|
|
776
|
+
const root = runtime.canonicalRoot;
|
|
777
|
+
const info = await this.inspectRoot(root, false);
|
|
778
|
+
const schema = info.workspaceIndex?.embedding;
|
|
779
|
+
if (!schema || schema.provider !== "qwen")
|
|
780
|
+
return { allowed: true };
|
|
781
|
+
const modelInfo = await this.loadEmbeddingModelInfo(this.searchModelLoadRequest(info, {}));
|
|
782
|
+
const plan = await planRemoteIndexAuthorization({
|
|
783
|
+
info,
|
|
784
|
+
model: modelInfo,
|
|
785
|
+
needsUpdate: true,
|
|
786
|
+
store: this.authorizationManager.store,
|
|
787
|
+
});
|
|
788
|
+
if (!plan)
|
|
789
|
+
return { allowed: true };
|
|
790
|
+
const authorization = await this.authorizationManager.existingWorkspacePermit(plan);
|
|
791
|
+
return authorization
|
|
792
|
+
? { allowed: true, authorization }
|
|
793
|
+
: { allowed: false };
|
|
794
|
+
}
|
|
795
|
+
async waitForFresh(runtime, authorization, runtimeOverrides = {}) {
|
|
796
|
+
let updateJob;
|
|
797
|
+
while (true) {
|
|
798
|
+
await this.settleKnownChanges(runtime);
|
|
799
|
+
if (!runtime.needsReconciliation()) {
|
|
800
|
+
return updateJob;
|
|
801
|
+
}
|
|
802
|
+
if (!runtime.requiresFullReconciliation() ||
|
|
803
|
+
runtime.canProbeFullReconciliation() ||
|
|
804
|
+
this.scheduler.getByRoot(runtime.canonicalRoot)?.state === "failed" ||
|
|
805
|
+
this.scheduler.getByRoot(runtime.canonicalRoot)?.state === "cancelled") {
|
|
806
|
+
const freshness = await this.probeCurrentFreshness(runtime);
|
|
807
|
+
if (freshness === "fresh") {
|
|
808
|
+
return updateJob;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
const currentJob = this.scheduler.getByRoot(runtime.canonicalRoot);
|
|
812
|
+
if (!runtime.requiresFullReconciliation() &&
|
|
813
|
+
(currentJob?.state === "failed" || currentJob?.state === "cancelled")) {
|
|
814
|
+
throw new DaemonError(currentJob.error?.code ?? "INDEX_FAILED", currentJob.error?.message ??
|
|
815
|
+
"Known index changes did not complete successfully.");
|
|
816
|
+
}
|
|
817
|
+
updateJob = await this.submitIndex(runtime, {
|
|
818
|
+
root: runtime.canonicalRoot,
|
|
819
|
+
apiKey: runtimeOverrides.apiKey,
|
|
820
|
+
device: runtimeOverrides.device,
|
|
821
|
+
embeddingConcurrency: runtimeOverrides.embeddingConcurrency,
|
|
822
|
+
runtimeOverridesAreEphemeral: true,
|
|
823
|
+
}, "fresh_query", true, authorization);
|
|
824
|
+
if (updateJob.state !== "succeeded") {
|
|
825
|
+
throw new DaemonError(updateJob.error?.code ?? "INDEX_FAILED", updateJob.error?.message ??
|
|
826
|
+
"Index reconciliation did not complete successfully.");
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
async loadEmbeddingModelInfo(request) {
|
|
831
|
+
const lease = await this.modelPool.acquire(request);
|
|
832
|
+
try {
|
|
833
|
+
return lease.model.info;
|
|
834
|
+
}
|
|
835
|
+
finally {
|
|
836
|
+
lease.release();
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
async probeCurrentFreshness(runtime) {
|
|
840
|
+
const releaseRuntimeActivity = runtime.beginActivity();
|
|
841
|
+
try {
|
|
842
|
+
const freshness = await runtime.probeFreshness(async () => {
|
|
843
|
+
const info = await this.inspectRoot(runtime.canonicalRoot, true);
|
|
844
|
+
this.statusCache.set(runtime.canonicalRoot, info);
|
|
845
|
+
return indexStatusIsFresh(info);
|
|
846
|
+
});
|
|
847
|
+
this.options.logger?.event(`runtime.recovery_probe_${freshness}`, {
|
|
848
|
+
root_id: rootIdentity(runtime.canonicalRoot),
|
|
849
|
+
});
|
|
850
|
+
return freshness;
|
|
851
|
+
}
|
|
852
|
+
finally {
|
|
853
|
+
releaseRuntimeActivity();
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
async closeWatcher(canonicalRoot) {
|
|
857
|
+
const watcher = this.watchers.get(canonicalRoot);
|
|
858
|
+
this.watchers.delete(canonicalRoot);
|
|
859
|
+
this.indexCoordinators.delete(canonicalRoot);
|
|
860
|
+
await watcher?.close();
|
|
861
|
+
}
|
|
862
|
+
assertRootNotDropping(canonicalRoot) {
|
|
863
|
+
if (this.droppingRoots.has(canonicalRoot)) {
|
|
864
|
+
throw new DaemonError("INDEX_DROP_IN_PROGRESS", "The Workspace index is being dropped.", true);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
indexModel(info, input) {
|
|
868
|
+
if (info.workspaceIndex?.embedding && !input.embedding) {
|
|
869
|
+
return {
|
|
870
|
+
provider: info.workspaceIndex.embedding.provider,
|
|
871
|
+
name: info.workspaceIndex.embedding.model,
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
const reference = resolveEmbeddingReference({
|
|
875
|
+
explicit: input.embedding ?? this.options.serviceOptions?.embedding,
|
|
876
|
+
environment: {
|
|
877
|
+
ZVEC_GREP_EMBEDDING: input.embeddingEnvironment ?? process.env.ZVEC_GREP_EMBEDDING,
|
|
878
|
+
},
|
|
879
|
+
globalDefault: readGlobalConfig().defaults?.embedding,
|
|
880
|
+
fallback: DEFAULT_LOCAL_EMBEDDING,
|
|
881
|
+
});
|
|
882
|
+
if (!reference) {
|
|
883
|
+
throw new DaemonError("MODEL_LOAD_FAILED", "A new index requires embedding or an explicit server default model.");
|
|
884
|
+
}
|
|
885
|
+
return parseEmbeddingModelReference(reference);
|
|
886
|
+
}
|
|
887
|
+
indexModelLoadRequest(info, input) {
|
|
888
|
+
const model = this.indexModel(info, input);
|
|
889
|
+
const workspaceRuntime = info.workspaceIndex?.embedding?.provider === model.provider
|
|
890
|
+
? this.readWorkspaceEmbeddingRuntime(info)
|
|
891
|
+
: {};
|
|
892
|
+
const runtime = this.resolveModelRuntime(model, workspaceRuntime, input);
|
|
893
|
+
if (input.rebuild !== true &&
|
|
894
|
+
info.workspaceIndex?.embedding &&
|
|
895
|
+
workspaceRuntime.endpoint !== runtime.endpoint) {
|
|
896
|
+
throw new DaemonError("EMBEDDING_ENDPOINT_MISMATCH", "The requested embedding endpoint differs from the workspace snapshot; use rebuild to change endpoints.");
|
|
897
|
+
}
|
|
898
|
+
const embeddingConcurrency = resolveIndexEmbeddingConcurrency(model, input.embeddingConcurrency ??
|
|
899
|
+
this.options.serviceOptions?.embeddingConcurrency);
|
|
900
|
+
return {
|
|
901
|
+
model,
|
|
902
|
+
runtime,
|
|
903
|
+
...(embeddingConcurrency !== undefined ? { embeddingConcurrency } : {}),
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
searchModelLoadRequest(info, overrides) {
|
|
907
|
+
const schema = info.workspaceIndex?.embedding;
|
|
908
|
+
if (!info.indexed || !schema) {
|
|
909
|
+
throw new DaemonError("INDEX_MISSING", "Search requires an existing workspace index.");
|
|
910
|
+
}
|
|
911
|
+
const model = {
|
|
912
|
+
provider: schema.provider,
|
|
913
|
+
name: schema.model,
|
|
914
|
+
};
|
|
915
|
+
const workspaceRuntime = this.readWorkspaceEmbeddingRuntime(info);
|
|
916
|
+
const runtime = this.resolveModelRuntime(model, workspaceRuntime, overrides);
|
|
917
|
+
return { model, runtime };
|
|
918
|
+
}
|
|
919
|
+
resolveModelRuntime(model, workspaceRuntime, overrides) {
|
|
920
|
+
const serviceOptions = this.options.serviceOptions;
|
|
921
|
+
return resolveEmbeddingRuntimeOptions(embeddingModelReference(model), {
|
|
922
|
+
apiKey: overrides.apiKey ?? serviceOptions?.apiKey,
|
|
923
|
+
endpoint: overrides.endpoint ?? serviceOptions?.endpoint,
|
|
924
|
+
device: overrides.device ?? serviceOptions?.device,
|
|
925
|
+
}, workspaceRuntime, readGlobalConfig());
|
|
926
|
+
}
|
|
927
|
+
overrideActiveModelLoadRequest(request, overrides) {
|
|
928
|
+
const runtime = resolveEmbeddingRuntimeOptions(embeddingModelReference(request.model), overrides, request.runtime ?? {}, readGlobalConfig());
|
|
929
|
+
return {
|
|
930
|
+
model: request.model,
|
|
931
|
+
runtime,
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
readWorkspaceEmbeddingRuntime(info) {
|
|
935
|
+
try {
|
|
936
|
+
const runtime = readWorkspaceEmbeddingRuntime(info);
|
|
937
|
+
this.workspaceRuntimeCache.set(info.root, runtime);
|
|
938
|
+
return runtime;
|
|
939
|
+
}
|
|
940
|
+
catch (error) {
|
|
941
|
+
const cached = this.workspaceRuntimeCache.get(info.root);
|
|
942
|
+
if (cached &&
|
|
943
|
+
isEngineError(error) &&
|
|
944
|
+
(error.code === "ZVEC_GREP.ENGINE.STORAGE.ZVEC_OPEN_FAILED" ||
|
|
945
|
+
error.code === "ZVEC_GREP.ENGINE.LOCK.BUSY")) {
|
|
946
|
+
return cached;
|
|
947
|
+
}
|
|
948
|
+
throw error;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
async inspectRootWithCache(root) {
|
|
952
|
+
const cached = this.statusCache.get(root);
|
|
953
|
+
if (cached) {
|
|
954
|
+
return cached;
|
|
955
|
+
}
|
|
956
|
+
try {
|
|
957
|
+
const info = await this.inspectRoot(root, false);
|
|
958
|
+
this.statusCache.set(root, info);
|
|
959
|
+
return info;
|
|
960
|
+
}
|
|
961
|
+
catch (error) {
|
|
962
|
+
const fallback = this.statusCache.get(root);
|
|
963
|
+
if (fallback &&
|
|
964
|
+
isEngineError(error) &&
|
|
965
|
+
error.code === "ZVEC_GREP.ENGINE.LOCK.BUSY") {
|
|
966
|
+
return fallback;
|
|
967
|
+
}
|
|
968
|
+
throw error;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
async inspectRoot(root, includeStatus) {
|
|
972
|
+
return await (this.options.inspectRoot ?? inspectRoot)(root, this.options.serviceOptions, includeStatus);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
function readWorkspaceEmbeddingRuntime(info) {
|
|
976
|
+
if (!info.workspaceIndex)
|
|
977
|
+
return {};
|
|
978
|
+
const location = workspaceIndexLocation(info.root);
|
|
979
|
+
return readWorkspaceManifest(location.home)?.embeddingRuntime ?? {};
|
|
980
|
+
}
|
|
981
|
+
function indexStatusIsFresh(info) {
|
|
982
|
+
const status = info.status;
|
|
983
|
+
return (status !== null &&
|
|
984
|
+
status !== undefined &&
|
|
985
|
+
status.filesAdded === 0 &&
|
|
986
|
+
status.filesModified === 0 &&
|
|
987
|
+
status.filesDeleted === 0 &&
|
|
988
|
+
status.filesPending === 0 &&
|
|
989
|
+
status.filesFailed === 0);
|
|
990
|
+
}
|
|
991
|
+
function assertDropOnlyInput(input) {
|
|
992
|
+
const conflicts = [
|
|
993
|
+
[input.embedding !== undefined, "embedding"],
|
|
994
|
+
[input.apiKey !== undefined, "apiKey"],
|
|
995
|
+
[input.endpoint !== undefined, "endpoint"],
|
|
996
|
+
[input.device !== undefined, "device"],
|
|
997
|
+
[input.rebuild !== undefined, "rebuild"],
|
|
998
|
+
[input.resetPaths !== undefined, "resetPaths"],
|
|
999
|
+
[input.globs !== undefined, "globs"],
|
|
1000
|
+
[input.insensitiveGlobs !== undefined, "insensitiveGlobs"],
|
|
1001
|
+
[input.fileTypes !== undefined, "fileTypes"],
|
|
1002
|
+
[input.excludedFileTypes !== undefined, "excludedFileTypes"],
|
|
1003
|
+
[input.hidden !== undefined, "hidden"],
|
|
1004
|
+
[input.noIgnore !== undefined, "noIgnore"],
|
|
1005
|
+
[input.ignoreFiles !== undefined, "ignoreFiles"],
|
|
1006
|
+
[input.maxDepth !== undefined, "maxDepth"],
|
|
1007
|
+
[input.maxFileSizeBytes !== undefined, "maxFileSizeBytes"],
|
|
1008
|
+
[input.follow !== undefined, "follow"],
|
|
1009
|
+
[input.embeddingConcurrency !== undefined, "embeddingConcurrency"],
|
|
1010
|
+
[input.wait !== undefined, "wait"],
|
|
1011
|
+
];
|
|
1012
|
+
const names = conflicts
|
|
1013
|
+
.filter(([conflictsWithDrop]) => conflictsWithDrop)
|
|
1014
|
+
.map(([, name]) => name);
|
|
1015
|
+
if (names.length > 0) {
|
|
1016
|
+
throw new DaemonError("INVALID_ARGUMENT", `zvec_grep_index drop cannot be combined with ${names.join(", ")}.`);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
function embeddingSchema(model) {
|
|
1020
|
+
return {
|
|
1021
|
+
provider: model.info.provider,
|
|
1022
|
+
model: model.info.name,
|
|
1023
|
+
dimension: model.info.dimension,
|
|
1024
|
+
metric: model.info.metric,
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
function parseEmbeddingModelReference(reference) {
|
|
1028
|
+
const separator = reference.indexOf("/");
|
|
1029
|
+
if (separator <= 0 || separator === reference.length - 1) {
|
|
1030
|
+
throw new DaemonError("MODEL_LOAD_FAILED", `Embedding model reference ${reference} is invalid.`);
|
|
1031
|
+
}
|
|
1032
|
+
return {
|
|
1033
|
+
provider: reference.slice(0, separator),
|
|
1034
|
+
name: reference.slice(separator + 1),
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
function embeddingModelReference(model) {
|
|
1038
|
+
return `${model.provider}/${model.name}`;
|
|
1039
|
+
}
|
|
1040
|
+
function persistentStatus(info) {
|
|
1041
|
+
return {
|
|
1042
|
+
home: info.home,
|
|
1043
|
+
index_path: info.indexPath,
|
|
1044
|
+
workspace_index: info.workspaceIndex
|
|
1045
|
+
? {
|
|
1046
|
+
id: info.workspaceIndex.id,
|
|
1047
|
+
name: info.workspaceIndex.name,
|
|
1048
|
+
path: info.workspaceIndex.path,
|
|
1049
|
+
root_paths: info.workspaceIndex.rootPaths.map((rootPath) => ({
|
|
1050
|
+
absolute_path: rootPath.absolutePath,
|
|
1051
|
+
recursive: rootPath.recursive,
|
|
1052
|
+
include: rootPath.include ? [...rootPath.include] : undefined,
|
|
1053
|
+
exclude: rootPath.exclude ? [...rootPath.exclude] : undefined,
|
|
1054
|
+
globs: rootPath.globs ? [...rootPath.globs] : undefined,
|
|
1055
|
+
insensitive_globs: rootPath.insensitiveGlobs
|
|
1056
|
+
? [...rootPath.insensitiveGlobs]
|
|
1057
|
+
: undefined,
|
|
1058
|
+
file_types: rootPath.fileTypes
|
|
1059
|
+
? [...rootPath.fileTypes]
|
|
1060
|
+
: undefined,
|
|
1061
|
+
excluded_file_types: rootPath.excludedFileTypes
|
|
1062
|
+
? [...rootPath.excludedFileTypes]
|
|
1063
|
+
: undefined,
|
|
1064
|
+
hidden: rootPath.hidden,
|
|
1065
|
+
no_ignore: rootPath.noIgnore,
|
|
1066
|
+
ignore_files: rootPath.ignoreFiles
|
|
1067
|
+
? [...rootPath.ignoreFiles]
|
|
1068
|
+
: undefined,
|
|
1069
|
+
max_depth: rootPath.maxDepth,
|
|
1070
|
+
max_file_size_bytes: rootPath.maxFileSizeBytes,
|
|
1071
|
+
follow: rootPath.follow,
|
|
1072
|
+
})),
|
|
1073
|
+
embedding: info.workspaceIndex.embedding,
|
|
1074
|
+
index_version: info.workspaceIndex.indexVersion,
|
|
1075
|
+
created_time: info.workspaceIndex.createdTime,
|
|
1076
|
+
updated_time: info.workspaceIndex.updatedTime,
|
|
1077
|
+
}
|
|
1078
|
+
: undefined,
|
|
1079
|
+
files: info.status
|
|
1080
|
+
? {
|
|
1081
|
+
stored: info.status.filesStored,
|
|
1082
|
+
scanned: info.status.filesScanned,
|
|
1083
|
+
indexed: info.status.filesIndexed,
|
|
1084
|
+
pending: info.status.filesPending,
|
|
1085
|
+
failed: info.status.filesFailed,
|
|
1086
|
+
added: info.status.filesAdded,
|
|
1087
|
+
modified: info.status.filesModified,
|
|
1088
|
+
deleted: info.status.filesDeleted,
|
|
1089
|
+
unchanged: info.status.filesUnchanged,
|
|
1090
|
+
entities: info.status.entitiesIndexed,
|
|
1091
|
+
truncated_fragments: info.status.fragmentsTruncated,
|
|
1092
|
+
}
|
|
1093
|
+
: undefined,
|
|
1094
|
+
suggestion: info.suggestion,
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
function formatProgress(job) {
|
|
1098
|
+
const progress = job.progress;
|
|
1099
|
+
if (!progress) {
|
|
1100
|
+
return undefined;
|
|
1101
|
+
}
|
|
1102
|
+
return {
|
|
1103
|
+
phase: progress.phase,
|
|
1104
|
+
files_total: progress.filesTotal,
|
|
1105
|
+
files_indexed: progress.filesIndexed,
|
|
1106
|
+
files_failed: progress.filesFailed,
|
|
1107
|
+
detail: progress.detail,
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
function searchIndexingSnapshot(job, completion) {
|
|
1111
|
+
const state = !job || job.state === "succeeded" ? "idle" : job.state;
|
|
1112
|
+
const effectiveCompletion = indexCompletionForJob(completion, job?.state, job?.progress);
|
|
1113
|
+
return {
|
|
1114
|
+
state,
|
|
1115
|
+
...effectiveCompletion,
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
//# sourceMappingURL=backend.js.map
|