homegraph 1.5.0 → 1.5.2
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/dist/bin/command-supervision.d.ts.map +1 -1
- package/dist/bin/command-supervision.js +7 -4
- package/dist/bin/command-supervision.js.map +1 -1
- package/dist/extraction/index.d.ts +1 -1
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +54 -43
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts.d.ts +69 -12
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +739 -86
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/diff-impact.d.ts +131 -0
- package/dist/mcp/diff-impact.d.ts.map +1 -0
- package/dist/mcp/diff-impact.js +385 -0
- package/dist/mcp/diff-impact.js.map +1 -0
- package/dist/mcp/liveness-watchdog.d.ts +18 -0
- package/dist/mcp/liveness-watchdog.d.ts.map +1 -1
- package/dist/mcp/liveness-watchdog.js +134 -22
- package/dist/mcp/liveness-watchdog.js.map +1 -1
- package/dist/mcp/server-instructions.d.ts +1 -1
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +2 -0
- package/dist/mcp/server-instructions.js.map +1 -1
- package/dist/mcp/tools.d.ts +21 -5
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +305 -55
- package/dist/mcp/tools.js.map +1 -1
- package/dist/resolution/callback-synthesizer.d.ts +2 -1
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/dist/resolution/callback-synthesizer.js +153 -53
- package/dist/resolution/callback-synthesizer.js.map +1 -1
- package/dist/resolution/frameworks/arkts-entry.d.ts.map +1 -1
- package/dist/resolution/frameworks/arkts-entry.js +20 -9
- package/dist/resolution/frameworks/arkts-entry.js.map +1 -1
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +1 -1
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/memory-budget.d.ts +33 -0
- package/dist/resolution/memory-budget.d.ts.map +1 -1
- package/dist/resolution/memory-budget.js +58 -0
- package/dist/resolution/memory-budget.js.map +1 -1
- package/dist/resolution/resolver-pool.d.ts +2 -0
- package/dist/resolution/resolver-pool.d.ts.map +1 -1
- package/dist/resolution/resolver-pool.js +4 -0
- package/dist/resolution/resolver-pool.js.map +1 -1
- package/dist/ui/shimmer-progress.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.js +4 -1
- package/dist/ui/shimmer-progress.js.map +1 -1
- package/package.json +4 -5
- package/dist/arkts/ohos-api-index.d.ts +0 -15
- package/dist/arkts/ohos-api-index.d.ts.map +0 -1
- package/dist/arkts/ohos-api-index.js +0 -190
- package/dist/arkts/ohos-api-index.js.map +0 -1
- package/dist/arkts/ohos-sdk-input.d.ts +0 -36
- package/dist/arkts/ohos-sdk-input.d.ts.map +0 -1
- package/dist/arkts/ohos-sdk-input.js +0 -214
- package/dist/arkts/ohos-sdk-input.js.map +0 -1
- package/dist/extraction/languages/arkts-state-decorators.d.ts +0 -13
- package/dist/extraction/languages/arkts-state-decorators.d.ts.map +0 -1
- package/dist/extraction/languages/arkts-state-decorators.js +0 -26
- package/dist/extraction/languages/arkts-state-decorators.js.map +0 -1
- package/dist/extraction/languages/arkts-viewtree.d.ts +0 -24
- package/dist/extraction/languages/arkts-viewtree.d.ts.map +0 -1
- package/dist/extraction/languages/arkts-viewtree.js +0 -148
- package/dist/extraction/languages/arkts-viewtree.js.map +0 -1
- package/dist/extraction/languages/ohos-api-consumer.d.ts +0 -34
- package/dist/extraction/languages/ohos-api-consumer.d.ts.map +0 -1
- package/dist/extraction/languages/ohos-api-consumer.js +0 -283
- package/dist/extraction/languages/ohos-api-consumer.js.map +0 -1
- package/dist/reasoning/config.d.ts +0 -45
- package/dist/reasoning/config.d.ts.map +0 -1
- package/dist/reasoning/config.js +0 -171
- package/dist/reasoning/config.js.map +0 -1
- package/dist/reasoning/credentials.d.ts +0 -5
- package/dist/reasoning/credentials.d.ts.map +0 -1
- package/dist/reasoning/credentials.js +0 -83
- package/dist/reasoning/credentials.js.map +0 -1
- package/dist/reasoning/login.d.ts +0 -21
- package/dist/reasoning/login.d.ts.map +0 -1
- package/dist/reasoning/login.js +0 -85
- package/dist/reasoning/login.js.map +0 -1
- package/dist/reasoning/reasoner.d.ts +0 -43
- package/dist/reasoning/reasoner.d.ts.map +0 -1
- package/dist/reasoning/reasoner.js +0 -308
- package/dist/reasoning/reasoner.js.map +0 -1
- package/dist/spec/build/git-scanner.d.ts +0 -93
- package/dist/spec/build/git-scanner.d.ts.map +0 -1
- package/dist/spec/build/git-scanner.js +0 -254
- package/dist/spec/build/git-scanner.js.map +0 -1
- package/dist/spec/evolve/llm-client.d.ts +0 -50
- package/dist/spec/evolve/llm-client.d.ts.map +0 -1
- package/dist/spec/evolve/llm-client.js +0 -176
- package/dist/spec/evolve/llm-client.js.map +0 -1
- package/dist/spec/evolve/logic-checker.d.ts +0 -12
- package/dist/spec/evolve/logic-checker.d.ts.map +0 -1
- package/dist/spec/evolve/logic-checker.js +0 -24
- package/dist/spec/evolve/logic-checker.js.map +0 -1
- package/dist/spec/git-utils.d.ts +0 -8
- package/dist/spec/git-utils.d.ts.map +0 -1
- package/dist/spec/git-utils.js +0 -14
- package/dist/spec/git-utils.js.map +0 -1
- package/dist/spec/llm/index.d.ts +0 -3
- package/dist/spec/llm/index.d.ts.map +0 -1
- package/dist/spec/llm/index.js +0 -11
- package/dist/spec/llm/index.js.map +0 -1
- package/dist/spec/mine/clusterer.d.ts +0 -63
- package/dist/spec/mine/clusterer.d.ts.map +0 -1
- package/dist/spec/mine/clusterer.js +0 -904
- package/dist/spec/mine/clusterer.js.map +0 -1
- package/dist/spec/mine/progress-handler.d.ts +0 -22
- package/dist/spec/mine/progress-handler.d.ts.map +0 -1
- package/dist/spec/mine/progress-handler.js +0 -108
- package/dist/spec/mine/progress-handler.js.map +0 -1
- package/dist/spec/mine/progress.d.ts +0 -23
- package/dist/spec/mine/progress.d.ts.map +0 -1
- package/dist/spec/mine/progress.js +0 -12
- package/dist/spec/mine/progress.js.map +0 -1
- package/dist/spec/mining/diff-parser.d.ts +0 -33
- package/dist/spec/mining/diff-parser.d.ts.map +0 -1
- package/dist/spec/mining/diff-parser.js +0 -166
- package/dist/spec/mining/diff-parser.js.map +0 -1
- package/dist/spec/mining/git-scanner.d.ts +0 -103
- package/dist/spec/mining/git-scanner.d.ts.map +0 -1
- package/dist/spec/mining/git-scanner.js +0 -307
- package/dist/spec/mining/git-scanner.js.map +0 -1
- package/dist/spec/mining/pipeline.d.ts +0 -53
- package/dist/spec/mining/pipeline.d.ts.map +0 -1
- package/dist/spec/mining/pipeline.js +0 -178
- package/dist/spec/mining/pipeline.js.map +0 -1
- package/dist/spec/mining/scope-resolver.d.ts +0 -45
- package/dist/spec/mining/scope-resolver.d.ts.map +0 -1
- package/dist/spec/mining/scope-resolver.js +0 -103
- package/dist/spec/mining/scope-resolver.js.map +0 -1
- package/dist/spec/mining/spec-extractor.d.ts +0 -69
- package/dist/spec/mining/spec-extractor.d.ts.map +0 -1
- package/dist/spec/mining/spec-extractor.js +0 -369
- package/dist/spec/mining/spec-extractor.js.map +0 -1
- package/dist/spec/utils.d.ts +0 -155
- package/dist/spec/utils.d.ts.map +0 -1
- package/dist/spec/utils.js +0 -411
- package/dist/spec/utils.js.map +0 -1
- package/scripts/add-lang/bench.sh +0 -60
- package/scripts/add-lang/check-grammar.mjs +0 -75
- package/scripts/add-lang/dump-ast.mjs +0 -103
- package/scripts/add-lang/verify-extraction.mjs +0 -70
- package/scripts/agent-eval/ab-adoption.sh +0 -91
- package/scripts/agent-eval/ab-hook.sh +0 -86
- package/scripts/agent-eval/ab-impl.sh +0 -78
- package/scripts/agent-eval/ab-new-vs-baseline.sh +0 -102
- package/scripts/agent-eval/ab-sufficiency.sh +0 -78
- package/scripts/agent-eval/arms-F.sh +0 -21
- package/scripts/agent-eval/arms-matrix.sh +0 -37
- package/scripts/agent-eval/audit.sh +0 -68
- package/scripts/agent-eval/bench-readme.sh +0 -28
- package/scripts/agent-eval/bench-why-repo.sh +0 -22
- package/scripts/agent-eval/block-read-hook.sh +0 -19
- package/scripts/agent-eval/hook-settings.json +0 -15
- package/scripts/agent-eval/itrun.sh +0 -120
- package/scripts/agent-eval/offload-eval-3arm.sh +0 -72
- package/scripts/agent-eval/offload-eval-cost.mjs +0 -133
- package/scripts/agent-eval/offload-eval-effort.mjs +0 -108
- package/scripts/agent-eval/offload-eval-frontload-matrix.sh +0 -25
- package/scripts/agent-eval/offload-eval-frontload.sh +0 -47
- package/scripts/agent-eval/offload-eval-ground-truth.json +0 -18
- package/scripts/agent-eval/offload-eval-hook.mjs +0 -84
- package/scripts/agent-eval/offload-eval-judge.mjs +0 -103
- package/scripts/agent-eval/offload-eval-matrix.sh +0 -20
- package/scripts/agent-eval/offload-eval-metrics.mjs +0 -94
- package/scripts/agent-eval/offload-eval-refs1.sh +0 -50
- package/scripts/agent-eval/offload-eval-setup.sh +0 -24
- package/scripts/agent-eval/offload-eval-styles.sh +0 -72
- package/scripts/agent-eval/offload-eval-summarize.mjs +0 -68
- package/scripts/agent-eval/offload-eval.md +0 -76
- package/scripts/agent-eval/parse-arms.mjs +0 -116
- package/scripts/agent-eval/parse-bench-readme.mjs +0 -84
- package/scripts/agent-eval/parse-run.mjs +0 -45
- package/scripts/agent-eval/parse-session.mjs +0 -93
- package/scripts/agent-eval/probe-context.mjs +0 -21
- package/scripts/agent-eval/probe-explore.mjs +0 -40
- package/scripts/agent-eval/probe-node.mjs +0 -20
- package/scripts/agent-eval/probe-sweep.mjs +0 -119
- package/scripts/agent-eval/probe-trace.mjs +0 -20
- package/scripts/agent-eval/redirect-read-hook.sh +0 -38
- package/scripts/agent-eval/repro-concurrent-explore.mjs +0 -119
- package/scripts/agent-eval/repro-daemon-clients.mjs +0 -125
- package/scripts/agent-eval/run-agent.sh +0 -34
- package/scripts/agent-eval/run-all.sh +0 -75
- package/scripts/agent-eval/run-arms.sh +0 -56
- package/scripts/agent-eval/seq-matrix.mjs +0 -137
- package/scripts/build-bundle.sh +0 -123
- package/scripts/exp_boundary_eval/README.md +0 -247
- package/scripts/exp_boundary_eval/_test_mcp_chain.py +0 -78
- package/scripts/exp_boundary_eval/_test_stdin.py +0 -8
- package/scripts/exp_boundary_eval/_utils.py +0 -1116
- package/scripts/exp_boundary_eval/analyze.py +0 -1313
- package/scripts/exp_boundary_eval/deveco_arm.py +0 -519
- package/scripts/exp_boundary_eval/run_all.py +0 -378
- package/scripts/exp_boundary_eval/run_one.py +0 -165
- package/scripts/exp_boundary_eval/run_session.py +0 -158
- package/scripts/exp_boundary_eval/setup.py +0 -120
- package/scripts/exp_boundary_eval/win_mcp_launcher.py +0 -73
- package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +0 -36
- package/scripts/exp_boundary_eval/win_node_launcher.py +0 -24
- package/scripts/extract-release-notes.mjs +0 -130
- package/scripts/local-install.sh +0 -41
- package/scripts/npm-sdk.js +0 -75
- package/scripts/npm-shim.js +0 -275
- package/scripts/ohos-sdk-publish.mjs +0 -133
- package/scripts/pack-npm.sh +0 -119
- package/scripts/prepare-release.mjs +0 -270
package/dist/mcp/tools.js
CHANGED
|
@@ -31,6 +31,7 @@ const generated_detection_1 = require("../extraction/generated-detection");
|
|
|
31
31
|
const arkts_1 = require("../extraction/languages/arkts");
|
|
32
32
|
const dynamic_boundaries_1 = require("./dynamic-boundaries");
|
|
33
33
|
const query_cache_1 = require("./query-cache");
|
|
34
|
+
const diff_impact_1 = require("./diff-impact");
|
|
34
35
|
/** ViewTree structural `references` vias — not UI event bindings. */
|
|
35
36
|
const VIEWTREE_STRUCTURE_VIAS = new Set([
|
|
36
37
|
'child-component',
|
|
@@ -73,6 +74,18 @@ const MAX_OUTPUT_LENGTH = 15000;
|
|
|
73
74
|
* far beyond any realistic legitimate query.
|
|
74
75
|
*/
|
|
75
76
|
const MAX_INPUT_LENGTH = 10_000;
|
|
77
|
+
/** Example values for success-shaped bad-arg guidance (keyed by arg name). */
|
|
78
|
+
const BAD_ARG_EXAMPLES = {
|
|
79
|
+
query: 'authenticate login',
|
|
80
|
+
symbol: 'authenticate',
|
|
81
|
+
filePath: 'src/auth.ts',
|
|
82
|
+
file: 'src/auth.ts',
|
|
83
|
+
path: 'src/components',
|
|
84
|
+
pattern: '*.ets',
|
|
85
|
+
projectPath: '/absolute/path/to/your/project',
|
|
86
|
+
repoPath: '/absolute/path/to/your/project',
|
|
87
|
+
diff: 'diff --git a/src/auth.ts b/src/auth.ts\n--- a/src/auth.ts\n+++ b/src/auth.ts\n@@ -10,3 +10,4 @@\n+export function authenticate() {}\n',
|
|
88
|
+
};
|
|
76
89
|
/**
|
|
77
90
|
* Maximum length for path-like string inputs (projectPath, path
|
|
78
91
|
* filter, glob pattern). Paths beyond a few thousand chars are
|
|
@@ -481,17 +494,19 @@ const READ_ONLY_ANNOTATIONS = {
|
|
|
481
494
|
exports.tools = [
|
|
482
495
|
{
|
|
483
496
|
name: 'homegraph_search',
|
|
484
|
-
description: 'LAST RESORT spelling lookup — locations only, no source.
|
|
497
|
+
description: 'LAST RESORT spelling lookup — locations only, no source. Required: `query` (e.g. "signIn"). ' +
|
|
498
|
+
'Prefer homegraph_explore when the question already names a symbol/file/@kit. ' +
|
|
499
|
+
'Bare-name search may return a compact explore result instead of locations.',
|
|
485
500
|
inputSchema: {
|
|
486
501
|
type: 'object',
|
|
487
502
|
properties: {
|
|
488
503
|
query: {
|
|
489
504
|
type: 'string',
|
|
490
|
-
description: 'Symbol name or partial name (e.g
|
|
505
|
+
description: 'Required. Symbol name or partial name (e.g. "auth", "signIn", "UserService").',
|
|
491
506
|
},
|
|
492
507
|
kind: {
|
|
493
508
|
type: 'string',
|
|
494
|
-
description: '
|
|
509
|
+
description: 'Optional filter by node kind',
|
|
495
510
|
enum: ['function', 'method', 'class', 'interface', 'type', 'variable', 'route', 'component'],
|
|
496
511
|
},
|
|
497
512
|
limit: {
|
|
@@ -507,17 +522,20 @@ exports.tools = [
|
|
|
507
522
|
},
|
|
508
523
|
{
|
|
509
524
|
name: 'homegraph_callers',
|
|
510
|
-
description: 'Compact caller list for
|
|
525
|
+
description: 'Compact caller list for one NAMED in-repo symbol (no bodies). Required: `symbol` (e.g. "authenticate"). ' +
|
|
526
|
+
'Use after you know the exact name. For full flows use homegraph_explore. ' +
|
|
527
|
+
'DO NOT call for SDK catalogs, one-function semantics, or "what if X fails" hypothetics. ' +
|
|
528
|
+
'Prefer one explore over parallel callers+callees+node.',
|
|
511
529
|
inputSchema: {
|
|
512
530
|
type: 'object',
|
|
513
531
|
properties: {
|
|
514
532
|
symbol: {
|
|
515
533
|
type: 'string',
|
|
516
|
-
description: '
|
|
534
|
+
description: 'Required. Exact function/method/class name (e.g. "authenticate", "AuthService.login").',
|
|
517
535
|
},
|
|
518
536
|
file: {
|
|
519
537
|
type: 'string',
|
|
520
|
-
description: 'Narrow to the definition in this file (path or suffix) when
|
|
538
|
+
description: 'Optional. Narrow to the definition in this file (path or suffix) when same-named symbols collide.',
|
|
521
539
|
},
|
|
522
540
|
limit: {
|
|
523
541
|
type: 'number',
|
|
@@ -532,17 +550,19 @@ exports.tools = [
|
|
|
532
550
|
},
|
|
533
551
|
{
|
|
534
552
|
name: 'homegraph_callees',
|
|
535
|
-
description: 'Compact callee list for
|
|
553
|
+
description: 'Compact callee list for one NAMED in-repo symbol (no bodies). Required: `symbol` (e.g. "authenticate"). ' +
|
|
554
|
+
'For full flows use homegraph_explore. DO NOT use for out-of-repo SDK internals or counterfactual analysis. ' +
|
|
555
|
+
'Prefer one explore over parallel node+callers+callees.',
|
|
536
556
|
inputSchema: {
|
|
537
557
|
type: 'object',
|
|
538
558
|
properties: {
|
|
539
559
|
symbol: {
|
|
540
560
|
type: 'string',
|
|
541
|
-
description: '
|
|
561
|
+
description: 'Required. Exact function/method/class name (e.g. "authenticate", "AuthService.login").',
|
|
542
562
|
},
|
|
543
563
|
file: {
|
|
544
564
|
type: 'string',
|
|
545
|
-
description: 'Narrow to the definition in this file (path or suffix) when
|
|
565
|
+
description: 'Optional. Narrow to the definition in this file (path or suffix) when same-named symbols collide.',
|
|
546
566
|
},
|
|
547
567
|
limit: {
|
|
548
568
|
type: 'number',
|
|
@@ -557,17 +577,19 @@ exports.tools = [
|
|
|
557
577
|
},
|
|
558
578
|
{
|
|
559
579
|
name: 'homegraph_impact',
|
|
560
|
-
description: 'Blast radius for
|
|
580
|
+
description: 'Blast radius for one NAMED in-repo symbol before a refactor. Required: `symbol` (e.g. "authenticate"). ' +
|
|
581
|
+
'Not for SDK docs, permission judgments, or hypothetical failure effects — those need Read/Grep. ' +
|
|
582
|
+
'For PR/diff review use homegraph_diff_impact instead.',
|
|
561
583
|
inputSchema: {
|
|
562
584
|
type: 'object',
|
|
563
585
|
properties: {
|
|
564
586
|
symbol: {
|
|
565
587
|
type: 'string',
|
|
566
|
-
description: '
|
|
588
|
+
description: 'Required. Exact symbol name to analyze (e.g. "authenticate", "CartRepository").',
|
|
567
589
|
},
|
|
568
590
|
file: {
|
|
569
591
|
type: 'string',
|
|
570
|
-
description: 'Narrow to the definition in this file (path or suffix) when
|
|
592
|
+
description: 'Optional. Narrow to the definition in this file (path or suffix) when same-named symbols collide.',
|
|
571
593
|
},
|
|
572
594
|
depth: {
|
|
573
595
|
type: 'number',
|
|
@@ -580,15 +602,64 @@ exports.tools = [
|
|
|
580
602
|
},
|
|
581
603
|
annotations: READ_ONLY_ANNOTATIONS,
|
|
582
604
|
},
|
|
605
|
+
{
|
|
606
|
+
name: 'homegraph_diff_impact',
|
|
607
|
+
description: 'PR / code-review evidence pack from a unified diff (or explicit hunks). ' +
|
|
608
|
+
'Required: `diff` (unified diff text) OR `hunks` [{ path, startLine, endLine }]. ' +
|
|
609
|
+
'Intersects NEW-side changed lines with indexed symbol spans — does NOT dump every symbol in touched files. ' +
|
|
610
|
+
'Returns changedSymbols + capped callers + impactSummary + UI edges (viewtree/arkui-*); optional relatedSpecs. ' +
|
|
611
|
+
'Index should match the post-change tree. Does not write review text or judge Specs.',
|
|
612
|
+
inputSchema: {
|
|
613
|
+
type: 'object',
|
|
614
|
+
properties: {
|
|
615
|
+
diff: {
|
|
616
|
+
type: 'string',
|
|
617
|
+
description: 'Unified diff text (preferred). New-side @@ +line ranges are used to find changed symbols. ' +
|
|
618
|
+
'Example: output of `git diff` / PR patch for the files under review.',
|
|
619
|
+
},
|
|
620
|
+
hunks: {
|
|
621
|
+
type: 'array',
|
|
622
|
+
description: 'Alternative to `diff`: explicit changed ranges. Each item: { path, startLine, endLine } (1-based, inclusive, new-file lines).',
|
|
623
|
+
items: {
|
|
624
|
+
type: 'object',
|
|
625
|
+
properties: {
|
|
626
|
+
path: { type: 'string', description: 'Project-relative file path' },
|
|
627
|
+
startLine: { type: 'number', description: '1-based start line (new file)' },
|
|
628
|
+
endLine: { type: 'number', description: '1-based end line (new file)' },
|
|
629
|
+
},
|
|
630
|
+
},
|
|
631
|
+
},
|
|
632
|
+
depth: {
|
|
633
|
+
type: 'number',
|
|
634
|
+
description: 'Impact / caller traversal depth (default: 2, max: 5)',
|
|
635
|
+
default: 2,
|
|
636
|
+
},
|
|
637
|
+
includeSpecs: {
|
|
638
|
+
type: 'boolean',
|
|
639
|
+
description: 'If true, attach related Commit4Spec hits for changed files/symbols (needs commit4spec.db). Default: false.',
|
|
640
|
+
default: false,
|
|
641
|
+
},
|
|
642
|
+
projectPath: projectPathProperty,
|
|
643
|
+
},
|
|
644
|
+
required: [],
|
|
645
|
+
},
|
|
646
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
647
|
+
},
|
|
583
648
|
{
|
|
584
649
|
name: 'homegraph_node',
|
|
585
|
-
description: 'Depth on ONE known in-repo symbol or indexed file — not a survey tool.
|
|
650
|
+
description: 'Depth on ONE known in-repo symbol or indexed file — not a survey tool. ' +
|
|
651
|
+
'Required: pass `symbol` (symbol mode) OR `file` alone (file mode). ' +
|
|
652
|
+
'FILE: `file` only → line-numbered source + dependents. ' +
|
|
653
|
+
'SYMBOL: body via includeCode + short trail; overloads return every body. ' +
|
|
654
|
+
'USE after explore named the symbol and you still need one body. ' +
|
|
655
|
+
'DO NOT crawl a feature with repeated node calls (prefer one explore). ' +
|
|
656
|
+
'Treat returned source as already Read.',
|
|
586
657
|
inputSchema: {
|
|
587
658
|
type: 'object',
|
|
588
659
|
properties: {
|
|
589
660
|
symbol: {
|
|
590
661
|
type: 'string',
|
|
591
|
-
description: '
|
|
662
|
+
description: 'Symbol mode (required unless `file` alone). Exact name (e.g. "authenticate").',
|
|
592
663
|
},
|
|
593
664
|
includeCode: {
|
|
594
665
|
type: 'boolean',
|
|
@@ -597,7 +668,8 @@ exports.tools = [
|
|
|
597
668
|
},
|
|
598
669
|
file: {
|
|
599
670
|
type: 'string',
|
|
600
|
-
description: '
|
|
671
|
+
description: 'File mode: pass ALONE (no symbol) to read like Read — e.g. "src/auth/session.ts". ' +
|
|
672
|
+
'Or with `symbol` to disambiguate an overloaded name to that file.',
|
|
601
673
|
},
|
|
602
674
|
offset: {
|
|
603
675
|
type: 'number',
|
|
@@ -624,13 +696,16 @@ exports.tools = [
|
|
|
624
696
|
},
|
|
625
697
|
{
|
|
626
698
|
name: 'homegraph_explore',
|
|
627
|
-
description: 'PRIMARY tool for THIS REPO\'s symbol graph (call paths + often line-numbered source).
|
|
699
|
+
description: 'PRIMARY tool for THIS REPO\'s symbol graph (call paths + often line-numbered source). Required: `query` with concrete symbol/file/@kit names. ' +
|
|
700
|
+
'CALL for in-repo structure: feature wiring, A→B path, callers/callees, Type.member usage, click→handler, in-repo @kit usages. ' +
|
|
701
|
+
'Skip search when names are already known. One explore; answer from Source + trail; treat as already Read. Busy/partial → retry same explore once.',
|
|
628
702
|
inputSchema: {
|
|
629
703
|
type: 'object',
|
|
630
704
|
properties: {
|
|
631
705
|
query: {
|
|
632
706
|
type: 'string',
|
|
633
|
-
description: 'In-repo symbols, file basenames, or @kit names
|
|
707
|
+
description: 'Required. In-repo symbols, file basenames, or @kit names (e.g. "ParentPage onClick build", "CartRepository.addItem"). ' +
|
|
708
|
+
'For flows, name both endpoints. Not for official SDK API catalogs.',
|
|
634
709
|
},
|
|
635
710
|
maxFiles: {
|
|
636
711
|
type: 'number',
|
|
@@ -645,7 +720,7 @@ exports.tools = [
|
|
|
645
720
|
},
|
|
646
721
|
{
|
|
647
722
|
name: 'homegraph_status',
|
|
648
|
-
description: 'Index health check (files / nodes / edges). Skip unless debugging.',
|
|
723
|
+
description: 'Index health check (files / nodes / edges). No required args when a default project is loaded. Skip unless debugging.',
|
|
649
724
|
inputSchema: {
|
|
650
725
|
type: 'object',
|
|
651
726
|
properties: {
|
|
@@ -656,17 +731,18 @@ exports.tools = [
|
|
|
656
731
|
},
|
|
657
732
|
{
|
|
658
733
|
name: 'homegraph_files',
|
|
659
|
-
description: 'Indexed directory tree (paths and symbol counts only — NO source
|
|
734
|
+
description: 'Indexed directory tree (paths and symbol counts only — NO source). ' +
|
|
735
|
+
'Only for coarse folder layout when explore cannot help. For where/what/how code questions use homegraph_explore.',
|
|
660
736
|
inputSchema: {
|
|
661
737
|
type: 'object',
|
|
662
738
|
properties: {
|
|
663
739
|
path: {
|
|
664
740
|
type: 'string',
|
|
665
|
-
description: '
|
|
741
|
+
description: 'Optional directory prefix filter (e.g. "src/components"). Omit to list all indexed files.',
|
|
666
742
|
},
|
|
667
743
|
pattern: {
|
|
668
744
|
type: 'string',
|
|
669
|
-
description: '
|
|
745
|
+
description: 'Optional glob filter (e.g. "*.tsx", "**/*.ets").',
|
|
670
746
|
},
|
|
671
747
|
format: {
|
|
672
748
|
type: 'string',
|
|
@@ -690,19 +766,19 @@ exports.tools = [
|
|
|
690
766
|
},
|
|
691
767
|
{
|
|
692
768
|
name: 'homegraph_spec_match',
|
|
693
|
-
description: 'Match a new spec
|
|
694
|
-
'
|
|
695
|
-
'
|
|
769
|
+
description: 'Match a new feature/spec description against the Commit4Spec knowledge graph (FTS5). ' +
|
|
770
|
+
'Required: `query` (title + description text). Returns similar historical specs with commits/fragments. ' +
|
|
771
|
+
'Needs `.homegraph/commit4spec/commit4spec.db` (from `homegraph spec build` / `mine`).',
|
|
696
772
|
inputSchema: {
|
|
697
773
|
type: 'object',
|
|
698
774
|
properties: {
|
|
699
775
|
query: {
|
|
700
776
|
type: 'string',
|
|
701
|
-
description: 'Spec text (title + description) to match against historical specs.',
|
|
777
|
+
description: 'Required. Spec text (title + description) to match against historical specs.',
|
|
702
778
|
},
|
|
703
779
|
repoPath: {
|
|
704
780
|
type: 'string',
|
|
705
|
-
description: '
|
|
781
|
+
description: 'Optional repository root (default: cwd). Spec DB lives under `.homegraph/commit4spec/`.',
|
|
706
782
|
},
|
|
707
783
|
topK: {
|
|
708
784
|
type: 'number',
|
|
@@ -721,20 +797,18 @@ exports.tools = [
|
|
|
721
797
|
},
|
|
722
798
|
{
|
|
723
799
|
name: 'homegraph_spec_find',
|
|
724
|
-
description: 'Find which specs
|
|
725
|
-
'
|
|
726
|
-
'→ spec_commit_relations → spec_nodes. Useful for answering "which specs does this file affect?" ' +
|
|
727
|
-
'The database defaults to .homegraph/commit4spec/commit4spec.db under the repo path.',
|
|
800
|
+
description: 'Find which Commit4Spec specs touch a file path. Required: `filePath` (e.g. "src/auth.ts"). ' +
|
|
801
|
+
'Needs `.homegraph/commit4spec/commit4spec.db`.',
|
|
728
802
|
inputSchema: {
|
|
729
803
|
type: 'object',
|
|
730
804
|
properties: {
|
|
731
805
|
filePath: {
|
|
732
806
|
type: 'string',
|
|
733
|
-
description: 'File path
|
|
807
|
+
description: 'Required. File path substring to match (e.g. "src/auth.ts" or "src/auth").',
|
|
734
808
|
},
|
|
735
809
|
repoPath: {
|
|
736
810
|
type: 'string',
|
|
737
|
-
description: '
|
|
811
|
+
description: 'Optional repository root (default: cwd). Spec DB lives under `.homegraph/commit4spec/`.',
|
|
738
812
|
},
|
|
739
813
|
},
|
|
740
814
|
required: ['filePath'],
|
|
@@ -743,31 +817,26 @@ exports.tools = [
|
|
|
743
817
|
},
|
|
744
818
|
{
|
|
745
819
|
name: 'homegraph_spec_trace',
|
|
746
|
-
description: 'Trace
|
|
747
|
-
'
|
|
748
|
-
'records in the Spec database using five-dimensional scoring: file-path match, code-diff content search ' +
|
|
749
|
-
'(FTS5), Spec title/subtitle name match, Spec recency, and line-range overlap. ' +
|
|
750
|
-
'Returns ranked Specs with score breakdowns even when exact line overlap is absent — code drifts over ' +
|
|
751
|
-
'time, so recency and content matching compensate. ' +
|
|
752
|
-
'The Spec DB defaults to .homegraph/commit4spec/commit4spec.db under the repo path.',
|
|
820
|
+
description: 'Trace one code symbol back to related design Specs (Commit4Spec). Required: `symbol` (e.g. "authenticate"). ' +
|
|
821
|
+
'Optional `file`/`line` to disambiguate. Needs code index + `.homegraph/commit4spec/commit4spec.db`.',
|
|
753
822
|
inputSchema: {
|
|
754
823
|
type: 'object',
|
|
755
824
|
properties: {
|
|
756
825
|
symbol: {
|
|
757
826
|
type: 'string',
|
|
758
|
-
description: 'Symbol name (bare or qualified). E.g. "authenticate", "AuthService.login"
|
|
827
|
+
description: 'Required. Symbol name (bare or qualified). E.g. "authenticate", "AuthService.login".',
|
|
759
828
|
},
|
|
760
829
|
file: {
|
|
761
830
|
type: 'string',
|
|
762
|
-
description: '
|
|
831
|
+
description: 'Optional file path for disambiguation when multiple symbols share the same name.',
|
|
763
832
|
},
|
|
764
833
|
line: {
|
|
765
834
|
type: 'number',
|
|
766
|
-
description: '
|
|
835
|
+
description: 'Optional line number for disambiguation.',
|
|
767
836
|
},
|
|
768
837
|
repoPath: {
|
|
769
838
|
type: 'string',
|
|
770
|
-
description: '
|
|
839
|
+
description: 'Optional repository root (default: cwd).',
|
|
771
840
|
},
|
|
772
841
|
topK: {
|
|
773
842
|
type: 'number',
|
|
@@ -1017,6 +1086,7 @@ class ToolHandler {
|
|
|
1017
1086
|
'homegraph_explore',
|
|
1018
1087
|
'homegraph_search',
|
|
1019
1088
|
'homegraph_node',
|
|
1089
|
+
'homegraph_diff_impact',
|
|
1020
1090
|
]);
|
|
1021
1091
|
if (stats.fileCount < TINY_REPO_FILE_THRESHOLD) {
|
|
1022
1092
|
visible = visible.filter(t => TINY_REPO_CORE_TOOLS.has(t.name));
|
|
@@ -1148,32 +1218,40 @@ class ToolHandler {
|
|
|
1148
1218
|
/**
|
|
1149
1219
|
* Validate that a value is a non-empty string within length bounds.
|
|
1150
1220
|
*
|
|
1151
|
-
*
|
|
1152
|
-
*
|
|
1153
|
-
*
|
|
1154
|
-
*
|
|
1221
|
+
* Bad / oversize args return SUCCESS-shaped guidance (no `isError`) with a
|
|
1222
|
+
* retry example — same policy as {@link NotIndexedError}: early `isError`
|
|
1223
|
+
* teaches agents to abandon the whole toolset. The length cap still blocks
|
|
1224
|
+
* DoS before FTS/work runs.
|
|
1155
1225
|
*/
|
|
1156
1226
|
validateString(value, name, maxLength = MAX_INPUT_LENGTH) {
|
|
1157
1227
|
if (typeof value !== 'string' || value.length === 0) {
|
|
1158
|
-
|
|
1228
|
+
const got = value === undefined || value === null
|
|
1229
|
+
? 'it was missing'
|
|
1230
|
+
: typeof value !== 'string'
|
|
1231
|
+
? `got ${typeof value}`
|
|
1232
|
+
: 'got an empty string';
|
|
1233
|
+
return this.badArgResult(`\`${name}\` must be a non-empty string (${got}).`, name);
|
|
1159
1234
|
}
|
|
1160
1235
|
if (value.length > maxLength) {
|
|
1161
|
-
return this.
|
|
1236
|
+
return this.badArgResult(`\`${name}\` exceeds maximum length of ${maxLength} characters (got ${value.length}). ` +
|
|
1237
|
+
'Shorten it — pass a concrete symbol/file name, not a pasted dump.', name);
|
|
1162
1238
|
}
|
|
1163
1239
|
return value;
|
|
1164
1240
|
}
|
|
1165
1241
|
/**
|
|
1166
1242
|
* Validate an optional path-like string input. Returns the value if
|
|
1167
|
-
* valid (or undefined), or
|
|
1243
|
+
* valid (or undefined), or SUCCESS-shaped guidance when the value is present
|
|
1244
|
+
* but invalid (wrong type / oversize).
|
|
1168
1245
|
*/
|
|
1169
1246
|
validateOptionalPath(value, name) {
|
|
1170
1247
|
if (value === undefined || value === null)
|
|
1171
1248
|
return undefined;
|
|
1172
1249
|
if (typeof value !== 'string') {
|
|
1173
|
-
return this.
|
|
1250
|
+
return this.badArgResult(`\`${name}\` must be a string when provided (got ${typeof value}).`, name);
|
|
1174
1251
|
}
|
|
1175
1252
|
if (value.length > MAX_PATH_LENGTH) {
|
|
1176
|
-
return this.
|
|
1253
|
+
return this.badArgResult(`\`${name}\` exceeds maximum length of ${MAX_PATH_LENGTH} characters (got ${value.length}). ` +
|
|
1254
|
+
'Pass a normal project-relative or absolute path.', name);
|
|
1177
1255
|
}
|
|
1178
1256
|
return value;
|
|
1179
1257
|
}
|
|
@@ -1600,6 +1678,7 @@ class ToolHandler {
|
|
|
1600
1678
|
case 'homegraph_callers': return await this.handleCallers(args);
|
|
1601
1679
|
case 'homegraph_callees': return await this.handleCallees(args);
|
|
1602
1680
|
case 'homegraph_impact': return await this.handleImpact(args);
|
|
1681
|
+
case 'homegraph_diff_impact': return await this.handleDiffImpact(args);
|
|
1603
1682
|
case 'homegraph_explore': return await this.handleExplore(args);
|
|
1604
1683
|
case 'homegraph_node': return await this.handleNode(args);
|
|
1605
1684
|
case 'homegraph_files': return await this.handleFiles(args);
|
|
@@ -1901,6 +1980,147 @@ class ToolHandler {
|
|
|
1901
1980
|
}
|
|
1902
1981
|
return this.textResult(this.truncateOutput(sections.join('\n') + filterNote));
|
|
1903
1982
|
}
|
|
1983
|
+
/**
|
|
1984
|
+
* Handle homegraph_diff_impact — diff line ranges ∩ symbol spans → evidence pack.
|
|
1985
|
+
*/
|
|
1986
|
+
async handleDiffImpact(args) {
|
|
1987
|
+
const resolved = (0, diff_impact_1.resolveDiffImpactHunks)({
|
|
1988
|
+
diff: args.diff,
|
|
1989
|
+
hunks: args.hunks,
|
|
1990
|
+
});
|
|
1991
|
+
if (resolved.error) {
|
|
1992
|
+
return this.badArgResult(resolved.error, 'diff');
|
|
1993
|
+
}
|
|
1994
|
+
if (resolved.hunks.length === 0) {
|
|
1995
|
+
return this.badArgResult('No file hunks found. Pass a unified `diff` with `+++` / `@@` headers, or `hunks: [{ path, startLine, endLine }]`.', 'diff');
|
|
1996
|
+
}
|
|
1997
|
+
const cg = this.getHomeGraph(args.projectPath);
|
|
1998
|
+
const depthRaw = Number(args.depth);
|
|
1999
|
+
const depth = Number.isFinite(depthRaw) ? depthRaw : 2;
|
|
2000
|
+
const includeSpecs = args.includeSpecs === true;
|
|
2001
|
+
const pack = (0, diff_impact_1.buildDiffImpactPack)(cg, resolved.hunks, {
|
|
2002
|
+
depth,
|
|
2003
|
+
notes: resolved.notes,
|
|
2004
|
+
});
|
|
2005
|
+
const relatedSpecs = [];
|
|
2006
|
+
if (includeSpecs) {
|
|
2007
|
+
const { resolveDbPath } = require('../spec/utils');
|
|
2008
|
+
const { createDatabase } = require('../db/sqlite-adapter');
|
|
2009
|
+
const { findSpecsByFilePath, findSpecsByCodeSymbol, } = require('../spec/graph/queries');
|
|
2010
|
+
const projectRoot = (() => {
|
|
2011
|
+
try {
|
|
2012
|
+
return cg.getProjectRoot();
|
|
2013
|
+
}
|
|
2014
|
+
catch {
|
|
2015
|
+
return args.projectPath || process.cwd();
|
|
2016
|
+
}
|
|
2017
|
+
})();
|
|
2018
|
+
const dbPath = resolveDbPath(projectRoot);
|
|
2019
|
+
let db = null;
|
|
2020
|
+
try {
|
|
2021
|
+
db = createDatabase(dbPath).db;
|
|
2022
|
+
}
|
|
2023
|
+
catch {
|
|
2024
|
+
pack.notes.push(`includeSpecs was true but Commit4Spec DB is unavailable at ${dbPath} (run \`homegraph spec build\` / \`mine\` first).`);
|
|
2025
|
+
}
|
|
2026
|
+
if (db) {
|
|
2027
|
+
try {
|
|
2028
|
+
const seenFileSpecs = new Set();
|
|
2029
|
+
for (const filePath of pack.changedFiles) {
|
|
2030
|
+
try {
|
|
2031
|
+
const found = findSpecsByFilePath(db, filePath);
|
|
2032
|
+
for (const r of found.results ?? []) {
|
|
2033
|
+
if (!r.id || seenFileSpecs.has(r.id))
|
|
2034
|
+
continue;
|
|
2035
|
+
seenFileSpecs.add(r.id);
|
|
2036
|
+
relatedSpecs.push({
|
|
2037
|
+
specId: r.id,
|
|
2038
|
+
title: r.title,
|
|
2039
|
+
via: 'file',
|
|
2040
|
+
filePath,
|
|
2041
|
+
});
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
catch {
|
|
2045
|
+
/* ignore per-file */
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
const forTrace = pack.changedSymbols.slice(0, diff_impact_1.DIFF_IMPACT_LIMITS.maxSpecSymbols);
|
|
2049
|
+
if (pack.changedSymbols.length > forTrace.length) {
|
|
2050
|
+
pack.notes.push(`Spec symbol-trace limited to ${diff_impact_1.DIFF_IMPACT_LIMITS.maxSpecSymbols} of ${pack.changedSymbols.length} changed symbols.`);
|
|
2051
|
+
}
|
|
2052
|
+
const seenSymKeys = new Set();
|
|
2053
|
+
for (const sym of forTrace) {
|
|
2054
|
+
try {
|
|
2055
|
+
const traced = findSpecsByCodeSymbol(db, {
|
|
2056
|
+
name: sym.name,
|
|
2057
|
+
qualifiedName: sym.name,
|
|
2058
|
+
kind: sym.kind,
|
|
2059
|
+
filePath: sym.filePath,
|
|
2060
|
+
startLine: sym.startLine,
|
|
2061
|
+
endLine: sym.endLine,
|
|
2062
|
+
}, 5);
|
|
2063
|
+
for (const m of traced.matches ?? []) {
|
|
2064
|
+
const id = m.spec?.id;
|
|
2065
|
+
if (!id)
|
|
2066
|
+
continue;
|
|
2067
|
+
const key = `${id}::${sym.name}`;
|
|
2068
|
+
if (seenSymKeys.has(key))
|
|
2069
|
+
continue;
|
|
2070
|
+
seenSymKeys.add(key);
|
|
2071
|
+
relatedSpecs.push({
|
|
2072
|
+
specId: id,
|
|
2073
|
+
title: m.spec.title,
|
|
2074
|
+
via: 'symbol',
|
|
2075
|
+
symbol: sym.name,
|
|
2076
|
+
score: typeof m.score === 'number' ? m.score : undefined,
|
|
2077
|
+
});
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
catch {
|
|
2081
|
+
/* ignore per-symbol */
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
finally {
|
|
2086
|
+
try {
|
|
2087
|
+
db.close();
|
|
2088
|
+
}
|
|
2089
|
+
catch {
|
|
2090
|
+
/* ignore */
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
const response = {
|
|
2096
|
+
...pack,
|
|
2097
|
+
// Drop raw hunk ranges from default agent payload noise — keep changedFiles + symbols.
|
|
2098
|
+
hunks: pack.hunks.map((h) => ({
|
|
2099
|
+
path: h.path,
|
|
2100
|
+
ranges: h.ranges,
|
|
2101
|
+
})),
|
|
2102
|
+
relatedSpecs: includeSpecs ? relatedSpecs : undefined,
|
|
2103
|
+
};
|
|
2104
|
+
const json = JSON.stringify(response, null, 2);
|
|
2105
|
+
if (json.length <= MAX_OUTPUT_LENGTH) {
|
|
2106
|
+
return this.textResult(json);
|
|
2107
|
+
}
|
|
2108
|
+
const slim = {
|
|
2109
|
+
...response,
|
|
2110
|
+
callers: response.callers.slice(0, 20),
|
|
2111
|
+
impactSummary: response.impactSummary.map((s) => ({
|
|
2112
|
+
...s,
|
|
2113
|
+
sampleNames: s.sampleNames.slice(0, 3),
|
|
2114
|
+
})),
|
|
2115
|
+
uiEdges: response.uiEdges.slice(0, 15),
|
|
2116
|
+
relatedSpecs: response.relatedSpecs?.slice(0, 15),
|
|
2117
|
+
notes: [
|
|
2118
|
+
...response.notes,
|
|
2119
|
+
'Output trimmed to fit MCP size limit — re-run with a smaller diff if you need full lists.',
|
|
2120
|
+
],
|
|
2121
|
+
};
|
|
2122
|
+
return this.textResult(this.truncateOutput(JSON.stringify(slim, null, 2)));
|
|
2123
|
+
}
|
|
1904
2124
|
/** Whether a graph edge may be traversed by homegraph_explore's main Flow BFS. */
|
|
1905
2125
|
isExploreFlowEdge(edge) {
|
|
1906
2126
|
if (edge.kind === 'calls')
|
|
@@ -2097,12 +2317,21 @@ class ToolHandler {
|
|
|
2097
2317
|
const hits = this.findAllSymbols(cg, t).nodes;
|
|
2098
2318
|
const cands = hits.filter((n) => CALLABLE.has(n.kind));
|
|
2099
2319
|
tokenFamily.set(t, cands);
|
|
2320
|
+
// Prefer in-repo callables over attached OHOS SDK stubs (`ohos-sdk:…`).
|
|
2321
|
+
// Lifecycle names like `aboutToAppear` / `build` collide with dozens of
|
|
2322
|
+
// API defs; counting those as ambiguity empties co-naming and drops the
|
|
2323
|
+
// project method the agent actually meant (ArkTS explore Flow regression).
|
|
2324
|
+
// Do NOT fall back to the full pool when co-naming empties — that would
|
|
2325
|
+
// pin a polymorphic name like `execute` (9+ impls) onto the Flow spine
|
|
2326
|
+
// and silence the Interface-dispatch announcement.
|
|
2327
|
+
const projectCands = cands.filter((n) => !(0, arkts_1.isOhosApiFilePath)(n.filePath));
|
|
2328
|
+
const pool = projectCands.length > 0 ? projectCands : cands;
|
|
2100
2329
|
// A qualified or otherwise-specific name (<=3 hits) keeps all; an
|
|
2101
2330
|
// ambiguous simple name keeps only candidates whose container is named.
|
|
2102
|
-
const specific =
|
|
2331
|
+
const specific = pool.length <= 3;
|
|
2103
2332
|
const pick = specific
|
|
2104
|
-
?
|
|
2105
|
-
:
|
|
2333
|
+
? pool
|
|
2334
|
+
: pool.filter((n) => {
|
|
2106
2335
|
const segs = (n.qualifiedName || '').toLowerCase().split(/::|\./).filter(Boolean);
|
|
2107
2336
|
const container = segs.length >= 2 ? segs[segs.length - 2] : '';
|
|
2108
2337
|
return !!container && segPool.has(container);
|
|
@@ -5946,6 +6175,12 @@ class ToolHandler {
|
|
|
5946
6175
|
if (!symbolRaw && fileHint) {
|
|
5947
6176
|
return this.handleFileView(cg, fileHint, { offset, limit, symbolsOnly });
|
|
5948
6177
|
}
|
|
6178
|
+
if (!symbolRaw && !fileHint) {
|
|
6179
|
+
return this.badArgResult('`homegraph_node` needs either `symbol` (symbol mode) or `file` alone (file mode). Both were missing.', 'symbol', {
|
|
6180
|
+
symbol: 'authenticate',
|
|
6181
|
+
includeCode: true,
|
|
6182
|
+
});
|
|
6183
|
+
}
|
|
5949
6184
|
const symbol = this.validateString(args.symbol, 'symbol');
|
|
5950
6185
|
if (typeof symbol !== 'string')
|
|
5951
6186
|
return symbol;
|
|
@@ -7111,6 +7346,21 @@ class ToolHandler {
|
|
|
7111
7346
|
content: [{ type: 'text', text }],
|
|
7112
7347
|
};
|
|
7113
7348
|
}
|
|
7349
|
+
/**
|
|
7350
|
+
* Recoverable bad-argument guidance: SUCCESS-shaped (no `isError`) so agents
|
|
7351
|
+
* retry with fixed args instead of abandoning HomeGraph for the session.
|
|
7352
|
+
* Reserved `isError` cases stay in {@link errorResult} (security / real faults).
|
|
7353
|
+
*/
|
|
7354
|
+
badArgResult(problem, argName, exampleOverride) {
|
|
7355
|
+
const example = exampleOverride ??
|
|
7356
|
+
{ [argName]: BAD_ARG_EXAMPLES[argName] ?? '…' };
|
|
7357
|
+
return this.textResult(`${problem}\n\n` +
|
|
7358
|
+
'This is not a HomeGraph failure — fix the arguments and retry the same tool.\n' +
|
|
7359
|
+
'Example:\n' +
|
|
7360
|
+
'```json\n' +
|
|
7361
|
+
`${JSON.stringify(example, null, 2)}\n` +
|
|
7362
|
+
'```');
|
|
7363
|
+
}
|
|
7114
7364
|
errorResult(message) {
|
|
7115
7365
|
return {
|
|
7116
7366
|
content: [{ type: 'text', text: `Error: ${message}` }],
|