Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions packages/cli/src/__tests__/pi-transcript.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,100 @@ describe('Maka Pi TUI transcript', () => {
assert.doesNotMatch(stripAnsi(renderMakaPiStatusLine({ ...meta(), goal: null }, 120)), /goal/);
});

test('status line drops whole low-value segments on overflow, lowest rank first (#3421)', () => {
const richMeta = {
...meta(),
modelContextWindow: 500_000,
usage: {
costUsd: 0.42,
cacheHitInput: 60,
cacheMissInput: 40,
contextRemaining: 480_000,
},
};
// Wide: everything renders.
const wide = stripAnsi(renderMakaPiStatusLine(richMeta, 120));
assert.match(wide, /ctx 20k\/500k 4%/);
assert.match(wide, /\$0\.42/);
assert.match(wide, /cache 60%/);
assert.match(wide, /deepseek · \/tmp\/project/);

// Below full width, cache drops before cost, and no segment is cut
// mid-token while any lower rank still survives.
const fullWidth = visibleWidth(wide);
const noCache = stripAnsi(renderMakaPiStatusLine(richMeta, fullWidth - 1));
assert.doesNotMatch(noCache, /cache/);
assert.match(noCache, /\$0\.42/);
const noCost = stripAnsi(
renderMakaPiStatusLine(richMeta, fullWidth - 'cache 60% · '.length - 1),
);
assert.doesNotMatch(noCost, /cache|\$0\.42/);
assert.match(noCost, /deepseek · \/tmp\/project/);
});

test('status line shortens cwd to its basename before dropping it (#3421)', () => {
const line = stripAnsi(
renderMakaPiStatusLine(
{
...meta(),
cwd: '/very/long/nested/project-directory',
modelContextWindow: 500_000,
usage: {
costUsd: 0,
cacheHitInput: 1,
cacheMissInput: 1,
contextRemaining: 480_000,
},
},
// Room for title, mode, model, ctx and a short tail only.
'Maka · Auto · deepseek-v4-flash · ctx 20k/500k 4% · project-directory'.length,
),
);
assert.doesNotMatch(line, /very\/long/);
assert.match(line, /project-directory/);
});

test('status line never drops mode, model, goal, or ctx at narrow widths (#3421)', () => {
const line = stripAnsi(
renderMakaPiStatusLine(
{
...meta(),
permissionMode: 'bypass',
modelContextWindow: 500_000,
usage: {
costUsd: 9.99,
cacheHitInput: 1,
cacheMissInput: 1,
contextRemaining: 480_000,
},
goal: {
goalId: 'goal-1',
revision: 1,
sessionId: 'session-1',
condition: 'Ship it',
setAt: Date.now() - 60_000,
iterations: 1,
maxIterations: 50,
consecutiveNoProgress: 0,
blockCap: 8,
tokenBudget: null,
tokensSpent: 0,
lastReason: null,
achievedAt: null,
pausedAt: null,
status: 'active' as const,
},
},
75,
),
);
assert.match(line, /Full access/);
assert.match(line, /deepseek-v4-flash/);
assert.match(line, /goal 1\/50/);
assert.match(line, /ctx 20k\/500k 4%/);
assert.doesNotMatch(line, /\$9\.99|cache|deepseek ·|tmp\/project/);
});

