@mrclrchtr/supi-code-intelligence 6.4.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 +6 -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/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 +608 -45
- 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 +31 -11
- package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +19 -3
- 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 +12 -1
- package/src/session/health-types.ts +18 -6
- package/src/session/health-workflow.ts +21 -19
- package/src/session/orientation-types.ts +5 -6
- package/src/session/orientation-workflow.ts +10 -2
- package/src/session/target-workflow.ts +9 -6
- package/src/substrate/lsp/source-tracking.ts +11 -6
- package/src/tool/code_find/guidance.ts +2 -2
- 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 +1 -1
- 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 +2 -4
- package/src/tool/code_health/markdown.ts +75 -58
- package/src/tool/code_health/refresh-outcome.ts +41 -1
- package/src/tool/code_health/refresh-status.ts +114 -48
- 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 +25 -38
- package/src/tool/code_inspect/tui.ts +7 -1
- 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 +1 -1
- package/src/tool/code_refactor_plan/tui.ts +7 -1
- package/src/tool/code_resolve/guidance.ts +2 -4
- package/src/tool/code_resolve/result.ts +13 -10
- package/src/tool/code_resolve/tui.ts +18 -1
- 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,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,
|
|
@@ -31,6 +31,11 @@ import {
|
|
|
31
31
|
readRefreshStatus,
|
|
32
32
|
readSourceTrackingStatus,
|
|
33
33
|
} from "./refresh-status.ts";
|
|
34
|
+
import {
|
|
35
|
+
formatCompactDiagnosticEvidence,
|
|
36
|
+
formatDiagnosticEvidence,
|
|
37
|
+
withDiagnosticScope,
|
|
38
|
+
} from "./scope.ts";
|
|
34
39
|
import { formatSemanticHealthState, readSemanticHealthState } from "./semantic-state.ts";
|
|
35
40
|
|
|
36
41
|
/** ── renderCall ────────────────────────────────────────────────── */
|
|
@@ -64,12 +69,16 @@ export function renderHealthResult(
|
|
|
64
69
|
options: ResultOptios,
|
|
65
70
|
theme: Theme,
|
|
66
71
|
context: ToolRendererContext | undefined,
|
|
67
|
-
):
|
|
72
|
+
): Component {
|
|
68
73
|
if (options.isPartial) return renderPartial("Gathering workspace health…", theme);
|
|
69
74
|
|
|
70
75
|
const data =
|
|
71
76
|
result.details?.type === "health" ? (result.details.data as Record<string, unknown>) : null;
|
|
72
|
-
const executionError = renderExecutionError(
|
|
77
|
+
const executionError = renderExecutionError(
|
|
78
|
+
result,
|
|
79
|
+
{ isError: context?.isError, expanded: options.expanded, label: "code_health failed" },
|
|
80
|
+
theme,
|
|
81
|
+
);
|
|
73
82
|
if (executionError) return executionError;
|
|
74
83
|
const domainError = renderDomainError(result, theme);
|
|
75
84
|
if (domainError) return renderDomainResult(result, options, theme, domainError);
|
|
@@ -136,7 +145,7 @@ function buildCompactSummary(data: Record<string, unknown> | null, theme: Theme)
|
|
|
136
145
|
formatSectionSummary(
|
|
137
146
|
section,
|
|
138
147
|
section.key === "diagnostics"
|
|
139
|
-
? formatCompactDiagnosticEvidence(readDiagnosticEvidence(data))
|
|
148
|
+
? formatCompactDiagnosticEvidence(readDiagnosticEvidence(data), diagnosticScopeKind(data))
|
|
140
149
|
: null,
|
|
141
150
|
theme,
|
|
142
151
|
fileReadinessPending,
|
|
@@ -230,36 +239,6 @@ function readDiagnosticEvidence(
|
|
|
230
239
|
return readRecord(readRecord(data?.diagnosticObservation)?.evidence);
|
|
231
240
|
}
|
|
232
241
|
|
|
233
|
-
function formatCompactDiagnosticEvidence(evidence: Record<string, unknown> | null): string | null {
|
|
234
|
-
if (!evidence) return null;
|
|
235
|
-
const counts = [
|
|
236
|
-
evidence.requested,
|
|
237
|
-
evidence.confirmed,
|
|
238
|
-
evidence.unconfirmed,
|
|
239
|
-
evidence.failed,
|
|
240
|
-
evidence.removed,
|
|
241
|
-
];
|
|
242
|
-
if (!counts.every(isEvidenceCount)) return null;
|
|
243
|
-
return `req ${evidence.requested} · conf ${evidence.confirmed} · unconf ${evidence.unconfirmed} · failed ${evidence.failed} · removed ${evidence.removed}`;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
function formatDiagnosticEvidence(evidence: Record<string, unknown> | null): string | null {
|
|
247
|
-
if (!evidence) return null;
|
|
248
|
-
const counts = [
|
|
249
|
-
evidence.requested,
|
|
250
|
-
evidence.confirmed,
|
|
251
|
-
evidence.unconfirmed,
|
|
252
|
-
evidence.failed,
|
|
253
|
-
evidence.removed,
|
|
254
|
-
];
|
|
255
|
-
if (!counts.every(isEvidenceCount)) return null;
|
|
256
|
-
return `${evidence.requested} requested, ${evidence.confirmed} confirmed, ${evidence.unconfirmed} unconfirmed, ${evidence.failed} failed, ${evidence.removed} removed`;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function isEvidenceCount(value: unknown): value is number {
|
|
260
|
-
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
242
|
function readRecord(value: unknown): Record<string, unknown> | null {
|
|
264
243
|
return typeof value === "object" && value !== null ? (value as Record<string, unknown>) : null;
|
|
265
244
|
}
|
|
@@ -324,21 +303,29 @@ function buildDiagnosticSummary(data: Record<string, unknown> | null, theme: The
|
|
|
324
303
|
const label = isPendingFileReadiness(data)
|
|
325
304
|
? "Diagnostics pending — LSP may still be warming; retry shortly"
|
|
326
305
|
: "Diagnostics unavailable";
|
|
327
|
-
return new Text(theme.fg("warning", label), 0, 0);
|
|
306
|
+
return new Text(theme.fg("warning", withDiagnosticScope(label, data)), 0, 0);
|
|
328
307
|
}
|
|
329
308
|
const trackedFiles = diagnosticScopeKind(data) === "tracked-files";
|
|
330
309
|
if (section.status === "partial") {
|
|
331
310
|
const coverage = formatDiagnosticEvidence(readDiagnosticEvidence(data));
|
|
332
311
|
const label = trackedFiles ? "Tracked-file diagnostics partial" : "Diagnostics partial";
|
|
333
|
-
|
|
312
|
+
const summary = coverage ? `${label} (${coverage})` : label;
|
|
313
|
+
return new Text(theme.fg("warning", withDiagnosticScope(summary, data)), 0, 0);
|
|
334
314
|
}
|
|
335
315
|
if (section.itemCount === 0) {
|
|
336
|
-
return new Text(
|
|
316
|
+
return new Text(
|
|
317
|
+
theme.fg("success", withDiagnosticScope(diagnosticEmptySummary(data), data)),
|
|
318
|
+
0,
|
|
319
|
+
0,
|
|
320
|
+
);
|
|
337
321
|
}
|
|
338
322
|
|
|
339
323
|
const fileLabel = `${trackedFiles ? "tracked " : ""}${section.itemCount === 1 ? "file" : "files"}`;
|
|
340
324
|
return new Text(
|
|
341
|
-
theme.fg(
|
|
325
|
+
theme.fg(
|
|
326
|
+
"warning",
|
|
327
|
+
theme.bold(withDiagnosticScope(`${section.itemCount} ${fileLabel} with issues`, data)),
|
|
328
|
+
),
|
|
342
329
|
0,
|
|
343
330
|
0,
|
|
344
331
|
);
|
|
@@ -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,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
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** TUI renderer for code_orientation. */
|
|
2
2
|
import { getMarkdownTheme, type Theme } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import { Container, Markdown, Spacer, Text } from "@earendil-works/pi-tui";
|
|
3
|
+
import { type Component, Container, Markdown, Spacer, Text } from "@earendil-works/pi-tui";
|
|
4
|
+
import { renderCandidateSelection } from "../../ui/tui/candidate-selection.ts";
|
|
4
5
|
import {
|
|
5
6
|
type EvidenceEntry,
|
|
6
7
|
formatCallPath,
|
|
@@ -50,15 +51,35 @@ export function renderOrientationResult(
|
|
|
50
51
|
options: ResultOptios,
|
|
51
52
|
theme: Theme,
|
|
52
53
|
context: ToolRendererContext | undefined,
|
|
53
|
-
):
|
|
54
|
+
): Component {
|
|
54
55
|
if (options.isPartial) return renderPartial("Orienting…", theme);
|
|
55
56
|
|
|
57
|
+
const executionError = renderExecutionError(
|
|
58
|
+
result,
|
|
59
|
+
{ isError: context?.isError, expanded: options.expanded, label: "code_orientation failed" },
|
|
60
|
+
theme,
|
|
61
|
+
);
|
|
62
|
+
if (executionError) return executionError;
|
|
63
|
+
|
|
64
|
+
const candidateSelection = renderCandidateSelection(
|
|
65
|
+
result,
|
|
66
|
+
options,
|
|
67
|
+
theme,
|
|
68
|
+
"orientation.candidates",
|
|
69
|
+
);
|
|
70
|
+
if (candidateSelection) return candidateSelection;
|
|
71
|
+
|
|
72
|
+
return renderOrientationDetails(result, options, theme);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function renderOrientationDetails(
|
|
76
|
+
result: ToolResult,
|
|
77
|
+
options: ResultOptios,
|
|
78
|
+
theme: Theme,
|
|
79
|
+
): Component {
|
|
56
80
|
const data =
|
|
57
81
|
result.details?.type === "context" ? (result.details.data as Record<string, unknown>) : null;
|
|
58
82
|
const markdownText = result.content.find((c) => c.type === "text")?.text ?? "";
|
|
59
|
-
|
|
60
|
-
const executionError = renderExecutionError(context, "code_orientation failed", theme);
|
|
61
|
-
if (executionError) return executionError;
|
|
62
83
|
const domainError = renderDomainError(result, theme);
|
|
63
84
|
if (domainError) return renderDomainResult(result, options, theme, domainError);
|
|
64
85
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const toolDescription =
|
|
2
|
-
"Apply a
|
|
2
|
+
"Apply a stored refactor plan by its returned planId after freshness and edit-safety checks. Changed files reject the apply and require a new plan; this tool does not regenerate one.";
|
|
3
3
|
|
|
4
4
|
export const promptSnippet = "apply a stored refactor plan";
|
|
5
5
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** TUI renderer for code_refactor_apply. */
|
|
2
2
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import { Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
3
|
+
import { type Component, Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
4
4
|
import {
|
|
5
5
|
formatCallValue,
|
|
6
6
|
type ResultOptios,
|
|
@@ -33,10 +33,14 @@ export function renderRefactorApplyResult(
|
|
|
33
33
|
options: ResultOptios,
|
|
34
34
|
theme: Theme,
|
|
35
35
|
context: ToolRendererContext | undefined,
|
|
36
|
-
):
|
|
36
|
+
): Component {
|
|
37
37
|
if (options.isPartial) return renderPartial("Applying…", theme);
|
|
38
38
|
|
|
39
|
-
const executionError = renderExecutionError(
|
|
39
|
+
const executionError = renderExecutionError(
|
|
40
|
+
result,
|
|
41
|
+
{ isError: context?.isError, expanded: options.expanded, label: "code_refactor_apply failed" },
|
|
42
|
+
theme,
|
|
43
|
+
);
|
|
40
44
|
if (executionError) return executionError;
|
|
41
45
|
const domainError = renderDomainError(result, theme);
|
|
42
46
|
if (domainError) return renderDomainResult(result, options, theme, domainError);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const toolDescription =
|
|
2
|
-
"
|
|
2
|
+
"Create and store a semantic refactor preview without changing files. Unsupported operations do not fall back to text edits.";
|
|
3
3
|
|
|
4
4
|
export const promptSnippet = "preview a semantic refactor";
|
|
5
5
|
|
|
@@ -50,5 +50,11 @@ export function renderRefactorPlanResult(
|
|
|
50
50
|
theme: Theme,
|
|
51
51
|
context: ToolRendererContext | undefined,
|
|
52
52
|
): ReturnType<typeof renderSimpleResult> {
|
|
53
|
-
return renderSimpleResult(
|
|
53
|
+
return renderSimpleResult(
|
|
54
|
+
result,
|
|
55
|
+
options,
|
|
56
|
+
theme,
|
|
57
|
+
{ progress: "Planning…", failure: "code_refactor_plan failed" },
|
|
58
|
+
context,
|
|
59
|
+
);
|
|
54
60
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export const toolDescription =
|
|
2
|
-
"Resolve a real symbol anchor or semantic query to target handles, or list a file's declarations as a target group.
|
|
2
|
+
"Resolve a real symbol anchor or semantic query to target handles for later code tools, or list a file's declarations as a target group. This tool does not search file text.";
|
|
3
3
|
|
|
4
4
|
export const promptSnippet = "resolve symbols or file declarations";
|
|
5
5
|
|
|
6
|
-
export const promptGuidelines = [
|
|
7
|
-
"Use code_resolve when a symbol query can match multiple symbols or when a later tool requires a target handle.",
|
|
8
|
-
];
|
|
6
|
+
export const promptGuidelines: string[] = [];
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type ResultProvenance,
|
|
11
11
|
type ToolResultAssembly,
|
|
12
12
|
} from "../result/assembly.ts";
|
|
13
|
+
import { formatCandidateRow } from "../result/candidate-row.ts";
|
|
13
14
|
import { createToolDisplaySection } from "../result/display.ts";
|
|
14
15
|
import type { ResolveDetails, ToolDisplaySection } from "../result/types.ts";
|
|
15
16
|
|
|
@@ -25,7 +26,7 @@ export interface ResolveResultAssembly {
|
|
|
25
26
|
interface ResolveProjection {
|
|
26
27
|
readonly key: string;
|
|
27
28
|
readonly title: string;
|
|
28
|
-
readonly status: "complete" | "unavailable";
|
|
29
|
+
readonly status: "complete" | "partial" | "unavailable";
|
|
29
30
|
readonly items: readonly unknown[];
|
|
30
31
|
readonly confidence: ConfidenceMode;
|
|
31
32
|
readonly evidence: EvidenceListMetadata | null;
|
|
@@ -153,19 +154,19 @@ function projectTargetGroup(
|
|
|
153
154
|
function projectCandidateOutcome(
|
|
154
155
|
outcome: Extract<TargetWorkflowOutcome, { kind: "disambiguation" | "kind-mismatch" }>,
|
|
155
156
|
): ResolveProjection {
|
|
156
|
-
const totalCount = outcome.candidates.length + outcome.omittedCount;
|
|
157
157
|
const evidence: EvidenceListMetadata = {
|
|
158
158
|
key: "resolve.candidates",
|
|
159
|
-
totalCount,
|
|
159
|
+
totalCount: outcome.totalCount,
|
|
160
160
|
shownCount: outcome.candidates.length,
|
|
161
161
|
omittedCount: outcome.omittedCount,
|
|
162
|
-
partialReason:
|
|
162
|
+
partialReason: outcome.partialReason,
|
|
163
163
|
};
|
|
164
|
+
const collectedCount = evidence.shownCount + (evidence.omittedCount ?? 0);
|
|
164
165
|
const mismatch = outcome.kind === "kind-mismatch";
|
|
165
166
|
return {
|
|
166
167
|
key: "resolve.candidates",
|
|
167
168
|
title: mismatch ? "Near matches" : "Candidates",
|
|
168
|
-
status: "complete",
|
|
169
|
+
status: outcome.partialReason ? "partial" : "complete",
|
|
169
170
|
items: outcome.candidates,
|
|
170
171
|
confidence: "semantic",
|
|
171
172
|
evidence,
|
|
@@ -173,7 +174,7 @@ function projectCandidateOutcome(
|
|
|
173
174
|
resultKind: outcome.kind,
|
|
174
175
|
...(mismatch ? { requestedKind: outcome.requestedKind } : {}),
|
|
175
176
|
confidence: "semantic",
|
|
176
|
-
targetCount: totalCount,
|
|
177
|
+
targetCount: evidence.totalCount ?? collectedCount,
|
|
177
178
|
omittedCount: outcome.omittedCount,
|
|
178
179
|
evidenceLists: [evidence],
|
|
179
180
|
targets: [],
|
|
@@ -254,15 +255,17 @@ function resolveDisplaySections(details: ResolveDetails): ToolDisplaySection[] {
|
|
|
254
255
|
}
|
|
255
256
|
|
|
256
257
|
if (details.candidates && details.candidates.length > 0) {
|
|
258
|
+
const evidence = details.evidenceLists?.find((entry) => entry.key === "resolve.candidates");
|
|
259
|
+
if (!evidence) return [];
|
|
257
260
|
return [
|
|
258
261
|
createToolDisplaySection({
|
|
259
262
|
key: "resolve.candidates",
|
|
260
263
|
title: "Candidates",
|
|
261
264
|
items: details.candidates,
|
|
262
|
-
totalCount:
|
|
263
|
-
omittedCount:
|
|
264
|
-
|
|
265
|
-
|
|
265
|
+
totalCount: evidence.totalCount,
|
|
266
|
+
omittedCount: evidence.omittedCount,
|
|
267
|
+
partialReason: evidence.partialReason,
|
|
268
|
+
format: (candidate) => formatCandidateRow(candidate, "rank-first"),
|
|
266
269
|
}),
|
|
267
270
|
];
|
|
268
271
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** TUI renderer for code_resolve. */
|
|
2
2
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import { Text } from "@earendil-works/pi-tui";
|
|
4
|
+
import { renderCandidateSelection } from "../../ui/tui/candidate-selection.ts";
|
|
4
5
|
import {
|
|
5
6
|
formatCallPath,
|
|
6
7
|
formatCallValue,
|
|
@@ -56,5 +57,21 @@ export function renderResolveResult(
|
|
|
56
57
|
theme: Theme,
|
|
57
58
|
context: ToolRendererContext | undefined,
|
|
58
59
|
): ReturnType<typeof renderSimpleResult> {
|
|
59
|
-
|
|
60
|
+
if (!options.isPartial && !context?.isError) {
|
|
61
|
+
const candidateSelection = renderCandidateSelection(
|
|
62
|
+
result,
|
|
63
|
+
options,
|
|
64
|
+
theme,
|
|
65
|
+
"resolve.candidates",
|
|
66
|
+
);
|
|
67
|
+
if (candidateSelection) return candidateSelection;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return renderSimpleResult(
|
|
71
|
+
result,
|
|
72
|
+
options,
|
|
73
|
+
theme,
|
|
74
|
+
{ progress: "Resolving…", failure: "code_resolve failed" },
|
|
75
|
+
context,
|
|
76
|
+
);
|
|
60
77
|
}
|
|
@@ -48,7 +48,7 @@ export function truncateToolContent(
|
|
|
48
48
|
return { text: `${result.content}${notice}`, truncated: true };
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
import { mkdtempSync, writeFileSync } from "node:fs";
|
|
51
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
52
52
|
import { tmpdir } from "node:os";
|
|
53
53
|
import { join } from "node:path";
|
|
54
54
|
import type { CodeIntelResult } from "../../types/index.ts";
|
|
@@ -57,7 +57,9 @@ import type { ToolOutputTruncationDetails } from "../result/types.ts";
|
|
|
57
57
|
/**
|
|
58
58
|
* Apply the canonical output bound to one assembled code-tool result:
|
|
59
59
|
* truncate at PI limits, spill the full content to a temp file when it
|
|
60
|
-
* overflowed
|
|
60
|
+
* overflowed or the human display omits returned evidence. A display-only
|
|
61
|
+
* continuation does not add text to model content. File failure is fatal only
|
|
62
|
+
* when model content would otherwise be lost.
|
|
61
63
|
*/
|
|
62
64
|
export function boundCodeToolResult(
|
|
63
65
|
content: string,
|
|
@@ -71,19 +73,43 @@ export function boundCodeToolResult(
|
|
|
71
73
|
maxLines: options.maxLines,
|
|
72
74
|
maxBytes: options.maxBytes,
|
|
73
75
|
});
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
const displayTruncated = details?.truncation?.displayTruncated === true;
|
|
77
|
+
const truncation = { truncated, ...(displayTruncated ? { displayTruncated } : {}) };
|
|
78
|
+
if ((truncated || displayTruncated) && content.length > 0) {
|
|
79
|
+
try {
|
|
80
|
+
const spillPath = saveFullContent(content, options.toolName);
|
|
81
|
+
return {
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: "text" as const,
|
|
85
|
+
text: truncated ? `${text}\n_Full output saved to: \`${spillPath}\`_` : text,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
details: withTruncation({ ...truncation, fullOutputPath: spillPath }),
|
|
89
|
+
};
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (truncated) throw error;
|
|
92
|
+
// Keep valid evidence when only its optional human continuation failed.
|
|
93
|
+
}
|
|
84
94
|
}
|
|
85
95
|
return {
|
|
86
96
|
content: [{ type: "text" as const, text }],
|
|
87
|
-
details: withTruncation(
|
|
97
|
+
details: withTruncation(truncation),
|
|
88
98
|
};
|
|
89
99
|
}
|
|
100
|
+
|
|
101
|
+
function saveFullContent(content: string, toolName: string): string {
|
|
102
|
+
const dir = mkdtempSync(join(tmpdir(), "supi-ci-"));
|
|
103
|
+
const spillPath = join(dir, `${toolName}-output.md`);
|
|
104
|
+
try {
|
|
105
|
+
writeFileSync(spillPath, content, "utf-8");
|
|
106
|
+
return spillPath;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
try {
|
|
109
|
+
rmSync(dir, { recursive: true, force: true });
|
|
110
|
+
} catch {
|
|
111
|
+
/* Preserve the write error. */
|
|
112
|
+
}
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Candidate fields used by the three target-selection row formats. */
|
|
2
|
+
export interface CandidateRowData {
|
|
3
|
+
readonly targetId: string;
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly kind: string | null;
|
|
6
|
+
readonly file: string;
|
|
7
|
+
readonly line: number;
|
|
8
|
+
readonly character: number;
|
|
9
|
+
readonly rank?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** The order used for the target id and rank in one candidate row. */
|
|
13
|
+
export type CandidateRowOrder = "handle-first" | "rank-first";
|
|
14
|
+
|
|
15
|
+
/** Format one candidate row for a serialized display section or TUI fallback. */
|
|
16
|
+
export function formatCandidateRow(
|
|
17
|
+
candidate: CandidateRowData,
|
|
18
|
+
order: CandidateRowOrder,
|
|
19
|
+
fallbackRank = 1,
|
|
20
|
+
): string {
|
|
21
|
+
const kind = candidate.kind ?? "unknown";
|
|
22
|
+
if (order === "handle-first") {
|
|
23
|
+
return `${candidate.targetId} — ${candidate.name} (${kind}) at ${candidate.file}:${candidate.line}:${candidate.character}`;
|
|
24
|
+
}
|
|
25
|
+
const rank = candidate.rank && candidate.rank > 0 ? candidate.rank : fallbackRank;
|
|
26
|
+
return `${rank}. ${candidate.name} (${kind}) — ${candidate.file}:${candidate.line}:${candidate.character} [${candidate.targetId}]`;
|
|
27
|
+
}
|
|
@@ -1,27 +1,42 @@
|
|
|
1
|
+
import type { ConfidenceMode } from "@mrclrchtr/supi-code-runtime/api";
|
|
2
|
+
import type { EvidenceListMetadata } from "../../analysis/evidence.ts";
|
|
1
3
|
import type { CodeIntelResult, ToolDisplaySection } from "../../types/index.ts";
|
|
4
|
+
import { assembledNextQueries, assembleToolResult } from "./assembly.ts";
|
|
2
5
|
|
|
3
|
-
/** Full
|
|
6
|
+
/** Full failure or candidate-selection result for search-family tools. */
|
|
4
7
|
export function searchErrorResult(
|
|
5
8
|
content: string,
|
|
6
9
|
opts?: {
|
|
10
|
+
/** Candidate selection is not invalid usage. Defaults to invalid-input. */
|
|
11
|
+
status?: "invalid-input" | "disambiguation";
|
|
7
12
|
scope?: string | null;
|
|
8
13
|
nextQueries?: string[];
|
|
9
14
|
message?: string;
|
|
10
15
|
displaySections?: readonly ToolDisplaySection[];
|
|
16
|
+
/** Evidence retained when a target still needs selection. */
|
|
17
|
+
evidenceLists?: readonly EvidenceListMetadata[];
|
|
18
|
+
confidence?: ConfidenceMode;
|
|
11
19
|
},
|
|
12
20
|
): CodeIntelResult {
|
|
21
|
+
const assembled = assembleToolResult({
|
|
22
|
+
data: null,
|
|
23
|
+
confidence: opts?.confidence ?? "unavailable",
|
|
24
|
+
evidenceLists: opts?.evidenceLists,
|
|
25
|
+
nextQueries: opts?.nextQueries,
|
|
26
|
+
});
|
|
13
27
|
return {
|
|
14
28
|
content,
|
|
15
29
|
details: {
|
|
16
30
|
type: "search" as const,
|
|
17
31
|
data: {
|
|
18
|
-
confidence:
|
|
32
|
+
confidence: assembled.confidence,
|
|
19
33
|
scope: opts?.scope ?? null,
|
|
20
|
-
candidateCount:
|
|
21
|
-
omittedCount:
|
|
22
|
-
|
|
34
|
+
candidateCount: assembled.totals.candidateCount,
|
|
35
|
+
omittedCount: assembled.totals.omittedCount,
|
|
36
|
+
...(opts?.evidenceLists ? { evidenceLists: [...assembled.evidenceLists] } : {}),
|
|
37
|
+
nextQueries: assembledNextQueries(assembled),
|
|
23
38
|
},
|
|
24
|
-
status: "invalid-input",
|
|
39
|
+
status: opts?.status ?? "invalid-input",
|
|
25
40
|
...(opts?.message ? { message: opts.message } : {}),
|
|
26
41
|
...(opts?.displaySections ? { displaySections: opts.displaySections } : {}),
|
|
27
42
|
},
|
package/src/tool/result/types.ts
CHANGED
|
@@ -22,9 +22,13 @@ import type { ResultProvenance } from "./assembly.ts";
|
|
|
22
22
|
/** Final state for a public tool result. */
|
|
23
23
|
export type ToolResultStatus = "completed" | "invalid-input" | "disambiguation" | "unavailable";
|
|
24
24
|
|
|
25
|
-
/**
|
|
25
|
+
/** Separate model-content and human-display bounds, with one optional continuation file. */
|
|
26
26
|
export interface ToolOutputTruncationDetails {
|
|
27
|
+
/** Model content exceeded the PI output limit. */
|
|
27
28
|
truncated: boolean;
|
|
29
|
+
/** The TUI omits evidence that remains in the model content. */
|
|
30
|
+
displayTruncated?: boolean;
|
|
31
|
+
/** Full returned content, not evidence beyond the requested result limit. */
|
|
28
32
|
fullOutputPath?: string;
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -240,9 +244,9 @@ export interface HealthDetails {
|
|
|
240
244
|
serverInventoryAvailable: boolean;
|
|
241
245
|
/** Server inventory remains workspace-wide even for a scoped diagnostic request. */
|
|
242
246
|
serverInventoryScope: "workspace";
|
|
243
|
-
/**
|
|
247
|
+
/** Diagnostic result scope and exact evidence boundary for this health call. */
|
|
244
248
|
diagnosticObservation: HealthDiagnosticObservation;
|
|
245
|
-
/** Current or most recent
|
|
249
|
+
/** Current or most recent refresh, including typed maintenance scope and evidence. */
|
|
246
250
|
refresh: HealthRefreshState;
|
|
247
251
|
structuralAvailable: boolean;
|
|
248
252
|
/** Structural (tree-sitter) substrate readiness. Undefined when not evaluated. */
|
package/src/tool/schemas.ts
CHANGED
|
@@ -21,6 +21,11 @@ export const QueryParam = Type.String({
|
|
|
21
21
|
description: "Human or code reference to resolve or search for.",
|
|
22
22
|
minLength: 1,
|
|
23
23
|
});
|
|
24
|
+
export const FindQueryParam = Type.String({
|
|
25
|
+
description:
|
|
26
|
+
"AST mode: name or import module-specifier substring. Semantic mode: workspace-symbol query.",
|
|
27
|
+
minLength: 1,
|
|
28
|
+
});
|
|
24
29
|
const LineParam = Type.Integer({ description: "1-based line.", minimum: 1 });
|
|
25
30
|
const CharacterParam = Type.Integer({
|
|
26
31
|
description: "1-based UTF-16 column.",
|
package/src/types/execution.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AgentToolUpdateCallback } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { WorkspaceCodeIntelligenceSession } from "../session/session.ts";
|
|
3
|
+
import type { GraphDetails } from "../tool/code_graph/details.ts";
|
|
3
4
|
import type {
|
|
4
5
|
ContextDetails,
|
|
5
6
|
HealthDetails,
|
|
@@ -59,6 +60,7 @@ export interface CodeIntelResult {
|
|
|
59
60
|
| (CodeIntelResultDetails & { type: "context"; data: ContextDetails })
|
|
60
61
|
| (CodeIntelResultDetails & { type: "inspect"; data: InspectDetails })
|
|
61
62
|
| (CodeIntelResultDetails & { type: "search"; data: SearchDetails })
|
|
63
|
+
| (CodeIntelResultDetails & { type: "graph"; data: GraphDetails })
|
|
62
64
|
| (CodeIntelResultDetails & { type: "resolve"; data: ResolveDetails })
|
|
63
65
|
| (CodeIntelResultDetails & { type: "health"; data: HealthDetails });
|
|
64
66
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -16,6 +16,8 @@ export type {
|
|
|
16
16
|
|
|
17
17
|
// ── Detail types ────────────────────────────────────────────────────────
|
|
18
18
|
|
|
19
|
+
export type { GraphDetails, GraphSectionDetails } from "../tool/code_graph/details.ts";
|
|
20
|
+
|
|
19
21
|
export type {
|
|
20
22
|
AnchoredResolutionMetadata,
|
|
21
23
|
AnchoredResolutionSource,
|