@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
|
@@ -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
|
|
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,8 +1,6 @@
|
|
|
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
|
-
export const promptSnippet = "preview a
|
|
4
|
+
export const promptSnippet = "preview a semantic refactor";
|
|
5
5
|
|
|
6
|
-
export const promptGuidelines = [
|
|
7
|
-
"Use code_refactor_plan for preview only, then call code_refactor_apply with its planId.",
|
|
8
|
-
];
|
|
6
|
+
export const promptGuidelines: string[] = [];
|
|
@@ -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
|
|
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
|
-
export const promptSnippet = "resolve
|
|
4
|
+
export const promptSnippet = "resolve symbols or file declarations";
|
|
5
5
|
|
|
6
|
-
export const promptGuidelines = [
|
|
7
|
-
"Use code_resolve when a symbol query may be ambiguous, when later calls should share a stable target handle, or when a known file’s declarations should be enumerated.",
|
|
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
|
}
|
package/src/tool/guidance.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// Parameter mechanics (formats, enum semantics, cross-field rules) live in
|
|
7
|
-
// schemas.ts / per-tool spec.ts and are not repeated here.
|
|
1
|
+
/**
|
|
2
|
+
* Each tool owns its model-facing text. This module assembles the canonical
|
|
3
|
+
* surface map used by registration. Parameter mechanics stay in specs and
|
|
4
|
+
* shared schemas.
|
|
5
|
+
*/
|
|
8
6
|
|
|
9
7
|
import type { CodeIntelligenceToolName } from "../types/index.ts";
|
|
10
8
|
import {
|
|
@@ -48,9 +46,13 @@ import {
|
|
|
48
46
|
promptSnippet as resolveSnippet,
|
|
49
47
|
} from "./code_resolve/guidance.ts";
|
|
50
48
|
|
|
49
|
+
/** Model-facing fields registered for one public code-intelligence tool. */
|
|
51
50
|
export interface CodeIntelligenceToolPromptSurface {
|
|
51
|
+
/** Selection contract in the active provider tool definition. */
|
|
52
52
|
description: string;
|
|
53
|
+
/** One-line capability phrase in the default tool list. */
|
|
53
54
|
promptSnippet: string;
|
|
55
|
+
/** Optional active-tool routing or ordering reminders. */
|
|
54
56
|
promptGuidelines: string[];
|
|
55
57
|
}
|
|
56
58
|
|
|
@@ -59,7 +61,7 @@ export type CodeIntelligenceToolPromptSurfaceMap = Record<
|
|
|
59
61
|
CodeIntelligenceToolPromptSurface
|
|
60
62
|
>;
|
|
61
63
|
|
|
62
|
-
export const CODE_INTELLIGENCE_TOOL_PROMPT_SURFACES
|
|
64
|
+
export const CODE_INTELLIGENCE_TOOL_PROMPT_SURFACES = {
|
|
63
65
|
code_resolve: {
|
|
64
66
|
description: resolveDescription,
|
|
65
67
|
promptSnippet: resolveSnippet,
|
|
@@ -100,4 +102,4 @@ export const CODE_INTELLIGENCE_TOOL_PROMPT_SURFACES: CodeIntelligenceToolPromptS
|
|
|
100
102
|
promptSnippet: applySnippet,
|
|
101
103
|
promptGuidelines: applyGuidelines,
|
|
102
104
|
},
|
|
103
|
-
};
|
|
105
|
+
} satisfies CodeIntelligenceToolPromptSurfaceMap;
|
|
@@ -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,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Bounded raw Markdown rendering for legacy target-selection results. */
|
|
2
|
+
import { getMarkdownTheme, type Theme } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import { type Component, Markdown, Text, truncateToWidth } from "@earendil-works/pi-tui";
|
|
4
|
+
|
|
5
|
+
/** Maximum source characters rendered by the legacy candidate body. */
|
|
6
|
+
const MAX_LEGACY_SOURCE_CHARACTERS = 4096;
|
|
7
|
+
|
|
8
|
+
/** Maximum physical rows rendered by the legacy candidate body. */
|
|
9
|
+
const MAX_LEGACY_BODY_ROWS = 40;
|
|
10
|
+
|
|
11
|
+
const LEGACY_TRUNCATION_NOTICE = `Legacy candidate body truncated for display (source limit: ${MAX_LEGACY_SOURCE_CHARACTERS} characters; body limit: ${MAX_LEGACY_BODY_ROWS} rows).`;
|
|
12
|
+
|
|
13
|
+
/** Read valid Markdown text blocks without trusting persisted content shape. */
|
|
14
|
+
export function readLegacyCandidateText(value: unknown): string {
|
|
15
|
+
if (!Array.isArray(value)) return "";
|
|
16
|
+
return value
|
|
17
|
+
.flatMap((block) => {
|
|
18
|
+
if (block === null || typeof block !== "object" || Array.isArray(block)) return [];
|
|
19
|
+
const record = block as Record<string, unknown>;
|
|
20
|
+
return record.type === "text" && typeof record.text === "string" ? [record.text] : [];
|
|
21
|
+
})
|
|
22
|
+
.join("\n");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Create a bounded legacy candidate body, or null when no valid text exists. */
|
|
26
|
+
export function createLegacyCandidateBody(markdownText: string, theme: Theme): Component | null {
|
|
27
|
+
if (!markdownText.trim()) return null;
|
|
28
|
+
return new BoundedLegacyCandidateBody(markdownText, theme);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class BoundedLegacyCandidateBody implements Component {
|
|
32
|
+
private readonly markdownText: string;
|
|
33
|
+
private readonly sourceTruncated: boolean;
|
|
34
|
+
|
|
35
|
+
constructor(
|
|
36
|
+
markdownText: string,
|
|
37
|
+
private readonly theme: Theme,
|
|
38
|
+
) {
|
|
39
|
+
const sourceCharacters = Array.from(markdownText);
|
|
40
|
+
this.sourceTruncated = sourceCharacters.length > MAX_LEGACY_SOURCE_CHARACTERS;
|
|
41
|
+
this.markdownText = this.sourceTruncated
|
|
42
|
+
? sourceCharacters.slice(0, MAX_LEGACY_SOURCE_CHARACTERS).join("")
|
|
43
|
+
: markdownText;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
render(width: number): string[] {
|
|
47
|
+
const safeWidth = Math.max(1, width);
|
|
48
|
+
const markdownRows = new Markdown(this.markdownText, 0, 0, getMarkdownTheme())
|
|
49
|
+
.render(safeWidth)
|
|
50
|
+
.map((row) => truncateToWidth(row, safeWidth, ""));
|
|
51
|
+
|
|
52
|
+
if (!this.sourceTruncated && markdownRows.length <= MAX_LEGACY_BODY_ROWS) {
|
|
53
|
+
return markdownRows;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const noticeRows = new Text(this.theme.fg("warning", LEGACY_TRUNCATION_NOTICE), 0, 0).render(
|
|
57
|
+
safeWidth,
|
|
58
|
+
);
|
|
59
|
+
const markdownRowBudget = Math.max(0, MAX_LEGACY_BODY_ROWS - noticeRows.length);
|
|
60
|
+
return [...markdownRows.slice(0, markdownRowBudget), ...noticeRows].slice(
|
|
61
|
+
0,
|
|
62
|
+
MAX_LEGACY_BODY_ROWS,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
invalidate(): void {
|
|
67
|
+
// The Markdown and notice components are rebuilt for each render.
|
|
68
|
+
}
|
|
69
|
+
}
|