homegraph 1.1.3 → 1.4.1
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/README.md +43 -18
- package/dist/arkts/ohos-api-index.d.ts +15 -0
- package/dist/arkts/ohos-api-index.d.ts.map +1 -0
- package/dist/arkts/ohos-api-index.js +190 -0
- package/dist/arkts/ohos-api-index.js.map +1 -0
- package/dist/arkts/ohos-sdk-input.d.ts +36 -0
- package/dist/arkts/ohos-sdk-input.d.ts.map +1 -0
- package/dist/arkts/ohos-sdk-input.js +214 -0
- package/dist/arkts/ohos-sdk-input.js.map +1 -0
- package/dist/bin/command-supervision.d.ts +12 -0
- package/dist/bin/command-supervision.d.ts.map +1 -0
- package/dist/bin/command-supervision.js +86 -0
- package/dist/bin/command-supervision.js.map +1 -0
- package/dist/bin/homegraph.d.ts +1 -1
- package/dist/bin/homegraph.js +709 -168
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +85 -0
- package/dist/context/index.js.map +1 -1
- package/dist/db/index.d.ts +84 -5
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +217 -14
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +58 -1
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/queries.d.ts +131 -2
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +473 -9
- package/dist/db/queries.js.map +1 -1
- package/dist/db/schema.sql +52 -1
- package/dist/db/wal-valve.d.ts +106 -0
- package/dist/db/wal-valve.d.ts.map +1 -0
- package/dist/db/wal-valve.js +208 -0
- package/dist/db/wal-valve.js.map +1 -0
- package/dist/directory.d.ts +36 -0
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +274 -0
- package/dist/directory.js.map +1 -1
- package/dist/extraction/arkts-batch-worker.d.ts +2 -0
- package/dist/extraction/arkts-batch-worker.d.ts.map +1 -0
- package/dist/extraction/arkts-batch-worker.js +28 -0
- package/dist/extraction/arkts-batch-worker.js.map +1 -0
- package/dist/extraction/cfml-extractor.d.ts +107 -0
- package/dist/extraction/cfml-extractor.d.ts.map +1 -0
- package/dist/extraction/cfml-extractor.js +494 -0
- package/dist/extraction/cfml-extractor.js.map +1 -0
- package/dist/extraction/context.d.ts +11 -0
- package/dist/extraction/context.d.ts.map +1 -1
- package/dist/extraction/context.js +20 -0
- package/dist/extraction/context.js.map +1 -1
- package/dist/extraction/grammars.d.ts +25 -1
- package/dist/extraction/grammars.d.ts.map +1 -1
- package/dist/extraction/grammars.js +177 -24
- package/dist/extraction/grammars.js.map +1 -1
- package/dist/extraction/index.d.ts +55 -2
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +923 -381
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts-state-decorators.d.ts +13 -0
- package/dist/extraction/languages/arkts-state-decorators.d.ts.map +1 -0
- package/dist/extraction/languages/arkts-state-decorators.js +26 -0
- package/dist/extraction/languages/arkts-state-decorators.js.map +1 -0
- package/dist/extraction/languages/arkts-viewtree.d.ts +4 -2
- package/dist/extraction/languages/arkts-viewtree.d.ts.map +1 -1
- package/dist/extraction/languages/arkts-viewtree.js +21 -6
- package/dist/extraction/languages/arkts-viewtree.js.map +1 -1
- package/dist/extraction/languages/arkts.d.ts +98 -2
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +1290 -61
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/extraction/languages/c-cpp.d.ts +98 -0
- package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/dist/extraction/languages/c-cpp.js +563 -1
- package/dist/extraction/languages/c-cpp.js.map +1 -1
- package/dist/extraction/languages/cfquery.d.ts +12 -0
- package/dist/extraction/languages/cfquery.d.ts.map +1 -0
- package/dist/extraction/languages/cfquery.js +28 -0
- package/dist/extraction/languages/cfquery.js.map +1 -0
- package/dist/extraction/languages/cfscript.d.ts +3 -0
- package/dist/extraction/languages/cfscript.d.ts.map +1 -0
- package/dist/extraction/languages/cfscript.js +73 -0
- package/dist/extraction/languages/cfscript.js.map +1 -0
- package/dist/extraction/languages/cobol.d.ts +33 -0
- package/dist/extraction/languages/cobol.d.ts.map +1 -0
- package/dist/extraction/languages/cobol.js +499 -0
- package/dist/extraction/languages/cobol.js.map +1 -0
- package/dist/extraction/languages/erlang.d.ts +3 -0
- package/dist/extraction/languages/erlang.d.ts.map +1 -0
- package/dist/extraction/languages/erlang.js +350 -0
- package/dist/extraction/languages/erlang.js.map +1 -0
- package/dist/extraction/languages/index.d.ts.map +1 -1
- package/dist/extraction/languages/index.js +16 -0
- package/dist/extraction/languages/index.js.map +1 -1
- package/dist/extraction/languages/nix.d.ts +3 -0
- package/dist/extraction/languages/nix.d.ts.map +1 -0
- package/dist/extraction/languages/nix.js +294 -0
- package/dist/extraction/languages/nix.js.map +1 -0
- package/dist/extraction/languages/ohos-api-consumer.d.ts +34 -0
- package/dist/extraction/languages/ohos-api-consumer.d.ts.map +1 -0
- package/dist/extraction/languages/ohos-api-consumer.js +283 -0
- package/dist/extraction/languages/ohos-api-consumer.js.map +1 -0
- package/dist/extraction/languages/solidity.d.ts +3 -0
- package/dist/extraction/languages/solidity.d.ts.map +1 -0
- package/dist/extraction/languages/solidity.js +293 -0
- package/dist/extraction/languages/solidity.js.map +1 -0
- package/dist/extraction/languages/terraform.d.ts +3 -0
- package/dist/extraction/languages/terraform.d.ts.map +1 -0
- package/dist/extraction/languages/terraform.js +641 -0
- package/dist/extraction/languages/terraform.js.map +1 -0
- package/dist/extraction/languages/vbnet.d.ts +11 -0
- package/dist/extraction/languages/vbnet.d.ts.map +1 -0
- package/dist/extraction/languages/vbnet.js +141 -0
- package/dist/extraction/languages/vbnet.js.map +1 -0
- package/dist/extraction/mybatis-extractor.d.ts +30 -10
- package/dist/extraction/mybatis-extractor.d.ts.map +1 -1
- package/dist/extraction/mybatis-extractor.js +140 -38
- package/dist/extraction/mybatis-extractor.js.map +1 -1
- package/dist/extraction/parse-pool.d.ts +152 -0
- package/dist/extraction/parse-pool.d.ts.map +1 -0
- package/dist/extraction/parse-pool.js +387 -0
- package/dist/extraction/parse-pool.js.map +1 -0
- package/dist/extraction/parse-worker.js +9 -2
- package/dist/extraction/parse-worker.js.map +1 -1
- package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -1
- package/dist/extraction/tree-sitter-helpers.js +1 -0
- package/dist/extraction/tree-sitter-helpers.js.map +1 -1
- package/dist/extraction/tree-sitter-types.d.ts +20 -1
- package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.d.ts +59 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.js +952 -37
- package/dist/extraction/tree-sitter.js.map +1 -1
- package/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-terraform.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
- package/dist/graph/traversal.d.ts.map +1 -1
- package/dist/graph/traversal.js +77 -18
- package/dist/graph/traversal.js.map +1 -1
- package/dist/index.d.ts +85 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +426 -9
- package/dist/index.js.map +1 -1
- package/dist/installer/index.d.ts +42 -0
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +97 -2
- package/dist/installer/index.js.map +1 -1
- package/dist/mcp/daemon-paths.d.ts +30 -3
- package/dist/mcp/daemon-paths.d.ts.map +1 -1
- package/dist/mcp/daemon-paths.js +50 -10
- package/dist/mcp/daemon-paths.js.map +1 -1
- package/dist/mcp/daemon-registry.d.ts.map +1 -1
- package/dist/mcp/daemon-registry.js +7 -3
- package/dist/mcp/daemon-registry.js.map +1 -1
- package/dist/mcp/daemon.d.ts +73 -3
- package/dist/mcp/daemon.d.ts.map +1 -1
- package/dist/mcp/daemon.js +258 -40
- package/dist/mcp/daemon.js.map +1 -1
- package/dist/mcp/dynamic-boundaries.d.ts.map +1 -1
- package/dist/mcp/dynamic-boundaries.js +2 -1
- package/dist/mcp/dynamic-boundaries.js.map +1 -1
- package/dist/mcp/early-ppid.d.ts +26 -0
- package/dist/mcp/early-ppid.d.ts.map +1 -0
- package/dist/mcp/early-ppid.js +29 -0
- package/dist/mcp/early-ppid.js.map +1 -0
- package/dist/mcp/engine.d.ts +16 -0
- package/dist/mcp/engine.d.ts.map +1 -1
- package/dist/mcp/engine.js +100 -2
- package/dist/mcp/engine.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +66 -49
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/liveness-watchdog.d.ts +18 -1
- package/dist/mcp/liveness-watchdog.d.ts.map +1 -1
- package/dist/mcp/liveness-watchdog.js +73 -13
- package/dist/mcp/liveness-watchdog.js.map +1 -1
- package/dist/mcp/memory-budget.d.ts +30 -0
- package/dist/mcp/memory-budget.d.ts.map +1 -0
- package/dist/mcp/memory-budget.js +123 -0
- package/dist/mcp/memory-budget.js.map +1 -0
- package/dist/mcp/ppid-watchdog.d.ts +18 -0
- package/dist/mcp/ppid-watchdog.d.ts.map +1 -1
- package/dist/mcp/ppid-watchdog.js +37 -0
- package/dist/mcp/ppid-watchdog.js.map +1 -1
- package/dist/mcp/proxy.d.ts.map +1 -1
- package/dist/mcp/proxy.js +88 -4
- package/dist/mcp/proxy.js.map +1 -1
- package/dist/mcp/query-cache.d.ts +56 -0
- package/dist/mcp/query-cache.d.ts.map +1 -0
- package/dist/mcp/query-cache.js +261 -0
- package/dist/mcp/query-cache.js.map +1 -0
- package/dist/mcp/query-pool.d.ts +128 -0
- package/dist/mcp/query-pool.d.ts.map +1 -0
- package/dist/mcp/query-pool.js +374 -0
- package/dist/mcp/query-pool.js.map +1 -0
- package/dist/mcp/query-worker.d.ts +24 -0
- package/dist/mcp/query-worker.d.ts.map +1 -0
- package/dist/mcp/query-worker.js +87 -0
- package/dist/mcp/query-worker.js.map +1 -0
- package/dist/mcp/server-instructions.d.ts +4 -29
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +39 -86
- package/dist/mcp/server-instructions.js.map +1 -1
- package/dist/mcp/session.d.ts +14 -0
- package/dist/mcp/session.d.ts.map +1 -1
- package/dist/mcp/session.js +28 -1
- package/dist/mcp/session.js.map +1 -1
- package/dist/mcp/startup-handshake.d.ts +44 -0
- package/dist/mcp/startup-handshake.d.ts.map +1 -0
- package/dist/mcp/startup-handshake.js +73 -0
- package/dist/mcp/startup-handshake.js.map +1 -0
- package/dist/mcp/tools.d.ts +179 -2
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +3027 -192
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp/transport.d.ts.map +1 -1
- package/dist/mcp/transport.js +18 -0
- package/dist/mcp/transport.js.map +1 -1
- package/dist/project-config.d.ts +58 -0
- package/dist/project-config.d.ts.map +1 -1
- package/dist/project-config.js +141 -2
- package/dist/project-config.js.map +1 -1
- package/dist/reasoning/login.js +1 -1
- package/dist/reasoning/login.js.map +1 -1
- package/dist/resolution/c-fnptr-synthesizer.d.ts +2 -29
- package/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
- package/dist/resolution/c-fnptr-synthesizer.js +866 -148
- package/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
- package/dist/resolution/callback-synthesizer.d.ts +9 -1
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/dist/resolution/callback-synthesizer.js +1232 -183
- package/dist/resolution/callback-synthesizer.js.map +1 -1
- package/dist/resolution/cooperative-yield.d.ts +32 -0
- package/dist/resolution/cooperative-yield.d.ts.map +1 -0
- package/dist/resolution/cooperative-yield.js +42 -0
- package/dist/resolution/cooperative-yield.js.map +1 -0
- package/dist/resolution/frameworks/cics.d.ts +20 -0
- package/dist/resolution/frameworks/cics.d.ts.map +1 -0
- package/dist/resolution/frameworks/cics.js +90 -0
- package/dist/resolution/frameworks/cics.js.map +1 -0
- package/dist/resolution/frameworks/index.d.ts.map +1 -1
- package/dist/resolution/frameworks/index.js +3 -0
- package/dist/resolution/frameworks/index.js.map +1 -1
- package/dist/resolution/frameworks/java.d.ts.map +1 -1
- package/dist/resolution/frameworks/java.js +14 -6
- package/dist/resolution/frameworks/java.js.map +1 -1
- package/dist/resolution/frameworks/terraform.d.ts +38 -0
- package/dist/resolution/frameworks/terraform.d.ts.map +1 -0
- package/dist/resolution/frameworks/terraform.js +277 -0
- package/dist/resolution/frameworks/terraform.js.map +1 -0
- package/dist/resolution/goframe-synthesizer.d.ts +2 -1
- package/dist/resolution/goframe-synthesizer.d.ts.map +1 -1
- package/dist/resolution/goframe-synthesizer.js +8 -3
- package/dist/resolution/goframe-synthesizer.js.map +1 -1
- package/dist/resolution/import-resolver.d.ts +7 -0
- package/dist/resolution/import-resolver.d.ts.map +1 -1
- package/dist/resolution/import-resolver.js +129 -4
- package/dist/resolution/import-resolver.js.map +1 -1
- package/dist/resolution/index.d.ts +65 -3
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +477 -59
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/name-matcher.d.ts +22 -3
- package/dist/resolution/name-matcher.d.ts.map +1 -1
- package/dist/resolution/name-matcher.js +657 -39
- package/dist/resolution/name-matcher.js.map +1 -1
- package/dist/resolution/strip-comments.d.ts +1 -1
- package/dist/resolution/strip-comments.d.ts.map +1 -1
- package/dist/resolution/strip-comments.js +49 -0
- package/dist/resolution/strip-comments.js.map +1 -1
- package/dist/resolution/types.d.ts +29 -0
- package/dist/resolution/types.d.ts.map +1 -1
- package/dist/resolution/workspace-packages.d.ts +10 -0
- package/dist/resolution/workspace-packages.d.ts.map +1 -1
- package/dist/resolution/workspace-packages.js +142 -4
- package/dist/resolution/workspace-packages.js.map +1 -1
- package/dist/search/identifier-segments.d.ts +60 -0
- package/dist/search/identifier-segments.d.ts.map +1 -0
- package/dist/search/identifier-segments.js +176 -0
- package/dist/search/identifier-segments.js.map +1 -0
- package/dist/search/query-utils.d.ts +201 -0
- package/dist/search/query-utils.d.ts.map +1 -1
- package/dist/search/query-utils.js +919 -2
- package/dist/search/query-utils.js.map +1 -1
- package/dist/spec/config.d.ts +7 -11
- package/dist/spec/config.d.ts.map +1 -1
- package/dist/spec/config.js +77 -48
- package/dist/spec/config.js.map +1 -1
- package/dist/spec/db/fragment-node.d.ts +1 -0
- package/dist/spec/db/fragment-node.d.ts.map +1 -1
- package/dist/spec/db/fragment-node.js +8 -0
- package/dist/spec/db/fragment-node.js.map +1 -1
- package/dist/spec/db/fts.d.ts +14 -0
- package/dist/spec/db/fts.d.ts.map +1 -1
- package/dist/spec/db/fts.js +43 -4
- package/dist/spec/db/fts.js.map +1 -1
- package/dist/spec/db/schema.d.ts +6 -3
- package/dist/spec/db/schema.d.ts.map +1 -1
- package/dist/spec/db/schema.js +36 -4
- package/dist/spec/db/schema.js.map +1 -1
- package/dist/spec/db/schema.sql +11 -1
- package/dist/spec/evolve/logic-checker.d.ts +2 -2
- package/dist/spec/evolve/logic-checker.d.ts.map +1 -1
- package/dist/spec/evolve/logic-checker.js +3 -27
- package/dist/spec/evolve/logic-checker.js.map +1 -1
- package/dist/spec/evolve/pipeline.d.ts +21 -19
- package/dist/spec/evolve/pipeline.d.ts.map +1 -1
- package/dist/spec/evolve/pipeline.js +284 -31
- package/dist/spec/evolve/pipeline.js.map +1 -1
- package/dist/spec/evolve/spec-rewriter.d.ts +2 -2
- package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -1
- package/dist/spec/evolve/spec-rewriter.js +7 -31
- package/dist/spec/evolve/spec-rewriter.js.map +1 -1
- package/dist/spec/graph/queries.d.ts +97 -0
- package/dist/spec/graph/queries.d.ts.map +1 -1
- package/dist/spec/graph/queries.js +225 -0
- package/dist/spec/graph/queries.js.map +1 -1
- package/dist/spec/llm/client.d.ts +29 -0
- package/dist/spec/llm/client.d.ts.map +1 -0
- package/dist/spec/llm/client.js +123 -0
- package/dist/spec/llm/client.js.map +1 -0
- package/dist/spec/llm/index.d.ts +3 -0
- package/dist/spec/llm/index.d.ts.map +1 -0
- package/dist/spec/llm/index.js +11 -0
- package/dist/spec/llm/index.js.map +1 -0
- package/dist/spec/llm/prompts.d.ts +13 -0
- package/dist/spec/llm/prompts.d.ts.map +1 -0
- package/dist/spec/llm/prompts.js +75 -0
- package/dist/spec/llm/prompts.js.map +1 -0
- package/dist/spec/mining/git-scanner.d.ts +12 -0
- package/dist/spec/mining/git-scanner.d.ts.map +1 -1
- package/dist/spec/mining/git-scanner.js +41 -0
- package/dist/spec/mining/git-scanner.js.map +1 -1
- package/dist/spec/mining/pipeline.d.ts.map +1 -1
- package/dist/spec/mining/pipeline.js +14 -1
- package/dist/spec/mining/pipeline.js.map +1 -1
- package/dist/spec/utils.d.ts +2 -1
- package/dist/spec/utils.d.ts.map +1 -1
- package/dist/spec/utils.js +3 -1
- package/dist/spec/utils.js.map +1 -1
- package/dist/sync/git-hooks.d.ts.map +1 -1
- package/dist/sync/git-hooks.js +2 -0
- package/dist/sync/git-hooks.js.map +1 -1
- package/dist/sync/watcher.d.ts +10 -5
- package/dist/sync/watcher.d.ts.map +1 -1
- package/dist/sync/watcher.js +51 -14
- package/dist/sync/watcher.js.map +1 -1
- package/dist/sync/worktree.d.ts +9 -0
- package/dist/sync/worktree.d.ts.map +1 -1
- package/dist/sync/worktree.js +45 -0
- package/dist/sync/worktree.js.map +1 -1
- package/dist/types.d.ts +25 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -1
- package/dist/ui/shimmer-progress.d.ts +2 -0
- package/dist/ui/shimmer-progress.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.js +19 -2
- package/dist/ui/shimmer-progress.js.map +1 -1
- package/dist/upgrade/index.d.ts +32 -0
- package/dist/upgrade/index.d.ts.map +1 -1
- package/dist/upgrade/index.js +163 -15
- package/dist/upgrade/index.js.map +1 -1
- package/dist/upgrade/remove-binary.d.ts +87 -0
- package/dist/upgrade/remove-binary.d.ts.map +1 -0
- package/dist/upgrade/remove-binary.js +289 -0
- package/dist/upgrade/remove-binary.js.map +1 -0
- package/dist/upgrade/update-check.d.ts +92 -0
- package/dist/upgrade/update-check.d.ts.map +1 -0
- package/dist/upgrade/update-check.js +258 -0
- package/dist/upgrade/update-check.js.map +1 -0
- package/package.json +4 -4
- package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -0
- package/scripts/agent-eval/repro-daemon-clients.mjs +125 -0
- package/scripts/agent-eval/run-all.sh +6 -0
- package/scripts/build-bundle.sh +5 -0
- package/scripts/exp_boundary_eval/README.md +247 -0
- package/scripts/exp_boundary_eval/_test_mcp_chain.py +78 -0
- package/scripts/exp_boundary_eval/_test_stdin.py +8 -0
- package/scripts/exp_boundary_eval/_utils.py +1116 -0
- package/scripts/exp_boundary_eval/analyze.py +1313 -0
- package/scripts/exp_boundary_eval/deveco_arm.py +519 -0
- package/scripts/exp_boundary_eval/run_all.py +378 -0
- package/scripts/exp_boundary_eval/run_one.py +165 -0
- package/scripts/exp_boundary_eval/run_session.py +158 -0
- package/scripts/exp_boundary_eval/setup.py +120 -0
- package/scripts/exp_boundary_eval/win_mcp_launcher.py +73 -0
- package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +36 -0
- package/scripts/exp_boundary_eval/win_node_launcher.py +24 -0
- package/scripts/npm-shim.js +32 -3
- package/scripts/ohos-sdk-publish.mjs +133 -0
- package/scripts/qa_eval/README.md +0 -407
- package/scripts/qa_eval/_test_deveco_probe.py +0 -41
- package/scripts/qa_eval/agent_runner.py +0 -526
- package/scripts/qa_eval/data/.gitignore +0 -4
- package/scripts/qa_eval/data/test-set.jsonl +0 -2
- package/scripts/qa_eval/eval_metrics.py +0 -274
- package/scripts/qa_eval/external_agent.py +0 -976
- package/scripts/qa_eval/llm_config.py +0 -92
- package/scripts/qa_eval/memory_monitor.py +0 -132
- package/scripts/qa_eval/my_answer_accuracy.py +0 -187
- package/scripts/qa_eval/requirements.txt +0 -2
- package/scripts/qa_eval/run_pipeline.py +0 -804
- package/scripts/qa_eval/stats_efficiency.py +0 -279
- package/scripts/qa_eval/stats_scores.py +0 -207
package/dist/db/queries.js
CHANGED
|
@@ -4,12 +4,49 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Prepared statements for CRUD operations on the knowledge graph.
|
|
6
6
|
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
7
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
41
|
exports.QueryBuilder = void 0;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
9
44
|
const utils_1 = require("../utils");
|
|
10
45
|
const query_utils_1 = require("../search/query-utils");
|
|
11
46
|
const query_parser_1 = require("../search/query-parser");
|
|
12
47
|
const generated_detection_1 = require("../extraction/generated-detection");
|
|
48
|
+
const arkts_1 = require("../extraction/languages/arkts");
|
|
49
|
+
const identifier_segments_1 = require("../search/identifier-segments");
|
|
13
50
|
/**
|
|
14
51
|
* Path-only heuristic for files that should not be candidates for
|
|
15
52
|
* "dominant file" detection: test/spec files and tool-generated files.
|
|
@@ -33,6 +70,14 @@ function isLowValueFile(filePath) {
|
|
|
33
70
|
(0, generated_detection_1.isGeneratedFile)(filePath));
|
|
34
71
|
}
|
|
35
72
|
const SQLITE_PARAM_CHUNK_SIZE = 500;
|
|
73
|
+
/**
|
|
74
|
+
* Last segment of a (possibly dotted/qualified) reference name — the part a
|
|
75
|
+
* new symbol's plain node name could match: 'util.greet' → 'greet'.
|
|
76
|
+
*/
|
|
77
|
+
function referenceNameTail(referenceName) {
|
|
78
|
+
const idx = Math.max(referenceName.lastIndexOf('.'), referenceName.lastIndexOf(':'));
|
|
79
|
+
return idx >= 0 ? referenceName.slice(idx + 1) : referenceName;
|
|
80
|
+
}
|
|
36
81
|
/**
|
|
37
82
|
* Convert database row to Node object
|
|
38
83
|
*/
|
|
@@ -100,14 +145,54 @@ class QueryBuilder {
|
|
|
100
145
|
// whole project, not a symbol, so it carries no discriminative signal (#720).
|
|
101
146
|
// Set once by the HomeGraph instance; empty by default (no down-weighting).
|
|
102
147
|
projectNameTokens = new Set();
|
|
148
|
+
segmentedNames = new Set();
|
|
149
|
+
static MAX_SEGMENTED_NAMES = 65536;
|
|
103
150
|
// Node cache for frequently accessed nodes (LRU-style, max 1000 entries)
|
|
104
151
|
nodeCache = new Map();
|
|
105
152
|
maxCacheSize = 1000;
|
|
153
|
+
/** Attached prebuilt OHOS API db (see arkts.ts). */
|
|
154
|
+
ohosApiDbPath = null;
|
|
106
155
|
// Prepared statements (lazily initialized)
|
|
107
156
|
stmts = {};
|
|
108
157
|
constructor(db) {
|
|
109
158
|
this.db = db;
|
|
110
159
|
}
|
|
160
|
+
/** Attach a versioned OHOS API db for federated symbol lookup. */
|
|
161
|
+
attachOhosApiDb(dbPath) {
|
|
162
|
+
if (dbPath === this.ohosApiDbPath)
|
|
163
|
+
return;
|
|
164
|
+
if (this.ohosApiDbPath) {
|
|
165
|
+
try {
|
|
166
|
+
this.db.exec('DETACH DATABASE ohos_api');
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
/* already detached */
|
|
170
|
+
}
|
|
171
|
+
this.ohosApiDbPath = null;
|
|
172
|
+
}
|
|
173
|
+
if (!dbPath)
|
|
174
|
+
return;
|
|
175
|
+
const resolved = path.resolve(dbPath);
|
|
176
|
+
if (!fs.existsSync(resolved)) {
|
|
177
|
+
throw new Error(`OHOS API db not found: ${resolved}`);
|
|
178
|
+
}
|
|
179
|
+
const escaped = resolved.replace(/'/g, "''");
|
|
180
|
+
this.db.exec(`ATTACH DATABASE '${escaped}' AS ohos_api`);
|
|
181
|
+
this.ohosApiDbPath = resolved;
|
|
182
|
+
this.stmts = {};
|
|
183
|
+
this.nodeCache.clear();
|
|
184
|
+
}
|
|
185
|
+
getOhosApiDbPath() {
|
|
186
|
+
return this.ohosApiDbPath;
|
|
187
|
+
}
|
|
188
|
+
hasOhosApiAttached() {
|
|
189
|
+
return this.ohosApiDbPath != null;
|
|
190
|
+
}
|
|
191
|
+
mapOhosApiNodeRow(row) {
|
|
192
|
+
const node = rowToNode(row);
|
|
193
|
+
node.filePath = (0, arkts_1.markOhosApiFilePath)(node.filePath);
|
|
194
|
+
return node;
|
|
195
|
+
}
|
|
111
196
|
/** Set the normalized project-name tokens used to down-weight non-discriminative
|
|
112
197
|
* query words in path scoring (#720). Called once when the project opens. */
|
|
113
198
|
setProjectNameTokens(tokens) {
|
|
@@ -180,6 +265,10 @@ class QueryBuilder {
|
|
|
180
265
|
returnType: node.returnType ?? null,
|
|
181
266
|
updatedAt: node.updatedAt ?? Date.now(),
|
|
182
267
|
});
|
|
268
|
+
// Segment vocabulary rides the same write path so it never drifts ahead of
|
|
269
|
+
// the nodes it describes. File/import nodes are excluded (#1144).
|
|
270
|
+
if (this.isSegmentableKind(node.kind))
|
|
271
|
+
this.insertNameSegments(node.name);
|
|
183
272
|
}
|
|
184
273
|
/**
|
|
185
274
|
* Insert multiple nodes in a transaction
|
|
@@ -251,6 +340,9 @@ class QueryBuilder {
|
|
|
251
340
|
returnType: node.returnType ?? null,
|
|
252
341
|
updatedAt: node.updatedAt ?? Date.now(),
|
|
253
342
|
});
|
|
343
|
+
// Framework post-extract renames must reach the segment vocabulary (#1141).
|
|
344
|
+
if (this.isSegmentableKind(node.kind))
|
|
345
|
+
this.insertNameSegments(node.name);
|
|
254
346
|
}
|
|
255
347
|
/**
|
|
256
348
|
* Delete a node by ID
|
|
@@ -278,6 +370,104 @@ class QueryBuilder {
|
|
|
278
370
|
}
|
|
279
371
|
this.stmts.deleteNodesByFile.run(filePath);
|
|
280
372
|
}
|
|
373
|
+
/** Which node kinds contribute their name to the segment vocabulary. */
|
|
374
|
+
isSegmentableKind(kind) {
|
|
375
|
+
return kind !== 'file' && kind !== 'import';
|
|
376
|
+
}
|
|
377
|
+
/** Write `name`'s segments into name_segment_vocab (idempotent). */
|
|
378
|
+
insertNameSegments(name) {
|
|
379
|
+
if (this.segmentedNames.has(name))
|
|
380
|
+
return;
|
|
381
|
+
if (this.segmentedNames.size >= QueryBuilder.MAX_SEGMENTED_NAMES)
|
|
382
|
+
this.segmentedNames.clear();
|
|
383
|
+
this.segmentedNames.add(name);
|
|
384
|
+
if (!this.stmts.insertNameSegment) {
|
|
385
|
+
this.stmts.insertNameSegment = this.db.prepare('INSERT OR IGNORE INTO name_segment_vocab (segment, name) VALUES (?, ?)');
|
|
386
|
+
}
|
|
387
|
+
for (const segment of (0, identifier_segments_1.splitIdentifierSegments)(name)) {
|
|
388
|
+
this.stmts.insertNameSegment.run(segment, name);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
// ===========================================================================
|
|
392
|
+
// Name-segment vocabulary (prompt-hook graph-derived gate)
|
|
393
|
+
// ===========================================================================
|
|
394
|
+
/** Wipe the segment vocabulary. A full index calls this at its start; the
|
|
395
|
+
* node write path repopulates it as files (re-)index, so the end state is
|
|
396
|
+
* exactly the current names with no orphan rows. */
|
|
397
|
+
clearNameSegmentVocab() {
|
|
398
|
+
this.db.exec('DELETE FROM name_segment_vocab');
|
|
399
|
+
this.segmentedNames.clear();
|
|
400
|
+
}
|
|
401
|
+
/** True when the vocab has no rows — an index built before the table existed.
|
|
402
|
+
* `sync` uses this to heal such databases (see rebuildNameSegmentVocabFrom). */
|
|
403
|
+
isNameSegmentVocabEmpty() {
|
|
404
|
+
const row = this.db.prepare('SELECT 1 FROM name_segment_vocab LIMIT 1').get();
|
|
405
|
+
return row === undefined;
|
|
406
|
+
}
|
|
407
|
+
/** One page of distinct segmentable node names, for batched vocab rebuilds
|
|
408
|
+
* (file basenames and import specifiers are excluded from the vocab — see
|
|
409
|
+
* insertNode). */
|
|
410
|
+
getDistinctNodeNames(limit, offset) {
|
|
411
|
+
const rows = this.db
|
|
412
|
+
.prepare("SELECT DISTINCT name FROM nodes WHERE kind NOT IN ('file', 'import') ORDER BY name LIMIT ? OFFSET ?")
|
|
413
|
+
.all(limit, offset);
|
|
414
|
+
return rows.map((r) => r.name);
|
|
415
|
+
}
|
|
416
|
+
/** Insert segments for a batch of names in one transaction (vocab heal path). */
|
|
417
|
+
insertNameSegmentsBatch(names) {
|
|
418
|
+
this.db.transaction(() => {
|
|
419
|
+
for (const name of names)
|
|
420
|
+
this.insertNameSegments(name);
|
|
421
|
+
})();
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Names whose segments cover at least `minWords` distinct PROMPT WORDS —
|
|
425
|
+
* the co-occurrence probe behind the prompt hook's medium tier: the words
|
|
426
|
+
* "state" and "machine" both being segments of `OrderStateMachine` is strong
|
|
427
|
+
* evidence the prompt names that symbol in prose. Ordered by coverage.
|
|
428
|
+
*
|
|
429
|
+
* Takes (segment variant → original word) pairs and folds variants back to
|
|
430
|
+
* their word INSIDE the SQL: a name matching both `service` and `services`
|
|
431
|
+
* counts ONE word, not two. Counting raw variants let plural-variant pairs
|
|
432
|
+
* of a single word tie with genuine two-word matches and — because ORDER
|
|
433
|
+
* BY/LIMIT run here, before any JS-side re-check — crowd a real match past
|
|
434
|
+
* the LIMIT on vocab-heavy repos (#1146).
|
|
435
|
+
*/
|
|
436
|
+
getSegmentCoOccurrence(variants, minWords, limit) {
|
|
437
|
+
if (variants.length === 0)
|
|
438
|
+
return [];
|
|
439
|
+
const placeholders = variants.map(() => '?').join(', ');
|
|
440
|
+
const whens = variants.map(() => 'WHEN ? THEN ?').join(' ');
|
|
441
|
+
const rows = this.db
|
|
442
|
+
.prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
|
|
443
|
+
FROM name_segment_vocab
|
|
444
|
+
WHERE segment IN (${placeholders})
|
|
445
|
+
GROUP BY name
|
|
446
|
+
HAVING matches >= ?
|
|
447
|
+
ORDER BY matches DESC, length(name) ASC
|
|
448
|
+
LIMIT ?`)
|
|
449
|
+
.all(...variants.flatMap((v) => [v.segment, v.word]), ...variants.map((v) => v.segment), minWords, limit);
|
|
450
|
+
return rows;
|
|
451
|
+
}
|
|
452
|
+
/** How many distinct names each segment appears in — the rarity signal that
|
|
453
|
+
* separates a discriminative word ("checkout") from a ubiquitous one ("state"). */
|
|
454
|
+
getSegmentNameCounts(segments) {
|
|
455
|
+
if (segments.length === 0)
|
|
456
|
+
return new Map();
|
|
457
|
+
const placeholders = segments.map(() => '?').join(', ');
|
|
458
|
+
const rows = this.db
|
|
459
|
+
.prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
|
|
460
|
+
WHERE segment IN (${placeholders}) GROUP BY segment`)
|
|
461
|
+
.all(...segments);
|
|
462
|
+
return new Map(rows.map((r) => [r.segment, r.n]));
|
|
463
|
+
}
|
|
464
|
+
/** Names containing the given segment (rare-single-word tier). */
|
|
465
|
+
getNamesForSegment(segment, limit) {
|
|
466
|
+
const rows = this.db
|
|
467
|
+
.prepare('SELECT name FROM name_segment_vocab WHERE segment = ? ORDER BY length(name) ASC LIMIT ?')
|
|
468
|
+
.all(segment, limit);
|
|
469
|
+
return rows.map((r) => r.name);
|
|
470
|
+
}
|
|
281
471
|
/**
|
|
282
472
|
* Get a node by ID
|
|
283
473
|
*/
|
|
@@ -571,6 +761,33 @@ class QueryBuilder {
|
|
|
571
761
|
yield rowToNode(row);
|
|
572
762
|
}
|
|
573
763
|
}
|
|
764
|
+
/**
|
|
765
|
+
* Stream nodes of a language whose `decorators` JSON array contains a
|
|
766
|
+
* quoted decorator name. LIKE is a substring filter (a decorator name can
|
|
767
|
+
* appear as a substring of another), so callers must still exact-check
|
|
768
|
+
* `node.decorators.includes(decorator)`. Exists so the kotlin expect/actual
|
|
769
|
+
* synthesizer never materializes the whole node table the way
|
|
770
|
+
* `getAllNodes().filter(...)` did — that array alone OOM'd Node's default
|
|
771
|
+
* heap on a 2M-node graph (#1212).
|
|
772
|
+
*/
|
|
773
|
+
*iterateNodesByLanguageWithDecorator(language, decorator) {
|
|
774
|
+
// Fresh statement per call — an iterator holds an open cursor (see
|
|
775
|
+
// iterateNodesByKind).
|
|
776
|
+
const stmt = this.db.prepare("SELECT * FROM nodes WHERE language = ? AND decorators LIKE '%' || ? || '%'");
|
|
777
|
+
for (const row of stmt.iterate(language, `"${decorator}"`)) {
|
|
778
|
+
yield rowToNode(row);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Distinct languages present in the files table. One indexed aggregate —
|
|
783
|
+
* lets the dynamic-edge synthesizers skip passes for languages the project
|
|
784
|
+
* doesn't contain at all (a Kotlin pass has no work on a pure-C repo), so
|
|
785
|
+
* their cost is zero rather than a full-graph scan that finds nothing (#1212).
|
|
786
|
+
*/
|
|
787
|
+
getDistinctFileLanguages() {
|
|
788
|
+
const rows = this.db.prepare('SELECT DISTINCT language FROM files').all();
|
|
789
|
+
return new Set(rows.map((r) => r.language));
|
|
790
|
+
}
|
|
574
791
|
/**
|
|
575
792
|
* Get all nodes in the database
|
|
576
793
|
*/
|
|
@@ -586,7 +803,15 @@ class QueryBuilder {
|
|
|
586
803
|
this.stmts.getNodesByName = this.db.prepare('SELECT * FROM nodes WHERE name = ?');
|
|
587
804
|
}
|
|
588
805
|
const rows = this.stmts.getNodesByName.all(name);
|
|
589
|
-
|
|
806
|
+
const main = rows.map(rowToNode);
|
|
807
|
+
if (!this.hasOhosApiAttached())
|
|
808
|
+
return main;
|
|
809
|
+
const apiRows = this.db
|
|
810
|
+
.prepare('SELECT * FROM ohos_api.nodes WHERE name = ?')
|
|
811
|
+
.all(name);
|
|
812
|
+
const seen = new Set(main.map((n) => n.id));
|
|
813
|
+
const api = apiRows.map((r) => this.mapOhosApiNodeRow(r)).filter((n) => !seen.has(n.id));
|
|
814
|
+
return [...main, ...api];
|
|
590
815
|
}
|
|
591
816
|
/**
|
|
592
817
|
* Get nodes by exact qualified name match (uses idx_nodes_qualified_name index)
|
|
@@ -722,8 +947,44 @@ class QueryBuilder {
|
|
|
722
947
|
return lowered.some((n) => nm.includes(n));
|
|
723
948
|
});
|
|
724
949
|
}
|
|
950
|
+
if (this.hasOhosApiAttached() && text.length >= 2) {
|
|
951
|
+
results = this.mergeOhosApiTextSearch(text, { kinds, languages, limit }, results);
|
|
952
|
+
}
|
|
725
953
|
return results;
|
|
726
954
|
}
|
|
955
|
+
mergeOhosApiTextSearch(text, options, existing) {
|
|
956
|
+
const { kinds, languages, limit = 100 } = options;
|
|
957
|
+
const seen = new Set(existing.map((r) => r.node.id));
|
|
958
|
+
const merged = [...existing];
|
|
959
|
+
const apiLimit = Math.min(20, Math.max(5, Math.floor(limit / 4)));
|
|
960
|
+
let sql = `
|
|
961
|
+
SELECT nodes.*, 0.9 as score
|
|
962
|
+
FROM ohos_api.nodes
|
|
963
|
+
WHERE (name LIKE ? OR qualified_name LIKE ?)
|
|
964
|
+
`;
|
|
965
|
+
const pattern = `%${text}%`;
|
|
966
|
+
const params = [pattern, pattern];
|
|
967
|
+
if (kinds && kinds.length > 0) {
|
|
968
|
+
sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
|
|
969
|
+
params.push(...kinds);
|
|
970
|
+
}
|
|
971
|
+
if (languages && languages.length > 0) {
|
|
972
|
+
sql += ` AND language IN (${languages.map(() => '?').join(',')})`;
|
|
973
|
+
params.push(...languages);
|
|
974
|
+
}
|
|
975
|
+
sql += ' LIMIT ?';
|
|
976
|
+
params.push(apiLimit);
|
|
977
|
+
const rows = this.db.prepare(sql).all(...params);
|
|
978
|
+
for (const row of rows) {
|
|
979
|
+
const node = this.mapOhosApiNodeRow(row);
|
|
980
|
+
if (seen.has(node.id))
|
|
981
|
+
continue;
|
|
982
|
+
seen.add(node.id);
|
|
983
|
+
merged.push({ node, score: row.score });
|
|
984
|
+
}
|
|
985
|
+
merged.sort((a, b) => b.score - a.score);
|
|
986
|
+
return merged.slice(0, limit);
|
|
987
|
+
}
|
|
727
988
|
/**
|
|
728
989
|
* Match-everything path used when the user supplied only field
|
|
729
990
|
* filters (`kind:function lang:typescript`) with no text. Returns
|
|
@@ -994,6 +1255,32 @@ class QueryBuilder {
|
|
|
994
1255
|
seenIds.add(r.node.id);
|
|
995
1256
|
allResults.push(r);
|
|
996
1257
|
}
|
|
1258
|
+
if (this.hasOhosApiAttached()) {
|
|
1259
|
+
let apiSql = `
|
|
1260
|
+
SELECT nodes.*, 0.95 as score
|
|
1261
|
+
FROM ohos_api.nodes
|
|
1262
|
+
WHERE name COLLATE NOCASE = ?
|
|
1263
|
+
`;
|
|
1264
|
+
const apiParams = [name];
|
|
1265
|
+
if (kinds && kinds.length > 0) {
|
|
1266
|
+
apiSql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
|
|
1267
|
+
apiParams.push(...kinds);
|
|
1268
|
+
}
|
|
1269
|
+
if (languages && languages.length > 0) {
|
|
1270
|
+
apiSql += ` AND language IN (${languages.map(() => '?').join(',')})`;
|
|
1271
|
+
apiParams.push(...languages);
|
|
1272
|
+
}
|
|
1273
|
+
apiSql += ' LIMIT ?';
|
|
1274
|
+
apiParams.push(perNameLimit);
|
|
1275
|
+
const apiRows = this.db.prepare(apiSql).all(...apiParams);
|
|
1276
|
+
for (const row of apiRows) {
|
|
1277
|
+
const node = this.mapOhosApiNodeRow(row);
|
|
1278
|
+
if (seenIds.has(node.id))
|
|
1279
|
+
continue;
|
|
1280
|
+
seenIds.add(node.id);
|
|
1281
|
+
allResults.push({ node, score: row.score });
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
997
1284
|
}
|
|
998
1285
|
// Sort all results by score so co-located results bubble up
|
|
999
1286
|
allResults.sort((a, b) => b.score - a.score);
|
|
@@ -1115,12 +1402,23 @@ class QueryBuilder {
|
|
|
1115
1402
|
/**
|
|
1116
1403
|
* Get incoming edges to a node
|
|
1117
1404
|
*/
|
|
1118
|
-
getIncomingEdges(targetId, kinds) {
|
|
1405
|
+
getIncomingEdges(targetId, kinds, limit) {
|
|
1406
|
+
const cap = typeof limit === 'number' && Number.isFinite(limit)
|
|
1407
|
+
? Math.max(1, Math.min(Math.floor(limit), 2000))
|
|
1408
|
+
: undefined;
|
|
1119
1409
|
if (kinds && kinds.length > 0) {
|
|
1120
|
-
|
|
1410
|
+
let sql = `SELECT * FROM edges WHERE target = ? AND kind IN (${kinds.map(() => '?').join(',')})`;
|
|
1411
|
+
if (cap !== undefined)
|
|
1412
|
+
sql += ` LIMIT ${cap}`;
|
|
1121
1413
|
const rows = this.db.prepare(sql).all(targetId, ...kinds);
|
|
1122
1414
|
return rows.map(rowToEdge);
|
|
1123
1415
|
}
|
|
1416
|
+
if (cap !== undefined) {
|
|
1417
|
+
const rows = this.db
|
|
1418
|
+
.prepare('SELECT * FROM edges WHERE target = ? LIMIT ?')
|
|
1419
|
+
.all(targetId, cap);
|
|
1420
|
+
return rows.map(rowToEdge);
|
|
1421
|
+
}
|
|
1124
1422
|
if (!this.stmts.getEdgesByTarget) {
|
|
1125
1423
|
this.stmts.getEdgesByTarget = this.db.prepare('SELECT * FROM edges WHERE target = ?');
|
|
1126
1424
|
}
|
|
@@ -1199,7 +1497,8 @@ class QueryBuilder {
|
|
|
1199
1497
|
* {@link getDependentFilePaths}: all kinds except `contains`.
|
|
1200
1498
|
*/
|
|
1201
1499
|
getCrossFileIncomingEdgesWithTarget(filePath) {
|
|
1202
|
-
const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind
|
|
1500
|
+
const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
|
|
1501
|
+
src.file_path AS source_file_path, src.language AS source_language
|
|
1203
1502
|
FROM edges e
|
|
1204
1503
|
JOIN nodes tgt ON tgt.id = e.target
|
|
1205
1504
|
JOIN nodes src ON src.id = e.source
|
|
@@ -1211,6 +1510,8 @@ class QueryBuilder {
|
|
|
1211
1510
|
...rowToEdge(row),
|
|
1212
1511
|
targetName: row.target_name,
|
|
1213
1512
|
targetKind: row.target_kind,
|
|
1513
|
+
sourceFilePath: row.source_file_path,
|
|
1514
|
+
sourceLanguage: row.source_language,
|
|
1214
1515
|
}));
|
|
1215
1516
|
}
|
|
1216
1517
|
/**
|
|
@@ -1397,7 +1698,7 @@ class QueryBuilder {
|
|
|
1397
1698
|
*/
|
|
1398
1699
|
getUnresolvedReferencesCount() {
|
|
1399
1700
|
if (!this.stmts.getUnresolvedCount) {
|
|
1400
|
-
this.stmts.getUnresolvedCount = this.db.prepare(
|
|
1701
|
+
this.stmts.getUnresolvedCount = this.db.prepare("SELECT COUNT(*) as count FROM unresolved_refs WHERE status = 'pending'");
|
|
1401
1702
|
}
|
|
1402
1703
|
const row = this.stmts.getUnresolvedCount.get();
|
|
1403
1704
|
return row.count;
|
|
@@ -1408,7 +1709,7 @@ class QueryBuilder {
|
|
|
1408
1709
|
*/
|
|
1409
1710
|
getUnresolvedReferencesBatch(offset, limit) {
|
|
1410
1711
|
if (!this.stmts.getUnresolvedBatch) {
|
|
1411
|
-
this.stmts.getUnresolvedBatch = this.db.prepare(
|
|
1712
|
+
this.stmts.getUnresolvedBatch = this.db.prepare("SELECT * FROM unresolved_refs WHERE status = 'pending' LIMIT ? OFFSET ?");
|
|
1412
1713
|
}
|
|
1413
1714
|
const rows = this.stmts.getUnresolvedBatch.all(limit, offset);
|
|
1414
1715
|
return rows.map((row) => ({
|
|
@@ -1442,6 +1743,135 @@ class QueryBuilder {
|
|
|
1442
1743
|
const rows = this.stmts.getAllNodeNames.all();
|
|
1443
1744
|
return rows.map((r) => r.name);
|
|
1444
1745
|
}
|
|
1746
|
+
/**
|
|
1747
|
+
* Stream distinct node names one row at a time — for resolver cache warm-up
|
|
1748
|
+
* that needs to yield to the event loop mid-scan.
|
|
1749
|
+
*/
|
|
1750
|
+
*iterateNodeNames() {
|
|
1751
|
+
const stmt = this.db.prepare('SELECT DISTINCT name FROM nodes');
|
|
1752
|
+
for (const row of stmt.iterate()) {
|
|
1753
|
+
yield row.name;
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
/**
|
|
1757
|
+
* Park refs as status='failed' so drain loops skip them while sync can retry
|
|
1758
|
+
* when a later file change introduces a matching symbol.
|
|
1759
|
+
*/
|
|
1760
|
+
markReferencesFailed(refs) {
|
|
1761
|
+
if (refs.length === 0)
|
|
1762
|
+
return;
|
|
1763
|
+
const stmt = this.db.prepare("UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE from_node_id = ? AND reference_name = ? AND reference_kind = ?");
|
|
1764
|
+
const markMany = this.db.transaction((items) => {
|
|
1765
|
+
for (const ref of items) {
|
|
1766
|
+
stmt.run(referenceNameTail(ref.referenceName), ref.fromNodeId, ref.referenceName, ref.referenceKind);
|
|
1767
|
+
}
|
|
1768
|
+
});
|
|
1769
|
+
markMany(refs);
|
|
1770
|
+
}
|
|
1771
|
+
/**
|
|
1772
|
+
* Delete unresolved-ref rows by row id — the precise cleanup for refs a
|
|
1773
|
+
* resolution pass actually processed. The key-tuple variant above also
|
|
1774
|
+
* deletes SIBLING rows (same caller calling the same callee at other lines)
|
|
1775
|
+
* that a later batch hasn't attempted yet, so when a batch boundary split a
|
|
1776
|
+
* caller's same-named call sites, the later sites' edges were silently never
|
|
1777
|
+
* created (#1269).
|
|
1778
|
+
*/
|
|
1779
|
+
deleteReferencesByRowIds(rowIds) {
|
|
1780
|
+
if (rowIds.length === 0)
|
|
1781
|
+
return;
|
|
1782
|
+
for (let i = 0; i < rowIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1783
|
+
const chunk = rowIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1784
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
1785
|
+
this.db.prepare(`DELETE FROM unresolved_refs WHERE id IN (${placeholders})`).run(...chunk);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
/**
|
|
1789
|
+
* Park refs as status='failed' by row id — the precise counterpart of
|
|
1790
|
+
* markReferencesFailed, for the same reason as deleteReferencesByRowIds:
|
|
1791
|
+
* the key-tuple variant also flips same-key sibling rows in later batches
|
|
1792
|
+
* to 'failed' before they were ever attempted (#1269). Resolution outcome
|
|
1793
|
+
* can differ per call site (receiver-type inference reads the ref's line),
|
|
1794
|
+
* so a sibling must not inherit this row's failure.
|
|
1795
|
+
*/
|
|
1796
|
+
markReferencesFailedByRowIds(refs) {
|
|
1797
|
+
if (refs.length === 0)
|
|
1798
|
+
return;
|
|
1799
|
+
const stmt = this.db.prepare("UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE id = ?");
|
|
1800
|
+
const markMany = this.db.transaction((items) => {
|
|
1801
|
+
for (const ref of items) {
|
|
1802
|
+
stmt.run(referenceNameTail(ref.referenceName), ref.rowId);
|
|
1803
|
+
}
|
|
1804
|
+
});
|
|
1805
|
+
markMany(refs);
|
|
1806
|
+
}
|
|
1807
|
+
/**
|
|
1808
|
+
* Failed refs whose name tail matches one of the given symbol names — the
|
|
1809
|
+
* candidates a sync should retry after files carrying those names changed
|
|
1810
|
+
* (#1240). Names matching more than `perNameCeiling` failed refs are
|
|
1811
|
+
* skipped entirely: at that population a name is external/builtin noise
|
|
1812
|
+
* (`get`, `map`, …) that one new definition won't resolve — the same
|
|
1813
|
+
* rationale as resolution's AMBIGUOUS_NAME_CEILING (#999) — and retrying an
|
|
1814
|
+
* arbitrary subset would be both wasted work and incoherent coverage.
|
|
1815
|
+
*/
|
|
1816
|
+
getRetryableFailedReferences(names, perNameCeiling = 500) {
|
|
1817
|
+
if (names.length === 0)
|
|
1818
|
+
return [];
|
|
1819
|
+
// Pass 1: per-tail counts, chunked under the SQLite parameter limit.
|
|
1820
|
+
const retryNames = [];
|
|
1821
|
+
for (let i = 0; i < names.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1822
|
+
const chunk = names.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1823
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
1824
|
+
const counts = this.db
|
|
1825
|
+
.prepare(`SELECT name_tail, COUNT(*) as count FROM unresolved_refs WHERE status = 'failed' AND name_tail IN (${placeholders}) GROUP BY name_tail`)
|
|
1826
|
+
.all(...chunk);
|
|
1827
|
+
for (const row of counts) {
|
|
1828
|
+
if (row.count <= perNameCeiling)
|
|
1829
|
+
retryNames.push(row.name_tail);
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
if (retryNames.length === 0)
|
|
1833
|
+
return [];
|
|
1834
|
+
// Pass 2: load the surviving rows.
|
|
1835
|
+
const rows = [];
|
|
1836
|
+
for (let i = 0; i < retryNames.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1837
|
+
const chunk = retryNames.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1838
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
1839
|
+
const chunkRows = this.db
|
|
1840
|
+
.prepare(`SELECT * FROM unresolved_refs WHERE status = 'failed' AND name_tail IN (${placeholders})`)
|
|
1841
|
+
.all(...chunk);
|
|
1842
|
+
rows.push(...chunkRows);
|
|
1843
|
+
}
|
|
1844
|
+
return rows.map((row) => ({
|
|
1845
|
+
fromNodeId: row.from_node_id,
|
|
1846
|
+
referenceName: row.reference_name,
|
|
1847
|
+
referenceKind: row.reference_kind,
|
|
1848
|
+
line: row.line,
|
|
1849
|
+
column: row.col,
|
|
1850
|
+
candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
|
|
1851
|
+
filePath: row.file_path,
|
|
1852
|
+
language: row.language,
|
|
1853
|
+
rowId: row.id,
|
|
1854
|
+
}));
|
|
1855
|
+
}
|
|
1856
|
+
/**
|
|
1857
|
+
* Distinct node names present in the given files — the symbol names a sync
|
|
1858
|
+
* pass uses to look up retryable failed refs after those files changed.
|
|
1859
|
+
*/
|
|
1860
|
+
getNodeNamesByFiles(filePaths) {
|
|
1861
|
+
if (filePaths.length === 0)
|
|
1862
|
+
return [];
|
|
1863
|
+
const names = new Set();
|
|
1864
|
+
for (let i = 0; i < filePaths.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1865
|
+
const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1866
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
1867
|
+
const rows = this.db
|
|
1868
|
+
.prepare(`SELECT DISTINCT name FROM nodes WHERE file_path IN (${placeholders})`)
|
|
1869
|
+
.all(...chunk);
|
|
1870
|
+
for (const row of rows)
|
|
1871
|
+
names.add(row.name);
|
|
1872
|
+
}
|
|
1873
|
+
return [...names];
|
|
1874
|
+
}
|
|
1445
1875
|
/**
|
|
1446
1876
|
* Get unresolved references scoped to specific file paths.
|
|
1447
1877
|
* Uses the idx_unresolved_file_path index for efficient lookup.
|
|
@@ -1458,7 +1888,7 @@ class QueryBuilder {
|
|
|
1458
1888
|
const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1459
1889
|
const placeholders = chunk.map(() => '?').join(',');
|
|
1460
1890
|
const chunkRows = this.db
|
|
1461
|
-
.prepare(`SELECT * FROM unresolved_refs WHERE file_path IN (${placeholders})`)
|
|
1891
|
+
.prepare(`SELECT * FROM unresolved_refs WHERE status = 'pending' AND file_path IN (${placeholders})`)
|
|
1462
1892
|
.all(...chunk);
|
|
1463
1893
|
rows.push(...chunkRows);
|
|
1464
1894
|
}
|
|
@@ -1485,8 +1915,16 @@ class QueryBuilder {
|
|
|
1485
1915
|
deleteResolvedReferences(fromNodeIds) {
|
|
1486
1916
|
if (fromNodeIds.length === 0)
|
|
1487
1917
|
return;
|
|
1488
|
-
|
|
1489
|
-
this.
|
|
1918
|
+
// Chunk under SQLite's parameter limit, matching every other IN-list in
|
|
1919
|
+
// this file. The internal resolution path uses deleteSpecificResolvedReferences
|
|
1920
|
+
// instead, but QueryBuilder is part of the public API, so a library consumer
|
|
1921
|
+
// passing more ids than SQLITE_MAX_VARIABLE_NUMBER (32766 on the bundled
|
|
1922
|
+
// node:sqlite) would otherwise hit "too many SQL variables". (#540, #1001)
|
|
1923
|
+
for (let i = 0; i < fromNodeIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1924
|
+
const chunk = fromNodeIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1925
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
1926
|
+
this.db.prepare(`DELETE FROM unresolved_refs WHERE from_node_id IN (${placeholders})`).run(...chunk);
|
|
1927
|
+
}
|
|
1490
1928
|
}
|
|
1491
1929
|
/**
|
|
1492
1930
|
* Delete specific resolved references by (fromNodeId, referenceName, referenceKind) tuples.
|
|
@@ -1588,12 +2026,38 @@ class QueryBuilder {
|
|
|
1588
2026
|
}
|
|
1589
2027
|
return result;
|
|
1590
2028
|
}
|
|
2029
|
+
// ===========================================================================
|
|
2030
|
+
// MCP Query Cache
|
|
2031
|
+
// ===========================================================================
|
|
2032
|
+
clearMcpQueryCache() {
|
|
2033
|
+
this.db.exec('DELETE FROM mcp_query_cache');
|
|
2034
|
+
}
|
|
2035
|
+
getMcpQueryCache(cacheKey) {
|
|
2036
|
+
const row = this.db
|
|
2037
|
+
.prepare('SELECT tool, response FROM mcp_query_cache WHERE cache_key = ?')
|
|
2038
|
+
.get(cacheKey);
|
|
2039
|
+
return row ?? null;
|
|
2040
|
+
}
|
|
2041
|
+
/** All cache keys — used to warm the in-memory key index after daemon restart. */
|
|
2042
|
+
listMcpQueryCacheKeys() {
|
|
2043
|
+
const rows = this.db
|
|
2044
|
+
.prepare('SELECT cache_key FROM mcp_query_cache')
|
|
2045
|
+
.all();
|
|
2046
|
+
return rows.map((r) => r.cache_key);
|
|
2047
|
+
}
|
|
2048
|
+
setMcpQueryCache(cacheKey, tool, response, createdAt) {
|
|
2049
|
+
this.db
|
|
2050
|
+
.prepare('INSERT INTO mcp_query_cache (cache_key, tool, response, created_at) VALUES (?, ?, ?, ?) ' +
|
|
2051
|
+
'ON CONFLICT(cache_key) DO UPDATE SET tool = excluded.tool, response = excluded.response, created_at = excluded.created_at')
|
|
2052
|
+
.run(cacheKey, tool, response, createdAt);
|
|
2053
|
+
}
|
|
1591
2054
|
/**
|
|
1592
2055
|
* Clear all data from the database
|
|
1593
2056
|
*/
|
|
1594
2057
|
clear() {
|
|
1595
2058
|
this.nodeCache.clear();
|
|
1596
2059
|
this.db.transaction(() => {
|
|
2060
|
+
this.db.exec('DELETE FROM mcp_query_cache');
|
|
1597
2061
|
this.db.exec('DELETE FROM unresolved_refs');
|
|
1598
2062
|
this.db.exec('DELETE FROM edges');
|
|
1599
2063
|
this.db.exec('DELETE FROM nodes');
|