@mrclrchtr/supi-code-intelligence 4.10.0 → 5.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 +2 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
- package/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
- package/node_modules/@mrclrchtr/supi-core/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
- package/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
- package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
- package/node_modules/@mrclrchtr/supi-lsp/README.md +80 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
- 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/api.ts +9 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +2 -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/config/config.ts +31 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
- package/node_modules/@mrclrchtr/supi-lsp/package.json +7 -6
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +10 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +206 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +78 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +114 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +372 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +14 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +62 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +491 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +9 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +71 -11
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +206 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +365 -297
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +52 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +185 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-file-state.ts +25 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +467 -115
- package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +161 -33
- package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +10 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/config/defaults.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +45 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +38 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +79 -9
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +13 -4
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +300 -24
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +5 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +464 -96
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-refactor-provider.ts +130 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +45 -329
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/refactor-planning.ts +57 -120
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-edit-normalizer.ts +320 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +207 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/readiness.ts +72 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +151 -26
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +40 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +50 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +136 -120
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +49 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +102 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +17 -7
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
- 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/api.ts +9 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +2 -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/config/config.ts +31 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/LICENSE +21 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/README.md +258 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/babel.cjs +257 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/jiti.cjs +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-cli.mjs +34 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-hooks.mjs +124 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-native.mjs +121 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.d.mts +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.mjs +4 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-static.mjs +23 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.cjs +30 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.cts +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.mts +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.mjs +29 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/types.d.ts +420 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/package.json +146 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +6 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +0 -9
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +16 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +65 -87
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +47 -95
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-timing.ts +147 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client-lifecycle.ts +39 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +561 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-message-size.ts +24 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +452 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +4 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +12 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +4 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/imports.ts +4 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +5 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +33 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/blocking-test-bootstrap.mjs +34 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/bootstrap.mjs +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store-helpers.ts +23 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +400 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/request-control.ts +48 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-parser-helpers.ts +24 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-query-helpers.ts +43 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +421 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +116 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +201 -0
- package/package.json +5 -5
- package/src/analysis/health/diagnostics.ts +236 -24
- package/src/analysis/health/recovery.ts +6 -2
- package/src/analysis/provider.ts +58 -0
- package/src/analysis/readiness.ts +30 -9
- package/src/analysis/refactor/apply.ts +45 -1
- package/src/analysis/refactor/mutation-authority.ts +143 -0
- package/src/analysis/relations/callees.ts +9 -1
- package/src/analysis/relations/types.ts +5 -2
- package/src/analysis/search/ast-scan-timing.ts +9 -2
- package/src/analysis/search/ast-scan.ts +1 -1
- package/src/analysis/search/deadline.ts +2 -2
- package/src/analysis/search/pattern-analysis.ts +46 -32
- package/src/analysis/search/pattern.ts +12 -2
- package/src/analysis/target/anchored.ts +20 -11
- package/src/analysis/target/file.ts +18 -11
- package/src/analysis/target/identity.ts +19 -3
- package/src/analysis/target/symbol.ts +36 -15
- package/src/api.ts +4 -0
- package/src/diagnostics/evidence.ts +51 -0
- package/src/session/capability-adapter.ts +12 -3
- package/src/session/find-workflow.ts +17 -7
- package/src/session/graph/collect.ts +18 -2
- package/src/session/graph-workflow.ts +19 -12
- package/src/session/health-refresh.ts +148 -0
- package/src/session/health-types.ts +37 -15
- package/src/session/health-workflow.ts +37 -39
- package/src/session/inspect/collect.ts +20 -3
- package/src/session/inspect-workflow.ts +10 -5
- package/src/session/orientation/collect.ts +10 -1
- package/src/session/orientation/context-facts.ts +3 -1
- package/src/session/orientation/context-sections.ts +20 -7
- package/src/session/orientation/gather.ts +17 -11
- package/src/session/orientation-types.ts +2 -1
- package/src/session/orientation-workflow.ts +15 -8
- package/src/session/refactor-plans.ts +2 -0
- package/src/session/refactor-workflow.ts +59 -14
- package/src/session/session.ts +4 -1
- package/src/session/target-workflow.ts +54 -23
- package/src/session/workflow-control.ts +7 -3
- package/src/substrate/lsp/lifecycle.ts +26 -46
- package/src/substrate/lsp/maintenance.ts +199 -25
- package/src/substrate/lsp/state.ts +2 -2
- package/src/substrate/workspace-provider-host.ts +25 -3
- package/src/tool/find/execute.ts +7 -1
- package/src/tool/find/render.ts +20 -3
- package/src/tool/find/tui.ts +23 -21
- package/src/tool/graph/execute.ts +23 -3
- package/src/tool/graph/tui.ts +59 -46
- package/src/tool/health/execute.ts +7 -2
- package/src/tool/health/markdown.ts +56 -14
- package/src/tool/health/refresh-status.ts +105 -0
- package/src/tool/health/tui.ts +95 -98
- package/src/tool/infra/workflow-control.ts +8 -0
- package/src/tool/inspect/execute.ts +7 -1
- package/src/tool/inspect/tui.ts +26 -18
- package/src/tool/orientation/execute.ts +21 -3
- package/src/tool/orientation/tui.ts +51 -35
- package/src/tool/refactor-apply/execute.ts +3 -0
- package/src/tool/refactor-apply/tui.ts +43 -25
- package/src/tool/refactor-plan/execute.ts +4 -0
- package/src/tool/refactor-plan/tui.ts +33 -20
- package/src/tool/register.ts +127 -22
- package/src/tool/resolve/execute.ts +18 -1
- package/src/tool/resolve/tui.ts +42 -24
- package/src/tool/result/display.ts +107 -0
- package/src/tool/result/errors.ts +20 -17
- package/src/tool/result/find.ts +52 -8
- package/src/tool/result/graph.ts +44 -1
- package/src/tool/result/health.ts +53 -1
- package/src/tool/result/inspect.ts +113 -1
- package/src/tool/result/orientation.ts +66 -14
- package/src/tool/result/refactor.ts +36 -4
- package/src/tool/result/resolve.ts +44 -7
- package/src/tool/result/types.ts +20 -0
- package/src/types/execution.ts +18 -5
- package/src/types/index.ts +8 -1
- package/src/ui/status-command.ts +5 -3
- package/src/ui/status-overlay.ts +4 -0
- package/src/ui/tui/common.ts +108 -10
- package/src/ui/tui/display.ts +48 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime.ts +0 -351
|
@@ -1,55 +1,73 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TUI renderer for code_refactor_apply — renderCall + renderResult.
|
|
3
|
-
*
|
|
4
|
-
* Has a custom result renderer (not using renderSimpleResult) because
|
|
5
|
-
* its compact view shows success/error status rather than a count badge.
|
|
6
|
-
*/
|
|
1
|
+
/** TUI renderer for code_refactor_apply. */
|
|
7
2
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
8
|
-
import { Container, Text } from "@earendil-works/pi-tui";
|
|
3
|
+
import { Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
9
4
|
import {
|
|
5
|
+
formatCallValue,
|
|
10
6
|
type ResultOptios,
|
|
7
|
+
renderDomainError,
|
|
8
|
+
renderDomainResult,
|
|
9
|
+
renderExecutionError,
|
|
11
10
|
renderMarkdownDetail,
|
|
12
11
|
renderPartial,
|
|
12
|
+
renderToolDisplaySections,
|
|
13
|
+
renderTruncationDisclosure,
|
|
14
|
+
type ToolRendererContext,
|
|
13
15
|
type ToolResult,
|
|
14
16
|
} from "../../ui/tui/common.ts";
|
|
15
17
|
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
);
|
|
18
|
+
/** Render the compact code_refactor_apply call header. */
|
|
19
|
+
export function renderRefactorApplyCall(
|
|
20
|
+
args: unknown,
|
|
21
|
+
theme: Theme,
|
|
22
|
+
_context: ToolRendererContext | undefined,
|
|
23
|
+
): Text {
|
|
24
|
+
const params = (args ?? {}) as { planId?: unknown };
|
|
25
|
+
const planId = formatCallValue(params.planId);
|
|
26
|
+
const suffix = planId ? ` ${theme.fg("accent", planId)}` : "";
|
|
27
|
+
return new Text(`${theme.fg("toolTitle", "code_refactor_apply")}${suffix}`, 0, 0);
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
/**
|
|
27
|
-
|
|
30
|
+
/** Render code_refactor_apply progress, status, and structured result details. */
|
|
28
31
|
export function renderRefactorApplyResult(
|
|
29
32
|
result: ToolResult,
|
|
30
33
|
options: ResultOptios,
|
|
31
34
|
theme: Theme,
|
|
32
|
-
|
|
35
|
+
context: ToolRendererContext | undefined,
|
|
33
36
|
): Container | Text {
|
|
34
|
-
if (options.isPartial)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
if (options.isPartial) return renderPartial("Applying…", theme);
|
|
38
|
+
|
|
39
|
+
const executionError = renderExecutionError(context, "code_refactor_apply failed", theme);
|
|
40
|
+
if (executionError) return executionError;
|
|
41
|
+
const domainError = renderDomainError(result, theme);
|
|
42
|
+
if (domainError) return renderDomainResult(result, options, theme, domainError);
|
|
37
43
|
|
|
38
44
|
if (!options.expanded) {
|
|
39
45
|
const applied =
|
|
40
|
-
|
|
41
|
-
result.details?.
|
|
42
|
-
|
|
43
|
-
return new Text(
|
|
46
|
+
result.details?.status === "completed" ||
|
|
47
|
+
(result.details?.status === undefined && result.details?.data?.confidence === "semantic");
|
|
48
|
+
const status = new Text(
|
|
44
49
|
applied
|
|
45
50
|
? theme.fg("success", theme.bold("Plan applied"))
|
|
46
51
|
: theme.fg("error", "Refactor apply failed"),
|
|
47
52
|
0,
|
|
48
53
|
0,
|
|
49
54
|
);
|
|
55
|
+
const truncation = renderTruncationDisclosure(result, theme);
|
|
56
|
+
if (!truncation) return status;
|
|
57
|
+
const container = new Container();
|
|
58
|
+
container.addChild(status);
|
|
59
|
+
container.addChild(new Spacer(1));
|
|
60
|
+
container.addChild(truncation);
|
|
61
|
+
return container;
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
const container = new Container();
|
|
65
|
+
renderToolDisplaySections(container, result.details?.displaySections, theme);
|
|
66
|
+
const truncation = renderTruncationDisclosure(result, theme);
|
|
67
|
+
if (truncation) {
|
|
68
|
+
container.addChild(new Spacer(1));
|
|
69
|
+
container.addChild(truncation);
|
|
70
|
+
}
|
|
53
71
|
renderMarkdownDetail(container, result, theme);
|
|
54
72
|
return container;
|
|
55
73
|
}
|
|
@@ -29,6 +29,7 @@ export async function executeRefactorPlanTool(
|
|
|
29
29
|
if (outcome.kind === "invalid-input") {
|
|
30
30
|
return searchErrorResult(`**Error:** ${outcome.message}`, {
|
|
31
31
|
nextQueries: ["Fix the target or operation and retry"],
|
|
32
|
+
message: outcome.message,
|
|
32
33
|
});
|
|
33
34
|
}
|
|
34
35
|
if (outcome.kind === "ambiguous") {
|
|
@@ -40,6 +41,7 @@ export async function executeRefactorPlanTool(
|
|
|
40
41
|
.join("\n");
|
|
41
42
|
return searchErrorResult(`**Refactor ambiguous:**\n${candidates}`, {
|
|
42
43
|
nextQueries: ["Use a precise target handle or anchor"],
|
|
44
|
+
message: "The refactor target is ambiguous.",
|
|
43
45
|
});
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -49,6 +51,8 @@ export async function executeRefactorPlanTool(
|
|
|
49
51
|
details: {
|
|
50
52
|
type: "search",
|
|
51
53
|
data: assembly.details,
|
|
54
|
+
status: "completed",
|
|
55
|
+
displaySections: assembly.displaySections,
|
|
52
56
|
},
|
|
53
57
|
};
|
|
54
58
|
}
|
|
@@ -1,41 +1,54 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TUI renderer for code_refactor_plan — renderCall + renderResult.
|
|
3
|
-
*/
|
|
1
|
+
/** TUI renderer for code_refactor_plan. */
|
|
4
2
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
5
3
|
import { Text } from "@earendil-works/pi-tui";
|
|
6
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
formatCallPath,
|
|
6
|
+
formatCallValue,
|
|
7
|
+
type ResultOptios,
|
|
8
|
+
renderSimpleResult,
|
|
9
|
+
type ToolRendererContext,
|
|
10
|
+
type ToolResult,
|
|
11
|
+
} from "../../ui/tui/common.ts";
|
|
7
12
|
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
/** Render the compact code_refactor_plan call header. */
|
|
14
|
+
export function renderRefactorPlanCall(
|
|
15
|
+
args: unknown,
|
|
16
|
+
theme: Theme,
|
|
17
|
+
_context: ToolRendererContext | undefined,
|
|
18
|
+
): Text {
|
|
11
19
|
const params = (args ?? {}) as {
|
|
12
|
-
operation?: Record<string, { newName?:
|
|
13
|
-
target?: { anchor?: { file
|
|
20
|
+
operation?: Record<string, { newName?: unknown } | undefined>;
|
|
21
|
+
target?: { anchor?: { file?: unknown }; handle?: unknown };
|
|
14
22
|
};
|
|
15
23
|
|
|
16
24
|
let content = theme.fg("toolTitle", "code_refactor_plan");
|
|
17
25
|
const operation = params.operation ? Object.entries(params.operation)[0] : undefined;
|
|
18
26
|
if (operation) {
|
|
19
|
-
content += ` ${theme.fg("accent", operation[0])}`;
|
|
20
|
-
|
|
27
|
+
content += ` ${theme.fg("accent", formatCallValue(operation[0], 40) ?? "operation")}`;
|
|
28
|
+
const newName =
|
|
29
|
+
operation[1] && typeof operation[1] === "object"
|
|
30
|
+
? formatCallValue(operation[1].newName)
|
|
31
|
+
: null;
|
|
32
|
+
if (newName) content += ` ${theme.fg("muted", newName)}`;
|
|
21
33
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
|
|
35
|
+
const anchorFile = formatCallPath(params.target?.anchor?.file);
|
|
36
|
+
if (anchorFile) {
|
|
37
|
+
content += ` ${theme.fg("muted", anchorFile)}`;
|
|
38
|
+
} else {
|
|
39
|
+
const handle = formatCallValue(params.target?.handle);
|
|
40
|
+
if (handle) content += ` ${theme.fg("muted", handle)}`;
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
return new Text(content, 0, 0);
|
|
30
44
|
}
|
|
31
45
|
|
|
32
|
-
/**
|
|
33
|
-
|
|
46
|
+
/** Render code_refactor_plan progress, status, and structured result details. */
|
|
34
47
|
export function renderRefactorPlanResult(
|
|
35
48
|
result: ToolResult,
|
|
36
49
|
options: ResultOptios,
|
|
37
50
|
theme: Theme,
|
|
38
|
-
|
|
51
|
+
context: ToolRendererContext | undefined,
|
|
39
52
|
): ReturnType<typeof renderSimpleResult> {
|
|
40
|
-
return renderSimpleResult(result, options, theme, "Planning…");
|
|
53
|
+
return renderSimpleResult(result, options, theme, "Planning…", context);
|
|
41
54
|
}
|
package/src/tool/register.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { createHmac, randomBytes } from "node:crypto";
|
|
1
2
|
import { mkdtempSync, writeFileSync } from "node:fs";
|
|
2
3
|
import { tmpdir } from "node:os";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
5
6
|
import type { Component } from "@earendil-works/pi-tui";
|
|
7
|
+
import { recordDebugEvent, startDebugTimer } from "@mrclrchtr/supi-core/debug";
|
|
8
|
+
import { truncateIdentity } from "@mrclrchtr/supi-lsp/debug-telemetry";
|
|
6
9
|
import type { WorkspaceCodeIntelligenceSession } from "../session/session.ts";
|
|
10
|
+
import type { CodeIntelResult, ToolOutputTruncationDetails } from "../types/index.ts";
|
|
7
11
|
import { renderFindCall, renderFindResult } from "./find/tui.ts";
|
|
8
12
|
import { renderGraphCall, renderGraphResult } from "./graph/tui.ts";
|
|
9
13
|
import {
|
|
@@ -76,6 +80,72 @@ function getToolRenderer(name: string): ToolRenderer {
|
|
|
76
80
|
*/
|
|
77
81
|
const registeredPis = new WeakSet<object>();
|
|
78
82
|
|
|
83
|
+
type CodeOperationOutcome = "completed" | "failed" | "canceled";
|
|
84
|
+
|
|
85
|
+
function createDebugOperationId(secret: Buffer, toolCallId: string): string {
|
|
86
|
+
const digest = createHmac("sha256", secret).update(toolCallId).digest().subarray(0, 16);
|
|
87
|
+
return `op-${digest.toString("base64url")}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function recordCodeOperationBoundary(
|
|
91
|
+
category: "code-operation.start" | "code-operation.finish",
|
|
92
|
+
operationId: string,
|
|
93
|
+
tool: string,
|
|
94
|
+
options: { cwd: string; outcome?: CodeOperationOutcome },
|
|
95
|
+
): void {
|
|
96
|
+
recordDebugEvent({
|
|
97
|
+
operationId,
|
|
98
|
+
source: "code-intelligence",
|
|
99
|
+
level: "debug",
|
|
100
|
+
category,
|
|
101
|
+
message:
|
|
102
|
+
category === "code-operation.start" ? "Code operation started" : "Code operation finished",
|
|
103
|
+
cwd: truncateIdentity(options.cwd),
|
|
104
|
+
data: options.outcome ? { tool, outcome: options.outcome } : { tool },
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function recordCodeWorkflowTiming(
|
|
109
|
+
timer: ReturnType<typeof startDebugTimer>,
|
|
110
|
+
operationId: string,
|
|
111
|
+
tool: string,
|
|
112
|
+
options: { cwd: string; outcome: CodeOperationOutcome },
|
|
113
|
+
): void {
|
|
114
|
+
timer.finish(
|
|
115
|
+
{
|
|
116
|
+
operationId,
|
|
117
|
+
source: "code-intelligence",
|
|
118
|
+
level: "debug",
|
|
119
|
+
category: "workflow.timing",
|
|
120
|
+
message: "Code workflow finished",
|
|
121
|
+
cwd: truncateIdentity(options.cwd),
|
|
122
|
+
data: { tool, outcome: options.outcome },
|
|
123
|
+
},
|
|
124
|
+
"workflow",
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function withTruncationDetails(
|
|
129
|
+
details: CodeIntelResult["details"],
|
|
130
|
+
truncation: ToolOutputTruncationDetails,
|
|
131
|
+
): CodeIntelResult["details"] {
|
|
132
|
+
return details ? { ...details, truncation } : details;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function terminalCodeOperationOutcome(
|
|
136
|
+
error: unknown,
|
|
137
|
+
signal: AbortSignal | undefined,
|
|
138
|
+
): CodeOperationOutcome {
|
|
139
|
+
if (signal?.aborted) return "canceled";
|
|
140
|
+
if (
|
|
141
|
+
error instanceof Error &&
|
|
142
|
+
(error.name === "AbortError" || error.name === "CodeRequestDeadlineError")
|
|
143
|
+
) {
|
|
144
|
+
return "canceled";
|
|
145
|
+
}
|
|
146
|
+
return "failed";
|
|
147
|
+
}
|
|
148
|
+
|
|
79
149
|
export function registerCodeIntelligenceTools(
|
|
80
150
|
pi: ExtensionAPI,
|
|
81
151
|
getOrCreateSession: (cwd: string) => WorkspaceCodeIntelligenceSession,
|
|
@@ -89,6 +159,7 @@ export function registerCodeIntelligenceTools(
|
|
|
89
159
|
// ponytail: WeakSet on pi identity; getAllTools() is not callable during load.
|
|
90
160
|
if (registeredPis.has(pi)) return;
|
|
91
161
|
registeredPis.add(pi);
|
|
162
|
+
const operationSecret = randomBytes(32);
|
|
92
163
|
|
|
93
164
|
for (const spec of specs) {
|
|
94
165
|
const surface = promptSurfaces[spec.name];
|
|
@@ -100,33 +171,67 @@ export function registerCodeIntelligenceTools(
|
|
|
100
171
|
promptGuidelines: surface.promptGuidelines,
|
|
101
172
|
parameters: spec.parameters,
|
|
102
173
|
// biome-ignore lint/complexity/useMaxParams: pi ToolDefinition.execute signature
|
|
103
|
-
execute: async (
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
174
|
+
execute: async (toolCallId, params, signal, onUpdate, ctx: ExtensionContext) => {
|
|
175
|
+
const operationId = createDebugOperationId(operationSecret, toolCallId);
|
|
176
|
+
const workflowTimer = startDebugTimer();
|
|
177
|
+
recordCodeOperationBoundary("code-operation.start", operationId, spec.name, {
|
|
107
178
|
cwd: ctx.cwd,
|
|
108
|
-
signal,
|
|
109
|
-
onUpdate,
|
|
110
|
-
session,
|
|
111
|
-
});
|
|
112
|
-
const { text, truncated } = truncateToolContent(content, {
|
|
113
|
-
maxLines: spec.maxLines,
|
|
114
|
-
maxBytes: spec.maxBytes,
|
|
115
179
|
});
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
180
|
+
try {
|
|
181
|
+
const session = getOrCreateSession(ctx.cwd);
|
|
182
|
+
session.setProjectTrusted(ctx.isProjectTrusted());
|
|
183
|
+
const { content, details } = await spec.run(params, {
|
|
184
|
+
cwd: ctx.cwd,
|
|
185
|
+
operationId,
|
|
186
|
+
signal,
|
|
187
|
+
onUpdate,
|
|
188
|
+
session,
|
|
189
|
+
});
|
|
190
|
+
recordCodeWorkflowTiming(workflowTimer, operationId, spec.name, {
|
|
191
|
+
cwd: ctx.cwd,
|
|
192
|
+
outcome: "completed",
|
|
193
|
+
});
|
|
194
|
+
const { text, truncated } = truncateToolContent(content, {
|
|
195
|
+
maxLines: spec.maxLines,
|
|
196
|
+
maxBytes: spec.maxBytes,
|
|
197
|
+
});
|
|
198
|
+
if (truncated && content.length > 0) {
|
|
199
|
+
const dir = mkdtempSync(join(tmpdir(), "supi-ci-"));
|
|
200
|
+
const spillPath = join(dir, `${spec.name}-output.md`);
|
|
201
|
+
writeFileSync(spillPath, content, "utf-8");
|
|
202
|
+
const notice = `\n_Full output saved to: \`${spillPath}\`_`;
|
|
203
|
+
recordCodeOperationBoundary("code-operation.finish", operationId, spec.name, {
|
|
204
|
+
cwd: ctx.cwd,
|
|
205
|
+
outcome: "completed",
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
content: [{ type: "text" as const, text: text + notice }],
|
|
209
|
+
details: withTruncationDetails(details, {
|
|
210
|
+
truncated: true,
|
|
211
|
+
fullOutputPath: spillPath,
|
|
212
|
+
}),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
recordCodeOperationBoundary("code-operation.finish", operationId, spec.name, {
|
|
216
|
+
cwd: ctx.cwd,
|
|
217
|
+
outcome: "completed",
|
|
218
|
+
});
|
|
121
219
|
return {
|
|
122
|
-
content: [{ type: "text" as const, text
|
|
123
|
-
details,
|
|
220
|
+
content: [{ type: "text" as const, text }],
|
|
221
|
+
details: withTruncationDetails(details, { truncated: false }),
|
|
124
222
|
};
|
|
223
|
+
} catch (error) {
|
|
224
|
+
const outcome = terminalCodeOperationOutcome(error, signal);
|
|
225
|
+
recordCodeWorkflowTiming(workflowTimer, operationId, spec.name, {
|
|
226
|
+
cwd: ctx.cwd,
|
|
227
|
+
outcome,
|
|
228
|
+
});
|
|
229
|
+
recordCodeOperationBoundary("code-operation.finish", operationId, spec.name, {
|
|
230
|
+
cwd: ctx.cwd,
|
|
231
|
+
outcome,
|
|
232
|
+
});
|
|
233
|
+
throw error;
|
|
125
234
|
}
|
|
126
|
-
return {
|
|
127
|
-
content: [{ type: "text" as const, text }],
|
|
128
|
-
details,
|
|
129
|
-
};
|
|
130
235
|
},
|
|
131
236
|
...getToolRenderer(spec.name),
|
|
132
237
|
});
|
|
@@ -31,6 +31,23 @@ export async function executeResolveTool(
|
|
|
31
31
|
|
|
32
32
|
return {
|
|
33
33
|
content,
|
|
34
|
-
details: {
|
|
34
|
+
details: {
|
|
35
|
+
type: "resolve",
|
|
36
|
+
data: assembly.details,
|
|
37
|
+
status:
|
|
38
|
+
outcome.kind === "resolved" || outcome.kind === "target-group"
|
|
39
|
+
? "completed"
|
|
40
|
+
: outcome.kind === "disambiguation" || outcome.kind === "kind-mismatch"
|
|
41
|
+
? "disambiguation"
|
|
42
|
+
: "invalid-input",
|
|
43
|
+
...(outcome.kind === "invalid-input"
|
|
44
|
+
? { message: outcome.message }
|
|
45
|
+
: outcome.kind === "disambiguation"
|
|
46
|
+
? { message: "Multiple target matches require one candidate." }
|
|
47
|
+
: outcome.kind === "kind-mismatch"
|
|
48
|
+
? { message: `No target matched provider kind ${outcome.requestedKind}.` }
|
|
49
|
+
: {}),
|
|
50
|
+
displaySections: assembly.displaySections,
|
|
51
|
+
},
|
|
35
52
|
};
|
|
36
53
|
}
|
package/src/tool/resolve/tui.ts
CHANGED
|
@@ -1,42 +1,60 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TUI renderer for code_resolve — renderCall + renderResult.
|
|
3
|
-
*/
|
|
1
|
+
/** TUI renderer for code_resolve. */
|
|
4
2
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
5
3
|
import { Text } from "@earendil-works/pi-tui";
|
|
6
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
formatCallPath,
|
|
6
|
+
formatCallValue,
|
|
7
|
+
type ResultOptios,
|
|
8
|
+
renderSimpleResult,
|
|
9
|
+
type ToolRendererContext,
|
|
10
|
+
type ToolResult,
|
|
11
|
+
} from "../../ui/tui/common.ts";
|
|
7
12
|
import type { CodeResolveToolParams } from "./execute.ts";
|
|
8
13
|
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
/** Render the compact code_resolve call header. */
|
|
15
|
+
export function renderResolveCall(
|
|
16
|
+
args: unknown,
|
|
17
|
+
theme: Theme,
|
|
18
|
+
_context: ToolRendererContext | undefined,
|
|
19
|
+
): Text {
|
|
20
|
+
const params = (args ?? {}) as Partial<CodeResolveToolParams>;
|
|
14
21
|
let content = theme.fg("toolTitle", "code_resolve");
|
|
22
|
+
const target = params.target;
|
|
23
|
+
if (!target || typeof target !== "object") return new Text(content, 0, 0);
|
|
15
24
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} else
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
content += ` ${theme.fg("accent", file)}${theme.fg("warning", `:${point.line}`)}`;
|
|
25
|
-
} else if ("file" in params.target) {
|
|
26
|
-
const file = params.target.file.split("/").pop() ?? params.target.file;
|
|
27
|
-
content += ` ${theme.fg("accent", file)}`;
|
|
25
|
+
const targetRecord = target as unknown as Record<string, unknown>;
|
|
26
|
+
if (targetRecord.symbol && typeof targetRecord.symbol === "object") {
|
|
27
|
+
content += renderResolveSymbol(targetRecord.symbol, theme);
|
|
28
|
+
} else if (targetRecord.anchor && typeof targetRecord.anchor === "object") {
|
|
29
|
+
content += renderResolveAnchor(targetRecord.anchor, theme);
|
|
30
|
+
} else {
|
|
31
|
+
const file = formatCallPath(targetRecord.file);
|
|
32
|
+
if (file) content += ` ${theme.fg("accent", file)}`;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
return new Text(content, 0, 0);
|
|
31
36
|
}
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
function renderResolveSymbol(value: object, theme: Theme): string {
|
|
39
|
+
const symbol = value as { query?: unknown; symbolKind?: unknown };
|
|
40
|
+
const query = formatCallValue(symbol.query);
|
|
41
|
+
const kind = formatCallValue(symbol.symbolKind, 30);
|
|
42
|
+
return `${query ? ` ${theme.fg("accent", query)}` : ""}${kind ? theme.fg("dim", ` [${kind}]`) : ""}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function renderResolveAnchor(value: object, theme: Theme): string {
|
|
46
|
+
const point = value as { file?: unknown; line?: unknown };
|
|
47
|
+
const file = formatCallPath(point.file);
|
|
48
|
+
const line = typeof point.line === "number" ? `:${point.line}` : "";
|
|
49
|
+
return file ? ` ${theme.fg("accent", file)}${theme.fg("warning", line)}` : "";
|
|
50
|
+
}
|
|
34
51
|
|
|
52
|
+
/** Render code_resolve progress, status, and structured result details. */
|
|
35
53
|
export function renderResolveResult(
|
|
36
54
|
result: ToolResult,
|
|
37
55
|
options: ResultOptios,
|
|
38
56
|
theme: Theme,
|
|
39
|
-
|
|
57
|
+
context: ToolRendererContext | undefined,
|
|
40
58
|
): ReturnType<typeof renderSimpleResult> {
|
|
41
|
-
return renderSimpleResult(result, options, theme, "Resolving…");
|
|
59
|
+
return renderSimpleResult(result, options, theme, "Resolving…", context);
|
|
42
60
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { ToolDisplaySection } from "./types.ts";
|
|
2
|
+
|
|
3
|
+
/** Maximum number of rows shown for one expanded TUI section. */
|
|
4
|
+
export const MAX_TUI_DISPLAY_ITEMS = 20;
|
|
5
|
+
|
|
6
|
+
/** Maximum visible characters kept in one structured TUI row. */
|
|
7
|
+
export const MAX_TUI_DISPLAY_LINE_LENGTH = 240;
|
|
8
|
+
|
|
9
|
+
/** Inputs for one bounded structured TUI section. */
|
|
10
|
+
export interface ToolDisplaySectionInput<T> {
|
|
11
|
+
key: string;
|
|
12
|
+
title: string;
|
|
13
|
+
items: readonly T[];
|
|
14
|
+
format: (item: T) => string;
|
|
15
|
+
totalCount?: number | null;
|
|
16
|
+
omittedCount?: number | null;
|
|
17
|
+
partialReason?: string | null;
|
|
18
|
+
maxItems?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Build a bounded, serializable TUI section from collected facts. */
|
|
22
|
+
export function createToolDisplaySection<T>(input: ToolDisplaySectionInput<T>): ToolDisplaySection {
|
|
23
|
+
const maxItems = Math.max(0, input.maxItems ?? MAX_TUI_DISPLAY_ITEMS);
|
|
24
|
+
const items = input.items.slice(0, maxItems);
|
|
25
|
+
const lines = items.map((item) => truncateDisplayText(input.format(item)));
|
|
26
|
+
const displayOmittedCount = Math.max(0, input.items.length - items.length);
|
|
27
|
+
let totalCount: number | null;
|
|
28
|
+
if (input.totalCount === undefined) totalCount = input.items.length;
|
|
29
|
+
else totalCount = input.totalCount;
|
|
30
|
+
const omittedCount =
|
|
31
|
+
totalCount === null
|
|
32
|
+
? input.omittedCount === null || input.omittedCount === undefined
|
|
33
|
+
? displayOmittedCount || null
|
|
34
|
+
: input.omittedCount + displayOmittedCount
|
|
35
|
+
: Math.max(0, totalCount - lines.length);
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
key: input.key,
|
|
39
|
+
title: input.title,
|
|
40
|
+
lines,
|
|
41
|
+
shownCount: lines.length,
|
|
42
|
+
totalCount,
|
|
43
|
+
omittedCount,
|
|
44
|
+
partialReason: input.partialReason ?? null,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Keep structured TUI rows readable without parsing or emitting Markdown. */
|
|
49
|
+
export function truncateDisplayText(
|
|
50
|
+
value: string,
|
|
51
|
+
maxLength = MAX_TUI_DISPLAY_LINE_LENGTH,
|
|
52
|
+
): string {
|
|
53
|
+
const limit = Math.max(1, maxLength);
|
|
54
|
+
return value
|
|
55
|
+
.split("\n")
|
|
56
|
+
.map((line) => {
|
|
57
|
+
if (line.length <= limit) return line;
|
|
58
|
+
return `${line.slice(0, Math.max(0, limit - 1))}…`;
|
|
59
|
+
})
|
|
60
|
+
.join("\n");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Read valid structured TUI sections from persisted tool details. */
|
|
64
|
+
export function readToolDisplaySections(value: unknown): ToolDisplaySection[] {
|
|
65
|
+
if (!Array.isArray(value)) return [];
|
|
66
|
+
return value.flatMap((entry) => {
|
|
67
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return [];
|
|
68
|
+
const record = entry as Record<string, unknown>;
|
|
69
|
+
if (
|
|
70
|
+
typeof record.key !== "string" ||
|
|
71
|
+
typeof record.title !== "string" ||
|
|
72
|
+
!Array.isArray(record.lines) ||
|
|
73
|
+
!record.lines.every((line) => typeof line === "string") ||
|
|
74
|
+
!isCount(record.shownCount) ||
|
|
75
|
+
!isNullableCount(record.totalCount) ||
|
|
76
|
+
!isNullableCount(record.omittedCount) ||
|
|
77
|
+
!isNullableString(record.partialReason)
|
|
78
|
+
) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
return [
|
|
82
|
+
{
|
|
83
|
+
key: record.key,
|
|
84
|
+
title: record.title,
|
|
85
|
+
lines: record.lines
|
|
86
|
+
.slice(0, MAX_TUI_DISPLAY_ITEMS)
|
|
87
|
+
.map((line) => truncateDisplayText(line)),
|
|
88
|
+
shownCount: record.shownCount,
|
|
89
|
+
totalCount: record.totalCount,
|
|
90
|
+
omittedCount: record.omittedCount,
|
|
91
|
+
partialReason: record.partialReason,
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isCount(value: unknown): value is number {
|
|
98
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function isNullableCount(value: unknown): value is number | null {
|
|
102
|
+
return value === null || isCount(value);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function isNullableString(value: unknown): value is string | null {
|
|
106
|
+
return value === null || typeof value === "string";
|
|
107
|
+
}
|