feat: Add rich Claude status animations to FAB

- Add multiple hook-driven animations for FAB (processing, reading, writing, subagent, sessionStart, notification)
- Create claude-status.ts route to handle status updates from Claude Code hooks
- Broadcast status via WebSocket to all connected clients
- Processing (UserPromptSubmit→Stop): orange pulsing dots
- Reading (Read/Glob/Grep): cyan eye icon with scan animation
- Writing (Edit/Write): green pencil icon with pulse
- Subagent: purple orbital ring animation
- SessionStart: green wake-up ripple effect (3s)
- Notification: yellow bounce animation (2s)
- Tool flash: quick white flash on any tool use
This commit is contained in:
2026-02-14 02:42:30 -06:00
parent d5a426f17d
commit d9e2548fb8
4 changed files with 479 additions and 12 deletions

View File

@@ -77,7 +77,7 @@ function getOrCreateSession(sessionId: string = DEFAULT_SESSION_ID): TerminalSes
export function startTerminalServer() {
const server = Bun.serve({
port: PORT_TERMINAL,
fetch(req, server) {
async fetch(req, server) {
const url = new URL(req.url)
const corsHeaders = {
@@ -113,6 +113,17 @@ export function startTerminalServer() {
return Response.json({ sessions: list })
}
// Claude status broadcast endpoint
if (url.pathname === '/claude-status' && req.method === 'POST') {
try {
const body = await req.json() as { status: ClaudeStatus, tool?: string }
broadcastClaudeStatus(body.status, body.tool)
return Response.json({ success: true }, { headers: corsHeaders })
} catch {
return Response.json({ error: 'Invalid JSON' }, { status: 400, headers: corsHeaders })
}
}
// Check if this is a WebSocket upgrade request
const upgradeHeader = req.headers.get('upgrade')
console.log(`[Terminal] Request: ${req.method} ${url.pathname}, Upgrade: ${upgradeHeader}`)
@@ -201,3 +212,30 @@ export function startTerminalServer() {
console.log(`[Terminal] WebSocket running at ws://localhost:${PORT_TERMINAL}`)
return server
}
// Claude status types
type ClaudeStatus = 'idle' | 'processing' | 'toolUse' | 'toolDone' | 'reading' | 'writing' | 'sessionStart' | 'subagentStart' | 'subagentStop' | 'notification' | 'thinking'
// Broadcast Claude status to ALL clients across ALL sessions
export function broadcastClaudeStatus(status: ClaudeStatus, tool?: string) {
const message = JSON.stringify({
type: 'claude-status',
status,
tool,
timestamp: Date.now()
})
let clientCount = 0
for (const [, session] of sessions) {
for (const ws of session.clients) {
try {
ws.send(message)
clientCount++
} catch {
// Client disconnected, ignore
}
}
}
console.log(`[Terminal] Claude status broadcast: ${status}${tool ? ` (${tool})` : ''}${clientCount} clients`)
}