Skip to content

Commit a789d4f

Browse files
committed
fix(cli): render oversized live tool results by byte size
With content now riding live tool_result frames, a result that exceeds the 48 KB live budget arrives as an empty placeholder plus contentBytes. Render the truthful byte count in the compact row (instead of the '(no output)' lie) and a dim note in the expanded card; the terminal reconcile still heals the full body from the durable transcript at turn end, clearing the placeholder. Generated-by: Maka (Kimi K3)
1 parent b6bd1e0 commit a789d4f

3 files changed

Lines changed: 107 additions & 1 deletion

File tree

packages/cli/src/__tests__/pi-transcript.test.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,88 @@ describe('Maka Pi TUI transcript', () => {
302302
assert.equal(state.entries.at(-1)?.kind, 'notice');
303303
});
304304

305+
test('shows the byte size of an oversized live tool result instead of no output', () => {
306+
const state = createMakaPiTranscriptState();
307+
applyMakaSessionEventToTranscript(
308+
state,
309+
event({
310+
type: 'tool_start',
311+
toolUseId: 'big-1',
312+
toolName: 'Bash',
313+
args: { command: 'npm test' },
314+
}),
315+
);
316+
applyMakaSessionEventToTranscript(
317+
state,
318+
event({
319+
type: 'tool_result',
320+
toolUseId: 'big-1',
321+
isError: false,
322+
durationMs: 2500,
323+
content: { kind: 'text', text: '' },
324+
contentBytes: 100_000,
325+
}),
326+
);
327+
328+
const compact = renderMakaPiTranscript(state, meta(), 80).map(stripAnsi).join('\n');
329+
assert.match(compact, /100000 bytes/);
330+
assert.doesNotMatch(compact, /no output/);
331+
332+
assert.equal(toggleAllToolExpansion(state), true);
333+
const expanded = renderMakaPiTranscript(state, meta(), 80).map(stripAnsi).join('\n');
334+
assert.match(expanded, /too large to show live: 100000 bytes/);
335+
});
336+
337+
test('the terminal reconcile replaces an oversized placeholder with the durable content', () => {
338+
const state = createMakaPiTranscriptState();
339+
applyMakaSessionEventToTranscript(
340+
state,
341+
event({
342+
type: 'tool_start',
343+
toolUseId: 'big-1',
344+
toolName: 'Bash',
345+
args: { command: 'npm test' },
346+
}),
347+
);
348+
applyMakaSessionEventToTranscript(
349+
state,
350+
event({
351+
type: 'tool_result',
352+
toolUseId: 'big-1',
353+
isError: false,
354+
content: { kind: 'text', text: '' },
355+
contentBytes: 100_000,
356+
}),
357+
);
358+
359+
assert.equal(
360+
reconcileToolsWithStoredMessages(state, 'turn-1', [
361+
{
362+
type: 'tool_call',
363+
id: 'big-1',
364+
turnId: 'turn-1',
365+
ts: 1,
366+
toolName: 'Bash',
367+
args: { command: 'npm test' },
368+
},
369+
{
370+
type: 'tool_result',
371+
id: 'big-1-result',
372+
turnId: 'turn-1',
373+
ts: 2,
374+
toolUseId: 'big-1',
375+
isError: false,
376+
content: { kind: 'text', text: 'all 3 suites passed' },
377+
},
378+
]),
379+
true,
380+
);
381+
382+
const row = renderMakaPiTranscript(state, meta(), 80).map(stripAnsi).join('\n');
383+
assert.match(row, /all 3 suites passed|1 line · 19 bytes/);
384+
assert.doesNotMatch(row, /100000 bytes/);
385+
});
386+
305387
test('removes a live poll card that the durable transcript folds into its Bash parent', () => {
306388
const state = createMakaPiTranscriptState();
307389
for (const tool of [

packages/cli/src/pi-transcript-tools.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,15 @@ function renderExpandedToolBlock(entry: MakaPiToolEntry, width: number): string[
193193
}
194194
lines.push(...renderToolStreams(entry.outputDeltas.values(), width));
195195
}
196-
if (entry.result || entry.output) {
196+
if (entry.resultBytes !== undefined && !plainResultText(entry)) {
197+
lines.push(
198+
...renderIndented(
199+
ansi.dim(`Result too large to show live: ${entry.resultBytes} bytes`),
200+
width,
201+
2,
202+
),
203+
);
204+
} else if (entry.result || entry.output) {
197205
lines.push(...renderToolResult(entry, width));
198206
}
199207
if (
@@ -258,6 +266,11 @@ function pipeOutputLineCount(output: { stdout?: string; stderr?: string }): numb
258266

259267
function compactToolSummary(entry: MakaPiToolEntry): CompactToolSummary | undefined {
260268
const result = entry.result;
269+
// An oversized live result carried only its byte size (#3521): show the
270+
// truthful size rather than the empty placeholder's `no output`.
271+
if (entry.resultBytes !== undefined && !plainResultText(entry)) {
272+
return { text: `${entry.resultBytes} bytes`, protect: true };
273+
}
261274
if (result?.kind === 'shell_run') {
262275
if (entry.toolName === 'WriteStdin') {
263276
return { text: formatPtyControlOperation(result.operation, entry.input) };

packages/cli/src/pi-transcript.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ export type MakaPiTranscriptEntry =
182182
output?: string;
183183
/** In-memory revision for render-cache invalidation when a result is replaced. */
184184
resultVersion: number;
185+
/**
186+
* Serialized size of a settled result whose content exceeded the live
187+
* frame budget and was omitted (#3521). Cleared when real content lands
188+
* (live or via the terminal reconcile).
189+
*/
190+
resultBytes?: number;
185191
progress: BoundedChunkBuffer<string>;
186192
outputDeltas: BoundedChunkBuffer<MakaPiToolOutputDelta>;
187193
durationMs?: number;
@@ -406,6 +412,7 @@ export function reconcileToolsWithStoredMessages(
406412
entry.input = structuredClone(durable.input);
407413
entry.result = durable.result ? structuredClone(durable.result) : undefined;
408414
entry.output = durable.output;
415+
delete entry.resultBytes;
409416
entry.durationMs = durable.durationMs;
410417
entry.status = durable.status;
411418
entry.hidden = durable.hidden;
@@ -634,6 +641,7 @@ export function applyMakaSessionEventToTranscript(
634641
result: event.content,
635642
output: formatToolResultContent(event.content),
636643
resultVersion: 1,
644+
...(event.contentBytes === undefined ? {} : { resultBytes: event.contentBytes }),
637645
durationMs: event.durationMs,
638646
status: event.isError ? 'error' : 'done',
639647
expanded: state.expandAllTools,
@@ -681,6 +689,8 @@ export function applyMakaSessionEventToTranscript(
681689
tool.status = toolResultTranscriptStatus(event.content, event.isError);
682690
tool.result = event.content;
683691
tool.output = formatToolResultContent(event.content);
692+
if (event.contentBytes === undefined) delete tool.resultBytes;
693+
else tool.resultBytes = event.contentBytes;
684694
tool.durationMs = event.durationMs;
685695
tool.resultVersion += 1;
686696
}
@@ -696,6 +706,7 @@ export function applyMakaSessionEventToTranscript(
696706
result: event.content,
697707
output: formatToolResultContent(event.content),
698708
resultVersion: 1,
709+
...(event.contentBytes === undefined ? {} : { resultBytes: event.contentBytes }),
699710
durationMs: event.durationMs,
700711
status: toolResultTranscriptStatus(event.content, event.isError),
701712
expanded: state.expandAllTools,

0 commit comments

Comments
 (0)