homegraph 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +268 -243
- package/dist/arkts/ohos-api-index.d.ts +15 -0
- package/dist/arkts/ohos-api-index.d.ts.map +1 -0
- package/dist/arkts/ohos-api-index.js +190 -0
- package/dist/arkts/ohos-api-index.js.map +1 -0
- package/dist/arkts/ohos-sdk-input.d.ts +36 -0
- package/dist/arkts/ohos-sdk-input.d.ts.map +1 -0
- package/dist/arkts/ohos-sdk-input.js +214 -0
- package/dist/arkts/ohos-sdk-input.js.map +1 -0
- package/dist/bin/command-supervision.d.ts +12 -0
- package/dist/bin/command-supervision.d.ts.map +1 -0
- package/dist/bin/command-supervision.js +86 -0
- package/dist/bin/command-supervision.js.map +1 -0
- package/dist/bin/homegraph.d.ts +1 -1
- package/dist/bin/homegraph.js +971 -71
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/db/index.d.ts +20 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +39 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +58 -19
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/queries.d.ts +14 -0
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +314 -143
- package/dist/db/queries.js.map +1 -1
- package/dist/db/schema.sql +172 -152
- package/dist/directory.d.ts +32 -0
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +88 -5
- package/dist/directory.js.map +1 -1
- package/dist/extraction/arkts-batch-worker.d.ts +2 -0
- package/dist/extraction/arkts-batch-worker.d.ts.map +1 -0
- package/dist/extraction/arkts-batch-worker.js +28 -0
- package/dist/extraction/arkts-batch-worker.js.map +1 -0
- package/dist/extraction/context.d.ts +11 -0
- package/dist/extraction/context.d.ts.map +1 -1
- package/dist/extraction/context.js +20 -0
- package/dist/extraction/context.js.map +1 -1
- package/dist/extraction/index.d.ts +16 -2
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +619 -380
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts-state-decorators.d.ts +13 -0
- package/dist/extraction/languages/arkts-state-decorators.d.ts.map +1 -0
- package/dist/extraction/languages/arkts-state-decorators.js +26 -0
- package/dist/extraction/languages/arkts-state-decorators.js.map +1 -0
- package/dist/extraction/languages/arkts-viewtree.d.ts +4 -2
- package/dist/extraction/languages/arkts-viewtree.d.ts.map +1 -1
- package/dist/extraction/languages/arkts-viewtree.js +21 -6
- package/dist/extraction/languages/arkts-viewtree.js.map +1 -1
- package/dist/extraction/languages/arkts.d.ts +98 -2
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +1290 -61
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/extraction/languages/c-cpp.d.ts +56 -0
- package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/dist/extraction/languages/c-cpp.js +198 -1
- package/dist/extraction/languages/c-cpp.js.map +1 -1
- package/dist/extraction/languages/ohos-api-consumer.d.ts +34 -0
- package/dist/extraction/languages/ohos-api-consumer.d.ts.map +1 -0
- package/dist/extraction/languages/ohos-api-consumer.js +283 -0
- package/dist/extraction/languages/ohos-api-consumer.js.map +1 -0
- package/dist/extraction/parse-pool.d.ts +126 -0
- package/dist/extraction/parse-pool.d.ts.map +1 -0
- package/dist/extraction/parse-pool.js +319 -0
- package/dist/extraction/parse-pool.js.map +1 -0
- package/dist/extraction/tree-sitter-types.d.ts +17 -0
- package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.d.ts +21 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.js +198 -27
- package/dist/extraction/tree-sitter.js.map +1 -1
- package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/dist/graph/traversal.d.ts.map +1 -1
- package/dist/graph/traversal.js +76 -17
- package/dist/graph/traversal.js.map +1 -1
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -4
- package/dist/index.js.map +1 -1
- package/dist/installer/instructions-template.js +9 -9
- package/dist/installer/targets/shared.d.ts +5 -6
- package/dist/installer/targets/shared.d.ts.map +1 -1
- package/dist/installer/targets/shared.js +5 -6
- package/dist/installer/targets/shared.js.map +1 -1
- package/dist/mcp/daemon-paths.d.ts +30 -3
- package/dist/mcp/daemon-paths.d.ts.map +1 -1
- package/dist/mcp/daemon-paths.js +50 -10
- package/dist/mcp/daemon-paths.js.map +1 -1
- package/dist/mcp/daemon-registry.d.ts.map +1 -1
- package/dist/mcp/daemon-registry.js +7 -3
- package/dist/mcp/daemon-registry.js.map +1 -1
- package/dist/mcp/daemon.d.ts +48 -0
- package/dist/mcp/daemon.d.ts.map +1 -1
- package/dist/mcp/daemon.js +196 -32
- package/dist/mcp/daemon.js.map +1 -1
- package/dist/mcp/engine.d.ts +17 -0
- package/dist/mcp/engine.d.ts.map +1 -1
- package/dist/mcp/engine.js +73 -1
- package/dist/mcp/engine.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +25 -43
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/liveness-watchdog.js +16 -16
- package/dist/mcp/ppid-watchdog.d.ts +18 -0
- package/dist/mcp/ppid-watchdog.d.ts.map +1 -1
- package/dist/mcp/ppid-watchdog.js +37 -0
- package/dist/mcp/ppid-watchdog.js.map +1 -1
- package/dist/mcp/query-cache.d.ts +25 -0
- package/dist/mcp/query-cache.d.ts.map +1 -0
- package/dist/mcp/query-cache.js +191 -0
- package/dist/mcp/query-cache.js.map +1 -0
- package/dist/mcp/query-pool.d.ts +94 -0
- package/dist/mcp/query-pool.d.ts.map +1 -0
- package/dist/mcp/query-pool.js +297 -0
- package/dist/mcp/query-pool.js.map +1 -0
- package/dist/mcp/query-worker.d.ts +24 -0
- package/dist/mcp/query-worker.d.ts.map +1 -0
- package/dist/mcp/query-worker.js +87 -0
- package/dist/mcp/query-worker.js.map +1 -0
- package/dist/mcp/server-instructions.d.ts +5 -7
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +72 -74
- package/dist/mcp/server-instructions.js.map +1 -1
- package/dist/mcp/tools.d.ts +94 -4
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +877 -71
- package/dist/mcp/tools.js.map +1 -1
- package/dist/project-config.d.ts +20 -0
- package/dist/project-config.d.ts.map +1 -1
- package/dist/project-config.js +42 -2
- package/dist/project-config.js.map +1 -1
- package/dist/reasoning/login.js +1 -1
- package/dist/reasoning/login.js.map +1 -1
- package/dist/reasoning/reasoner.js +32 -32
- package/dist/resolution/c-fnptr-synthesizer.d.ts +0 -28
- package/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
- package/dist/resolution/c-fnptr-synthesizer.js +765 -79
- package/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
- package/dist/resolution/callback-synthesizer.d.ts +1 -1
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/dist/resolution/callback-synthesizer.js +72 -11
- package/dist/resolution/callback-synthesizer.js.map +1 -1
- package/dist/resolution/cooperative-yield.d.ts +32 -0
- package/dist/resolution/cooperative-yield.d.ts.map +1 -0
- package/dist/resolution/cooperative-yield.js +42 -0
- package/dist/resolution/cooperative-yield.js.map +1 -0
- package/dist/resolution/index.d.ts +11 -2
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +72 -4
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/name-matcher.d.ts +22 -0
- package/dist/resolution/name-matcher.d.ts.map +1 -1
- package/dist/resolution/name-matcher.js +317 -20
- package/dist/resolution/name-matcher.js.map +1 -1
- package/dist/spec/config.d.ts +39 -0
- package/dist/spec/config.d.ts.map +1 -0
- package/dist/spec/config.js +304 -0
- package/dist/spec/config.js.map +1 -0
- package/dist/spec/db/commit-node.d.ts +23 -0
- package/dist/spec/db/commit-node.d.ts.map +1 -0
- package/dist/spec/db/commit-node.js +62 -0
- package/dist/spec/db/commit-node.js.map +1 -0
- package/dist/spec/db/fragment-node.d.ts +24 -0
- package/dist/spec/db/fragment-node.d.ts.map +1 -0
- package/dist/spec/db/fragment-node.js +128 -0
- package/dist/spec/db/fragment-node.js.map +1 -0
- package/dist/spec/db/fts.d.ts +74 -0
- package/dist/spec/db/fts.d.ts.map +1 -0
- package/dist/spec/db/fts.js +324 -0
- package/dist/spec/db/fts.js.map +1 -0
- package/dist/spec/db/index.d.ts +13 -0
- package/dist/spec/db/index.d.ts.map +1 -0
- package/dist/spec/db/index.js +50 -0
- package/dist/spec/db/index.js.map +1 -0
- package/dist/spec/db/relations.d.ts +55 -0
- package/dist/spec/db/relations.d.ts.map +1 -0
- package/dist/spec/db/relations.js +158 -0
- package/dist/spec/db/relations.js.map +1 -0
- package/dist/spec/db/schema.d.ts +33 -0
- package/dist/spec/db/schema.d.ts.map +1 -0
- package/dist/spec/db/schema.js +119 -0
- package/dist/spec/db/schema.js.map +1 -0
- package/dist/spec/db/schema.sql +117 -0
- package/dist/spec/db/spec-node.d.ts +41 -0
- package/dist/spec/db/spec-node.d.ts.map +1 -0
- package/dist/spec/db/spec-node.js +114 -0
- package/dist/spec/db/spec-node.js.map +1 -0
- package/dist/spec/evolve/impact-locator.d.ts +13 -0
- package/dist/spec/evolve/impact-locator.d.ts.map +1 -0
- package/dist/spec/evolve/impact-locator.js +25 -0
- package/dist/spec/evolve/impact-locator.js.map +1 -0
- package/dist/spec/evolve/llm-client.d.ts +50 -0
- package/dist/spec/evolve/llm-client.d.ts.map +1 -0
- package/dist/spec/evolve/llm-client.js +176 -0
- package/dist/spec/evolve/llm-client.js.map +1 -0
- package/dist/spec/evolve/logic-checker.d.ts +12 -0
- package/dist/spec/evolve/logic-checker.d.ts.map +1 -0
- package/dist/spec/evolve/logic-checker.js +24 -0
- package/dist/spec/evolve/logic-checker.js.map +1 -0
- package/dist/spec/evolve/pipeline.d.ts +42 -0
- package/dist/spec/evolve/pipeline.d.ts.map +1 -0
- package/dist/spec/evolve/pipeline.js +567 -0
- package/dist/spec/evolve/pipeline.js.map +1 -0
- package/dist/spec/evolve/spec-rewriter.d.ts +42 -0
- package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -0
- package/dist/spec/evolve/spec-rewriter.js +230 -0
- package/dist/spec/evolve/spec-rewriter.js.map +1 -0
- package/dist/spec/graph/queries.d.ts +155 -0
- package/dist/spec/graph/queries.d.ts.map +1 -0
- package/dist/spec/graph/queries.js +440 -0
- package/dist/spec/graph/queries.js.map +1 -0
- package/dist/spec/llm/client.d.ts +29 -0
- package/dist/spec/llm/client.d.ts.map +1 -0
- package/dist/spec/llm/client.js +123 -0
- package/dist/spec/llm/client.js.map +1 -0
- package/dist/spec/llm/index.d.ts +3 -0
- package/dist/spec/llm/index.d.ts.map +1 -0
- package/dist/spec/llm/index.js +11 -0
- package/dist/spec/llm/index.js.map +1 -0
- package/dist/spec/llm/prompts.d.ts +13 -0
- package/dist/spec/llm/prompts.d.ts.map +1 -0
- package/dist/spec/llm/prompts.js +75 -0
- package/dist/spec/llm/prompts.js.map +1 -0
- package/dist/spec/mining/diff-parser.d.ts +33 -0
- package/dist/spec/mining/diff-parser.d.ts.map +1 -0
- package/dist/spec/mining/diff-parser.js +166 -0
- package/dist/spec/mining/diff-parser.js.map +1 -0
- package/dist/spec/mining/git-scanner.d.ts +103 -0
- package/dist/spec/mining/git-scanner.d.ts.map +1 -0
- package/dist/spec/mining/git-scanner.js +307 -0
- package/dist/spec/mining/git-scanner.js.map +1 -0
- package/dist/spec/mining/pipeline.d.ts +53 -0
- package/dist/spec/mining/pipeline.d.ts.map +1 -0
- package/dist/spec/mining/pipeline.js +178 -0
- package/dist/spec/mining/pipeline.js.map +1 -0
- package/dist/spec/mining/scope-resolver.d.ts +45 -0
- package/dist/spec/mining/scope-resolver.d.ts.map +1 -0
- package/dist/spec/mining/scope-resolver.js +103 -0
- package/dist/spec/mining/scope-resolver.js.map +1 -0
- package/dist/spec/mining/spec-extractor.d.ts +69 -0
- package/dist/spec/mining/spec-extractor.d.ts.map +1 -0
- package/dist/spec/mining/spec-extractor.js +369 -0
- package/dist/spec/mining/spec-extractor.js.map +1 -0
- package/dist/spec/types.d.ts +149 -0
- package/dist/spec/types.d.ts.map +1 -0
- package/dist/spec/types.js +15 -0
- package/dist/spec/types.js.map +1 -0
- package/dist/spec/utils.d.ts +167 -0
- package/dist/spec/utils.d.ts.map +1 -0
- package/dist/spec/utils.js +463 -0
- package/dist/spec/utils.js.map +1 -0
- package/dist/sync/worktree.d.ts +9 -0
- package/dist/sync/worktree.d.ts.map +1 -1
- package/dist/sync/worktree.js +40 -0
- package/dist/sync/worktree.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.d.ts +2 -0
- package/dist/ui/shimmer-progress.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.js +19 -2
- package/dist/ui/shimmer-progress.js.map +1 -1
- package/dist/upgrade/index.js +1 -1
- package/dist/upgrade/index.js.map +1 -1
- package/package.json +58 -57
- package/scripts/add-lang/bench.sh +60 -60
- package/scripts/add-lang/check-grammar.mjs +75 -75
- package/scripts/add-lang/dump-ast.mjs +103 -103
- package/scripts/add-lang/verify-extraction.mjs +70 -70
- package/scripts/agent-eval/ab-adoption.sh +91 -91
- package/scripts/agent-eval/ab-hook.sh +86 -86
- package/scripts/agent-eval/ab-impl.sh +78 -78
- package/scripts/agent-eval/ab-new-vs-baseline.sh +102 -102
- package/scripts/agent-eval/ab-sufficiency.sh +78 -78
- package/scripts/agent-eval/arms-F.sh +21 -21
- package/scripts/agent-eval/arms-matrix.sh +37 -37
- package/scripts/agent-eval/audit.sh +68 -68
- package/scripts/agent-eval/bench-readme.sh +28 -28
- package/scripts/agent-eval/bench-why-repo.sh +22 -22
- package/scripts/agent-eval/block-read-hook.sh +19 -19
- package/scripts/agent-eval/hook-settings.json +15 -15
- package/scripts/agent-eval/itrun.sh +120 -120
- package/scripts/agent-eval/offload-eval-3arm.sh +72 -72
- package/scripts/agent-eval/offload-eval-cost.mjs +133 -133
- package/scripts/agent-eval/offload-eval-effort.mjs +108 -108
- package/scripts/agent-eval/offload-eval-frontload-matrix.sh +25 -25
- package/scripts/agent-eval/offload-eval-frontload.sh +47 -47
- package/scripts/agent-eval/offload-eval-ground-truth.json +18 -18
- package/scripts/agent-eval/offload-eval-hook.mjs +84 -84
- package/scripts/agent-eval/offload-eval-judge.mjs +103 -103
- package/scripts/agent-eval/offload-eval-matrix.sh +20 -20
- package/scripts/agent-eval/offload-eval-metrics.mjs +94 -94
- package/scripts/agent-eval/offload-eval-refs1.sh +50 -50
- package/scripts/agent-eval/offload-eval-setup.sh +24 -24
- package/scripts/agent-eval/offload-eval-styles.sh +71 -71
- package/scripts/agent-eval/offload-eval-summarize.mjs +68 -68
- package/scripts/agent-eval/offload-eval.md +76 -76
- package/scripts/agent-eval/parse-arms.mjs +116 -116
- package/scripts/agent-eval/parse-bench-readme.mjs +84 -84
- package/scripts/agent-eval/parse-run.mjs +45 -45
- package/scripts/agent-eval/parse-session.mjs +93 -93
- package/scripts/agent-eval/probe-context.mjs +21 -21
- package/scripts/agent-eval/probe-explore.mjs +40 -40
- package/scripts/agent-eval/probe-node.mjs +20 -20
- package/scripts/agent-eval/probe-sweep.mjs +119 -119
- package/scripts/agent-eval/probe-trace.mjs +20 -20
- package/scripts/agent-eval/redirect-read-hook.sh +38 -38
- package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -0
- package/scripts/agent-eval/repro-daemon-clients.mjs +125 -0
- package/scripts/agent-eval/run-agent.sh +34 -34
- package/scripts/agent-eval/run-all.sh +69 -69
- package/scripts/agent-eval/run-arms.sh +56 -56
- package/scripts/agent-eval/seq-matrix.mjs +137 -137
- package/scripts/build-bundle.sh +118 -118
- package/scripts/exp_boundary_eval/README.md +247 -0
- 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/_test_mcp_chain.py +78 -0
- package/scripts/exp_boundary_eval/_test_stdin.py +8 -0
- package/scripts/exp_boundary_eval/_utils.py +1116 -0
- package/scripts/exp_boundary_eval/analyze.py +1313 -0
- package/scripts/exp_boundary_eval/data/agents.json +109 -0
- package/scripts/exp_boundary_eval/data/experiments.json +140 -0
- package/scripts/exp_boundary_eval/deveco_arm.py +519 -0
- package/scripts/exp_boundary_eval/run_all.py +378 -0
- package/scripts/exp_boundary_eval/run_one.py +165 -0
- package/scripts/exp_boundary_eval/run_session.py +158 -0
- package/scripts/exp_boundary_eval/setup.py +120 -0
- package/scripts/exp_boundary_eval/win_mcp_launcher.py +73 -0
- package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +36 -0
- package/scripts/exp_boundary_eval/win_node_launcher.py +24 -0
- package/scripts/extract-release-notes.mjs +130 -130
- package/scripts/local-install.sh +41 -41
- package/scripts/npm-sdk.js +75 -75
- package/scripts/npm-shim.js +268 -246
- package/scripts/ohos-sdk-publish.mjs +133 -0
- package/scripts/pack-npm.sh +119 -119
- package/scripts/prepare-release.mjs +270 -270
- package/scripts/qa_eval/README.md +407 -404
- package/scripts/qa_eval/_test_deveco_probe.py +41 -41
- package/scripts/qa_eval/agent_runner.py +526 -526
- package/scripts/qa_eval/data/.gitignore +4 -4
- package/scripts/qa_eval/data/test-set.jsonl +2 -22
- package/scripts/qa_eval/eval_metrics.py +274 -233
- package/scripts/qa_eval/external_agent.py +976 -671
- package/scripts/qa_eval/llm_config.py +92 -92
- package/scripts/qa_eval/memory_monitor.py +132 -132
- package/scripts/qa_eval/my_answer_accuracy.py +187 -187
- package/scripts/qa_eval/requirements.txt +2 -2
- package/scripts/qa_eval/run_pipeline.py +804 -711
- package/scripts/qa_eval/stats_efficiency.py +279 -279
- package/scripts/qa_eval/stats_scores.py +207 -207
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Graph traversal queries for the Spec→Commit→CodeFragment knowledge graph.
|
|
4
|
+
*
|
|
5
|
+
* Replaces `commit4spec/graph/queries.py`. Provides spec context retrieval,
|
|
6
|
+
* stats, and search+traverse functionality.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.getSpecContext = getSpecContext;
|
|
10
|
+
exports.findSpecsByFragmentPath = findSpecsByFragmentPath;
|
|
11
|
+
exports.findSpecsByFilePath = findSpecsByFilePath;
|
|
12
|
+
exports.getSpecStats = getSpecStats;
|
|
13
|
+
exports.searchAndGetContext = searchAndGetContext;
|
|
14
|
+
exports.findSpecsByCodeSymbol = findSpecsByCodeSymbol;
|
|
15
|
+
const fts_1 = require("../db/fts");
|
|
16
|
+
// ===========================================================================
|
|
17
|
+
// Private helpers
|
|
18
|
+
// ===========================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Parse a JSON string into a string array, returning [] on any failure.
|
|
21
|
+
*/
|
|
22
|
+
function _parseSubtitles(raw) {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(raw || '[]');
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Convert a DB row (snake_case keys) to a SpecNode (camelCase).
|
|
32
|
+
*/
|
|
33
|
+
function _rowToSpecNode(row) {
|
|
34
|
+
return {
|
|
35
|
+
id: row.id,
|
|
36
|
+
title: row.title,
|
|
37
|
+
subtitles: _parseSubtitles(row.subtitles),
|
|
38
|
+
status: row.status,
|
|
39
|
+
version: row.version,
|
|
40
|
+
filePath: row.file_path,
|
|
41
|
+
timestamp: row.timestamp,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// ===========================================================================
|
|
45
|
+
// Public API
|
|
46
|
+
// ===========================================================================
|
|
47
|
+
/**
|
|
48
|
+
* Retrieve full context for a Spec — the spec node itself, all linked
|
|
49
|
+
* commits (with their relation types), and optionally the code fragments
|
|
50
|
+
* each commit touched.
|
|
51
|
+
*
|
|
52
|
+
* Commits are ordered by relation-type priority (GENERATE first, then
|
|
53
|
+
* SUMMARIZED_FROM, then others) and then by timestamp descending within
|
|
54
|
+
* each priority tier.
|
|
55
|
+
*
|
|
56
|
+
* @param db Active SQLite database handle.
|
|
57
|
+
* @param specId Spec identifier to look up.
|
|
58
|
+
* @param maxCommits Maximum number of linked commits to return (default 5).
|
|
59
|
+
* @param includeFragments Whether to load code fragments for each commit (default true).
|
|
60
|
+
* @returns SpecContext on success, or null when the spec is not found.
|
|
61
|
+
*/
|
|
62
|
+
function getSpecContext(db, specId, maxCommits = 5, includeFragments = true) {
|
|
63
|
+
// 1. Look up the spec by id
|
|
64
|
+
const specRow = db
|
|
65
|
+
.prepare(`SELECT id, title, subtitles, status, version, file_path, timestamp
|
|
66
|
+
FROM spec_nodes
|
|
67
|
+
WHERE id = ?`)
|
|
68
|
+
.get(specId);
|
|
69
|
+
if (!specRow)
|
|
70
|
+
return null;
|
|
71
|
+
const spec = _rowToSpecNode(specRow);
|
|
72
|
+
// 2. Query linked commits with priority ordering
|
|
73
|
+
const commitRows = db
|
|
74
|
+
.prepare(`SELECT c.hash, c.message, c.author, c.timestamp, r.relation_type
|
|
75
|
+
FROM spec_commit_relations r
|
|
76
|
+
JOIN commit_nodes c ON c.hash = r.commit_hash
|
|
77
|
+
WHERE r.spec_id = ?
|
|
78
|
+
ORDER BY
|
|
79
|
+
CASE r.relation_type
|
|
80
|
+
WHEN 'GENERATE' THEN 0
|
|
81
|
+
WHEN 'SUMMARIZED_FROM' THEN 1
|
|
82
|
+
ELSE 2
|
|
83
|
+
END,
|
|
84
|
+
c.timestamp DESC
|
|
85
|
+
LIMIT ?`)
|
|
86
|
+
.all(specId, maxCommits);
|
|
87
|
+
// 3. Build commit contexts (with optional fragments)
|
|
88
|
+
const commits = [];
|
|
89
|
+
for (const crow of commitRows) {
|
|
90
|
+
const commit = {
|
|
91
|
+
hash: crow.hash,
|
|
92
|
+
message: crow.message,
|
|
93
|
+
author: crow.author,
|
|
94
|
+
timestamp: crow.timestamp,
|
|
95
|
+
};
|
|
96
|
+
let fragments = [];
|
|
97
|
+
if (includeFragments) {
|
|
98
|
+
const fragRows = db
|
|
99
|
+
.prepare(`SELECT f.id, f.change_type, f.file_path, f.start_line,
|
|
100
|
+
f.end_line, f.code_diff
|
|
101
|
+
FROM commit_fragment_relations r
|
|
102
|
+
JOIN code_fragment_nodes f ON f.id = r.fragment_id
|
|
103
|
+
WHERE r.commit_hash = ?
|
|
104
|
+
ORDER BY f.file_path, f.start_line`)
|
|
105
|
+
.all(crow.hash);
|
|
106
|
+
fragments = fragRows.map((fr) => ({
|
|
107
|
+
id: fr.id,
|
|
108
|
+
changeType: fr.change_type,
|
|
109
|
+
filePath: fr.file_path,
|
|
110
|
+
startLine: fr.start_line,
|
|
111
|
+
endLine: fr.end_line,
|
|
112
|
+
codeDiff: fr.code_diff,
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
commits.push({
|
|
116
|
+
commit,
|
|
117
|
+
relationType: crow.relation_type,
|
|
118
|
+
fragments,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return { spec, commits };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Find all spec IDs related to code fragments whose file path matches
|
|
125
|
+
* the given substring.
|
|
126
|
+
*
|
|
127
|
+
* @param db Active SQLite database handle.
|
|
128
|
+
* @param filePath File path substring to search for (LIKE-wrapped).
|
|
129
|
+
* @returns Array of distinct spec IDs.
|
|
130
|
+
*/
|
|
131
|
+
function findSpecsByFragmentPath(db, filePath) {
|
|
132
|
+
const pattern = `%${filePath}%`;
|
|
133
|
+
const rows = db
|
|
134
|
+
.prepare(`SELECT DISTINCT r.spec_id
|
|
135
|
+
FROM spec_commit_relations r
|
|
136
|
+
JOIN commit_fragment_relations cfr ON cfr.commit_hash = r.commit_hash
|
|
137
|
+
JOIN code_fragment_nodes cf ON cf.id = cfr.fragment_id
|
|
138
|
+
WHERE cf.file_path LIKE ?`)
|
|
139
|
+
.all(pattern);
|
|
140
|
+
return rows.map((r) => r.spec_id);
|
|
141
|
+
}
|
|
142
|
+
// ===========================================================================
|
|
143
|
+
// findSpecsByFilePath
|
|
144
|
+
// ===========================================================================
|
|
145
|
+
/** Default max results returned by findSpecsByFilePath. */
|
|
146
|
+
const DEFAULT_MAX_SPEC_FIND_RESULTS = 100;
|
|
147
|
+
/**
|
|
148
|
+
* Find specs whose code fragments reference the given file path.
|
|
149
|
+
*
|
|
150
|
+
* Traverses: filePath -> code_fragment_nodes -> commit_fragment_relations
|
|
151
|
+
* -> commit_nodes -> spec_commit_relations -> spec_nodes.
|
|
152
|
+
*
|
|
153
|
+
* Uses LIKE matching against code_fragment_nodes.file_path, so partial
|
|
154
|
+
* paths work (e.g. `src/auth.ts` matches `src/auth/login.ts` and
|
|
155
|
+
* `app/src/auth.ts`). LIKE metacharacters (`%`, `_`, `\`) in the
|
|
156
|
+
* filePath are automatically escaped.
|
|
157
|
+
*
|
|
158
|
+
* An empty or whitespace-only filePath is rejected with an error
|
|
159
|
+
* (it would match every spec in the graph).
|
|
160
|
+
*
|
|
161
|
+
* @param db Active SQLite database handle.
|
|
162
|
+
* @param filePath File path to search for (substring LIKE match).
|
|
163
|
+
* @param maxResults Maximum number of results to return (default 100).
|
|
164
|
+
* @returns FindSpecsByFilePathResult with .results, .matched_count, and .truncated.
|
|
165
|
+
*/
|
|
166
|
+
function findSpecsByFilePath(db, filePath, maxResults = DEFAULT_MAX_SPEC_FIND_RESULTS) {
|
|
167
|
+
// Guard against empty input that would match every spec
|
|
168
|
+
if (!filePath || filePath.trim().length === 0) {
|
|
169
|
+
throw new Error('Empty file path is not allowed -- it would match every spec in the knowledge graph. ' +
|
|
170
|
+
'Provide a concrete file path (e.g. "src/auth.ts") or a partial path (e.g. "src/auth").');
|
|
171
|
+
}
|
|
172
|
+
// Escape LIKE metacharacters (SQLite ESCAPE '\' is used in the query)
|
|
173
|
+
const escaped = filePath
|
|
174
|
+
.replace(/\\/g, '\\\\') // literal backslash
|
|
175
|
+
.replace(/%/g, '\\%') // percent wildcard
|
|
176
|
+
.replace(/_/g, '\\_'); // underscore wildcard
|
|
177
|
+
const pattern = `%${escaped}%`;
|
|
178
|
+
const rows = db
|
|
179
|
+
.prepare(`SELECT DISTINCT s.id, s.title, s.status, s.version, s.file_path
|
|
180
|
+
FROM spec_nodes s
|
|
181
|
+
JOIN spec_commit_relations scr ON scr.spec_id = s.id
|
|
182
|
+
JOIN commit_fragment_relations cfr ON cfr.commit_hash = scr.commit_hash
|
|
183
|
+
JOIN code_fragment_nodes cf ON cf.id = cfr.fragment_id
|
|
184
|
+
WHERE cf.file_path LIKE ? ESCAPE '\\'
|
|
185
|
+
ORDER BY s.id
|
|
186
|
+
LIMIT ?`)
|
|
187
|
+
.all(pattern, maxResults + 1);
|
|
188
|
+
const truncated = rows.length > maxResults;
|
|
189
|
+
const slice = truncated ? rows.slice(0, maxResults) : rows;
|
|
190
|
+
return {
|
|
191
|
+
results: slice.map((r) => ({
|
|
192
|
+
id: r.id,
|
|
193
|
+
title: r.title,
|
|
194
|
+
status: r.status,
|
|
195
|
+
version: r.version,
|
|
196
|
+
filePath: r.file_path,
|
|
197
|
+
})),
|
|
198
|
+
matched_count: slice.length,
|
|
199
|
+
truncated,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Compute statistics about the Spec knowledge graph.
|
|
204
|
+
*
|
|
205
|
+
* @param db Active SQLite database handle.
|
|
206
|
+
* @returns SpecStats with entity counts and relation totals.
|
|
207
|
+
*/
|
|
208
|
+
function getSpecStats(db) {
|
|
209
|
+
const specCount = db.prepare('SELECT COUNT(*) as cnt FROM spec_nodes').get().cnt;
|
|
210
|
+
const commitCount = db.prepare('SELECT COUNT(*) as cnt FROM commit_nodes').get().cnt;
|
|
211
|
+
const fragmentCount = db
|
|
212
|
+
.prepare('SELECT COUNT(*) as cnt FROM code_fragment_nodes')
|
|
213
|
+
.get().cnt;
|
|
214
|
+
const scrCount = db
|
|
215
|
+
.prepare('SELECT COUNT(*) as cnt FROM spec_commit_relations')
|
|
216
|
+
.get().cnt;
|
|
217
|
+
const cfrCount = db
|
|
218
|
+
.prepare('SELECT COUNT(*) as cnt FROM commit_fragment_relations')
|
|
219
|
+
.get().cnt;
|
|
220
|
+
const ssrCount = db
|
|
221
|
+
.prepare('SELECT COUNT(*) as cnt FROM spec_spec_relations')
|
|
222
|
+
.get().cnt;
|
|
223
|
+
const activeSpecCount = db
|
|
224
|
+
.prepare("SELECT COUNT(*) as cnt FROM spec_nodes WHERE status = 'active'")
|
|
225
|
+
.get().cnt;
|
|
226
|
+
const deprecatedSpecCount = db
|
|
227
|
+
.prepare("SELECT COUNT(*) as cnt FROM spec_nodes WHERE status = 'deprecated'")
|
|
228
|
+
.get().cnt;
|
|
229
|
+
return {
|
|
230
|
+
specCount,
|
|
231
|
+
commitCount,
|
|
232
|
+
fragmentCount,
|
|
233
|
+
relationCount: scrCount + cfrCount + ssrCount,
|
|
234
|
+
activeSpecCount,
|
|
235
|
+
deprecatedSpecCount,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Full-text search for specs and return full context for each match.
|
|
240
|
+
*
|
|
241
|
+
* Combines FTS5 + LIKE fallback search with graph traversal so callers
|
|
242
|
+
* get everything in one call: spec metadata, linked commits, and
|
|
243
|
+
* optionally code fragments.
|
|
244
|
+
*
|
|
245
|
+
* Results are sorted by `_score` descending, then by spec timestamp
|
|
246
|
+
* descending as a tiebreaker.
|
|
247
|
+
*
|
|
248
|
+
* @param db Active SQLite database handle.
|
|
249
|
+
* @param query Search query string.
|
|
250
|
+
* @param topK Maximum number of results to return (default 10).
|
|
251
|
+
* @param includeFragments Whether to load code fragments per commit (default true).
|
|
252
|
+
* @returns Array of SpecContext (null results filtered out).
|
|
253
|
+
*/
|
|
254
|
+
function searchAndGetContext(db, query, topK = 10, includeFragments = true) {
|
|
255
|
+
// 1. Search specs via FTS5 + LIKE fallback
|
|
256
|
+
const results = (0, fts_1.searchSpecs)(db, query, topK);
|
|
257
|
+
// 2. Get full context for each result
|
|
258
|
+
const scored = [];
|
|
259
|
+
for (const result of results) {
|
|
260
|
+
const context = getSpecContext(db, result.id, 5, includeFragments);
|
|
261
|
+
if (context !== null) {
|
|
262
|
+
scored.push({
|
|
263
|
+
score: result._score ?? 0,
|
|
264
|
+
timestamp: context.spec.timestamp,
|
|
265
|
+
context,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// 3. Sort by _score descending, then by spec timestamp descending
|
|
270
|
+
scored.sort((a, b) => {
|
|
271
|
+
if (b.score !== a.score)
|
|
272
|
+
return b.score - a.score;
|
|
273
|
+
return b.timestamp - a.timestamp;
|
|
274
|
+
});
|
|
275
|
+
return scored.map((c) => c.context);
|
|
276
|
+
}
|
|
277
|
+
/** Weight constants for the five scoring dimensions. */
|
|
278
|
+
const WEIGHTS = {
|
|
279
|
+
filePath: 0.30,
|
|
280
|
+
content: 0.25,
|
|
281
|
+
name: 0.15,
|
|
282
|
+
recency: 0.20,
|
|
283
|
+
overlap: 0.10,
|
|
284
|
+
};
|
|
285
|
+
/** Maximum candidates to consider from the initial file-path JOIN. */
|
|
286
|
+
const MAX_CANDIDATES = 200;
|
|
287
|
+
/**
|
|
288
|
+
* Escape LIKE metacharacters in a string, also escaping the escape character.
|
|
289
|
+
*/
|
|
290
|
+
function escapeLike(str) {
|
|
291
|
+
return str
|
|
292
|
+
.replace(/\\/g, '\\\\')
|
|
293
|
+
.replace(/%/g, '\\%')
|
|
294
|
+
.replace(/_/g, '\\_');
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Find Specs associated with a code entity by multi-dimensional scoring:
|
|
298
|
+
*
|
|
299
|
+
* 1. File path match (weight 0.30) — most stable anchor; function rarely changes file
|
|
300
|
+
* 2. Code-diff content match via FTS5 (weight 0.25) — catches entity names in diff text
|
|
301
|
+
* that never appear in Spec titles
|
|
302
|
+
* 3. Spec title/subtitle name match via FTS5 (weight 0.15) — semantic alignment
|
|
303
|
+
* 4. Recency (weight 0.20) — newer Specs are more likely to describe current code
|
|
304
|
+
* 5. Line-range overlap (weight 0.10) — soft signal; code drifts over time
|
|
305
|
+
*
|
|
306
|
+
* All five dimensions contribute even when some are zero — a spec without line
|
|
307
|
+
* overlap can still rank first if its content/name/recency scores are high.
|
|
308
|
+
*
|
|
309
|
+
* @param specDb commit4spec.db connection
|
|
310
|
+
* @param entity Code entity info (from homegraph.db nodes)
|
|
311
|
+
* @param topK Maximum matches to return (default 10)
|
|
312
|
+
* @returns Ranked, scored matches with score breakdowns
|
|
313
|
+
*/
|
|
314
|
+
function findSpecsByCodeSymbol(specDb, entity, topK = 10) {
|
|
315
|
+
const pathEscaped = escapeLike(entity.filePath);
|
|
316
|
+
const likePattern = `%${pathEscaped}%`;
|
|
317
|
+
const suffixLikePattern = `%${pathEscaped}`; // cf.file_path ends with entity's path
|
|
318
|
+
// -----------------------------------------------------------------------
|
|
319
|
+
// 1. Gather candidates: all specs whose fragments touch the entity's file
|
|
320
|
+
// -----------------------------------------------------------------------
|
|
321
|
+
const candidateRows = specDb
|
|
322
|
+
.prepare(`
|
|
323
|
+
SELECT
|
|
324
|
+
s.id, s.title, s.status, s.version, s.file_path, s.timestamp,
|
|
325
|
+
MAX(
|
|
326
|
+
MIN(cf.end_line, @entityEnd) - MAX(cf.start_line, @entityStart) + 1,
|
|
327
|
+
0
|
|
328
|
+
) AS overlap_lines,
|
|
329
|
+
COUNT(DISTINCT cf.id) AS fragment_count,
|
|
330
|
+
COUNT(DISTINCT scr.commit_hash) AS commit_count,
|
|
331
|
+
MAX(CASE
|
|
332
|
+
WHEN cf.file_path = @exactFilePath THEN 3
|
|
333
|
+
WHEN cf.file_path LIKE @suffixLikePattern ESCAPE '\\' THEN 2
|
|
334
|
+
ELSE 1
|
|
335
|
+
END) AS file_path_match_level
|
|
336
|
+
FROM spec_nodes s
|
|
337
|
+
JOIN spec_commit_relations scr ON scr.spec_id = s.id
|
|
338
|
+
JOIN commit_fragment_relations cfr ON cfr.commit_hash = scr.commit_hash
|
|
339
|
+
JOIN code_fragment_nodes cf ON cf.id = cfr.fragment_id
|
|
340
|
+
WHERE s.status = 'active'
|
|
341
|
+
AND cf.file_path LIKE @likePattern ESCAPE '\\'
|
|
342
|
+
GROUP BY s.id
|
|
343
|
+
ORDER BY s.timestamp DESC
|
|
344
|
+
LIMIT @maxCandidates
|
|
345
|
+
`)
|
|
346
|
+
.all({
|
|
347
|
+
entityEnd: entity.endLine,
|
|
348
|
+
entityStart: entity.startLine,
|
|
349
|
+
exactFilePath: entity.filePath,
|
|
350
|
+
suffixLikePattern,
|
|
351
|
+
likePattern,
|
|
352
|
+
maxCandidates: MAX_CANDIDATES,
|
|
353
|
+
});
|
|
354
|
+
// -----------------------------------------------------------------------
|
|
355
|
+
// 2. Content-match signal: search code_fragments_fts for the entity name
|
|
356
|
+
// -----------------------------------------------------------------------
|
|
357
|
+
const contentFragmentIds = new Set((0, fts_1.searchCodeFragments)(specDb, entity.name, 50));
|
|
358
|
+
// Map from spec_id → whether any of its fragments matched in content search
|
|
359
|
+
const contentSpecIds = new Set();
|
|
360
|
+
if (contentFragmentIds.size > 0) {
|
|
361
|
+
const fragsIn = [...contentFragmentIds].map(() => '?').join(',');
|
|
362
|
+
const contentSpecRows = specDb
|
|
363
|
+
.prepare(`
|
|
364
|
+
SELECT DISTINCT scr.spec_id
|
|
365
|
+
FROM commit_fragment_relations cfr
|
|
366
|
+
JOIN spec_commit_relations scr ON scr.commit_hash = cfr.commit_hash
|
|
367
|
+
WHERE cfr.fragment_id IN (${fragsIn})
|
|
368
|
+
`)
|
|
369
|
+
.all(...contentFragmentIds);
|
|
370
|
+
for (const r of contentSpecRows) {
|
|
371
|
+
contentSpecIds.add(r.spec_id);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// -----------------------------------------------------------------------
|
|
375
|
+
// 3. Name-match signal: search specs_fts for the entity name
|
|
376
|
+
// -----------------------------------------------------------------------
|
|
377
|
+
const nameResults = (0, fts_1.searchSpecs)(specDb, entity.name, topK * 3);
|
|
378
|
+
const nameScoreMap = new Map();
|
|
379
|
+
const nameMaxScore = Math.max(1, ...nameResults.map((r) => r._score ?? 0));
|
|
380
|
+
for (const r of nameResults) {
|
|
381
|
+
nameScoreMap.set(r.id, (r._score ?? 0) / nameMaxScore); // normalize to [0, 1]
|
|
382
|
+
}
|
|
383
|
+
// -----------------------------------------------------------------------
|
|
384
|
+
// 4. Compute weighted score for each candidate
|
|
385
|
+
// -----------------------------------------------------------------------
|
|
386
|
+
const now = Date.now();
|
|
387
|
+
const entityLength = Math.max(1, entity.endLine - entity.startLine + 1);
|
|
388
|
+
const scored = candidateRows.map((row) => {
|
|
389
|
+
// 4a. File-path score — derived from the best-matching fragment's file_path
|
|
390
|
+
// (computed in SQL as file_path_match_level: 3=exact, 2=suffix, 1=LIKE)
|
|
391
|
+
const filePathScore = row.file_path_match_level === 3 ? 1.0
|
|
392
|
+
: row.file_path_match_level === 2 ? 0.8
|
|
393
|
+
: 0.6;
|
|
394
|
+
// 4b. Content score
|
|
395
|
+
const contentScore = contentSpecIds.has(row.id) ? 1.0 : 0;
|
|
396
|
+
// 4c. Name score
|
|
397
|
+
const nameScore = nameScoreMap.get(row.id) ?? 0;
|
|
398
|
+
// 4d. Recency score: MapSpec(timestamp, 0, maxTs)MapSpec => [0, 1]
|
|
399
|
+
const daysSinceUpdate = (now - row.timestamp) / (1000 * 60 * 60 * 24);
|
|
400
|
+
const recencyScore = 1 / (1 + Math.max(0, daysSinceUpdate) / 180);
|
|
401
|
+
// 4e. Overlap score
|
|
402
|
+
const overlapRatio = Math.min(1.0, row.overlap_lines / entityLength);
|
|
403
|
+
const overlapScore = overlapRatio;
|
|
404
|
+
const score = filePathScore * WEIGHTS.filePath +
|
|
405
|
+
contentScore * WEIGHTS.content +
|
|
406
|
+
nameScore * WEIGHTS.name +
|
|
407
|
+
recencyScore * WEIGHTS.recency +
|
|
408
|
+
overlapScore * WEIGHTS.overlap;
|
|
409
|
+
return {
|
|
410
|
+
spec: {
|
|
411
|
+
id: row.id,
|
|
412
|
+
title: row.title,
|
|
413
|
+
status: row.status,
|
|
414
|
+
version: row.version,
|
|
415
|
+
filePath: row.file_path,
|
|
416
|
+
timestamp: row.timestamp,
|
|
417
|
+
},
|
|
418
|
+
score,
|
|
419
|
+
scoreDetail: {
|
|
420
|
+
filePathScore,
|
|
421
|
+
contentScore,
|
|
422
|
+
nameScore,
|
|
423
|
+
recencyScore,
|
|
424
|
+
overlapScore,
|
|
425
|
+
},
|
|
426
|
+
fragmentCount: row.fragment_count,
|
|
427
|
+
commitCount: row.commit_count,
|
|
428
|
+
};
|
|
429
|
+
});
|
|
430
|
+
// -----------------------------------------------------------------------
|
|
431
|
+
// 5. Sort and trim
|
|
432
|
+
// -----------------------------------------------------------------------
|
|
433
|
+
scored.sort((a, b) => b.score - a.score);
|
|
434
|
+
return {
|
|
435
|
+
entity,
|
|
436
|
+
matches: scored.slice(0, topK),
|
|
437
|
+
totalCandidates: candidateRows.length,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
//# sourceMappingURL=queries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../../src/spec/graph/queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { LLMConfig } from '../config';
|
|
2
|
+
export interface LlmClient {
|
|
3
|
+
chat(systemPrompt: string, userPrompt: string): Promise<string>;
|
|
4
|
+
chatJson(systemPrompt: string, userPrompt: string): Promise<Record<string, unknown>>;
|
|
5
|
+
}
|
|
6
|
+
export declare class OpenAiLlmClient implements LlmClient {
|
|
7
|
+
private config;
|
|
8
|
+
constructor(config: LLMConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Send a chat completion request and return the message content string.
|
|
11
|
+
*
|
|
12
|
+
* Calls the OpenAI-compatible chat completions API and returns
|
|
13
|
+
* `choices[0].message.content`. On any error, returns an empty string.
|
|
14
|
+
*/
|
|
15
|
+
chat(systemPrompt: string, userPrompt: string): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Same as `chat()`, but parses the response as JSON.
|
|
18
|
+
*
|
|
19
|
+
* Parsing strategy (tried in order):
|
|
20
|
+
* 1. Direct `JSON.parse(content)`.
|
|
21
|
+
* 2. Extract from `` ```json ... ``` `` fenced block.
|
|
22
|
+
* 3. Extract from `` ``` ... ``` `` fenced block.
|
|
23
|
+
* 4. Fallback: log a debug warning and return `{}`.
|
|
24
|
+
*
|
|
25
|
+
* Empty or null content from `chat()` also returns `{}`.
|
|
26
|
+
*/
|
|
27
|
+
chatJson(systemPrompt: string, userPrompt: string): Promise<Record<string, unknown>>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/spec/llm/client.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAOtC,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACtF;AAMD,qBAAa,eAAgB,YAAW,SAAS;IAC/C,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,EAAE,SAAS;IAQ7B;;;;;OAKG;IACG,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkCrE;;;;;;;;;;OAUG;IACG,QAAQ,CACZ,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CA+CpC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.OpenAiLlmClient = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Provider-agnostic LLM client for spec self-evolution.
|
|
9
|
+
*
|
|
10
|
+
* Supports OpenAI-compatible chat completions API. No mock mode — callers
|
|
11
|
+
* that need test doubles inject their own stubs implementing the interface.
|
|
12
|
+
*
|
|
13
|
+
* @module spec/llm/client
|
|
14
|
+
*/
|
|
15
|
+
const openai_1 = __importDefault(require("openai"));
|
|
16
|
+
const errors_1 = require("../../errors");
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// OpenAiLlmClient
|
|
19
|
+
// =============================================================================
|
|
20
|
+
class OpenAiLlmClient {
|
|
21
|
+
config;
|
|
22
|
+
constructor(config) {
|
|
23
|
+
this.config = config;
|
|
24
|
+
}
|
|
25
|
+
// ===========================================================================
|
|
26
|
+
// chat
|
|
27
|
+
// ===========================================================================
|
|
28
|
+
/**
|
|
29
|
+
* Send a chat completion request and return the message content string.
|
|
30
|
+
*
|
|
31
|
+
* Calls the OpenAI-compatible chat completions API and returns
|
|
32
|
+
* `choices[0].message.content`. On any error, returns an empty string.
|
|
33
|
+
*/
|
|
34
|
+
async chat(systemPrompt, userPrompt) {
|
|
35
|
+
const baseURL = this.config.baseUrl
|
|
36
|
+
? this.config.baseUrl
|
|
37
|
+
: this.config.provider === 'anthropic'
|
|
38
|
+
? 'https://api.anthropic.com/v1'
|
|
39
|
+
: undefined;
|
|
40
|
+
const client = new openai_1.default({
|
|
41
|
+
apiKey: this.config.apiKey,
|
|
42
|
+
baseURL,
|
|
43
|
+
});
|
|
44
|
+
try {
|
|
45
|
+
const completion = await client.chat.completions.create({
|
|
46
|
+
model: this.config.model,
|
|
47
|
+
temperature: this.config.temperature,
|
|
48
|
+
max_tokens: this.config.maxTokens,
|
|
49
|
+
messages: [
|
|
50
|
+
{ role: 'system', content: systemPrompt },
|
|
51
|
+
{ role: 'user', content: userPrompt },
|
|
52
|
+
],
|
|
53
|
+
});
|
|
54
|
+
const content = completion.choices[0]?.message?.content;
|
|
55
|
+
return content ?? '';
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return '';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// ===========================================================================
|
|
62
|
+
// chatJson
|
|
63
|
+
// ===========================================================================
|
|
64
|
+
/**
|
|
65
|
+
* Same as `chat()`, but parses the response as JSON.
|
|
66
|
+
*
|
|
67
|
+
* Parsing strategy (tried in order):
|
|
68
|
+
* 1. Direct `JSON.parse(content)`.
|
|
69
|
+
* 2. Extract from `` ```json ... ``` `` fenced block.
|
|
70
|
+
* 3. Extract from `` ``` ... ``` `` fenced block.
|
|
71
|
+
* 4. Fallback: log a debug warning and return `{}`.
|
|
72
|
+
*
|
|
73
|
+
* Empty or null content from `chat()` also returns `{}`.
|
|
74
|
+
*/
|
|
75
|
+
async chatJson(systemPrompt, userPrompt) {
|
|
76
|
+
const raw = await this.chat(systemPrompt, userPrompt);
|
|
77
|
+
if (!raw)
|
|
78
|
+
return {};
|
|
79
|
+
// 1. Direct parse
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(raw);
|
|
82
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
83
|
+
return parsed;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Fall through to fence extraction
|
|
88
|
+
}
|
|
89
|
+
// 2. ```json ... ``` fence
|
|
90
|
+
const jsonFenceMatch = /```json\s*([\s\S]*?)```/.exec(raw);
|
|
91
|
+
if (jsonFenceMatch) {
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(jsonFenceMatch[1].trim());
|
|
94
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
95
|
+
return parsed;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Fall through
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// 3. ``` ... ``` fence
|
|
103
|
+
const fenceMatch = /```\s*([\s\S]*?)```/.exec(raw);
|
|
104
|
+
if (fenceMatch) {
|
|
105
|
+
try {
|
|
106
|
+
const parsed = JSON.parse(fenceMatch[1].trim());
|
|
107
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
108
|
+
return parsed;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Fall through
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// 4. Fallback
|
|
116
|
+
(0, errors_1.logDebug)('chatJson: could not parse response as JSON', {
|
|
117
|
+
raw: raw.length > 200 ? raw.slice(0, 200) + '…' : raw,
|
|
118
|
+
});
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.OpenAiLlmClient = OpenAiLlmClient;
|
|
123
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/spec/llm/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/spec/llm/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildSpecEvaluationUserPrompt = exports.SPEC_EVALUATION_SYSTEM_PROMPT = exports.buildLogicCheckUserPrompt = exports.LOGIC_CHECK_SYSTEM_PROMPT = exports.OpenAiLlmClient = void 0;
|
|
4
|
+
var client_1 = require("./client");
|
|
5
|
+
Object.defineProperty(exports, "OpenAiLlmClient", { enumerable: true, get: function () { return client_1.OpenAiLlmClient; } });
|
|
6
|
+
var prompts_1 = require("./prompts");
|
|
7
|
+
Object.defineProperty(exports, "LOGIC_CHECK_SYSTEM_PROMPT", { enumerable: true, get: function () { return prompts_1.LOGIC_CHECK_SYSTEM_PROMPT; } });
|
|
8
|
+
Object.defineProperty(exports, "buildLogicCheckUserPrompt", { enumerable: true, get: function () { return prompts_1.buildLogicCheckUserPrompt; } });
|
|
9
|
+
Object.defineProperty(exports, "SPEC_EVALUATION_SYSTEM_PROMPT", { enumerable: true, get: function () { return prompts_1.SPEC_EVALUATION_SYSTEM_PROMPT; } });
|
|
10
|
+
Object.defineProperty(exports, "buildSpecEvaluationUserPrompt", { enumerable: true, get: function () { return prompts_1.buildSpecEvaluationUserPrompt; } });
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/spec/llm/index.ts"],"names":[],"mappings":";;;AAAA,mCAAsD;AAAlC,yGAAA,eAAe,OAAA;AACnC,qCAKmB;AAJjB,oHAAA,yBAAyB,OAAA;AACzB,oHAAA,yBAAyB,OAAA;AACzB,wHAAA,6BAA6B,OAAA;AAC7B,wHAAA,6BAA6B,OAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM prompt templates for spec self-evolution.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from logic-checker.ts and spec-rewriter.ts so evolve modules
|
|
5
|
+
* don't contain prompt strings directly.
|
|
6
|
+
*
|
|
7
|
+
* @module spec/llm/prompts
|
|
8
|
+
*/
|
|
9
|
+
export declare const LOGIC_CHECK_SYSTEM_PROMPT = "You are a code review assistant. Your task is to determine whether a git commit represents a business-logic change (as opposed to purely cosmetic, formatting, comment-only, or test-only changes).\n\nA business-logic change includes:\n- Changes to algorithms, data structures, or control flow\n- Changes to business rules, validation logic, or domain behavior\n- Adding or removing functionality\n- Bug fixes that change behavior\n\nNOT business-logic changes:\n- Whitespace, formatting, or code style changes\n- Comment-only changes\n- Test-only changes (adding tests without changing production code)\n- Configuration changes that don't alter behavior\n- Package/dependency version bumps\n\nRespond with a JSON object:\n{\n \"is_logic_change\": true/false,\n \"reason\": \"Brief explanation of why this is or is not a logic change\"\n}";
|
|
10
|
+
export declare function buildLogicCheckUserPrompt(commitMessage: string, truncatedDiff: string): string;
|
|
11
|
+
export declare const SPEC_EVALUATION_SYSTEM_PROMPT = "You are a technical documentation maintainer. Your task is to evaluate whether a git commit requires updating a software design specification (plan.md).\n\nGiven the current plan content, the commit message, and the code diff, determine:\n1. Whether the plan needs to be updated (UPDATE), deprecated (DEPRECATE), or left unchanged (UNCHANGED).\n2. If UPDATE: provide the new title, subtitles (as an array of heading-preview strings), and full rewritten plan_content.\n3. If DEPRECATE: provide a brief explanation in the plan_content field.\n\nResponse format (JSON):\n{\n \"action\": \"UPDATE\" | \"DEPRECATE\" | \"UNCHANGED\",\n \"title\": \"New spec title (for UPDATE)\",\n \"subtitles\": [\"heading1 \u2192 heading2 - preview\", ...],\n \"plan_content\": \"Full rewritten markdown content (for UPDATE) or deprecation reason (for DEPRECATE)\"\n}";
|
|
12
|
+
export declare function buildSpecEvaluationUserPrompt(planContent: string, commitMessage: string, truncatedDiff: string, scheduleNextSpecs: string[]): string;
|
|
13
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/spec/llm/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,eAAO,MAAM,yBAAyB,20BAmBpC,CAAC;AAEH,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,GACpB,MAAM,CAOR;AAMD,eAAO,MAAM,6BAA6B,w1BAaxC,CAAC;AAEH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,MAAM,EAAE,GAC1B,MAAM,CAcR"}
|