@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,783 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `untangle query` — der Befehl, um den es geht.
|
|
3
|
+
*
|
|
4
|
+
* Er verdrahtet @untangle-code/search und macht dabei ZWEI Dinge unter EINER
|
|
5
|
+
* Oberflaeche sichtbar (Nutzerwunsch A4):
|
|
6
|
+
*
|
|
7
|
+
* - die SEMANTISCHE Suche (hybrid aus dichtem Vektor, BM25 und exaktem
|
|
8
|
+
* Symbolnamen, fusioniert per RRF), und
|
|
9
|
+
* - die GREP-artige Suche (Literal oder regulaerer Ausdruck) mit
|
|
10
|
+
* Kontextzeilen, Pfad-Ein-/Ausschluss und Trefferbegrenzung.
|
|
11
|
+
*
|
|
12
|
+
* `--explain` ist kein Debug-Anhang, sondern der Kern von vision.md §1d: die
|
|
13
|
+
* Score-Zerlegung beantwortet „warum steht das oben?" — und damit auch die
|
|
14
|
+
* Gegenfrage „warum steht der richtige Treffer NICHT oben?".
|
|
15
|
+
*
|
|
16
|
+
* WICHTIG UND EHRLICH: Gesucht wird im INDEX, nicht auf der Platte. Solange
|
|
17
|
+
* `untangle index` fehlt (siehe dort), ist der Index leer. Dieser Befehl
|
|
18
|
+
* behauptet dann nicht „nichts gefunden", sondern nennt den fehlenden Index
|
|
19
|
+
* als Grund und endet mit Exit-Code 4.
|
|
20
|
+
*/
|
|
21
|
+
import path from "node:path";
|
|
22
|
+
import { OfflineEmbeddingProvider } from "@untangle-code/core";
|
|
23
|
+
import { compareCodepoints, isUntangleError, embeddingProfileShortId, INDEX_CONTEXT_INCOMPLETE_WARNING_CODE, uniqueSortedByCodepoints, } from "@untangle-code/domain";
|
|
24
|
+
import { COMPLEXITY_BIASES, GREP_SORTS, NO_SUFFICIENT_MATCH_WARNING_CODE, OUTPUT_FORMATS, SEARCH_ABSTENTIONS, SEARCH_MODES, SEARCH_SORTS, formatGrepResultSet, formatHitAsText, formatSearchGraphRelationsAsText, formatSearchResultSet, } from "@untangle-code/search";
|
|
25
|
+
import { codeCollectionName } from "@untangle-code/storage-qdrant";
|
|
26
|
+
import { boolFlag, enumFlag, integerFlag, listFlag, numberFlag, stringFlag, } from "../cli/args.js";
|
|
27
|
+
import { withDeadline } from "../cli/deadline.js";
|
|
28
|
+
import { EXIT, EnvironmentError, OperationalError, UsageError } from "../cli/exit.js";
|
|
29
|
+
import { inspectIndexFreshness } from "../cli/index-freshness.js";
|
|
30
|
+
import { refreshWorkspaceIndex } from "../cli/index-refresh.js";
|
|
31
|
+
import { resolveIndexState, } from "../cli/index-state.js";
|
|
32
|
+
import { line, note } from "../cli/io.js";
|
|
33
|
+
import { createSearchGraphEnrichment } from "../cli/search-graph-enrichment.js";
|
|
34
|
+
import { systemClock } from "../cli/system.js";
|
|
35
|
+
import { errorMessage, loadWorkspace, wireEmbedder, wireSearchEngine, wireStorage, matchesStoredBackend, storageIndexScope, } from "../cli/workspace.js";
|
|
36
|
+
/**
|
|
37
|
+
* Frist der ganzen Anfrage.
|
|
38
|
+
*
|
|
39
|
+
* Includes retrieval and optional graph enrichment. Semantic/hybrid search
|
|
40
|
+
* also computes a query embedding, which can require loading a service model.
|
|
41
|
+
* The finite deadline keeps an unresponsive terminal from hanging indefinitely.
|
|
42
|
+
*/
|
|
43
|
+
export const DEFAULT_QUERY_TIMEOUT_MS = 60_000;
|
|
44
|
+
const FLAGS = {
|
|
45
|
+
embedder: {
|
|
46
|
+
kind: "string",
|
|
47
|
+
placeholder: "auto|service|offline",
|
|
48
|
+
describe: "auto selects the last index run's profile; service forces the configured service, offline selects the locally built collection.",
|
|
49
|
+
defaultLabel: "auto",
|
|
50
|
+
},
|
|
51
|
+
root: {
|
|
52
|
+
kind: "string",
|
|
53
|
+
placeholder: "PATH",
|
|
54
|
+
describe: "Project directory; configuration is discovered from here.",
|
|
55
|
+
defaultLabel: "current directory",
|
|
56
|
+
},
|
|
57
|
+
format: {
|
|
58
|
+
kind: "string",
|
|
59
|
+
placeholder: OUTPUT_FORMATS.join("|"),
|
|
60
|
+
describe: "Output format. jsonl is streamable; json contains the complete result.",
|
|
61
|
+
defaultLabel: "text",
|
|
62
|
+
},
|
|
63
|
+
limit: { kind: "number", alias: "n", placeholder: "N", describe: "Number of results." },
|
|
64
|
+
explain: {
|
|
65
|
+
kind: "boolean",
|
|
66
|
+
describe: "Show each result's score breakdown (vision.md §1d).",
|
|
67
|
+
},
|
|
68
|
+
mode: {
|
|
69
|
+
kind: "string",
|
|
70
|
+
placeholder: SEARCH_MODES.join("|"),
|
|
71
|
+
describe: "Independent retrieval and ranking paths: lexical/symbol require no embedding.",
|
|
72
|
+
defaultLabel: "hybrid",
|
|
73
|
+
},
|
|
74
|
+
abstention: {
|
|
75
|
+
kind: "string",
|
|
76
|
+
placeholder: SEARCH_ABSTENTIONS.join("|"),
|
|
77
|
+
describe: "Behavior with insufficient evidence: strict returns no hits; evidence returns hits with the verdict.",
|
|
78
|
+
defaultLabel: "strict",
|
|
79
|
+
},
|
|
80
|
+
sort: {
|
|
81
|
+
kind: "string",
|
|
82
|
+
placeholder: SEARCH_SORTS.join("|"),
|
|
83
|
+
describe: "Result sort key.",
|
|
84
|
+
defaultLabel: "relevance",
|
|
85
|
+
},
|
|
86
|
+
content: { kind: "boolean", describe: "Include chunk content (token-intensive)." },
|
|
87
|
+
linked: {
|
|
88
|
+
kind: "boolean",
|
|
89
|
+
describe: "Direct, unambiguously resolved relationships from the persisted symbol graph.",
|
|
90
|
+
},
|
|
91
|
+
"min-score": {
|
|
92
|
+
kind: "number",
|
|
93
|
+
placeholder: "X",
|
|
94
|
+
describe: "Discard results below this score.",
|
|
95
|
+
},
|
|
96
|
+
"complexity-bias": {
|
|
97
|
+
kind: "string",
|
|
98
|
+
placeholder: COMPLEXITY_BIASES.join("|"),
|
|
99
|
+
describe: "Prefer simpler or more complex results (vision.md §1b).",
|
|
100
|
+
defaultLabel: "none",
|
|
101
|
+
},
|
|
102
|
+
path: {
|
|
103
|
+
kind: "list",
|
|
104
|
+
placeholder: "GLOB",
|
|
105
|
+
describe: "Include these paths only. Repeatable.",
|
|
106
|
+
},
|
|
107
|
+
exclude: {
|
|
108
|
+
kind: "list",
|
|
109
|
+
placeholder: "GLOB",
|
|
110
|
+
describe: "Exclude these paths. Repeatable.",
|
|
111
|
+
},
|
|
112
|
+
lang: { kind: "list", placeholder: "ID", describe: "Include these languages only. Repeatable." },
|
|
113
|
+
repo: {
|
|
114
|
+
kind: "list",
|
|
115
|
+
placeholder: "ID",
|
|
116
|
+
describe: "Include these repositories only. Repeatable.",
|
|
117
|
+
},
|
|
118
|
+
ref: { kind: "list", placeholder: "ID", describe: "Include these refs only. Repeatable." },
|
|
119
|
+
symbol: { kind: "list", placeholder: "NAME", describe: "Exact symbol names. Repeatable." },
|
|
120
|
+
workspace: { kind: "string", placeholder: "ID", describe: "Override workspace ID." },
|
|
121
|
+
timeout: {
|
|
122
|
+
kind: "number",
|
|
123
|
+
placeholder: "MS",
|
|
124
|
+
describe: "Deadline for the entire query. Expiry makes the query fail.",
|
|
125
|
+
defaultLabel: String(DEFAULT_QUERY_TIMEOUT_MS),
|
|
126
|
+
},
|
|
127
|
+
refresh: {
|
|
128
|
+
kind: "boolean",
|
|
129
|
+
describe: "Refresh stale checked-out refs before searching; progress goes to stderr.",
|
|
130
|
+
},
|
|
131
|
+
"require-fresh": {
|
|
132
|
+
kind: "boolean",
|
|
133
|
+
describe: "Search only with confirmed current content hashes; otherwise exit 4.",
|
|
134
|
+
},
|
|
135
|
+
// --- grep-Modus (Nutzerwunsch A4) ---------------------------------------
|
|
136
|
+
grep: {
|
|
137
|
+
kind: "boolean",
|
|
138
|
+
alias: "g",
|
|
139
|
+
describe: "grep mode: literal search in indexed content.",
|
|
140
|
+
},
|
|
141
|
+
regex: { kind: "boolean", alias: "e", describe: "grep mode with a regular expression." },
|
|
142
|
+
"ignore-case": {
|
|
143
|
+
kind: "boolean",
|
|
144
|
+
alias: "i",
|
|
145
|
+
describe: "grep: ignore letter case.",
|
|
146
|
+
},
|
|
147
|
+
word: {
|
|
148
|
+
kind: "boolean",
|
|
149
|
+
alias: "w",
|
|
150
|
+
describe: "grep: whole words only (identifier boundaries).",
|
|
151
|
+
},
|
|
152
|
+
after: {
|
|
153
|
+
kind: "number",
|
|
154
|
+
alias: "A",
|
|
155
|
+
placeholder: "N",
|
|
156
|
+
describe: "grep: context lines after the match.",
|
|
157
|
+
},
|
|
158
|
+
before: {
|
|
159
|
+
kind: "number",
|
|
160
|
+
alias: "B",
|
|
161
|
+
placeholder: "N",
|
|
162
|
+
describe: "grep: context lines before the match.",
|
|
163
|
+
},
|
|
164
|
+
context: {
|
|
165
|
+
kind: "boolean-or-number",
|
|
166
|
+
alias: "C",
|
|
167
|
+
placeholder: "N",
|
|
168
|
+
describe: "Search: direct relationships from the persisted file graph. grep: =N or -C N shows context on both sides.",
|
|
169
|
+
},
|
|
170
|
+
"max-matches": {
|
|
171
|
+
kind: "number",
|
|
172
|
+
placeholder: "N",
|
|
173
|
+
describe: "grep: maximum total matches.",
|
|
174
|
+
},
|
|
175
|
+
"max-per-file": { kind: "number", placeholder: "N", describe: "grep: maximum matches per file." },
|
|
176
|
+
"max-scanned": {
|
|
177
|
+
kind: "number",
|
|
178
|
+
placeholder: "N",
|
|
179
|
+
describe: "grep: maximum searched chunks.",
|
|
180
|
+
},
|
|
181
|
+
"grep-sort": {
|
|
182
|
+
kind: "string",
|
|
183
|
+
placeholder: GREP_SORTS.join("|"),
|
|
184
|
+
describe: "grep: match ordering.",
|
|
185
|
+
defaultLabel: "path",
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
export const queryCommand = {
|
|
189
|
+
spec: {
|
|
190
|
+
name: "query",
|
|
191
|
+
implementedBy: "commands/query.js",
|
|
192
|
+
summary: "Search the index with semantic and grep-style queries",
|
|
193
|
+
usage: "untangle query <text> [options]",
|
|
194
|
+
details: [
|
|
195
|
+
"Without --grep/--regex, hybrid search retrieves dense vectors, BM25 and exact symbols independently, then combines them with RRF. --mode selects independent retrieval and ranking paths; lexical/symbol need no embedding service.",
|
|
196
|
+
"Before each search, index freshness is checked against the full current content manifest and returned as indexFreshness. --refresh updates stale checked-out refs; --require-fresh rejects unconfirmed freshness. An outdated lexical index format requires reindexing.",
|
|
197
|
+
"--grep (literal) and --regex search the same index with the same filters and skip ledger. Context lines come from the same chunk and stop at its boundary.",
|
|
198
|
+
"--explain shows the full score breakdown: each component's raw value, weight and contribution, making the ranking inspectable.",
|
|
199
|
+
"Profile discovery: `untangle index` records the embedding profile per repository/ref in the local registry (.untangle/index-states-v1). Without --embedder, query uses the generation-bound current state and reports that choice on stderr. Override with --embedder=service or --embedder=offline.",
|
|
200
|
+
"Search reads the index, not the working tree. Unindexed content cannot be found; the result therefore includes its skip ledger and, for grep, the number of searched chunks.",
|
|
201
|
+
],
|
|
202
|
+
flags: FLAGS,
|
|
203
|
+
examples: [
|
|
204
|
+
'untangle query "where is the payment triggered"',
|
|
205
|
+
'untangle query "charge" --mode=symbol --explain',
|
|
206
|
+
"untangle query --regex \"await\\\\s+fetch\\\\(\" -C 2 --path='src/**' --exclude='**/*.test.ts'",
|
|
207
|
+
'untangle query "retry" --format=jsonl | jq -r .filePath',
|
|
208
|
+
],
|
|
209
|
+
exitCodes: [
|
|
210
|
+
[EXIT.ok, "Search completed, including zero-hit results."],
|
|
211
|
+
[EXIT.operational, "Invalid configuration or a storage error."],
|
|
212
|
+
[EXIT.usage, "Invalid arguments."],
|
|
213
|
+
[
|
|
214
|
+
EXIT.environment,
|
|
215
|
+
"No compatible index, or the selected storage/embedding provider is unavailable.",
|
|
216
|
+
],
|
|
217
|
+
[EXIT.cancelled, "Cancelled."],
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
async run(ctx, args) {
|
|
221
|
+
const format = enumFlag(args, "format", OUTPUT_FORMATS, "text");
|
|
222
|
+
const isGrep = boolFlag(args, "grep") || boolFlag(args, "regex");
|
|
223
|
+
const text = args.positionals.join(" ").trim();
|
|
224
|
+
if (text.length === 0) {
|
|
225
|
+
throw new UsageError("Search text is required.", isGrep
|
|
226
|
+
? 'Example: untangle query --regex "await\\\\s+fetch\\\\("'
|
|
227
|
+
: 'Example: untangle query "where is the payment triggered"');
|
|
228
|
+
}
|
|
229
|
+
const view = loadWorkspace({
|
|
230
|
+
cwd: args.flags["root"] === undefined ? ctx.cwd : String(args.flags["root"]),
|
|
231
|
+
env: ctx.env,
|
|
232
|
+
workspaceIdOverride: stringFlag(args, "workspace"),
|
|
233
|
+
strict: true,
|
|
234
|
+
});
|
|
235
|
+
if (view.load.warnings.length > 0) {
|
|
236
|
+
for (const warning of view.load.warnings) {
|
|
237
|
+
note(ctx.io, `Configuration warning: ${warning.path || "(root)"}: ${warning.message}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const wiring = wireStorage(view, ctx.env);
|
|
241
|
+
const timeoutMs = integerFlag(args, "timeout", DEFAULT_QUERY_TIMEOUT_MS);
|
|
242
|
+
// `untangle index --embedder=offline` legt seine Punkte in einer EIGENEN
|
|
243
|
+
// Sammlung ab (eigener `embedding_profile_id`, spec.md §10.1) — sonst
|
|
244
|
+
// mischten netzlose und echte Vektoren in einem Raum, in dem sie nicht
|
|
245
|
+
// vergleichbar sind. Damit dieser Index auch DURCHSUCHBAR ist, kennt
|
|
246
|
+
// `query` denselben Schalter.
|
|
247
|
+
//
|
|
248
|
+
// WP-229: Ihn zu KENNEN reichte aber nicht — man musste ihn auch bei jeder
|
|
249
|
+
// Abfrage wiederholen. `auto` liest deshalb den Indexzustand, den
|
|
250
|
+
// `untangle index` hinterlaesst, und nimmt von dort, WOMIT tatsaechlich
|
|
251
|
+
// indiziert wurde. Geraten wird nichts: gibt es keinen Zustand, gilt die
|
|
252
|
+
// Konfiguration wie bisher, und widersprechen sich mehrere, sagt der
|
|
253
|
+
// Befehl das und laesst den Nutzer entscheiden.
|
|
254
|
+
const selectedRepoIds = listFlag(args, "repo");
|
|
255
|
+
const selectedRefIds = listFlag(args, "ref");
|
|
256
|
+
const indexStateResolution = await resolveIndexState(indexStateRoots({
|
|
257
|
+
invocationRoot: args.flags["root"] === undefined
|
|
258
|
+
? ctx.cwd
|
|
259
|
+
: path.resolve(ctx.cwd, String(args.flags["root"])),
|
|
260
|
+
configBaseDir: view.load.sources.configBaseDir,
|
|
261
|
+
repositories: view.config.repositories ?? [],
|
|
262
|
+
selectedRepoIds,
|
|
263
|
+
}), view.workspaceId, { repoIds: selectedRepoIds, refs: selectedRefIds, ...storageIndexScope(wiring) });
|
|
264
|
+
if (indexStateResolution.kind === "invalid") {
|
|
265
|
+
const details = indexStateResolution.diagnostics
|
|
266
|
+
.map((diagnostic) => `${diagnostic.path}: ${diagnostic.message}`)
|
|
267
|
+
.join("; ");
|
|
268
|
+
throw new EnvironmentError(`The local index state is invalid; search will not use partial or ` +
|
|
269
|
+
`stale provenance. ${details}`, "Rerun the affected indexing job. It publishes the repository/ref registry atomically.");
|
|
270
|
+
}
|
|
271
|
+
const automaticEmbedder = enumFlag(args, "embedder", ["auto", "service", "offline"], "auto") === "auto";
|
|
272
|
+
const useOffline = resolveEmbedderChoice(ctx, args, indexStateResolution);
|
|
273
|
+
const embedder = useOffline ? new OfflineEmbeddingProvider(systemClock) : wireEmbedder(view);
|
|
274
|
+
const searchView = useOffline
|
|
275
|
+
? {
|
|
276
|
+
...view,
|
|
277
|
+
profile: embedder.profile,
|
|
278
|
+
profileId: embedder.profileId,
|
|
279
|
+
profileShortId: embeddingProfileShortId(embedder.profileId),
|
|
280
|
+
}
|
|
281
|
+
: view;
|
|
282
|
+
const collection = useOffline
|
|
283
|
+
? codeCollectionName(wiring.collectionPrefix, searchView.profileShortId)
|
|
284
|
+
: wiring.codeCollection;
|
|
285
|
+
const foundIndexStates = queryIndexStatesFromResolution(indexStateResolution, automaticEmbedder);
|
|
286
|
+
const compatibleIndexStates = foundIndexStates.filter(({ state }) => state.embeddingProfileId === searchView.profileId &&
|
|
287
|
+
state.collection === collection &&
|
|
288
|
+
matchesStoredBackend(state, wiring));
|
|
289
|
+
const freshnessCheck = await withDeadline((signal) => inspectIndexFreshness(view, compatibleIndexStates, {
|
|
290
|
+
signal,
|
|
291
|
+
expectedRepoIds: selectedRepoIds.length > 0 ? selectedRepoIds : view.repoIds,
|
|
292
|
+
expectedRefs: selectedRefIds,
|
|
293
|
+
}), timeoutMs, ctx.signal);
|
|
294
|
+
ctx.signal.throwIfAborted();
|
|
295
|
+
const indexFreshness = freshnessCheck.ok
|
|
296
|
+
? freshnessCheck.value
|
|
297
|
+
: {
|
|
298
|
+
status: "unknown",
|
|
299
|
+
checkedAt: systemClock.nowIso(),
|
|
300
|
+
repositories: [],
|
|
301
|
+
};
|
|
302
|
+
if (boolFlag(args, "refresh") && indexFreshness.status !== "fresh") {
|
|
303
|
+
await refreshWorkspaceIndex(ctx, {
|
|
304
|
+
view,
|
|
305
|
+
repoIds: selectedRepoIds,
|
|
306
|
+
refIds: selectedRefIds,
|
|
307
|
+
embedder: useOffline ? "offline" : "auto",
|
|
308
|
+
});
|
|
309
|
+
return queryCommand.run(ctx, {
|
|
310
|
+
...args,
|
|
311
|
+
flags: { ...args.flags, refresh: false, "require-fresh": true },
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
if (indexFreshness.status === "incompatible" ||
|
|
315
|
+
(boolFlag(args, "require-fresh") && indexFreshness.status !== "fresh")) {
|
|
316
|
+
throw new EnvironmentError(`The search index is ${indexFreshness.status}; this query requires a current, compatible index.`, "Run the same query with --refresh or update with `untangle index`.");
|
|
317
|
+
}
|
|
318
|
+
note(ctx.io, `Index freshness: ${indexFreshness.status} (content hashes checked ${indexFreshness.checkedAt}).`);
|
|
319
|
+
const indexContexts = compatibleIndexStates.flatMap(({ state }) => state.generationId !== undefined
|
|
320
|
+
? [
|
|
321
|
+
{
|
|
322
|
+
repoId: state.repoId,
|
|
323
|
+
refId: state.refId,
|
|
324
|
+
generationId: state.generationId,
|
|
325
|
+
...(state.corpusRevisionFingerprint === undefined || indexFreshness.status !== "fresh"
|
|
326
|
+
? {}
|
|
327
|
+
: { corpusRevisionFingerprint: state.corpusRevisionFingerprint }),
|
|
328
|
+
outcome: state.outcome,
|
|
329
|
+
},
|
|
330
|
+
]
|
|
331
|
+
: []);
|
|
332
|
+
const effectiveRefIds = queryRefIdsFromIndexStates(selectedRefIds, compatibleIndexStates);
|
|
333
|
+
// Der fehlende Index ist der haeufigste Fall und verdient eine eigene,
|
|
334
|
+
// eindeutige Antwort — nicht eine leere Trefferliste (E4).
|
|
335
|
+
const probe = await withDeadline((signal) => wiring.vectorStore.collectionExists(collection, { signal }), timeoutMs, ctx.signal);
|
|
336
|
+
if (!probe.ok) {
|
|
337
|
+
ctx.signal.throwIfAborted();
|
|
338
|
+
throw new EnvironmentError(probe.timedOut
|
|
339
|
+
? `${wiring.backend === "qdrant" ? "Qdrant" : "LanceDB"} at ${wiring.storeUrl} did not answer within ${String(timeoutMs)}ms.`
|
|
340
|
+
: `${wiring.backend === "qdrant" ? "Qdrant" : "LanceDB"} at ${wiring.storeUrl} is unreachable: ${errorMessage(probe.error)}`, "Run `untangle doctor` for the next step specific to this failure.", { cause: probe.error });
|
|
341
|
+
}
|
|
342
|
+
if (!probe.value) {
|
|
343
|
+
if (boolFlag(args, "refresh")) {
|
|
344
|
+
await refreshWorkspaceIndex(ctx, {
|
|
345
|
+
view,
|
|
346
|
+
repoIds: selectedRepoIds,
|
|
347
|
+
refIds: selectedRefIds,
|
|
348
|
+
embedder: useOffline ? "offline" : "auto",
|
|
349
|
+
});
|
|
350
|
+
return queryCommand.run(ctx, {
|
|
351
|
+
...args,
|
|
352
|
+
flags: { ...args.flags, refresh: false, "require-fresh": true },
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
throw new EnvironmentError(`No index exists for this embedding profile: collection "${collection}" ` +
|
|
356
|
+
`is absent from ${wiring.storeUrl}. Nothing was searched; this does not ` +
|
|
357
|
+
`mean there are no results.`, useOffline
|
|
358
|
+
? "Run `untangle index --embedder=offline` to build this collection."
|
|
359
|
+
: "Run `untangle index`. Without an available embedding service, use `untangle index --embedder=offline` and select `--embedder=offline` here too.");
|
|
360
|
+
}
|
|
361
|
+
const engine = wireSearchEngine({
|
|
362
|
+
view: searchView,
|
|
363
|
+
vectorStore: wiring.vectorStore,
|
|
364
|
+
collection,
|
|
365
|
+
embedder,
|
|
366
|
+
indexContexts,
|
|
367
|
+
...(!isGrep && (boolFlag(args, "context") || boolFlag(args, "linked"))
|
|
368
|
+
? { graphEnrichment: createSearchGraphEnrichment(wiring.storage.graphStore) }
|
|
369
|
+
: {}),
|
|
370
|
+
});
|
|
371
|
+
if (isGrep) {
|
|
372
|
+
const request = buildGrepRequest(args, view.workspaceId, text, effectiveRefIds);
|
|
373
|
+
const outcome = await withDeadline((signal) => engine.grep(request, { signal }), timeoutMs, ctx.signal);
|
|
374
|
+
if (!outcome.ok) {
|
|
375
|
+
ctx.signal.throwIfAborted();
|
|
376
|
+
throw toRuntimeError(outcome, wiring.storeUrl, timeoutMs, "grep", useOffline);
|
|
377
|
+
}
|
|
378
|
+
outcome.value.indexFreshness = indexFreshness;
|
|
379
|
+
addFreshnessWarning(outcome.value, indexFreshness);
|
|
380
|
+
renderGrep(ctx, outcome.value, format);
|
|
381
|
+
assertEverythingWasSearched(ctx, outcome.value.skipped, wiring.backend);
|
|
382
|
+
return EXIT.ok;
|
|
383
|
+
}
|
|
384
|
+
const request = buildSearchRequest(args, view.workspaceId, text, selectedRefIds.length === 0 ? undefined : effectiveRefIds);
|
|
385
|
+
const outcome = await withDeadline((signal) => engine.search(request, { signal }), timeoutMs, ctx.signal);
|
|
386
|
+
if (!outcome.ok) {
|
|
387
|
+
ctx.signal.throwIfAborted();
|
|
388
|
+
throw toRuntimeError(outcome, wiring.storeUrl, timeoutMs, request, useOffline);
|
|
389
|
+
}
|
|
390
|
+
outcome.value.indexFreshness = indexFreshness;
|
|
391
|
+
addFreshnessWarning(outcome.value, indexFreshness);
|
|
392
|
+
renderSearch(ctx, outcome.value, format, boolFlag(args, "explain"));
|
|
393
|
+
assertEverythingWasSearched(ctx, outcome.value.skipped, wiring.backend);
|
|
394
|
+
return EXIT.ok;
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
/* --------------------------------------------------------------------- */
|
|
398
|
+
export function addFreshnessWarning(result, freshness) {
|
|
399
|
+
if (freshness.status === "fresh")
|
|
400
|
+
return;
|
|
401
|
+
const warning = {
|
|
402
|
+
code: INDEX_CONTEXT_INCOMPLETE_WARNING_CODE,
|
|
403
|
+
message: `Indexfrische ${freshness.status}: results describe an unconfirmed or stale snapshot. Update with --refresh. This query is not reliable product-complexity evidence.`,
|
|
404
|
+
details: {
|
|
405
|
+
status: freshness.status,
|
|
406
|
+
checkedAt: freshness.checkedAt,
|
|
407
|
+
reasons: freshness.repositories.map((entry) => entry.reason),
|
|
408
|
+
},
|
|
409
|
+
};
|
|
410
|
+
const existingIndex = result.warnings.findIndex((entry) => entry.code === INDEX_CONTEXT_INCOMPLETE_WARNING_CODE);
|
|
411
|
+
const existing = result.warnings[existingIndex];
|
|
412
|
+
if (existing === undefined)
|
|
413
|
+
result.warnings.push(warning);
|
|
414
|
+
else
|
|
415
|
+
result.warnings[existingIndex] = {
|
|
416
|
+
...existing,
|
|
417
|
+
message: `${existing.message} ${warning.message}`,
|
|
418
|
+
details: { ...existing.details, indexFreshness: warning.details },
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Welcher Einbetter durchsucht wird — und woher diese Entscheidung stammt
|
|
423
|
+
* (WP-229).
|
|
424
|
+
*
|
|
425
|
+
* `--embedder=offline` und `--embedder=service` sind ausdrueckliche
|
|
426
|
+
* Anweisungen und gewinnen immer. `auto` fragt den Indexzustand: er ist die
|
|
427
|
+
* einzige Quelle, die WEISS, womit gebaut wurde. Was dabei entschieden wird,
|
|
428
|
+
* steht auf stderr — eine Wahl, die der Nutzer nicht sieht, ist eine Wahl,
|
|
429
|
+
* die er nicht ueberstimmen kann.
|
|
430
|
+
*/
|
|
431
|
+
export function resolveEmbedderChoice(ctx, args, resolution) {
|
|
432
|
+
const flag = enumFlag(args, "embedder", ["auto", "service", "offline"], "auto");
|
|
433
|
+
if (flag === "offline")
|
|
434
|
+
return true;
|
|
435
|
+
if (flag === "service")
|
|
436
|
+
return false;
|
|
437
|
+
if (resolution.kind === "none") {
|
|
438
|
+
// Kein Zustand heisst: es wurde hier noch nicht indiziert, oder mit einer
|
|
439
|
+
// aelteren Fassung. Dann gilt die Konfiguration — und wenn dazu kein Index
|
|
440
|
+
// existiert, meldet das der Aufrufer mit der Begruendung, die es schon gab.
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
if (resolution.kind === "ambiguous") {
|
|
444
|
+
const states = resolution.found
|
|
445
|
+
.map((entry) => `${entry.state.repoId}/${entry.state.refName}: ${entry.state.embedder}`)
|
|
446
|
+
.join(", ");
|
|
447
|
+
throw new UsageError("The current repository/ref states use different embedders; `auto` " +
|
|
448
|
+
`would search only a subset (${states}). Select --embedder=service or ` +
|
|
449
|
+
"--embedder=offline explicitly.", "An explicit selection searches only locally registered refs for that profile.");
|
|
450
|
+
}
|
|
451
|
+
if (resolution.kind === "invalid") {
|
|
452
|
+
// The command rejects this case before selecting an embedder. Keeping the
|
|
453
|
+
// guard here makes the helper exhaustive if it is reused independently.
|
|
454
|
+
throw new EnvironmentError("The local index state is invalid; the embedding profile will not be guessed.", "Rerun the affected indexing job.");
|
|
455
|
+
}
|
|
456
|
+
const state = resolution.found.state;
|
|
457
|
+
note(ctx.io, `Embedding profile from the last index run: ${describeEmbedder(state.embedder)} ` +
|
|
458
|
+
`(${resolution.found.statePath}). ` +
|
|
459
|
+
"Override with --embedder=service or --embedder=offline.");
|
|
460
|
+
if (state.outcome !== "completed") {
|
|
461
|
+
note(ctx.io, `Warning: this indexing run ended as "${state.outcome}". Anything it could not finish ` +
|
|
462
|
+
"cannot be found here either.");
|
|
463
|
+
}
|
|
464
|
+
return state.embedder === "offline";
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Wo nach dem Indexzustand gesucht wird. Ohne Repo-Filter gilt die bisherige
|
|
468
|
+
* Reihenfolge: Aufrufswurzel, Konfigurationswurzel, dann alle konfigurierten
|
|
469
|
+
* Repositories codepoint-sortiert. Mit `--repo` duerfen dagegen nur die
|
|
470
|
+
* tatsaechlich ausgewaehlten Repository-Wurzeln die Auto-Embedder-Wahl
|
|
471
|
+
* beeinflussen; ein unbeteiligtes Repository darf keine Ambiguitaet erzeugen.
|
|
472
|
+
*/
|
|
473
|
+
export function indexStateRoots(input) {
|
|
474
|
+
const selected = new Set(input.selectedRepoIds);
|
|
475
|
+
const roots = selected.size === 0 || input.repositories.length === 0
|
|
476
|
+
? [input.invocationRoot, input.configBaseDir]
|
|
477
|
+
: [];
|
|
478
|
+
const repositories = [...input.repositories]
|
|
479
|
+
.filter((repository) => selected.size === 0 || selected.has(repository.id))
|
|
480
|
+
.sort((a, b) => compareCodepoints(a.id, b.id));
|
|
481
|
+
for (const repository of repositories) {
|
|
482
|
+
roots.push(path.resolve(input.configBaseDir, repository.path));
|
|
483
|
+
}
|
|
484
|
+
return roots;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Resolves an omitted ref scope to the refs for which the selected collection
|
|
488
|
+
* has local index state. Explicit canonical IDs remain authoritative; an
|
|
489
|
+
* explicit human ref name expands to every compatible canonical ID carrying
|
|
490
|
+
* that name (for example `main` in two selected repositories).
|
|
491
|
+
*
|
|
492
|
+
* The grep path receives these IDs directly. Semantic search receives the
|
|
493
|
+
* richer index contexts and derives the same scope inside the engine, where
|
|
494
|
+
* it can still distinguish an implicit scope for provenance validation. This
|
|
495
|
+
* is deliberately based on profile/collection-compatible states supplied by
|
|
496
|
+
* the caller: an old state for another embedding space must not widen a scan.
|
|
497
|
+
*/
|
|
498
|
+
export function queryRefIdsFromIndexStates(requestedRefIds, compatibleIndexStates) {
|
|
499
|
+
if (requestedRefIds.length === 0) {
|
|
500
|
+
return uniqueSortedByCodepoints(compatibleIndexStates.map(({ state }) => state.refId));
|
|
501
|
+
}
|
|
502
|
+
const canonicalIds = new Set(compatibleIndexStates.map(({ state }) => state.refId));
|
|
503
|
+
const resolved = [];
|
|
504
|
+
for (const requested of requestedRefIds) {
|
|
505
|
+
if (canonicalIds.has(requested)) {
|
|
506
|
+
resolved.push(requested);
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
const nameMatches = compatibleIndexStates
|
|
510
|
+
.filter(({ state }) => state.refName === requested)
|
|
511
|
+
.map(({ state }) => state.refId);
|
|
512
|
+
// Keep an unknown explicit value. It will remain a restrictive store
|
|
513
|
+
// filter and cannot silently fall back to the implicit/all-ref scope.
|
|
514
|
+
resolved.push(...(nameMatches.length === 0 ? [requested] : nameMatches));
|
|
515
|
+
}
|
|
516
|
+
return uniqueSortedByCodepoints(resolved);
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Auto-routing follows only the generation-checked current pointer of every
|
|
520
|
+
* selected repo/ref. An explicit embedder selection may intentionally reopen
|
|
521
|
+
* an older retained profile and therefore receives the complete registry.
|
|
522
|
+
*/
|
|
523
|
+
export function queryIndexStatesFromResolution(resolution, automaticEmbedder) {
|
|
524
|
+
if (resolution.kind === "none")
|
|
525
|
+
return [];
|
|
526
|
+
const all = resolution.all;
|
|
527
|
+
return automaticEmbedder ? all.filter((entry) => entry.current) : all;
|
|
528
|
+
}
|
|
529
|
+
function describeEmbedder(choice) {
|
|
530
|
+
return choice === "offline" ? "offline (local, in-process)" : "the configured service";
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Ziele, die ueberhaupt nicht durchsucht werden konnten.
|
|
534
|
+
*
|
|
535
|
+
* DIESE UNTERSCHEIDUNG IST DER KERN VON E4 AN DIESER OBERFLAECHE. Der
|
|
536
|
+
* Abrufkern degradiert bewusst sichtbar: faellt ein Embedding-Profil aus (weil
|
|
537
|
+
* Ollama nicht antwortet), meldet er das als Warnung UND als Ledger-Eintrag
|
|
538
|
+
* und liefert die uebrigen Profile trotzdem. Fuer den Aufrufer sieht das
|
|
539
|
+
* Ergebnis dann aus wie „null Treffer" — und genau das waere die Luege:
|
|
540
|
+
* gesucht wurde nichts.
|
|
541
|
+
*
|
|
542
|
+
* Gemessen an einem blockierten Ollama gab diese Oberflaeche vor der
|
|
543
|
+
* Einfuehrung dieser Pruefung „Keine Treffer." mit Exit-Code 0 aus, obwohl im
|
|
544
|
+
* Ledger `provider_unavailable` stand. Jetzt endet derselbe Fall mit
|
|
545
|
+
* Exit-Code 4 und der Begruendung aus dem Ledger.
|
|
546
|
+
*
|
|
547
|
+
* Erkannt wird der Ausfall an der Kombination, die der Abrufkern EXAKT fuer
|
|
548
|
+
* diesen Fall schreibt: `subjectKind === "search_candidate"` zusammen mit
|
|
549
|
+
* `reason === "provider_unavailable"`. Ein wegen Filtern oder Budget
|
|
550
|
+
* ausgelassenes Ziel traegt stattdessen `excluded_by_configuration` und ist
|
|
551
|
+
* kein Ausfall.
|
|
552
|
+
*/
|
|
553
|
+
export function failedTargets(skipped) {
|
|
554
|
+
return skipped.filter((entry) => entry.subjectKind === "search_candidate" && entry.reason === "provider_unavailable");
|
|
555
|
+
}
|
|
556
|
+
/** Wirft, wenn ein Ziel ausgefallen ist — „nichts durchsucht" ist kein Erfolg. */
|
|
557
|
+
function assertEverythingWasSearched(ctx, skipped, backend) {
|
|
558
|
+
const failed = failedTargets(skipped);
|
|
559
|
+
if (failed.length === 0)
|
|
560
|
+
return;
|
|
561
|
+
for (const entry of failed) {
|
|
562
|
+
note(ctx.io, `Unavailable target: ${entry.detail}`);
|
|
563
|
+
}
|
|
564
|
+
throw new EnvironmentError(`${String(failed.length)} search target(s) did not respond. The result above is ` +
|
|
565
|
+
"incomplete; this does not mean nothing was found.", `Run \`untangle doctor\` to check Ollama and ${backend === "lancedb" ? "LanceDB" : "Qdrant"} independently with separate deadlines.`);
|
|
566
|
+
}
|
|
567
|
+
export function buildSearchRequest(args, workspaceId, text, refIdsOverride) {
|
|
568
|
+
if (typeof args.flags["context"] === "number") {
|
|
569
|
+
throw new UsageError('Option "--context=N" applies only in grep mode.', 'For semantic search, use "--context" without a number.');
|
|
570
|
+
}
|
|
571
|
+
const limit = numberFlag(args, "limit");
|
|
572
|
+
const minScore = numberFlag(args, "min-score");
|
|
573
|
+
const paths = listFlag(args, "path");
|
|
574
|
+
const excludes = listFlag(args, "exclude");
|
|
575
|
+
const languages = listFlag(args, "lang");
|
|
576
|
+
const repositories = listFlag(args, "repo");
|
|
577
|
+
const refs = refIdsOverride === undefined ? listFlag(args, "ref") : uniqueSortedByCodepoints(refIdsOverride);
|
|
578
|
+
const symbolNames = listFlag(args, "symbol");
|
|
579
|
+
return {
|
|
580
|
+
query: text,
|
|
581
|
+
workspaceId,
|
|
582
|
+
...(limit === undefined ? {} : { limit }),
|
|
583
|
+
...(minScore === undefined ? {} : { minScore }),
|
|
584
|
+
...(paths.length === 0 ? {} : { pathGlob: paths }),
|
|
585
|
+
...(excludes.length === 0 ? {} : { pathExclude: excludes }),
|
|
586
|
+
...(languages.length === 0 ? {} : { languages }),
|
|
587
|
+
...(repositories.length === 0 ? {} : { repositories }),
|
|
588
|
+
...(refs.length === 0 ? {} : { refs }),
|
|
589
|
+
...(symbolNames.length === 0 ? {} : { symbolNames }),
|
|
590
|
+
mode: enumFlag(args, "mode", SEARCH_MODES, "hybrid"),
|
|
591
|
+
abstention: enumFlag(args, "abstention", SEARCH_ABSTENTIONS, "strict"),
|
|
592
|
+
sort: enumFlag(args, "sort", SEARCH_SORTS, "relevance"),
|
|
593
|
+
complexityBias: enumFlag(args, "complexity-bias", COMPLEXITY_BIASES, "none"),
|
|
594
|
+
includeContent: boolFlag(args, "content"),
|
|
595
|
+
includeContext: boolFlag(args, "context"),
|
|
596
|
+
includeLinked: boolFlag(args, "linked"),
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
export function buildGrepRequest(args, workspaceId, pattern, refIdsOverride) {
|
|
600
|
+
if (args.flags["context"] === true) {
|
|
601
|
+
throw new UsageError('Option "--context" requires a non-negative integer in grep mode.', 'Example: "--context=2" or "-C 2".');
|
|
602
|
+
}
|
|
603
|
+
const both = integerFlag(args, "context", 0);
|
|
604
|
+
const before = integerFlag(args, "before", both);
|
|
605
|
+
const after = integerFlag(args, "after", both);
|
|
606
|
+
const paths = listFlag(args, "path");
|
|
607
|
+
const excludes = listFlag(args, "exclude");
|
|
608
|
+
const languages = listFlag(args, "lang");
|
|
609
|
+
const repositories = listFlag(args, "repo");
|
|
610
|
+
const refs = refIdsOverride === undefined ? listFlag(args, "ref") : uniqueSortedByCodepoints(refIdsOverride);
|
|
611
|
+
const maxMatches = numberFlag(args, "max-matches");
|
|
612
|
+
const maxPerFile = numberFlag(args, "max-per-file");
|
|
613
|
+
const maxScanned = numberFlag(args, "max-scanned");
|
|
614
|
+
return {
|
|
615
|
+
pattern,
|
|
616
|
+
regex: boolFlag(args, "regex"),
|
|
617
|
+
// grep ist per Vorgabe gross-/kleinschreibungsempfindlich, wie das Werkzeug,
|
|
618
|
+
// dessen Namen der Modus traegt. `-i` hebt das auf.
|
|
619
|
+
caseSensitive: !boolFlag(args, "ignore-case"),
|
|
620
|
+
wholeWord: boolFlag(args, "word"),
|
|
621
|
+
workspaceId,
|
|
622
|
+
...(repositories.length === 0 ? {} : { repositories }),
|
|
623
|
+
...(refs.length === 0 ? {} : { refs }),
|
|
624
|
+
...(languages.length === 0 ? {} : { languages }),
|
|
625
|
+
...(paths.length === 0 ? {} : { pathGlob: paths }),
|
|
626
|
+
...(excludes.length === 0 ? {} : { pathExclude: excludes }),
|
|
627
|
+
contextLinesBefore: before,
|
|
628
|
+
contextLinesAfter: after,
|
|
629
|
+
...(maxMatches === undefined ? {} : { maxMatches }),
|
|
630
|
+
...(maxPerFile === undefined ? {} : { maxMatchesPerFile: maxPerFile }),
|
|
631
|
+
...(maxScanned === undefined ? {} : { maxScannedChunks: maxScanned }),
|
|
632
|
+
sort: enumFlag(args, "grep-sort", GREP_SORTS, "path"),
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
/* --------------------------------------------------------------------- */
|
|
636
|
+
export function renderSearch(ctx, set, format, explain) {
|
|
637
|
+
if (format !== "text") {
|
|
638
|
+
// WP-230: `line` und nicht `out`. Die Formatierer liefern ihren Text OHNE
|
|
639
|
+
// abschliessenden Zeilenumbruch; ohne ihn klebte der Ledger-Hinweis an der
|
|
640
|
+
// letzten Ausgabezeile, und bei `jsonl` haette die letzte Zeile keinen
|
|
641
|
+
// Abschluss — beides macht eine maschinenlesbare Ausgabe unlesbar.
|
|
642
|
+
line(ctx.io, formatSearchResultSet(set, format));
|
|
643
|
+
reportLedger(ctx, set.skipped.length, set.warnings.length);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
// Die Enthaltung wird VOR dem Leer-Zweig bestimmt und unabhaengig von ihm
|
|
647
|
+
// gemeldet. Frueher stand sie ausschliesslich in `if (totalHits === 0)` —
|
|
648
|
+
// eine Enthaltung wurde also aus der Listenlaenge erschlossen. Sobald
|
|
649
|
+
// Treffer trotz Ablehnung stehenbleiben, haette dieser Zweig geschwiegen und
|
|
650
|
+
// eine selbstbewusst aussehende Trefferliste gedruckt.
|
|
651
|
+
const insufficient = set.warnings.some((warning) => warning.code === NO_SUFFICIENT_MATCH_WARNING_CODE);
|
|
652
|
+
if (set.totalHits === 0) {
|
|
653
|
+
note(ctx.io, failedTargets(set.skipped).length > 0
|
|
654
|
+
? "No results, but the search was also incomplete (see below)."
|
|
655
|
+
: insufficient
|
|
656
|
+
? "No sufficiently relevant results found."
|
|
657
|
+
: "No results.");
|
|
658
|
+
reportLedger(ctx, set.skipped.length, set.warnings.length);
|
|
659
|
+
if (set.skipped.length > 0) {
|
|
660
|
+
note(ctx.io, "Skipped candidates appear in the --format=json skip ledger.");
|
|
661
|
+
}
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
if (insufficient) {
|
|
665
|
+
note(ctx.io, "No sufficiently relevant results found.");
|
|
666
|
+
}
|
|
667
|
+
for (const group of set.groups) {
|
|
668
|
+
if (set.profileSeparation) {
|
|
669
|
+
note(ctx.io, `# Profile ${group.embeddingProfileId} (${group.repoIds.join(", ")})`);
|
|
670
|
+
}
|
|
671
|
+
// Vorbehalte unbedingt drucken. Sie standen bisher NUR unter
|
|
672
|
+
// `profileSeparation`, und das ist im ausgelieferten CLI nie wahr:
|
|
673
|
+
// `wireSearchEngine` baut genau ein Profilziel. Der Vorbehalt traegt die
|
|
674
|
+
// drei gemessenen Werte samt Schwellen — er war damit im Textmodus
|
|
675
|
+
// unsichtbar.
|
|
676
|
+
for (const caveat of group.caveats)
|
|
677
|
+
note(ctx.io, `# Qualification: ${caveat}`);
|
|
678
|
+
for (const hit of group.hits) {
|
|
679
|
+
if (explain) {
|
|
680
|
+
// WP-230: `formatHitAsText` endet ohne Zeilenumbruch. Mit `out` klebte
|
|
681
|
+
// der naechste Treffer — und am Ende der Ledger-Hinweis — an der
|
|
682
|
+
// letzten Zeile der Score-Zerlegung.
|
|
683
|
+
line(ctx.io, formatHitAsText(hit));
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
line(ctx.io, compactHitLine(hit));
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
reportLedger(ctx, set.skipped.length, set.warnings.length);
|
|
691
|
+
}
|
|
692
|
+
/** Eine Zeile je Treffer — Rang, Ort, Symbol, Score. */
|
|
693
|
+
function compactHitLine(hit) {
|
|
694
|
+
const where = `${hit.filePath}:${String(hit.range.startLine)}-${String(hit.range.endLine)}`;
|
|
695
|
+
const symbol = hit.symbolName === undefined ? "" : ` ${hit.symbolName}`;
|
|
696
|
+
const incomplete = hit.incompletePayloadFields === undefined || hit.incompletePayloadFields.length === 0
|
|
697
|
+
? ""
|
|
698
|
+
: ` [Fallback values: ${[...hit.incompletePayloadFields].sort(compareCodepoints).join(",")}]`;
|
|
699
|
+
const lines = [
|
|
700
|
+
`${String(hit.rank).padStart(3)} ${hit.score.final.toFixed(4)} ${where}${symbol}${incomplete}`,
|
|
701
|
+
];
|
|
702
|
+
if (hit.graphContext !== undefined) {
|
|
703
|
+
lines.push(...formatSearchGraphRelationsAsText("context", hit.graphContext));
|
|
704
|
+
}
|
|
705
|
+
if (hit.linkedSymbols !== undefined) {
|
|
706
|
+
lines.push(...formatSearchGraphRelationsAsText("linked", hit.linkedSymbols));
|
|
707
|
+
}
|
|
708
|
+
return lines.join("\n");
|
|
709
|
+
}
|
|
710
|
+
export function renderGrep(ctx, set, format) {
|
|
711
|
+
if (format !== "text") {
|
|
712
|
+
// WP-230, dieselbe Ursache wie oben.
|
|
713
|
+
line(ctx.io, formatGrepResultSet(set, format));
|
|
714
|
+
reportGrepTail(ctx, set);
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
for (const match of set.matches) {
|
|
718
|
+
for (const before of match.before) {
|
|
719
|
+
line(ctx.io, `${match.filePath}-${String(before.line)}-${before.text}`);
|
|
720
|
+
}
|
|
721
|
+
line(ctx.io, `${match.filePath}:${String(match.line)}:${String(match.column)}:${match.lineText}`);
|
|
722
|
+
for (const after of match.after) {
|
|
723
|
+
line(ctx.io, `${match.filePath}-${String(after.line)}-${after.text}`);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
reportGrepTail(ctx, set);
|
|
727
|
+
}
|
|
728
|
+
function reportGrepTail(ctx, set) {
|
|
729
|
+
note(ctx.io, `${String(set.totalMatches)} results, ${String(set.scannedChunks)} chunks searched.`);
|
|
730
|
+
if (set.truncated) {
|
|
731
|
+
note(ctx.io, `Truncated; reason: ${set.truncationReason ?? "unbenannt"}.`);
|
|
732
|
+
}
|
|
733
|
+
reportLedger(ctx, set.skipped.length, set.warnings.length);
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Der Ledger-Hinweis. Er steht auf stderr, weil er Diagnose ist — aber er
|
|
737
|
+
* steht IMMER, wenn es etwas zu melden gibt. Ein Ledger, den niemand sieht,
|
|
738
|
+
* ist kein Ledger.
|
|
739
|
+
*/
|
|
740
|
+
function reportLedger(ctx, skipped, warnings) {
|
|
741
|
+
if (skipped === 0 && warnings === 0)
|
|
742
|
+
return;
|
|
743
|
+
note(ctx.io, `Note: ${String(skipped)} skipped candidates, ${String(warnings)} warning(s). ` +
|
|
744
|
+
"Both are fully available in --format=json.");
|
|
745
|
+
}
|
|
746
|
+
export function toRuntimeError(outcome, qdrantUrl, timeoutMs, request, useOffline) {
|
|
747
|
+
const backendLabel = qdrantUrl.startsWith("file:") ? "LanceDB" : "Qdrant";
|
|
748
|
+
if (outcome.timedOut) {
|
|
749
|
+
const mode = request === "grep" ? "grep" : (request.mode ?? "hybrid");
|
|
750
|
+
const usesEmbedding = mode === "semantic" || mode === "hybrid";
|
|
751
|
+
const stages = [`Search retrieval from ${backendLabel} at ${qdrantUrl}`];
|
|
752
|
+
if (usesEmbedding)
|
|
753
|
+
stages.push(useOffline ? "local query embedding" : "Query embedding through Ollama");
|
|
754
|
+
const graphFlags = [];
|
|
755
|
+
if (request !== "grep" && request.includeContext)
|
|
756
|
+
graphFlags.push("--context");
|
|
757
|
+
if (request !== "grep" && request.includeLinked)
|
|
758
|
+
graphFlags.push("--linked");
|
|
759
|
+
if (graphFlags.length > 0)
|
|
760
|
+
stages.push(`Graph enrichment (${graphFlags.join(" ")}) from ${backendLabel}`);
|
|
761
|
+
return new EnvironmentError(`The query was cancelled after ${String(timeoutMs)}ms; no result is available. ` +
|
|
762
|
+
`Mode "${mode}" covers ${stages.join("; ")}.`, `Run \`untangle doctor\` to check ${backendLabel}${usesEmbedding && !useOffline ? " and Ollama" : ""} with separate deadlines.` +
|
|
763
|
+
(graphFlags.length > 0
|
|
764
|
+
? " Compare the runtime with the same query without graph enrichment."
|
|
765
|
+
: ""), { cause: outcome.error });
|
|
766
|
+
}
|
|
767
|
+
const error = outcome.error;
|
|
768
|
+
const message = errorMessage(error);
|
|
769
|
+
if ((isUntangleError(error) &&
|
|
770
|
+
(error.code === "QDRANT_UNAVAILABLE" ||
|
|
771
|
+
error.code === "LANCEDB_UNAVAILABLE" ||
|
|
772
|
+
error.code === "LANCEDB_SCHEMA_INCOMPATIBLE")) ||
|
|
773
|
+
/QDRANT_UNAVAILABLE|LANCEDB_UNAVAILABLE|fetch failed|ECONNREFUSED|ENOTFOUND|timed out/iu.test(message)) {
|
|
774
|
+
return new EnvironmentError(`The store at ${qdrantUrl} did not answer the query: ${message}`, `Run \`untangle doctor\` to check ${backendLabel} and Ollama independently.`, { cause: error });
|
|
775
|
+
}
|
|
776
|
+
if (/EMBEDDING|OLLAMA|model/iu.test(message)) {
|
|
777
|
+
return new EnvironmentError(`Could not create the query embedding: ${message}`, "Run `untangle doctor` to check whether Ollama is running and has the model.", { cause: error });
|
|
778
|
+
}
|
|
779
|
+
return new OperationalError(`Search failed: ${message}`, undefined, {
|
|
780
|
+
cause: error,
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
//# sourceMappingURL=query.js.map
|