homegraph 0.9.10 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +243 -193
- package/dist/bin/fatal-handler.d.ts +20 -0
- package/dist/bin/fatal-handler.d.ts.map +1 -0
- package/dist/bin/fatal-handler.js +118 -0
- package/dist/bin/fatal-handler.js.map +1 -0
- package/dist/bin/homegraph.d.ts +6 -6
- package/dist/bin/homegraph.js +532 -109
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/bin/node-version-check.d.ts +4 -4
- package/dist/bin/node-version-check.js +12 -12
- package/dist/bin/uninstall.d.ts +1 -1
- package/dist/bin/uninstall.js +1 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +8 -1
- package/dist/context/index.js.map +1 -1
- package/dist/db/index.d.ts +22 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +48 -2
- 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 +26 -17
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/queries.d.ts +21 -1
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +180 -137
- package/dist/db/queries.js.map +1 -1
- package/dist/db/schema.sql +152 -151
- package/dist/db/sqlite-adapter.d.ts +1 -1
- package/dist/db/sqlite-adapter.js +3 -3
- package/dist/directory.d.ts +87 -6
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +319 -57
- package/dist/directory.js.map +1 -1
- package/dist/errors.d.ts +15 -15
- package/dist/errors.js +20 -20
- package/dist/extraction/astro-extractor.d.ts +79 -0
- package/dist/extraction/astro-extractor.d.ts.map +1 -0
- package/dist/extraction/astro-extractor.js +320 -0
- package/dist/extraction/astro-extractor.js.map +1 -0
- package/dist/extraction/context.d.ts +1 -1
- package/dist/extraction/context.js +1 -1
- package/dist/extraction/extraction-version.d.ts +2 -2
- package/dist/extraction/extraction-version.d.ts.map +1 -1
- package/dist/extraction/extraction-version.js +2 -2
- package/dist/extraction/extraction-version.js.map +1 -1
- package/dist/extraction/function-ref.d.ts +118 -0
- package/dist/extraction/function-ref.d.ts.map +1 -0
- package/dist/extraction/function-ref.js +727 -0
- package/dist/extraction/function-ref.js.map +1 -0
- package/dist/extraction/generated-detection.d.ts.map +1 -1
- package/dist/extraction/generated-detection.js +3 -0
- package/dist/extraction/generated-detection.js.map +1 -1
- package/dist/extraction/grammars.d.ts +15 -5
- package/dist/extraction/grammars.d.ts.map +1 -1
- package/dist/extraction/grammars.js +44 -10
- package/dist/extraction/grammars.js.map +1 -1
- package/dist/extraction/index.d.ts +37 -0
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +562 -70
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts-viewtree.d.ts +22 -0
- package/dist/extraction/languages/arkts-viewtree.d.ts.map +1 -0
- package/dist/extraction/languages/arkts-viewtree.js +133 -0
- package/dist/extraction/languages/arkts-viewtree.js.map +1 -0
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +211 -20
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/extraction/languages/c-cpp.d.ts +8 -0
- package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/dist/extraction/languages/c-cpp.js +104 -2
- package/dist/extraction/languages/c-cpp.js.map +1 -1
- package/dist/extraction/languages/csharp.d.ts.map +1 -1
- package/dist/extraction/languages/csharp.js +58 -3
- package/dist/extraction/languages/csharp.js.map +1 -1
- package/dist/extraction/languages/dart.d.ts.map +1 -1
- package/dist/extraction/languages/dart.js +183 -1
- package/dist/extraction/languages/dart.js.map +1 -1
- package/dist/extraction/languages/go.d.ts.map +1 -1
- package/dist/extraction/languages/go.js +37 -0
- package/dist/extraction/languages/go.js.map +1 -1
- package/dist/extraction/languages/index.d.ts.map +1 -1
- package/dist/extraction/languages/index.js +2 -0
- package/dist/extraction/languages/index.js.map +1 -1
- package/dist/extraction/languages/java.d.ts.map +1 -1
- package/dist/extraction/languages/java.js +241 -0
- package/dist/extraction/languages/java.js.map +1 -1
- package/dist/extraction/languages/javascript.d.ts.map +1 -1
- package/dist/extraction/languages/javascript.js +16 -0
- package/dist/extraction/languages/javascript.js.map +1 -1
- package/dist/extraction/languages/kotlin.d.ts.map +1 -1
- package/dist/extraction/languages/kotlin.js +94 -0
- package/dist/extraction/languages/kotlin.js.map +1 -1
- package/dist/extraction/languages/objc.d.ts.map +1 -1
- package/dist/extraction/languages/objc.js +42 -0
- package/dist/extraction/languages/objc.js.map +1 -1
- package/dist/extraction/languages/pascal.d.ts.map +1 -1
- package/dist/extraction/languages/pascal.js +11 -0
- package/dist/extraction/languages/pascal.js.map +1 -1
- package/dist/extraction/languages/php.d.ts.map +1 -1
- package/dist/extraction/languages/php.js +77 -1
- package/dist/extraction/languages/php.js.map +1 -1
- package/dist/extraction/languages/r.d.ts +3 -0
- package/dist/extraction/languages/r.d.ts.map +1 -0
- package/dist/extraction/languages/r.js +314 -0
- package/dist/extraction/languages/r.js.map +1 -0
- package/dist/extraction/languages/rust.d.ts.map +1 -1
- package/dist/extraction/languages/rust.js +29 -0
- package/dist/extraction/languages/rust.js.map +1 -1
- package/dist/extraction/languages/scala.d.ts.map +1 -1
- package/dist/extraction/languages/scala.js +44 -9
- package/dist/extraction/languages/scala.js.map +1 -1
- package/dist/extraction/languages/swift.d.ts.map +1 -1
- package/dist/extraction/languages/swift.js +61 -0
- package/dist/extraction/languages/swift.js.map +1 -1
- package/dist/extraction/languages/typescript.d.ts +13 -0
- package/dist/extraction/languages/typescript.d.ts.map +1 -1
- package/dist/extraction/languages/typescript.js +38 -0
- package/dist/extraction/languages/typescript.js.map +1 -1
- package/dist/extraction/liquid-extractor.d.ts.map +1 -1
- package/dist/extraction/liquid-extractor.js +4 -1
- package/dist/extraction/liquid-extractor.js.map +1 -1
- package/dist/extraction/parse-worker.js +4 -1
- package/dist/extraction/parse-worker.js.map +1 -1
- package/dist/extraction/svelte-extractor.d.ts.map +1 -1
- package/dist/extraction/svelte-extractor.js +6 -3
- package/dist/extraction/svelte-extractor.js.map +1 -1
- package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -1
- package/dist/extraction/tree-sitter-helpers.js +59 -10
- package/dist/extraction/tree-sitter-helpers.js.map +1 -1
- package/dist/extraction/tree-sitter-types.d.ts +29 -0
- package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.d.ts +192 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.js +1553 -45
- package/dist/extraction/tree-sitter.js.map +1 -1
- package/dist/extraction/vue-extractor.d.ts.map +1 -1
- package/dist/extraction/vue-extractor.js +6 -3
- package/dist/extraction/vue-extractor.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/extraction/wasm/tree-sitter-r.wasm +0 -0
- package/dist/graph/traversal.d.ts.map +1 -1
- package/dist/graph/traversal.js +11 -2
- package/dist/graph/traversal.js.map +1 -1
- package/dist/index.d.ts +64 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +137 -41
- package/dist/index.js.map +1 -1
- package/dist/installer/config-writer.d.ts +1 -1
- package/dist/installer/config-writer.js +1 -1
- package/dist/installer/index.d.ts +4 -4
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +100 -73
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/instructions-template.d.ts +34 -11
- package/dist/installer/instructions-template.d.ts.map +1 -1
- package/dist/installer/instructions-template.js +44 -12
- package/dist/installer/instructions-template.js.map +1 -1
- package/dist/installer/targets/antigravity.d.ts +6 -6
- package/dist/installer/targets/antigravity.js +14 -14
- package/dist/installer/targets/claude.d.ts +19 -13
- package/dist/installer/targets/claude.d.ts.map +1 -1
- package/dist/installer/targets/claude.js +97 -29
- package/dist/installer/targets/claude.js.map +1 -1
- package/dist/installer/targets/codebuddy.d.ts +17 -0
- package/dist/installer/targets/codebuddy.d.ts.map +1 -0
- package/dist/installer/targets/codebuddy.js +150 -0
- package/dist/installer/targets/codebuddy.js.map +1 -0
- package/dist/installer/targets/codex.js +5 -7
- package/dist/installer/targets/codex.js.map +1 -1
- package/dist/installer/targets/cursor.d.ts +1 -1
- package/dist/installer/targets/cursor.js +7 -7
- package/dist/installer/targets/deveco.d.ts +23 -0
- package/dist/installer/targets/deveco.d.ts.map +1 -0
- package/dist/installer/targets/deveco.js +217 -0
- package/dist/installer/targets/deveco.js.map +1 -0
- package/dist/installer/targets/gemini.js +5 -7
- package/dist/installer/targets/gemini.js.map +1 -1
- package/dist/installer/targets/hermes.js +15 -15
- package/dist/installer/targets/kiro.d.ts +1 -1
- package/dist/installer/targets/kiro.js +4 -4
- package/dist/installer/targets/opencode.d.ts +9 -1
- package/dist/installer/targets/opencode.d.ts.map +1 -1
- package/dist/installer/targets/opencode.js +92 -41
- package/dist/installer/targets/opencode.js.map +1 -1
- package/dist/installer/targets/registry.d.ts.map +1 -1
- package/dist/installer/targets/registry.js +4 -0
- package/dist/installer/targets/registry.js.map +1 -1
- package/dist/installer/targets/shared.d.ts +28 -4
- package/dist/installer/targets/shared.d.ts.map +1 -1
- package/dist/installer/targets/shared.js +32 -15
- package/dist/installer/targets/shared.js.map +1 -1
- package/dist/installer/targets/types.d.ts +9 -2
- package/dist/installer/targets/types.d.ts.map +1 -1
- package/dist/mcp/daemon-manager.d.ts +42 -0
- package/dist/mcp/daemon-manager.d.ts.map +1 -0
- package/dist/mcp/daemon-manager.js +129 -0
- package/dist/mcp/daemon-manager.js.map +1 -0
- package/dist/mcp/daemon-paths.d.ts +1 -1
- package/dist/mcp/daemon-paths.js +3 -3
- package/dist/mcp/daemon-registry.d.ts +47 -0
- package/dist/mcp/daemon-registry.d.ts.map +1 -0
- package/dist/mcp/daemon-registry.js +229 -0
- package/dist/mcp/daemon-registry.js.map +1 -0
- package/dist/mcp/daemon.d.ts.map +1 -1
- package/dist/mcp/daemon.js +27 -6
- package/dist/mcp/daemon.js.map +1 -1
- package/dist/mcp/dynamic-boundaries.d.ts +41 -0
- package/dist/mcp/dynamic-boundaries.d.ts.map +1 -0
- package/dist/mcp/dynamic-boundaries.js +359 -0
- package/dist/mcp/dynamic-boundaries.js.map +1 -0
- package/dist/mcp/engine.d.ts +4 -4
- package/dist/mcp/engine.d.ts.map +1 -1
- package/dist/mcp/engine.js +32 -24
- package/dist/mcp/engine.js.map +1 -1
- package/dist/mcp/index.d.ts +8 -7
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +39 -18
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/liveness-watchdog.d.ts +18 -0
- package/dist/mcp/liveness-watchdog.d.ts.map +1 -0
- package/dist/mcp/liveness-watchdog.js +207 -0
- package/dist/mcp/liveness-watchdog.js.map +1 -0
- package/dist/mcp/proxy.d.ts +6 -0
- package/dist/mcp/proxy.d.ts.map +1 -1
- package/dist/mcp/proxy.js +75 -18
- package/dist/mcp/proxy.js.map +1 -1
- package/dist/mcp/server-instructions.d.ts +22 -7
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +91 -59
- package/dist/mcp/server-instructions.js.map +1 -1
- package/dist/mcp/session.d.ts +3 -1
- package/dist/mcp/session.d.ts.map +1 -1
- package/dist/mcp/session.js +43 -7
- package/dist/mcp/session.js.map +1 -1
- package/dist/mcp/stdin-teardown.d.ts +27 -0
- package/dist/mcp/stdin-teardown.d.ts.map +1 -0
- package/dist/mcp/stdin-teardown.js +49 -0
- package/dist/mcp/stdin-teardown.js.map +1 -0
- package/dist/mcp/tools.d.ts +137 -16
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +1271 -219
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp/transport.d.ts +1 -1
- package/dist/mcp/transport.d.ts.map +1 -1
- package/dist/mcp/transport.js +20 -4
- package/dist/mcp/transport.js.map +1 -1
- package/dist/mcp/version.d.ts +1 -1
- package/dist/mcp/version.js +2 -2
- package/dist/project-config.d.ts +36 -0
- package/dist/project-config.d.ts.map +1 -0
- package/dist/project-config.js +235 -0
- package/dist/project-config.js.map +1 -0
- package/dist/reasoning/config.d.ts +45 -0
- package/dist/reasoning/config.d.ts.map +1 -0
- package/dist/reasoning/config.js +171 -0
- package/dist/reasoning/config.js.map +1 -0
- package/dist/reasoning/credentials.d.ts +5 -0
- package/dist/reasoning/credentials.d.ts.map +1 -0
- package/dist/reasoning/credentials.js +83 -0
- package/dist/reasoning/credentials.js.map +1 -0
- package/dist/reasoning/login.d.ts +21 -0
- package/dist/reasoning/login.d.ts.map +1 -0
- package/dist/reasoning/login.js +85 -0
- package/dist/reasoning/login.js.map +1 -0
- package/dist/reasoning/reasoner.d.ts +43 -0
- package/dist/reasoning/reasoner.d.ts.map +1 -0
- package/dist/reasoning/reasoner.js +308 -0
- package/dist/reasoning/reasoner.js.map +1 -0
- package/dist/resolution/c-fnptr-synthesizer.d.ts +33 -0
- package/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -0
- package/dist/resolution/c-fnptr-synthesizer.js +352 -0
- package/dist/resolution/c-fnptr-synthesizer.js.map +1 -0
- package/dist/resolution/callback-synthesizer.d.ts +6 -1
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/dist/resolution/callback-synthesizer.js +1197 -1
- package/dist/resolution/callback-synthesizer.js.map +1 -1
- package/dist/resolution/frameworks/arkts-entry.d.ts +12 -0
- package/dist/resolution/frameworks/arkts-entry.d.ts.map +1 -0
- package/dist/resolution/frameworks/arkts-entry.js +214 -0
- package/dist/resolution/frameworks/arkts-entry.js.map +1 -0
- package/dist/resolution/frameworks/arkts-napi.d.ts +3 -0
- package/dist/resolution/frameworks/arkts-napi.d.ts.map +1 -0
- package/dist/resolution/frameworks/arkts-napi.js +166 -0
- package/dist/resolution/frameworks/arkts-napi.js.map +1 -0
- package/dist/resolution/frameworks/astro.d.ts +9 -0
- package/dist/resolution/frameworks/astro.d.ts.map +1 -0
- package/dist/resolution/frameworks/astro.js +169 -0
- package/dist/resolution/frameworks/astro.js.map +1 -0
- package/dist/resolution/frameworks/goframe.d.ts +41 -0
- package/dist/resolution/frameworks/goframe.d.ts.map +1 -0
- package/dist/resolution/frameworks/goframe.js +112 -0
- package/dist/resolution/frameworks/goframe.js.map +1 -0
- package/dist/resolution/frameworks/index.d.ts +3 -0
- package/dist/resolution/frameworks/index.d.ts.map +1 -1
- package/dist/resolution/frameworks/index.js +17 -1
- package/dist/resolution/frameworks/index.js.map +1 -1
- package/dist/resolution/frameworks/java.js +6 -1
- package/dist/resolution/frameworks/java.js.map +1 -1
- package/dist/resolution/frameworks/react.d.ts.map +1 -1
- package/dist/resolution/frameworks/react.js +32 -63
- package/dist/resolution/frameworks/react.js.map +1 -1
- package/dist/resolution/frameworks/svelte.js +6 -2
- package/dist/resolution/frameworks/svelte.js.map +1 -1
- package/dist/resolution/frameworks/vue.js +24 -27
- package/dist/resolution/frameworks/vue.js.map +1 -1
- package/dist/resolution/goframe-synthesizer.d.ts +28 -0
- package/dist/resolution/goframe-synthesizer.d.ts.map +1 -0
- package/dist/resolution/goframe-synthesizer.js +158 -0
- package/dist/resolution/goframe-synthesizer.js.map +1 -0
- package/dist/resolution/import-resolver.d.ts +10 -0
- package/dist/resolution/import-resolver.d.ts.map +1 -1
- package/dist/resolution/import-resolver.js +125 -2
- package/dist/resolution/import-resolver.js.map +1 -1
- package/dist/resolution/index.d.ts +37 -0
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +306 -3
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/name-matcher.d.ts +41 -0
- package/dist/resolution/name-matcher.d.ts.map +1 -1
- package/dist/resolution/name-matcher.js +519 -14
- package/dist/resolution/name-matcher.js.map +1 -1
- package/dist/resolution/strip-comments.d.ts +1 -1
- package/dist/resolution/strip-comments.d.ts.map +1 -1
- package/dist/resolution/strip-comments.js +2 -0
- package/dist/resolution/strip-comments.js.map +1 -1
- package/dist/resolution/types.d.ts +20 -3
- package/dist/resolution/types.d.ts.map +1 -1
- package/dist/search/query-utils.d.ts +17 -1
- package/dist/search/query-utils.d.ts.map +1 -1
- package/dist/search/query-utils.js +79 -10
- package/dist/search/query-utils.js.map +1 -1
- package/dist/sync/git-hooks.d.ts +4 -4
- package/dist/sync/git-hooks.js +5 -5
- package/dist/sync/watcher.d.ts +69 -2
- package/dist/sync/watcher.d.ts.map +1 -1
- package/dist/sync/watcher.js +226 -21
- package/dist/sync/watcher.js.map +1 -1
- package/dist/sync/worktree.d.ts +3 -3
- package/dist/sync/worktree.js +5 -5
- package/dist/telemetry/index.d.ts +143 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +541 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/types.d.ts +18 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -1
- package/dist/types.js.map +1 -1
- package/dist/upgrade/index.d.ts.map +1 -1
- package/dist/upgrade/index.js +46 -10
- package/dist/upgrade/index.js.map +1 -1
- package/dist/utils.d.ts +46 -27
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +87 -53
- package/dist/utils.js.map +1 -1
- package/package.json +57 -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 -0
- package/scripts/agent-eval/ab-hook.sh +86 -0
- package/scripts/agent-eval/ab-impl.sh +78 -0
- package/scripts/agent-eval/ab-new-vs-baseline.sh +102 -0
- package/scripts/agent-eval/ab-sufficiency.sh +78 -0
- 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 -0
- package/scripts/agent-eval/offload-eval-cost.mjs +133 -0
- package/scripts/agent-eval/offload-eval-effort.mjs +108 -0
- package/scripts/agent-eval/offload-eval-frontload-matrix.sh +25 -0
- package/scripts/agent-eval/offload-eval-frontload.sh +47 -0
- package/scripts/agent-eval/offload-eval-ground-truth.json +18 -0
- package/scripts/agent-eval/offload-eval-hook.mjs +84 -0
- package/scripts/agent-eval/offload-eval-judge.mjs +103 -0
- package/scripts/agent-eval/offload-eval-matrix.sh +20 -0
- package/scripts/agent-eval/offload-eval-metrics.mjs +94 -0
- package/scripts/agent-eval/offload-eval-refs1.sh +50 -0
- package/scripts/agent-eval/offload-eval-setup.sh +24 -0
- package/scripts/agent-eval/offload-eval-styles.sh +72 -0
- package/scripts/agent-eval/offload-eval-summarize.mjs +68 -0
- package/scripts/agent-eval/offload-eval.md +76 -0
- 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 -0
- package/scripts/agent-eval/run-agent.sh +34 -34
- package/scripts/agent-eval/run-all.sh +69 -67
- 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/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 +246 -246
- package/scripts/pack-npm.sh +119 -119
- package/scripts/prepare-release.mjs +270 -270
- package/scripts/qa_eval/README.md +400 -0
- package/scripts/qa_eval/agent_runner.py +526 -0
- package/scripts/qa_eval/data/.gitignore +4 -0
- package/scripts/qa_eval/data/test-set.jsonl +22 -0
- package/scripts/qa_eval/eval_metrics.py +233 -0
- package/scripts/qa_eval/external_agent.py +577 -0
- package/scripts/qa_eval/llm_config.py +92 -0
- package/scripts/qa_eval/memory_monitor.py +132 -0
- package/scripts/qa_eval/my_answer_accuracy.py +187 -0
- package/scripts/qa_eval/requirements.txt +2 -0
- package/scripts/qa_eval/run_pipeline.py +702 -0
- package/scripts/qa_eval/stats_efficiency.py +279 -0
- package/scripts/qa_eval/stats_scores.py +207 -0
- package/dist/bin/codegraph.d.ts +0 -26
- package/dist/bin/codegraph.d.ts.map +0 -1
- package/dist/bin/codegraph.js +0 -1572
- package/dist/bin/codegraph.js.map +0 -1
- package/dist/extraction/arkanalyzer-extractor.d.ts +0 -6
- package/dist/extraction/arkanalyzer-extractor.d.ts.map +0 -1
- package/dist/extraction/arkanalyzer-extractor.js +0 -11
- package/dist/extraction/arkanalyzer-extractor.js.map +0 -1
- package/dist/extraction/arkanalyzer-project.d.ts +0 -20
- package/dist/extraction/arkanalyzer-project.d.ts.map +0 -1
- package/dist/extraction/arkanalyzer-project.js +0 -596
- package/dist/extraction/arkanalyzer-project.js.map +0 -1
package/dist/directory.d.ts
CHANGED
|
@@ -1,31 +1,112 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Directory Management
|
|
3
3
|
*
|
|
4
|
-
* Manages the .homegraph/ directory structure for
|
|
4
|
+
* Manages the .homegraph/ directory structure for HomeGraph data.
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Resolve the per-project data directory name, honoring the `HOMEGRAPH_DIR`
|
|
8
|
+
* environment override (default `.homegraph`). The override is a single path
|
|
9
|
+
* segment that lives in the project root.
|
|
10
|
+
*
|
|
11
|
+
* Why this exists: two environments that share one working tree must NOT share
|
|
12
|
+
* one `.homegraph/` — most concretely Windows-native and WSL (issue #636). The
|
|
13
|
+
* daemon lockfile (`.homegraph/daemon.pid`) records a platform-specific pid and
|
|
14
|
+
* socket path (a Windows named pipe vs a WSL Unix socket), and SQLite file
|
|
15
|
+
* locking across the WSL2 ↔ Windows filesystem boundary is unreliable, so two
|
|
16
|
+
* daemons sharing one index risks corruption. Setting `HOMEGRAPH_DIR=.homegraph-win`
|
|
17
|
+
* on one side gives each environment its own index in the same tree.
|
|
18
|
+
*
|
|
19
|
+
* Read live (not captured at load) so it is both process-accurate and testable.
|
|
20
|
+
* An override that isn't a plain directory name — empty, containing a path
|
|
21
|
+
* separator, `.`, `..`/traversal, or absolute — is ignored (we keep the
|
|
22
|
+
* default) rather than risk writing the index outside the project or into the
|
|
23
|
+
* project root itself; we warn once to stderr so the misconfiguration is seen.
|
|
8
24
|
*/
|
|
25
|
+
export declare function homeGraphDirName(): string;
|
|
26
|
+
/** Default data directory name (also honors {@link homeGraphDirName} at runtime). */
|
|
9
27
|
export declare const HOMEGRAPH_DIR = ".homegraph";
|
|
28
|
+
/**
|
|
29
|
+
* Is `name` (a single path segment) a HomeGraph data directory? Matches the
|
|
30
|
+
* default `.homegraph`, the active override, and any `.homegraph-*` sibling.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isHomeGraphDataDir(name: string): boolean;
|
|
10
33
|
/**
|
|
11
34
|
* Get the .homegraph directory path for a project
|
|
12
35
|
*/
|
|
13
|
-
export declare function
|
|
36
|
+
export declare function getHomeGraphDir(projectRoot: string): string;
|
|
14
37
|
/**
|
|
15
|
-
* Check if a project has been initialized with
|
|
38
|
+
* Check if a project has been initialized with HomeGraph
|
|
16
39
|
* Requires both .homegraph/ directory AND homegraph.db to exist
|
|
17
40
|
*/
|
|
18
41
|
export declare function isInitialized(projectRoot: string): boolean;
|
|
19
42
|
/**
|
|
20
43
|
* Find the nearest parent directory containing .homegraph/
|
|
21
44
|
*
|
|
22
|
-
* Walks up from the given path to find a
|
|
45
|
+
* Walks up from the given path to find a HomeGraph-initialized project,
|
|
23
46
|
* similar to how git finds .git/ directories.
|
|
24
47
|
*
|
|
25
48
|
* @param startPath - Directory to start searching from
|
|
26
49
|
* @returns The project root containing .homegraph/, or null if not found
|
|
27
50
|
*/
|
|
28
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Reason a directory is unsafe to use as an index ROOT, or null when it's fine.
|
|
53
|
+
*
|
|
54
|
+
* Indexing your home directory or a filesystem root drags in caches, `Library`,
|
|
55
|
+
* every other project, etc. — a multi-GB index, constant file-watcher churn, and
|
|
56
|
+
* (pre-1.0 on macOS) a file-descriptor blowup that exhausted `kern.maxfiles` and
|
|
57
|
+
* took unrelated apps / the whole machine down (#845). The classic trigger:
|
|
58
|
+
* running the installer or `homegraph init` from `$HOME`, which auto-indexes the
|
|
59
|
+
* current directory. These are never intended project roots, so the installer
|
|
60
|
+
* and `init`/`index` refuse them (overridable with `--force`).
|
|
61
|
+
*
|
|
62
|
+
* Pure-ish (reads only `os.homedir()` + realpath) so it's easy to unit-test.
|
|
63
|
+
* The returned string is a human phrase that slots into "… looks like {reason}".
|
|
64
|
+
*/
|
|
65
|
+
export declare function unsafeIndexRootReason(projectRoot: string): string | null;
|
|
66
|
+
export declare function findNearestHomeGraphRoot(startPath: string): string | null;
|
|
67
|
+
/**
|
|
68
|
+
* Indexed sub-project roots beneath `root` (bounded breadth-first scan). For
|
|
69
|
+
* the monorepo case behind #964: the index lives in a CHILD
|
|
70
|
+
* (`packages/x/.homegraph/`), not at the workspace root the agent's cwd points
|
|
71
|
+
* at. Descent stops at the first indexed directory on a branch (a project's
|
|
72
|
+
* own sub-dirs aren't separate projects) and is bounded by depth + count so it
|
|
73
|
+
* never turns into a full-tree crawl on a large repo.
|
|
74
|
+
*/
|
|
75
|
+
export declare function findIndexedSubprojectRoots(root: string, opts?: {
|
|
76
|
+
maxDepth?: number;
|
|
77
|
+
max?: number;
|
|
78
|
+
}): string[];
|
|
79
|
+
/**
|
|
80
|
+
* What the front-load hook should do for a prompt issued from a directory.
|
|
81
|
+
*/
|
|
82
|
+
export interface FrontloadPlan {
|
|
83
|
+
/** Open + explore this project and inject its source as context. `null` when
|
|
84
|
+
* there's no single project to front-load (none indexed, or several indexed
|
|
85
|
+
* sub-projects with no clear match — see {@link nudgeProjects}). */
|
|
86
|
+
exploreRoot: string | null;
|
|
87
|
+
/** Indexed sub-projects to surface in a "pass `projectPath`" nudge: the rest
|
|
88
|
+
* of a monorepo's indexed projects alongside `exploreRoot`, or — when no one
|
|
89
|
+
* project clearly matches — the full list (with `exploreRoot` null). */
|
|
90
|
+
nudgeProjects: string[];
|
|
91
|
+
/** True when the plan came from scanning DOWN into sub-projects (cwd itself
|
|
92
|
+
* is not under any index) — the monorepo case, where a follow-up
|
|
93
|
+
* `homegraph_explore` needs an explicit `projectPath`. */
|
|
94
|
+
viaSubScan: boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Decide what the front-load hook injects for a `prompt` issued from `cwd`,
|
|
98
|
+
* shaped by where the `.homegraph/` index(es) actually are:
|
|
99
|
+
* 1. **cwd (or an ancestor) is indexed** → front-load that project. The
|
|
100
|
+
* normal single-project / nested-file case.
|
|
101
|
+
* 2. **cwd isn't indexed but looks like a workspace root** → the indexes live
|
|
102
|
+
* in sub-projects (the monorepo case behind #964). One indexed
|
|
103
|
+
* sub-project → front-load it; several → front-load the one the prompt
|
|
104
|
+
* names (by relative path like `packages/api`, or package directory name)
|
|
105
|
+
* and nudge about the rest; several with no match → nudge the full list so
|
|
106
|
+
* the agent passes `projectPath`, rather than guessing wrong.
|
|
107
|
+
* 3. **nothing indexed reachable** → do nothing (the agent's own tools apply).
|
|
108
|
+
*/
|
|
109
|
+
export declare function planFrontload(cwd: string, prompt: string): FrontloadPlan;
|
|
29
110
|
/**
|
|
30
111
|
* Create the .homegraph directory structure
|
|
31
112
|
* Note: Only throws if homegraph.db already exists, not just if .homegraph/ exists.
|
package/dist/directory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAqBzC;AAED,qFAAqF;AACrF,eAAO,MAAM,aAAa,eAAwB,CAAC;AAEnD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOxD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAQ1D;AAED;;;;;;;;GAQG;AACH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8BxE;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmBzE;AA2BD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7C,MAAM,EAAE,CAmBV;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;yEAEqE;IACrE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;6EAEyE;IACzE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB;;+DAE2D;IAC3D,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAwCxE;AAyDD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAgBzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAuBzD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BnE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CA+B5D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAYlF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG;IACtD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CA6BA"}
|
package/dist/directory.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Directory Management
|
|
4
4
|
*
|
|
5
|
-
* Manages the .homegraph/ directory structure for
|
|
5
|
+
* Manages the .homegraph/ directory structure for HomeGraph data.
|
|
6
6
|
*/
|
|
7
7
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
8
|
if (k2 === undefined) k2 = k;
|
|
@@ -39,9 +39,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
})();
|
|
40
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
41
|
exports.HOMEGRAPH_DIR = void 0;
|
|
42
|
-
exports.
|
|
42
|
+
exports.homeGraphDirName = homeGraphDirName;
|
|
43
|
+
exports.isHomeGraphDataDir = isHomeGraphDataDir;
|
|
44
|
+
exports.getHomeGraphDir = getHomeGraphDir;
|
|
43
45
|
exports.isInitialized = isInitialized;
|
|
44
|
-
exports.
|
|
46
|
+
exports.unsafeIndexRootReason = unsafeIndexRootReason;
|
|
47
|
+
exports.findNearestHomeGraphRoot = findNearestHomeGraphRoot;
|
|
48
|
+
exports.findIndexedSubprojectRoots = findIndexedSubprojectRoots;
|
|
49
|
+
exports.planFrontload = planFrontload;
|
|
45
50
|
exports.createDirectory = createDirectory;
|
|
46
51
|
exports.removeDirectory = removeDirectory;
|
|
47
52
|
exports.listDirectoryContents = listDirectoryContents;
|
|
@@ -49,40 +54,133 @@ exports.getDirectorySize = getDirectorySize;
|
|
|
49
54
|
exports.ensureSubdirectory = ensureSubdirectory;
|
|
50
55
|
exports.validateDirectory = validateDirectory;
|
|
51
56
|
const fs = __importStar(require("fs"));
|
|
57
|
+
const os = __importStar(require("os"));
|
|
52
58
|
const path = __importStar(require("path"));
|
|
59
|
+
/** The default per-project data directory name. */
|
|
60
|
+
const DEFAULT_HOMEGRAPH_DIR = '.homegraph';
|
|
61
|
+
let warnedBadDirName = false;
|
|
53
62
|
/**
|
|
54
|
-
*
|
|
63
|
+
* Resolve the per-project data directory name, honoring the `HOMEGRAPH_DIR`
|
|
64
|
+
* environment override (default `.homegraph`). The override is a single path
|
|
65
|
+
* segment that lives in the project root.
|
|
66
|
+
*
|
|
67
|
+
* Why this exists: two environments that share one working tree must NOT share
|
|
68
|
+
* one `.homegraph/` — most concretely Windows-native and WSL (issue #636). The
|
|
69
|
+
* daemon lockfile (`.homegraph/daemon.pid`) records a platform-specific pid and
|
|
70
|
+
* socket path (a Windows named pipe vs a WSL Unix socket), and SQLite file
|
|
71
|
+
* locking across the WSL2 ↔ Windows filesystem boundary is unreliable, so two
|
|
72
|
+
* daemons sharing one index risks corruption. Setting `HOMEGRAPH_DIR=.homegraph-win`
|
|
73
|
+
* on one side gives each environment its own index in the same tree.
|
|
74
|
+
*
|
|
75
|
+
* Read live (not captured at load) so it is both process-accurate and testable.
|
|
76
|
+
* An override that isn't a plain directory name — empty, containing a path
|
|
77
|
+
* separator, `.`, `..`/traversal, or absolute — is ignored (we keep the
|
|
78
|
+
* default) rather than risk writing the index outside the project or into the
|
|
79
|
+
* project root itself; we warn once to stderr so the misconfiguration is seen.
|
|
80
|
+
*/
|
|
81
|
+
function homeGraphDirName() {
|
|
82
|
+
const raw = process.env.HOMEGRAPH_DIR?.trim();
|
|
83
|
+
if (!raw)
|
|
84
|
+
return DEFAULT_HOMEGRAPH_DIR;
|
|
85
|
+
const invalid = raw === '.' ||
|
|
86
|
+
raw.includes('..') ||
|
|
87
|
+
raw.includes('/') ||
|
|
88
|
+
raw.includes('\\') ||
|
|
89
|
+
path.isAbsolute(raw);
|
|
90
|
+
if (invalid) {
|
|
91
|
+
if (!warnedBadDirName) {
|
|
92
|
+
warnedBadDirName = true;
|
|
93
|
+
// stderr only — stdout is the MCP protocol channel.
|
|
94
|
+
console.warn(`[homegraph] Ignoring invalid HOMEGRAPH_DIR="${raw}" — it must be a plain ` +
|
|
95
|
+
`directory name (no path separators, no "..", not absolute). Using "${DEFAULT_HOMEGRAPH_DIR}".`);
|
|
96
|
+
}
|
|
97
|
+
return DEFAULT_HOMEGRAPH_DIR;
|
|
98
|
+
}
|
|
99
|
+
return raw;
|
|
100
|
+
}
|
|
101
|
+
/** Default data directory name (also honors {@link homeGraphDirName} at runtime). */
|
|
102
|
+
exports.HOMEGRAPH_DIR = DEFAULT_HOMEGRAPH_DIR;
|
|
103
|
+
/**
|
|
104
|
+
* Is `name` (a single path segment) a HomeGraph data directory? Matches the
|
|
105
|
+
* default `.homegraph`, the active override, and any `.homegraph-*` sibling.
|
|
55
106
|
*/
|
|
56
|
-
|
|
107
|
+
function isHomeGraphDataDir(name) {
|
|
108
|
+
const active = homeGraphDirName();
|
|
109
|
+
return (name === DEFAULT_HOMEGRAPH_DIR ||
|
|
110
|
+
name === active ||
|
|
111
|
+
name.startsWith(DEFAULT_HOMEGRAPH_DIR + '-'));
|
|
112
|
+
}
|
|
57
113
|
/**
|
|
58
114
|
* Get the .homegraph directory path for a project
|
|
59
115
|
*/
|
|
60
|
-
function
|
|
61
|
-
return path.join(projectRoot,
|
|
116
|
+
function getHomeGraphDir(projectRoot) {
|
|
117
|
+
return path.join(projectRoot, homeGraphDirName());
|
|
62
118
|
}
|
|
63
119
|
/**
|
|
64
|
-
* Check if a project has been initialized with
|
|
120
|
+
* Check if a project has been initialized with HomeGraph
|
|
65
121
|
* Requires both .homegraph/ directory AND homegraph.db to exist
|
|
66
122
|
*/
|
|
67
123
|
function isInitialized(projectRoot) {
|
|
68
|
-
const
|
|
69
|
-
if (!fs.existsSync(
|
|
124
|
+
const homegraphDir = getHomeGraphDir(projectRoot);
|
|
125
|
+
if (!fs.existsSync(homegraphDir) || !fs.statSync(homegraphDir).isDirectory()) {
|
|
70
126
|
return false;
|
|
71
127
|
}
|
|
72
128
|
// Must have homegraph.db, not just .homegraph folder
|
|
73
|
-
const dbPath = path.join(
|
|
129
|
+
const dbPath = path.join(homegraphDir, 'homegraph.db');
|
|
74
130
|
return fs.existsSync(dbPath);
|
|
75
131
|
}
|
|
76
132
|
/**
|
|
77
133
|
* Find the nearest parent directory containing .homegraph/
|
|
78
134
|
*
|
|
79
|
-
* Walks up from the given path to find a
|
|
135
|
+
* Walks up from the given path to find a HomeGraph-initialized project,
|
|
80
136
|
* similar to how git finds .git/ directories.
|
|
81
137
|
*
|
|
82
138
|
* @param startPath - Directory to start searching from
|
|
83
139
|
* @returns The project root containing .homegraph/, or null if not found
|
|
84
140
|
*/
|
|
85
|
-
|
|
141
|
+
/**
|
|
142
|
+
* Reason a directory is unsafe to use as an index ROOT, or null when it's fine.
|
|
143
|
+
*
|
|
144
|
+
* Indexing your home directory or a filesystem root drags in caches, `Library`,
|
|
145
|
+
* every other project, etc. — a multi-GB index, constant file-watcher churn, and
|
|
146
|
+
* (pre-1.0 on macOS) a file-descriptor blowup that exhausted `kern.maxfiles` and
|
|
147
|
+
* took unrelated apps / the whole machine down (#845). The classic trigger:
|
|
148
|
+
* running the installer or `homegraph init` from `$HOME`, which auto-indexes the
|
|
149
|
+
* current directory. These are never intended project roots, so the installer
|
|
150
|
+
* and `init`/`index` refuse them (overridable with `--force`).
|
|
151
|
+
*
|
|
152
|
+
* Pure-ish (reads only `os.homedir()` + realpath) so it's easy to unit-test.
|
|
153
|
+
* The returned string is a human phrase that slots into "… looks like {reason}".
|
|
154
|
+
*/
|
|
155
|
+
function unsafeIndexRootReason(projectRoot) {
|
|
156
|
+
const resolve = (p) => {
|
|
157
|
+
try {
|
|
158
|
+
return fs.realpathSync(path.resolve(p));
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return path.resolve(p);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
const resolved = resolve(projectRoot);
|
|
165
|
+
// Filesystem root: `/` on POSIX, a drive root like `C:\` on Windows.
|
|
166
|
+
if (path.parse(resolved).root === resolved) {
|
|
167
|
+
return 'the filesystem root';
|
|
168
|
+
}
|
|
169
|
+
const home = resolve(os.homedir());
|
|
170
|
+
// Case-insensitive on macOS/Windows (case-preserving but case-insensitive FS).
|
|
171
|
+
const norm = (p) => process.platform === 'darwin' || process.platform === 'win32' ? p.toLowerCase() : p;
|
|
172
|
+
const r = norm(resolved);
|
|
173
|
+
const h = norm(home);
|
|
174
|
+
if (r === h) {
|
|
175
|
+
return 'your home directory';
|
|
176
|
+
}
|
|
177
|
+
// An ancestor of home (e.g. `/Users`, `/home`) — even broader than home.
|
|
178
|
+
if (h.startsWith(r + path.sep)) {
|
|
179
|
+
return 'a parent of your home directory';
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
function findNearestHomeGraphRoot(startPath) {
|
|
86
184
|
let current = path.resolve(startPath);
|
|
87
185
|
const root = path.parse(current).root;
|
|
88
186
|
while (current !== root) {
|
|
@@ -100,61 +198,227 @@ function findNearestCodeGraphRoot(startPath) {
|
|
|
100
198
|
}
|
|
101
199
|
return null;
|
|
102
200
|
}
|
|
201
|
+
/** Heavy/irrelevant directory names the sub-project scan never descends into. */
|
|
202
|
+
const SUBPROJECT_SCAN_SKIP = new Set([
|
|
203
|
+
'node_modules', '.git', '.svn', '.hg', 'dist', 'build', 'out', 'target',
|
|
204
|
+
'vendor', 'bin', 'obj', '.next', '.nuxt', '.svelte-kit', '.cache', 'coverage',
|
|
205
|
+
'.venv', 'venv', '__pycache__', '.turbo', '.idea', '.vscode', 'tmp', 'temp',
|
|
206
|
+
]);
|
|
207
|
+
/** Manifests that mark a directory as a project/workspace root. The down-scan
|
|
208
|
+
* is gated on one of these so a non-project cwd (e.g. `$HOME`) is a cheap
|
|
209
|
+
* no-op instead of a deep filesystem crawl. */
|
|
210
|
+
const WORKSPACE_ROOT_MANIFESTS = [
|
|
211
|
+
'package.json', 'pnpm-workspace.yaml', 'lerna.json', 'nx.json', 'turbo.json',
|
|
212
|
+
'go.work', 'go.mod', 'Cargo.toml', 'pom.xml', 'build.gradle', 'build.gradle.kts',
|
|
213
|
+
'settings.gradle', 'pyproject.toml', 'composer.json', 'Gemfile', 'rush.json',
|
|
214
|
+
'WORKSPACE', 'WORKSPACE.bazel',
|
|
215
|
+
];
|
|
216
|
+
function looksLikeProjectRoot(dir) {
|
|
217
|
+
return WORKSPACE_ROOT_MANIFESTS.some((m) => fs.existsSync(path.join(dir, m)));
|
|
218
|
+
}
|
|
219
|
+
function escapeRegExp(s) {
|
|
220
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Indexed sub-project roots beneath `root` (bounded breadth-first scan). For
|
|
224
|
+
* the monorepo case behind #964: the index lives in a CHILD
|
|
225
|
+
* (`packages/x/.homegraph/`), not at the workspace root the agent's cwd points
|
|
226
|
+
* at. Descent stops at the first indexed directory on a branch (a project's
|
|
227
|
+
* own sub-dirs aren't separate projects) and is bounded by depth + count so it
|
|
228
|
+
* never turns into a full-tree crawl on a large repo.
|
|
229
|
+
*/
|
|
230
|
+
function findIndexedSubprojectRoots(root, opts = {}) {
|
|
231
|
+
const maxDepth = opts.maxDepth ?? 4;
|
|
232
|
+
const max = opts.max ?? 64;
|
|
233
|
+
const out = [];
|
|
234
|
+
const walk = (dir, depth) => {
|
|
235
|
+
if (out.length >= max || depth > maxDepth)
|
|
236
|
+
return;
|
|
237
|
+
let entries;
|
|
238
|
+
try {
|
|
239
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
for (const e of entries) {
|
|
245
|
+
if (out.length >= max)
|
|
246
|
+
return;
|
|
247
|
+
if (!e.isDirectory())
|
|
248
|
+
continue;
|
|
249
|
+
if (e.name.startsWith('.') || SUBPROJECT_SCAN_SKIP.has(e.name))
|
|
250
|
+
continue;
|
|
251
|
+
const child = path.join(dir, e.name);
|
|
252
|
+
if (isInitialized(child)) {
|
|
253
|
+
out.push(child);
|
|
254
|
+
continue;
|
|
255
|
+
} // don't descend into an indexed project
|
|
256
|
+
walk(child, depth + 1);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
walk(root, 1);
|
|
260
|
+
return out;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Decide what the front-load hook injects for a `prompt` issued from `cwd`,
|
|
264
|
+
* shaped by where the `.homegraph/` index(es) actually are:
|
|
265
|
+
* 1. **cwd (or an ancestor) is indexed** → front-load that project. The
|
|
266
|
+
* normal single-project / nested-file case.
|
|
267
|
+
* 2. **cwd isn't indexed but looks like a workspace root** → the indexes live
|
|
268
|
+
* in sub-projects (the monorepo case behind #964). One indexed
|
|
269
|
+
* sub-project → front-load it; several → front-load the one the prompt
|
|
270
|
+
* names (by relative path like `packages/api`, or package directory name)
|
|
271
|
+
* and nudge about the rest; several with no match → nudge the full list so
|
|
272
|
+
* the agent passes `projectPath`, rather than guessing wrong.
|
|
273
|
+
* 3. **nothing indexed reachable** → do nothing (the agent's own tools apply).
|
|
274
|
+
*/
|
|
275
|
+
function planFrontload(cwd, prompt) {
|
|
276
|
+
const none = { exploreRoot: null, nudgeProjects: [], viaSubScan: false };
|
|
277
|
+
// 1. up-walk — nearest indexed ancestor (incl. cwd). Cheap; covers the common
|
|
278
|
+
// single-project case without a down-scan.
|
|
279
|
+
let dir = path.resolve(cwd);
|
|
280
|
+
for (let i = 0; i < 6; i++) {
|
|
281
|
+
if (isInitialized(dir))
|
|
282
|
+
return { exploreRoot: dir, nudgeProjects: [], viaSubScan: false };
|
|
283
|
+
const parent = path.dirname(dir);
|
|
284
|
+
if (parent === dir)
|
|
285
|
+
break;
|
|
286
|
+
dir = parent;
|
|
287
|
+
}
|
|
288
|
+
// 2. down-scan — only from something that looks like a workspace root, so a
|
|
289
|
+
// non-project cwd (e.g. $HOME) is a cheap no-op, not a deep crawl.
|
|
290
|
+
const base = path.resolve(cwd);
|
|
291
|
+
if (!looksLikeProjectRoot(base))
|
|
292
|
+
return none;
|
|
293
|
+
const subs = findIndexedSubprojectRoots(base);
|
|
294
|
+
if (subs.length === 0)
|
|
295
|
+
return none;
|
|
296
|
+
if (subs.length === 1)
|
|
297
|
+
return { exploreRoot: subs[0], nudgeProjects: [], viaSubScan: true };
|
|
298
|
+
// Several indexed sub-projects — pick the one the prompt points at, if any.
|
|
299
|
+
const p = prompt.toLowerCase();
|
|
300
|
+
let best = null;
|
|
301
|
+
for (const s of subs) {
|
|
302
|
+
const rel = path.relative(base, s);
|
|
303
|
+
const relLc = rel.split(path.sep).join('/').toLowerCase();
|
|
304
|
+
const name = path.basename(s).toLowerCase();
|
|
305
|
+
let score = 0;
|
|
306
|
+
if (relLc && p.includes(relLc))
|
|
307
|
+
score = 10; // "packages/api"
|
|
308
|
+
else if (name.length >= 3 && new RegExp(`\\b${escapeRegExp(name)}\\b`).test(p))
|
|
309
|
+
score = 5; // "api"
|
|
310
|
+
if (score > 0 && (!best || score > best.score || (score === best.score && rel.length < best.relLen))) {
|
|
311
|
+
best = { root: s, score, relLen: rel.length };
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (best) {
|
|
315
|
+
return { exploreRoot: best.root, nudgeProjects: subs.filter((s) => s !== best.root), viaSubScan: true };
|
|
316
|
+
}
|
|
317
|
+
// No clear match — nudge the full list rather than front-load a guess.
|
|
318
|
+
return { exploreRoot: null, nudgeProjects: subs, viaSubScan: true };
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Contents of `.homegraph/.gitignore`. A single wildcard ignore keeps every
|
|
322
|
+
* transient file in the index dir — the database, `daemon.pid`, the socket,
|
|
323
|
+
* logs, cache, and anything future versions add — out of git, without having
|
|
324
|
+
* to enumerate each name (issues #788, #492, #484). Older versions wrote an
|
|
325
|
+
* explicit allowlist that never listed `daemon.pid` or the socket, so those
|
|
326
|
+
* runtime files were silently committed.
|
|
327
|
+
*/
|
|
328
|
+
const GITIGNORE_CONTENT = `# HomeGraph data files — local to each machine, not for committing.
|
|
329
|
+
# Ignore everything in .homegraph/ except this file itself, so transient
|
|
330
|
+
# files (the database, daemon.pid, sockets, logs) never show up in git.
|
|
331
|
+
*
|
|
332
|
+
!.gitignore
|
|
333
|
+
`;
|
|
334
|
+
/** Header line that prefixes every .gitignore HomeGraph has auto-generated. */
|
|
335
|
+
const GITIGNORE_MARKER = '# HomeGraph data files';
|
|
336
|
+
/**
|
|
337
|
+
* Is `content` a stale HomeGraph-generated `.gitignore` that should be
|
|
338
|
+
* regenerated in place? True when it carries our header but predates the
|
|
339
|
+
* wildcard ignore (it has no bare `*` line) — i.e. one of the old explicit
|
|
340
|
+
* allowlists (`*.db`, `cache/`, `.dirty`, …) that never ignored `daemon.pid`
|
|
341
|
+
* or the socket (issue #788). A file WITHOUT our header is user-authored and
|
|
342
|
+
* is left untouched; one that already has the wildcard is current. Matching
|
|
343
|
+
* on the header (not a byte-exact list of past defaults) heals every old
|
|
344
|
+
* variant — v0.7.x through 0.9.9 — and is idempotent once upgraded.
|
|
345
|
+
*/
|
|
346
|
+
function isStaleDefaultGitignore(content) {
|
|
347
|
+
if (!content.trimStart().startsWith(GITIGNORE_MARKER))
|
|
348
|
+
return false;
|
|
349
|
+
return !content.split('\n').some((line) => line.trim() === '*');
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Write `.homegraph/.gitignore` if it's absent, or upgrade a stale
|
|
353
|
+
* HomeGraph-generated default in place; a user-customized file is left alone.
|
|
354
|
+
* Best-effort — returns `false` only if a needed write failed.
|
|
355
|
+
*/
|
|
356
|
+
function ensureGitignore(gitignorePath) {
|
|
357
|
+
let existing;
|
|
358
|
+
try {
|
|
359
|
+
existing = fs.readFileSync(gitignorePath, 'utf-8');
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
existing = null; // absent (ENOENT) or unreadable — (re)create below
|
|
363
|
+
}
|
|
364
|
+
// Current default or a user-authored file: nothing to do.
|
|
365
|
+
if (existing !== null && !isStaleDefaultGitignore(existing))
|
|
366
|
+
return true;
|
|
367
|
+
try {
|
|
368
|
+
fs.writeFileSync(gitignorePath, GITIGNORE_CONTENT, 'utf-8');
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
103
375
|
/**
|
|
104
376
|
* Create the .homegraph directory structure
|
|
105
377
|
* Note: Only throws if homegraph.db already exists, not just if .homegraph/ exists.
|
|
106
378
|
*/
|
|
107
379
|
function createDirectory(projectRoot) {
|
|
108
|
-
const
|
|
109
|
-
const dbPath = path.join(
|
|
110
|
-
// Only throw if
|
|
380
|
+
const homegraphDir = getHomeGraphDir(projectRoot);
|
|
381
|
+
const dbPath = path.join(homegraphDir, 'homegraph.db');
|
|
382
|
+
// Only throw if HomeGraph is actually initialized (db exists)
|
|
111
383
|
// .homegraph/ folder alone is fine
|
|
112
384
|
if (fs.existsSync(dbPath)) {
|
|
113
|
-
throw new Error(`
|
|
385
|
+
throw new Error(`HomeGraph already initialized in ${projectRoot}`);
|
|
114
386
|
}
|
|
115
387
|
// Create main directory (if it doesn't exist)
|
|
116
|
-
fs.mkdirSync(
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const gitignoreContent = `# CodeGraph data files — local to each machine, not for committing.
|
|
121
|
-
# Ignore everything in .homegraph/ except this file itself, so transient
|
|
122
|
-
# files (the database, daemon.pid, sockets, logs) never show up in git.
|
|
123
|
-
*
|
|
124
|
-
!.gitignore
|
|
125
|
-
`;
|
|
126
|
-
fs.writeFileSync(gitignorePath, gitignoreContent, 'utf-8');
|
|
127
|
-
}
|
|
388
|
+
fs.mkdirSync(homegraphDir, { recursive: true });
|
|
389
|
+
// Write .gitignore inside .homegraph (create if absent, upgrade a stale
|
|
390
|
+
// pre-wildcard default left by an older version — issue #788).
|
|
391
|
+
ensureGitignore(path.join(homegraphDir, '.gitignore'));
|
|
128
392
|
}
|
|
129
393
|
/**
|
|
130
394
|
* Remove the .homegraph directory
|
|
131
395
|
*/
|
|
132
396
|
function removeDirectory(projectRoot) {
|
|
133
|
-
const
|
|
134
|
-
if (!fs.existsSync(
|
|
397
|
+
const homegraphDir = getHomeGraphDir(projectRoot);
|
|
398
|
+
if (!fs.existsSync(homegraphDir)) {
|
|
135
399
|
return;
|
|
136
400
|
}
|
|
137
401
|
// Verify .homegraph is a real directory, not a symlink pointing elsewhere
|
|
138
|
-
const lstat = fs.lstatSync(
|
|
402
|
+
const lstat = fs.lstatSync(homegraphDir);
|
|
139
403
|
if (lstat.isSymbolicLink()) {
|
|
140
404
|
// Only remove the symlink itself, never follow it for recursive delete
|
|
141
|
-
fs.unlinkSync(
|
|
405
|
+
fs.unlinkSync(homegraphDir);
|
|
142
406
|
return;
|
|
143
407
|
}
|
|
144
408
|
if (!lstat.isDirectory()) {
|
|
145
409
|
// Not a directory - remove the single file
|
|
146
|
-
fs.unlinkSync(
|
|
410
|
+
fs.unlinkSync(homegraphDir);
|
|
147
411
|
return;
|
|
148
412
|
}
|
|
149
413
|
// Recursively remove directory
|
|
150
|
-
fs.rmSync(
|
|
414
|
+
fs.rmSync(homegraphDir, { recursive: true, force: true });
|
|
151
415
|
}
|
|
152
416
|
/**
|
|
153
417
|
* Get all files in the .homegraph directory
|
|
154
418
|
*/
|
|
155
419
|
function listDirectoryContents(projectRoot) {
|
|
156
|
-
const
|
|
157
|
-
if (!fs.existsSync(
|
|
420
|
+
const homegraphDir = getHomeGraphDir(projectRoot);
|
|
421
|
+
if (!fs.existsSync(homegraphDir)) {
|
|
158
422
|
return [];
|
|
159
423
|
}
|
|
160
424
|
const files = [];
|
|
@@ -174,15 +438,15 @@ function listDirectoryContents(projectRoot) {
|
|
|
174
438
|
}
|
|
175
439
|
}
|
|
176
440
|
}
|
|
177
|
-
walkDir(
|
|
441
|
+
walkDir(homegraphDir);
|
|
178
442
|
return files;
|
|
179
443
|
}
|
|
180
444
|
/**
|
|
181
445
|
* Get the total size of the .homegraph directory in bytes
|
|
182
446
|
*/
|
|
183
447
|
function getDirectorySize(projectRoot) {
|
|
184
|
-
const
|
|
185
|
-
if (!fs.existsSync(
|
|
448
|
+
const homegraphDir = getHomeGraphDir(projectRoot);
|
|
449
|
+
if (!fs.existsSync(homegraphDir)) {
|
|
186
450
|
return 0;
|
|
187
451
|
}
|
|
188
452
|
let totalSize = 0;
|
|
@@ -203,7 +467,7 @@ function getDirectorySize(projectRoot) {
|
|
|
203
467
|
}
|
|
204
468
|
}
|
|
205
469
|
}
|
|
206
|
-
walkDir(
|
|
470
|
+
walkDir(homegraphDir);
|
|
207
471
|
return totalSize;
|
|
208
472
|
}
|
|
209
473
|
/**
|
|
@@ -213,7 +477,7 @@ function ensureSubdirectory(projectRoot, subdirName) {
|
|
|
213
477
|
if (subdirName.includes('..') || subdirName.includes(path.sep) || subdirName.includes('/')) {
|
|
214
478
|
throw new Error(`Invalid subdirectory name: ${subdirName}`);
|
|
215
479
|
}
|
|
216
|
-
const subdirPath = path.join(
|
|
480
|
+
const subdirPath = path.join(getHomeGraphDir(projectRoot), subdirName);
|
|
217
481
|
if (!fs.existsSync(subdirPath)) {
|
|
218
482
|
fs.mkdirSync(subdirPath, { recursive: true });
|
|
219
483
|
}
|
|
@@ -224,26 +488,24 @@ function ensureSubdirectory(projectRoot, subdirName) {
|
|
|
224
488
|
*/
|
|
225
489
|
function validateDirectory(projectRoot) {
|
|
226
490
|
const errors = [];
|
|
227
|
-
const
|
|
228
|
-
if (!fs.existsSync(
|
|
229
|
-
errors.push('
|
|
491
|
+
const homegraphDir = getHomeGraphDir(projectRoot);
|
|
492
|
+
if (!fs.existsSync(homegraphDir)) {
|
|
493
|
+
errors.push('HomeGraph directory does not exist');
|
|
230
494
|
return { valid: false, errors };
|
|
231
495
|
}
|
|
232
|
-
if (!fs.statSync(
|
|
496
|
+
if (!fs.statSync(homegraphDir).isDirectory()) {
|
|
233
497
|
errors.push('.homegraph exists but is not a directory');
|
|
234
498
|
return { valid: false, errors };
|
|
235
499
|
}
|
|
236
|
-
// Auto-repair
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
errors.push('.gitignore missing in .homegraph directory and could not be created');
|
|
246
|
-
}
|
|
500
|
+
// Auto-repair / upgrade .gitignore (non-critical file). A missing one is
|
|
501
|
+
// recreated; a stale pre-wildcard default that never ignored daemon.pid is
|
|
502
|
+
// regenerated in place (issue #788); a user-authored file is left alone.
|
|
503
|
+
const gitignorePath = path.join(homegraphDir, '.gitignore');
|
|
504
|
+
const existedBefore = fs.existsSync(gitignorePath);
|
|
505
|
+
if (!ensureGitignore(gitignorePath) && !existedBefore) {
|
|
506
|
+
// Only a missing-and-uncreatable file is surfaced; a failed in-place
|
|
507
|
+
// upgrade of an existing file is non-fatal — the index still works.
|
|
508
|
+
errors.push('.gitignore missing in .homegraph directory and could not be created');
|
|
247
509
|
}
|
|
248
510
|
return {
|
|
249
511
|
valid: errors.length === 0,
|