@@ -45,6 +45,7 @@ import {
4545} from '@maka/core/tool-result-status' ;
4646import { type ShellRunUpdate } from '@maka/core/events' ;
4747import { homedir } from 'node:os' ;
48+ import { basename } from 'node:path' ;
4849import type { MakaSessionDriver } from './session-driver.js' ;
4950import { BoundedChunkBuffer } from './bounded-chunk-buffer.js' ;
5051import { ansi } from './tui-ansi.js' ;
@@ -1329,20 +1330,25 @@ export function permissionModeLabel(mode: string): string {
13291330export function renderMakaPiStatusLine ( metadata : MakaPiTranscriptMetadata , width : number ) : string {
13301331 const safeWidth = Math . max ( 1 , width ) ;
13311332 const sep = ansi . dim ( ' · ' ) ;
1332- const parts : string [ ] = [
1333- ansi . bold ( metadata . title ) ,
1334- ansi . dim ( permissionModeLabel ( metadata . permissionMode ) ) ,
1335- ansi . dim ( metadata . model ) ,
1333+ // #3421: segments carry a dropRank so overflow drops whole low-value
1334+ // segments instead of cutting the chain mid-token from the right.
1335+ // Lower ranks drop first; segments without a rank never drop:
1336+ // title, permission mode and goal are safety-relevant, ctx is the
1337+ // context budget, model is the session's identity.
1338+ const parts : MakaPiStatusLineSegment [ ] = [
1339+ { text : ansi . bold ( metadata . title ) } ,
1340+ { text : ansi . dim ( permissionModeLabel ( metadata . permissionMode ) ) } ,
1341+ { text : ansi . dim ( metadata . model ) } ,
13361342 ] ;
13371343 // #1064: omit thinking:default — it is noise before the user explicitly
13381344 // changes the level. Only a non-default, explicitly set level shows.
13391345 if ( metadata . thinkingLevel ) {
1340- parts . push ( ansi . dim ( `thinking:${ metadata . thinkingLevel } ` ) ) ;
1346+ parts . push ( { text : ansi . dim ( `thinking:${ metadata . thinkingLevel } ` ) , dropRank : 3 } ) ;
13411347 }
13421348 if ( metadata . orchestrationMode === 'swarm' ) {
1343- parts . push ( ansi . accent ( 'swarm' ) ) ;
1349+ parts . push ( { text : ansi . accent ( 'swarm' ) , dropRank : 4 } ) ;
13441350 } else if ( metadata . orchestrationMode === 'graph' ) {
1345- parts . push ( ansi . accent ( 'graph' ) ) ;
1351+ parts . push ( { text : ansi . accent ( 'graph' ) , dropRank : 4 } ) ;
13461352 }
13471353 // An autonomous goal burns tokens between prompts; it must never be
13481354 // invisible. Terminal goals show nothing (the desktop chip hides them too).
@@ -1351,13 +1357,14 @@ export function renderMakaPiStatusLine(metadata: MakaPiTranscriptMetadata, width
13511357 // paused gets warning salience: the loop stopped burning but stays armed
13521358 // and resumable, which the user must not miss. waiting is a normal
13531359 // transient between turns, so it stays dim like the other chrome.
1354- parts . push (
1355- metadata . goal . status === 'active'
1356- ? ansi . accent ( text )
1357- : metadata . goal . status === 'paused'
1358- ? ansi . yellow ( text )
1359- : ansi . dim ( text ) ,
1360- ) ;
1360+ parts . push ( {
1361+ text :
1362+ metadata . goal . status === 'active'
1363+ ? ansi . accent ( text )
1364+ : metadata . goal . status === 'paused'
1365+ ? ansi . yellow ( text )
1366+ : ansi . dim ( text ) ,
1367+ } ) ;
13611368 }
13621369 const usage = metadata . usage ;
13631370 // ctx segment: only show "used" when contextRemaining is available, since
@@ -1370,32 +1377,82 @@ export function renderMakaPiStatusLine(metadata: MakaPiTranscriptMetadata, width
13701377 const pct = Math . round ( ( used / metadata . modelContextWindow ) * 100 ) ;
13711378 // #1064: color warning — yellow >80%, red >95%, dim otherwise.
13721379 const ctxColor = pct > 95 ? ansi . red : pct > 80 ? ansi . yellow : ansi . dim ;
1373- parts . push (
1374- ctxColor (
1380+ parts . push ( {
1381+ text : ctxColor (
13751382 `ctx ${ formatTokenCount ( used ) } /${ formatTokenCount ( metadata . modelContextWindow ) } ${ pct } %` ,
13761383 ) ,
1377- ) ;
1384+ } ) ;
13781385 } else if ( metadata . modelContextWindow !== undefined ) {
13791386 // #3371: the window is known but no usage has arrived yet (fresh session,
13801387 // or the provider doesn't report per-step input tokens). Degrade
13811388 // explicitly, pi-style, instead of hiding the segment silently — the user
13821389 // can then tell "not measured yet" apart from "window unknown".
1383- parts . push ( ansi . dim ( `ctx ?/${ formatTokenCount ( metadata . modelContextWindow ) } ` ) ) ;
1390+ parts . push ( { text : ansi . dim ( `ctx ?/${ formatTokenCount ( metadata . modelContextWindow ) } ` ) } ) ;
13841391 }
13851392 if ( usage ) {
13861393 if ( usage . costUsd > 0 ) {
1387- parts . push ( ansi . dim ( `$${ formatCost ( usage . costUsd ) } ` ) ) ;
1394+ parts . push ( { text : ansi . dim ( `$${ formatCost ( usage . costUsd ) } ` ) , dropRank : 1 } ) ;
13881395 }
13891396 const totalCache = usage . cacheHitInput + usage . cacheMissInput ;
13901397 if ( totalCache > 0 ) {
13911398 const hitRate = Math . round ( ( usage . cacheHitInput / totalCache ) * 100 ) ;
1392- parts . push ( ansi . dim ( `cache ${ hitRate } %` ) ) ;
1399+ parts . push ( { text : ansi . dim ( `cache ${ hitRate } %` ) , dropRank : 0 } ) ;
13931400 }
13941401 }
1395- parts . push ( ansi . dim ( metadata . connectionSlug ) ) ;
1402+ parts . push ( { text : ansi . dim ( metadata . connectionSlug ) , dropRank : 2 } ) ;
13961403 // #1064: shorten cwd to ~-relative path instead of the full path.
1397- parts . push ( ansi . dim ( shortenCwd ( metadata . cwd ) ) ) ;
1398- return fitLine ( parts . join ( sep ) , safeWidth ) ;
1404+ const cwd = shortenCwd ( metadata . cwd ) ;
1405+ // cwd degrades progressively (full → basename → dropped), after every
1406+ // ranked segment above but before the final truncation fallback. A drive
1407+ // root (C:\) or filesystem root has no useful basename — empty, or the
1408+ // path itself — so it drops directly instead of rendering an empty
1409+ // segment after the separator.
1410+ const cwdBase = basename ( cwd ) ;
1411+ parts . push ( {
1412+ text : ansi . dim ( cwd ) ,
1413+ dropRank : 5 ,
1414+ shortenedText : cwdBase === '' || cwdBase === cwd ? undefined : ansi . dim ( cwdBase ) ,
1415+ } ) ;
1416+ return fitStatusLine ( parts , sep , safeWidth ) ;
1417+ }
1418+
1419+ interface MakaPiStatusLineSegment {
1420+ text : string ;
1421+ /** Overflow drops whole segments lowest-rank-first; undefined never drops. */
1422+ dropRank ?: number ;
1423+ /** Progressive fallback tried before this segment is dropped entirely. */
1424+ shortenedText ?: string ;
1425+ }
1426+
1427+ function fitStatusLine ( segments : MakaPiStatusLineSegment [ ] , sep : string , width : number ) : string {
1428+ const lineWidth = ( segs : MakaPiStatusLineSegment [ ] ) : number =>
1429+ visibleWidth ( segs . map ( ( segment ) => segment . text ) . join ( sep ) ) ;
1430+ let kept = segments ;
1431+ // Drop whole low-value segments, lowest rank first, re-checking after each
1432+ // rank so the fewest possible segments are sacrificed.
1433+ while ( lineWidth ( kept ) > width ) {
1434+ const droppable = kept . some ( ( segment ) => segment . dropRank !== undefined ) ;
1435+ if ( ! droppable ) break ;
1436+ const lowest = Math . min (
1437+ ...kept . flatMap ( ( segment ) => ( segment . dropRank !== undefined ? [ segment . dropRank ] : [ ] ) ) ,
1438+ ) ;
1439+ // A segment with a shortened form degrades to it before dropping.
1440+ const shorten = kept . find (
1441+ ( segment ) => segment . dropRank === lowest && segment . shortenedText !== undefined ,
1442+ ) ;
1443+ if ( shorten ) {
1444+ kept = kept . map ( ( segment ) =>
1445+ segment === shorten
1446+ ? { ...segment , text : segment . shortenedText ?? segment . text , shortenedText : undefined }
1447+ : segment ,
1448+ ) ;
1449+ } else {
1450+ kept = kept . filter ( ( segment ) => segment . dropRank !== lowest ) ;
1451+ }
1452+ }
1453+ // Last resort for still-oversized lines (e.g. a long model id alone):
1454+ // the previous hard truncation.
1455+ return fitLine ( kept . map ( ( segment ) => segment . text ) . join ( sep ) , width ) ;
13991456}
14001457
14011458/**
0 commit comments