test('keeps assistant text after a tool call visible after the tool block', () => {
const state = createMakaPiTranscriptState();
appendUserPrompt(state, 'inspect the package');
Expand Down
4 changes: 3 additions & 1 deletion packages/cli/src/__tests__/pi-tui-runner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3182,7 +3182,9 @@ describe('Maka Pi TUI runner', () => {
});

test('restores switched session state from stored messages', async () => {
const terminal = new FakeTerminal();
// 120 cols: the status line fits every segment, so the usage segments this
// test asserts (ctx, cache) are not priority-dropped (#3421).
const terminal = new FakeTerminal(120);
const driver = new SlashCommandDriver(
[fakeSessionSummary('session-2', '/repo')],
new Map([
Expand Down
99 changes: 76 additions & 23 deletions packages/cli/src/pi-transcript.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Markdown } from '@earendil-works/pi-tui';
import { Markdown, visibleWidth } from '@earendil-works/pi-tui';
import type {
ProviderRetryEvent,
SandboxBoundaryRequestEvent,
Expand All @@ -20,6 +20,7 @@ import { mergeShellRunStateWithDiagnostics } from '@maka/core/shell-run-result';
import { projectToolActivityArgs } from '@maka/core/tool-activity-args';
import { type ShellRunUpdate } from '@maka/core/events';
import { homedir } from 'node:os';
import { basename } from 'node:path';
import {
materializeSession,
type ChatItem,
Expand Down Expand Up @@ -1328,20 +1329,25 @@ export function permissionModeLabel(mode: string): string {
export function renderMakaPiStatusLine(metadata: MakaPiTranscriptMetadata, width: number): string {
const safeWidth = Math.max(1, width);
const sep = ansi.dim(' · ');
const parts: string[] = [
ansi.bold(metadata.title),
ansi.dim(permissionModeLabel(metadata.permissionMode)),
ansi.dim(metadata.model),
// #3421: segments carry a dropRank so overflow drops whole low-value
// segments instead of cutting the chain mid-token from the right.
// Lower ranks drop first; segments without a rank never drop:
// title, permission mode and goal are safety-relevant, ctx is the
// context budget, model is the session's identity.
const parts: MakaPiStatusLineSegment[] = [
{ text: ansi.bold(metadata.title) },
{ text: ansi.dim(permissionModeLabel(metadata.permissionMode)) },
{ text: ansi.dim(metadata.model) },
];
// #1064: omit thinking:default — it is noise before the user explicitly
// changes the level. Only a non-default, explicitly set level shows.
if (metadata.thinkingLevel) {
parts.push(ansi.dim(`thinking:${metadata.thinkingLevel}`));
parts.push({ text: ansi.dim(`thinking:${metadata.thinkingLevel}`), dropRank: 3 });
}
if (metadata.orchestrationMode === 'swarm') {
parts.push(ansi.accent('swarm'));
parts.push({ text: ansi.accent('swarm'), dropRank: 4 });
} else if (metadata.orchestrationMode === 'graph') {
parts.push(ansi.accent('graph'));
parts.push({ text: ansi.accent('graph'), dropRank: 4 });
}
// An autonomous goal burns tokens between prompts; it must never be
// invisible. Terminal goals show nothing (the desktop chip hides them too).
Expand All @@ -1350,13 +1356,14 @@ export function renderMakaPiStatusLine(metadata: MakaPiTranscriptMetadata, width
// paused gets warning salience: the loop stopped burning but stays armed
// and resumable, which the user must not miss. waiting is a normal
// transient between turns, so it stays dim like the other chrome.
parts.push(
metadata.goal.status === 'active'
? ansi.accent(text)
: metadata.goal.status === 'paused'
? ansi.yellow(text)
: ansi.dim(text),
);
parts.push({
text:
metadata.goal.status === 'active'
? ansi.accent(text)
: metadata.goal.status === 'paused'
? ansi.yellow(text)
: ansi.dim(text),
});
}
const usage = metadata.usage;
if (usage) {
Expand All @@ -1369,25 +1376,71 @@ export function renderMakaPiStatusLine(metadata: MakaPiTranscriptMetadata, width
const pct = Math.round((used / metadata.modelContextWindow) * 100);
// #1064: color warning — yellow >80%, red >95%, dim otherwise.
const ctxColor = pct > 95 ? ansi.red : pct > 80 ? ansi.yellow : ansi.dim;
parts.push(
ctxColor(
parts.push({
text: ctxColor(
`ctx ${formatTokenCount(used)}/${formatTokenCount(metadata.modelContextWindow)} ${pct}%`,
),
);
});
}
if (usage.costUsd > 0) {
parts.push(ansi.dim(`$${formatCost(usage.costUsd)}`));
parts.push({ text: ansi.dim(`$${formatCost(usage.costUsd)}`), dropRank: 1 });
}
const totalCache = usage.cacheHitInput + usage.cacheMissInput;
if (totalCache > 0) {
const hitRate = Math.round((usage.cacheHitInput / totalCache) * 100);
parts.push(ansi.dim(`cache ${hitRate}%`));
parts.push({ text: ansi.dim(`cache ${hitRate}%`), dropRank: 0 });
}
}
parts.push(ansi.dim(metadata.connectionSlug));
parts.push({ text: ansi.dim(metadata.connectionSlug), dropRank: 2 });
// #1064: shorten cwd to ~-relative path instead of the full path.
parts.push(ansi.dim(shortenCwd(metadata.cwd)));
return fitLine(parts.join(sep), safeWidth);
const cwd = shortenCwd(metadata.cwd);
// cwd degrades progressively (full → basename → dropped), after every
// ranked segment above but before the final truncation fallback.
parts.push({
text: ansi.dim(cwd),
dropRank: 5,
shortenedText: cwd === '~' || cwd === '/' ? undefined : ansi.dim(basename(cwd)),
});
return fitStatusLine(parts, sep, safeWidth);
}

interface MakaPiStatusLineSegment {
text: string;
/** Overflow drops whole segments lowest-rank-first; undefined never drops. */
dropRank?: number;
/** Progressive fallback tried before this segment is dropped entirely. */
shortenedText?: string;
}

function fitStatusLine(segments: MakaPiStatusLineSegment[], sep: string, width: number): string {
const lineWidth = (segs: MakaPiStatusLineSegment[]): number =>
visibleWidth(segs.map((segment) => segment.text).join(sep));
let kept = segments;
// Drop whole low-value segments, lowest rank first, re-checking after each
// rank so the fewest possible segments are sacrificed.
for (let rank = 0; lineWidth(kept) > width; rank++) {
const droppable = kept.some((segment) => segment.dropRank !== undefined);
if (!droppable) break;
const lowest = Math.min(
...kept.flatMap((segment) => (segment.dropRank !== undefined ? [segment.dropRank] : [])),
);
// A segment with a shortened form degrades to it before dropping.
const shorten = kept.find(
(segment) => segment.dropRank === lowest && segment.shortenedText !== undefined,
);
if (shorten) {
kept = kept.map((segment) =>
segment === shorten
? { ...segment, text: segment.shortenedText ?? segment.text, shortenedText: undefined }
: segment,
);
} else {
kept = kept.filter((segment) => segment.dropRank !== lowest);
}
}
// Last resort for still-oversized lines (e.g. a long model id alone):
// the previous hard truncation.
return fitLine(kept.map((segment) => segment.text).join(sep), width);
}

/**
Expand Down