Files
stack/packages/cli/src/tui/app.tsx
Jason Woltje 4d5cc5990a feat(cli): branded top bar with mosaic windmill icon
- ASCII art mosaic windmill: 4 colored tiles (blue, purple, teal, amber)
  with pink center, matching the Mosaic Stack brand
- 3-line info block (Claude Code style):
  Line 1: 'Mosaic Stack v0.0.0'
  Line 2: model (context) · thinking · agent name
  Line 3: ● host connection status
- Remove bordered box in favor of open layout with icon
2026-03-15 14:28:28 -05:00

83 lines
2.3 KiB
TypeScript

import React from 'react';
import { Box, useApp, useInput } from 'ink';
import { TopBar } from './components/top-bar.js';
import { BottomBar } from './components/bottom-bar.js';
import { MessageList } from './components/message-list.js';
import { InputBar } from './components/input-bar.js';
import { useSocket } from './hooks/use-socket.js';
import { useGitInfo } from './hooks/use-git-info.js';
export interface TuiAppProps {
gatewayUrl: string;
conversationId?: string;
sessionCookie?: string;
}
export function TuiApp({ gatewayUrl, conversationId, sessionCookie }: TuiAppProps) {
const { exit } = useApp();
const gitInfo = useGitInfo();
const socket = useSocket({
gatewayUrl,
sessionCookie,
initialConversationId: conversationId,
});
useInput((ch, key) => {
if (key.ctrl && ch === 'c') {
exit();
}
// Ctrl+T: cycle thinking level
if (key.ctrl && ch === 't') {
const levels = socket.availableThinkingLevels;
if (levels.length > 0) {
const currentIdx = levels.indexOf(socket.thinkingLevel);
const nextIdx = (currentIdx + 1) % levels.length;
const next = levels[nextIdx];
if (next) {
socket.setThinkingLevel(next);
}
}
}
});
return (
<Box flexDirection="column" height="100%">
<TopBar
gatewayUrl={gatewayUrl}
version="0.0.0"
modelName={socket.modelName}
thinkingLevel={socket.thinkingLevel}
contextWindow={socket.tokenUsage.contextWindow}
agentName="default"
connected={socket.connected}
connecting={socket.connecting}
/>
<MessageList
messages={socket.messages}
isStreaming={socket.isStreaming}
currentStreamText={socket.currentStreamText}
currentThinkingText={socket.currentThinkingText}
activeToolCalls={socket.activeToolCalls}
/>
<InputBar
onSubmit={socket.sendMessage}
isStreaming={socket.isStreaming}
connected={socket.connected}
/>
<BottomBar
gitInfo={gitInfo}
tokenUsage={socket.tokenUsage}
connected={socket.connected}
connecting={socket.connecting}
modelName={socket.modelName}
providerName={socket.providerName}
thinkingLevel={socket.thinkingLevel}
/>
</Box>
);
}