@mrclrchtr/supi-code-intelligence 6.3.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +164 -82
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +8 -1
- package/node_modules/@mrclrchtr/supi-core/README.md +8 -0
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +10 -3
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
- package/node_modules/@mrclrchtr/supi-core/src/llm.ts +141 -16
- package/node_modules/@mrclrchtr/supi-lsp/README.md +35 -13
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +8 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +8 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +10 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/llm.ts +141 -16
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/index.js +3 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/legacy.js +3 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/package.json +3 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +16 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +43 -35
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +83 -17
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +108 -92
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +44 -82
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +3 -4
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-publication.ts +9 -68
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +45 -58
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +230 -331
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +201 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +129 -70
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-typescript.ts +395 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +8 -12
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +685 -183
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +60 -60
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-request-enrollment.ts +75 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-semantic-input-barrier.ts +443 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-semantic-input-errors.ts +30 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-semantic-input-file.ts +15 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +290 -37
- package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +72 -16
- package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +1 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +30 -4
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sentinels.ts +4 -32
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sources.ts +108 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +10 -4
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-process-crash-report.ts +50 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +11 -7
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +770 -56
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +3 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +37 -4
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +48 -12
- package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +50 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +8 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +10 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/llm.ts +141 -16
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +3 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +2 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callee-display-name.ts +165 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +67 -9
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +2 -0
- package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +19 -18
- package/node_modules/yaml/browser/dist/nodes/Alias.js +25 -23
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +19 -18
- package/node_modules/yaml/dist/nodes/Alias.js +25 -23
- package/node_modules/yaml/package.json +1 -1
- package/package.json +5 -5
- package/src/analysis/health/diagnostics.ts +1 -2
- package/src/analysis/health/file-scope.ts +4 -1
- package/src/analysis/health/server-status.ts +1 -1
- package/src/analysis/relations/callees.ts +17 -8
- package/src/analysis/relations/implementations.ts +1 -2
- package/src/analysis/relations/references.ts +8 -4
- package/src/analysis/relations/types.ts +6 -30
- package/src/analysis/target/anchored.ts +9 -1
- package/src/analysis/target/symbol.ts +29 -11
- package/src/analysis/target/types.ts +14 -6
- package/src/api.ts +2 -0
- package/src/session/graph/collect.ts +18 -3
- package/src/session/health-refresh.ts +27 -11
- package/src/session/health-types.ts +21 -4
- package/src/session/health-workflow.ts +28 -22
- package/src/session/orientation-types.ts +5 -6
- package/src/session/orientation-workflow.ts +10 -2
- package/src/session/session.ts +12 -5
- package/src/session/target-workflow.ts +9 -6
- package/src/substrate/lsp/maintenance.ts +53 -47
- package/src/substrate/lsp/source-tracking.ts +252 -0
- package/src/tool/code_find/guidance.ts +3 -3
- package/src/tool/code_find/spec.ts +5 -4
- package/src/tool/code_find/tui.ts +7 -1
- package/src/tool/code_graph/details.ts +32 -0
- package/src/tool/code_graph/display.ts +54 -0
- package/src/tool/code_graph/format.ts +60 -0
- package/src/tool/code_graph/guidance.ts +2 -2
- package/src/tool/code_graph/markdown.ts +76 -198
- package/src/tool/code_graph/read-next.ts +65 -0
- package/src/tool/code_graph/result.ts +118 -83
- package/src/tool/code_graph/tui.ts +216 -54
- package/src/tool/code_health/guidance.ts +3 -5
- package/src/tool/code_health/markdown.ts +90 -57
- package/src/tool/code_health/refresh-outcome.ts +51 -0
- package/src/tool/code_health/refresh-status.ts +130 -43
- package/src/tool/code_health/scope.ts +78 -0
- package/src/tool/code_health/spec.ts +1 -1
- package/src/tool/code_health/tui.ts +29 -38
- package/src/tool/code_inspect/guidance.ts +5 -3
- package/src/tool/code_inspect/tui.ts +7 -1
- package/src/tool/code_orientation/guidance.ts +3 -4
- package/src/tool/code_orientation/result.ts +31 -8
- package/src/tool/code_orientation/tui.ts +26 -5
- package/src/tool/code_refactor_apply/guidance.ts +1 -1
- package/src/tool/code_refactor_apply/tui.ts +7 -3
- package/src/tool/code_refactor_plan/guidance.ts +3 -5
- package/src/tool/code_refactor_plan/tui.ts +7 -1
- package/src/tool/code_resolve/guidance.ts +3 -5
- package/src/tool/code_resolve/result.ts +13 -10
- package/src/tool/code_resolve/tui.ts +18 -1
- package/src/tool/guidance.ts +11 -9
- package/src/tool/infra/truncate.ts +39 -13
- package/src/tool/result/candidate-row.ts +27 -0
- package/src/tool/result/errors.ts +21 -6
- package/src/tool/result/types.ts +7 -3
- package/src/tool/schemas.ts +5 -0
- package/src/types/execution.ts +2 -0
- package/src/types/index.ts +2 -0
- package/src/ui/tui/candidate-legacy-body.ts +69 -0
- package/src/ui/tui/candidate-selection.ts +366 -0
- package/src/ui/tui/common.ts +26 -31
- package/src/ui/tui/execution-error.ts +92 -0
|
@@ -3,17 +3,34 @@ import {
|
|
|
3
3
|
type ProcessCrashRecoveryEntry,
|
|
4
4
|
type ProcessCrashRecoveryOutcome,
|
|
5
5
|
type ProcessCrashRecoveryReport,
|
|
6
|
+
type StartupRetryEntry,
|
|
7
|
+
type StartupRetryReport,
|
|
6
8
|
} from "@mrclrchtr/supi-lsp/api";
|
|
7
9
|
import {
|
|
8
10
|
formatCompactProcessCrashRecovery,
|
|
11
|
+
formatCompactStartupRetry,
|
|
9
12
|
formatProcessCrashRecovery,
|
|
10
13
|
formatStaleDiagnosticRestarts,
|
|
14
|
+
formatStartupRetry,
|
|
11
15
|
isFileReadinessPending,
|
|
12
16
|
} from "./refresh-outcome.ts";
|
|
17
|
+
import {
|
|
18
|
+
formatCompactMaintenanceEvidence,
|
|
19
|
+
formatMaintenanceEvidence,
|
|
20
|
+
formatMaintenanceScope,
|
|
21
|
+
} from "./scope.ts";
|
|
13
22
|
import { readSemanticHealthState } from "./semantic-state.ts";
|
|
14
23
|
|
|
15
24
|
/** Render current and retained health refresh status for the TUI. */
|
|
16
25
|
|
|
26
|
+
/** Read source discovery counts from structured health details. */
|
|
27
|
+
export function readSourceTrackingStatus(source: Record<string, unknown> | null): string | null {
|
|
28
|
+
if (!source || (source.status !== "complete" && source.status !== "limited")) return null;
|
|
29
|
+
const reason =
|
|
30
|
+
source.status === "limited" && typeof source.reason === "string" ? ` (${source.reason})` : "";
|
|
31
|
+
return `${source.status}${reason}: ${readNumber(source.observedFileCount)} observed, ${readArrayLength(source.discovered)} discovered, ${readArrayLength(source.tracked)} tracked, ${readArrayLength(source.skipped)} skipped, ${readArrayLength(source.unavailable)} unavailable, ${readNumber(source.deferred)} deferred`;
|
|
32
|
+
}
|
|
33
|
+
|
|
17
34
|
export function readRefreshStatus(data: Record<string, unknown> | null): string | null {
|
|
18
35
|
const refresh = readRecord(data?.refresh);
|
|
19
36
|
if (!refresh) return null;
|
|
@@ -41,18 +58,31 @@ function formatCompletedRefreshStatus(
|
|
|
41
58
|
const processCrashRecovery = formatProcessCrashRecovery(
|
|
42
59
|
readProcessCrashRecovery(refresh.processCrashRecovery),
|
|
43
60
|
);
|
|
61
|
+
const startupRetry = formatStartupRetry(readStartupRetry(refresh.startupRetry));
|
|
44
62
|
const noOp =
|
|
45
|
-
!fileReadinessPending &&
|
|
63
|
+
!fileReadinessPending &&
|
|
64
|
+
attempted === 0 &&
|
|
65
|
+
restarted === 0 &&
|
|
66
|
+
processCrashRecovery === null &&
|
|
67
|
+
startupRetry === null;
|
|
46
68
|
const label = refreshAttemptLabel(refresh);
|
|
47
69
|
const base = fileReadinessPending
|
|
48
70
|
? `${label} waiting — LSP may still be warming; retry shortly`
|
|
49
71
|
: noOp
|
|
50
72
|
? `${label} completed no-op`
|
|
51
73
|
: `${label} completed: ${attempted} clients targeted`;
|
|
52
|
-
const outcomes = formatRefreshOutcomes(
|
|
74
|
+
const outcomes = formatRefreshOutcomes({
|
|
75
|
+
refresh,
|
|
76
|
+
restarted,
|
|
77
|
+
processCrashRecovery,
|
|
78
|
+
startupRetry,
|
|
79
|
+
noOp,
|
|
80
|
+
});
|
|
53
81
|
const withOutcome = outcomes.length > 0 ? `${base}; ${outcomes.join("; ")}` : base;
|
|
54
|
-
const
|
|
55
|
-
const
|
|
82
|
+
const maintenanceScope = formatMaintenanceScope(refresh);
|
|
83
|
+
const withScope = maintenanceScope ? `${withOutcome}; ${maintenanceScope}` : withOutcome;
|
|
84
|
+
const evidence = formatMaintenanceEvidence(readRecord(refresh.diagnosticEvidence));
|
|
85
|
+
const withEvidence = evidence ? `${withScope}; ${evidence}` : withScope;
|
|
56
86
|
const stale = readRecord(refresh.staleAssessment);
|
|
57
87
|
return stale?.suspected === true
|
|
58
88
|
? `${withEvidence}; stale pattern suspected in ${readNumber(stale.matchedFileCount)} files`
|
|
@@ -63,23 +93,26 @@ function formatFailedRefreshStatus(refresh: Record<string, unknown>): string {
|
|
|
63
93
|
const processCrashRecovery = formatProcessCrashRecovery(
|
|
64
94
|
readProcessCrashRecovery(refresh.processCrashRecovery),
|
|
65
95
|
);
|
|
96
|
+
const startupRetry = formatStartupRetry(readStartupRetry(refresh.startupRetry));
|
|
66
97
|
const staleRestart = formatStaleDiagnosticRestartsForRecord(refresh);
|
|
67
|
-
const
|
|
98
|
+
const maintenanceScope = formatMaintenanceScope(refresh);
|
|
99
|
+
const evidence = formatMaintenanceEvidence(readRecord(refresh.diagnosticEvidence));
|
|
68
100
|
const reason = typeof refresh.reason === "string" ? `: ${refresh.reason}` : "";
|
|
69
|
-
return `${refreshAttemptLabel(refresh)} failed${reason}${staleRestart ? `; ${staleRestart}` : ""}${processCrashRecovery ? `; ${processCrashRecovery}` : ""}${evidence ? `; ${evidence}` : ""}`;
|
|
101
|
+
return `${refreshAttemptLabel(refresh)} failed${reason}${maintenanceScope ? `; ${maintenanceScope}` : ""}${staleRestart ? `; ${staleRestart}` : ""}${processCrashRecovery ? `; ${processCrashRecovery}` : ""}${startupRetry ? `; ${startupRetry}` : ""}${evidence ? `; ${evidence}` : ""}`;
|
|
70
102
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
noOp: boolean
|
|
77
|
-
): string[] {
|
|
103
|
+
function formatRefreshOutcomes(options: {
|
|
104
|
+
refresh: Record<string, unknown>;
|
|
105
|
+
restarted: number;
|
|
106
|
+
processCrashRecovery: string | null;
|
|
107
|
+
startupRetry: string | null;
|
|
108
|
+
noOp: boolean;
|
|
109
|
+
}): string[] {
|
|
78
110
|
const outcomes: string[] = [];
|
|
79
|
-
if (refresh.operationScope === "workspace-runtime" && !noOp) {
|
|
80
|
-
outcomes.push(formatStaleDiagnosticRestarts(restarted));
|
|
111
|
+
if (options.refresh.operationScope === "workspace-runtime" && !options.noOp) {
|
|
112
|
+
outcomes.push(formatStaleDiagnosticRestarts(options.restarted));
|
|
81
113
|
}
|
|
82
|
-
if (processCrashRecovery) outcomes.push(processCrashRecovery);
|
|
114
|
+
if (options.processCrashRecovery) outcomes.push(options.processCrashRecovery);
|
|
115
|
+
if (options.startupRetry) outcomes.push(options.startupRetry);
|
|
83
116
|
return outcomes;
|
|
84
117
|
}
|
|
85
118
|
|
|
@@ -88,20 +121,25 @@ export function readCompactRefreshStatus(data: Record<string, unknown> | null):
|
|
|
88
121
|
const refresh = readRecord(data?.refresh);
|
|
89
122
|
if (!refresh || (refresh.kind !== "completed" && refresh.kind !== "failed")) return null;
|
|
90
123
|
|
|
124
|
+
const sourceTracking = formatSourceTracking(readRecord(refresh.sourceTracking));
|
|
91
125
|
const processCrashRecovery = formatCompactProcessCrashRecovery(
|
|
92
126
|
readProcessCrashRecovery(refresh.processCrashRecovery),
|
|
93
127
|
);
|
|
128
|
+
const startupRetry = formatCompactStartupRetry(readStartupRetry(refresh.startupRetry));
|
|
129
|
+
const maintenanceScope = formatMaintenanceScope(refresh);
|
|
94
130
|
if (refresh.kind === "failed") {
|
|
95
131
|
const staleRestart = formatStaleDiagnosticRestartsForRecord(refresh);
|
|
96
132
|
return (
|
|
97
|
-
[staleRestart, processCrashRecovery]
|
|
133
|
+
[maintenanceScope, sourceTracking, staleRestart, processCrashRecovery, startupRetry]
|
|
98
134
|
.filter((value): value is string => value !== null)
|
|
99
135
|
.join("; ") || null
|
|
100
136
|
);
|
|
101
137
|
}
|
|
102
138
|
const fileReadinessPending = isPendingFileReadiness(data);
|
|
103
139
|
if (
|
|
140
|
+
!sourceTracking &&
|
|
104
141
|
!processCrashRecovery &&
|
|
142
|
+
!startupRetry &&
|
|
105
143
|
readNumber(refresh.restartedClients) === 0 &&
|
|
106
144
|
!fileReadinessPending
|
|
107
145
|
) {
|
|
@@ -110,7 +148,14 @@ export function readCompactRefreshStatus(data: Record<string, unknown> | null):
|
|
|
110
148
|
|
|
111
149
|
const staleRestart = formatStaleDiagnosticRestartsForRecord(refresh);
|
|
112
150
|
const readiness = fileReadinessPending ? "LSP may still be warming; retry shortly" : null;
|
|
113
|
-
return [
|
|
151
|
+
return [
|
|
152
|
+
maintenanceScope,
|
|
153
|
+
sourceTracking,
|
|
154
|
+
staleRestart,
|
|
155
|
+
processCrashRecovery,
|
|
156
|
+
startupRetry,
|
|
157
|
+
readiness,
|
|
158
|
+
]
|
|
114
159
|
.filter((value): value is string => value !== null)
|
|
115
160
|
.join("; ");
|
|
116
161
|
}
|
|
@@ -122,16 +167,26 @@ export function readPreviousRefreshStatus(data: Record<string, unknown> | null):
|
|
|
122
167
|
}
|
|
123
168
|
const attempt = readRecord(refresh.lastAttempt);
|
|
124
169
|
if (!attempt) return null;
|
|
125
|
-
const evidence =
|
|
170
|
+
const evidence = formatCompactMaintenanceEvidence(readRecord(attempt.diagnosticEvidence));
|
|
171
|
+
const sourceTracking = formatSourceTracking(readRecord(attempt.sourceTracking));
|
|
126
172
|
const processCrashRecovery = formatCompactProcessCrashRecovery(
|
|
127
173
|
readProcessCrashRecovery(attempt.processCrashRecovery),
|
|
128
174
|
);
|
|
175
|
+
const startupRetry = formatCompactStartupRetry(readStartupRetry(attempt.startupRetry));
|
|
129
176
|
const staleRestart = formatStaleDiagnosticRestartsForRecord(attempt);
|
|
130
177
|
const fileReadinessPending =
|
|
131
178
|
attempt.kind === "completed" &&
|
|
132
179
|
isFileReadinessPending(attempt, readSemanticHealthState(data?.semanticState));
|
|
133
180
|
const readiness = fileReadinessPending ? "LSP may still be warming; retry shortly" : null;
|
|
134
|
-
const outcome = [
|
|
181
|
+
const outcome = [
|
|
182
|
+
readiness,
|
|
183
|
+
formatMaintenanceScope(attempt),
|
|
184
|
+
sourceTracking,
|
|
185
|
+
staleRestart,
|
|
186
|
+
processCrashRecovery,
|
|
187
|
+
startupRetry,
|
|
188
|
+
evidence,
|
|
189
|
+
]
|
|
135
190
|
.filter((value): value is string => value !== null)
|
|
136
191
|
.join("; ");
|
|
137
192
|
if (attempt.kind === "failed") {
|
|
@@ -169,15 +224,25 @@ function formatStaleDiagnosticRestartsForRecord(attempt: Record<string, unknown>
|
|
|
169
224
|
function formatLastRefreshSuffix(refresh: Record<string, unknown>): string {
|
|
170
225
|
const attempt = readRecord(refresh.lastAttempt);
|
|
171
226
|
if (!attempt) return "";
|
|
172
|
-
const evidence =
|
|
227
|
+
const evidence = formatMaintenanceEvidence(readRecord(attempt.diagnosticEvidence));
|
|
228
|
+
const sourceTracking = formatSourceTracking(readRecord(attempt.sourceTracking));
|
|
173
229
|
const staleRestart = formatStaleDiagnosticRestartsForRecord(attempt);
|
|
174
230
|
const processCrashRecovery = formatProcessCrashRecovery(
|
|
175
231
|
readProcessCrashRecovery(attempt.processCrashRecovery),
|
|
176
232
|
);
|
|
233
|
+
const startupRetry = formatStartupRetry(readStartupRetry(attempt.startupRetry));
|
|
177
234
|
const fileReadinessPending =
|
|
178
235
|
attempt.kind === "completed" && isFileReadinessPending(attempt, null);
|
|
179
236
|
const readiness = fileReadinessPending ? "LSP may still be warming; retry shortly" : null;
|
|
180
|
-
const outcome = [
|
|
237
|
+
const outcome = [
|
|
238
|
+
readiness,
|
|
239
|
+
formatMaintenanceScope(attempt),
|
|
240
|
+
sourceTracking,
|
|
241
|
+
staleRestart,
|
|
242
|
+
processCrashRecovery,
|
|
243
|
+
startupRetry,
|
|
244
|
+
evidence,
|
|
245
|
+
]
|
|
181
246
|
.filter((value): value is string => value !== null)
|
|
182
247
|
.join("; ");
|
|
183
248
|
if (attempt.kind === "failed") {
|
|
@@ -191,16 +256,13 @@ function formatLastRefreshSuffix(refresh: Record<string, unknown>): string {
|
|
|
191
256
|
return "";
|
|
192
257
|
}
|
|
193
258
|
|
|
194
|
-
function
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
return `req ${counts[0]} · conf ${counts[1]} · unconf ${counts[2]} · failed ${counts[3]} · removed ${counts[4]}`;
|
|
259
|
+
function formatSourceTracking(source: Record<string, unknown> | null): string | null {
|
|
260
|
+
const status = readSourceTrackingStatus(source);
|
|
261
|
+
return status ? `source discovery ${status}` : null;
|
|
198
262
|
}
|
|
199
263
|
|
|
200
|
-
function
|
|
201
|
-
|
|
202
|
-
if (!counts) return null;
|
|
203
|
-
return `${counts[0]} requested, ${counts[1]} confirmed, ${counts[2]} unconfirmed, ${counts[3]} failed, ${counts[4]} removed`;
|
|
264
|
+
function readArrayLength(value: unknown): number {
|
|
265
|
+
return Array.isArray(value) ? value.length : 0;
|
|
204
266
|
}
|
|
205
267
|
|
|
206
268
|
export function isPendingFileReadiness(data: Record<string, unknown> | null): boolean {
|
|
@@ -213,6 +275,43 @@ export function isPendingFileReadiness(data: Record<string, unknown> | null): bo
|
|
|
213
275
|
return isFileReadinessPending(attempt, readSemanticHealthState(data?.semanticState));
|
|
214
276
|
}
|
|
215
277
|
|
|
278
|
+
function readStartupRetry(value: unknown): StartupRetryReport | null {
|
|
279
|
+
const report = readRecord(value);
|
|
280
|
+
if (!report) return null;
|
|
281
|
+
const recoveredRoutes = report.recoveredRoutes;
|
|
282
|
+
const failedRoutes = report.failedRoutes;
|
|
283
|
+
const omittedEntries = report.omittedEntries;
|
|
284
|
+
if (
|
|
285
|
+
!isEvidenceCount(recoveredRoutes) ||
|
|
286
|
+
!isEvidenceCount(failedRoutes) ||
|
|
287
|
+
!isEvidenceCount(omittedEntries) ||
|
|
288
|
+
!Array.isArray(report.entries) ||
|
|
289
|
+
report.entries.length > MAX_PROCESS_CRASH_RECOVERY_ENTRIES
|
|
290
|
+
) {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
const entries = report.entries
|
|
294
|
+
.map(readStartupRetryEntry)
|
|
295
|
+
.filter((entry): entry is StartupRetryEntry => entry !== null);
|
|
296
|
+
if (entries.length !== report.entries.length) return null;
|
|
297
|
+
return { recoveredRoutes, failedRoutes, entries, omittedEntries };
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function readStartupRetryEntry(value: unknown): StartupRetryEntry | null {
|
|
301
|
+
const entry = readRecord(value);
|
|
302
|
+
if (!entry || typeof entry.name !== "string" || typeof entry.root !== "string") return null;
|
|
303
|
+
if (entry.outcome !== "recovered" && entry.outcome !== "retry-failed") return null;
|
|
304
|
+
if (entry.nextAction !== undefined && entry.nextAction !== "refresh") return null;
|
|
305
|
+
if (entry.failureMessage !== undefined && typeof entry.failureMessage !== "string") return null;
|
|
306
|
+
return {
|
|
307
|
+
name: entry.name,
|
|
308
|
+
root: entry.root,
|
|
309
|
+
outcome: entry.outcome,
|
|
310
|
+
...(entry.nextAction !== undefined ? { nextAction: entry.nextAction } : {}),
|
|
311
|
+
...(entry.failureMessage !== undefined ? { failureMessage: entry.failureMessage } : {}),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
216
315
|
function readProcessCrashRecovery(value: unknown): ProcessCrashRecoveryReport | null {
|
|
217
316
|
const report = readRecord(value);
|
|
218
317
|
if (!report) return null;
|
|
@@ -246,7 +345,7 @@ function readProcessCrashRecoveryEntry(value: unknown): ProcessCrashRecoveryEntr
|
|
|
246
345
|
if (
|
|
247
346
|
entry.nextAction !== undefined &&
|
|
248
347
|
entry.nextAction !== "use-exact-file" &&
|
|
249
|
-
entry.nextAction !== "
|
|
348
|
+
entry.nextAction !== "refresh"
|
|
250
349
|
) {
|
|
251
350
|
return null;
|
|
252
351
|
}
|
|
@@ -269,18 +368,6 @@ function isProcessCrashRecoveryOutcome(value: unknown): value is ProcessCrashRec
|
|
|
269
368
|
);
|
|
270
369
|
}
|
|
271
370
|
|
|
272
|
-
function readEvidenceCounts(evidence: Record<string, unknown> | null): number[] | null {
|
|
273
|
-
if (!evidence) return null;
|
|
274
|
-
const counts = [
|
|
275
|
-
evidence.requested,
|
|
276
|
-
evidence.confirmed,
|
|
277
|
-
evidence.unconfirmed,
|
|
278
|
-
evidence.failed,
|
|
279
|
-
evidence.removed,
|
|
280
|
-
];
|
|
281
|
-
return counts.every(isEvidenceCount) ? counts : null;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
371
|
function isEvidenceCount(value: unknown): value is number {
|
|
285
372
|
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
286
373
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** Formatting for diagnostic result and maintenance scopes and their evidence. */
|
|
2
|
+
|
|
3
|
+
function readRecord(value: unknown): Record<string, unknown> | null {
|
|
4
|
+
return typeof value === "object" && value !== null ? (value as Record<string, unknown>) : null;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function withDiagnosticScope(summary: string, data: Record<string, unknown> | null): string {
|
|
8
|
+
const scope = formatDiagnosticScope(readDiagnosticScope(data));
|
|
9
|
+
return scope ? `${summary} — evidence scope: ${scope}` : summary;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function readDiagnosticScope(data: Record<string, unknown> | null): Record<string, unknown> | null {
|
|
13
|
+
return readRecord(readRecord(data?.diagnosticObservation)?.scope);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function formatDiagnosticScope(scope: Record<string, unknown> | null): string | null {
|
|
17
|
+
if (scope?.kind === "file" && typeof scope.path === "string") {
|
|
18
|
+
return `live file diagnostic request for ${scope.path}`;
|
|
19
|
+
}
|
|
20
|
+
if (scope?.kind === "tracked-files") {
|
|
21
|
+
return typeof scope.filter === "string"
|
|
22
|
+
? `tracked-file diagnostic snapshot under ${scope.filter}`
|
|
23
|
+
: "tracked-file diagnostic snapshot";
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function formatCompactDiagnosticEvidence(
|
|
29
|
+
evidence: Record<string, unknown> | null,
|
|
30
|
+
scopeKind: string | null,
|
|
31
|
+
): string | null {
|
|
32
|
+
const counts = readEvidenceCounts(evidence);
|
|
33
|
+
if (!counts) return null;
|
|
34
|
+
const scopeLabel = scopeKind === "file" ? "file" : "tracked-file";
|
|
35
|
+
return `${scopeLabel} evidence req ${counts[0]} · conf ${counts[1]} · unconf ${counts[2]} · failed ${counts[3]} · removed ${counts[4]}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function formatDiagnosticEvidence(evidence: Record<string, unknown> | null): string | null {
|
|
39
|
+
const counts = readEvidenceCounts(evidence);
|
|
40
|
+
if (!counts) return null;
|
|
41
|
+
return `${counts[0]} requested, ${counts[1]} confirmed, ${counts[2]} unconfirmed, ${counts[3]} failed, ${counts[4]} removed`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function formatMaintenanceEvidence(evidence: Record<string, unknown> | null): string | null {
|
|
45
|
+
const counts = readEvidenceCounts(evidence);
|
|
46
|
+
if (!counts) return null;
|
|
47
|
+
return `maintenance evidence: ${counts[0]} requested, ${counts[1]} confirmed, ${counts[2]} unconfirmed, ${counts[3]} failed, ${counts[4]} removed`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function formatCompactMaintenanceEvidence(
|
|
51
|
+
evidence: Record<string, unknown> | null,
|
|
52
|
+
): string | null {
|
|
53
|
+
const counts = readEvidenceCounts(evidence);
|
|
54
|
+
if (!counts) return null;
|
|
55
|
+
return `maintenance evidence req ${counts[0]} · conf ${counts[1]} · unconf ${counts[2]} · failed ${counts[3]} · removed ${counts[4]}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function formatMaintenanceScope(refresh: Record<string, unknown>): string | null {
|
|
59
|
+
if (refresh.operationScope === "file-runtime") return "maintenance scope: file runtime";
|
|
60
|
+
if (refresh.operationScope === "workspace-runtime") return "maintenance scope: workspace runtime";
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function readEvidenceCounts(evidence: Record<string, unknown> | null): number[] | null {
|
|
65
|
+
if (!evidence) return null;
|
|
66
|
+
const counts = [
|
|
67
|
+
evidence.requested,
|
|
68
|
+
evidence.confirmed,
|
|
69
|
+
evidence.unconfirmed,
|
|
70
|
+
evidence.failed,
|
|
71
|
+
evidence.removed,
|
|
72
|
+
];
|
|
73
|
+
return counts.every(isEvidenceCount) ? counts : null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function isEvidenceCount(value: unknown): value is number {
|
|
77
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
78
|
+
}
|
|
@@ -18,7 +18,7 @@ export const codeHealthSpec = {
|
|
|
18
18
|
refresh: Type.Optional(
|
|
19
19
|
Type.Boolean({
|
|
20
20
|
description:
|
|
21
|
-
"
|
|
21
|
+
"Retry failed LSP routes and collect fresh diagnostic health evidence; result reports route recovery separately from diagnostic confirmation.",
|
|
22
22
|
}),
|
|
23
23
|
),
|
|
24
24
|
include: Type.Optional(
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
6
|
-
import { Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
6
|
+
import { type Component, Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
7
7
|
import {
|
|
8
8
|
formatProjectServerRouteStatusCounts,
|
|
9
9
|
type ProjectServerRouteStatusCounts,
|
|
@@ -29,7 +29,13 @@ import {
|
|
|
29
29
|
readCompactRefreshStatus,
|
|
30
30
|
readPreviousRefreshStatus,
|
|
31
31
|
readRefreshStatus,
|
|
32
|
+
readSourceTrackingStatus,
|
|
32
33
|
} from "./refresh-status.ts";
|
|
34
|
+
import {
|
|
35
|
+
formatCompactDiagnosticEvidence,
|
|
36
|
+
formatDiagnosticEvidence,
|
|
37
|
+
withDiagnosticScope,
|
|
38
|
+
} from "./scope.ts";
|
|
33
39
|
import { formatSemanticHealthState, readSemanticHealthState } from "./semantic-state.ts";
|
|
34
40
|
|
|
35
41
|
/** ── renderCall ────────────────────────────────────────────────── */
|
|
@@ -63,12 +69,16 @@ export function renderHealthResult(
|
|
|
63
69
|
options: ResultOptios,
|
|
64
70
|
theme: Theme,
|
|
65
71
|
context: ToolRendererContext | undefined,
|
|
66
|
-
):
|
|
72
|
+
): Component {
|
|
67
73
|
if (options.isPartial) return renderPartial("Gathering workspace health…", theme);
|
|
68
74
|
|
|
69
75
|
const data =
|
|
70
76
|
result.details?.type === "health" ? (result.details.data as Record<string, unknown>) : null;
|
|
71
|
-
const executionError = renderExecutionError(
|
|
77
|
+
const executionError = renderExecutionError(
|
|
78
|
+
result,
|
|
79
|
+
{ isError: context?.isError, expanded: options.expanded, label: "code_health failed" },
|
|
80
|
+
theme,
|
|
81
|
+
);
|
|
72
82
|
if (executionError) return executionError;
|
|
73
83
|
const domainError = renderDomainError(result, theme);
|
|
74
84
|
if (domainError) return renderDomainResult(result, options, theme, domainError);
|
|
@@ -135,7 +145,7 @@ function buildCompactSummary(data: Record<string, unknown> | null, theme: Theme)
|
|
|
135
145
|
formatSectionSummary(
|
|
136
146
|
section,
|
|
137
147
|
section.key === "diagnostics"
|
|
138
|
-
? formatCompactDiagnosticEvidence(readDiagnosticEvidence(data))
|
|
148
|
+
? formatCompactDiagnosticEvidence(readDiagnosticEvidence(data), diagnosticScopeKind(data))
|
|
139
149
|
: null,
|
|
140
150
|
theme,
|
|
141
151
|
fileReadinessPending,
|
|
@@ -192,6 +202,8 @@ function buildStatusBar(data: Record<string, unknown> | null, theme: Theme): Tex
|
|
|
192
202
|
const semanticStatus = readSemanticStatus(data);
|
|
193
203
|
const structuralStatus = readString(data, "structuralStatus");
|
|
194
204
|
const refreshStatus = readRefreshStatus(data);
|
|
205
|
+
const refresh = readRecord(data?.refresh);
|
|
206
|
+
const sourceTracking = readSourceTrackingStatus(readRecord(refresh?.sourceTracking));
|
|
195
207
|
|
|
196
208
|
const lspColor = semanticStatus.startsWith("ready") ? "success" : "warning";
|
|
197
209
|
const structuralColor = structuralStatus === "ready" ? "success" : "muted";
|
|
@@ -204,6 +216,7 @@ function buildStatusBar(data: Record<string, unknown> | null, theme: Theme): Tex
|
|
|
204
216
|
lines.push(`Tree-sitter: ${theme.fg(structuralColor, structuralStatus)}`);
|
|
205
217
|
}
|
|
206
218
|
if (refreshStatus) lines.push(`Diagnostics: ${theme.fg("dim", refreshStatus)}`);
|
|
219
|
+
if (sourceTracking) lines.push(`Source discovery: ${theme.fg("dim", sourceTracking)}`);
|
|
207
220
|
|
|
208
221
|
return new Text(lines.join(" "), 0, 0);
|
|
209
222
|
}
|
|
@@ -226,36 +239,6 @@ function readDiagnosticEvidence(
|
|
|
226
239
|
return readRecord(readRecord(data?.diagnosticObservation)?.evidence);
|
|
227
240
|
}
|
|
228
241
|
|
|
229
|
-
function formatCompactDiagnosticEvidence(evidence: Record<string, unknown> | null): string | null {
|
|
230
|
-
if (!evidence) return null;
|
|
231
|
-
const counts = [
|
|
232
|
-
evidence.requested,
|
|
233
|
-
evidence.confirmed,
|
|
234
|
-
evidence.unconfirmed,
|
|
235
|
-
evidence.failed,
|
|
236
|
-
evidence.removed,
|
|
237
|
-
];
|
|
238
|
-
if (!counts.every(isEvidenceCount)) return null;
|
|
239
|
-
return `req ${evidence.requested} · conf ${evidence.confirmed} · unconf ${evidence.unconfirmed} · failed ${evidence.failed} · removed ${evidence.removed}`;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function formatDiagnosticEvidence(evidence: Record<string, unknown> | null): string | null {
|
|
243
|
-
if (!evidence) return null;
|
|
244
|
-
const counts = [
|
|
245
|
-
evidence.requested,
|
|
246
|
-
evidence.confirmed,
|
|
247
|
-
evidence.unconfirmed,
|
|
248
|
-
evidence.failed,
|
|
249
|
-
evidence.removed,
|
|
250
|
-
];
|
|
251
|
-
if (!counts.every(isEvidenceCount)) return null;
|
|
252
|
-
return `${evidence.requested} requested, ${evidence.confirmed} confirmed, ${evidence.unconfirmed} unconfirmed, ${evidence.failed} failed, ${evidence.removed} removed`;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function isEvidenceCount(value: unknown): value is number {
|
|
256
|
-
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
242
|
function readRecord(value: unknown): Record<string, unknown> | null {
|
|
260
243
|
return typeof value === "object" && value !== null ? (value as Record<string, unknown>) : null;
|
|
261
244
|
}
|
|
@@ -320,21 +303,29 @@ function buildDiagnosticSummary(data: Record<string, unknown> | null, theme: The
|
|
|
320
303
|
const label = isPendingFileReadiness(data)
|
|
321
304
|
? "Diagnostics pending — LSP may still be warming; retry shortly"
|
|
322
305
|
: "Diagnostics unavailable";
|
|
323
|
-
return new Text(theme.fg("warning", label), 0, 0);
|
|
306
|
+
return new Text(theme.fg("warning", withDiagnosticScope(label, data)), 0, 0);
|
|
324
307
|
}
|
|
325
308
|
const trackedFiles = diagnosticScopeKind(data) === "tracked-files";
|
|
326
309
|
if (section.status === "partial") {
|
|
327
310
|
const coverage = formatDiagnosticEvidence(readDiagnosticEvidence(data));
|
|
328
311
|
const label = trackedFiles ? "Tracked-file diagnostics partial" : "Diagnostics partial";
|
|
329
|
-
|
|
312
|
+
const summary = coverage ? `${label} (${coverage})` : label;
|
|
313
|
+
return new Text(theme.fg("warning", withDiagnosticScope(summary, data)), 0, 0);
|
|
330
314
|
}
|
|
331
315
|
if (section.itemCount === 0) {
|
|
332
|
-
return new Text(
|
|
316
|
+
return new Text(
|
|
317
|
+
theme.fg("success", withDiagnosticScope(diagnosticEmptySummary(data), data)),
|
|
318
|
+
0,
|
|
319
|
+
0,
|
|
320
|
+
);
|
|
333
321
|
}
|
|
334
322
|
|
|
335
323
|
const fileLabel = `${trackedFiles ? "tracked " : ""}${section.itemCount === 1 ? "file" : "files"}`;
|
|
336
324
|
return new Text(
|
|
337
|
-
theme.fg(
|
|
325
|
+
theme.fg(
|
|
326
|
+
"warning",
|
|
327
|
+
theme.bold(withDiagnosticScope(`${section.itemCount} ${fileLabel} with issues`, data)),
|
|
328
|
+
),
|
|
338
329
|
0,
|
|
339
330
|
0,
|
|
340
331
|
);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export const toolDescription =
|
|
2
|
-
"Inspect one
|
|
2
|
+
"Inspect one source location for syntax, its enclosing declaration, hover information, definitions, and nearby diagnostics. Use it for point-local facts, not broad code context.";
|
|
3
3
|
|
|
4
|
-
export const promptSnippet = "
|
|
4
|
+
export const promptSnippet = "inspect a source location";
|
|
5
5
|
|
|
6
|
-
export const promptGuidelines
|
|
6
|
+
export const promptGuidelines = [
|
|
7
|
+
"Use code_inspect for diagnostics near a source location; use code_health for broader diagnostics or language-server status.",
|
|
8
|
+
];
|
|
@@ -40,5 +40,11 @@ export function renderInspectResult(
|
|
|
40
40
|
theme: Theme,
|
|
41
41
|
context: ToolRendererContext | undefined,
|
|
42
42
|
): ReturnType<typeof renderSimpleResult> {
|
|
43
|
-
return renderSimpleResult(
|
|
43
|
+
return renderSimpleResult(
|
|
44
|
+
result,
|
|
45
|
+
options,
|
|
46
|
+
theme,
|
|
47
|
+
{ progress: "Inspecting…", failure: "code_inspect failed" },
|
|
48
|
+
context,
|
|
49
|
+
);
|
|
44
50
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
export const toolDescription =
|
|
2
|
-
"
|
|
2
|
+
"Return observed workspace or focused code context to choose what source to inspect next. Omit `focus` for workspace context. A directory focus can surface local instruction files.";
|
|
3
3
|
|
|
4
|
-
export const promptSnippet = "workspace
|
|
4
|
+
export const promptSnippet = "orient around workspace or code context";
|
|
5
5
|
|
|
6
6
|
export const promptGuidelines = [
|
|
7
|
-
"Use code_orientation before broad
|
|
8
|
-
"Use code_graph for relationships and code_health for provider or diagnostic state.",
|
|
7
|
+
"Use code_orientation before broad source reading when workspace or path context can narrow the files.",
|
|
9
8
|
];
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { ConfidenceMode } from "@mrclrchtr/supi-code-runtime/api";
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
type EvidenceListMetadata,
|
|
4
|
+
renderEvidenceListMetadataDisclosure,
|
|
5
|
+
} from "../../analysis/evidence.ts";
|
|
3
6
|
import type { ReadNextItem } from "../../analysis/read-next.ts";
|
|
4
7
|
import type {
|
|
5
8
|
OrientationCandidate,
|
|
@@ -15,6 +18,7 @@ import {
|
|
|
15
18
|
type ResultSection,
|
|
16
19
|
type ToolResultAssembly,
|
|
17
20
|
} from "../result/assembly.ts";
|
|
21
|
+
import { formatCandidateRow } from "../result/candidate-row.ts";
|
|
18
22
|
import { createToolDisplaySection } from "../result/display.ts";
|
|
19
23
|
import type {
|
|
20
24
|
ContextDetails,
|
|
@@ -47,17 +51,17 @@ export interface OrientationResultAssembly {
|
|
|
47
51
|
/** Build structured candidate rows for an unresolved Orientation target. */
|
|
48
52
|
export function orientationCandidateDisplaySections(
|
|
49
53
|
candidates: readonly OrientationCandidate[],
|
|
50
|
-
|
|
54
|
+
evidence: EvidenceListMetadata,
|
|
51
55
|
): readonly ToolDisplaySection[] {
|
|
52
56
|
return [
|
|
53
57
|
createToolDisplaySection({
|
|
54
58
|
key: "orientation.candidates",
|
|
55
59
|
title: "Candidates",
|
|
56
60
|
items: candidates,
|
|
57
|
-
totalCount:
|
|
58
|
-
omittedCount,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
totalCount: evidence.totalCount,
|
|
62
|
+
omittedCount: evidence.omittedCount,
|
|
63
|
+
partialReason: evidence.partialReason,
|
|
64
|
+
format: (candidate) => formatCandidateRow(candidate, "rank-first"),
|
|
61
65
|
}),
|
|
62
66
|
];
|
|
63
67
|
}
|
|
@@ -215,13 +219,23 @@ export function finishOrientationResult(outcome: OrientationOutcome): CodeIntelR
|
|
|
215
219
|
`${candidate.rank}. **${candidate.name}** (\`${candidate.kind ?? "unknown"}\`) — \`${candidate.file}\`:${candidate.line}:${candidate.character} — \`${candidate.targetId}\``,
|
|
216
220
|
);
|
|
217
221
|
}
|
|
222
|
+
const evidence: EvidenceListMetadata = {
|
|
223
|
+
key: "orientation.candidates",
|
|
224
|
+
totalCount: outcome.totalCount,
|
|
225
|
+
shownCount: candidates.length,
|
|
226
|
+
omittedCount: outcome.omittedCount,
|
|
227
|
+
partialReason: outcome.partialReason,
|
|
228
|
+
};
|
|
229
|
+
const disclosure = renderEvidenceListMetadataDisclosure(evidence);
|
|
230
|
+
if (disclosure) lines.push("", disclosure);
|
|
218
231
|
const nextQueries =
|
|
219
232
|
outcome.kind === "kind-mismatch"
|
|
220
233
|
? ["Retry without symbolKind, use an observed provider kind, or focus one handle"]
|
|
221
234
|
: ["Use one candidate handle as focus.target.handle"];
|
|
222
235
|
const details = assembleOrientationDetails({
|
|
223
236
|
confidence: "semantic",
|
|
224
|
-
omittedCount:
|
|
237
|
+
omittedCount: evidence.omittedCount ?? 0,
|
|
238
|
+
evidenceLists: [evidence],
|
|
225
239
|
candidates,
|
|
226
240
|
nextQueries,
|
|
227
241
|
});
|
|
@@ -231,7 +245,8 @@ export function finishOrientationResult(outcome: OrientationOutcome): CodeIntelR
|
|
|
231
245
|
type: "context",
|
|
232
246
|
data: details,
|
|
233
247
|
status: "completed",
|
|
234
|
-
|
|
248
|
+
message: orientationSelectionMessage(outcome),
|
|
249
|
+
displaySections: orientationCandidateDisplaySections(candidates, evidence),
|
|
235
250
|
},
|
|
236
251
|
};
|
|
237
252
|
}
|
|
@@ -246,3 +261,11 @@ export function finishOrientationResult(outcome: OrientationOutcome): CodeIntelR
|
|
|
246
261
|
},
|
|
247
262
|
};
|
|
248
263
|
}
|
|
264
|
+
|
|
265
|
+
function orientationSelectionMessage(
|
|
266
|
+
outcome: Extract<OrientationOutcome, { kind: "disambiguation" | "kind-mismatch" }>,
|
|
267
|
+
): string {
|
|
268
|
+
return outcome.kind === "kind-mismatch"
|
|
269
|
+
? `No Orientation target matched provider kind ${outcome.requestedKind}.`
|
|
270
|
+
: "Multiple Orientation targets require one candidate.";
|
|
271
|
+
}
|