diff --git a/packages/cli/src/tui/app.tsx b/packages/cli/src/tui/app.tsx
index 889247a..0214d1f 100644
--- a/packages/cli/src/tui/app.tsx
+++ b/packages/cli/src/tui/app.tsx
@@ -47,13 +47,20 @@ export function TuiApp({ gatewayUrl, conversationId, sessionCookie }: TuiAppProp
activeToolCalls={socket.activeToolCalls}
/>
-
-
+
+
);
}
diff --git a/packages/cli/src/tui/components/bottom-bar.tsx b/packages/cli/src/tui/components/bottom-bar.tsx
index 6d00e21..7c494db 100644
--- a/packages/cli/src/tui/components/bottom-bar.tsx
+++ b/packages/cli/src/tui/components/bottom-bar.tsx
@@ -6,55 +6,101 @@ import type { GitInfo } from '../hooks/use-git-info.js';
export interface BottomBarProps {
gitInfo: GitInfo;
tokenUsage: TokenUsage;
+ connected: boolean;
+ connecting: boolean;
+ modelName: string | null;
+ providerName: string | null;
}
function formatTokens(n: number): string {
if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
- if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;
+ if (n >= 1_000) return `${(n / 1_000).toFixed(0)}k`;
return String(n);
}
-/** Compact the cwd — show ~ for home, truncate long paths */
+/** Compact the cwd — replace home with ~ */
function compactCwd(cwd: string): string {
const home = process.env['HOME'] ?? '';
if (home && cwd.startsWith(home)) {
- cwd = '~' + cwd.slice(home.length);
- }
- // If still very long, show last 3 segments
- const parts = cwd.split('/');
- if (parts.length > 4) {
- return '…/' + parts.slice(-3).join('/');
+ return '~' + cwd.slice(home.length);
}
return cwd;
}
-export function BottomBar({ gitInfo, tokenUsage }: BottomBarProps) {
+export function BottomBar({
+ gitInfo,
+ tokenUsage,
+ connected,
+ connecting,
+ modelName,
+ providerName,
+}: BottomBarProps) {
+ const gatewayStatus = connected ? 'Connected' : connecting ? 'Connecting…' : 'Disconnected';
+ const gatewayColor = connected ? 'green' : connecting ? 'yellow' : 'red';
+
const hasTokens = tokenUsage.total > 0;
return (
-
-
- cwd:
- {compactCwd(gitInfo.cwd)}
- {gitInfo.branch && (
- <>
- ⎇
- {gitInfo.branch}
- >
- )}
+
+ {/* Line 1: path (branch) ····· Gateway: Status */}
+
+
+ {compactCwd(gitInfo.cwd)}
+ {gitInfo.branch && ({gitInfo.branch})}
+
+
+ Gateway:
+ {gatewayStatus}
+
-
- {hasTokens ? (
- <>
- tokens:
- ↑{formatTokens(tokenUsage.input)}
- /
- ↓{formatTokens(tokenUsage.output)}
- ({formatTokens(tokenUsage.total)})
- >
- ) : (
- tokens: —
- )}
+
+ {/* Line 2: token stats ····· (provider) model */}
+
+
+ {hasTokens ? (
+ <>
+ ^{formatTokens(tokenUsage.input)}
+ {' '}
+ v{formatTokens(tokenUsage.output)}
+ {tokenUsage.cacheRead > 0 && (
+ <>
+ {' '}
+ R{formatTokens(tokenUsage.cacheRead)}
+ >
+ )}
+ {tokenUsage.cacheWrite > 0 && (
+ <>
+ {' '}
+ W{formatTokens(tokenUsage.cacheWrite)}
+ >
+ )}
+ {tokenUsage.cost > 0 && (
+ <>
+ {' '}
+ ${tokenUsage.cost.toFixed(3)}
+ >
+ )}
+ {tokenUsage.contextPercent > 0 && (
+ <>
+ {' '}
+
+ {tokenUsage.contextPercent.toFixed(1)}%/{formatTokens(tokenUsage.contextWindow)}
+
+ >
+ )}
+ >
+ ) : (
+ —
+ )}
+
+
+ {(providerName ?? modelName) && (
+
+ {providerName ? `(${providerName}) ` : ''}
+ {modelName ?? ''}
+
+ )}
+
);
diff --git a/packages/cli/src/tui/components/input-bar.tsx b/packages/cli/src/tui/components/input-bar.tsx
index 6f65ef6..ab02c2f 100644
--- a/packages/cli/src/tui/components/input-bar.tsx
+++ b/packages/cli/src/tui/components/input-bar.tsx
@@ -26,12 +26,10 @@ export function InputBar({ onSubmit, isStreaming, connected }: InputBarProps) {
? 'waiting for response…'
: 'message mosaic…';
- const promptColor = !connected ? 'red' : isStreaming ? 'yellow' : 'green';
-
return (
-
-
- ❯{' '}
+
+
+ {'❯ '}
void;
connectionError: string | null;
}
@@ -65,8 +71,18 @@ export function useSocket(opts: UseSocketOptions): UseSocketReturn {
const [currentThinkingText, setCurrentThinkingText] = useState('');
const [activeToolCalls, setActiveToolCalls] = useState([]);
// TODO: wire up once gateway emits token-usage and model-info events
- const tokenUsage: TokenUsage = { input: 0, output: 0, total: 0 };
+ const tokenUsage: TokenUsage = {
+ input: 0,
+ output: 0,
+ total: 0,
+ cacheRead: 0,
+ cacheWrite: 0,
+ cost: 0,
+ contextPercent: 0,
+ contextWindow: 0,
+ };
const modelName: string | null = null;
+ const providerName: string | null = null;
const [connectionError, setConnectionError] = useState(null);
const socketRef = useRef(null);
@@ -191,6 +207,7 @@ export function useSocket(opts: UseSocketOptions): UseSocketReturn {
activeToolCalls,
tokenUsage,
modelName,
+ providerName,
sendMessage,
connectionError,
};