@untangle-code/cli 0.0.0-stage → 0.1.0
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 +661 -0
- package/NOTICE +90 -0
- package/README.md +424 -2
- package/THIRD_PARTY_LICENSES.md +152 -0
- package/dist/cli/args.d.ts +48 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +167 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/command.d.ts +69 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +82 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/deadline.d.ts +33 -0
- package/dist/cli/deadline.d.ts.map +1 -0
- package/dist/cli/deadline.js +49 -0
- package/dist/cli/deadline.js.map +1 -0
- package/dist/cli/embedder-deadline.d.ts +72 -0
- package/dist/cli/embedder-deadline.d.ts.map +1 -0
- package/dist/cli/embedder-deadline.js +117 -0
- package/dist/cli/embedder-deadline.js.map +1 -0
- package/dist/cli/exit.d.ts +71 -0
- package/dist/cli/exit.d.ts.map +1 -0
- package/dist/cli/exit.js +81 -0
- package/dist/cli/exit.js.map +1 -0
- package/dist/cli/graphs.d.ts +65 -0
- package/dist/cli/graphs.d.ts.map +1 -0
- package/dist/cli/graphs.js +108 -0
- package/dist/cli/graphs.js.map +1 -0
- package/dist/cli/index-freshness.d.ts +13 -0
- package/dist/cli/index-freshness.d.ts.map +1 -0
- package/dist/cli/index-freshness.js +226 -0
- package/dist/cli/index-freshness.js.map +1 -0
- package/dist/cli/index-refresh.d.ts +10 -0
- package/dist/cli/index-refresh.d.ts.map +1 -0
- package/dist/cli/index-refresh.js +76 -0
- package/dist/cli/index-refresh.js.map +1 -0
- package/dist/cli/index-state.d.ts +184 -0
- package/dist/cli/index-state.d.ts.map +1 -0
- package/dist/cli/index-state.js +852 -0
- package/dist/cli/index-state.js.map +1 -0
- package/dist/cli/io.d.ts +29 -0
- package/dist/cli/io.d.ts.map +1 -0
- package/dist/cli/io.js +42 -0
- package/dist/cli/io.js.map +1 -0
- package/dist/cli/language-support.d.ts +77 -0
- package/dist/cli/language-support.d.ts.map +1 -0
- package/dist/cli/language-support.js +152 -0
- package/dist/cli/language-support.js.map +1 -0
- package/dist/cli/renewing-lease.d.ts +26 -0
- package/dist/cli/renewing-lease.d.ts.map +1 -0
- package/dist/cli/renewing-lease.js +102 -0
- package/dist/cli/renewing-lease.js.map +1 -0
- package/dist/cli/search-graph-enrichment.d.ts +16 -0
- package/dist/cli/search-graph-enrichment.d.ts.map +1 -0
- package/dist/cli/search-graph-enrichment.js +428 -0
- package/dist/cli/search-graph-enrichment.js.map +1 -0
- package/dist/cli/system.d.ts +34 -0
- package/dist/cli/system.d.ts.map +1 -0
- package/dist/cli/system.js +89 -0
- package/dist/cli/system.js.map +1 -0
- package/dist/cli/vector-store-policy.d.ts +116 -0
- package/dist/cli/vector-store-policy.d.ts.map +1 -0
- package/dist/cli/vector-store-policy.js +160 -0
- package/dist/cli/vector-store-policy.js.map +1 -0
- package/dist/cli/version.d.ts +3 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +3 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli/workspace.d.ts +105 -0
- package/dist/cli/workspace.d.ts.map +1 -0
- package/dist/cli/workspace.js +215 -0
- package/dist/cli/workspace.js.map +1 -0
- package/dist/commands/complexity.d.ts +72 -0
- package/dist/commands/complexity.d.ts.map +1 -0
- package/dist/commands/complexity.js +580 -0
- package/dist/commands/complexity.js.map +1 -0
- package/dist/commands/doctor.d.ts +66 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +764 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.languages.d.ts +37 -0
- package/dist/commands/doctor.languages.d.ts.map +1 -0
- package/dist/commands/doctor.languages.js +143 -0
- package/dist/commands/doctor.languages.js.map +1 -0
- package/dist/commands/doctor.storage.d.ts +17 -0
- package/dist/commands/doctor.storage.d.ts.map +1 -0
- package/dist/commands/doctor.storage.js +91 -0
- package/dist/commands/doctor.storage.js.map +1 -0
- package/dist/commands/extensions/add.d.ts +10 -0
- package/dist/commands/extensions/add.d.ts.map +1 -0
- package/dist/commands/extensions/add.js +213 -0
- package/dist/commands/extensions/add.js.map +1 -0
- package/dist/commands/extensions/configure.d.ts +5 -0
- package/dist/commands/extensions/configure.d.ts.map +1 -0
- package/dist/commands/extensions/configure.js +58 -0
- package/dist/commands/extensions/configure.js.map +1 -0
- package/dist/commands/extensions/container.d.ts +15 -0
- package/dist/commands/extensions/container.d.ts.map +1 -0
- package/dist/commands/extensions/container.js +135 -0
- package/dist/commands/extensions/container.js.map +1 -0
- package/dist/commands/extensions/context.d.ts +37 -0
- package/dist/commands/extensions/context.d.ts.map +1 -0
- package/dist/commands/extensions/context.js +72 -0
- package/dist/commands/extensions/context.js.map +1 -0
- package/dist/commands/extensions/enable.d.ts +6 -0
- package/dist/commands/extensions/enable.d.ts.map +1 -0
- package/dist/commands/extensions/enable.js +180 -0
- package/dist/commands/extensions/enable.js.map +1 -0
- package/dist/commands/extensions/environment.d.ts +74 -0
- package/dist/commands/extensions/environment.d.ts.map +1 -0
- package/dist/commands/extensions/environment.js +168 -0
- package/dist/commands/extensions/environment.js.map +1 -0
- package/dist/commands/extensions/feature-scan.d.ts +48 -0
- package/dist/commands/extensions/feature-scan.d.ts.map +1 -0
- package/dist/commands/extensions/feature-scan.js +156 -0
- package/dist/commands/extensions/feature-scan.js.map +1 -0
- package/dist/commands/extensions/invoke.d.ts +60 -0
- package/dist/commands/extensions/invoke.d.ts.map +1 -0
- package/dist/commands/extensions/invoke.js +275 -0
- package/dist/commands/extensions/invoke.js.map +1 -0
- package/dist/commands/extensions/list.d.ts +5 -0
- package/dist/commands/extensions/list.d.ts.map +1 -0
- package/dist/commands/extensions/list.js +125 -0
- package/dist/commands/extensions/list.js.map +1 -0
- package/dist/commands/extensions/logs.d.ts +5 -0
- package/dist/commands/extensions/logs.d.ts.map +1 -0
- package/dist/commands/extensions/logs.js +74 -0
- package/dist/commands/extensions/logs.js.map +1 -0
- package/dist/commands/extensions/provision.d.ts +36 -0
- package/dist/commands/extensions/provision.d.ts.map +1 -0
- package/dist/commands/extensions/provision.js +137 -0
- package/dist/commands/extensions/provision.js.map +1 -0
- package/dist/commands/extensions/remove.d.ts +5 -0
- package/dist/commands/extensions/remove.d.ts.map +1 -0
- package/dist/commands/extensions/remove.js +77 -0
- package/dist/commands/extensions/remove.js.map +1 -0
- package/dist/commands/extensions/render.d.ts +16 -0
- package/dist/commands/extensions/render.d.ts.map +1 -0
- package/dist/commands/extensions/render.js +25 -0
- package/dist/commands/extensions/render.js.map +1 -0
- package/dist/commands/extensions/run.d.ts +30 -0
- package/dist/commands/extensions/run.d.ts.map +1 -0
- package/dist/commands/extensions/run.js +292 -0
- package/dist/commands/extensions/run.js.map +1 -0
- package/dist/commands/extensions/secret-store.d.ts +15 -0
- package/dist/commands/extensions/secret-store.d.ts.map +1 -0
- package/dist/commands/extensions/secret-store.js +164 -0
- package/dist/commands/extensions/secret-store.js.map +1 -0
- package/dist/commands/extensions/setup.d.ts +17 -0
- package/dist/commands/extensions/setup.d.ts.map +1 -0
- package/dist/commands/extensions/setup.js +94 -0
- package/dist/commands/extensions/setup.js.map +1 -0
- package/dist/commands/extensions/source.d.ts +47 -0
- package/dist/commands/extensions/source.d.ts.map +1 -0
- package/dist/commands/extensions/source.js +142 -0
- package/dist/commands/extensions/source.js.map +1 -0
- package/dist/commands/extensions/state.d.ts +62 -0
- package/dist/commands/extensions/state.d.ts.map +1 -0
- package/dist/commands/extensions/state.js +177 -0
- package/dist/commands/extensions/state.js.map +1 -0
- package/dist/commands/extensions/status.d.ts +9 -0
- package/dist/commands/extensions/status.d.ts.map +1 -0
- package/dist/commands/extensions/status.js +239 -0
- package/dist/commands/extensions/status.js.map +1 -0
- package/dist/commands/extensions.d.ts +3 -0
- package/dist/commands/extensions.d.ts.map +1 -0
- package/dist/commands/extensions.js +223 -0
- package/dist/commands/extensions.js.map +1 -0
- package/dist/commands/flow/index.d.ts +3 -0
- package/dist/commands/flow/index.d.ts.map +1 -0
- package/dist/commands/flow/index.js +295 -0
- package/dist/commands/flow/index.js.map +1 -0
- package/dist/commands/flow/limits.d.ts +12 -0
- package/dist/commands/flow/limits.d.ts.map +1 -0
- package/dist/commands/flow/limits.js +13 -0
- package/dist/commands/flow/limits.js.map +1 -0
- package/dist/commands/flow/output.d.ts +8 -0
- package/dist/commands/flow/output.d.ts.map +1 -0
- package/dist/commands/flow/output.js +11 -0
- package/dist/commands/flow/output.js.map +1 -0
- package/dist/commands/flow/render.d.ts +51 -0
- package/dist/commands/flow/render.d.ts.map +1 -0
- package/dist/commands/flow/render.js +220 -0
- package/dist/commands/flow/render.js.map +1 -0
- package/dist/commands/flow/select.d.ts +31 -0
- package/dist/commands/flow/select.d.ts.map +1 -0
- package/dist/commands/flow/select.js +62 -0
- package/dist/commands/flow/select.js.map +1 -0
- package/dist/commands/graph/boundaries-input.d.ts +26 -0
- package/dist/commands/graph/boundaries-input.d.ts.map +1 -0
- package/dist/commands/graph/boundaries-input.js +54 -0
- package/dist/commands/graph/boundaries-input.js.map +1 -0
- package/dist/commands/graph/boundaries.d.ts +4 -0
- package/dist/commands/graph/boundaries.d.ts.map +1 -0
- package/dist/commands/graph/boundaries.js +141 -0
- package/dist/commands/graph/boundaries.js.map +1 -0
- package/dist/commands/graph/bounds.d.ts +16 -0
- package/dist/commands/graph/bounds.d.ts.map +1 -0
- package/dist/commands/graph/bounds.js +22 -0
- package/dist/commands/graph/bounds.js.map +1 -0
- package/dist/commands/graph/category-clusters.d.ts +20 -0
- package/dist/commands/graph/category-clusters.d.ts.map +1 -0
- package/dist/commands/graph/category-clusters.js +158 -0
- package/dist/commands/graph/category-clusters.js.map +1 -0
- package/dist/commands/graph/feature-3d.d.ts +22 -0
- package/dist/commands/graph/feature-3d.d.ts.map +1 -0
- package/dist/commands/graph/feature-3d.js +114 -0
- package/dist/commands/graph/feature-3d.js.map +1 -0
- package/dist/commands/graph/feature-clusters.d.ts +17 -0
- package/dist/commands/graph/feature-clusters.d.ts.map +1 -0
- package/dist/commands/graph/feature-clusters.js +94 -0
- package/dist/commands/graph/feature-clusters.js.map +1 -0
- package/dist/commands/graph/feature-html.d.ts +26 -0
- package/dist/commands/graph/feature-html.d.ts.map +1 -0
- package/dist/commands/graph/feature-html.js +314 -0
- package/dist/commands/graph/feature-html.js.map +1 -0
- package/dist/commands/graph/feature-map.d.ts +31 -0
- package/dist/commands/graph/feature-map.d.ts.map +1 -0
- package/dist/commands/graph/feature-map.js +217 -0
- package/dist/commands/graph/feature-map.js.map +1 -0
- package/dist/commands/graph/feature-model.d.ts +55 -0
- package/dist/commands/graph/feature-model.d.ts.map +1 -0
- package/dist/commands/graph/feature-model.js +167 -0
- package/dist/commands/graph/feature-model.js.map +1 -0
- package/dist/commands/graph/feature-untangle-motion.d.ts +33 -0
- package/dist/commands/graph/feature-untangle-motion.d.ts.map +1 -0
- package/dist/commands/graph/feature-untangle-motion.js +155 -0
- package/dist/commands/graph/feature-untangle-motion.js.map +1 -0
- package/dist/commands/graph/index.d.ts +3 -0
- package/dist/commands/graph/index.d.ts.map +1 -0
- package/dist/commands/graph/index.js +414 -0
- package/dist/commands/graph/index.js.map +1 -0
- package/dist/commands/graph/render.d.ts +63 -0
- package/dist/commands/graph/render.d.ts.map +1 -0
- package/dist/commands/graph/render.js +352 -0
- package/dist/commands/graph/render.js.map +1 -0
- package/dist/commands/graph/select.d.ts +34 -0
- package/dist/commands/graph/select.d.ts.map +1 -0
- package/dist/commands/graph/select.js +55 -0
- package/dist/commands/graph/select.js.map +1 -0
- package/dist/commands/index/index.d.ts +6 -0
- package/dist/commands/index/index.d.ts.map +1 -0
- package/dist/commands/index/index.js +461 -0
- package/dist/commands/index/index.js.map +1 -0
- package/dist/commands/index/render.d.ts +53 -0
- package/dist/commands/index/render.d.ts.map +1 -0
- package/dist/commands/index/render.js +205 -0
- package/dist/commands/index/render.js.map +1 -0
- package/dist/commands/index/target.d.ts +34 -0
- package/dist/commands/index/target.d.ts.map +1 -0
- package/dist/commands/index/target.js +97 -0
- package/dist/commands/index/target.js.map +1 -0
- package/dist/commands/index-watch.d.ts +30 -0
- package/dist/commands/index-watch.d.ts.map +1 -0
- package/dist/commands/index-watch.js +138 -0
- package/dist/commands/index-watch.js.map +1 -0
- package/dist/commands/init/command.d.ts +25 -0
- package/dist/commands/init/command.d.ts.map +1 -0
- package/dist/commands/init/command.js +198 -0
- package/dist/commands/init/command.js.map +1 -0
- package/dist/commands/init/config-draft.d.ts +48 -0
- package/dist/commands/init/config-draft.d.ts.map +1 -0
- package/dist/commands/init/config-draft.js +201 -0
- package/dist/commands/init/config-draft.js.map +1 -0
- package/dist/commands/init/diff.d.ts +33 -0
- package/dist/commands/init/diff.d.ts.map +1 -0
- package/dist/commands/init/diff.js +109 -0
- package/dist/commands/init/diff.js.map +1 -0
- package/dist/commands/init/http-probe.d.ts +26 -0
- package/dist/commands/init/http-probe.d.ts.map +1 -0
- package/dist/commands/init/http-probe.js +144 -0
- package/dist/commands/init/http-probe.js.map +1 -0
- package/dist/commands/init/ignore-rules.d.ts +70 -0
- package/dist/commands/init/ignore-rules.d.ts.map +1 -0
- package/dist/commands/init/ignore-rules.js +146 -0
- package/dist/commands/init/ignore-rules.js.map +1 -0
- package/dist/commands/init/index.d.ts +33 -0
- package/dist/commands/init/index.d.ts.map +1 -0
- package/dist/commands/init/index.js +32 -0
- package/dist/commands/init/index.js.map +1 -0
- package/dist/commands/init/integrations-apply.d.ts +50 -0
- package/dist/commands/init/integrations-apply.d.ts.map +1 -0
- package/dist/commands/init/integrations-apply.js +452 -0
- package/dist/commands/init/integrations-apply.js.map +1 -0
- package/dist/commands/init/integrations-plan.d.ts +68 -0
- package/dist/commands/init/integrations-plan.d.ts.map +1 -0
- package/dist/commands/init/integrations-plan.js +515 -0
- package/dist/commands/init/integrations-plan.js.map +1 -0
- package/dist/commands/init/integrations.d.ts +5 -0
- package/dist/commands/init/integrations.d.ts.map +1 -0
- package/dist/commands/init/integrations.js +4 -0
- package/dist/commands/init/integrations.js.map +1 -0
- package/dist/commands/init/languages.d.ts +55 -0
- package/dist/commands/init/languages.d.ts.map +1 -0
- package/dist/commands/init/languages.js +245 -0
- package/dist/commands/init/languages.js.map +1 -0
- package/dist/commands/init/product-context.d.ts +63 -0
- package/dist/commands/init/product-context.d.ts.map +1 -0
- package/dist/commands/init/product-context.js +390 -0
- package/dist/commands/init/product-context.js.map +1 -0
- package/dist/commands/init/render.d.ts +38 -0
- package/dist/commands/init/render.d.ts.map +1 -0
- package/dist/commands/init/render.js +501 -0
- package/dist/commands/init/render.js.map +1 -0
- package/dist/commands/init/report.d.ts +24 -0
- package/dist/commands/init/report.d.ts.map +1 -0
- package/dist/commands/init/report.js +163 -0
- package/dist/commands/init/report.js.map +1 -0
- package/dist/commands/init/run.d.ts +71 -0
- package/dist/commands/init/run.d.ts.map +1 -0
- package/dist/commands/init/run.js +253 -0
- package/dist/commands/init/run.js.map +1 -0
- package/dist/commands/init/services.d.ts +82 -0
- package/dist/commands/init/services.d.ts.map +1 -0
- package/dist/commands/init/services.js +209 -0
- package/dist/commands/init/services.js.map +1 -0
- package/dist/commands/init/storage.d.ts +8 -0
- package/dist/commands/init/storage.d.ts.map +1 -0
- package/dist/commands/init/storage.js +102 -0
- package/dist/commands/init/storage.js.map +1 -0
- package/dist/commands/init/toml.d.ts +65 -0
- package/dist/commands/init/toml.d.ts.map +1 -0
- package/dist/commands/init/toml.js +159 -0
- package/dist/commands/init/toml.js.map +1 -0
- package/dist/commands/init/topology.d.ts +54 -0
- package/dist/commands/init/topology.d.ts.map +1 -0
- package/dist/commands/init/topology.js +146 -0
- package/dist/commands/init/topology.js.map +1 -0
- package/dist/commands/init/types.d.ts +334 -0
- package/dist/commands/init/types.d.ts.map +1 -0
- package/dist/commands/init/types.js +31 -0
- package/dist/commands/init/types.js.map +1 -0
- package/dist/commands/init/wizard-terminal.d.ts +36 -0
- package/dist/commands/init/wizard-terminal.d.ts.map +1 -0
- package/dist/commands/init/wizard-terminal.js +163 -0
- package/dist/commands/init/wizard-terminal.js.map +1 -0
- package/dist/commands/init/wizard.d.ts +25 -0
- package/dist/commands/init/wizard.d.ts.map +1 -0
- package/dist/commands/init/wizard.js +358 -0
- package/dist/commands/init/wizard.js.map +1 -0
- package/dist/commands/mcp.d.ts +4 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +111 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/product-test-runner.d.ts +4 -0
- package/dist/commands/product-test-runner.d.ts.map +1 -0
- package/dist/commands/product-test-runner.js +85 -0
- package/dist/commands/product-test-runner.js.map +1 -0
- package/dist/commands/product.d.ts +16 -0
- package/dist/commands/product.d.ts.map +1 -0
- package/dist/commands/product.js +262 -0
- package/dist/commands/product.js.map +1 -0
- package/dist/commands/query.d.ts +114 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +783 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/scan.d.ts +10 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +302 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/sdd.d.ts +24 -0
- package/dist/commands/sdd.d.ts.map +1 -0
- package/dist/commands/sdd.js +195 -0
- package/dist/commands/sdd.js.map +1 -0
- package/dist/commands/unavailable.d.ts +40 -0
- package/dist/commands/unavailable.d.ts.map +1 -0
- package/dist/commands/unavailable.js +73 -0
- package/dist/commands/unavailable.js.map +1 -0
- package/dist/commands/watch/analyze.d.ts +69 -0
- package/dist/commands/watch/analyze.d.ts.map +1 -0
- package/dist/commands/watch/analyze.js +402 -0
- package/dist/commands/watch/analyze.js.map +1 -0
- package/dist/commands/watch/cli.d.ts +8 -0
- package/dist/commands/watch/cli.d.ts.map +1 -0
- package/dist/commands/watch/cli.js +97 -0
- package/dist/commands/watch/cli.js.map +1 -0
- package/dist/commands/watch/delta.d.ts +46 -0
- package/dist/commands/watch/delta.d.ts.map +1 -0
- package/dist/commands/watch/delta.js +170 -0
- package/dist/commands/watch/delta.js.map +1 -0
- package/dist/commands/watch/events.d.ts +214 -0
- package/dist/commands/watch/events.d.ts.map +1 -0
- package/dist/commands/watch/events.js +13 -0
- package/dist/commands/watch/events.js.map +1 -0
- package/dist/commands/watch/index.d.ts +19 -0
- package/dist/commands/watch/index.d.ts.map +1 -0
- package/dist/commands/watch/index.js +15 -0
- package/dist/commands/watch/index.js.map +1 -0
- package/dist/commands/watch/options.d.ts +43 -0
- package/dist/commands/watch/options.d.ts.map +1 -0
- package/dist/commands/watch/options.js +193 -0
- package/dist/commands/watch/options.js.map +1 -0
- package/dist/commands/watch/render.d.ts +26 -0
- package/dist/commands/watch/render.d.ts.map +1 -0
- package/dist/commands/watch/render.js +175 -0
- package/dist/commands/watch/render.js.map +1 -0
- package/dist/commands/watch/run.d.ts +14 -0
- package/dist/commands/watch/run.d.ts.map +1 -0
- package/dist/commands/watch/run.js +460 -0
- package/dist/commands/watch/run.js.map +1 -0
- package/dist/commands/watch/runtime.d.ts +67 -0
- package/dist/commands/watch/runtime.d.ts.map +1 -0
- package/dist/commands/watch/runtime.js +149 -0
- package/dist/commands/watch/runtime.js.map +1 -0
- package/dist/commands/watch-command.d.ts +3 -0
- package/dist/commands/watch-command.d.ts.map +1 -0
- package/dist/commands/watch-command.js +273 -0
- package/dist/commands/watch-command.js.map +1 -0
- package/dist/entry-point.d.ts +11 -0
- package/dist/entry-point.d.ts.map +1 -0
- package/dist/entry-point.js +65 -0
- package/dist/entry-point.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +245 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/boundaries-schema.d.ts +262 -0
- package/dist/mcp/boundaries-schema.d.ts.map +1 -0
- package/dist/mcp/boundaries-schema.js +183 -0
- package/dist/mcp/boundaries-schema.js.map +1 -0
- package/dist/mcp/default-runtime.d.ts +16 -0
- package/dist/mcp/default-runtime.d.ts.map +1 -0
- package/dist/mcp/default-runtime.js +718 -0
- package/dist/mcp/default-runtime.js.map +1 -0
- package/dist/mcp/envelope.d.ts +13 -0
- package/dist/mcp/envelope.d.ts.map +1 -0
- package/dist/mcp/envelope.js +29 -0
- package/dist/mcp/envelope.js.map +1 -0
- package/dist/mcp/index.d.ts +8 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/output-schemas.d.ts +5928 -0
- package/dist/mcp/output-schemas.d.ts.map +1 -0
- package/dist/mcp/output-schemas.js +2814 -0
- package/dist/mcp/output-schemas.js.map +1 -0
- package/dist/mcp/path-sandbox.d.ts +35 -0
- package/dist/mcp/path-sandbox.d.ts.map +1 -0
- package/dist/mcp/path-sandbox.js +128 -0
- package/dist/mcp/path-sandbox.js.map +1 -0
- package/dist/mcp/server.d.ts +155 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +257 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/stdio.d.ts +20 -0
- package/dist/mcp/stdio.d.ts.map +1 -0
- package/dist/mcp/stdio.js +71 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/mcp/tools.d.ts +355 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +319 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/types.d.ts +15 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +45 -0
- package/dist/mcp/types.js.map +1 -0
- package/package.json +99 -3
- package/src/cli/args.ts +231 -0
- package/src/cli/command.ts +146 -0
- package/src/cli/deadline.ts +56 -0
- package/src/cli/embedder-deadline.ts +187 -0
- package/src/cli/exit.ts +94 -0
- package/src/cli/graphs.ts +191 -0
- package/src/cli/index-freshness.ts +303 -0
- package/src/cli/index-refresh.ts +125 -0
- package/src/cli/index-state.ts +1217 -0
- package/src/cli/io.ts +56 -0
- package/src/cli/language-support.ts +203 -0
- package/src/cli/renewing-lease.ts +121 -0
- package/src/cli/search-graph-enrichment.ts +639 -0
- package/src/cli/system.ts +94 -0
- package/src/cli/vector-store-policy.ts +213 -0
- package/src/cli/version.ts +2 -0
- package/src/cli/workspace.ts +324 -0
- package/src/commands/complexity.ts +776 -0
- package/src/commands/doctor.languages.ts +187 -0
- package/src/commands/doctor.storage.ts +124 -0
- package/src/commands/doctor.ts +946 -0
- package/src/commands/extensions/add.ts +312 -0
- package/src/commands/extensions/configure.ts +82 -0
- package/src/commands/extensions/container.ts +209 -0
- package/src/commands/extensions/context.ts +109 -0
- package/src/commands/extensions/enable.ts +237 -0
- package/src/commands/extensions/environment.ts +218 -0
- package/src/commands/extensions/feature-scan.ts +232 -0
- package/src/commands/extensions/invoke.ts +368 -0
- package/src/commands/extensions/list.ts +158 -0
- package/src/commands/extensions/logs.ts +104 -0
- package/src/commands/extensions/provision.ts +206 -0
- package/src/commands/extensions/remove.ts +110 -0
- package/src/commands/extensions/render.ts +32 -0
- package/src/commands/extensions/run.ts +386 -0
- package/src/commands/extensions/secret-store.ts +223 -0
- package/src/commands/extensions/setup.ts +140 -0
- package/src/commands/extensions/source.ts +189 -0
- package/src/commands/extensions/state.ts +252 -0
- package/src/commands/extensions/status.ts +320 -0
- package/src/commands/extensions.ts +280 -0
- package/src/commands/flow/index.ts +402 -0
- package/src/commands/flow/limits.ts +14 -0
- package/src/commands/flow/output.ts +16 -0
- package/src/commands/flow/render.ts +318 -0
- package/src/commands/flow/select.ts +101 -0
- package/src/commands/graph/boundaries-input.ts +63 -0
- package/src/commands/graph/boundaries.ts +182 -0
- package/src/commands/graph/bounds.ts +25 -0
- package/src/commands/graph/category-clusters.ts +194 -0
- package/src/commands/graph/feature-3d.ts +141 -0
- package/src/commands/graph/feature-clusters.ts +125 -0
- package/src/commands/graph/feature-html.ts +336 -0
- package/src/commands/graph/feature-map.ts +270 -0
- package/src/commands/graph/feature-model.ts +234 -0
- package/src/commands/graph/feature-untangle-motion.ts +192 -0
- package/src/commands/graph/index.ts +562 -0
- package/src/commands/graph/render.ts +503 -0
- package/src/commands/graph/select.ts +77 -0
- package/src/commands/index/index.ts +595 -0
- package/src/commands/index/render.ts +325 -0
- package/src/commands/index/target.ts +136 -0
- package/src/commands/index-watch.ts +206 -0
- package/src/commands/init/command.ts +238 -0
- package/src/commands/init/config-draft.ts +235 -0
- package/src/commands/init/diff.ts +117 -0
- package/src/commands/init/http-probe.ts +150 -0
- package/src/commands/init/ignore-rules.ts +170 -0
- package/src/commands/init/index.ts +63 -0
- package/src/commands/init/integrations-apply.ts +618 -0
- package/src/commands/init/integrations-plan.ts +634 -0
- package/src/commands/init/integrations.ts +8 -0
- package/src/commands/init/languages.ts +320 -0
- package/src/commands/init/product-context.ts +576 -0
- package/src/commands/init/render.ts +598 -0
- package/src/commands/init/report.ts +204 -0
- package/src/commands/init/run.ts +349 -0
- package/src/commands/init/services.ts +271 -0
- package/src/commands/init/storage.ts +136 -0
- package/src/commands/init/toml.ts +174 -0
- package/src/commands/init/topology.ts +192 -0
- package/src/commands/init/types.ts +366 -0
- package/src/commands/init/wizard-terminal.ts +206 -0
- package/src/commands/init/wizard.ts +450 -0
- package/src/commands/mcp.ts +123 -0
- package/src/commands/product-test-runner.ts +80 -0
- package/src/commands/product.ts +331 -0
- package/src/commands/query.ts +1032 -0
- package/src/commands/scan.ts +360 -0
- package/src/commands/sdd.ts +243 -0
- package/src/commands/unavailable.ts +92 -0
- package/src/commands/watch/README.md +160 -0
- package/src/commands/watch/analyze.ts +600 -0
- package/src/commands/watch/cli.ts +108 -0
- package/src/commands/watch/delta.ts +186 -0
- package/src/commands/watch/events.ts +235 -0
- package/src/commands/watch/index.ts +53 -0
- package/src/commands/watch/options.ts +234 -0
- package/src/commands/watch/render.ts +240 -0
- package/src/commands/watch/run.ts +553 -0
- package/src/commands/watch/runtime.ts +167 -0
- package/src/commands/watch-command.ts +294 -0
- package/src/entry-point.ts +67 -0
- package/src/index.ts +291 -0
- package/src/mcp/boundaries-schema.ts +193 -0
- package/src/mcp/default-runtime.ts +1034 -0
- package/src/mcp/envelope.ts +57 -0
- package/src/mcp/index.ts +28 -0
- package/src/mcp/output-schemas.ts +3071 -0
- package/src/mcp/path-sandbox.ts +156 -0
- package/src/mcp/server.ts +358 -0
- package/src/mcp/stdio.ts +92 -0
- package/src/mcp/tools.ts +563 -0
- package/src/mcp/types.ts +66 -0
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Der lokale Indexzustand: welches Einbettungsprofil welchen Repo/Ref-Index
|
|
3
|
+
* gebaut hat.
|
|
4
|
+
*
|
|
5
|
+
* Seit Welle 9 ist das keine Singleton-Datei mehr. Eine physische
|
|
6
|
+
* Repository-Wurzel kann mehrere konfigurierte Repo-IDs, Refs und
|
|
7
|
+
* Einbettungsprofile tragen. Jeder dieser Zustaende liegt deshalb in einem
|
|
8
|
+
* eigenen, aus seiner kanonischen Identitaet gehashten Datensatz. Ein
|
|
9
|
+
* separater, generationsgebundener Pointer pro Repo/Ref bezeichnet das
|
|
10
|
+
* Profil des letzten gestarteten Laufs fuer `--embedder=auto`.
|
|
11
|
+
*
|
|
12
|
+
* `index-state.json` bleibt als lesbarer Migrations-Fallback erhalten. Sobald
|
|
13
|
+
* die Registry dieselbe logische Identitaet kennt, gewinnt jedoch immer ihr
|
|
14
|
+
* Datensatz; der Singleton wird dann nicht ein zweites Mal ausgegeben.
|
|
15
|
+
*
|
|
16
|
+
* Alle Dateinamen entstehen ausschliesslich aus SHA-256-Hashes. Registry und
|
|
17
|
+
* Datensaetze sind hart begrenzt. Korrupte, uebergrosse oder unbeschraenkte
|
|
18
|
+
* Registry-Inhalte werden nicht teilweise als gesund behandelt.
|
|
19
|
+
*/
|
|
20
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
21
|
+
import { constants as fsConstants } from "node:fs";
|
|
22
|
+
import { lstat, mkdir, open, opendir, rename, rm, writeFile } from "node:fs/promises";
|
|
23
|
+
import path from "node:path";
|
|
24
|
+
export function indexStateAfterRun(input) {
|
|
25
|
+
const { generationId, corpusRevisionFingerprint, ...state } = input;
|
|
26
|
+
if (state.outcome === "failed" && generationId === null)
|
|
27
|
+
return null;
|
|
28
|
+
return {
|
|
29
|
+
...state,
|
|
30
|
+
...(generationId === null ? {} : { generationId }),
|
|
31
|
+
...(state.outcome === "completed" && corpusRevisionFingerprint !== undefined
|
|
32
|
+
? { corpusRevisionFingerprint }
|
|
33
|
+
: {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Alter Singleton-Name unterhalb von `.untangle/`. Nur noch Lesefallback. */
|
|
37
|
+
export const INDEX_STATE_FILE = "index-state.json";
|
|
38
|
+
export const INDEX_STATE_REGISTRY_DIR = "index-states-v1";
|
|
39
|
+
export const INDEX_STATE_RECORDS_DIR = "records";
|
|
40
|
+
export const INDEX_STATE_CURRENT_DIR = "current";
|
|
41
|
+
/** Harte Ressourcenlimits fuer lokal kontrollierbare Registry-Lesevorgaenge. */
|
|
42
|
+
export const MAX_INDEX_STATE_FILE_BYTES = 64 * 1024;
|
|
43
|
+
export const MAX_INDEX_STATE_REGISTRY_ENTRIES = 512;
|
|
44
|
+
const MAX_INDEX_STATE_FIELD_LENGTH = 8 * 1024;
|
|
45
|
+
const HASH_FILE_PATTERN = /^[0-9a-f]{64}\.json$/u;
|
|
46
|
+
const TEMP_FILE_PATTERN = /^[0-9a-f]{64}\.json\.[0-9a-f-]{36}\.tmp$/u;
|
|
47
|
+
const READ_ONLY_NO_FOLLOW = fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW;
|
|
48
|
+
/** `<repoRoot>/.untangle` — dasselbe Verzeichnis, das `untangle index` anlegt. */
|
|
49
|
+
export function stateRootOf(repoRoot) {
|
|
50
|
+
return path.join(repoRoot, ".untangle");
|
|
51
|
+
}
|
|
52
|
+
/** Der alte Singleton-Pfad. Externe Hinweise und Migration duerfen ihn weiter nennen. */
|
|
53
|
+
export function indexStatePath(stateRoot) {
|
|
54
|
+
return path.join(stateRoot, INDEX_STATE_FILE);
|
|
55
|
+
}
|
|
56
|
+
export function indexStateRecordKey(identity) {
|
|
57
|
+
return hashCanonical([
|
|
58
|
+
"untangle-index-state-record-v1",
|
|
59
|
+
identity.workspaceId,
|
|
60
|
+
identity.repoId,
|
|
61
|
+
identity.refId,
|
|
62
|
+
identity.embeddingProfileId,
|
|
63
|
+
...storageIdentitySuffix(identity),
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
export function indexStateCurrentKey(identity) {
|
|
67
|
+
return hashCanonical([
|
|
68
|
+
"untangle-index-state-current-v1",
|
|
69
|
+
identity.workspaceId,
|
|
70
|
+
identity.repoId,
|
|
71
|
+
identity.refId,
|
|
72
|
+
...storageIdentitySuffix(identity),
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
/** Preserve old Qdrant keys; embedded paths get independent publication namespaces. */
|
|
76
|
+
function storageIdentitySuffix(identity) {
|
|
77
|
+
return identity.storageBackend === "lancedb" ? ["lancedb", identity.storeUrl ?? ""] : [];
|
|
78
|
+
}
|
|
79
|
+
/** Lock key shared by every profile publication for one repo/ref/backend pointer. */
|
|
80
|
+
export function indexStateLockKey(identity) {
|
|
81
|
+
return `index-state:${indexStateCurrentKey(identity)}`;
|
|
82
|
+
}
|
|
83
|
+
export function indexStateRecordPath(stateRoot, identity) {
|
|
84
|
+
return path.join(stateRoot, INDEX_STATE_REGISTRY_DIR, INDEX_STATE_RECORDS_DIR, `${indexStateRecordKey(identity)}.json`);
|
|
85
|
+
}
|
|
86
|
+
export function indexStateCurrentPath(stateRoot, identity) {
|
|
87
|
+
return path.join(stateRoot, INDEX_STATE_REGISTRY_DIR, INDEX_STATE_CURRENT_DIR, `${indexStateCurrentKey(identity)}.json`);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Publiziert einen Registry-Datensatz und macht ihn zum aktuellen Profil des
|
|
91
|
+
* Repo/Ref-Paares. Beide Dateien werden einzeln atomar ersetzt. Der Aufrufer
|
|
92
|
+
* serialisiert die kurze Sequenz mit {@link indexStateLockKey}.
|
|
93
|
+
*
|
|
94
|
+
* Misslingt ein Teil, werden der neue Datensatz, der current-Pointer und ein
|
|
95
|
+
* passender Legacy-Fallback invalidiert. Damit kann ein neuer Lauf nie einen
|
|
96
|
+
* alten `completed`-Hinweis gesund aussehen lassen.
|
|
97
|
+
*/
|
|
98
|
+
export async function writeIndexState(stateRoot, state, options = {}) {
|
|
99
|
+
const recordTarget = indexStateRecordPath(stateRoot, state);
|
|
100
|
+
const serializedState = serializeRegistryState(state);
|
|
101
|
+
if (serializedState === null) {
|
|
102
|
+
const error = new Error("Registry index states require a valid generation-bound state.");
|
|
103
|
+
const invalidated = await invalidateAfterFailure(stateRoot, state, "unconditional", options);
|
|
104
|
+
return failedWrite(recordTarget, error, invalidated);
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
await atomicWrite(recordTarget, serializedState, options.assertOwnership);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
const invalidated = await invalidateAfterFailure(stateRoot, state, "unconditional", options);
|
|
111
|
+
return failedWrite(recordTarget, error, invalidated);
|
|
112
|
+
}
|
|
113
|
+
const pointerTarget = indexStateCurrentPath(stateRoot, state);
|
|
114
|
+
const pointer = currentPointerFor(state);
|
|
115
|
+
try {
|
|
116
|
+
await atomicWrite(pointerTarget, `${JSON.stringify(pointer, null, 2)}\n`, options.assertOwnership);
|
|
117
|
+
return { ok: true, path: recordTarget };
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
const invalidated = await invalidateAfterFailure(stateRoot, state, "unconditional", options);
|
|
121
|
+
return failedWrite(pointerTarget, error, invalidated);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Replaces exactly one `running` registry record while its generation still
|
|
126
|
+
* matches. The current pointer is deliberately not republished: if another
|
|
127
|
+
* profile became current while this run finished, a late terminal write may
|
|
128
|
+
* archive its own result but cannot steal `auto` routing back.
|
|
129
|
+
*/
|
|
130
|
+
export async function replaceRunningIndexState(stateRoot, terminalState, options = {}) {
|
|
131
|
+
const target = indexStateRecordPath(stateRoot, terminalState);
|
|
132
|
+
const current = await readExactRegistryRecord(target, terminalState);
|
|
133
|
+
if (current.kind === "absent") {
|
|
134
|
+
return { ok: true, path: target, superseded: true };
|
|
135
|
+
}
|
|
136
|
+
if (current.kind === "invalid") {
|
|
137
|
+
const invalidated = await invalidateAfterFailure(stateRoot, terminalState, "matching", options);
|
|
138
|
+
return {
|
|
139
|
+
...failedWrite(target, new Error(current.message), invalidated),
|
|
140
|
+
superseded: false,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (!isRunningStateFor(current.state, terminalState)) {
|
|
144
|
+
return { ok: true, path: target, superseded: true };
|
|
145
|
+
}
|
|
146
|
+
const serializedState = serializeRegistryState(terminalState);
|
|
147
|
+
if (serializedState === null) {
|
|
148
|
+
const error = new Error("Terminal registry states require the running generation identity.");
|
|
149
|
+
const invalidated = await invalidateAfterFailure(stateRoot, terminalState, "matching", options);
|
|
150
|
+
return { ...failedWrite(target, error, invalidated), superseded: false };
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
await atomicWrite(target, serializedState, options.assertOwnership);
|
|
154
|
+
return { ok: true, path: target, superseded: false };
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
const invalidated = await invalidateAfterFailure(stateRoot, terminalState, "matching", options);
|
|
158
|
+
return { ...failedWrite(target, error, invalidated), superseded: false };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function isRunningStateFor(current, terminal) {
|
|
162
|
+
return (current.outcome === "running" &&
|
|
163
|
+
terminal.outcome !== "running" &&
|
|
164
|
+
current.workspaceId === terminal.workspaceId &&
|
|
165
|
+
current.repoId === terminal.repoId &&
|
|
166
|
+
current.refId === terminal.refId &&
|
|
167
|
+
current.refName === terminal.refName &&
|
|
168
|
+
current.embedder === terminal.embedder &&
|
|
169
|
+
current.embeddingProfileId === terminal.embeddingProfileId &&
|
|
170
|
+
current.collection === terminal.collection &&
|
|
171
|
+
(current.storageBackend ?? "qdrant") === (terminal.storageBackend ?? "qdrant") &&
|
|
172
|
+
(current.storeUrl ?? current.qdrantUrl) === (terminal.storeUrl ?? terminal.qdrantUrl) &&
|
|
173
|
+
current.generationId !== undefined &&
|
|
174
|
+
current.generationId === terminal.generationId);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Compatibility reader for old callers. It returns a state only when exactly
|
|
178
|
+
* one current repo/ref state exists below this physical root; callers needing
|
|
179
|
+
* every context use {@link resolveIndexState}.
|
|
180
|
+
*/
|
|
181
|
+
export async function readIndexState(stateRoot) {
|
|
182
|
+
const registry = await readLocalRegistry(stateRoot);
|
|
183
|
+
if (registry.kind === "invalid")
|
|
184
|
+
return null;
|
|
185
|
+
const current = registry.entries.filter((entry) => entry.current);
|
|
186
|
+
return current.length === 1 ? (current[0]?.state ?? null) : null;
|
|
187
|
+
}
|
|
188
|
+
/** The parser remains public for legacy migration and focused tests. */
|
|
189
|
+
export function parseIndexState(text) {
|
|
190
|
+
if (Buffer.byteLength(text, "utf8") > MAX_INDEX_STATE_FILE_BYTES)
|
|
191
|
+
return null;
|
|
192
|
+
let raw;
|
|
193
|
+
try {
|
|
194
|
+
raw = JSON.parse(text);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
200
|
+
return null;
|
|
201
|
+
const record = raw;
|
|
202
|
+
if (record["schemaVersion"] !== 1)
|
|
203
|
+
return null;
|
|
204
|
+
const embedder = record["embedder"];
|
|
205
|
+
if (embedder !== "service" && embedder !== "offline")
|
|
206
|
+
return null;
|
|
207
|
+
const outcome = record["outcome"];
|
|
208
|
+
if (outcome !== "running" &&
|
|
209
|
+
outcome !== "completed" &&
|
|
210
|
+
outcome !== "cancelled" &&
|
|
211
|
+
outcome !== "failed") {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const strings = [
|
|
215
|
+
"workspaceId",
|
|
216
|
+
"repoId",
|
|
217
|
+
"refId",
|
|
218
|
+
"refName",
|
|
219
|
+
"embeddingProfileId",
|
|
220
|
+
"collection",
|
|
221
|
+
];
|
|
222
|
+
const values = {};
|
|
223
|
+
for (const key of strings) {
|
|
224
|
+
const value = record[key];
|
|
225
|
+
if (!isBoundedString(value))
|
|
226
|
+
return null;
|
|
227
|
+
values[key] = value;
|
|
228
|
+
}
|
|
229
|
+
const storage = parseStorageIdentity(record, true);
|
|
230
|
+
if (storage === null)
|
|
231
|
+
return null;
|
|
232
|
+
const generationId = record["generationId"];
|
|
233
|
+
if (generationId !== undefined && !isBoundedString(generationId))
|
|
234
|
+
return null;
|
|
235
|
+
const corpusRevisionFingerprint = record["corpusRevisionFingerprint"];
|
|
236
|
+
if (corpusRevisionFingerprint !== undefined &&
|
|
237
|
+
(typeof corpusRevisionFingerprint !== "string" ||
|
|
238
|
+
!/^[0-9a-f]{64}$/u.test(corpusRevisionFingerprint))) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
const indexedAt = record["indexedAt"];
|
|
242
|
+
const indexConfigFingerprint = record["indexConfigFingerprint"];
|
|
243
|
+
const lexicalTokenizerVersion = record["lexicalTokenizerVersion"];
|
|
244
|
+
if (indexedAt !== undefined &&
|
|
245
|
+
(typeof indexedAt !== "string" || !Number.isFinite(Date.parse(indexedAt))))
|
|
246
|
+
return null;
|
|
247
|
+
if (indexConfigFingerprint !== undefined &&
|
|
248
|
+
(typeof indexConfigFingerprint !== "string" || !/^[0-9a-f]{64}$/u.test(indexConfigFingerprint)))
|
|
249
|
+
return null;
|
|
250
|
+
if (lexicalTokenizerVersion !== undefined && !isBoundedString(lexicalTokenizerVersion))
|
|
251
|
+
return null;
|
|
252
|
+
return {
|
|
253
|
+
schemaVersion: 1,
|
|
254
|
+
workspaceId: values["workspaceId"],
|
|
255
|
+
repoId: values["repoId"],
|
|
256
|
+
refId: values["refId"],
|
|
257
|
+
refName: values["refName"],
|
|
258
|
+
embedder,
|
|
259
|
+
embeddingProfileId: values["embeddingProfileId"],
|
|
260
|
+
collection: values["collection"],
|
|
261
|
+
...storage,
|
|
262
|
+
...(generationId === undefined ? {} : { generationId }),
|
|
263
|
+
...(corpusRevisionFingerprint === undefined ? {} : { corpusRevisionFingerprint }),
|
|
264
|
+
...(indexedAt === undefined ? {} : { indexedAt }),
|
|
265
|
+
...(indexConfigFingerprint === undefined ? {} : { indexConfigFingerprint }),
|
|
266
|
+
...(lexicalTokenizerVersion === undefined ? {} : { lexicalTokenizerVersion }),
|
|
267
|
+
outcome,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Enumerates every bounded registry under the candidate physical roots.
|
|
272
|
+
* Roots are de-duplicated, records are not: one root can legitimately contain
|
|
273
|
+
* multiple repo IDs, refs and profiles.
|
|
274
|
+
*/
|
|
275
|
+
export async function resolveIndexState(candidateRoots, workspaceId, scope = {}) {
|
|
276
|
+
const collected = await collectScopedIndexStates(candidateRoots, workspaceId, scope);
|
|
277
|
+
collected.found.sort(compareFoundStates);
|
|
278
|
+
if (collected.diagnostics.length > 0) {
|
|
279
|
+
collected.diagnostics.sort((a, b) => compareText(a.path, b.path) || compareText(a.code, b.code));
|
|
280
|
+
return { kind: "invalid", diagnostics: collected.diagnostics, all: collected.found };
|
|
281
|
+
}
|
|
282
|
+
return resolveCollectedStates(collected.found);
|
|
283
|
+
}
|
|
284
|
+
async function collectScopedIndexStates(candidateRoots, workspaceId, scope) {
|
|
285
|
+
const selectedRepoIds = new Set(scope.repoIds ?? []);
|
|
286
|
+
const selectedRefs = new Set(scope.refs ?? []);
|
|
287
|
+
const seenRoots = new Set();
|
|
288
|
+
const found = [];
|
|
289
|
+
const diagnostics = [];
|
|
290
|
+
for (const candidateRoot of candidateRoots) {
|
|
291
|
+
const repoRoot = path.resolve(candidateRoot);
|
|
292
|
+
if (seenRoots.has(repoRoot))
|
|
293
|
+
continue;
|
|
294
|
+
seenRoots.add(repoRoot);
|
|
295
|
+
const registry = await readLocalRegistry(stateRootOf(repoRoot));
|
|
296
|
+
if (registry.kind === "invalid") {
|
|
297
|
+
diagnostics.push(...registry.diagnostics);
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
for (const entry of registry.entries) {
|
|
301
|
+
if (!stateMatchesScope(entry.state, workspaceId, selectedRepoIds, selectedRefs, scope))
|
|
302
|
+
continue;
|
|
303
|
+
found.push({ repoRoot, ...entry });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return { found, diagnostics };
|
|
307
|
+
}
|
|
308
|
+
function stateMatchesScope(state, workspaceId, selectedRepoIds, selectedRefs, scope) {
|
|
309
|
+
return (state.workspaceId === workspaceId &&
|
|
310
|
+
(scope.storageBackend === undefined ||
|
|
311
|
+
(state.storageBackend ?? "qdrant") === scope.storageBackend) &&
|
|
312
|
+
(scope.storeUrl === undefined || (state.storeUrl ?? state.qdrantUrl) === scope.storeUrl) &&
|
|
313
|
+
(selectedRepoIds.size === 0 || selectedRepoIds.has(state.repoId)) &&
|
|
314
|
+
(selectedRefs.size === 0 || selectedRefs.has(state.refId) || selectedRefs.has(state.refName)));
|
|
315
|
+
}
|
|
316
|
+
function resolveCollectedStates(found) {
|
|
317
|
+
if (found.length === 0)
|
|
318
|
+
return { kind: "none" };
|
|
319
|
+
const current = found.filter((entry) => entry.current);
|
|
320
|
+
if (current.length === 0) {
|
|
321
|
+
return {
|
|
322
|
+
kind: "invalid",
|
|
323
|
+
diagnostics: [
|
|
324
|
+
{
|
|
325
|
+
code: "INDEX_STATE_CORRUPT",
|
|
326
|
+
path: found[0]?.statePath ?? "(index-state registry)",
|
|
327
|
+
message: "The selected registry states have no valid current pointer.",
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
all: found,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
const first = current[0];
|
|
334
|
+
if (current.some((entry) => entry.state.embedder !== first.state.embedder)) {
|
|
335
|
+
return { kind: "ambiguous", found: current, all: found };
|
|
336
|
+
}
|
|
337
|
+
return { kind: "resolved", embedder: first.state.embedder, found: first, current, all: found };
|
|
338
|
+
}
|
|
339
|
+
async function readLocalRegistry(stateRoot) {
|
|
340
|
+
const recordsDirectory = path.join(stateRoot, INDEX_STATE_REGISTRY_DIR, INDEX_STATE_RECORDS_DIR);
|
|
341
|
+
const currentDirectory = path.join(stateRoot, INDEX_STATE_REGISTRY_DIR, INDEX_STATE_CURRENT_DIR);
|
|
342
|
+
const recordsListing = await listRegistryFiles(recordsDirectory);
|
|
343
|
+
if (recordsListing.kind === "invalid")
|
|
344
|
+
return recordsListing;
|
|
345
|
+
const currentListing = await listRegistryFiles(currentDirectory);
|
|
346
|
+
if (currentListing.kind === "invalid")
|
|
347
|
+
return currentListing;
|
|
348
|
+
const recordRead = await readRegistryRecords(recordsListing.paths);
|
|
349
|
+
if (recordRead.kind === "invalid")
|
|
350
|
+
return recordRead;
|
|
351
|
+
const currentRead = await readCurrentPointers(currentListing.paths, recordRead.value);
|
|
352
|
+
if (currentRead.kind === "invalid")
|
|
353
|
+
return currentRead;
|
|
354
|
+
const missingPointer = firstRecordWithoutCurrent(recordRead.value, currentRead.value);
|
|
355
|
+
if (missingPointer !== null)
|
|
356
|
+
return missingPointer;
|
|
357
|
+
const entries = registryEntries(recordRead.value, currentRead.value);
|
|
358
|
+
const legacyMerge = await mergeLegacyState(stateRoot, recordRead.value, currentRead.value, entries);
|
|
359
|
+
if (legacyMerge !== null)
|
|
360
|
+
return legacyMerge;
|
|
361
|
+
entries.sort((a, b) => compareStateEntries(a, b));
|
|
362
|
+
return { kind: "valid", entries };
|
|
363
|
+
}
|
|
364
|
+
async function readRegistryRecords(paths) {
|
|
365
|
+
const records = new Map();
|
|
366
|
+
for (const recordPath of paths) {
|
|
367
|
+
const read = await readBoundedRegularFile(recordPath);
|
|
368
|
+
if (read.kind === "absent") {
|
|
369
|
+
return invalidRegistry(recordPath, "Registry record disappeared while being read.");
|
|
370
|
+
}
|
|
371
|
+
if (read.kind === "invalid")
|
|
372
|
+
return invalidFileRead(recordPath, read);
|
|
373
|
+
const state = parseIndexState(read.text);
|
|
374
|
+
if (state === null || state.generationId === undefined) {
|
|
375
|
+
return invalidRegistry(recordPath, "Registry record is invalid or has no generation.");
|
|
376
|
+
}
|
|
377
|
+
const key = indexStateRecordKey(state);
|
|
378
|
+
if (path.basename(recordPath) !== `${key}.json`) {
|
|
379
|
+
return invalidRegistry(recordPath, "Registry filename does not match the canonical identity.");
|
|
380
|
+
}
|
|
381
|
+
records.set(key, { state, statePath: recordPath });
|
|
382
|
+
}
|
|
383
|
+
return { kind: "valid", value: records };
|
|
384
|
+
}
|
|
385
|
+
async function readCurrentPointers(paths, records) {
|
|
386
|
+
const currentByGroup = new Map();
|
|
387
|
+
for (const pointerPath of paths) {
|
|
388
|
+
const read = await readBoundedRegularFile(pointerPath);
|
|
389
|
+
if (read.kind === "absent") {
|
|
390
|
+
return invalidRegistry(pointerPath, "Current pointer disappeared while being read.");
|
|
391
|
+
}
|
|
392
|
+
if (read.kind === "invalid")
|
|
393
|
+
return invalidFileRead(pointerPath, read);
|
|
394
|
+
const parsed = validateCurrentPointer(pointerPath, read.text, records, currentByGroup);
|
|
395
|
+
if (parsed.kind === "invalid")
|
|
396
|
+
return parsed;
|
|
397
|
+
currentByGroup.set(parsed.value.currentKey, parsed.value.recordKey);
|
|
398
|
+
}
|
|
399
|
+
return { kind: "valid", value: currentByGroup };
|
|
400
|
+
}
|
|
401
|
+
function validateCurrentPointer(pointerPath, text, records, currentByGroup) {
|
|
402
|
+
const pointer = parseCurrentPointer(text);
|
|
403
|
+
if (pointer === null)
|
|
404
|
+
return invalidRegistry(pointerPath, "Current pointer is invalid.");
|
|
405
|
+
const currentKey = indexStateCurrentKey(pointer);
|
|
406
|
+
if (path.basename(pointerPath) !== `${currentKey}.json`) {
|
|
407
|
+
return invalidRegistry(pointerPath, "Pointer filename does not match the repository/ref identity.");
|
|
408
|
+
}
|
|
409
|
+
const pointed = records.get(pointer.recordKey);
|
|
410
|
+
if (pointed === undefined || !pointerMatchesState(pointer, pointed.state)) {
|
|
411
|
+
return invalidRegistry(pointerPath, "Current pointer does not reference the same profile- and generation-bound record.");
|
|
412
|
+
}
|
|
413
|
+
if (currentByGroup.has(currentKey)) {
|
|
414
|
+
return invalidRegistry(pointerPath, "Repository/ref has more than one current pointer.");
|
|
415
|
+
}
|
|
416
|
+
return { kind: "valid", value: { currentKey, recordKey: pointer.recordKey } };
|
|
417
|
+
}
|
|
418
|
+
function firstRecordWithoutCurrent(records, currentByGroup) {
|
|
419
|
+
for (const { state, statePath } of records.values()) {
|
|
420
|
+
if (!currentByGroup.has(indexStateCurrentKey(state))) {
|
|
421
|
+
return invalidRegistry(statePath, "Registry record belongs to a repository/ref without a current pointer.");
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
function registryEntries(records, currentByGroup) {
|
|
427
|
+
return [...records.entries()].map(([recordKey, { state, statePath }]) => ({
|
|
428
|
+
state,
|
|
429
|
+
statePath,
|
|
430
|
+
source: "registry",
|
|
431
|
+
current: currentByGroup.get(indexStateCurrentKey(state)) === recordKey,
|
|
432
|
+
}));
|
|
433
|
+
}
|
|
434
|
+
async function mergeLegacyState(stateRoot, records, currentByGroup, entries) {
|
|
435
|
+
const legacyPath = indexStatePath(stateRoot);
|
|
436
|
+
const legacyRead = await readBoundedRegularFile(legacyPath);
|
|
437
|
+
if (legacyRead.kind === "absent")
|
|
438
|
+
return null;
|
|
439
|
+
if (legacyRead.kind === "invalid")
|
|
440
|
+
return invalidFileRead(legacyPath, legacyRead);
|
|
441
|
+
const legacyState = parseIndexState(legacyRead.text);
|
|
442
|
+
if (legacyState === null) {
|
|
443
|
+
return invalidRegistry(legacyPath, "Legacy index state is invalid.");
|
|
444
|
+
}
|
|
445
|
+
if (records.has(indexStateRecordKey(legacyState)))
|
|
446
|
+
return null;
|
|
447
|
+
entries.push({
|
|
448
|
+
state: legacyState,
|
|
449
|
+
statePath: legacyPath,
|
|
450
|
+
source: "legacy",
|
|
451
|
+
current: !currentByGroup.has(indexStateCurrentKey(legacyState)),
|
|
452
|
+
});
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
async function listRegistryFiles(directory) {
|
|
456
|
+
try {
|
|
457
|
+
const information = await lstat(directory);
|
|
458
|
+
if (!information.isDirectory()) {
|
|
459
|
+
return {
|
|
460
|
+
kind: "invalid",
|
|
461
|
+
diagnostics: [
|
|
462
|
+
diagnostic("INDEX_STATE_CORRUPT", directory, "Registry directory is not a regular local directory."),
|
|
463
|
+
],
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
if (isNotFound(error))
|
|
469
|
+
return { kind: "valid", paths: [] };
|
|
470
|
+
return {
|
|
471
|
+
kind: "invalid",
|
|
472
|
+
diagnostics: [
|
|
473
|
+
diagnostic("INDEX_STATE_IO", directory, `Cannot inspect registry: ${errorText(error)}`),
|
|
474
|
+
],
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
let handle;
|
|
478
|
+
try {
|
|
479
|
+
handle = await opendir(directory);
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
if (isNotFound(error))
|
|
483
|
+
return { kind: "valid", paths: [] };
|
|
484
|
+
return {
|
|
485
|
+
kind: "invalid",
|
|
486
|
+
diagnostics: [
|
|
487
|
+
diagnostic("INDEX_STATE_IO", directory, `Cannot read registry: ${errorText(error)}`),
|
|
488
|
+
],
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
const names = [];
|
|
492
|
+
try {
|
|
493
|
+
for await (const entry of handle) {
|
|
494
|
+
names.push(entry.name);
|
|
495
|
+
if (names.length > MAX_INDEX_STATE_REGISTRY_ENTRIES) {
|
|
496
|
+
return {
|
|
497
|
+
kind: "invalid",
|
|
498
|
+
diagnostics: [
|
|
499
|
+
diagnostic("INDEX_STATE_UNBOUNDED", directory, `Registry contains more than ${String(MAX_INDEX_STATE_REGISTRY_ENTRIES)} Eintraege.`),
|
|
500
|
+
],
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
if (TEMP_FILE_PATTERN.test(entry.name) && entry.isFile())
|
|
504
|
+
continue;
|
|
505
|
+
if (!HASH_FILE_PATTERN.test(entry.name) || !entry.isFile()) {
|
|
506
|
+
return {
|
|
507
|
+
kind: "invalid",
|
|
508
|
+
diagnostics: [
|
|
509
|
+
diagnostic("INDEX_STATE_CORRUPT", path.join(directory, entry.name), "Registry accepts only regular JSON records with canonical filenames."),
|
|
510
|
+
],
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
catch (error) {
|
|
516
|
+
return {
|
|
517
|
+
kind: "invalid",
|
|
518
|
+
diagnostics: [
|
|
519
|
+
diagnostic("INDEX_STATE_IO", directory, `Registry read failed: ${errorText(error)}`),
|
|
520
|
+
],
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
finally {
|
|
524
|
+
await handle.close().catch(() => undefined);
|
|
525
|
+
}
|
|
526
|
+
return {
|
|
527
|
+
kind: "valid",
|
|
528
|
+
paths: names
|
|
529
|
+
.filter((name) => HASH_FILE_PATTERN.test(name))
|
|
530
|
+
.sort(compareText)
|
|
531
|
+
.map((name) => path.join(directory, name)),
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
async function readBoundedRegularFile(filePath) {
|
|
535
|
+
try {
|
|
536
|
+
const information = await lstat(filePath);
|
|
537
|
+
if (!information.isFile()) {
|
|
538
|
+
return { kind: "invalid", reason: "not_regular", message: "Path is not a regular file." };
|
|
539
|
+
}
|
|
540
|
+
if (information.size > MAX_INDEX_STATE_FILE_BYTES) {
|
|
541
|
+
return {
|
|
542
|
+
kind: "invalid",
|
|
543
|
+
reason: "oversized",
|
|
544
|
+
message: `File exceeds ${String(MAX_INDEX_STATE_FILE_BYTES)} Bytes.`,
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
catch (error) {
|
|
549
|
+
if (isNotFound(error))
|
|
550
|
+
return { kind: "absent" };
|
|
551
|
+
return { kind: "invalid", reason: "io", message: errorText(error) };
|
|
552
|
+
}
|
|
553
|
+
let handle;
|
|
554
|
+
try {
|
|
555
|
+
// `lstat` rejects an existing symlink; O_NOFOLLOW also closes the race in
|
|
556
|
+
// which that path is swapped between the check and open.
|
|
557
|
+
handle = await open(filePath, READ_ONLY_NO_FOLLOW);
|
|
558
|
+
const buffer = Buffer.alloc(MAX_INDEX_STATE_FILE_BYTES + 1);
|
|
559
|
+
let totalBytesRead = 0;
|
|
560
|
+
while (totalBytesRead < buffer.length) {
|
|
561
|
+
const { bytesRead } = await handle.read(buffer, totalBytesRead, buffer.length - totalBytesRead, totalBytesRead);
|
|
562
|
+
if (bytesRead === 0)
|
|
563
|
+
break;
|
|
564
|
+
totalBytesRead += bytesRead;
|
|
565
|
+
}
|
|
566
|
+
if (totalBytesRead > MAX_INDEX_STATE_FILE_BYTES) {
|
|
567
|
+
return {
|
|
568
|
+
kind: "invalid",
|
|
569
|
+
reason: "oversized",
|
|
570
|
+
message: `File exceeds ${String(MAX_INDEX_STATE_FILE_BYTES)} Bytes.`,
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
return { kind: "valid", text: buffer.subarray(0, totalBytesRead).toString("utf8") };
|
|
574
|
+
}
|
|
575
|
+
catch (error) {
|
|
576
|
+
if (isNotFound(error))
|
|
577
|
+
return { kind: "absent" };
|
|
578
|
+
return { kind: "invalid", reason: "io", message: errorText(error) };
|
|
579
|
+
}
|
|
580
|
+
finally {
|
|
581
|
+
await handle?.close().catch(() => undefined);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
/** Embedded state identities must be canonical absolute local file URLs. */
|
|
585
|
+
function isLocalStoreUrl(value) {
|
|
586
|
+
try {
|
|
587
|
+
const url = new URL(value);
|
|
588
|
+
return (url.protocol === "file:" &&
|
|
589
|
+
url.hostname === "" &&
|
|
590
|
+
url.search === "" &&
|
|
591
|
+
url.hash === "" &&
|
|
592
|
+
url.href === value &&
|
|
593
|
+
!url.pathname.includes("%00"));
|
|
594
|
+
}
|
|
595
|
+
catch {
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
function parseStorageIdentity(record, requireEndpoint) {
|
|
600
|
+
const backend = record["storageBackend"];
|
|
601
|
+
const storeUrl = record["storeUrl"];
|
|
602
|
+
const qdrantUrl = record["qdrantUrl"];
|
|
603
|
+
if (backend !== undefined && backend !== "qdrant" && backend !== "lancedb")
|
|
604
|
+
return null;
|
|
605
|
+
if (backend === "lancedb") {
|
|
606
|
+
if (!isBoundedString(storeUrl) || !isLocalStoreUrl(storeUrl))
|
|
607
|
+
return null;
|
|
608
|
+
if (qdrantUrl !== undefined)
|
|
609
|
+
return null;
|
|
610
|
+
return { storageBackend: "lancedb", storeUrl };
|
|
611
|
+
}
|
|
612
|
+
if (storeUrl !== undefined && (!isBoundedString(storeUrl) || storeUrl !== qdrantUrl))
|
|
613
|
+
return null;
|
|
614
|
+
if (requireEndpoint && !isBoundedString(qdrantUrl))
|
|
615
|
+
return null;
|
|
616
|
+
if (qdrantUrl !== undefined && !isBoundedString(qdrantUrl))
|
|
617
|
+
return null;
|
|
618
|
+
return {
|
|
619
|
+
...(backend === undefined ? {} : { storageBackend: backend }),
|
|
620
|
+
...(storeUrl === undefined ? {} : { storeUrl }),
|
|
621
|
+
...(qdrantUrl === undefined ? {} : { qdrantUrl }),
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
function parseCurrentPointer(text) {
|
|
625
|
+
if (Buffer.byteLength(text, "utf8") > MAX_INDEX_STATE_FILE_BYTES)
|
|
626
|
+
return null;
|
|
627
|
+
let raw;
|
|
628
|
+
try {
|
|
629
|
+
raw = JSON.parse(text);
|
|
630
|
+
}
|
|
631
|
+
catch {
|
|
632
|
+
return null;
|
|
633
|
+
}
|
|
634
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
635
|
+
return null;
|
|
636
|
+
const record = raw;
|
|
637
|
+
if (record["schemaVersion"] !== 1)
|
|
638
|
+
return null;
|
|
639
|
+
const storage = parseStorageIdentity(record, false);
|
|
640
|
+
if (storage === null)
|
|
641
|
+
return null;
|
|
642
|
+
const workspaceId = record["workspaceId"];
|
|
643
|
+
const repoId = record["repoId"];
|
|
644
|
+
const refId = record["refId"];
|
|
645
|
+
const embeddingProfileId = record["embeddingProfileId"];
|
|
646
|
+
const generationId = record["generationId"];
|
|
647
|
+
const recordKey = record["recordKey"];
|
|
648
|
+
if (!isBoundedString(workspaceId) ||
|
|
649
|
+
!isBoundedString(repoId) ||
|
|
650
|
+
!isBoundedString(refId) ||
|
|
651
|
+
!isBoundedString(embeddingProfileId) ||
|
|
652
|
+
!isBoundedString(generationId) ||
|
|
653
|
+
typeof recordKey !== "string" ||
|
|
654
|
+
!/^[0-9a-f]{64}$/u.test(recordKey)) {
|
|
655
|
+
return null;
|
|
656
|
+
}
|
|
657
|
+
return {
|
|
658
|
+
schemaVersion: 1,
|
|
659
|
+
...storage,
|
|
660
|
+
workspaceId,
|
|
661
|
+
repoId,
|
|
662
|
+
refId,
|
|
663
|
+
embeddingProfileId,
|
|
664
|
+
generationId,
|
|
665
|
+
recordKey,
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
function currentPointerFor(state) {
|
|
669
|
+
if (state.generationId === undefined) {
|
|
670
|
+
throw new Error("A current pointer requires a generation id.");
|
|
671
|
+
}
|
|
672
|
+
return {
|
|
673
|
+
schemaVersion: 1,
|
|
674
|
+
workspaceId: state.workspaceId,
|
|
675
|
+
repoId: state.repoId,
|
|
676
|
+
refId: state.refId,
|
|
677
|
+
embeddingProfileId: state.embeddingProfileId,
|
|
678
|
+
generationId: state.generationId,
|
|
679
|
+
recordKey: indexStateRecordKey(state),
|
|
680
|
+
...(state.storageBackend === "lancedb"
|
|
681
|
+
? { storageBackend: "lancedb", storeUrl: state.storeUrl }
|
|
682
|
+
: {}),
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
function pointerMatchesState(pointer, state) {
|
|
686
|
+
return (pointer.workspaceId === state.workspaceId &&
|
|
687
|
+
pointer.repoId === state.repoId &&
|
|
688
|
+
pointer.refId === state.refId &&
|
|
689
|
+
pointer.embeddingProfileId === state.embeddingProfileId &&
|
|
690
|
+
pointer.generationId === state.generationId &&
|
|
691
|
+
pointer.recordKey === indexStateRecordKey(state) &&
|
|
692
|
+
indexStateCurrentKey(pointer) === indexStateCurrentKey(state));
|
|
693
|
+
}
|
|
694
|
+
async function readExactRegistryRecord(target, identity) {
|
|
695
|
+
const read = await readBoundedRegularFile(target);
|
|
696
|
+
if (read.kind === "absent")
|
|
697
|
+
return read;
|
|
698
|
+
if (read.kind === "invalid")
|
|
699
|
+
return { kind: "invalid", message: read.message };
|
|
700
|
+
const state = parseIndexState(read.text);
|
|
701
|
+
if (state === null ||
|
|
702
|
+
state.generationId === undefined ||
|
|
703
|
+
indexStateRecordKey(state) !== indexStateRecordKey(identity)) {
|
|
704
|
+
return { kind: "invalid", message: "Registry record does not match its key." };
|
|
705
|
+
}
|
|
706
|
+
return { kind: "valid", state };
|
|
707
|
+
}
|
|
708
|
+
async function atomicWrite(target, text, assertOwnership) {
|
|
709
|
+
await mkdir(path.dirname(target), { recursive: true, mode: 0o700 });
|
|
710
|
+
const temporary = `${target}.${randomUUID()}.tmp`;
|
|
711
|
+
try {
|
|
712
|
+
await writeFile(temporary, text, { encoding: "utf8", flag: "wx", mode: 0o600 });
|
|
713
|
+
await assertOwnership?.();
|
|
714
|
+
await rename(temporary, target);
|
|
715
|
+
}
|
|
716
|
+
catch (error) {
|
|
717
|
+
await rm(temporary, { force: true }).catch(() => undefined);
|
|
718
|
+
throw error;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
function serializeRegistryState(state) {
|
|
722
|
+
if (state.generationId === undefined)
|
|
723
|
+
return null;
|
|
724
|
+
const text = `${JSON.stringify(state, null, 2)}\n`;
|
|
725
|
+
const parsed = parseIndexState(text);
|
|
726
|
+
if (parsed === null || parsed.generationId === undefined)
|
|
727
|
+
return null;
|
|
728
|
+
return text;
|
|
729
|
+
}
|
|
730
|
+
async function invalidateAfterFailure(stateRoot, state, pointerInvalidation, options) {
|
|
731
|
+
if (options.assertOwnership !== undefined) {
|
|
732
|
+
try {
|
|
733
|
+
// Never let a writer that already lost its lease remove a successor's
|
|
734
|
+
// record or pointer. The surviving running marker remains fail-closed.
|
|
735
|
+
await options.assertOwnership();
|
|
736
|
+
}
|
|
737
|
+
catch (error) {
|
|
738
|
+
return { ok: false, error };
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return invalidatePublication(stateRoot, state, pointerInvalidation);
|
|
742
|
+
}
|
|
743
|
+
async function invalidatePublication(stateRoot, state, pointerInvalidation) {
|
|
744
|
+
const errors = [];
|
|
745
|
+
await removeAndCollect(indexStateRecordPath(stateRoot, state), errors);
|
|
746
|
+
await invalidateCurrentPointer(stateRoot, state, pointerInvalidation, errors);
|
|
747
|
+
await invalidateLegacyFallback(stateRoot, state, pointerInvalidation, errors);
|
|
748
|
+
return errors.length === 0 ? { ok: true } : { ok: false, error: errors[0] };
|
|
749
|
+
}
|
|
750
|
+
async function invalidateCurrentPointer(stateRoot, state, pointerInvalidation, errors) {
|
|
751
|
+
const pointerPath = indexStateCurrentPath(stateRoot, state);
|
|
752
|
+
if (pointerInvalidation === "unconditional") {
|
|
753
|
+
await removeAndCollect(pointerPath, errors);
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
const pointerRead = await readBoundedRegularFile(pointerPath);
|
|
757
|
+
if (pointerRead.kind === "invalid") {
|
|
758
|
+
await removeAndCollect(pointerPath, errors);
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
if (pointerRead.kind !== "valid")
|
|
762
|
+
return;
|
|
763
|
+
const pointer = parseCurrentPointer(pointerRead.text);
|
|
764
|
+
if (pointer === null || pointerIdentifiesState(pointer, state)) {
|
|
765
|
+
await removeAndCollect(pointerPath, errors);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
function pointerIdentifiesState(pointer, state) {
|
|
769
|
+
return (pointer.recordKey === indexStateRecordKey(state) && pointer.generationId === state.generationId);
|
|
770
|
+
}
|
|
771
|
+
async function invalidateLegacyFallback(stateRoot, state, pointerInvalidation, errors) {
|
|
772
|
+
const legacyPath = indexStatePath(stateRoot);
|
|
773
|
+
const legacyRead = await readBoundedRegularFile(legacyPath);
|
|
774
|
+
if (legacyRead.kind !== "valid")
|
|
775
|
+
return;
|
|
776
|
+
const legacy = parseIndexState(legacyRead.text);
|
|
777
|
+
if (legacy !== null && legacyMustBeInvalidated(legacy, state, pointerInvalidation)) {
|
|
778
|
+
await removeAndCollect(legacyPath, errors);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
function legacyMustBeInvalidated(legacy, state, pointerInvalidation) {
|
|
782
|
+
const sameGroup = indexStateCurrentKey(legacy) === indexStateCurrentKey(state);
|
|
783
|
+
return (sameGroup &&
|
|
784
|
+
(pointerInvalidation === "unconditional" ||
|
|
785
|
+
legacy.embeddingProfileId === state.embeddingProfileId));
|
|
786
|
+
}
|
|
787
|
+
async function removeAndCollect(target, errors) {
|
|
788
|
+
try {
|
|
789
|
+
await rm(target, { force: true });
|
|
790
|
+
}
|
|
791
|
+
catch (error) {
|
|
792
|
+
errors.push(error);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
function failedWrite(target, error, invalidated) {
|
|
796
|
+
return {
|
|
797
|
+
ok: false,
|
|
798
|
+
error,
|
|
799
|
+
path: target,
|
|
800
|
+
previousStateInvalidated: invalidated.ok,
|
|
801
|
+
...(invalidated.error === undefined ? {} : { invalidationError: invalidated.error }),
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
function invalidFileRead(filePath, read) {
|
|
805
|
+
return {
|
|
806
|
+
kind: "invalid",
|
|
807
|
+
diagnostics: [
|
|
808
|
+
diagnostic(read.reason === "oversized"
|
|
809
|
+
? "INDEX_STATE_OVERSIZED"
|
|
810
|
+
: read.reason === "io"
|
|
811
|
+
? "INDEX_STATE_IO"
|
|
812
|
+
: "INDEX_STATE_CORRUPT", filePath, read.message),
|
|
813
|
+
],
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
function invalidRegistry(filePath, message) {
|
|
817
|
+
return {
|
|
818
|
+
kind: "invalid",
|
|
819
|
+
diagnostics: [diagnostic("INDEX_STATE_CORRUPT", filePath, message)],
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
function diagnostic(code, filePath, message) {
|
|
823
|
+
return { code, path: filePath, message };
|
|
824
|
+
}
|
|
825
|
+
function isBoundedString(value) {
|
|
826
|
+
return (typeof value === "string" && value.length > 0 && value.length <= MAX_INDEX_STATE_FIELD_LENGTH);
|
|
827
|
+
}
|
|
828
|
+
function hashCanonical(parts) {
|
|
829
|
+
return createHash("sha256").update(JSON.stringify(parts), "utf8").digest("hex");
|
|
830
|
+
}
|
|
831
|
+
function compareFoundStates(left, right) {
|
|
832
|
+
return compareText(left.repoRoot, right.repoRoot) || compareStateEntries(left, right);
|
|
833
|
+
}
|
|
834
|
+
function compareStateEntries(left, right) {
|
|
835
|
+
return (compareText(left.state.repoId, right.state.repoId) ||
|
|
836
|
+
compareText(left.state.refId, right.state.refId) ||
|
|
837
|
+
compareText(left.state.embeddingProfileId, right.state.embeddingProfileId) ||
|
|
838
|
+
compareText(left.statePath, right.statePath));
|
|
839
|
+
}
|
|
840
|
+
function compareText(left, right) {
|
|
841
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
842
|
+
}
|
|
843
|
+
function isNotFound(error) {
|
|
844
|
+
return (typeof error === "object" &&
|
|
845
|
+
error !== null &&
|
|
846
|
+
"code" in error &&
|
|
847
|
+
error.code === "ENOENT");
|
|
848
|
+
}
|
|
849
|
+
function errorText(error) {
|
|
850
|
+
return error instanceof Error ? error.message : String(error);
|
|
851
|
+
}
|
|
852
|
+
//# sourceMappingURL=index-state.js.map
|