@gaunt-sloth/core 2.0.0-alpha.3 → 2.0.0-alpha.31
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 +52 -20
- package/dist/config/colour.d.ts +38 -0
- package/dist/config/colour.js +36 -0
- package/dist/config/colour.js.map +1 -0
- package/dist/config/defaults.d.ts +84 -0
- package/dist/config/defaults.js +99 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/filesystem-tools.d.ts +41 -0
- package/dist/config/filesystem-tools.js +56 -0
- package/dist/config/filesystem-tools.js.map +1 -0
- package/dist/config/jsonc.d.ts +12 -0
- package/dist/config/jsonc.js +41 -0
- package/dist/config/jsonc.js.map +1 -0
- package/dist/config/loader.d.ts +246 -0
- package/dist/config/loader.js +1321 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/mouse.d.ts +50 -0
- package/dist/config/mouse.js +44 -0
- package/dist/config/mouse.js.map +1 -0
- package/dist/config/profiles.d.ts +68 -0
- package/dist/config/profiles.js +93 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/providerKeys.d.ts +69 -0
- package/dist/config/providerKeys.js +69 -0
- package/dist/config/providerKeys.js.map +1 -0
- package/dist/config/schema.d.ts +2999 -0
- package/dist/config/schema.js +1519 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/shell-policy.d.ts +896 -0
- package/dist/config/shell-policy.js +750 -0
- package/dist/config/shell-policy.js.map +1 -0
- package/dist/config/tool-descriptions.d.ts +211 -0
- package/dist/config/tool-descriptions.js +272 -0
- package/dist/config/tool-descriptions.js.map +1 -0
- package/dist/config/types.d.ts +760 -0
- package/dist/config/types.js +13 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config.d.ts +34 -827
- package/dist/config.js +25 -657
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +46 -0
- package/dist/constants.js +46 -0
- package/dist/constants.js.map +1 -1
- package/dist/core/GthAbstractAgent.d.ts +135 -2
- package/dist/core/GthAbstractAgent.js +496 -30
- package/dist/core/GthAbstractAgent.js.map +1 -1
- package/dist/core/GthAgentRunner.d.ts +568 -54
- package/dist/core/GthAgentRunner.js +1537 -136
- package/dist/core/GthAgentRunner.js.map +1 -1
- package/dist/core/GthLangChainAgent.d.ts +115 -0
- package/dist/core/GthLangChainAgent.js +644 -17
- package/dist/core/GthLangChainAgent.js.map +1 -1
- package/dist/core/approvals/annotations.d.ts +122 -0
- package/dist/core/approvals/annotations.js +137 -0
- package/dist/core/approvals/annotations.js.map +1 -0
- package/dist/core/approvals/grants.d.ts +216 -0
- package/dist/core/approvals/grants.js +469 -0
- package/dist/core/approvals/grants.js.map +1 -0
- package/dist/core/approvals/matcher.d.ts +202 -0
- package/dist/core/approvals/matcher.js +267 -0
- package/dist/core/approvals/matcher.js.map +1 -0
- package/dist/core/approvals/mcpSubjects.d.ts +40 -0
- package/dist/core/approvals/mcpSubjects.js +99 -0
- package/dist/core/approvals/mcpSubjects.js.map +1 -0
- package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
- package/dist/core/approvals/toolAnnotationSources.js +277 -0
- package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
- package/dist/core/approvals/toolHost.d.ts +46 -0
- package/dist/core/approvals/toolHost.js +108 -0
- package/dist/core/approvals/toolHost.js.map +1 -0
- package/dist/core/debugCapture.d.ts +75 -0
- package/dist/core/debugCapture.js +101 -0
- package/dist/core/debugCapture.js.map +1 -0
- package/dist/core/gthLeanAgentFactory.d.ts +9 -0
- package/dist/core/gthLeanAgentFactory.js +10 -0
- package/dist/core/gthLeanAgentFactory.js.map +1 -0
- package/dist/core/launchBanner.d.ts +120 -0
- package/dist/core/launchBanner.js +418 -0
- package/dist/core/launchBanner.js.map +1 -0
- package/dist/core/plainToolIndication.d.ts +15 -0
- package/dist/core/plainToolIndication.js +174 -0
- package/dist/core/plainToolIndication.js.map +1 -0
- package/dist/core/reasoningBlocks.d.ts +60 -0
- package/dist/core/reasoningBlocks.js +98 -0
- package/dist/core/reasoningBlocks.js.map +1 -0
- package/dist/core/refusal.d.ts +53 -0
- package/dist/core/refusal.js +133 -0
- package/dist/core/refusal.js.map +1 -0
- package/dist/core/runStats.d.ts +52 -0
- package/dist/core/runStats.js +118 -0
- package/dist/core/runStats.js.map +1 -0
- package/dist/core/shell/ShellCommandFailedError.d.ts +54 -0
- package/dist/core/shell/ShellCommandFailedError.js +68 -0
- package/dist/core/shell/ShellCommandFailedError.js.map +1 -0
- package/dist/core/shell/abstention.d.ts +88 -0
- package/dist/core/shell/abstention.js +184 -0
- package/dist/core/shell/abstention.js.map +1 -0
- package/dist/core/shell/approvalCapture.d.ts +271 -0
- package/dist/core/shell/approvalCapture.js +108 -0
- package/dist/core/shell/approvalCapture.js.map +1 -0
- package/dist/core/shell/approvalStop.d.ts +84 -0
- package/dist/core/shell/approvalStop.js +119 -0
- package/dist/core/shell/approvalStop.js.map +1 -0
- package/dist/core/shell/arity.d.ts +6 -0
- package/dist/core/shell/arity.js +20 -6
- package/dist/core/shell/arity.js.map +1 -1
- package/dist/core/shell/denylist.d.ts +11 -0
- package/dist/core/shell/denylist.js +37 -0
- package/dist/core/shell/denylist.js.map +1 -0
- package/dist/core/shell/escalationSeverity.d.ts +141 -0
- package/dist/core/shell/escalationSeverity.js +89 -0
- package/dist/core/shell/escalationSeverity.js.map +1 -0
- package/dist/core/shell/framing.d.ts +190 -0
- package/dist/core/shell/framing.js +633 -0
- package/dist/core/shell/framing.js.map +1 -0
- package/dist/core/shell/hardline.d.ts +81 -0
- package/dist/core/shell/hardline.js +607 -0
- package/dist/core/shell/hardline.js.map +1 -0
- package/dist/core/shell/negotiation.d.ts +249 -0
- package/dist/core/shell/negotiation.js +355 -0
- package/dist/core/shell/negotiation.js.map +1 -0
- package/dist/core/shell/normalize.d.ts +44 -4
- package/dist/core/shell/normalize.js +61 -7
- package/dist/core/shell/normalize.js.map +1 -1
- package/dist/core/shell/openWorld.d.ts +263 -0
- package/dist/core/shell/openWorld.js +1188 -0
- package/dist/core/shell/openWorld.js.map +1 -0
- package/dist/core/shell/rater.d.ts +935 -0
- package/dist/core/shell/rater.js +1473 -0
- package/dist/core/shell/rater.js.map +1 -0
- package/dist/core/shell/raterModel.d.ts +41 -0
- package/dist/core/shell/raterModel.js +51 -0
- package/dist/core/shell/raterModel.js.map +1 -0
- package/dist/core/shell/rejection.d.ts +69 -0
- package/dist/core/shell/rejection.js +38 -0
- package/dist/core/shell/rejection.js.map +1 -0
- package/dist/core/toolCallRepair/grammar.d.ts +41 -0
- package/dist/core/toolCallRepair/grammar.js +116 -0
- package/dist/core/toolCallRepair/grammar.js.map +1 -0
- package/dist/core/toolCallRepair/index.d.ts +2 -0
- package/dist/core/toolCallRepair/index.js +7 -0
- package/dist/core/toolCallRepair/index.js.map +1 -0
- package/dist/core/toolCallRepair/payload.d.ts +36 -0
- package/dist/core/toolCallRepair/payload.js +341 -0
- package/dist/core/toolCallRepair/payload.js.map +1 -0
- package/dist/core/toolCallRepair/promote.d.ts +45 -0
- package/dist/core/toolCallRepair/promote.js +90 -0
- package/dist/core/toolCallRepair/promote.js.map +1 -0
- package/dist/core/toolDisplay.d.ts +123 -0
- package/dist/core/toolDisplay.js +451 -0
- package/dist/core/toolDisplay.js.map +1 -0
- package/dist/core/toolOutputChannel.d.ts +95 -0
- package/dist/core/toolOutputChannel.js +165 -0
- package/dist/core/toolOutputChannel.js.map +1 -0
- package/dist/core/types.d.ts +294 -12
- package/dist/core/types.js.map +1 -1
- package/dist/history/historyFormat.d.ts +28 -0
- package/dist/history/historyFormat.js +127 -0
- package/dist/history/historyFormat.js.map +1 -0
- package/dist/history/historyStore.d.ts +198 -0
- package/dist/history/historyStore.js +482 -0
- package/dist/history/historyStore.js.map +1 -0
- package/dist/history/recordSession.d.ts +37 -0
- package/dist/history/recordSession.js +56 -0
- package/dist/history/recordSession.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +5 -10
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/deepseek.d.ts +1 -1
- package/dist/providers/deepseek.js +5 -10
- package/dist/providers/deepseek.js.map +1 -1
- package/dist/providers/geminiSchemaSanitizer.d.ts +55 -0
- package/dist/providers/geminiSchemaSanitizer.js +347 -0
- package/dist/providers/geminiSchemaSanitizer.js.map +1 -0
- package/dist/providers/geminiThinking.d.ts +52 -0
- package/dist/providers/geminiThinking.js +72 -0
- package/dist/providers/geminiThinking.js.map +1 -0
- package/dist/providers/google-genai.d.ts +1 -1
- package/dist/providers/google-genai.js +12 -11
- package/dist/providers/google-genai.js.map +1 -1
- package/dist/providers/groq.d.ts +1 -1
- package/dist/providers/groq.js +5 -10
- package/dist/providers/groq.js.map +1 -1
- package/dist/providers/huggingface.d.ts +25 -0
- package/dist/providers/huggingface.js +69 -0
- package/dist/providers/huggingface.js.map +1 -0
- package/dist/providers/modelCatalog.d.ts +109 -0
- package/dist/providers/modelCatalog.js +245 -0
- package/dist/providers/modelCatalog.js.map +1 -0
- package/dist/providers/modelDiscovery.d.ts +153 -6
- package/dist/providers/modelDiscovery.js +295 -41
- package/dist/providers/modelDiscovery.js.map +1 -1
- package/dist/providers/ollama.d.ts +19 -5
- package/dist/providers/ollama.js +60 -52
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +39 -10
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +4 -5
- package/dist/providers/openrouter.js +20 -35
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/vertexai.d.ts +1 -1
- package/dist/providers/vertexai.js +12 -11
- package/dist/providers/vertexai.js.map +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +5 -10
- package/dist/providers/xai.js.map +1 -1
- package/dist/runtime/askStructured.d.ts +105 -0
- package/dist/runtime/askStructured.js +120 -0
- package/dist/runtime/askStructured.js.map +1 -0
- package/dist/runtime/conversation.d.ts +60 -0
- package/dist/runtime/conversation.js +151 -0
- package/dist/runtime/conversation.js.map +1 -0
- package/dist/runtime/singleShot.d.ts +25 -5
- package/dist/runtime/singleShot.js +95 -36
- package/dist/runtime/singleShot.js.map +1 -1
- package/dist/runtime/structuredOutput.d.ts +104 -0
- package/dist/runtime/structuredOutput.js +393 -0
- package/dist/runtime/structuredOutput.js.map +1 -0
- package/dist/utils/ProgressIndicator.d.ts +21 -0
- package/dist/utils/ProgressIndicator.js +30 -3
- package/dist/utils/ProgressIndicator.js.map +1 -1
- package/dist/utils/aiignoreUtils.js.map +1 -1
- package/dist/utils/binaryOutputUtils.js.map +1 -1
- package/dist/utils/consoleUtils.d.ts +52 -0
- package/dist/utils/consoleUtils.js +72 -2
- package/dist/utils/consoleUtils.js.map +1 -1
- package/dist/utils/crashHandler.d.ts +87 -0
- package/dist/utils/crashHandler.js +128 -0
- package/dist/utils/crashHandler.js.map +1 -0
- package/dist/utils/debugDump.d.ts +134 -0
- package/dist/utils/debugDump.js +381 -0
- package/dist/utils/debugDump.js.map +1 -0
- package/dist/utils/debugUtils.d.ts +13 -4
- package/dist/utils/debugUtils.js +36 -13
- package/dist/utils/debugUtils.js.map +1 -1
- package/dist/utils/displayWidth.d.ts +53 -0
- package/dist/utils/displayWidth.js +195 -0
- package/dist/utils/displayWidth.js.map +1 -0
- package/dist/utils/fileUtils.d.ts +24 -2
- package/dist/utils/fileUtils.js +54 -12
- package/dist/utils/fileUtils.js.map +1 -1
- package/dist/utils/llmUtils.d.ts +39 -8
- package/dist/utils/llmUtils.js +76 -8
- package/dist/utils/llmUtils.js.map +1 -1
- package/dist/utils/redactSecrets.d.ts +63 -0
- package/dist/utils/redactSecrets.js +286 -0
- package/dist/utils/redactSecrets.js.map +1 -0
- package/dist/utils/systemPromptNotes.d.ts +225 -0
- package/dist/utils/systemPromptNotes.js +340 -0
- package/dist/utils/systemPromptNotes.js.map +1 -0
- package/dist/utils/systemUtils.d.ts +49 -1
- package/dist/utils/systemUtils.js +67 -3
- package/dist/utils/systemUtils.js.map +1 -1
- package/dist/utils/toolMatching.d.ts +30 -0
- package/dist/utils/toolMatching.js +44 -0
- package/dist/utils/toolMatching.js.map +1 -0
- package/dist/utils/untrustedText.d.ts +66 -0
- package/dist/utils/untrustedText.js +80 -0
- package/dist/utils/untrustedText.js.map +1 -0
- package/package.json +22 -6
- package/schema/gsloth-config.schema.json +3134 -0
- package/dist/core/shell/allowlist.d.ts +0 -75
- package/dist/core/shell/allowlist.js +0 -187
- package/dist/core/shell/allowlist.js.map +0 -1
- package/dist/core/shell/judge.d.ts +0 -161
- package/dist/core/shell/judge.js +0 -261
- package/dist/core/shell/judge.js.map +0 -1
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module toolDisplay
|
|
3
|
+
* TUI-C30 — the surface-agnostic tool-display registry: how a tool CALL is summarised
|
|
4
|
+
* (`name(arg=val, …)`) and how its OUTPUT is previewed (up to {@link TOOL_OUTPUT_PREVIEW_LINES}
|
|
5
|
+
* greyed lines, diff-coloured for `write_file`/`edit_file`), shared by BOTH render surfaces:
|
|
6
|
+
*
|
|
7
|
+
* - the Ink TUI's `ToolCallPanel` (`packages/app/src/tui/components/LiveTurn.tsx`), and
|
|
8
|
+
* - the plain/readline (`--no-tui`, piped, single-shot) surface
|
|
9
|
+
* (`core/plainToolIndication.ts`).
|
|
10
|
+
*
|
|
11
|
+
* Everything here is PURE STRINGS plus a style tag per line ({@link ToolDisplayLine}), so the
|
|
12
|
+
* module knows nothing about Ink or ANSI: the TUI maps styles to `<Text>` props and the plain
|
|
13
|
+
* surface maps them to raw ANSI via {@link renderToolLineAnsi}. The shape mirrors vue-ui's
|
|
14
|
+
* PLAT-17 `toolDisplay.ts` (name → glyph + which args to summarise + optional result formatter,
|
|
15
|
+
* with a generic fallback — cf. openclaw's `TOOL_DISPLAY_CONFIG` and opencode's
|
|
16
|
+
* `collapseToolOutput`) so the surfaces stay analogous without sharing code.
|
|
17
|
+
*
|
|
18
|
+
* Design rules (from the node spec):
|
|
19
|
+
* - **One canonical output cap: {@link TOOL_OUTPUT_PREVIEW_LINES} lines** (and a per-line char
|
|
20
|
+
* cap), applied by {@link capToolDisplayLines} with a `… (+N more lines)` overflow marker.
|
|
21
|
+
* This is a RENDER-time cap only — the model-facing `OutputBuffer`/EXT-9 head-tail caps are a
|
|
22
|
+
* separate layer beneath it and are never touched here.
|
|
23
|
+
* - **Secret redaction reuses the GS2-47 `redactSecrets` lineage** (literal env/config secrets +
|
|
24
|
+
* provider key patterns) — no new redactor. Applied to the params summary and every
|
|
25
|
+
* preview/body line, fail-safe (redact MORE on any error, never leak).
|
|
26
|
+
* - **`write_file`/`edit_file` render the change as a diff derived from the tool's ARGS**
|
|
27
|
+
* (added = `added` style/green, removed = `removed` style/red); monochrome keeps the `+`/`-`
|
|
28
|
+
* prefixes so the diff still reads without colour (DL-7 graceful degradation).
|
|
29
|
+
*/
|
|
30
|
+
import { displayWidth, sliceToWidth } from '#src/utils/displayWidth.js';
|
|
31
|
+
import { collectSecretValues, redactText } from '#src/utils/redactSecrets.js';
|
|
32
|
+
import { env } from '#src/utils/systemUtils.js';
|
|
33
|
+
/** The single canonical output-preview cap (lines). No other preview length exists anywhere. */
|
|
34
|
+
export const TOOL_OUTPUT_PREVIEW_LINES = 10;
|
|
35
|
+
/**
|
|
36
|
+
* Per-line cap for preview lines, in terminal COLUMNS (a one-line minified bundle must not flood a
|
|
37
|
+
* row). The `CHARS` in the name is historical; every cap here is a column budget, because a
|
|
38
|
+
* character count is not a width — see `#src/utils/displayWidth.js`.
|
|
39
|
+
*/
|
|
40
|
+
export const TOOL_PREVIEW_LINE_MAX_CHARS = 200;
|
|
41
|
+
/** Per-value cap inside a params summary, in terminal COLUMNS. */
|
|
42
|
+
export const TOOL_PARAM_VALUE_MAX_CHARS = 48;
|
|
43
|
+
/** Whole params-summary cap (everything inside the parentheses), in terminal COLUMNS. */
|
|
44
|
+
export const TOOL_SUMMARY_MAX_CHARS = 120;
|
|
45
|
+
/** The overflow/truncation marker used everywhere in this module. */
|
|
46
|
+
export const ELLIPSIS = '…';
|
|
47
|
+
/**
|
|
48
|
+
* Columns {@link ELLIPSIS} itself occupies, which every truncator has to reserve out of its budget
|
|
49
|
+
* before slicing. Derived rather than written as `1` so it stays true of whatever marker is used.
|
|
50
|
+
*/
|
|
51
|
+
export const ELLIPSIS_WIDTH = displayWidth(ELLIPSIS);
|
|
52
|
+
const FALLBACK_GLYPH = '⚙';
|
|
53
|
+
const FILE_GLYPH = '📁';
|
|
54
|
+
const SHELL_GLYPH = '🔧';
|
|
55
|
+
/* ------------------------------------------------------------------------- *
|
|
56
|
+
* Small shared helpers *
|
|
57
|
+
* ------------------------------------------------------------------------- */
|
|
58
|
+
/**
|
|
59
|
+
* Tolerant parse of a (possibly partial) streamed args JSON. Mirrors the view-model's
|
|
60
|
+
* defensive posture: a half-streamed or malformed buffer never throws — it returns `null`.
|
|
61
|
+
*/
|
|
62
|
+
export function parseToolArgsSafe(argsText) {
|
|
63
|
+
if (!argsText || !argsText.trim())
|
|
64
|
+
return null;
|
|
65
|
+
try {
|
|
66
|
+
const parsed = JSON.parse(argsText);
|
|
67
|
+
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
68
|
+
return parsed;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The live gth config, registered once per run so {@link getDefaultSecrets} can harvest INLINE
|
|
78
|
+
* config secrets (a pasted `apiKey`/`token` value) via the GS2-47 config walk — not only the
|
|
79
|
+
* env-derived literals. `GthAgentRunner.init` sets this next to the crash-context hand-off, so
|
|
80
|
+
* both render surfaces (the plain observer and the Ink TUI) see it. `undefined` (no config yet)
|
|
81
|
+
* degrades to env-only collection + the provider patterns, exactly as before.
|
|
82
|
+
*/
|
|
83
|
+
let displayConfig = undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Register the live config for inline-secret collection (TUI-C32 residual a). Resets the secret
|
|
86
|
+
* cache so the next {@link getDefaultSecrets} recomputes with the config's inline literals folded
|
|
87
|
+
* in. Idempotent; a later call with a fresh config supersedes the previous one.
|
|
88
|
+
*/
|
|
89
|
+
export function setToolDisplayConfig(config) {
|
|
90
|
+
displayConfig = config;
|
|
91
|
+
cachedSecrets = null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Lazily-computed default secret literals for redaction (GS2-47 technique 1), harvested from the
|
|
95
|
+
* process env AND the registered config (inline `apiKey`/`token` values) the same way
|
|
96
|
+
* `/debug-dump` does. Cached because `collectSecretValues` walks the whole env + config; the set
|
|
97
|
+
* cannot change mid-process in any way this render path must react to (a new config resets it via
|
|
98
|
+
* {@link setToolDisplayConfig}). `redactText` additionally always applies the provider-key
|
|
99
|
+
* patterns (technique 2).
|
|
100
|
+
*/
|
|
101
|
+
let cachedSecrets = null;
|
|
102
|
+
function getDefaultSecrets() {
|
|
103
|
+
if (cachedSecrets === null) {
|
|
104
|
+
try {
|
|
105
|
+
cachedSecrets = collectSecretValues(displayConfig, env ?? {});
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
cachedSecrets = []; // patterns still apply via redactText
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return cachedSecrets;
|
|
112
|
+
}
|
|
113
|
+
/** Test seam: drop the cached secret literals + registered config so specs can vary both. */
|
|
114
|
+
export function resetToolDisplaySecretsCacheForTests() {
|
|
115
|
+
cachedSecrets = null;
|
|
116
|
+
displayConfig = undefined;
|
|
117
|
+
}
|
|
118
|
+
/** Collapse whitespace runs (incl. newlines) so a value stays a one-line token. */
|
|
119
|
+
function inline(value) {
|
|
120
|
+
return value.replace(/\s+/g, ' ').trim();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Truncate to `max` terminal COLUMNS with the {@link ELLIPSIS} marker, reserving the marker's own
|
|
124
|
+
* width out of the budget. Slicing goes through the shared width primitive: a code-point count
|
|
125
|
+
* would read a CJK or emoji value as shorter than it renders and hand it back whole, over-running
|
|
126
|
+
* the row it is drawn on.
|
|
127
|
+
*
|
|
128
|
+
* Whether the value fits is put to the SLICE rather than to the ruler, because the slice stops at
|
|
129
|
+
* the budget: a value that over-runs is recognised from its first `max` columns, where measuring
|
|
130
|
+
* it reads all of it — and the values arriving here are whole tool-output lines, which
|
|
131
|
+
* {@link TOOL_PREVIEW_LINE_MAX_CHARS} exists precisely because they can be a megabyte long.
|
|
132
|
+
*/
|
|
133
|
+
function truncate(value, max) {
|
|
134
|
+
const fitted = sliceToWidth(value, max);
|
|
135
|
+
if (fitted === value)
|
|
136
|
+
return value;
|
|
137
|
+
return sliceToWidth(value, max - ELLIPSIS_WIDTH) + ELLIPSIS;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Render one arg value for the summary: strings inline+truncated, the rest JSON-ish.
|
|
141
|
+
*
|
|
142
|
+
* ORDER MATTERS (fix-cycle-1 finding): redaction runs BEFORE any transformation. Truncating
|
|
143
|
+
* first would bisect a literal secret longer than the value cap so it no longer
|
|
144
|
+
* literal-matches — its head would render in the call summary on both surfaces (a partial
|
|
145
|
+
* leak); whitespace-collapsing first could likewise alter a literal out of matching. So:
|
|
146
|
+
* redact the RAW text, then inline, then truncate (`<redacted>` contains no whitespace and is
|
|
147
|
+
* shorter than the cap, so the later steps can never damage the marker).
|
|
148
|
+
*/
|
|
149
|
+
function formatParamValue(value, secrets) {
|
|
150
|
+
let text;
|
|
151
|
+
if (typeof value === 'string') {
|
|
152
|
+
text = value;
|
|
153
|
+
}
|
|
154
|
+
else if (value === undefined) {
|
|
155
|
+
text = 'undefined';
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
try {
|
|
159
|
+
text = JSON.stringify(value) ?? String(value);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
text = String(value);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return truncate(inline(redactText(text, secrets)), TOOL_PARAM_VALUE_MAX_CHARS);
|
|
166
|
+
}
|
|
167
|
+
/** Split into lines, dropping a single trailing newline's phantom empty last element. */
|
|
168
|
+
function toLines(text) {
|
|
169
|
+
const lines = text.split('\n');
|
|
170
|
+
if (lines.length > 1 && lines[lines.length - 1] === '')
|
|
171
|
+
lines.pop();
|
|
172
|
+
return lines;
|
|
173
|
+
}
|
|
174
|
+
/** Map raw text lines to styled lines. */
|
|
175
|
+
function styled(lines, style) {
|
|
176
|
+
return lines.map((text) => ({ text, style }));
|
|
177
|
+
}
|
|
178
|
+
/* ------------------------------------------------------------------------- *
|
|
179
|
+
* Shell-shaped results (<COMMAND_OUTPUT>) — run_* / run_shell_command / *
|
|
180
|
+
* custom toolkit tools all share this body shape, so it is detected by *
|
|
181
|
+
* SHAPE, not by name (custom tool names are user-defined). *
|
|
182
|
+
* ------------------------------------------------------------------------- */
|
|
183
|
+
const COMMAND_OUTPUT_RE = /<COMMAND_OUTPUT>\n?([\s\S]*?)<\/COMMAND_OUTPUT>\n?([\s\S]*)$/;
|
|
184
|
+
/**
|
|
185
|
+
* Parse the shared shell-result shape (`Executing '…'…\n\n<COMMAND_OUTPUT>…</COMMAND_OUTPUT>\n\n
|
|
186
|
+
* <status line>`). Returns the captured output body and the trailing status text, or `null`
|
|
187
|
+
* when the result is not shell-shaped.
|
|
188
|
+
*/
|
|
189
|
+
export function parseCommandOutputResult(result) {
|
|
190
|
+
if (!result)
|
|
191
|
+
return null;
|
|
192
|
+
const match = COMMAND_OUTPUT_RE.exec(result);
|
|
193
|
+
if (!match)
|
|
194
|
+
return null;
|
|
195
|
+
return { body: match[1] ?? '', tail: (match[2] ?? '').trim() };
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* TUI-C32 residual c — may this tool NAME be treated as shell-shaped at all? A registered entry
|
|
199
|
+
* must be explicitly {@link ToolDisplayEntry.shellShaped}; an unregistered/custom name falls back
|
|
200
|
+
* to shape-detection (custom toolkit tools own user-defined names yet share the result shape). A
|
|
201
|
+
* registered non-shell tool (`read_file`, `list_directory`, …) is therefore NEVER shell-parsed
|
|
202
|
+
* just because its result happens to contain the `<COMMAND_OUTPUT>` marker.
|
|
203
|
+
*/
|
|
204
|
+
function nameAllowsShellShape(name) {
|
|
205
|
+
const entry = TOOL_DISPLAY_REGISTRY[name];
|
|
206
|
+
return entry ? entry.shellShaped === true : true;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* TUI-C32 residual c — is THIS tool call genuinely a shell-shaped result (name allows it AND the
|
|
210
|
+
* result actually carries the `<COMMAND_OUTPUT>` shape)? Used by the plain surface to decide
|
|
211
|
+
* `liveOutputAlreadyShown` (the child streamed live via the tool-output channel's default sink),
|
|
212
|
+
* so a non-shell tool whose result merely quotes the marker no longer has its body suppressed.
|
|
213
|
+
*/
|
|
214
|
+
export function isShellShapedResult(name, result) {
|
|
215
|
+
return nameAllowsShellShape(name) && parseCommandOutputResult(result) !== null;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Body formatter for shell-shaped calls: the child's output (preferring the LIVE streamed
|
|
219
|
+
* output — verbatim what the child printed — over the result's `<COMMAND_OUTPUT>` copy of it,
|
|
220
|
+
* which is the TUI-C17 dedupe) followed by the closing status line. When the live output
|
|
221
|
+
* already streamed raw to the terminal (plain surface), only the status tail is rendered so
|
|
222
|
+
* nothing the user just watched is repeated.
|
|
223
|
+
*/
|
|
224
|
+
function formatShellBody(input) {
|
|
225
|
+
const parsed = parseCommandOutputResult(input.result);
|
|
226
|
+
// Not shell-shaped: only handle the still-running live-output case (a named run_* entry with
|
|
227
|
+
// no result yet). Anything with a non-shell result falls through to the generic rendering so
|
|
228
|
+
// e.g. a hardline refusal text is never dropped.
|
|
229
|
+
if (!parsed && (input.result || !input.output))
|
|
230
|
+
return null;
|
|
231
|
+
const lines = [];
|
|
232
|
+
if (!input.liveOutputAlreadyShown) {
|
|
233
|
+
// TUI-C32 residual d — the streamed live output is normally the verbatim, most-complete copy,
|
|
234
|
+
// so it is preferred (TUI-C17 dedupe). But if the live channel dropped straggler/tail chunks
|
|
235
|
+
// it can be a strict PREFIX of the result's `<COMMAND_OUTPUT>` copy (which the model always
|
|
236
|
+
// receives in full) — in that case fall back to the fuller copy so the expanded view can still
|
|
237
|
+
// recover what the stream missed. The common case (live === result, an independent/capped
|
|
238
|
+
// result, or an empty live output) is unchanged: only a genuine dropped-tail prefix overrides.
|
|
239
|
+
const live = input.output ?? '';
|
|
240
|
+
const resultBody = parsed?.body ?? '';
|
|
241
|
+
const body = resultBody.length > live.length && resultBody.startsWith(live) ? resultBody : live;
|
|
242
|
+
if (body.trim().length > 0)
|
|
243
|
+
lines.push(...styled(toLines(body), 'dim'));
|
|
244
|
+
}
|
|
245
|
+
if (parsed && parsed.tail.length > 0) {
|
|
246
|
+
lines.push(...styled(toLines(parsed.tail), 'dim'));
|
|
247
|
+
}
|
|
248
|
+
return lines.length > 0 ? lines : null;
|
|
249
|
+
}
|
|
250
|
+
/* ------------------------------------------------------------------------- *
|
|
251
|
+
* write_file / edit_file — diff-coloured rendering derived from the ARGS *
|
|
252
|
+
* ------------------------------------------------------------------------- */
|
|
253
|
+
/** `write_file` body: every content line is an ADDED diff line (there is no old content). */
|
|
254
|
+
function formatWriteFileBody(input, args) {
|
|
255
|
+
if (input.isError)
|
|
256
|
+
return null; // fall through: the error text is the story, not the diff
|
|
257
|
+
const content = args?.content;
|
|
258
|
+
if (typeof content !== 'string')
|
|
259
|
+
return null;
|
|
260
|
+
const lines = styled(toLines(content).map((l) => `+ ${l}`), 'added');
|
|
261
|
+
if (input.result && input.result.trim().length > 0) {
|
|
262
|
+
lines.push(...styled(toLines(input.result.trim()), 'dim'));
|
|
263
|
+
}
|
|
264
|
+
return lines;
|
|
265
|
+
}
|
|
266
|
+
/** `edit_file` body: per edit, the removed oldText lines then the added newText lines. */
|
|
267
|
+
function formatEditFileBody(input, args) {
|
|
268
|
+
if (input.isError)
|
|
269
|
+
return null; // fall through: show the recoverable error text instead
|
|
270
|
+
const edits = args?.edits;
|
|
271
|
+
if (!Array.isArray(edits) || edits.length === 0)
|
|
272
|
+
return null;
|
|
273
|
+
const lines = [];
|
|
274
|
+
let rendered = 0;
|
|
275
|
+
for (const raw of edits) {
|
|
276
|
+
const oldText = raw?.oldText;
|
|
277
|
+
const newText = raw?.newText;
|
|
278
|
+
if (typeof oldText !== 'string' || typeof newText !== 'string')
|
|
279
|
+
continue;
|
|
280
|
+
if (rendered > 0)
|
|
281
|
+
lines.push({ text: `${ELLIPSIS}`, style: 'dim' }); // hunk separator
|
|
282
|
+
rendered += 1;
|
|
283
|
+
lines.push(...styled(toLines(oldText).map((l) => `- ${l}`), 'removed'));
|
|
284
|
+
lines.push(...styled(toLines(newText).map((l) => `+ ${l}`), 'added'));
|
|
285
|
+
}
|
|
286
|
+
return rendered > 0 ? lines : null;
|
|
287
|
+
}
|
|
288
|
+
/* ------------------------------------------------------------------------- *
|
|
289
|
+
* The registry *
|
|
290
|
+
* ------------------------------------------------------------------------- */
|
|
291
|
+
/**
|
|
292
|
+
* Named entries. Anything not listed uses the generic fallback (all args summarised,
|
|
293
|
+
* output+result previewed dim) — plus the SHAPE-based shell formatter, which also covers
|
|
294
|
+
* user-named custom toolkit tools (they share the `<COMMAND_OUTPUT>` result shape).
|
|
295
|
+
*/
|
|
296
|
+
const TOOL_DISPLAY_REGISTRY = {
|
|
297
|
+
read_file: { glyph: FILE_GLYPH, summariseArgs: ['path', 'offset', 'limit', 'head', 'tail'] },
|
|
298
|
+
read_multiple_files: { glyph: FILE_GLYPH, summariseArgs: ['paths'] },
|
|
299
|
+
gth_read_binary: { glyph: FILE_GLYPH, summariseArgs: ['path'] },
|
|
300
|
+
write_file: { glyph: FILE_GLYPH, summariseArgs: ['path'], formatBody: formatWriteFileBody },
|
|
301
|
+
edit_file: {
|
|
302
|
+
glyph: FILE_GLYPH,
|
|
303
|
+
summariseArgs: ['path', 'dryRun'],
|
|
304
|
+
formatBody: formatEditFileBody,
|
|
305
|
+
},
|
|
306
|
+
create_directory: { glyph: FILE_GLYPH },
|
|
307
|
+
list_directory: { glyph: FILE_GLYPH },
|
|
308
|
+
list_directory_with_sizes: { glyph: FILE_GLYPH },
|
|
309
|
+
directory_tree: { glyph: FILE_GLYPH },
|
|
310
|
+
move_file: { glyph: FILE_GLYPH },
|
|
311
|
+
search_files: { glyph: FILE_GLYPH },
|
|
312
|
+
get_file_info: { glyph: FILE_GLYPH },
|
|
313
|
+
delete_file: { glyph: FILE_GLYPH },
|
|
314
|
+
delete_directory: { glyph: FILE_GLYPH },
|
|
315
|
+
list_allowed_directories: { glyph: FILE_GLYPH },
|
|
316
|
+
run_shell_command: {
|
|
317
|
+
glyph: SHELL_GLYPH,
|
|
318
|
+
summariseArgs: ['command'],
|
|
319
|
+
formatBody: formatShellBody,
|
|
320
|
+
shellShaped: true,
|
|
321
|
+
},
|
|
322
|
+
run_tests: { glyph: SHELL_GLYPH, formatBody: formatShellBody, shellShaped: true },
|
|
323
|
+
run_single_test: {
|
|
324
|
+
glyph: SHELL_GLYPH,
|
|
325
|
+
summariseArgs: ['testPath'],
|
|
326
|
+
formatBody: formatShellBody,
|
|
327
|
+
shellShaped: true,
|
|
328
|
+
},
|
|
329
|
+
run_lint: { glyph: SHELL_GLYPH, formatBody: formatShellBody, shellShaped: true },
|
|
330
|
+
run_build: { glyph: SHELL_GLYPH, formatBody: formatShellBody, shellShaped: true },
|
|
331
|
+
task: { glyph: '🤖', summariseArgs: ['subagent_type', 'description'] },
|
|
332
|
+
};
|
|
333
|
+
/** The registry glyph for a tool name (generic `⚙` when unknown). */
|
|
334
|
+
export function getToolGlyph(name) {
|
|
335
|
+
return TOOL_DISPLAY_REGISTRY[name]?.glyph ?? FALLBACK_GLYPH;
|
|
336
|
+
}
|
|
337
|
+
/* ------------------------------------------------------------------------- *
|
|
338
|
+
* Params summary *
|
|
339
|
+
* ------------------------------------------------------------------------- */
|
|
340
|
+
/**
|
|
341
|
+
* One-line call summary: `name(arg=val, other=…)`. Key args only (per the registry entry, or
|
|
342
|
+
* all args for unknown tools), each value inlined + truncated, the whole parenthesised part
|
|
343
|
+
* capped at {@link TOOL_SUMMARY_MAX_CHARS}, and everything secret-redacted (literals +
|
|
344
|
+
* provider patterns). Unparsable (mid-stream/malformed) args render as `name(…)` — never a
|
|
345
|
+
* raw JSON dump. `secrets` defaults to the env-derived literals; pass explicitly for tests.
|
|
346
|
+
*
|
|
347
|
+
* Redaction runs BEFORE every truncation step (per value in {@link formatParamValue}, and again
|
|
348
|
+
* before the whole-summary cap): truncating first would bisect a literal secret longer than a
|
|
349
|
+
* cap so it no longer literal-matches, leaking its head into the rendered summary
|
|
350
|
+
* (fix-cycle-1 finding). The final pass over the assembled string is defense in depth only —
|
|
351
|
+
* `redactText` is idempotent, so re-redacting already-marked text is safe.
|
|
352
|
+
*/
|
|
353
|
+
export function summariseToolCall(name, argsText, secrets = getDefaultSecrets()) {
|
|
354
|
+
const label = name || '(tool)';
|
|
355
|
+
const args = parseToolArgsSafe(argsText);
|
|
356
|
+
if (args === null) {
|
|
357
|
+
const hasRawArgs = !!argsText && argsText.trim().length > 0 && argsText.trim() !== '{}';
|
|
358
|
+
return hasRawArgs ? `${label}(${ELLIPSIS})` : `${label}()`;
|
|
359
|
+
}
|
|
360
|
+
const entry = TOOL_DISPLAY_REGISTRY[name];
|
|
361
|
+
const keys = entry?.summariseArgs !== undefined
|
|
362
|
+
? entry.summariseArgs.filter((k) => args[k] !== undefined)
|
|
363
|
+
: Object.keys(args);
|
|
364
|
+
const parts = keys.map((k) => `${k}=${formatParamValue(args[k], secrets)}`);
|
|
365
|
+
// Anything parsed but not summarised (write_file's content, unlisted keys) is signalled with
|
|
366
|
+
// a trailing ellipsis so the summary never silently pretends to be the whole call.
|
|
367
|
+
const hasHiddenArgs = entry?.summariseArgs !== undefined && Object.keys(args).some((k) => !keys.includes(k));
|
|
368
|
+
if (hasHiddenArgs)
|
|
369
|
+
parts.push(ELLIPSIS);
|
|
370
|
+
// Redact before the whole-summary cap too, so this truncation can no more bisect a secret
|
|
371
|
+
// out of literal-matching than the per-value one can.
|
|
372
|
+
const inner = truncate(redactText(parts.join(', '), secrets), TOOL_SUMMARY_MAX_CHARS);
|
|
373
|
+
return redactText(`${label}(${inner})`, secrets);
|
|
374
|
+
}
|
|
375
|
+
/* ------------------------------------------------------------------------- *
|
|
376
|
+
* Body + preview *
|
|
377
|
+
* ------------------------------------------------------------------------- */
|
|
378
|
+
/**
|
|
379
|
+
* The FULL (uncapped) body lines for a call: the registry formatter when one applies, else the
|
|
380
|
+
* shape-based shell formatter, else the generic fallback (live output lines, then the final
|
|
381
|
+
* result — both dim). Every line is secret-redacted. Used by the TUI's EXPANDED panel; cap it
|
|
382
|
+
* with {@link capToolDisplayLines} for the collapsed preview.
|
|
383
|
+
*/
|
|
384
|
+
export function buildToolBodyLines(input, secrets = getDefaultSecrets()) {
|
|
385
|
+
const args = parseToolArgsSafe(input.argsText);
|
|
386
|
+
const entry = TOOL_DISPLAY_REGISTRY[input.name];
|
|
387
|
+
let lines = entry?.formatBody?.(input, args) ?? null;
|
|
388
|
+
// TUI-C32 residual c — only fall back to the shape-based shell formatter for names that may be
|
|
389
|
+
// shell-shaped (flagged registry entries + unregistered custom tools), so a registered non-shell
|
|
390
|
+
// tool whose result merely contains `<COMMAND_OUTPUT>` is rendered generically, not shell-parsed.
|
|
391
|
+
if (lines === null && nameAllowsShellShape(input.name))
|
|
392
|
+
lines = formatShellBody(input);
|
|
393
|
+
if (lines === null) {
|
|
394
|
+
lines = [];
|
|
395
|
+
if (input.output && input.output.trim().length > 0 && !input.liveOutputAlreadyShown) {
|
|
396
|
+
lines.push(...styled(toLines(input.output), 'dim'));
|
|
397
|
+
}
|
|
398
|
+
if (input.result && input.result.trim().length > 0) {
|
|
399
|
+
lines.push(...styled(toLines(input.result), 'dim'));
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return lines.map((l) => ({ ...l, text: redactText(l.text, secrets) }));
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Apply the canonical render cap: at most `maxLines` lines (each char-capped at
|
|
406
|
+
* {@link TOOL_PREVIEW_LINE_MAX_CHARS} with `…`), plus a dim `… (+N more lines)` overflow
|
|
407
|
+
* marker when anything was cut. The marker line is IN ADDITION to the cap so exactly how much
|
|
408
|
+
* was hidden is always stated (DL-4 transparency).
|
|
409
|
+
*/
|
|
410
|
+
export function capToolDisplayLines(lines, maxLines = TOOL_OUTPUT_PREVIEW_LINES) {
|
|
411
|
+
const capped = lines.slice(0, maxLines).map((l) => ({
|
|
412
|
+
...l,
|
|
413
|
+
text: truncate(l.text, TOOL_PREVIEW_LINE_MAX_CHARS),
|
|
414
|
+
}));
|
|
415
|
+
const hidden = lines.length - capped.length;
|
|
416
|
+
if (hidden > 0) {
|
|
417
|
+
capped.push({
|
|
418
|
+
text: `${ELLIPSIS} (+${hidden} more line${hidden === 1 ? '' : 's'})`,
|
|
419
|
+
style: 'dim',
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
return capped;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* The collapsed inline preview: {@link buildToolBodyLines} capped at the canonical
|
|
426
|
+
* {@link TOOL_OUTPUT_PREVIEW_LINES}.
|
|
427
|
+
*/
|
|
428
|
+
export function buildToolPreviewLines(input, secrets = getDefaultSecrets()) {
|
|
429
|
+
return capToolDisplayLines(buildToolBodyLines(input, secrets));
|
|
430
|
+
}
|
|
431
|
+
/* ------------------------------------------------------------------------- *
|
|
432
|
+
* ANSI adapter (plain surface) *
|
|
433
|
+
* ------------------------------------------------------------------------- */
|
|
434
|
+
const ANSI_BY_STYLE = {
|
|
435
|
+
dim: '\x1b[2m',
|
|
436
|
+
added: '\x1b[32m',
|
|
437
|
+
removed: '\x1b[31m',
|
|
438
|
+
};
|
|
439
|
+
const ANSI_RESET = '\x1b[0m';
|
|
440
|
+
/**
|
|
441
|
+
* Render one styled line as a raw string for the plain surface. Each line is SELF-STYLED
|
|
442
|
+
* (its own SGR open + reset) so lines compose safely regardless of surrounding styling.
|
|
443
|
+
* With `colour` false the raw text is returned unchanged — the clean monochrome degradation
|
|
444
|
+
* for non-TTY/piped output (DL-7); diff lines still read via their `+`/`-` prefixes.
|
|
445
|
+
*/
|
|
446
|
+
export function renderToolLineAnsi(line, colour) {
|
|
447
|
+
if (!colour)
|
|
448
|
+
return line.text;
|
|
449
|
+
return `${ANSI_BY_STYLE[line.style]}${line.text}${ANSI_RESET}`;
|
|
450
|
+
}
|
|
451
|
+
//# sourceMappingURL=toolDisplay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolDisplay.js","sourceRoot":"","sources":["../../src/core/toolDisplay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module toolOutputChannel
|
|
3
|
+
* TUI-C17 — the managed route for LIVE tool output (a custom/dev toolkit child process's
|
|
4
|
+
* stdout/stderr chunks and its "🔧 Executing …" announcement).
|
|
5
|
+
*
|
|
6
|
+
* The toolkits used to write child output straight to `process.stdout` and announce runs via
|
|
7
|
+
* `displayInfo`. Under the Ink TUI both bypass Ink's managed frame: the raw text prints out of
|
|
8
|
+
* order above the agent message, never reaches the `TurnViewModel`, and vanishes on the next
|
|
9
|
+
* re-render. The fix is an emit/subscribe seam:
|
|
10
|
+
*
|
|
11
|
+
* - The toolkits call {@link emitToolOutput} instead of writing to stdout/`displayInfo`.
|
|
12
|
+
* - With NO subscriber (every non-TUI surface: `--no-tui`, piped, `exec`, the AG-UI server),
|
|
13
|
+
* the DEFAULT SINK reproduces the historical behaviour byte-for-byte — `displayInfo` for the
|
|
14
|
+
* notice, `stdout.write` for chunks, `displayWarning`/`displayError` for a failure-path
|
|
15
|
+
* warning/error — so headless output is unchanged.
|
|
16
|
+
* - The Ink TUI subscribes for the duration of a turn via {@link mergeToolOutputIntoEvents},
|
|
17
|
+
* which converts each chunk into a typed `tool_output` {@link AgentStreamEvent} attributed to
|
|
18
|
+
* its tool call, merged live into the turn's event stream so it lands in `foldEvents`.
|
|
19
|
+
*
|
|
20
|
+
* Single-subscriber by design: one process hosts at most one interactive TUI session, and the
|
|
21
|
+
* non-TUI surfaces never subscribe. (Concurrent server sessions — AG-UI/ACP — stay on the
|
|
22
|
+
* default sink, exactly as before.)
|
|
23
|
+
*
|
|
24
|
+
* TUI-C31 hardens the seam's edge windows: failure-path warnings/errors now travel the channel
|
|
25
|
+
* too ({@link GthToolOutputChunk} `kind: 'warning' | 'error'`, residual a); the merge drains a
|
|
26
|
+
* straggler queued in the unsubscribe microwindow (residual b) and cleans up on early-`return()`
|
|
27
|
+
* (residual c); and {@link setToolOutputSuppressed} lets the mounted TUI suppress a
|
|
28
|
+
* post-unsubscribe straggler between turns instead of leaking it to raw stdout (residual d).
|
|
29
|
+
*/
|
|
30
|
+
import type { AgentStreamEvent } from '#src/core/types.js';
|
|
31
|
+
/** One emitted piece of live tool output, attributed to the tool (and call) that produced it. */
|
|
32
|
+
export interface GthToolOutputChunk {
|
|
33
|
+
/**
|
|
34
|
+
* The LangChain tool call id this output belongs to (`ToolRunnableConfig.toolCall.id`),
|
|
35
|
+
* when the invoking framework supplied one. Lets a consumer nest output under the exact call.
|
|
36
|
+
*/
|
|
37
|
+
toolCallId?: string;
|
|
38
|
+
/** The gth tool name (e.g. `run_shell_command`, a custom tool's name). Always known. */
|
|
39
|
+
toolName: string;
|
|
40
|
+
/**
|
|
41
|
+
* `notice` — the "🔧 Executing …" announcement (historically `displayInfo`);
|
|
42
|
+
* `output` — a verbatim child stdout/stderr chunk (historically `stdout.write`);
|
|
43
|
+
* `warning` / `error` — a failure-path advisory (historically `displayWarning`/`displayError`),
|
|
44
|
+
* e.g. a hardline refusal or a spawn-level failure. TUI-C31 (a): routing these through the
|
|
45
|
+
* channel keeps them out of raw stdout while the Ink frame is mounted; the default sink still
|
|
46
|
+
* renders them via `displayWarning`/`displayError` for every non-TUI surface, byte-for-byte.
|
|
47
|
+
*/
|
|
48
|
+
kind: 'notice' | 'output' | 'warning' | 'error';
|
|
49
|
+
/**
|
|
50
|
+
* The text, verbatim. Notices carry NO leading newline — raw-console framing (the historical
|
|
51
|
+
* leading `\n`) is the default sink's concern, not the producer's. A `warning`/`error` DOES
|
|
52
|
+
* carry whatever leading framing its historical `displayWarning`/`displayError` call had (the
|
|
53
|
+
* default sink forwards it unchanged), so headless output stays byte-for-byte identical.
|
|
54
|
+
*/
|
|
55
|
+
text: string;
|
|
56
|
+
}
|
|
57
|
+
export type GthToolOutputListener = (chunk: GthToolOutputChunk) => void;
|
|
58
|
+
/**
|
|
59
|
+
* Subscribe to live tool output, replacing the default stdout/`displayInfo` sink for as long
|
|
60
|
+
* as the subscription is active. Returns an unsubscribe function. Last subscriber wins; the
|
|
61
|
+
* returned unsubscribe only clears its OWN registration (a stale unsubscribe can never detach
|
|
62
|
+
* a newer subscriber).
|
|
63
|
+
*/
|
|
64
|
+
export declare function subscribeToolOutput(listener: GthToolOutputListener): () => void;
|
|
65
|
+
/**
|
|
66
|
+
* TUI-C31 (d): mark whether a terminal-owning surface (the Ink TUI) is mounted. While mounted,
|
|
67
|
+
* the default sink SUPPRESSES output that has no per-turn subscriber (a post-turn straggler)
|
|
68
|
+
* rather than writing it raw over the managed frame. The TUI session sets this `true` around the
|
|
69
|
+
* whole session (`render()` … `waitUntilExit()`) and back to `false` on unmount, so once the TUI
|
|
70
|
+
* is gone the default (headless) stdout sink is fully restored. An active per-turn subscriber
|
|
71
|
+
* always takes precedence, so legitimate in-turn output is untouched.
|
|
72
|
+
*/
|
|
73
|
+
export declare function setToolOutputSuppressed(value: boolean): void;
|
|
74
|
+
/**
|
|
75
|
+
* Emit one piece of live tool output. Routed to the active subscriber when present (the Ink
|
|
76
|
+
* TUI), otherwise to the DEFAULT SINK, which reproduces the pre-TUI-C17 behaviour exactly:
|
|
77
|
+
* the notice via `displayInfo` with its historical leading newline, chunks via `stdout.write`,
|
|
78
|
+
* a warning via `displayWarning` and an error via `displayError` (TUI-C31 a). While the TUI is
|
|
79
|
+
* mounted but no subscriber is attached (between turns), a no-subscriber emit is SUPPRESSED
|
|
80
|
+
* rather than written raw over the managed frame (TUI-C31 d).
|
|
81
|
+
*/
|
|
82
|
+
export declare function emitToolOutput(chunk: GthToolOutputChunk): void;
|
|
83
|
+
/**
|
|
84
|
+
* Merge live tool output into an agent event stream: subscribes to the channel for the
|
|
85
|
+
* lifetime of `inner` and yields each emitted chunk as a `tool_output` event, interleaved
|
|
86
|
+
* with `inner`'s own events in arrival order. Because tool child output arrives WHILE the
|
|
87
|
+
* graph stream is awaiting its next message, the merge is push-based (a woken queue), so a
|
|
88
|
+
* long-running command's output streams into the consumer live rather than batching until
|
|
89
|
+
* the tool finishes.
|
|
90
|
+
*
|
|
91
|
+
* Used by the TUI session around `processMessagesWithEvents`; always unsubscribes (restoring
|
|
92
|
+
* the default stdout sink) when the inner stream completes, throws, or the consumer stops
|
|
93
|
+
* early. Errors from `inner` (including aborts) propagate unchanged after the queue drains.
|
|
94
|
+
*/
|
|
95
|
+
export declare function mergeToolOutputIntoEvents(inner: AsyncGenerator<AgentStreamEvent>): AsyncGenerator<AgentStreamEvent>;
|