homegraph 1.5.1 → 1.5.3
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/CHANGELOG.md +131 -0
- package/LICENSE +21 -21
- package/README.md +312 -305
- package/dist/arkui/index.d.ts +4 -0
- package/dist/arkui/index.d.ts.map +1 -0
- package/dist/arkui/index.js +23 -0
- package/dist/arkui/index.js.map +1 -0
- package/dist/arkui/migrate-passage.d.ts +28 -0
- package/dist/arkui/migrate-passage.d.ts.map +1 -0
- package/dist/arkui/migrate-passage.js +310 -0
- package/dist/arkui/migrate-passage.js.map +1 -0
- package/dist/arkui/migrate-semantics.d.ts +47 -0
- package/dist/arkui/migrate-semantics.d.ts.map +1 -0
- package/dist/arkui/migrate-semantics.js +229 -0
- package/dist/arkui/migrate-semantics.js.map +1 -0
- package/dist/arkui/migrate-snapshot.d.ts +79 -0
- package/dist/arkui/migrate-snapshot.d.ts.map +1 -0
- package/dist/arkui/migrate-snapshot.js +340 -0
- package/dist/arkui/migrate-snapshot.js.map +1 -0
- package/dist/bin/fatal-handler.js +2 -2
- package/dist/bin/homegraph.js +111 -162
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/bin/node-version-check.d.ts +6 -15
- package/dist/bin/node-version-check.d.ts.map +1 -1
- package/dist/bin/node-version-check.js +8 -37
- package/dist/bin/node-version-check.js.map +1 -1
- package/dist/db/index.d.ts +36 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +124 -38
- 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 +52 -38
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/queries.d.ts +42 -0
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +330 -163
- package/dist/db/queries.js.map +1 -1
- package/dist/db/schema.sql +208 -203
- package/dist/db/sqlite-adapter.d.ts +8 -3
- package/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/dist/db/sqlite-adapter.js +45 -3
- package/dist/db/sqlite-adapter.js.map +1 -1
- package/dist/directory.js +5 -5
- package/dist/extraction/extraction-version.d.ts +1 -1
- package/dist/extraction/extraction-version.js +1 -1
- package/dist/extraction/generated-detection.d.ts +42 -11
- package/dist/extraction/generated-detection.d.ts.map +1 -1
- package/dist/extraction/generated-detection.js +141 -20
- package/dist/extraction/generated-detection.js.map +1 -1
- package/dist/extraction/index.d.ts +43 -1
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +150 -43
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts.d.ts +70 -6
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +958 -108
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/extraction/wasm/tree-sitter-c_sharp.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-pascal.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
- package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -1
- package/dist/extraction/wasm-runtime-flags.js +9 -6
- package/dist/extraction/wasm-runtime-flags.js.map +1 -1
- package/dist/graph-sources.d.ts +41 -0
- package/dist/graph-sources.d.ts.map +1 -0
- package/dist/graph-sources.js +82 -0
- package/dist/graph-sources.js.map +1 -0
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +80 -9
- package/dist/index.js.map +1 -1
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +0 -48
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/instructions-template.js +9 -9
- package/dist/installer/targets/antigravity.js +1 -1
- package/dist/installer/targets/antigravity.js.map +1 -1
- package/dist/installer/targets/deveco.js +1 -1
- package/dist/installer/targets/deveco.js.map +1 -1
- package/dist/installer/targets/hermes.d.ts +1 -1
- package/dist/installer/targets/hermes.js +2 -2
- package/dist/installer/targets/hermes.js.map +1 -1
- package/dist/installer/targets/opencode.js +1 -1
- package/dist/installer/targets/opencode.js.map +1 -1
- package/dist/installer/targets/shared.js +1 -1
- package/dist/installer/targets/shared.js.map +1 -1
- package/dist/mcp/daemon-paths.d.ts +5 -4
- package/dist/mcp/daemon-paths.d.ts.map +1 -1
- package/dist/mcp/daemon-paths.js +28 -13
- 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 +4 -1
- package/dist/mcp/daemon-registry.js.map +1 -1
- package/dist/mcp/daemon.d.ts +1 -1
- package/dist/mcp/daemon.js +1 -1
- package/dist/mcp/diff-impact.d.ts +131 -0
- package/dist/mcp/diff-impact.d.ts.map +1 -0
- package/dist/mcp/diff-impact.js +385 -0
- package/dist/mcp/diff-impact.js.map +1 -0
- package/dist/mcp/engine.d.ts.map +1 -1
- package/dist/mcp/engine.js +12 -3
- package/dist/mcp/engine.js.map +1 -1
- package/dist/mcp/explore-dedup.d.ts +137 -0
- package/dist/mcp/explore-dedup.d.ts.map +1 -0
- package/dist/mcp/explore-dedup.js +236 -0
- package/dist/mcp/explore-dedup.js.map +1 -0
- package/dist/mcp/explore-session-state.d.ts +217 -0
- package/dist/mcp/explore-session-state.d.ts.map +1 -0
- package/dist/mcp/explore-session-state.js +322 -0
- package/dist/mcp/explore-session-state.js.map +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +4 -7
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/liveness-watchdog.js +51 -51
- package/dist/mcp/proxy.d.ts.map +1 -1
- package/dist/mcp/proxy.js +5 -14
- package/dist/mcp/proxy.js.map +1 -1
- package/dist/mcp/query-worker.d.ts +1 -1
- package/dist/mcp/query-worker.js +1 -1
- package/dist/mcp/server-instructions.d.ts +7 -2
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +125 -47
- package/dist/mcp/server-instructions.js.map +1 -1
- package/dist/mcp/session.d.ts +14 -3
- package/dist/mcp/session.d.ts.map +1 -1
- package/dist/mcp/session.js +17 -14
- package/dist/mcp/session.js.map +1 -1
- package/dist/mcp/startup-handshake.d.ts +1 -1
- package/dist/mcp/startup-handshake.js +1 -1
- package/dist/mcp/tools.d.ts +138 -12
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +3279 -476
- package/dist/mcp/tools.js.map +1 -1
- package/dist/resolution/callback-synthesizer.d.ts +2 -1
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/dist/resolution/callback-synthesizer.js +153 -53
- package/dist/resolution/callback-synthesizer.js.map +1 -1
- package/dist/resolution/frameworks/arkts-entry.d.ts.map +1 -1
- package/dist/resolution/frameworks/arkts-entry.js +20 -9
- package/dist/resolution/frameworks/arkts-entry.js.map +1 -1
- package/dist/resolution/frameworks/arkts-napi.d.ts +14 -0
- package/dist/resolution/frameworks/arkts-napi.d.ts.map +1 -1
- package/dist/resolution/frameworks/arkts-napi.js +169 -49
- package/dist/resolution/frameworks/arkts-napi.js.map +1 -1
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +1 -1
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/memory-budget.d.ts +33 -0
- package/dist/resolution/memory-budget.d.ts.map +1 -1
- package/dist/resolution/memory-budget.js +58 -0
- package/dist/resolution/memory-budget.js.map +1 -1
- package/dist/resolution/resolver-pool.d.ts +2 -0
- package/dist/resolution/resolver-pool.d.ts.map +1 -1
- package/dist/resolution/resolver-pool.js +4 -0
- package/dist/resolution/resolver-pool.js.map +1 -1
- package/dist/search/query-utils.d.ts +116 -4
- package/dist/search/query-utils.d.ts.map +1 -1
- package/dist/search/query-utils.js +869 -60
- package/dist/search/query-utils.js.map +1 -1
- package/dist/spec/db/commit-node.js +4 -4
- package/dist/spec/db/fragment-node.js +10 -10
- package/dist/spec/db/fts.js +8 -8
- package/dist/spec/db/relations.js +88 -88
- package/dist/spec/db/schema.js +6 -6
- package/dist/spec/db/schema.sql +121 -121
- package/dist/spec/db/spec-node.js +4 -4
- package/dist/spec/llm/prompts.js +53 -53
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.js +4 -1
- package/dist/ui/shimmer-progress.js.map +1 -1
- package/dist/upgrade/index.d.ts +14 -26
- package/dist/upgrade/index.d.ts.map +1 -1
- package/dist/upgrade/index.js +28 -123
- package/dist/upgrade/index.js.map +1 -1
- package/dist/upgrade/remove-binary.d.ts +19 -19
- package/dist/upgrade/remove-binary.d.ts.map +1 -1
- package/dist/upgrade/remove-binary.js +20 -21
- package/dist/upgrade/remove-binary.js.map +1 -1
- package/dist/upgrade/update-check.d.ts +4 -3
- package/dist/upgrade/update-check.d.ts.map +1 -1
- package/dist/upgrade/update-check.js +4 -3
- package/dist/upgrade/update-check.js.map +1 -1
- package/package.json +65 -62
- package/dist/extraction/languages/arkts-viewtree.d.ts +0 -22
- package/dist/extraction/languages/arkts-viewtree.d.ts.map +0 -1
- package/dist/extraction/languages/arkts-viewtree.js +0 -133
- package/dist/extraction/languages/arkts-viewtree.js.map +0 -1
- package/dist/reasoning/config.d.ts +0 -45
- package/dist/reasoning/config.d.ts.map +0 -1
- package/dist/reasoning/config.js +0 -171
- package/dist/reasoning/config.js.map +0 -1
- package/dist/reasoning/credentials.d.ts +0 -5
- package/dist/reasoning/credentials.d.ts.map +0 -1
- package/dist/reasoning/credentials.js +0 -83
- package/dist/reasoning/credentials.js.map +0 -1
- package/dist/reasoning/login.d.ts +0 -21
- package/dist/reasoning/login.d.ts.map +0 -1
- package/dist/reasoning/login.js +0 -85
- package/dist/reasoning/login.js.map +0 -1
- package/dist/reasoning/reasoner.d.ts +0 -43
- package/dist/reasoning/reasoner.d.ts.map +0 -1
- package/dist/reasoning/reasoner.js +0 -308
- package/dist/reasoning/reasoner.js.map +0 -1
- package/dist/spec/evolve/llm-client.d.ts +0 -50
- package/dist/spec/evolve/llm-client.d.ts.map +0 -1
- package/dist/spec/evolve/llm-client.js +0 -176
- package/dist/spec/evolve/llm-client.js.map +0 -1
- package/dist/spec/evolve/logic-checker.d.ts +0 -12
- package/dist/spec/evolve/logic-checker.d.ts.map +0 -1
- package/dist/spec/evolve/logic-checker.js +0 -24
- package/dist/spec/evolve/logic-checker.js.map +0 -1
- package/dist/spec/llm/index.d.ts +0 -3
- package/dist/spec/llm/index.d.ts.map +0 -1
- package/dist/spec/llm/index.js +0 -11
- package/dist/spec/llm/index.js.map +0 -1
- package/dist/spec/mining/diff-parser.d.ts +0 -33
- package/dist/spec/mining/diff-parser.d.ts.map +0 -1
- package/dist/spec/mining/diff-parser.js +0 -166
- package/dist/spec/mining/diff-parser.js.map +0 -1
- package/dist/spec/mining/git-scanner.d.ts +0 -103
- package/dist/spec/mining/git-scanner.d.ts.map +0 -1
- package/dist/spec/mining/git-scanner.js +0 -307
- package/dist/spec/mining/git-scanner.js.map +0 -1
- package/dist/spec/mining/pipeline.d.ts +0 -53
- package/dist/spec/mining/pipeline.d.ts.map +0 -1
- package/dist/spec/mining/pipeline.js +0 -178
- package/dist/spec/mining/pipeline.js.map +0 -1
- package/dist/spec/mining/scope-resolver.d.ts +0 -45
- package/dist/spec/mining/scope-resolver.d.ts.map +0 -1
- package/dist/spec/mining/scope-resolver.js +0 -103
- package/dist/spec/mining/scope-resolver.js.map +0 -1
- package/dist/spec/mining/spec-extractor.d.ts +0 -69
- package/dist/spec/mining/spec-extractor.d.ts.map +0 -1
- package/dist/spec/mining/spec-extractor.js +0 -369
- package/dist/spec/mining/spec-extractor.js.map +0 -1
- package/dist/spec/utils.d.ts +0 -167
- package/dist/spec/utils.d.ts.map +0 -1
- package/dist/spec/utils.js +0 -463
- package/dist/spec/utils.js.map +0 -1
- package/dist/telemetry/index.d.ts +0 -143
- package/dist/telemetry/index.d.ts.map +0 -1
- package/dist/telemetry/index.js +0 -541
- package/dist/telemetry/index.js.map +0 -1
- package/scripts/_tmp-cfwk-resolve.log +0 -0
- package/scripts/_tmp-cfwk-sig.log +0 -0
- package/scripts/_tmp-cfwk-vt.log +0 -0
- package/scripts/add-lang/bench.sh +0 -60
- package/scripts/add-lang/check-grammar.mjs +0 -75
- package/scripts/add-lang/dump-ast.mjs +0 -103
- package/scripts/add-lang/verify-extraction.mjs +0 -70
- package/scripts/agent-eval/ab-adoption.sh +0 -91
- package/scripts/agent-eval/ab-hook.sh +0 -86
- package/scripts/agent-eval/ab-impl.sh +0 -78
- package/scripts/agent-eval/ab-new-vs-baseline.sh +0 -102
- package/scripts/agent-eval/ab-sufficiency.sh +0 -78
- package/scripts/agent-eval/arms-F.sh +0 -21
- package/scripts/agent-eval/arms-matrix.sh +0 -37
- package/scripts/agent-eval/audit.sh +0 -68
- package/scripts/agent-eval/bench-readme.sh +0 -28
- package/scripts/agent-eval/bench-why-repo.sh +0 -22
- package/scripts/agent-eval/block-read-hook.sh +0 -19
- package/scripts/agent-eval/hook-settings.json +0 -15
- package/scripts/agent-eval/itrun.sh +0 -120
- package/scripts/agent-eval/offload-eval-3arm.sh +0 -72
- package/scripts/agent-eval/offload-eval-cost.mjs +0 -133
- package/scripts/agent-eval/offload-eval-effort.mjs +0 -108
- package/scripts/agent-eval/offload-eval-frontload-matrix.sh +0 -25
- package/scripts/agent-eval/offload-eval-frontload.sh +0 -47
- package/scripts/agent-eval/offload-eval-ground-truth.json +0 -18
- package/scripts/agent-eval/offload-eval-hook.mjs +0 -84
- package/scripts/agent-eval/offload-eval-judge.mjs +0 -103
- package/scripts/agent-eval/offload-eval-matrix.sh +0 -20
- package/scripts/agent-eval/offload-eval-metrics.mjs +0 -94
- package/scripts/agent-eval/offload-eval-refs1.sh +0 -50
- package/scripts/agent-eval/offload-eval-setup.sh +0 -24
- package/scripts/agent-eval/offload-eval-styles.sh +0 -72
- package/scripts/agent-eval/offload-eval-summarize.mjs +0 -68
- package/scripts/agent-eval/offload-eval.md +0 -76
- package/scripts/agent-eval/parse-arms.mjs +0 -116
- package/scripts/agent-eval/parse-bench-readme.mjs +0 -84
- package/scripts/agent-eval/parse-run.mjs +0 -45
- package/scripts/agent-eval/parse-session.mjs +0 -93
- package/scripts/agent-eval/probe-context.mjs +0 -21
- package/scripts/agent-eval/probe-explore.mjs +0 -40
- package/scripts/agent-eval/probe-node.mjs +0 -20
- package/scripts/agent-eval/probe-sweep.mjs +0 -119
- package/scripts/agent-eval/probe-trace.mjs +0 -20
- package/scripts/agent-eval/redirect-read-hook.sh +0 -38
- package/scripts/agent-eval/repro-concurrent-explore.mjs +0 -119
- package/scripts/agent-eval/repro-daemon-clients.mjs +0 -125
- package/scripts/agent-eval/run-agent.sh +0 -34
- package/scripts/agent-eval/run-all.sh +0 -75
- package/scripts/agent-eval/run-arms.sh +0 -56
- package/scripts/agent-eval/seq-matrix.mjs +0 -137
- package/scripts/bench-arkts-init-rss.log +0 -0
- package/scripts/build-bundle.sh +0 -123
- package/scripts/exp_boundary_eval/README.md +0 -247
- package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-38.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-38.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/deveco_arm.cpython-38.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_all.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_all.cpython-38.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-38.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-38.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/setup.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/setup.cpython-38.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/win_mcp_launcher.cpython-38.pyc +0 -0
- package/scripts/exp_boundary_eval/_test_mcp_chain.py +0 -78
- package/scripts/exp_boundary_eval/_test_stdin.py +0 -8
- package/scripts/exp_boundary_eval/_utils.py +0 -1116
- package/scripts/exp_boundary_eval/analyze.py +0 -1313
- package/scripts/exp_boundary_eval/deveco_arm.py +0 -519
- package/scripts/exp_boundary_eval/run_all.py +0 -378
- package/scripts/exp_boundary_eval/run_one.py +0 -165
- package/scripts/exp_boundary_eval/run_session.py +0 -158
- package/scripts/exp_boundary_eval/setup.py +0 -120
- package/scripts/exp_boundary_eval/win_mcp_launcher.py +0 -73
- package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +0 -36
- package/scripts/exp_boundary_eval/win_node_launcher.py +0 -24
- package/scripts/extract-release-notes.mjs +0 -130
- package/scripts/local-install.sh +0 -41
- package/scripts/npm-sdk.js +0 -75
- package/scripts/npm-shim.js +0 -275
- package/scripts/ohos-sdk-publish.mjs +0 -133
- package/scripts/pack-npm.sh +0 -119
- package/scripts/prepare-release.mjs +0 -270
- package/scripts/probe-arkts-mem-why-run.log +0 -0
- package/scripts/probe-banner-livecard-ir.log +0 -0
- package/scripts/probe-cfwk-ast.stderr.log +0 -0
- package/scripts/probe-cfwk-ast.stdout.log +0 -0
- package/scripts/probe-cfwk-attr-shape.log +0 -0
- package/scripts/probe-cfwk-cfgdump.stderr.log +0 -0
- package/scripts/probe-cfwk-cfgdump.stdout.log +0 -0
- package/scripts/probe-cfwk-cvc.stderr.log +0 -0
- package/scripts/probe-cfwk-cvc.stdout.log +0 -0
- package/scripts/probe-cfwk-diag2.log +0 -0
- package/scripts/probe-cfwk-diag3.log +0 -0
- package/scripts/probe-cfwk-fedbg.stderr.log +0 -0
- package/scripts/probe-cfwk-fedbg.stdout.log +0 -0
- package/scripts/probe-cfwk-fileresult.log +0 -0
- package/scripts/probe-cfwk-fix.stderr.log +0 -0
- package/scripts/probe-cfwk-fix.stdout.log +0 -0
- package/scripts/probe-cfwk-fix2.stderr.log +0 -0
- package/scripts/probe-cfwk-fix2.stdout.log +0 -0
- package/scripts/probe-cfwk-fix3.stderr.log +0 -0
- package/scripts/probe-cfwk-fix3.stdout.log +0 -0
- package/scripts/probe-cfwk-foreach.log +0 -0
- package/scripts/probe-cfwk-getmethod-throw.log +0 -0
- package/scripts/probe-cfwk-hg-extract.log +0 -0
- package/scripts/probe-cfwk-pr1003-noprior.stderr.log +0 -0
- package/scripts/probe-cfwk-pr1003-noprior.stdout.log +0 -0
- package/scripts/probe-cfwk-pr1003.stderr.log +0 -0
- package/scripts/probe-cfwk-pr1003.stdout.log +0 -0
- package/scripts/probe-cfwk-preroot-noprior.stderr.log +0 -0
- package/scripts/probe-cfwk-preroot-noprior.stdout.log +0 -0
- package/scripts/probe-cfwk-preroot-prior.stderr.log +0 -0
- package/scripts/probe-cfwk-preroot-prior.stdout.log +0 -0
- package/scripts/probe-cfwk-preroot-skipstate.stderr.log +0 -0
- package/scripts/probe-cfwk-preroot-skipstate.stdout.log +0 -0
- package/scripts/probe-cfwk-resolve-sim.log +0 -0
- package/scripts/probe-cfwk-tree-shape.log +0 -0
- package/scripts/probe-cfwk-walk-abort.log +0 -0
- package/scripts/probe-cfwk.log +0 -0
- package/scripts/probe-force-index.log +0 -0
- package/scripts/probe-no-force-index.log +0 -0
- package/scripts/probe-samefile-ir.stderr.log +0 -0
- package/scripts/probe-samefile-ir.stdout.log +0 -224
- package/scripts/probe-sdk-vs-project.log +0 -0
- package/scripts/probe-viewtree-downgrade.log +0 -0
package/dist/db/queries.js
CHANGED
|
@@ -133,6 +133,7 @@ function rowToFileRecord(row) {
|
|
|
133
133
|
indexedAt: row.indexed_at,
|
|
134
134
|
nodeCount: row.node_count,
|
|
135
135
|
errors: row.errors ? (0, utils_1.safeJsonParse)(row.errors, undefined) : undefined,
|
|
136
|
+
generated: row.generated === 1,
|
|
136
137
|
};
|
|
137
138
|
}
|
|
138
139
|
/**
|
|
@@ -152,6 +153,11 @@ class QueryBuilder {
|
|
|
152
153
|
maxCacheSize = 1000;
|
|
153
154
|
/** Attached prebuilt OHOS API db (see arkts.ts). */
|
|
154
155
|
ohosApiDbPath = null;
|
|
156
|
+
/**
|
|
157
|
+
* When false, name/search lookups skip the project `nodes` table and only
|
|
158
|
+
* return attached `ohos_api` rows (`HOMEGRAPH_SOURCES=sdk`). Default true.
|
|
159
|
+
*/
|
|
160
|
+
includeProjectNodes = true;
|
|
155
161
|
// Prepared statements (lazily initialized)
|
|
156
162
|
stmts = {};
|
|
157
163
|
// Multi-row INSERT statements, cached per (statement kind × row count).
|
|
@@ -202,6 +208,16 @@ class QueryBuilder {
|
|
|
202
208
|
this.stmts = {};
|
|
203
209
|
this.batchStmts.clear();
|
|
204
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Toggle whether project-index nodes participate in lookups.
|
|
213
|
+
* SDK-only sessions set this false after opening the project db for ATTACH.
|
|
214
|
+
*/
|
|
215
|
+
setIncludeProjectNodes(include) {
|
|
216
|
+
this.includeProjectNodes = include;
|
|
217
|
+
}
|
|
218
|
+
getIncludeProjectNodes() {
|
|
219
|
+
return this.includeProjectNodes;
|
|
220
|
+
}
|
|
205
221
|
/** Attach a versioned OHOS API db for federated symbol lookup. */
|
|
206
222
|
attachOhosApiDb(dbPath) {
|
|
207
223
|
if (dbPath === this.ohosApiDbPath)
|
|
@@ -255,20 +271,20 @@ class QueryBuilder {
|
|
|
255
271
|
*/
|
|
256
272
|
insertNode(node) {
|
|
257
273
|
if (!this.stmts.insertNode) {
|
|
258
|
-
this.stmts.insertNode = this.db.prepare(`
|
|
259
|
-
INSERT OR REPLACE INTO nodes (
|
|
260
|
-
id, kind, name, qualified_name, file_path, language,
|
|
261
|
-
start_line, end_line, start_column, end_column,
|
|
262
|
-
docstring, signature, visibility,
|
|
263
|
-
is_exported, is_async, is_static, is_abstract,
|
|
264
|
-
decorators, type_parameters, return_type, updated_at
|
|
265
|
-
) VALUES (
|
|
266
|
-
@id, @kind, @name, @qualifiedName, @filePath, @language,
|
|
267
|
-
@startLine, @endLine, @startColumn, @endColumn,
|
|
268
|
-
@docstring, @signature, @visibility,
|
|
269
|
-
@isExported, @isAsync, @isStatic, @isAbstract,
|
|
270
|
-
@decorators, @typeParameters, @returnType, @updatedAt
|
|
271
|
-
)
|
|
274
|
+
this.stmts.insertNode = this.db.prepare(`
|
|
275
|
+
INSERT OR REPLACE INTO nodes (
|
|
276
|
+
id, kind, name, qualified_name, file_path, language,
|
|
277
|
+
start_line, end_line, start_column, end_column,
|
|
278
|
+
docstring, signature, visibility,
|
|
279
|
+
is_exported, is_async, is_static, is_abstract,
|
|
280
|
+
decorators, type_parameters, return_type, updated_at
|
|
281
|
+
) VALUES (
|
|
282
|
+
@id, @kind, @name, @qualifiedName, @filePath, @language,
|
|
283
|
+
@startLine, @endLine, @startColumn, @endColumn,
|
|
284
|
+
@docstring, @signature, @visibility,
|
|
285
|
+
@isExported, @isAsync, @isStatic, @isAbstract,
|
|
286
|
+
@decorators, @typeParameters, @returnType, @updatedAt
|
|
287
|
+
)
|
|
272
288
|
`);
|
|
273
289
|
}
|
|
274
290
|
// Validate required fields to prevent SQLite bind errors
|
|
@@ -364,29 +380,29 @@ class QueryBuilder {
|
|
|
364
380
|
*/
|
|
365
381
|
updateNode(node) {
|
|
366
382
|
if (!this.stmts.updateNode) {
|
|
367
|
-
this.stmts.updateNode = this.db.prepare(`
|
|
368
|
-
UPDATE nodes SET
|
|
369
|
-
kind = @kind,
|
|
370
|
-
name = @name,
|
|
371
|
-
qualified_name = @qualifiedName,
|
|
372
|
-
file_path = @filePath,
|
|
373
|
-
language = @language,
|
|
374
|
-
start_line = @startLine,
|
|
375
|
-
end_line = @endLine,
|
|
376
|
-
start_column = @startColumn,
|
|
377
|
-
end_column = @endColumn,
|
|
378
|
-
docstring = @docstring,
|
|
379
|
-
signature = @signature,
|
|
380
|
-
visibility = @visibility,
|
|
381
|
-
is_exported = @isExported,
|
|
382
|
-
is_async = @isAsync,
|
|
383
|
-
is_static = @isStatic,
|
|
384
|
-
is_abstract = @isAbstract,
|
|
385
|
-
decorators = @decorators,
|
|
386
|
-
type_parameters = @typeParameters,
|
|
387
|
-
return_type = @returnType,
|
|
388
|
-
updated_at = @updatedAt
|
|
389
|
-
WHERE id = @id
|
|
383
|
+
this.stmts.updateNode = this.db.prepare(`
|
|
384
|
+
UPDATE nodes SET
|
|
385
|
+
kind = @kind,
|
|
386
|
+
name = @name,
|
|
387
|
+
qualified_name = @qualifiedName,
|
|
388
|
+
file_path = @filePath,
|
|
389
|
+
language = @language,
|
|
390
|
+
start_line = @startLine,
|
|
391
|
+
end_line = @endLine,
|
|
392
|
+
start_column = @startColumn,
|
|
393
|
+
end_column = @endColumn,
|
|
394
|
+
docstring = @docstring,
|
|
395
|
+
signature = @signature,
|
|
396
|
+
visibility = @visibility,
|
|
397
|
+
is_exported = @isExported,
|
|
398
|
+
is_async = @isAsync,
|
|
399
|
+
is_static = @isStatic,
|
|
400
|
+
is_abstract = @isAbstract,
|
|
401
|
+
decorators = @decorators,
|
|
402
|
+
type_parameters = @typeParameters,
|
|
403
|
+
return_type = @returnType,
|
|
404
|
+
updated_at = @updatedAt
|
|
405
|
+
WHERE id = @id
|
|
390
406
|
`);
|
|
391
407
|
}
|
|
392
408
|
// Invalidate cache before update
|
|
@@ -518,12 +534,12 @@ class QueryBuilder {
|
|
|
518
534
|
const placeholders = variants.map(() => '?').join(', ');
|
|
519
535
|
const whens = variants.map(() => 'WHEN ? THEN ?').join(' ');
|
|
520
536
|
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
|
|
537
|
+
.prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
|
|
538
|
+
FROM name_segment_vocab
|
|
539
|
+
WHERE segment IN (${placeholders})
|
|
540
|
+
GROUP BY name
|
|
541
|
+
HAVING matches >= ?
|
|
542
|
+
ORDER BY matches DESC, length(name) ASC
|
|
527
543
|
LIMIT ?`)
|
|
528
544
|
.all(...variants.flatMap((v) => [v.segment, v.word]), ...variants.map((v) => v.segment), minWords, limit);
|
|
529
545
|
return rows;
|
|
@@ -535,7 +551,7 @@ class QueryBuilder {
|
|
|
535
551
|
return new Map();
|
|
536
552
|
const placeholders = segments.map(() => '?').join(', ');
|
|
537
553
|
const rows = this.db
|
|
538
|
-
.prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
|
|
554
|
+
.prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
|
|
539
555
|
WHERE segment IN (${placeholders}) GROUP BY segment`)
|
|
540
556
|
.all(...segments);
|
|
541
557
|
return new Map(rows.map((r) => [r.segment, r.n]));
|
|
@@ -695,15 +711,15 @@ class QueryBuilder {
|
|
|
695
711
|
// protobuf stub) outranks the real `server/etcdserver/server.go`
|
|
696
712
|
// (470 edges) by 4×, and the boost would push the agent toward
|
|
697
713
|
// generated code.
|
|
698
|
-
this.stmts.getDominantFile = this.db.prepare(`
|
|
699
|
-
SELECT n.file_path AS file_path, COUNT(*) AS edge_count
|
|
700
|
-
FROM edges e
|
|
701
|
-
JOIN nodes n ON e.source = n.id
|
|
702
|
-
JOIN nodes m ON e.target = m.id
|
|
703
|
-
WHERE n.file_path = m.file_path
|
|
704
|
-
GROUP BY n.file_path
|
|
705
|
-
ORDER BY edge_count DESC
|
|
706
|
-
LIMIT 20
|
|
714
|
+
this.stmts.getDominantFile = this.db.prepare(`
|
|
715
|
+
SELECT n.file_path AS file_path, COUNT(*) AS edge_count
|
|
716
|
+
FROM edges e
|
|
717
|
+
JOIN nodes n ON e.source = n.id
|
|
718
|
+
JOIN nodes m ON e.target = m.id
|
|
719
|
+
WHERE n.file_path = m.file_path
|
|
720
|
+
GROUP BY n.file_path
|
|
721
|
+
ORDER BY edge_count DESC
|
|
722
|
+
LIMIT 20
|
|
707
723
|
`);
|
|
708
724
|
}
|
|
709
725
|
const rows = this.stmts.getDominantFile.all();
|
|
@@ -730,13 +746,13 @@ class QueryBuilder {
|
|
|
730
746
|
*/
|
|
731
747
|
getTopRouteFile() {
|
|
732
748
|
if (!this.stmts.getTopRouteFile) {
|
|
733
|
-
this.stmts.getTopRouteFile = this.db.prepare(`
|
|
734
|
-
SELECT file_path, COUNT(*) AS cnt
|
|
735
|
-
FROM nodes
|
|
736
|
-
WHERE kind = 'route'
|
|
737
|
-
GROUP BY file_path
|
|
738
|
-
ORDER BY cnt DESC
|
|
739
|
-
LIMIT 20
|
|
749
|
+
this.stmts.getTopRouteFile = this.db.prepare(`
|
|
750
|
+
SELECT file_path, COUNT(*) AS cnt
|
|
751
|
+
FROM nodes
|
|
752
|
+
WHERE kind = 'route'
|
|
753
|
+
GROUP BY file_path
|
|
754
|
+
ORDER BY cnt DESC
|
|
755
|
+
LIMIT 20
|
|
740
756
|
`);
|
|
741
757
|
}
|
|
742
758
|
const rows = this.stmts.getTopRouteFile.all();
|
|
@@ -767,21 +783,21 @@ class QueryBuilder {
|
|
|
767
783
|
// Edge kind varies across framework resolvers: Spring/Rails/
|
|
768
784
|
// Laravel/Drupal emit `references`, Express emits `calls`. Accept
|
|
769
785
|
// both — the semantic is the same (route → its handler).
|
|
770
|
-
this.stmts.getRoutingManifest = this.db.prepare(`
|
|
771
|
-
SELECT
|
|
772
|
-
r.name AS url,
|
|
773
|
-
h.name AS handler,
|
|
774
|
-
h.file_path AS handler_file,
|
|
775
|
-
h.start_line AS handler_line,
|
|
776
|
-
h.kind AS handler_kind
|
|
777
|
-
FROM nodes r
|
|
778
|
-
JOIN edges e ON e.source = r.id
|
|
779
|
-
JOIN nodes h ON e.target = h.id
|
|
780
|
-
WHERE r.kind = 'route'
|
|
781
|
-
AND e.kind IN ('references', 'calls')
|
|
782
|
-
AND h.kind IN ('function', 'method', 'class')
|
|
783
|
-
ORDER BY r.file_path, r.start_line
|
|
784
|
-
LIMIT ?
|
|
786
|
+
this.stmts.getRoutingManifest = this.db.prepare(`
|
|
787
|
+
SELECT
|
|
788
|
+
r.name AS url,
|
|
789
|
+
h.name AS handler,
|
|
790
|
+
h.file_path AS handler_file,
|
|
791
|
+
h.start_line AS handler_line,
|
|
792
|
+
h.kind AS handler_kind
|
|
793
|
+
FROM nodes r
|
|
794
|
+
JOIN edges e ON e.source = r.id
|
|
795
|
+
JOIN nodes h ON e.target = h.id
|
|
796
|
+
WHERE r.kind = 'route'
|
|
797
|
+
AND e.kind IN ('references', 'calls')
|
|
798
|
+
AND h.kind IN ('function', 'method', 'class')
|
|
799
|
+
ORDER BY r.file_path, r.start_line
|
|
800
|
+
LIMIT ?
|
|
785
801
|
`);
|
|
786
802
|
}
|
|
787
803
|
const rows = this.stmts.getRoutingManifest.all(limit);
|
|
@@ -878,15 +894,21 @@ class QueryBuilder {
|
|
|
878
894
|
* Get nodes by exact name match (uses idx_nodes_name index)
|
|
879
895
|
*/
|
|
880
896
|
getNodesByName(name) {
|
|
881
|
-
|
|
882
|
-
|
|
897
|
+
const main = [];
|
|
898
|
+
if (this.includeProjectNodes) {
|
|
899
|
+
if (!this.stmts.getNodesByName) {
|
|
900
|
+
// Content-derived order (not insertion/rowid order): sync appends nodes
|
|
901
|
+
// as files change, so without ORDER BY the same tree can resolve
|
|
902
|
+
// differently than a full rebuild that writes in scan order.
|
|
903
|
+
this.stmts.getNodesByName = this.db.prepare('SELECT * FROM nodes WHERE name = ? ORDER BY file_path, start_line');
|
|
904
|
+
}
|
|
905
|
+
const rows = this.stmts.getNodesByName.all(name);
|
|
906
|
+
main.push(...rows.map(rowToNode));
|
|
883
907
|
}
|
|
884
|
-
const rows = this.stmts.getNodesByName.all(name);
|
|
885
|
-
const main = rows.map(rowToNode);
|
|
886
908
|
if (!this.hasOhosApiAttached())
|
|
887
909
|
return main;
|
|
888
910
|
const apiRows = this.db
|
|
889
|
-
.prepare('SELECT * FROM ohos_api.nodes WHERE name = ?')
|
|
911
|
+
.prepare('SELECT * FROM ohos_api.nodes WHERE name = ? ORDER BY file_path, start_line')
|
|
890
912
|
.all(name);
|
|
891
913
|
const seen = new Set(main.map((n) => n.id));
|
|
892
914
|
const api = apiRows.map((r) => this.mapOhosApiNodeRow(r)).filter((n) => !seen.has(n.id));
|
|
@@ -942,12 +964,17 @@ class QueryBuilder {
|
|
|
942
964
|
const text = parsed.text;
|
|
943
965
|
const kinds = mergedKinds;
|
|
944
966
|
const languages = mergedLanguages;
|
|
967
|
+
// SDK-only: skip project FTS entirely; federate OHOS API hits only.
|
|
968
|
+
if (!this.includeProjectNodes) {
|
|
969
|
+
if (!this.hasOhosApiAttached() || text.length < 2)
|
|
970
|
+
return [];
|
|
971
|
+
return this.mergeOhosApiTextSearch(text, { kinds, languages, limit }, []);
|
|
972
|
+
}
|
|
945
973
|
// First try FTS5 with prefix matching
|
|
946
974
|
let results = text
|
|
947
975
|
? this.searchNodesFTS(text, { kinds, languages, limit, offset })
|
|
948
976
|
// Over-fetch by 5× when running filter-only (no text). The
|
|
949
|
-
// post-scoring path: + name: filters can be very selective, so
|
|
950
|
-
// a smaller multiplier risks returning fewer than `limit`
|
|
977
|
+
// post-scoring path: + name: filters can be very selective, so // a smaller multiplier risks returning fewer than `limit`
|
|
951
978
|
// results despite the DB having plenty of matches.
|
|
952
979
|
: this.searchAllByFilters({ kinds, languages, limit: limit * 5 });
|
|
953
980
|
// If no FTS results, try LIKE-based substring search
|
|
@@ -1036,10 +1063,10 @@ class QueryBuilder {
|
|
|
1036
1063
|
const seen = new Set(existing.map((r) => r.node.id));
|
|
1037
1064
|
const merged = [...existing];
|
|
1038
1065
|
const apiLimit = Math.min(20, Math.max(5, Math.floor(limit / 4)));
|
|
1039
|
-
let sql = `
|
|
1040
|
-
SELECT nodes.*, 0.9 as score
|
|
1041
|
-
FROM ohos_api.nodes
|
|
1042
|
-
WHERE (name LIKE ? OR qualified_name LIKE ?)
|
|
1066
|
+
let sql = `
|
|
1067
|
+
SELECT nodes.*, 0.9 as score
|
|
1068
|
+
FROM ohos_api.nodes
|
|
1069
|
+
WHERE (name LIKE ? OR qualified_name LIKE ?)
|
|
1043
1070
|
`;
|
|
1044
1071
|
const pattern = `%${text}%`;
|
|
1045
1072
|
const params = [pattern, pattern];
|
|
@@ -1178,11 +1205,11 @@ class QueryBuilder {
|
|
|
1178
1205
|
// Fetch 5x requested limit so post-hoc rescoring (kindBonus, pathRelevance,
|
|
1179
1206
|
// nameMatchBonus) can promote results that BM25 alone undervalues.
|
|
1180
1207
|
const ftsLimit = Math.max(limit * 5, 100);
|
|
1181
|
-
let sql = `
|
|
1182
|
-
SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
|
|
1183
|
-
FROM nodes_fts
|
|
1184
|
-
JOIN nodes ON nodes_fts.id = nodes.id
|
|
1185
|
-
WHERE nodes_fts MATCH ?
|
|
1208
|
+
let sql = `
|
|
1209
|
+
SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
|
|
1210
|
+
FROM nodes_fts
|
|
1211
|
+
JOIN nodes ON nodes_fts.id = nodes.id
|
|
1212
|
+
WHERE nodes_fts MATCH ?
|
|
1186
1213
|
`;
|
|
1187
1214
|
const params = [ftsQuery];
|
|
1188
1215
|
if (kinds && kinds.length > 0) {
|
|
@@ -1213,21 +1240,21 @@ class QueryBuilder {
|
|
|
1213
1240
|
*/
|
|
1214
1241
|
searchNodesLike(query, options) {
|
|
1215
1242
|
const { kinds, languages, limit = 100, offset = 0 } = options;
|
|
1216
|
-
let sql = `
|
|
1217
|
-
SELECT nodes.*,
|
|
1218
|
-
CASE
|
|
1219
|
-
WHEN name = ? THEN 1.0
|
|
1220
|
-
WHEN name LIKE ? THEN 0.9
|
|
1221
|
-
WHEN name LIKE ? THEN 0.8
|
|
1222
|
-
WHEN qualified_name LIKE ? THEN 0.7
|
|
1223
|
-
ELSE 0.5
|
|
1224
|
-
END as score
|
|
1225
|
-
FROM nodes
|
|
1226
|
-
WHERE (
|
|
1227
|
-
name LIKE ? OR
|
|
1228
|
-
qualified_name LIKE ? OR
|
|
1229
|
-
name LIKE ?
|
|
1230
|
-
)
|
|
1243
|
+
let sql = `
|
|
1244
|
+
SELECT nodes.*,
|
|
1245
|
+
CASE
|
|
1246
|
+
WHEN name = ? THEN 1.0
|
|
1247
|
+
WHEN name LIKE ? THEN 0.9
|
|
1248
|
+
WHEN name LIKE ? THEN 0.8
|
|
1249
|
+
WHEN qualified_name LIKE ? THEN 0.7
|
|
1250
|
+
ELSE 0.5
|
|
1251
|
+
END as score
|
|
1252
|
+
FROM nodes
|
|
1253
|
+
WHERE (
|
|
1254
|
+
name LIKE ? OR
|
|
1255
|
+
qualified_name LIKE ? OR
|
|
1256
|
+
name LIKE ?
|
|
1257
|
+
)
|
|
1231
1258
|
`;
|
|
1232
1259
|
// Pattern variants for better matching
|
|
1233
1260
|
const exactMatch = query;
|
|
@@ -1272,6 +1299,42 @@ class QueryBuilder {
|
|
|
1272
1299
|
if (names.length === 0)
|
|
1273
1300
|
return [];
|
|
1274
1301
|
const { kinds, languages, limit = 50 } = options;
|
|
1302
|
+
// SDK-only: skip project co-location passes; exact-name against ohos_api only.
|
|
1303
|
+
if (!this.includeProjectNodes) {
|
|
1304
|
+
if (!this.hasOhosApiAttached())
|
|
1305
|
+
return [];
|
|
1306
|
+
const perNameLimit = Math.max(8, Math.ceil(limit / names.length));
|
|
1307
|
+
const allResults = [];
|
|
1308
|
+
const seenIds = new Set();
|
|
1309
|
+
for (const name of names) {
|
|
1310
|
+
let apiSql = `
|
|
1311
|
+
SELECT nodes.*, 0.95 as score
|
|
1312
|
+
FROM ohos_api.nodes
|
|
1313
|
+
WHERE name COLLATE NOCASE = ?
|
|
1314
|
+
`;
|
|
1315
|
+
const apiParams = [name];
|
|
1316
|
+
if (kinds && kinds.length > 0) {
|
|
1317
|
+
apiSql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
|
|
1318
|
+
apiParams.push(...kinds);
|
|
1319
|
+
}
|
|
1320
|
+
if (languages && languages.length > 0) {
|
|
1321
|
+
apiSql += ` AND language IN (${languages.map(() => '?').join(',')})`;
|
|
1322
|
+
apiParams.push(...languages);
|
|
1323
|
+
}
|
|
1324
|
+
apiSql += ' LIMIT ?';
|
|
1325
|
+
apiParams.push(perNameLimit);
|
|
1326
|
+
const apiRows = this.db.prepare(apiSql).all(...apiParams);
|
|
1327
|
+
for (const row of apiRows) {
|
|
1328
|
+
const node = this.mapOhosApiNodeRow(row);
|
|
1329
|
+
if (seenIds.has(node.id))
|
|
1330
|
+
continue;
|
|
1331
|
+
seenIds.add(node.id);
|
|
1332
|
+
allResults.push({ node, score: row.score });
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
allResults.sort((a, b) => b.score - a.score);
|
|
1336
|
+
return allResults.slice(0, limit);
|
|
1337
|
+
}
|
|
1275
1338
|
// Two-pass approach to handle common names (e.g., "run" has 40+ matches):
|
|
1276
1339
|
// Pass 1: Find which files contain distinctive (rare) symbols from the query.
|
|
1277
1340
|
// Pass 2: Query each name, boosting results that co-locate with distinctive symbols.
|
|
@@ -1301,10 +1364,10 @@ class QueryBuilder {
|
|
|
1301
1364
|
const allResults = [];
|
|
1302
1365
|
const seenIds = new Set();
|
|
1303
1366
|
for (const name of names) {
|
|
1304
|
-
let sql = `
|
|
1305
|
-
SELECT nodes.*, 1.0 as score
|
|
1306
|
-
FROM nodes
|
|
1307
|
-
WHERE name COLLATE NOCASE = ?
|
|
1367
|
+
let sql = `
|
|
1368
|
+
SELECT nodes.*, 1.0 as score
|
|
1369
|
+
FROM nodes
|
|
1370
|
+
WHERE name COLLATE NOCASE = ?
|
|
1308
1371
|
`;
|
|
1309
1372
|
const params = [name];
|
|
1310
1373
|
if (kinds && kinds.length > 0) {
|
|
@@ -1335,10 +1398,10 @@ class QueryBuilder {
|
|
|
1335
1398
|
allResults.push(r);
|
|
1336
1399
|
}
|
|
1337
1400
|
if (this.hasOhosApiAttached()) {
|
|
1338
|
-
let apiSql = `
|
|
1339
|
-
SELECT nodes.*, 0.95 as score
|
|
1340
|
-
FROM ohos_api.nodes
|
|
1341
|
-
WHERE name COLLATE NOCASE = ?
|
|
1401
|
+
let apiSql = `
|
|
1402
|
+
SELECT nodes.*, 0.95 as score
|
|
1403
|
+
FROM ohos_api.nodes
|
|
1404
|
+
WHERE name COLLATE NOCASE = ?
|
|
1342
1405
|
`;
|
|
1343
1406
|
const apiParams = [name];
|
|
1344
1407
|
if (kinds && kinds.length > 0) {
|
|
@@ -1374,10 +1437,10 @@ class QueryBuilder {
|
|
|
1374
1437
|
*/
|
|
1375
1438
|
findNodesByNameSubstring(substring, options = {}) {
|
|
1376
1439
|
const { kinds, languages, limit = 30, excludePrefix } = options;
|
|
1377
|
-
let sql = `
|
|
1378
|
-
SELECT nodes.*, 1.0 as score
|
|
1379
|
-
FROM nodes
|
|
1380
|
-
WHERE name LIKE ?
|
|
1440
|
+
let sql = `
|
|
1441
|
+
SELECT nodes.*, 1.0 as score
|
|
1442
|
+
FROM nodes
|
|
1443
|
+
WHERE name LIKE ?
|
|
1381
1444
|
`;
|
|
1382
1445
|
const params = [`%${substring}%`];
|
|
1383
1446
|
// Exclude prefix matches (handled by FTS-based prefix search in Step 2b)
|
|
@@ -1409,9 +1472,9 @@ class QueryBuilder {
|
|
|
1409
1472
|
*/
|
|
1410
1473
|
insertEdge(edge) {
|
|
1411
1474
|
if (!this.stmts.insertEdge) {
|
|
1412
|
-
this.stmts.insertEdge = this.db.prepare(`
|
|
1413
|
-
INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance)
|
|
1414
|
-
VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance)
|
|
1475
|
+
this.stmts.insertEdge = this.db.prepare(`
|
|
1476
|
+
INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance)
|
|
1477
|
+
VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance)
|
|
1415
1478
|
`);
|
|
1416
1479
|
}
|
|
1417
1480
|
this.stmts.insertEdge.run({
|
|
@@ -1538,12 +1601,12 @@ class QueryBuilder {
|
|
|
1538
1601
|
* it. One indexed query (idx_nodes_file_path + idx_edges_target_kind).
|
|
1539
1602
|
*/
|
|
1540
1603
|
getDependentFilePaths(filePath) {
|
|
1541
|
-
const sql = `SELECT DISTINCT src.file_path AS fp
|
|
1542
|
-
FROM edges e
|
|
1543
|
-
JOIN nodes tgt ON tgt.id = e.target
|
|
1544
|
-
JOIN nodes src ON src.id = e.source
|
|
1545
|
-
WHERE tgt.file_path = ?
|
|
1546
|
-
AND e.kind != 'contains'
|
|
1604
|
+
const sql = `SELECT DISTINCT src.file_path AS fp
|
|
1605
|
+
FROM edges e
|
|
1606
|
+
JOIN nodes tgt ON tgt.id = e.target
|
|
1607
|
+
JOIN nodes src ON src.id = e.source
|
|
1608
|
+
WHERE tgt.file_path = ?
|
|
1609
|
+
AND e.kind != 'contains'
|
|
1547
1610
|
AND src.file_path != ?`;
|
|
1548
1611
|
const rows = this.db.prepare(sql).all(filePath, filePath);
|
|
1549
1612
|
return rows.map((r) => r.fp);
|
|
@@ -1555,12 +1618,12 @@ class QueryBuilder {
|
|
|
1555
1618
|
* (all kinds except `contains`); same reason imports-only is insufficient.
|
|
1556
1619
|
*/
|
|
1557
1620
|
getDependencyFilePaths(filePath) {
|
|
1558
|
-
const sql = `SELECT DISTINCT tgt.file_path AS fp
|
|
1559
|
-
FROM edges e
|
|
1560
|
-
JOIN nodes src ON src.id = e.source
|
|
1561
|
-
JOIN nodes tgt ON tgt.id = e.target
|
|
1562
|
-
WHERE src.file_path = ?
|
|
1563
|
-
AND e.kind != 'contains'
|
|
1621
|
+
const sql = `SELECT DISTINCT tgt.file_path AS fp
|
|
1622
|
+
FROM edges e
|
|
1623
|
+
JOIN nodes src ON src.id = e.source
|
|
1624
|
+
JOIN nodes tgt ON tgt.id = e.target
|
|
1625
|
+
WHERE src.file_path = ?
|
|
1626
|
+
AND e.kind != 'contains'
|
|
1564
1627
|
AND tgt.file_path != ?`;
|
|
1565
1628
|
const rows = this.db.prepare(sql).all(filePath, filePath);
|
|
1566
1629
|
return rows.map((r) => r.fp);
|
|
@@ -1576,13 +1639,13 @@ class QueryBuilder {
|
|
|
1576
1639
|
* {@link getDependentFilePaths}: all kinds except `contains`.
|
|
1577
1640
|
*/
|
|
1578
1641
|
getCrossFileIncomingEdgesWithTarget(filePath) {
|
|
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
|
|
1581
|
-
FROM edges e
|
|
1582
|
-
JOIN nodes tgt ON tgt.id = e.target
|
|
1583
|
-
JOIN nodes src ON src.id = e.source
|
|
1584
|
-
WHERE tgt.file_path = ?
|
|
1585
|
-
AND e.kind != 'contains'
|
|
1642
|
+
const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
|
|
1643
|
+
src.file_path AS source_file_path, src.language AS source_language
|
|
1644
|
+
FROM edges e
|
|
1645
|
+
JOIN nodes tgt ON tgt.id = e.target
|
|
1646
|
+
JOIN nodes src ON src.id = e.source
|
|
1647
|
+
WHERE tgt.file_path = ?
|
|
1648
|
+
AND e.kind != 'contains'
|
|
1586
1649
|
AND src.file_path != ?`;
|
|
1587
1650
|
const rows = this.db.prepare(sql).all(filePath, filePath);
|
|
1588
1651
|
return rows.map(row => ({
|
|
@@ -1599,10 +1662,10 @@ class QueryBuilder {
|
|
|
1599
1662
|
*/
|
|
1600
1663
|
deleteArkTSCrossFileCallEdges() {
|
|
1601
1664
|
const result = this.db
|
|
1602
|
-
.prepare(`DELETE FROM edges
|
|
1603
|
-
WHERE kind = 'calls'
|
|
1604
|
-
AND provenance = 'heuristic'
|
|
1605
|
-
AND metadata LIKE '%"synthesizedBy":"arkanalyzer"%'
|
|
1665
|
+
.prepare(`DELETE FROM edges
|
|
1666
|
+
WHERE kind = 'calls'
|
|
1667
|
+
AND provenance = 'heuristic'
|
|
1668
|
+
AND metadata LIKE '%"synthesizedBy":"arkanalyzer"%'
|
|
1606
1669
|
AND metadata LIKE '%"sourceFile"%'`)
|
|
1607
1670
|
.run();
|
|
1608
1671
|
return result.changes;
|
|
@@ -1615,17 +1678,18 @@ class QueryBuilder {
|
|
|
1615
1678
|
*/
|
|
1616
1679
|
upsertFile(file) {
|
|
1617
1680
|
if (!this.stmts.upsertFile) {
|
|
1618
|
-
this.stmts.upsertFile = this.db.prepare(`
|
|
1619
|
-
INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, errors)
|
|
1620
|
-
VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @errors)
|
|
1621
|
-
ON CONFLICT(path) DO UPDATE SET
|
|
1622
|
-
content_hash = @contentHash,
|
|
1623
|
-
language = @language,
|
|
1624
|
-
size = @size,
|
|
1625
|
-
modified_at = @modifiedAt,
|
|
1626
|
-
indexed_at = @indexedAt,
|
|
1627
|
-
node_count = @nodeCount,
|
|
1628
|
-
errors = @errors
|
|
1681
|
+
this.stmts.upsertFile = this.db.prepare(`
|
|
1682
|
+
INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, errors, generated)
|
|
1683
|
+
VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @errors, @generated)
|
|
1684
|
+
ON CONFLICT(path) DO UPDATE SET
|
|
1685
|
+
content_hash = @contentHash,
|
|
1686
|
+
language = @language,
|
|
1687
|
+
size = @size,
|
|
1688
|
+
modified_at = @modifiedAt,
|
|
1689
|
+
indexed_at = @indexedAt,
|
|
1690
|
+
node_count = @nodeCount,
|
|
1691
|
+
errors = @errors,
|
|
1692
|
+
generated = @generated
|
|
1629
1693
|
`);
|
|
1630
1694
|
}
|
|
1631
1695
|
this.stmts.upsertFile.run({
|
|
@@ -1637,6 +1701,7 @@ class QueryBuilder {
|
|
|
1637
1701
|
indexedAt: file.indexedAt,
|
|
1638
1702
|
nodeCount: file.nodeCount,
|
|
1639
1703
|
errors: file.errors ? JSON.stringify(file.errors) : null,
|
|
1704
|
+
generated: file.generated ? 1 : 0,
|
|
1640
1705
|
});
|
|
1641
1706
|
}
|
|
1642
1707
|
/**
|
|
@@ -1699,9 +1764,9 @@ class QueryBuilder {
|
|
|
1699
1764
|
*/
|
|
1700
1765
|
insertUnresolvedRef(ref) {
|
|
1701
1766
|
if (!this.stmts.insertUnresolved) {
|
|
1702
|
-
this.stmts.insertUnresolved = this.db.prepare(`
|
|
1703
|
-
INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language)
|
|
1704
|
-
VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language)
|
|
1767
|
+
this.stmts.insertUnresolved = this.db.prepare(`
|
|
1768
|
+
INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language)
|
|
1769
|
+
VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language)
|
|
1705
1770
|
`);
|
|
1706
1771
|
}
|
|
1707
1772
|
this.stmts.insertUnresolved.run({
|
|
@@ -1994,6 +2059,107 @@ class QueryBuilder {
|
|
|
1994
2059
|
}
|
|
1995
2060
|
return [...names];
|
|
1996
2061
|
}
|
|
2062
|
+
/**
|
|
2063
|
+
* Resolution edges targeting any of the given node names — candidates for the
|
|
2064
|
+
* sync rebind pass when a definition set changes. Includes source file/language
|
|
2065
|
+
* so a dropped edge can be resurrected as its original unresolved ref.
|
|
2066
|
+
*
|
|
2067
|
+
* Names matching more than `perNameCeiling` edges are skipped entirely, same
|
|
2068
|
+
* rationale and same default as {@link getRetryableFailedReferences}: at that
|
|
2069
|
+
* population the name is generic (`get`, `clear`, …); one definition changing
|
|
2070
|
+
* won't flip most of them, and rebinding an arbitrary subset is both wasted
|
|
2071
|
+
* work and incoherent coverage.
|
|
2072
|
+
*/
|
|
2073
|
+
getResolutionEdgesByTargetName(names, perNameCeiling = 500) {
|
|
2074
|
+
if (names.length === 0)
|
|
2075
|
+
return [];
|
|
2076
|
+
// Pass 1: per-name edge counts, chunked under the SQLite parameter limit.
|
|
2077
|
+
const keep = [];
|
|
2078
|
+
for (let i = 0; i < names.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
2079
|
+
const chunk = names.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
2080
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
2081
|
+
const counts = this.db
|
|
2082
|
+
.prepare(`SELECT tgt.name AS name, COUNT(*) AS count
|
|
2083
|
+
FROM edges e
|
|
2084
|
+
JOIN nodes tgt ON tgt.id = e.target
|
|
2085
|
+
WHERE tgt.name IN (${placeholders})
|
|
2086
|
+
AND (e.provenance IS NULL OR e.provenance != 'heuristic')
|
|
2087
|
+
GROUP BY tgt.name`)
|
|
2088
|
+
.all(...chunk);
|
|
2089
|
+
for (const row of counts) {
|
|
2090
|
+
if (row.count <= perNameCeiling)
|
|
2091
|
+
keep.push(row.name);
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
if (keep.length === 0)
|
|
2095
|
+
return [];
|
|
2096
|
+
// Pass 2: load the surviving edges with the source file context a
|
|
2097
|
+
// resurrection needs.
|
|
2098
|
+
const out = [];
|
|
2099
|
+
for (let i = 0; i < keep.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
2100
|
+
const chunk = keep.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
2101
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
2102
|
+
const rows = this.db
|
|
2103
|
+
.prepare(`SELECT e.*, src.file_path AS source_file_path, src.language AS source_language
|
|
2104
|
+
FROM edges e
|
|
2105
|
+
JOIN nodes tgt ON tgt.id = e.target
|
|
2106
|
+
JOIN nodes src ON src.id = e.source
|
|
2107
|
+
WHERE tgt.name IN (${placeholders})
|
|
2108
|
+
AND (e.provenance IS NULL OR e.provenance != 'heuristic')`)
|
|
2109
|
+
.all(...chunk);
|
|
2110
|
+
for (const row of rows) {
|
|
2111
|
+
out.push({
|
|
2112
|
+
...rowToEdge(row),
|
|
2113
|
+
edgeId: row.id,
|
|
2114
|
+
sourceFilePath: row.source_file_path,
|
|
2115
|
+
sourceLanguage: row.source_language,
|
|
2116
|
+
});
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
return out;
|
|
2120
|
+
}
|
|
2121
|
+
/** Delete edges by primary key — the rebind pass's half of a re-resolution. */
|
|
2122
|
+
deleteEdgesByIds(edgeIds) {
|
|
2123
|
+
if (edgeIds.length === 0)
|
|
2124
|
+
return 0;
|
|
2125
|
+
let changed = 0;
|
|
2126
|
+
this.db.transaction(() => {
|
|
2127
|
+
for (let i = 0; i < edgeIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
2128
|
+
const chunk = edgeIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
2129
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
2130
|
+
changed += this.db.prepare(`DELETE FROM edges WHERE id IN (${placeholders})`).run(...chunk).changes;
|
|
2131
|
+
}
|
|
2132
|
+
})();
|
|
2133
|
+
return changed;
|
|
2134
|
+
}
|
|
2135
|
+
/**
|
|
2136
|
+
* Distinct `file\0name` pairs defined by the given files — the shape sync's
|
|
2137
|
+
* definition delta needs.
|
|
2138
|
+
*
|
|
2139
|
+
* Deliberately NOT `getNodeNamesByFiles`: a bare name set is taken over the
|
|
2140
|
+
* WHOLE changed batch, so a name that moves between two files in one commit
|
|
2141
|
+
* (or exists in one changed file and is newly added to another) appears on
|
|
2142
|
+
* both sides and cancels out of the symmetric difference — even though a
|
|
2143
|
+
* definition genuinely appeared or vanished and every reference to that name
|
|
2144
|
+
* repo-wide may now bind elsewhere. Keying by file makes each definition its
|
|
2145
|
+
* own fact, so the move is seen as one removal plus one addition.
|
|
2146
|
+
*/
|
|
2147
|
+
getNodeNamePairsByFiles(filePaths) {
|
|
2148
|
+
const pairs = new Set();
|
|
2149
|
+
if (filePaths.length === 0)
|
|
2150
|
+
return pairs;
|
|
2151
|
+
for (let i = 0; i < filePaths.length; i += SQLITE_PARAM_CHUNK_SIZE) {
|
|
2152
|
+
const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
|
|
2153
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
2154
|
+
const rows = this.db
|
|
2155
|
+
.prepare(`SELECT DISTINCT file_path, name FROM nodes WHERE file_path IN (${placeholders})`)
|
|
2156
|
+
.all(...chunk);
|
|
2157
|
+
// NUL-joined: a path or a symbol name can contain a space, never a NUL.
|
|
2158
|
+
for (const row of rows)
|
|
2159
|
+
pairs.add(`${row.file_path}\0${row.name}`);
|
|
2160
|
+
}
|
|
2161
|
+
return pairs;
|
|
2162
|
+
}
|
|
1997
2163
|
/**
|
|
1998
2164
|
* Get unresolved references scoped to specific file paths.
|
|
1999
2165
|
* Uses the idx_unresolved_file_path index for efficient lookup.
|
|
@@ -2085,11 +2251,11 @@ class QueryBuilder {
|
|
|
2085
2251
|
*/
|
|
2086
2252
|
getStats() {
|
|
2087
2253
|
// Single query for all three aggregate counts
|
|
2088
|
-
const counts = this.db.prepare(`
|
|
2089
|
-
SELECT
|
|
2090
|
-
(SELECT COUNT(*) FROM nodes) AS node_count,
|
|
2091
|
-
(SELECT COUNT(*) FROM edges) AS edge_count,
|
|
2092
|
-
(SELECT COUNT(*) FROM files) AS file_count
|
|
2254
|
+
const counts = this.db.prepare(`
|
|
2255
|
+
SELECT
|
|
2256
|
+
(SELECT COUNT(*) FROM nodes) AS node_count,
|
|
2257
|
+
(SELECT COUNT(*) FROM edges) AS edge_count,
|
|
2258
|
+
(SELECT COUNT(*) FROM files) AS file_count
|
|
2093
2259
|
`).get();
|
|
2094
2260
|
const nodesByKind = {};
|
|
2095
2261
|
const nodeKindRows = this.db
|
|
@@ -2120,6 +2286,7 @@ class QueryBuilder {
|
|
|
2120
2286
|
edgesByKind,
|
|
2121
2287
|
filesByLanguage,
|
|
2122
2288
|
dbSizeBytes: 0, // Set by caller using DatabaseConnection.getSize()
|
|
2289
|
+
walSizeBytes: 0, // Set by caller using DatabaseConnection.getWalSizeBytes()
|
|
2123
2290
|
lastUpdated: Date.now(),
|
|
2124
2291
|
};
|
|
2125
2292
|
}
|