homegraph 1.2.0 → 1.5.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/README.md +48 -11
- package/dist/bin/homegraph.js +298 -72
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +117 -11
- package/dist/context/index.js.map +1 -1
- package/dist/db/index.d.ts +207 -6
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +461 -20
- 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 +19 -1
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/queries.d.ts +157 -3
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +426 -9
- package/dist/db/queries.js.map +1 -1
- package/dist/db/schema.sql +32 -1
- package/dist/db/sqlite-adapter.d.ts +24 -17
- package/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/dist/db/sqlite-adapter.js +292 -36
- package/dist/db/sqlite-adapter.js.map +1 -1
- package/dist/db/wal-valve.d.ts +119 -0
- package/dist/db/wal-valve.d.ts.map +1 -0
- package/dist/db/wal-valve.js +290 -0
- package/dist/db/wal-valve.js.map +1 -0
- package/dist/directory.d.ts +9 -5
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +210 -19
- package/dist/directory.js.map +1 -1
- package/dist/extraction/arkts-batch-worker.js +3 -2
- package/dist/extraction/arkts-batch-worker.js.map +1 -1
- 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/default-ignore.d.ts +39 -0
- package/dist/extraction/default-ignore.d.ts.map +1 -0
- package/dist/extraction/default-ignore.js +221 -0
- package/dist/extraction/default-ignore.js.map +1 -0
- 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 +52 -14
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +521 -314
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts.d.ts +90 -6
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +1579 -128
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/extraction/languages/c-cpp.d.ts +42 -0
- package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/dist/extraction/languages/c-cpp.js +369 -4
- 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/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 +27 -1
- package/dist/extraction/parse-pool.d.ts.map +1 -1
- package/dist/extraction/parse-pool.js +75 -7
- package/dist/extraction/parse-pool.js.map +1 -1
- package/dist/extraction/parse-worker.js +9 -2
- package/dist/extraction/parse-worker.js.map +1 -1
- package/dist/extraction/store-worker.d.ts +20 -0
- package/dist/extraction/store-worker.d.ts.map +1 -0
- package/dist/extraction/store-worker.js +102 -0
- package/dist/extraction/store-worker.js.map +1 -0
- package/dist/extraction/store-writer.d.ts +48 -0
- package/dist/extraction/store-writer.d.ts.map +1 -0
- package/dist/extraction/store-writer.js +167 -0
- package/dist/extraction/store-writer.js.map +1 -0
- 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 +3 -1
- package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.d.ts +38 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.js +801 -10
- 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/extraction/wasm-runtime-flags.d.ts +14 -4
- package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -1
- package/dist/extraction/wasm-runtime-flags.js +55 -7
- package/dist/extraction/wasm-runtime-flags.js.map +1 -1
- package/dist/graph/traversal.d.ts.map +1 -1
- package/dist/graph/traversal.js +1 -1
- package/dist/graph/traversal.js.map +1 -1
- package/dist/index.d.ts +74 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +436 -55
- 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.d.ts +25 -3
- package/dist/mcp/daemon.d.ts.map +1 -1
- package/dist/mcp/daemon.js +62 -8
- 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 +4 -5
- package/dist/mcp/engine.d.ts.map +1 -1
- package/dist/mcp/engine.js +27 -1
- package/dist/mcp/engine.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +41 -6
- 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/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 +35 -4
- package/dist/mcp/query-cache.d.ts.map +1 -1
- package/dist/mcp/query-cache.js +89 -19
- package/dist/mcp/query-cache.js.map +1 -1
- package/dist/mcp/query-pool.d.ts +46 -12
- package/dist/mcp/query-pool.d.ts.map +1 -1
- package/dist/mcp/query-pool.js +100 -23
- package/dist/mcp/query-pool.js.map +1 -1
- package/dist/mcp/query-worker.d.ts +2 -2
- package/dist/mcp/query-worker.js +2 -2
- package/dist/mcp/server-instructions.d.ts +4 -27
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +39 -84
- 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 +104 -4
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +2432 -217
- 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 +38 -0
- package/dist/project-config.d.ts.map +1 -1
- package/dist/project-config.js +101 -2
- package/dist/project-config.js.map +1 -1
- package/dist/resolution/c-fnptr-synthesizer.d.ts +2 -1
- package/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
- package/dist/resolution/c-fnptr-synthesizer.js +178 -146
- package/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
- package/dist/resolution/callback-synthesizer.d.ts +54 -10
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/dist/resolution/callback-synthesizer.js +1299 -257
- package/dist/resolution/callback-synthesizer.js.map +1 -1
- package/dist/resolution/cooperative-yield.d.ts +10 -2
- package/dist/resolution/cooperative-yield.d.ts.map +1 -1
- package/dist/resolution/cooperative-yield.js +6 -4
- package/dist/resolution/cooperative-yield.js.map +1 -1
- 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/go.d.ts.map +1 -1
- package/dist/resolution/frameworks/go.js +29 -6
- package/dist/resolution/frameworks/go.js.map +1 -1
- 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 +9 -3
- package/dist/resolution/import-resolver.d.ts.map +1 -1
- package/dist/resolution/import-resolver.js +295 -11
- package/dist/resolution/import-resolver.js.map +1 -1
- package/dist/resolution/index.d.ts +146 -8
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +1089 -131
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/memory-budget.d.ts +48 -0
- package/dist/resolution/memory-budget.d.ts.map +1 -0
- package/dist/resolution/memory-budget.js +162 -0
- package/dist/resolution/memory-budget.js.map +1 -0
- package/dist/resolution/name-matcher.d.ts +12 -4
- package/dist/resolution/name-matcher.d.ts.map +1 -1
- package/dist/resolution/name-matcher.js +793 -130
- package/dist/resolution/name-matcher.js.map +1 -1
- package/dist/resolution/resolver-pool.d.ts +106 -0
- package/dist/resolution/resolver-pool.d.ts.map +1 -0
- package/dist/resolution/resolver-pool.js +344 -0
- package/dist/resolution/resolver-pool.js.map +1 -0
- package/dist/resolution/resolver-worker.d.ts +17 -0
- package/dist/resolution/resolver-worker.d.ts.map +1 -0
- package/dist/resolution/resolver-worker.js +141 -0
- package/dist/resolution/resolver-worker.js.map +1 -0
- 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 +32 -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/build/diff-parser.d.ts +55 -0
- package/dist/spec/build/diff-parser.d.ts.map +1 -0
- package/dist/spec/build/diff-parser.js +205 -0
- package/dist/spec/build/diff-parser.js.map +1 -0
- package/dist/spec/build/git-scanner.d.ts +93 -0
- package/dist/spec/build/git-scanner.d.ts.map +1 -0
- package/dist/spec/build/git-scanner.js +254 -0
- package/dist/spec/build/git-scanner.js.map +1 -0
- package/dist/spec/build/pipeline.d.ts +54 -0
- package/dist/spec/build/pipeline.d.ts.map +1 -0
- package/dist/spec/build/pipeline.js +170 -0
- package/dist/spec/build/pipeline.js.map +1 -0
- package/dist/spec/build/scan.d.ts +48 -0
- package/dist/spec/build/scan.d.ts.map +1 -0
- package/dist/spec/build/scan.js +89 -0
- package/dist/spec/build/scan.js.map +1 -0
- package/dist/spec/build/scope-resolver.d.ts +50 -0
- package/dist/spec/build/scope-resolver.d.ts.map +1 -0
- package/dist/spec/build/scope-resolver.js +105 -0
- package/dist/spec/build/scope-resolver.js.map +1 -0
- package/dist/spec/build/spec-extractor.d.ts +74 -0
- package/dist/spec/build/spec-extractor.d.ts.map +1 -0
- package/dist/spec/build/spec-extractor.js +344 -0
- package/dist/spec/build/spec-extractor.js.map +1 -0
- package/dist/spec/config.d.ts +35 -1
- package/dist/spec/config.d.ts.map +1 -1
- package/dist/spec/config.js +30 -5
- package/dist/spec/config.js.map +1 -1
- package/dist/spec/db/fts.d.ts.map +1 -1
- package/dist/spec/db/fts.js +19 -50
- package/dist/spec/db/fts.js.map +1 -1
- package/dist/spec/db/index.d.ts +5 -3
- package/dist/spec/db/index.d.ts.map +1 -1
- package/dist/spec/db/index.js +16 -1
- package/dist/spec/db/index.js.map +1 -1
- package/dist/spec/db/persist.d.ts +45 -0
- package/dist/spec/db/persist.d.ts.map +1 -0
- package/dist/spec/db/persist.js +66 -0
- package/dist/spec/db/persist.js.map +1 -0
- package/dist/spec/db/relations.d.ts +80 -1
- package/dist/spec/db/relations.d.ts.map +1 -1
- package/dist/spec/db/relations.js +175 -4
- package/dist/spec/db/relations.js.map +1 -1
- package/dist/spec/db/schema.d.ts +4 -0
- package/dist/spec/db/schema.d.ts.map +1 -1
- package/dist/spec/db/schema.js +4 -0
- package/dist/spec/db/schema.js.map +1 -1
- package/dist/spec/db/schema.sql +5 -1
- package/dist/spec/db/spec-node.d.ts +5 -0
- package/dist/spec/db/spec-node.d.ts.map +1 -1
- package/dist/spec/db/spec-node.js +11 -5
- package/dist/spec/db/spec-node.js.map +1 -1
- package/dist/spec/db/sql-utils.d.ts +11 -0
- package/dist/spec/db/sql-utils.d.ts.map +1 -0
- package/dist/spec/db/sql-utils.js +19 -0
- package/dist/spec/db/sql-utils.js.map +1 -0
- package/dist/spec/evolve/cluster-context.d.ts +30 -0
- package/dist/spec/evolve/cluster-context.d.ts.map +1 -0
- package/dist/spec/evolve/cluster-context.js +78 -0
- package/dist/spec/evolve/cluster-context.js.map +1 -0
- package/dist/spec/evolve/commit-spec-analyzer.d.ts +51 -0
- package/dist/spec/evolve/commit-spec-analyzer.d.ts.map +1 -0
- package/dist/spec/evolve/commit-spec-analyzer.js +88 -0
- package/dist/spec/evolve/commit-spec-analyzer.js.map +1 -0
- package/dist/spec/evolve/commit-spec-persister.d.ts +53 -0
- package/dist/spec/evolve/commit-spec-persister.d.ts.map +1 -0
- package/dist/spec/evolve/commit-spec-persister.js +93 -0
- package/dist/spec/evolve/commit-spec-persister.js.map +1 -0
- package/dist/spec/evolve/impact-locator.d.ts +23 -7
- package/dist/spec/evolve/impact-locator.d.ts.map +1 -1
- package/dist/spec/evolve/impact-locator.js +58 -14
- package/dist/spec/evolve/impact-locator.js.map +1 -1
- package/dist/spec/evolve/pipeline.d.ts +62 -25
- package/dist/spec/evolve/pipeline.d.ts.map +1 -1
- package/dist/spec/evolve/pipeline.js +436 -457
- package/dist/spec/evolve/pipeline.js.map +1 -1
- package/dist/spec/evolve/spec-rewriter.d.ts +13 -13
- package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -1
- package/dist/spec/evolve/spec-rewriter.js +45 -45
- package/dist/spec/evolve/spec-rewriter.js.map +1 -1
- package/dist/spec/git/commits.d.ts +85 -0
- package/dist/spec/git/commits.d.ts.map +1 -0
- package/dist/spec/git/commits.js +218 -0
- package/dist/spec/git/commits.js.map +1 -0
- package/dist/spec/git/exec.d.ts +13 -0
- package/dist/spec/git/exec.d.ts.map +1 -0
- package/dist/spec/git/exec.js +19 -0
- package/dist/spec/git/exec.js.map +1 -0
- package/dist/spec/git/index.d.ts +9 -0
- package/dist/spec/git/index.d.ts.map +1 -0
- package/dist/spec/git/index.js +22 -0
- package/dist/spec/git/index.js.map +1 -0
- package/dist/spec/git-utils.d.ts +8 -0
- package/dist/spec/git-utils.d.ts.map +1 -0
- package/dist/spec/git-utils.js +14 -0
- package/dist/spec/git-utils.js.map +1 -0
- package/dist/spec/graph/index.d.ts +8 -0
- package/dist/spec/graph/index.d.ts.map +1 -0
- package/dist/spec/graph/index.js +17 -0
- package/dist/spec/graph/index.js.map +1 -0
- package/dist/spec/graph/queries.d.ts +6 -35
- package/dist/spec/graph/queries.d.ts.map +1 -1
- package/dist/spec/graph/queries.js +71 -248
- package/dist/spec/graph/queries.js.map +1 -1
- package/dist/spec/llm/agent-client.d.ts +59 -0
- package/dist/spec/llm/agent-client.d.ts.map +1 -0
- package/dist/spec/llm/agent-client.js +213 -0
- package/dist/spec/llm/agent-client.js.map +1 -0
- package/dist/spec/llm/agents/claude-code.d.ts +32 -0
- package/dist/spec/llm/agents/claude-code.d.ts.map +1 -0
- package/dist/spec/llm/agents/claude-code.js +125 -0
- package/dist/spec/llm/agents/claude-code.js.map +1 -0
- package/dist/spec/llm/agents/codex.d.ts +32 -0
- package/dist/spec/llm/agents/codex.d.ts.map +1 -0
- package/dist/spec/llm/agents/codex.js +145 -0
- package/dist/spec/llm/agents/codex.js.map +1 -0
- package/dist/spec/llm/agents/detect-utils.d.ts +28 -0
- package/dist/spec/llm/agents/detect-utils.d.ts.map +1 -0
- package/dist/spec/llm/agents/detect-utils.js +91 -0
- package/dist/spec/llm/agents/detect-utils.js.map +1 -0
- package/dist/spec/llm/agents/deveco-code.d.ts +33 -0
- package/dist/spec/llm/agents/deveco-code.d.ts.map +1 -0
- package/dist/spec/llm/agents/deveco-code.js +165 -0
- package/dist/spec/llm/agents/deveco-code.js.map +1 -0
- package/dist/spec/llm/agents/index.d.ts +31 -0
- package/dist/spec/llm/agents/index.d.ts.map +1 -0
- package/dist/spec/llm/agents/index.js +65 -0
- package/dist/spec/llm/agents/index.js.map +1 -0
- package/dist/spec/llm/agents/types.d.ts +76 -0
- package/dist/spec/llm/agents/types.d.ts.map +1 -0
- package/dist/spec/llm/agents/types.js +15 -0
- package/dist/spec/llm/agents/types.js.map +1 -0
- package/dist/spec/llm/client.d.ts +31 -11
- package/dist/spec/llm/client.d.ts.map +1 -1
- package/dist/spec/llm/client.js +143 -81
- package/dist/spec/llm/client.js.map +1 -1
- package/dist/spec/llm/factory.d.ts +41 -0
- package/dist/spec/llm/factory.d.ts.map +1 -0
- package/dist/spec/llm/factory.js +80 -0
- package/dist/spec/llm/factory.js.map +1 -0
- package/dist/spec/llm/prompts.d.ts +24 -8
- package/dist/spec/llm/prompts.d.ts.map +1 -1
- package/dist/spec/llm/prompts.js +100 -50
- package/dist/spec/llm/prompts.js.map +1 -1
- package/dist/spec/llm/retry.d.ts +53 -0
- package/dist/spec/llm/retry.d.ts.map +1 -0
- package/dist/spec/llm/retry.js +153 -0
- package/dist/spec/llm/retry.js.map +1 -0
- package/dist/spec/mine/clusterer.d.ts +63 -0
- package/dist/spec/mine/clusterer.d.ts.map +1 -0
- package/dist/spec/mine/clusterer.js +904 -0
- package/dist/spec/mine/clusterer.js.map +1 -0
- package/dist/spec/mine/clustering/features.d.ts +38 -0
- package/dist/spec/mine/clustering/features.d.ts.map +1 -0
- package/dist/spec/mine/clustering/features.js +108 -0
- package/dist/spec/mine/clustering/features.js.map +1 -0
- package/dist/spec/mine/clustering/index.d.ts +62 -0
- package/dist/spec/mine/clustering/index.d.ts.map +1 -0
- package/dist/spec/mine/clustering/index.js +259 -0
- package/dist/spec/mine/clustering/index.js.map +1 -0
- package/dist/spec/mine/clustering/leiden.d.ts +61 -0
- package/dist/spec/mine/clustering/leiden.d.ts.map +1 -0
- package/dist/spec/mine/clustering/leiden.js +489 -0
- package/dist/spec/mine/clustering/leiden.js.map +1 -0
- package/dist/spec/mine/clustering/text-similarity.d.ts +22 -0
- package/dist/spec/mine/clustering/text-similarity.d.ts.map +1 -0
- package/dist/spec/mine/clustering/text-similarity.js +98 -0
- package/dist/spec/mine/clustering/text-similarity.js.map +1 -0
- package/dist/spec/mine/generator.d.ts +54 -0
- package/dist/spec/mine/generator.d.ts.map +1 -0
- package/dist/spec/mine/generator.js +267 -0
- package/dist/spec/mine/generator.js.map +1 -0
- package/dist/spec/mine/persist.d.ts +37 -0
- package/dist/spec/mine/persist.d.ts.map +1 -0
- package/dist/spec/mine/persist.js +170 -0
- package/dist/spec/mine/persist.js.map +1 -0
- package/dist/spec/mine/pipeline.d.ts +41 -0
- package/dist/spec/mine/pipeline.d.ts.map +1 -0
- package/dist/spec/mine/pipeline.js +236 -0
- package/dist/spec/mine/pipeline.js.map +1 -0
- package/dist/spec/mine/progress-handler.d.ts +22 -0
- package/dist/spec/mine/progress-handler.d.ts.map +1 -0
- package/dist/spec/mine/progress-handler.js +108 -0
- package/dist/spec/mine/progress-handler.js.map +1 -0
- package/dist/spec/mine/progress.d.ts +23 -0
- package/dist/spec/mine/progress.d.ts.map +1 -0
- package/dist/spec/mine/progress.js +12 -0
- package/dist/spec/mine/progress.js.map +1 -0
- package/dist/spec/mine/scanner.d.ts +59 -0
- package/dist/spec/mine/scanner.d.ts.map +1 -0
- package/dist/spec/mine/scanner.js +383 -0
- package/dist/spec/mine/scanner.js.map +1 -0
- package/dist/spec/types.d.ts +32 -0
- package/dist/spec/types.d.ts.map +1 -1
- package/dist/spec/ui/index.d.ts +9 -0
- package/dist/spec/ui/index.d.ts.map +1 -0
- package/dist/spec/ui/index.js +16 -0
- package/dist/spec/ui/index.js.map +1 -0
- package/dist/spec/ui/progress-handler.d.ts +33 -0
- package/dist/spec/ui/progress-handler.d.ts.map +1 -0
- package/dist/spec/ui/progress-handler.js +132 -0
- package/dist/spec/ui/progress-handler.js.map +1 -0
- package/dist/spec/ui/progress.d.ts +24 -0
- package/dist/spec/ui/progress.d.ts.map +1 -0
- package/dist/spec/ui/progress.js +13 -0
- package/dist/spec/ui/progress.js.map +1 -0
- package/dist/spec/utils/fs.d.ts +45 -0
- package/dist/spec/utils/fs.d.ts.map +1 -0
- package/dist/spec/utils/fs.js +163 -0
- package/dist/spec/utils/fs.js.map +1 -0
- package/dist/spec/utils/index.d.ts +12 -0
- package/dist/spec/utils/index.d.ts.map +1 -0
- package/dist/spec/utils/index.js +26 -0
- package/dist/spec/utils/index.js.map +1 -0
- package/dist/spec/utils/meta.d.ts +32 -0
- package/dist/spec/utils/meta.d.ts.map +1 -0
- package/dist/spec/utils/meta.js +122 -0
- package/dist/spec/utils/meta.js.map +1 -0
- package/dist/spec/utils/truncate.d.ts +86 -0
- package/dist/spec/utils/truncate.d.ts.map +1 -0
- package/dist/spec/utils/truncate.js +172 -0
- package/dist/spec/utils/truncate.js.map +1 -0
- package/dist/spec/utils.d.ts +4 -16
- package/dist/spec/utils.d.ts.map +1 -1
- package/dist/spec/utils.js +6 -58
- 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 +35 -6
- package/dist/sync/watcher.d.ts.map +1 -1
- package/dist/sync/watcher.js +127 -17
- package/dist/sync/watcher.js.map +1 -1
- package/dist/sync/worktree.d.ts.map +1 -1
- package/dist/sync/worktree.js +5 -0
- package/dist/sync/worktree.js.map +1 -1
- package/dist/telemetry/index.js +3 -3
- package/dist/telemetry/index.js.map +1 -1
- package/dist/types.d.ts +22 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -0
- package/dist/types.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 +162 -14
- 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 +6 -2
- package/scripts/agent-eval/run-all.sh +6 -0
- package/scripts/build-bundle.sh +5 -0
- package/scripts/npm-shim.js +8 -1
- package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/deveco_arm.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/setup.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/data/agents.json +0 -109
- package/scripts/exp_boundary_eval/data/experiments.json +0 -140
- 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
|
@@ -46,6 +46,7 @@ const query_utils_1 = require("../search/query-utils");
|
|
|
46
46
|
const query_parser_1 = require("../search/query-parser");
|
|
47
47
|
const generated_detection_1 = require("../extraction/generated-detection");
|
|
48
48
|
const arkts_1 = require("../extraction/languages/arkts");
|
|
49
|
+
const identifier_segments_1 = require("../search/identifier-segments");
|
|
49
50
|
/**
|
|
50
51
|
* Path-only heuristic for files that should not be candidates for
|
|
51
52
|
* "dominant file" detection: test/spec files and tool-generated files.
|
|
@@ -69,6 +70,14 @@ function isLowValueFile(filePath) {
|
|
|
69
70
|
(0, generated_detection_1.isGeneratedFile)(filePath));
|
|
70
71
|
}
|
|
71
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
|
+
}
|
|
72
81
|
/**
|
|
73
82
|
* Convert database row to Node object
|
|
74
83
|
*/
|
|
@@ -136,6 +145,8 @@ class QueryBuilder {
|
|
|
136
145
|
// whole project, not a symbol, so it carries no discriminative signal (#720).
|
|
137
146
|
// Set once by the HomeGraph instance; empty by default (no down-weighting).
|
|
138
147
|
projectNameTokens = new Set();
|
|
148
|
+
segmentedNames = new Set();
|
|
149
|
+
static MAX_SEGMENTED_NAMES = 65536;
|
|
139
150
|
// Node cache for frequently accessed nodes (LRU-style, max 1000 entries)
|
|
140
151
|
nodeCache = new Map();
|
|
141
152
|
maxCacheSize = 1000;
|
|
@@ -143,9 +154,54 @@ class QueryBuilder {
|
|
|
143
154
|
ohosApiDbPath = null;
|
|
144
155
|
// Prepared statements (lazily initialized)
|
|
145
156
|
stmts = {};
|
|
157
|
+
// Multi-row INSERT statements, cached per (statement kind × row count).
|
|
158
|
+
batchStmts = new Map();
|
|
159
|
+
static BATCH_SIZES = [128, 32, 8, 1];
|
|
160
|
+
/**
|
|
161
|
+
* Run `rows` through a multi-row `INSERT` built as `head + (tuple,)*n`,
|
|
162
|
+
* decomposed greedily into the cached batch sizes. Preserves row order.
|
|
163
|
+
*/
|
|
164
|
+
runBatched(kind, head, tuple, rows) {
|
|
165
|
+
if (rows.length === 0)
|
|
166
|
+
return;
|
|
167
|
+
let i = 0;
|
|
168
|
+
for (const size of QueryBuilder.BATCH_SIZES) {
|
|
169
|
+
while (rows.length - i >= size) {
|
|
170
|
+
const key = `${kind}:${size}`;
|
|
171
|
+
let stmt = this.batchStmts.get(key);
|
|
172
|
+
if (!stmt) {
|
|
173
|
+
stmt = this.db.prepare(head + new Array(size).fill(tuple).join(','));
|
|
174
|
+
this.batchStmts.set(key, stmt);
|
|
175
|
+
}
|
|
176
|
+
if (size === 1) {
|
|
177
|
+
stmt.run(...rows[i]);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
const params = [];
|
|
181
|
+
for (let r = 0; r < size; r++) {
|
|
182
|
+
const row = rows[i + r];
|
|
183
|
+
for (let c = 0; c < row.length; c++)
|
|
184
|
+
params.push(row[c]);
|
|
185
|
+
}
|
|
186
|
+
stmt.run(...params);
|
|
187
|
+
}
|
|
188
|
+
i += size;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
146
192
|
constructor(db) {
|
|
147
193
|
this.db = db;
|
|
148
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Swap the underlying connection in place. Used by pool workers'
|
|
197
|
+
* connection recycling: a long-lived read connection pins WAL checkpoint
|
|
198
|
+
* progress; workers close and reopen at the pool-idle boundary.
|
|
199
|
+
*/
|
|
200
|
+
rebind(db) {
|
|
201
|
+
this.db = db;
|
|
202
|
+
this.stmts = {};
|
|
203
|
+
this.batchStmts.clear();
|
|
204
|
+
}
|
|
149
205
|
/** Attach a versioned OHOS API db for federated symbol lookup. */
|
|
150
206
|
attachOhosApiDb(dbPath) {
|
|
151
207
|
if (dbPath === this.ohosApiDbPath)
|
|
@@ -254,6 +310,10 @@ class QueryBuilder {
|
|
|
254
310
|
returnType: node.returnType ?? null,
|
|
255
311
|
updatedAt: node.updatedAt ?? Date.now(),
|
|
256
312
|
});
|
|
313
|
+
// Segment vocabulary rides the same write path so it never drifts ahead of
|
|
314
|
+
// the nodes it describes. File/import nodes are excluded (#1144).
|
|
315
|
+
if (this.isSegmentableKind(node.kind))
|
|
316
|
+
this.insertNameSegments(node.name);
|
|
257
317
|
}
|
|
258
318
|
/**
|
|
259
319
|
* Insert multiple nodes in a transaction
|
|
@@ -265,6 +325,40 @@ class QueryBuilder {
|
|
|
265
325
|
}
|
|
266
326
|
})();
|
|
267
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Store one file's whole extraction bundle — nodes, edges, unresolved refs,
|
|
330
|
+
* and the file record — in a SINGLE transaction. The bulk-index path calls
|
|
331
|
+
* this once per file instead of opening one transaction per table (#1015
|
|
332
|
+
* file-order commit discipline is unchanged: callers still invoke it in file
|
|
333
|
+
* order, and row order within is input order).
|
|
334
|
+
*
|
|
335
|
+
* Edges MUST already be endpoint-filtered by the caller (the store path
|
|
336
|
+
* filters to the file's own inserted node ids), so the per-file existence
|
|
337
|
+
* SELECT that insertEdges() pays is skipped here.
|
|
338
|
+
*/
|
|
339
|
+
storeFileBundle(bundle) {
|
|
340
|
+
this.db.transaction(() => {
|
|
341
|
+
this.insertNodes(bundle.nodes);
|
|
342
|
+
if (bundle.edges.length > 0) {
|
|
343
|
+
const rows = [];
|
|
344
|
+
for (const edge of bundle.edges) {
|
|
345
|
+
rows.push([
|
|
346
|
+
edge.source,
|
|
347
|
+
edge.target,
|
|
348
|
+
edge.kind,
|
|
349
|
+
edge.metadata ? JSON.stringify(edge.metadata) : null,
|
|
350
|
+
edge.line ?? null,
|
|
351
|
+
edge.column ?? null,
|
|
352
|
+
edge.provenance ?? null,
|
|
353
|
+
]);
|
|
354
|
+
}
|
|
355
|
+
this.runBatched('insertEdges', 'INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance) VALUES ', '(?,?,?,?,?,?,?)', rows);
|
|
356
|
+
}
|
|
357
|
+
if (bundle.refs.length > 0)
|
|
358
|
+
this.insertUnresolvedRefsBatch(bundle.refs);
|
|
359
|
+
this.upsertFile(bundle.file);
|
|
360
|
+
})();
|
|
361
|
+
}
|
|
268
362
|
/**
|
|
269
363
|
* Update an existing node
|
|
270
364
|
*/
|
|
@@ -325,6 +419,9 @@ class QueryBuilder {
|
|
|
325
419
|
returnType: node.returnType ?? null,
|
|
326
420
|
updatedAt: node.updatedAt ?? Date.now(),
|
|
327
421
|
});
|
|
422
|
+
// Framework post-extract renames must reach the segment vocabulary (#1141).
|
|
423
|
+
if (this.isSegmentableKind(node.kind))
|
|
424
|
+
this.insertNameSegments(node.name);
|
|
328
425
|
}
|
|
329
426
|
/**
|
|
330
427
|
* Delete a node by ID
|
|
@@ -352,6 +449,104 @@ class QueryBuilder {
|
|
|
352
449
|
}
|
|
353
450
|
this.stmts.deleteNodesByFile.run(filePath);
|
|
354
451
|
}
|
|
452
|
+
/** Which node kinds contribute their name to the segment vocabulary. */
|
|
453
|
+
isSegmentableKind(kind) {
|
|
454
|
+
return kind !== 'file' && kind !== 'import';
|
|
455
|
+
}
|
|
456
|
+
/** Write `name`'s segments into name_segment_vocab (idempotent). */
|
|
457
|
+
insertNameSegments(name) {
|
|
458
|
+
if (this.segmentedNames.has(name))
|
|
459
|
+
return;
|
|
460
|
+
if (this.segmentedNames.size >= QueryBuilder.MAX_SEGMENTED_NAMES)
|
|
461
|
+
this.segmentedNames.clear();
|
|
462
|
+
this.segmentedNames.add(name);
|
|
463
|
+
if (!this.stmts.insertNameSegment) {
|
|
464
|
+
this.stmts.insertNameSegment = this.db.prepare('INSERT OR IGNORE INTO name_segment_vocab (segment, name) VALUES (?, ?)');
|
|
465
|
+
}
|
|
466
|
+
for (const segment of (0, identifier_segments_1.splitIdentifierSegments)(name)) {
|
|
467
|
+
this.stmts.insertNameSegment.run(segment, name);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
// ===========================================================================
|
|
471
|
+
// Name-segment vocabulary (prompt-hook graph-derived gate)
|
|
472
|
+
// ===========================================================================
|
|
473
|
+
/** Wipe the segment vocabulary. A full index calls this at its start; the
|
|
474
|
+
* node write path repopulates it as files (re-)index, so the end state is
|
|
475
|
+
* exactly the current names with no orphan rows. */
|
|
476
|
+
clearNameSegmentVocab() {
|
|
477
|
+
this.db.exec('DELETE FROM name_segment_vocab');
|
|
478
|
+
this.segmentedNames.clear();
|
|
479
|
+
}
|
|
480
|
+
/** True when the vocab has no rows — an index built before the table existed.
|
|
481
|
+
* `sync` uses this to heal such databases (see rebuildNameSegmentVocabFrom). */
|
|
482
|
+
isNameSegmentVocabEmpty() {
|
|
483
|
+
const row = this.db.prepare('SELECT 1 FROM name_segment_vocab LIMIT 1').get();
|
|
484
|
+
return row === undefined;
|
|
485
|
+
}
|
|
486
|
+
/** One page of distinct segmentable node names, for batched vocab rebuilds
|
|
487
|
+
* (file basenames and import specifiers are excluded from the vocab — see
|
|
488
|
+
* insertNode). */
|
|
489
|
+
getDistinctNodeNames(limit, offset) {
|
|
490
|
+
const rows = this.db
|
|
491
|
+
.prepare("SELECT DISTINCT name FROM nodes WHERE kind NOT IN ('file', 'import') ORDER BY name LIMIT ? OFFSET ?")
|
|
492
|
+
.all(limit, offset);
|
|
493
|
+
return rows.map((r) => r.name);
|
|
494
|
+
}
|
|
495
|
+
/** Insert segments for a batch of names in one transaction (vocab heal path). */
|
|
496
|
+
insertNameSegmentsBatch(names) {
|
|
497
|
+
this.db.transaction(() => {
|
|
498
|
+
for (const name of names)
|
|
499
|
+
this.insertNameSegments(name);
|
|
500
|
+
})();
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Names whose segments cover at least `minWords` distinct PROMPT WORDS —
|
|
504
|
+
* the co-occurrence probe behind the prompt hook's medium tier: the words
|
|
505
|
+
* "state" and "machine" both being segments of `OrderStateMachine` is strong
|
|
506
|
+
* evidence the prompt names that symbol in prose. Ordered by coverage.
|
|
507
|
+
*
|
|
508
|
+
* Takes (segment variant → original word) pairs and folds variants back to
|
|
509
|
+
* their word INSIDE the SQL: a name matching both `service` and `services`
|
|
510
|
+
* counts ONE word, not two. Counting raw variants let plural-variant pairs
|
|
511
|
+
* of a single word tie with genuine two-word matches and — because ORDER
|
|
512
|
+
* BY/LIMIT run here, before any JS-side re-check — crowd a real match past
|
|
513
|
+
* the LIMIT on vocab-heavy repos (#1146).
|
|
514
|
+
*/
|
|
515
|
+
getSegmentCoOccurrence(variants, minWords, limit) {
|
|
516
|
+
if (variants.length === 0)
|
|
517
|
+
return [];
|
|
518
|
+
const placeholders = variants.map(() => '?').join(', ');
|
|
519
|
+
const whens = variants.map(() => 'WHEN ? THEN ?').join(' ');
|
|
520
|
+
const rows = this.db
|
|
521
|
+
.prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
|
|
522
|
+
FROM name_segment_vocab
|
|
523
|
+
WHERE segment IN (${placeholders})
|
|
524
|
+
GROUP BY name
|
|
525
|
+
HAVING matches >= ?
|
|
526
|
+
ORDER BY matches DESC, length(name) ASC
|
|
527
|
+
LIMIT ?`)
|
|
528
|
+
.all(...variants.flatMap((v) => [v.segment, v.word]), ...variants.map((v) => v.segment), minWords, limit);
|
|
529
|
+
return rows;
|
|
530
|
+
}
|
|
531
|
+
/** How many distinct names each segment appears in — the rarity signal that
|
|
532
|
+
* separates a discriminative word ("checkout") from a ubiquitous one ("state"). */
|
|
533
|
+
getSegmentNameCounts(segments) {
|
|
534
|
+
if (segments.length === 0)
|
|
535
|
+
return new Map();
|
|
536
|
+
const placeholders = segments.map(() => '?').join(', ');
|
|
537
|
+
const rows = this.db
|
|
538
|
+
.prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
|
|
539
|
+
WHERE segment IN (${placeholders}) GROUP BY segment`)
|
|
540
|
+
.all(...segments);
|
|
541
|
+
return new Map(rows.map((r) => [r.segment, r.n]));
|
|
542
|
+
}
|
|
543
|
+
/** Names containing the given segment (rare-single-word tier). */
|
|
544
|
+
getNamesForSegment(segment, limit) {
|
|
545
|
+
const rows = this.db
|
|
546
|
+
.prepare('SELECT name FROM name_segment_vocab WHERE segment = ? ORDER BY length(name) ASC LIMIT ?')
|
|
547
|
+
.all(segment, limit);
|
|
548
|
+
return rows.map((r) => r.name);
|
|
549
|
+
}
|
|
355
550
|
/**
|
|
356
551
|
* Get a node by ID
|
|
357
552
|
*/
|
|
@@ -645,6 +840,33 @@ class QueryBuilder {
|
|
|
645
840
|
yield rowToNode(row);
|
|
646
841
|
}
|
|
647
842
|
}
|
|
843
|
+
/**
|
|
844
|
+
* Stream nodes of a language whose `decorators` JSON array contains a
|
|
845
|
+
* quoted decorator name. LIKE is a substring filter (a decorator name can
|
|
846
|
+
* appear as a substring of another), so callers must still exact-check
|
|
847
|
+
* `node.decorators.includes(decorator)`. Exists so the kotlin expect/actual
|
|
848
|
+
* synthesizer never materializes the whole node table the way
|
|
849
|
+
* `getAllNodes().filter(...)` did — that array alone OOM'd Node's default
|
|
850
|
+
* heap on a 2M-node graph (#1212).
|
|
851
|
+
*/
|
|
852
|
+
*iterateNodesByLanguageWithDecorator(language, decorator) {
|
|
853
|
+
// Fresh statement per call — an iterator holds an open cursor (see
|
|
854
|
+
// iterateNodesByKind).
|
|
855
|
+
const stmt = this.db.prepare("SELECT * FROM nodes WHERE language = ? AND decorators LIKE '%' || ? || '%'");
|
|
856
|
+
for (const row of stmt.iterate(language, `"${decorator}"`)) {
|
|
857
|
+
yield rowToNode(row);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Distinct languages present in the files table. One indexed aggregate —
|
|
862
|
+
* lets the dynamic-edge synthesizers skip passes for languages the project
|
|
863
|
+
* doesn't contain at all (a Kotlin pass has no work on a pure-C repo), so
|
|
864
|
+
* their cost is zero rather than a full-graph scan that finds nothing (#1212).
|
|
865
|
+
*/
|
|
866
|
+
getDistinctFileLanguages() {
|
|
867
|
+
const rows = this.db.prepare('SELECT DISTINCT language FROM files').all();
|
|
868
|
+
return new Set(rows.map((r) => r.language));
|
|
869
|
+
}
|
|
648
870
|
/**
|
|
649
871
|
* Get all nodes in the database
|
|
650
872
|
*/
|
|
@@ -1259,12 +1481,23 @@ class QueryBuilder {
|
|
|
1259
1481
|
/**
|
|
1260
1482
|
* Get incoming edges to a node
|
|
1261
1483
|
*/
|
|
1262
|
-
getIncomingEdges(targetId, kinds) {
|
|
1484
|
+
getIncomingEdges(targetId, kinds, limit) {
|
|
1485
|
+
const cap = typeof limit === 'number' && Number.isFinite(limit)
|
|
1486
|
+
? Math.max(1, Math.min(Math.floor(limit), 2000))
|
|
1487
|
+
: undefined;
|
|
1263
1488
|
if (kinds && kinds.length > 0) {
|
|
1264
|
-
|
|
1489
|
+
let sql = `SELECT * FROM edges WHERE target = ? AND kind IN (${kinds.map(() => '?').join(',')})`;
|
|
1490
|
+
if (cap !== undefined)
|
|
1491
|
+
sql += ` LIMIT ${cap}`;
|
|
1265
1492
|
const rows = this.db.prepare(sql).all(targetId, ...kinds);
|
|
1266
1493
|
return rows.map(rowToEdge);
|
|
1267
1494
|
}
|
|
1495
|
+
if (cap !== undefined) {
|
|
1496
|
+
const rows = this.db
|
|
1497
|
+
.prepare('SELECT * FROM edges WHERE target = ? LIMIT ?')
|
|
1498
|
+
.all(targetId, cap);
|
|
1499
|
+
return rows.map(rowToEdge);
|
|
1500
|
+
}
|
|
1268
1501
|
if (!this.stmts.getEdgesByTarget) {
|
|
1269
1502
|
this.stmts.getEdgesByTarget = this.db.prepare('SELECT * FROM edges WHERE target = ?');
|
|
1270
1503
|
}
|
|
@@ -1343,7 +1576,8 @@ class QueryBuilder {
|
|
|
1343
1576
|
* {@link getDependentFilePaths}: all kinds except `contains`.
|
|
1344
1577
|
*/
|
|
1345
1578
|
getCrossFileIncomingEdgesWithTarget(filePath) {
|
|
1346
|
-
const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind
|
|
1579
|
+
const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
|
|
1580
|
+
src.file_path AS source_file_path, src.language AS source_language
|
|
1347
1581
|
FROM edges e
|
|
1348
1582
|
JOIN nodes tgt ON tgt.id = e.target
|
|
1349
1583
|
JOIN nodes src ON src.id = e.source
|
|
@@ -1355,6 +1589,8 @@ class QueryBuilder {
|
|
|
1355
1589
|
...rowToEdge(row),
|
|
1356
1590
|
targetName: row.target_name,
|
|
1357
1591
|
targetKind: row.target_kind,
|
|
1592
|
+
sourceFilePath: row.source_file_path,
|
|
1593
|
+
sourceLanguage: row.source_language,
|
|
1358
1594
|
}));
|
|
1359
1595
|
}
|
|
1360
1596
|
/**
|
|
@@ -1541,7 +1777,7 @@ class QueryBuilder {
|
|
|
1541
1777
|
*/
|
|
1542
1778
|
getUnresolvedReferencesCount() {
|
|
1543
1779
|
if (!this.stmts.getUnresolvedCount) {
|
|
1544
|
-
this.stmts.getUnresolvedCount = this.db.prepare(
|
|
1780
|
+
this.stmts.getUnresolvedCount = this.db.prepare("SELECT COUNT(*) as count FROM unresolved_refs WHERE status = 'pending'");
|
|
1545
1781
|
}
|
|
1546
1782
|
const row = this.stmts.getUnresolvedCount.get();
|
|
1547
1783
|
return row.count;
|
|
@@ -1552,7 +1788,7 @@ class QueryBuilder {
|
|
|
1552
1788
|
*/
|
|
1553
1789
|
getUnresolvedReferencesBatch(offset, limit) {
|
|
1554
1790
|
if (!this.stmts.getUnresolvedBatch) {
|
|
1555
|
-
this.stmts.getUnresolvedBatch = this.db.prepare(
|
|
1791
|
+
this.stmts.getUnresolvedBatch = this.db.prepare("SELECT * FROM unresolved_refs WHERE status = 'pending' ORDER BY rowid LIMIT ? OFFSET ?");
|
|
1556
1792
|
}
|
|
1557
1793
|
const rows = this.stmts.getUnresolvedBatch.all(limit, offset);
|
|
1558
1794
|
return rows.map((row) => ({
|
|
@@ -1564,6 +1800,32 @@ class QueryBuilder {
|
|
|
1564
1800
|
candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
|
|
1565
1801
|
filePath: row.file_path,
|
|
1566
1802
|
language: row.language,
|
|
1803
|
+
rowId: row.id,
|
|
1804
|
+
}));
|
|
1805
|
+
}
|
|
1806
|
+
/**
|
|
1807
|
+
* Keyset variant of {@link getUnresolvedReferencesBatch} for the batched
|
|
1808
|
+
* resolution loop: seek past the last-seen row id instead of OFFSET-walking.
|
|
1809
|
+
* OFFSET reads re-scan the accumulated failed-row prefix on every batch —
|
|
1810
|
+
* O(failed rows) per read, measured at 54.6s of the kernel-scale batch loop
|
|
1811
|
+
* (§7a.2) — while the seek is O(batch) forever. `id` is the rowid alias, so
|
|
1812
|
+
* the enumeration order is identical to the OFFSET reader's.
|
|
1813
|
+
*/
|
|
1814
|
+
getUnresolvedReferencesBatchAfter(afterRowId, limit) {
|
|
1815
|
+
if (!this.stmts.getUnresolvedBatchAfter) {
|
|
1816
|
+
this.stmts.getUnresolvedBatchAfter = this.db.prepare("SELECT * FROM unresolved_refs WHERE status = 'pending' AND id > ? ORDER BY id LIMIT ?");
|
|
1817
|
+
}
|
|
1818
|
+
const rows = this.stmts.getUnresolvedBatchAfter.all(afterRowId, limit);
|
|
1819
|
+
return rows.map((row) => ({
|
|
1820
|
+
fromNodeId: row.from_node_id,
|
|
1821
|
+
referenceName: row.reference_name,
|
|
1822
|
+
referenceKind: row.reference_kind,
|
|
1823
|
+
line: row.line,
|
|
1824
|
+
column: row.col,
|
|
1825
|
+
candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
|
|
1826
|
+
filePath: row.file_path,
|
|
1827
|
+
language: row.language,
|
|
1828
|
+
rowId: row.id,
|
|
1567
1829
|
}));
|
|
1568
1830
|
}
|
|
1569
1831
|
/**
|
|
@@ -1586,6 +1848,152 @@ class QueryBuilder {
|
|
|
1586
1848
|
const rows = this.stmts.getAllNodeNames.all();
|
|
1587
1849
|
return rows.map((r) => r.name);
|
|
1588
1850
|
}
|
|
1851
|
+
/**
|
|
1852
|
+
* Stream distinct node names one row at a time — for resolver cache warm-up
|
|
1853
|
+
* that needs to yield to the event loop mid-scan.
|
|
1854
|
+
*/
|
|
1855
|
+
*iterateNodeNames() {
|
|
1856
|
+
const stmt = this.db.prepare('SELECT DISTINCT name FROM nodes');
|
|
1857
|
+
for (const row of stmt.iterate()) {
|
|
1858
|
+
yield row.name;
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
/**
|
|
1862
|
+
* Park refs as status='failed' so drain loops skip them while sync can retry
|
|
1863
|
+
* when a later file change introduces a matching symbol.
|
|
1864
|
+
*/
|
|
1865
|
+
markReferencesFailed(refs) {
|
|
1866
|
+
if (refs.length === 0)
|
|
1867
|
+
return 0;
|
|
1868
|
+
const stmt = this.db.prepare("UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE from_node_id = ? AND reference_name = ? AND reference_kind = ?");
|
|
1869
|
+
let changed = 0;
|
|
1870
|
+
const markMany = this.db.transaction((items) => {
|
|
1871
|
+
for (const ref of items) {
|
|
1872
|
+
changed += stmt.run(referenceNameTail(ref.referenceName), ref.fromNodeId, ref.referenceName, ref.referenceKind).changes;
|
|
1873
|
+
}
|
|
1874
|
+
});
|
|
1875
|
+
markMany(refs);
|
|
1876
|
+
return changed;
|
|
1877
|
+
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Delete unresolved-ref rows by row id — the precise cleanup for refs a
|
|
1880
|
+
* resolution pass actually processed. The key-tuple variant above also
|
|
1881
|
+
* deletes SIBLING rows (same caller calling the same callee at other lines)
|
|
1882
|
+
* that a later batch hasn't attempted yet, so when a batch boundary split a
|
|
1883
|
+
* caller's same-named call sites, the later sites' edges were silently never
|
|
1884
|
+
* created (#1269).
|
|
1885
|
+
*/
|
|
1886
|
+
deleteReferencesByRowIds(rowIds) {
|
|
1887
|
+
if (rowIds.length === 0)
|
|
1888
|
+
return 0;
|
|
1889
|
+
let changed = 0;
|
|
1890
|
+
this.db.transaction(() => {
|
|
1891
|
+
for (let i = 0; i < rowIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1892
|
+
const chunk = rowIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1893
|
+
if (chunk.length === SQLITE_PARAM_CHUNK_SIZE) {
|
|
1894
|
+
if (!this.stmts.deleteRefsByRowIdsFull) {
|
|
1895
|
+
const placeholders = new Array(SQLITE_PARAM_CHUNK_SIZE).fill('?').join(',');
|
|
1896
|
+
this.stmts.deleteRefsByRowIdsFull = this.db.prepare(`DELETE FROM unresolved_refs WHERE id IN (${placeholders})`);
|
|
1897
|
+
}
|
|
1898
|
+
changed += this.stmts.deleteRefsByRowIdsFull.run(...chunk).changes;
|
|
1899
|
+
}
|
|
1900
|
+
else {
|
|
1901
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
1902
|
+
changed += this.db.prepare(`DELETE FROM unresolved_refs WHERE id IN (${placeholders})`).run(...chunk).changes;
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
})();
|
|
1906
|
+
return changed;
|
|
1907
|
+
}
|
|
1908
|
+
/**
|
|
1909
|
+
* Park refs as status='failed' by row id — the precise counterpart of
|
|
1910
|
+
* markReferencesFailed, for the same reason as deleteReferencesByRowIds:
|
|
1911
|
+
* the key-tuple variant also flips same-key sibling rows in later batches
|
|
1912
|
+
* to 'failed' before they were ever attempted (#1269). Resolution outcome
|
|
1913
|
+
* can differ per call site (receiver-type inference reads the ref's line),
|
|
1914
|
+
* so a sibling must not inherit this row's failure.
|
|
1915
|
+
*/
|
|
1916
|
+
markReferencesFailedByRowIds(refs) {
|
|
1917
|
+
if (refs.length === 0)
|
|
1918
|
+
return 0;
|
|
1919
|
+
const stmt = this.db.prepare("UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE id = ?");
|
|
1920
|
+
let changed = 0;
|
|
1921
|
+
const markMany = this.db.transaction((items) => {
|
|
1922
|
+
for (const ref of items) {
|
|
1923
|
+
changed += stmt.run(referenceNameTail(ref.referenceName), ref.rowId).changes;
|
|
1924
|
+
}
|
|
1925
|
+
});
|
|
1926
|
+
markMany(refs);
|
|
1927
|
+
return changed;
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Failed refs whose name tail matches one of the given symbol names — the
|
|
1931
|
+
* candidates a sync should retry after files carrying those names changed
|
|
1932
|
+
* (#1240). Names matching more than `perNameCeiling` failed refs are
|
|
1933
|
+
* skipped entirely: at that population a name is external/builtin noise
|
|
1934
|
+
* (`get`, `map`, …) that one new definition won't resolve — the same
|
|
1935
|
+
* rationale as resolution's AMBIGUOUS_NAME_CEILING (#999) — and retrying an
|
|
1936
|
+
* arbitrary subset would be both wasted work and incoherent coverage.
|
|
1937
|
+
*/
|
|
1938
|
+
getRetryableFailedReferences(names, perNameCeiling = 500) {
|
|
1939
|
+
if (names.length === 0)
|
|
1940
|
+
return [];
|
|
1941
|
+
// Pass 1: per-tail counts, chunked under the SQLite parameter limit.
|
|
1942
|
+
const retryNames = [];
|
|
1943
|
+
for (let i = 0; i < names.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1944
|
+
const chunk = names.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1945
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
1946
|
+
const counts = this.db
|
|
1947
|
+
.prepare(`SELECT name_tail, COUNT(*) as count FROM unresolved_refs WHERE status = 'failed' AND name_tail IN (${placeholders}) GROUP BY name_tail`)
|
|
1948
|
+
.all(...chunk);
|
|
1949
|
+
for (const row of counts) {
|
|
1950
|
+
if (row.count <= perNameCeiling)
|
|
1951
|
+
retryNames.push(row.name_tail);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
if (retryNames.length === 0)
|
|
1955
|
+
return [];
|
|
1956
|
+
// Pass 2: load the surviving rows.
|
|
1957
|
+
const rows = [];
|
|
1958
|
+
for (let i = 0; i < retryNames.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1959
|
+
const chunk = retryNames.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1960
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
1961
|
+
const chunkRows = this.db
|
|
1962
|
+
.prepare(`SELECT * FROM unresolved_refs WHERE status = 'failed' AND name_tail IN (${placeholders})`)
|
|
1963
|
+
.all(...chunk);
|
|
1964
|
+
rows.push(...chunkRows);
|
|
1965
|
+
}
|
|
1966
|
+
return rows.map((row) => ({
|
|
1967
|
+
fromNodeId: row.from_node_id,
|
|
1968
|
+
referenceName: row.reference_name,
|
|
1969
|
+
referenceKind: row.reference_kind,
|
|
1970
|
+
line: row.line,
|
|
1971
|
+
column: row.col,
|
|
1972
|
+
candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
|
|
1973
|
+
filePath: row.file_path,
|
|
1974
|
+
language: row.language,
|
|
1975
|
+
rowId: row.id,
|
|
1976
|
+
}));
|
|
1977
|
+
}
|
|
1978
|
+
/**
|
|
1979
|
+
* Distinct node names present in the given files — the symbol names a sync
|
|
1980
|
+
* pass uses to look up retryable failed refs after those files changed.
|
|
1981
|
+
*/
|
|
1982
|
+
getNodeNamesByFiles(filePaths) {
|
|
1983
|
+
if (filePaths.length === 0)
|
|
1984
|
+
return [];
|
|
1985
|
+
const names = new Set();
|
|
1986
|
+
for (let i = 0; i < filePaths.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1987
|
+
const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1988
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
1989
|
+
const rows = this.db
|
|
1990
|
+
.prepare(`SELECT DISTINCT name FROM nodes WHERE file_path IN (${placeholders})`)
|
|
1991
|
+
.all(...chunk);
|
|
1992
|
+
for (const row of rows)
|
|
1993
|
+
names.add(row.name);
|
|
1994
|
+
}
|
|
1995
|
+
return [...names];
|
|
1996
|
+
}
|
|
1589
1997
|
/**
|
|
1590
1998
|
* Get unresolved references scoped to specific file paths.
|
|
1591
1999
|
* Uses the idx_unresolved_file_path index for efficient lookup.
|
|
@@ -1602,7 +2010,7 @@ class QueryBuilder {
|
|
|
1602
2010
|
const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1603
2011
|
const placeholders = chunk.map(() => '?').join(',');
|
|
1604
2012
|
const chunkRows = this.db
|
|
1605
|
-
.prepare(`SELECT * FROM unresolved_refs WHERE file_path IN (${placeholders})`)
|
|
2013
|
+
.prepare(`SELECT * FROM unresolved_refs WHERE status = 'pending' AND file_path IN (${placeholders})`)
|
|
1606
2014
|
.all(...chunk);
|
|
1607
2015
|
rows.push(...chunkRows);
|
|
1608
2016
|
}
|
|
@@ -1633,7 +2041,7 @@ class QueryBuilder {
|
|
|
1633
2041
|
// this file. The internal resolution path uses deleteSpecificResolvedReferences
|
|
1634
2042
|
// instead, but QueryBuilder is part of the public API, so a library consumer
|
|
1635
2043
|
// passing more ids than SQLITE_MAX_VARIABLE_NUMBER (32766 on the bundled
|
|
1636
|
-
//
|
|
2044
|
+
// SQLite would otherwise hit "too many SQL variables". (#540, #1001)
|
|
1637
2045
|
for (let i = 0; i < fromNodeIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
1638
2046
|
const chunk = fromNodeIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
1639
2047
|
const placeholders = chunk.map(() => '?').join(',');
|
|
@@ -1646,14 +2054,16 @@ class QueryBuilder {
|
|
|
1646
2054
|
*/
|
|
1647
2055
|
deleteSpecificResolvedReferences(refs) {
|
|
1648
2056
|
if (refs.length === 0)
|
|
1649
|
-
return;
|
|
2057
|
+
return 0;
|
|
1650
2058
|
const stmt = this.db.prepare('DELETE FROM unresolved_refs WHERE from_node_id = ? AND reference_name = ? AND reference_kind = ?');
|
|
2059
|
+
let changed = 0;
|
|
1651
2060
|
const deleteMany = this.db.transaction((items) => {
|
|
1652
2061
|
for (const ref of items) {
|
|
1653
|
-
stmt.run(ref.fromNodeId, ref.referenceName, ref.referenceKind);
|
|
2062
|
+
changed += stmt.run(ref.fromNodeId, ref.referenceName, ref.referenceKind).changes;
|
|
1654
2063
|
}
|
|
1655
2064
|
});
|
|
1656
2065
|
deleteMany(refs);
|
|
2066
|
+
return changed;
|
|
1657
2067
|
}
|
|
1658
2068
|
// ===========================================================================
|
|
1659
2069
|
// Statistics
|
|
@@ -1752,6 +2162,13 @@ class QueryBuilder {
|
|
|
1752
2162
|
.get(cacheKey);
|
|
1753
2163
|
return row ?? null;
|
|
1754
2164
|
}
|
|
2165
|
+
/** All cache keys — used to warm the in-memory key index after daemon restart. */
|
|
2166
|
+
listMcpQueryCacheKeys() {
|
|
2167
|
+
const rows = this.db
|
|
2168
|
+
.prepare('SELECT cache_key FROM mcp_query_cache')
|
|
2169
|
+
.all();
|
|
2170
|
+
return rows.map((r) => r.cache_key);
|
|
2171
|
+
}
|
|
1755
2172
|
setMcpQueryCache(cacheKey, tool, response, createdAt) {
|
|
1756
2173
|
this.db
|
|
1757
2174
|
.prepare('INSERT INTO mcp_query_cache (cache_key, tool, response, created_at) VALUES (?, ?, ?, ?) ' +
|