@wrongstack/webui 0.73.1 → 0.82.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/index-D1cZ__pQ.js +94 -0
- package/dist/assets/index-DB5NTtW7.css +1 -0
- package/dist/assets/vendor-CumDpIdV.js +81 -0
- package/dist/index.css +23 -0
- package/dist/index.css.map +1 -1
- package/dist/index.html +3 -3
- package/dist/index.js +284 -73
- package/dist/index.js.map +1 -1
- package/dist/server/entry.js +59 -12
- package/dist/server/entry.js.map +1 -1
- package/dist/server/index.d.ts +14 -14
- package/dist/server/index.js +59 -12
- package/dist/server/index.js.map +1 -1
- package/package.json +5 -5
- package/dist/assets/index-BH3RI9-8.js +0 -94
- package/dist/assets/index-C_0-qbQ-.css +0 -1
- package/dist/assets/vendor-DBuK7aZd.js +0 -546
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/main.tsx","../src/lib/favicon.ts","../src/lib/ws-client.ts","../src/stores/chat-store.ts","../src/stores/config-store.ts","../src/stores/session-store.ts","../src/stores/ui-store.ts","../src/stores/history-store.ts","../src/stores/worktree-store.ts","../src/stores/fleet-store.ts","../src/hooks/useWebSocket.ts","../src/lib/utils.ts","../src/components/Toaster.tsx","../src/lib/chime.ts","../src/lib/notify.ts","../src/hooks/ws-handlers.ts","../src/App.tsx","../src/components/ChatView/index.tsx","../src/components/ChatInput.tsx","../src/components/CommandPalette/index.tsx","../src/components/CommandPalette/export-utils.ts","../src/components/FilePicker.tsx","../src/components/ui/button.tsx","../src/components/ChatInput/slash-commands.ts","../src/components/ConnectionChip.tsx","../src/components/ContextModePicker.tsx","../src/components/CostChip.tsx","../src/lib/tool-summary.ts","../src/components/MessageBubble/index.tsx","../src/components/DiffView.tsx","../src/components/ToolResult.tsx","../src/components/MessageBubble/CopyButton.tsx","../src/components/MessageBubble/utils.tsx","../src/components/MessageBubble/ErrorBody.tsx","../src/components/MessageBubble/ToolInputView.tsx","../src/components/ModePicker.tsx","../src/components/SearchOverlay.tsx","../src/components/ThemeToggle.tsx","../src/components/ThemeProvider.tsx","../src/components/ToolGroup.tsx","../src/components/WelcomeScreen.tsx","../src/components/ui/scroll-area.tsx","../src/components/ChatView/utils.ts","../src/components/ChatView/ThinkingBubble.tsx","../src/components/CollabPanel.tsx","../src/components/ConfirmDialog.tsx","../src/components/ui/dialog.tsx","../src/components/ConnectionBanner.tsx","../src/components/ErrorBoundary.tsx","../src/components/FleetPanel.tsx","../src/components/QuickModelSwitcher.tsx","../src/components/SettingsPanel/index.tsx","../src/components/ui/input.tsx","../src/components/ui/tabs.tsx","../src/components/SettingsPanel/PreferenceToggle.tsx","../src/components/SettingsPanel/ProviderSection.tsx","../src/components/SettingsPanel/ModelSection.tsx","../src/components/ShortcutsOverlay.tsx","../src/components/Sidebar/index.tsx","../src/components/Sidebar/ConfigSection.tsx","../src/components/Sidebar/SessionActions.tsx","../src/components/Sidebar/SessionList.tsx"],"sourcesContent":["import React from 'react';\nimport ReactDOM from 'react-dom/client';\n// Self-hosted fonts (CSP-clean: served from 'self'). IBM Plex gives the UI an\n// engineering-instrument character — Plex Sans (variable) for UI text, Plex\n// Mono for data readouts, labels, and code.\nimport '@fontsource-variable/ibm-plex-sans';\nimport '@fontsource/ibm-plex-mono/400.css';\nimport '@fontsource/ibm-plex-mono/500.css';\nimport '@fontsource/ibm-plex-mono/600.css';\nimport { App } from './App';\nimport './index.css';\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n <React.StrictMode>\n <App />\n </React.StrictMode>,\n);\n","/**\n * Dynamic favicon helper. We don't ship a `.ico` file — the icon is built at\n * runtime as an inline SVG data URL so it can be re-rendered with or without\n * a status badge.\n *\n * setFaviconStatus('idle') → plain \"W\" mark\n * setFaviconStatus('running') → \"W\" + amber pulse dot (running indicator)\n * setFaviconStatus('ready') → \"W\" + green dot (run finished, tab hidden)\n * setFaviconStatus('error') → \"W\" + red dot (run failed, tab hidden)\n * setFaviconStatus('attention') → \"W\" + yellow dot (approval needed, tab hidden)\n *\n * The status auto-resets to 'idle' on the next visibilitychange where the\n * tab becomes visible — so the badge only persists while the user is away.\n */\n\nexport type FaviconStatus = 'idle' | 'running' | 'ready' | 'error' | 'attention';\n\nconst BASE_BG = '#4f46e5'; // indigo-600, matches the topbar Zap mark.\n\nfunction buildSvg(status: FaviconStatus): string {\n const badge = (() => {\n if (status === 'ready')\n return '<circle cx=\"50\" cy=\"14\" r=\"14\" fill=\"#22c55e\" stroke=\"#fff\" stroke-width=\"3\" />';\n if (status === 'error')\n return '<circle cx=\"50\" cy=\"14\" r=\"14\" fill=\"#ef4444\" stroke=\"#fff\" stroke-width=\"3\" />';\n if (status === 'running')\n return '<circle cx=\"50\" cy=\"14\" r=\"14\" fill=\"#f59e0b\" stroke=\"#fff\" stroke-width=\"3\" />';\n if (status === 'attention')\n return '<circle cx=\"50\" cy=\"14\" r=\"14\" fill=\"#eab308\" stroke=\"#fff\" stroke-width=\"3\"><animate attributeName=\"opacity\" values=\"1;0.3;1\" dur=\"1s\" repeatCount=\"indefinite\"/></circle>';\n return '';\n })();\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 64 64\">\n <rect x=\"2\" y=\"2\" width=\"60\" height=\"60\" rx=\"14\" fill=\"${BASE_BG}\" />\n <text x=\"32\" y=\"44\" text-anchor=\"middle\" font-family=\"-apple-system,Segoe UI,Roboto,sans-serif\" font-size=\"38\" font-weight=\"700\" fill=\"#fff\">W</text>\n ${badge}\n </svg>`;\n}\n\nfunction svgToDataUrl(svg: string): string {\n // encodeURIComponent keeps the URL valid across browsers; btoa would\n // also work but breaks on non-ASCII (not a concern here, but cleaner).\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;\n}\n\nfunction ensureLink(): HTMLLinkElement | null {\n if (typeof document === 'undefined') return null;\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"icon\"]');\n if (!link) {\n link = document.createElement('link');\n link.rel = 'icon';\n link.type = 'image/svg+xml';\n document.head.appendChild(link);\n }\n return link;\n}\n\nlet currentStatus: FaviconStatus = 'idle';\n\nexport function setFaviconStatus(status: FaviconStatus): void {\n currentStatus = status;\n const link = ensureLink();\n if (!link) return;\n link.href = svgToDataUrl(buildSvg(status));\n}\n\nlet visibilityHookInstalled = false;\n\n/** Install the visibilitychange listener once. When the user comes back to\n * the tab we clear any \"ready/error\" badge so they don't see a stale\n * notification dot after they've already returned. */\nexport function installFaviconVisibilityReset(): void {\n if (visibilityHookInstalled || typeof document === 'undefined') return;\n visibilityHookInstalled = true;\n document.addEventListener('visibilitychange', () => {\n if (!document.hidden && (currentStatus === 'ready' || currentStatus === 'error' || currentStatus === 'attention')) {\n setFaviconStatus('idle');\n }\n });\n}\n","import type { WSClientMessage, WSServerMessage } from '../types';\r\n\r\ntype EventHandler = (msg: WSServerMessage) => void;\r\n\r\ninterface PendingConfirm {\r\n resolve: (decision: 'yes' | 'no' | 'always' | 'deny') => void;\r\n}\r\n\r\n/** Internal connection lifecycle states the UI subscribes to. */\r\nexport type WsStatus =\r\n | { state: 'connecting' }\r\n | { state: 'open' }\r\n | { state: 'closed'; error?: string }\r\n | { state: 'reconnecting'; attempt: number; nextRetryAt: number; lastError?: string };\r\n\r\nconst WS_TOKEN_KEY = 'ws_token';\r\n\r\n/** Read wsToken from sessionStorage (survives page refresh, cleared on tab close). */\r\nfunction getStoredToken(): string | null {\r\n try {\r\n return sessionStorage.getItem(WS_TOKEN_KEY);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** Store wsToken in sessionStorage. */\r\nfunction setStoredToken(token: string): void {\r\n try {\r\n sessionStorage.setItem(WS_TOKEN_KEY, token);\r\n } catch {\r\n /* sessionStorage unavailable (private browsing quota, etc.) — degrade gracefully */\r\n }\r\n}\r\n\r\n/** Clear wsToken from sessionStorage. */\r\nfunction clearStoredToken(): void {\r\n try {\r\n sessionStorage.removeItem(WS_TOKEN_KEY);\r\n } catch {\r\n /* best-effort */\r\n }\r\n}\r\n\r\nexport class WrongStackWebSocketClient {\r\n private ws: WebSocket | null = null;\r\n private url: string;\r\n private handlers: Map<string, Set<EventHandler>> = new Map();\r\n private reconnectAttempts = 0;\r\n private maxReconnectAttempts = 10;\r\n private reconnectDelay = 1000;\r\n private shouldReconnect = true;\r\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\r\n private messageQueue: WSClientMessage[] = [];\r\n private pendingConfirms: Map<string, PendingConfirm> = new Map();\r\n private sessionId: string | null = null;\r\n /** Stored last close reason / error message so the UI can show \"what\r\n * went wrong\" while reconnecting instead of a generic spinner. */\r\n private lastErrorText: string | undefined;\r\n private statusListeners = new Set<(s: WsStatus) => void>();\r\n private currentStatus: WsStatus = { state: 'connecting' };\r\n\r\n onStatus(fn: (s: WsStatus) => void): () => void {\r\n this.statusListeners.add(fn);\r\n fn(this.currentStatus);\r\n return () => this.statusListeners.delete(fn);\r\n }\r\n\r\n get status(): WsStatus {\r\n return this.currentStatus;\r\n }\r\n\r\n private setStatus(s: WsStatus) {\r\n this.currentStatus = s;\r\n for (const fn of this.statusListeners) {\r\n try {\r\n fn(s);\r\n } catch {\r\n /* listener errors must not break the socket */\r\n }\r\n }\r\n }\r\n\r\n constructor(url?: string) {\r\n this.url = url ?? defaultWsUrl();\r\n }\r\n\r\n async connect(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n if (this.ws?.readyState === WebSocket.OPEN) {\r\n resolve();\r\n return;\r\n }\r\n\r\n this.setStatus({ state: 'connecting' });\r\n\r\n try {\r\n // Include auth token from sessionStorage if available (from session.start).\r\n // Initial connect to loopback is exempt, but reconnections should\r\n // carry the token for defense-in-depth.\r\n const storedToken = getStoredToken();\r\n const wsUrl = storedToken\r\n ? `${this.url}${this.url.includes('?') ? '&' : '?'}token=${storedToken}`\r\n : this.url;\r\n this.ws = new WebSocket(wsUrl);\r\n this.ws.binaryType = 'arraybuffer';\r\n\r\n const connectTimeout = setTimeout(() => {\r\n reject(new Error('Connection timeout'));\r\n }, 10000);\r\n\r\n // Track whether the connection was ever established so onerror and\r\n // onclose know whether to reject the promise or just attempt a\r\n // reconnect. Without this, a connection failure leaves callers\r\n // awaiting connect() hanging forever.\r\n let established = false;\r\n\r\n this.ws.onopen = () => {\r\n clearTimeout(connectTimeout);\r\n established = true;\r\n console.log('[WS Client] Connected');\r\n this.reconnectAttempts = 0;\r\n this.lastErrorText = undefined;\r\n this.setStatus({ state: 'open' });\r\n this.flushMessageQueue();\r\n resolve();\r\n };\r\n\r\n this.ws.onmessage = (event) => {\r\n try {\r\n const msg = JSON.parse(event.data) as WSServerMessage;\r\n this.handleMessage(msg);\r\n } catch (err) {\r\n console.error('[WS Client] Failed to parse message', err);\r\n }\r\n };\r\n\r\n this.ws.onerror = (error) => {\r\n console.error('[WS Client] Error', error);\r\n // ErrorEvent in browsers is intentionally opaque — Chrome won't\r\n // expose the underlying reason for security. We stash a generic\r\n // hint so the UI has something to display.\r\n this.lastErrorText = 'Connection error (see browser devtools)';\r\n if (!established) {\r\n clearTimeout(connectTimeout);\r\n reject(new Error(this.lastErrorText));\r\n }\r\n };\r\n\r\n this.ws.onclose = (ev) => {\r\n console.log('[WS Client] Disconnected', ev.code, ev.reason);\r\n if (!established) {\r\n clearTimeout(connectTimeout);\r\n const reason = ev.reason || `Closed with code ${ev.code}`;\r\n this.lastErrorText = reason;\r\n reject(new Error(reason));\r\n return;\r\n }\r\n if (ev.reason && !this.lastErrorText) {\r\n this.lastErrorText = `${ev.reason} (code ${ev.code})`;\r\n } else if (!this.lastErrorText && ev.code !== 1000) {\r\n this.lastErrorText = `Closed with code ${ev.code}`;\r\n }\r\n this.attemptReconnect();\r\n };\r\n } catch (err) {\r\n this.lastErrorText = err instanceof Error ? err.message : String(err);\r\n this.setStatus({ state: 'closed', error: this.lastErrorText });\r\n reject(err);\r\n }\r\n });\r\n }\r\n\r\n private attemptReconnect() {\r\n if (!this.shouldReconnect || this.reconnectAttempts >= this.maxReconnectAttempts) {\r\n console.log('[WS Client] Not reconnecting');\r\n this.reconnectTimer = null;\r\n this.setStatus({ state: 'closed', error: this.lastErrorText ?? 'Disconnected' });\r\n return;\r\n }\r\n\r\n this.reconnectAttempts++;\r\n const delay = Math.min(this.reconnectDelay * 2 ** (this.reconnectAttempts - 1), 30000);\r\n const nextRetryAt = Date.now() + delay;\r\n console.log(`[WS Client] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\r\n this.setStatus({\r\n state: 'reconnecting',\r\n attempt: this.reconnectAttempts,\r\n nextRetryAt,\r\n lastError: this.lastErrorText,\r\n });\r\n\r\n this.reconnectTimer = setTimeout(async () => {\r\n if (this.shouldReconnect) {\r\n try {\r\n await this.connect();\r\n } catch (err) {\r\n console.error('[WS Client] Reconnect failed', err);\r\n }\r\n }\r\n }, delay);\r\n }\r\n\r\n /** Force an immediate reconnect attempt, bypassing the backoff timer. */\r\n retryNow(): void {\r\n if (this.currentStatus.state === 'open') return;\r\n if (this.reconnectTimer) {\r\n clearTimeout(this.reconnectTimer);\r\n this.reconnectTimer = null;\r\n }\r\n this.reconnectAttempts = 0;\r\n void this.connect().catch(() => undefined);\r\n }\r\n\r\n private flushMessageQueue() {\r\n while (this.messageQueue.length > 0) {\r\n const msg = this.messageQueue.shift();\r\n if (msg) this.send(msg);\r\n }\r\n }\r\n\r\n private handleMessage(msg: WSServerMessage) {\r\n if (msg.type === 'tool.confirm_needed') {\r\n const payload = msg.payload as unknown as {\r\n id: string;\r\n toolName: string;\r\n input: unknown;\r\n suggestedPattern: string;\r\n resolve: (d: 'yes' | 'no' | 'always' | 'deny') => void;\r\n };\r\n\r\n this.pendingConfirms.set(payload.id, {\r\n resolve: payload.resolve,\r\n });\r\n\r\n const msgForHandler = {\r\n ...msg,\r\n payload: {\r\n ...payload,\r\n resolve: () => {},\r\n },\r\n };\r\n\r\n this.emit(msgForHandler as WSServerMessage);\r\n return;\r\n }\r\n\r\n if (msg.type === 'session.start') {\r\n const payload = msg.payload as { sessionId: string; wsToken?: string };\r\n this.sessionId = payload.sessionId;\r\n if (payload.wsToken) {\r\n setStoredToken(payload.wsToken);\r\n }\r\n }\r\n\r\n this.emit(msg);\r\n }\r\n\r\n private emit(msg: WSServerMessage) {\r\n const handlers = this.handlers.get(msg.type);\r\n if (handlers) {\r\n for (const handler of handlers) {\r\n try {\r\n handler(msg);\r\n } catch (err) {\r\n console.error(`[WS Client] Handler error for ${msg.type}`, err);\r\n }\r\n }\r\n }\r\n }\r\n\r\n send(message: WSClientMessage) {\r\n if (this.ws?.readyState === WebSocket.OPEN) {\r\n this.ws.send(JSON.stringify(message));\r\n } else {\r\n this.messageQueue.push(message);\r\n }\r\n }\r\n\r\n on(eventType: string, handler: EventHandler): () => void {\r\n let handlers = this.handlers.get(eventType);\r\n if (!handlers) {\r\n handlers = new Set();\r\n this.handlers.set(eventType, handlers);\r\n }\r\n handlers.add(handler);\r\n return () => handlers?.delete(handler);\r\n }\r\n\r\n off(eventType: string, handler: EventHandler) {\r\n this.handlers.get(eventType)?.delete(handler);\r\n }\r\n\r\n sendMessage(content: string): string {\r\n const id = `msg_${Date.now()}_${crypto.randomUUID().slice(0, 8)}`;\r\n this.send({\r\n type: 'user_message',\r\n payload: {\r\n id,\r\n content,\r\n timestamp: Date.now(),\r\n },\r\n });\r\n return id;\r\n }\r\n\r\n sendAbort() {\r\n this.send({\r\n type: 'abort',\r\n payload: {},\r\n } as unknown as WSClientMessage);\r\n }\r\n\r\n sendConfirm(id: string, decision: 'yes' | 'no' | 'always' | 'deny') {\r\n const pending = this.pendingConfirms.get(id);\r\n if (pending) {\r\n pending.resolve(decision);\r\n this.pendingConfirms.delete(id);\r\n }\r\n this.send({\r\n type: 'tool.confirm_result',\r\n payload: { id, decision },\r\n });\r\n }\r\n\r\n switchModel(provider: string, model: string) {\r\n this.send({\r\n type: 'model.switch',\r\n payload: { provider, model },\r\n });\r\n }\r\n\r\n // ---- Provider/Model/Key management (mirrors TUI/CLI auth-menu) ----\r\n\r\n listProviders() {\r\n this.send({ type: 'providers.list' });\r\n }\r\n\r\n listProviderModels(providerId: string) {\r\n this.send({ type: 'provider.models', payload: { providerId } });\r\n }\r\n\r\n listSavedProviders() {\r\n this.send({ type: 'providers.saved' });\r\n }\r\n\r\n addKey(providerId: string, label: string, apiKey: string) {\r\n this.send({ type: 'key.add', payload: { providerId, label, apiKey } });\r\n }\r\n\r\n updateKey(providerId: string, label: string, apiKey: string) {\r\n this.send({ type: 'key.update', payload: { providerId, label, apiKey } });\r\n }\r\n\r\n deleteKey(providerId: string, label: string) {\r\n this.send({ type: 'key.delete', payload: { providerId, label } });\r\n }\r\n\r\n setActiveKey(providerId: string, label: string) {\r\n this.send({ type: 'key.set_active', payload: { providerId, label } });\r\n }\r\n\r\n addProvider(id: string, family: string, baseUrl?: string, apiKey?: string) {\r\n this.send({ type: 'provider.add', payload: { id, family, baseUrl, apiKey } });\r\n }\r\n\r\n removeProvider(providerId: string) {\r\n this.send({ type: 'provider.remove', payload: { providerId } });\r\n }\r\n\r\n newSession() {\r\n this.send({ type: 'session.new' });\r\n }\r\n\r\n clearContext() {\r\n this.send({ type: 'context.clear' });\r\n }\r\n\r\n compactContext(aggressive = false) {\r\n this.send({ type: 'context.compact', payload: { aggressive } });\r\n }\r\n\r\n repairContext() {\r\n this.send({ type: 'context.repair' });\r\n }\r\n\r\n debugContext() {\r\n this.send({ type: 'context.debug' });\r\n }\r\n\r\n listContextModes() {\r\n this.send({ type: 'context.modes.list' });\r\n }\r\n\r\n switchContextMode(id: string) {\r\n this.send({ type: 'context.mode.switch', payload: { id } });\r\n }\r\n\r\n // ---- Inspect commands (mirror TUI/CLI's /tools /memory /skill /diag /stats) ----\r\n\r\n listTools() {\r\n this.send({ type: 'tools.list' });\r\n }\r\n\r\n listMemory() {\r\n this.send({ type: 'memory.list' });\r\n }\r\n\r\n remember(text: string, scope?: 'project-agents' | 'project-memory' | 'user-memory') {\r\n this.send({ type: 'memory.remember', payload: { text, scope } });\r\n }\r\n\r\n forget(text: string, scope?: 'project-agents' | 'project-memory' | 'user-memory') {\r\n this.send({ type: 'memory.forget', payload: { text, scope } });\r\n }\r\n\r\n listSkills() {\r\n this.send({ type: 'skills.list' });\r\n }\r\n\r\n getDiag() {\r\n this.send({ type: 'diag.get' });\r\n }\r\n\r\n getStats() {\r\n this.send({ type: 'stats.get' });\r\n }\r\n\r\n saveSession() {\r\n this.send({ type: 'session.save' });\r\n }\r\n\r\n resumeSessionById(id: string) {\r\n this.send({ type: 'session.resume', payload: { id } });\r\n }\r\n\r\n listModes() {\r\n this.send({ type: 'modes.list' });\r\n }\r\n\r\n switchMode(id: string) {\r\n this.send({ type: 'mode.switch', payload: { id } });\r\n }\r\n\r\n listFiles(query?: string, limit?: number) {\r\n this.send({ type: 'files.list', payload: { query, limit } });\r\n }\r\n\r\n getTodos() {\r\n this.send({ type: 'todos.get' });\r\n }\r\n\r\n clearTodos() {\r\n this.send({ type: 'todos.clear' });\r\n }\r\n\r\n listSessions(limit = 50) {\r\n this.send({ type: 'sessions.list', payload: { limit } });\r\n }\r\n\r\n deleteSession(id: string) {\r\n this.send({ type: 'session.delete', payload: { id } });\r\n }\r\n\r\n resumeSession(sessionId: string) {\r\n this.send({\r\n type: 'session.resume',\r\n payload: { id: sessionId },\r\n });\r\n }\r\n\r\n ping() {\r\n this.send({ type: 'ping' });\r\n }\r\n\r\n disconnect() {\r\n this.shouldReconnect = false;\r\n if (this.reconnectTimer) {\r\n clearTimeout(this.reconnectTimer);\r\n this.reconnectTimer = null;\r\n }\r\n this.ws?.close();\r\n this.ws = null;\r\n clearStoredToken();\r\n }\r\n\r\n get isConnected(): boolean {\r\n return this.ws?.readyState === WebSocket.OPEN;\r\n }\r\n\r\n get currentSessionId(): string | null {\r\n return this.sessionId;\r\n }\r\n}\r\n\r\nlet client: WrongStackWebSocketClient | null = null;\r\n\r\n/**\r\n * Default WS URL derived from the page's host.\r\n *\r\n * Subtle gotcha on Windows: when the page is loaded from `http://localhost:3456`,\r\n * the browser resolves `localhost` *itself* and on Windows it tries IPv6 `[::1]`\r\n * before IPv4 `127.0.0.1`. If the backend listens only on `127.0.0.1`, every\r\n * connection attempt to `ws://localhost:3457` first hits the IPv6 socket\r\n * (refused) and then either gives up or flaps — symptom: \"ws disconnect hep\".\r\n *\r\n * Fix: when the page is on a loopback host (`localhost` / `127.0.0.1` / `::1`),\r\n * force the WS URL to use the literal IPv4 loopback address. That bypasses the\r\n * DNS dance entirely. For any other hostname (LAN IP, custom WS_HOST override)\r\n * we keep the page's hostname so things still \"just work\".\r\n *\r\n * The WS port is NOT hardcoded: the HTTP server stamps the live port into the\r\n * served HTML as `<meta name=\"wrongstack-ws-port\">` (see http-server.ts), so\r\n * several WebUI instances can run on different PORT/WS_PORT pairs at once. We\r\n * fall back to 3457 only when the tag is absent (e.g. the vite dev server).\r\n */\r\nconst DEFAULT_WS_PORT = 3457;\r\n\r\nfunction resolveWsPort(): number {\r\n if (typeof document === 'undefined') return DEFAULT_WS_PORT;\r\n const raw = document\r\n .querySelector('meta[name=\"wrongstack-ws-port\"]')\r\n ?.getAttribute('content');\r\n const parsed = raw ? Number.parseInt(raw, 10) : Number.NaN;\r\n return Number.isFinite(parsed) && parsed > 0 && parsed < 65536 ? parsed : DEFAULT_WS_PORT;\r\n}\r\n\r\nfunction defaultWsUrl(): string {\r\n const port = resolveWsPort();\r\n if (typeof window === 'undefined' || !window.location?.hostname) {\r\n return `ws://127.0.0.1:${port}`;\r\n }\r\n const host = window.location.hostname.toLowerCase();\r\n if (host === 'localhost' || host === '127.0.0.1' || host === '[::1]' || host === '::1') {\r\n return `ws://127.0.0.1:${port}`;\r\n }\r\n return `ws://${window.location.hostname}:${port}`;\r\n}\r\n\r\nexport function getWSClient(url?: string): WrongStackWebSocketClient {\r\n if (!client) {\r\n client = new WrongStackWebSocketClient(url);\r\n }\r\n return client;\r\n}\r\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport type { ChatMessage } from './types.js';\n\n/**\n * Strip immediately-repeated paragraphs/lines from an assistant reply.\n * MiniMax-M2.7 (and other smaller open models) sometimes emit the same\n * paragraph twice in one stream — we don't want that to land in the chat.\n * We only collapse *consecutive* duplicates so legitimate repetition\n * elsewhere in the message is preserved.\n */\nfunction dedupeRepeatedBlocks(text: string): string {\n if (!text) return text;\n const paraSplit = text.split(/\\n{2,}/);\n const paras: string[] = [];\n for (const p of paraSplit) {\n if (paras.length > 0 && paras[paras.length - 1]!.trim() === p.trim()) continue;\n paras.push(p);\n }\n const cleaned = paras.map((p) => {\n const lines = p.split('\\n');\n const out: string[] = [];\n for (const line of lines) {\n if (out.length > 0 && line.trim().length > 0 && out[out.length - 1]!.trim() === line.trim()) {\n continue;\n }\n out.push(line);\n }\n return out.join('\\n');\n });\n return cleaned.join('\\n\\n');\n}\n\n// ============================================\n// Chat Store\n// ============================================\n\ninterface ChatState {\n messages: ChatMessage[];\n currentAssistantMessageId: string | null;\n currentToolId: string | null;\n isLoading: boolean;\n abortController: AbortController | null;\n executions: Map<string, ToolExecution>;\n /** Messages typed while the agent was running. Drained one-at-a-time\n * after run.result lands so the user can stack up follow-ups without\n * waiting for each turn to finish. */\n queue: string[];\n /** Snapshot taken at the start of the current run (first iteration.started\n * after idle). Used by run.result to compute the per-turn summary —\n * duration is now-at minus this `at`, cost delta is the difference\n * between the session's current cost and the cost captured here. Null\n * while idle. */\n runStart: { at: number; cost: number } | null;\n /** Transient extended-thinking buffer. Populated by provider.thinking_delta\n * events and shown as a soft, ephemeral bubble below the chat tail while\n * the model is reasoning. Cleared the moment the model produces user-\n * facing output (text_delta) or starts a tool — and at provider.response /\n * run.result. Never persisted into `messages`, so refresh wipes it. */\n thinkingBuffer: string;\n /** Wall-clock ms when the current thinking burst started, for the chip's\n * elapsed timer. Reset alongside `thinkingBuffer`. */\n thinkingStartedAt: number | null;\n\n addMessage: (msg: Omit<ChatMessage, 'id' | 'timestamp'>) => string;\n updateMessage: (id: string, updates: Partial<ChatMessage>) => void;\n appendToMessage: (id: string, text: string) => void;\n finalizeMessage: (id: string) => void;\n setToolResult: (id: string, result: string, ok: boolean) => void;\n appendToolProgress: (id: string, line: string) => void;\n setLoading: (loading: boolean) => void;\n setAbortController: (ctrl: AbortController | null) => void;\n clearMessages: () => void;\n setCurrentAssistantMessage: (id: string | null) => void;\n setCurrentToolId: (id: string | null) => void;\n truncateAfter: (id: string) => void;\n addExecution: (exec: ToolExecution) => void;\n updateExecution: (id: string, updates: Partial<ToolExecution>) => void;\n enqueue: (text: string) => void;\n dequeue: () => string | null;\n removeQueued: (idx: number) => void;\n clearQueue: () => void;\n setRunStart: (s: { at: number; cost: number } | null) => void;\n appendThinking: (text: string) => void;\n clearThinking: () => void;\n}\n\ninterface ToolExecution {\n id: string;\n name: string;\n input?: unknown;\n output?: string;\n durationMs?: number;\n ok: boolean;\n startedAt: number;\n completedAt?: number;\n}\n\nexport const useChatStore = create<ChatState>()(\n persist(\n (set, get) => ({\n messages: [],\n currentAssistantMessageId: null,\n currentToolId: null,\n isLoading: false,\n abortController: null,\n executions: new Map(),\n queue: [],\n runStart: null,\n thinkingBuffer: '',\n thinkingStartedAt: null,\n\n addMessage: (msg) => {\n const id = `msg_${Date.now()}_${crypto.randomUUID().slice(0, 8)}`;\n const fullMsg: ChatMessage = { ...msg, id, timestamp: Date.now() };\n set((state) => ({\n messages: [...state.messages, fullMsg],\n currentAssistantMessageId:\n msg.role === 'assistant' ? id : state.currentAssistantMessageId,\n }));\n return id;\n },\n\n updateMessage: (id, updates) => {\n set((state) => ({\n messages: state.messages.map((m) => (m.id === id ? { ...m, ...updates } : m)),\n }));\n },\n\n appendToMessage: (id, text) => {\n set((state) => ({\n messages: state.messages.map((m) =>\n m.id === id ? { ...m, content: m.content + text } : m,\n ),\n }));\n },\n\n finalizeMessage: (id) => {\n set((state) => ({\n messages: state.messages.map((m) =>\n m.id === id ? { ...m, content: dedupeRepeatedBlocks(m.content), streaming: false } : m,\n ),\n }));\n },\n\n setToolResult: (id, result, ok) => {\n set((state) => ({\n messages: state.messages.map((m) =>\n m.id === id ? { ...m, toolResult: result, isError: !ok, progressLines: undefined } : m,\n ),\n }));\n },\n\n appendToolProgress: (id, line) => {\n set((state) => ({\n messages: state.messages.map((m) => {\n if (m.id !== id) return m;\n const prev = m.progressLines ?? [];\n const next = [...prev, line];\n const trimmed = next.length > 30 ? next.slice(next.length - 30) : next;\n return { ...m, progressLines: trimmed };\n }),\n }));\n },\n\n setLoading: (loading) => set({ isLoading: loading }),\n setAbortController: (ctrl) => set({ abortController: ctrl }),\n\n clearMessages: () =>\n set({\n messages: [],\n currentAssistantMessageId: null,\n currentToolId: null,\n executions: new Map(),\n }),\n\n setCurrentAssistantMessage: (id) => set({ currentAssistantMessageId: id }),\n setCurrentToolId: (id) => set({ currentToolId: id }),\n\n truncateAfter: (id) =>\n set((state) => {\n const idx = state.messages.findIndex((m) => m.id === id);\n if (idx === -1) return state;\n return {\n messages: state.messages.slice(0, idx),\n currentAssistantMessageId: null,\n currentToolId: null,\n };\n }),\n\n addExecution: (exec) => {\n set((state) => {\n const newExecutions = new Map(state.executions);\n newExecutions.set(exec.id, exec);\n return { executions: newExecutions };\n });\n },\n\n updateExecution: (id, updates) => {\n set((state) => {\n const newExecutions = new Map(state.executions);\n const existing = newExecutions.get(id);\n if (existing) {\n newExecutions.set(id, { ...existing, ...updates });\n }\n return { executions: newExecutions };\n });\n },\n\n enqueue: (text) => set((state) => ({ queue: [...state.queue, text] })),\n dequeue: () => {\n const { queue } = get();\n if (queue.length === 0) return null;\n const [next, ...rest] = queue;\n set({ queue: rest });\n return next!;\n },\n removeQueued: (idx) => set((state) => ({ queue: state.queue.filter((_, i) => i !== idx) })),\n clearQueue: () => set({ queue: [] }),\n setRunStart: (s) => set({ runStart: s }),\n appendThinking: (text) =>\n set((state) => ({\n thinkingBuffer: state.thinkingBuffer + text,\n thinkingStartedAt: state.thinkingStartedAt ?? Date.now(),\n })),\n clearThinking: () => set({ thinkingBuffer: '', thinkingStartedAt: null }),\n }),\n {\n name: 'wrongstack-chat',\n partialize: () => ({}),\n },\n ),\n);\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\n\n// ============================================\n// Config Store\n// ============================================\n\nexport interface ConfigState {\n provider: string;\n model: string;\n baseUrl?: string;\n apiKey?: string;\n wsUrl: string;\n wsConnected: boolean;\n /** Fine-grained connection state from the WS client. Drives the topbar's\n * reconnect indicator. */\n wsStatus:\n | { state: 'connecting' }\n | { state: 'open' }\n | { state: 'closed'; error?: string }\n | { state: 'reconnecting'; attempt: number; nextRetryAt: number; lastError?: string };\n theme: 'light' | 'dark' | 'system';\n autoConnect: boolean;\n /** Play a soft synthesized chime when run.result lands with status=done.\n * Off by default — opt-in via the Command Palette. Persisted so the\n * preference survives reloads. Actual playback only fires after the\n * user has interacted with the page (Web Audio autoplay policy). */\n soundOnComplete: boolean;\n\n setProvider: (provider: string) => void;\n setModel: (model: string) => void;\n setConfig: (\n config: Partial<Omit<ConfigState, 'setProvider' | 'setModel' | 'setConfig' | 'setTheme'>>,\n ) => void;\n setTheme: (theme: 'light' | 'dark' | 'system') => void;\n setWsConnected: (connected: boolean) => void;\n setWsStatus: (s: ConfigState['wsStatus']) => void;\n setSoundOnComplete: (on: boolean) => void;\n}\n\nexport const useConfigStore = create<ConfigState>()(\n persist(\n (set) => ({\n provider: 'anthropic',\n model: 'claude-sonnet-4-20250514',\n wsUrl: (() => {\n if (typeof window === 'undefined' || !window.location?.hostname) {\n return 'ws://127.0.0.1:3457';\n }\n const h = window.location.hostname.toLowerCase();\n if (h === 'localhost' || h === '127.0.0.1' || h === '[::1]' || h === '::1') {\n return 'ws://127.0.0.1:3457';\n }\n return `ws://${window.location.hostname}:3457`;\n })(),\n wsConnected: false,\n wsStatus: { state: 'connecting' },\n theme: 'system',\n autoConnect: true,\n soundOnComplete: false,\n setProvider: (provider) => set({ provider }),\n setModel: (model) => set({ model }),\n setConfig: (config) => set(config),\n setTheme: (theme) => set({ theme }),\n setWsConnected: (connected) => set({ wsConnected: connected }),\n setWsStatus: (wsStatus) => set({ wsStatus, wsConnected: wsStatus.state === 'open' }),\n setSoundOnComplete: (on) => set({ soundOnComplete: on }),\n }),\n {\n name: 'wrongstack-config',\n },\n ),\n);\n","import type { Usage } from '@wrongstack/core';\nimport { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport type { SessionInfo } from './types.js';\n\n// ============================================\n// Session Store\n// ============================================\n\ninterface SessionState {\n session: SessionInfo | null;\n totalTokens: Usage;\n /** Input tokens of the LAST provider response — used as the \"live context\n * size\" indicator in the topbar (matches what TUI's ContextChip shows). */\n lastInputTokens: number;\n cost: number;\n startTime: number | null;\n /** Model max context window, from models.dev catalog. 0 = unknown. */\n maxContext: number;\n /** USD per 1M tokens — used to compute cost deltas on every provider.response. */\n inputCost: number;\n outputCost: number;\n cacheReadCost: number;\n /** basename(projectRoot) for the topbar. */\n projectName: string;\n /** Active mode id (default | code | …). */\n mode: string;\n /** All modes the backend knows about, populated by modes.list. The\n * topbar mode chip uses this to render a picker; empty until the\n * backend responds. */\n modes: Array<{ id: string; name: string; description: string }>;\n /** Active context-window policy id (balanced | frugal | deep | archival). */\n contextMode: string;\n /** Context-window policy presets from the backend. */\n contextModes: Array<{\n id: string;\n name: string;\n description: string;\n thresholds?: { warn: number; soft: number; hard: number };\n preserveK?: number;\n eliseThreshold?: number;\n }>;\n /** Iteration progress while the agent is running. Resets on run.result. */\n iteration: { index: number; max: number } | null;\n /** Live snapshot of context.todos — backend broadcasts on every\n * tool.executed, and the sidebar/overlay reads from here. */\n todos: Array<{\n id: string;\n content: string;\n status: 'pending' | 'in_progress' | 'completed';\n activeForm?: string;\n }>;\n\n setSession: (session: SessionInfo | null) => void;\n updateUsage: (usage: Usage) => void;\n addCost: (cost: number) => void;\n startSession: (session: SessionInfo) => void;\n endSession: () => void;\n setEnv: (env: {\n maxContext?: number;\n projectName?: string;\n mode?: string;\n contextMode?: string;\n inputCost?: number;\n outputCost?: number;\n cacheReadCost?: number;\n }) => void;\n setIteration: (it: { index: number; max: number } | null) => void;\n setModes: (modes: Array<{ id: string; name: string; description: string }>) => void;\n setContextModes: (modes: SessionState['contextModes']) => void;\n setTodos: (todos: SessionState['todos']) => void;\n}\n\nexport const useSessionStore = create<SessionState>()(\n persist(\n (set) => ({\n session: null,\n totalTokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n lastInputTokens: 0,\n cost: 0,\n startTime: null,\n maxContext: 0,\n inputCost: 0,\n outputCost: 0,\n cacheReadCost: 0,\n projectName: '',\n mode: 'default',\n modes: [],\n contextMode: 'balanced',\n contextModes: [],\n iteration: null,\n todos: [],\n\n setSession: (session) => set({ session }),\n\n updateUsage: (usage) =>\n set((state) => {\n const inputDelta = usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);\n const cacheReadDelta = usage.cacheRead ?? 0;\n const cacheWriteDelta = usage.cacheWrite ?? 0;\n return {\n totalTokens: {\n input: state.totalTokens.input + usage.input,\n output: state.totalTokens.output + usage.output,\n cacheRead: (state.totalTokens.cacheRead ?? 0) + cacheReadDelta,\n cacheWrite: (state.totalTokens.cacheWrite ?? 0) + cacheWriteDelta,\n },\n lastInputTokens: inputDelta || state.lastInputTokens,\n };\n }),\n\n addCost: (cost) => set((state) => ({ cost: state.cost + cost })),\n\n startSession: (session) =>\n set({\n session,\n startTime: Date.now(),\n iteration: null,\n lastInputTokens: 0,\n totalTokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n cost: 0,\n }),\n\n endSession: () =>\n set({\n session: null,\n startTime: null,\n iteration: null,\n }),\n\n setEnv: (env) =>\n set((state) => ({\n maxContext: env.maxContext ?? state.maxContext,\n projectName: env.projectName ?? state.projectName,\n mode: env.mode ?? state.mode,\n contextMode: env.contextMode ?? state.contextMode,\n inputCost: env.inputCost ?? state.inputCost,\n outputCost: env.outputCost ?? state.outputCost,\n cacheReadCost: env.cacheReadCost ?? state.cacheReadCost,\n })),\n\n setIteration: (iteration) => set({ iteration }),\n setModes: (modes) => set({ modes }),\n setContextModes: (contextModes) => set({ contextModes }),\n setTodos: (todos) => set({ todos }),\n }),\n {\n name: 'wrongstack-session',\n partialize: () => ({}),\n },\n ),\n);\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\n\n// ============================================\n// UI Store\n// ============================================\n\ninterface UIState {\n sidebarOpen: boolean;\n settingsOpen: boolean;\n currentView: 'chat' | 'history' | 'settings';\n showConfirmDialog: boolean;\n confirmInfo: {\n id: string;\n toolName: string;\n input: unknown;\n suggestedPattern: string;\n } | null;\n paletteOpen: boolean;\n shortcutsOpen: boolean;\n searchOpen: boolean;\n searchQuery: string;\n promptHistory: string[];\n sidebarWidth: number;\n pinnedIds: string[];\n compactMode: boolean;\n modelSwitcherOpen: boolean;\n favoriteSessionIds: string[];\n sessionNicknames: Record<string, string>;\n\n toggleSidebar: () => void;\n setSidebarOpen: (open: boolean) => void;\n setSettingsOpen: (open: boolean) => void;\n setCurrentView: (view: 'chat' | 'history' | 'settings') => void;\n showConfirm: (info: UIState['confirmInfo']) => void;\n hideConfirm: () => void;\n setPaletteOpen: (open: boolean) => void;\n setShortcutsOpen: (open: boolean) => void;\n setSearchOpen: (open: boolean) => void;\n setSearchQuery: (q: string) => void;\n pushPrompt: (text: string) => void;\n setSidebarWidth: (px: number) => void;\n togglePin: (id: string) => void;\n unpinAll: () => void;\n toggleCompactMode: () => void;\n setModelSwitcherOpen: (open: boolean) => void;\n toggleFavoriteSession: (id: string) => void;\n setSessionNickname: (id: string, nickname: string) => void;\n}\n\nexport const useUIStore = create<UIState>()(\n persist(\n (set) => ({\n sidebarOpen: true,\n settingsOpen: false,\n currentView: 'chat',\n showConfirmDialog: false,\n confirmInfo: null,\n paletteOpen: false,\n shortcutsOpen: false,\n searchOpen: false,\n searchQuery: '',\n promptHistory: [],\n sidebarWidth: 288,\n pinnedIds: [],\n compactMode: false,\n modelSwitcherOpen: false,\n favoriteSessionIds: [],\n sessionNicknames: {},\n\n toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),\n setSidebarOpen: (open) => set({ sidebarOpen: open }),\n setSettingsOpen: (open) => set({ settingsOpen: open }),\n setCurrentView: (view) => set({ currentView: view }),\n showConfirm: (info) => set({ showConfirmDialog: true, confirmInfo: info }),\n hideConfirm: () => set({ showConfirmDialog: false, confirmInfo: null }),\n setPaletteOpen: (open) => set({ paletteOpen: open }),\n setShortcutsOpen: (open) => set({ shortcutsOpen: open }),\n setSearchOpen: (open) => set({ searchOpen: open, searchQuery: open ? '' : '' }),\n setSearchQuery: (q) => set({ searchQuery: q }),\n pushPrompt: (text) =>\n set((state) => {\n const trimmed = text.trim();\n if (!trimmed) return state;\n const filtered = state.promptHistory.filter((p) => p !== trimmed);\n return { promptHistory: [trimmed, ...filtered].slice(0, 50) };\n }),\n setSidebarWidth: (px) => set({ sidebarWidth: Math.max(200, Math.min(480, Math.round(px))) }),\n togglePin: (id) =>\n set((state) => {\n const has = state.pinnedIds.includes(id);\n return {\n pinnedIds: has ? state.pinnedIds.filter((p) => p !== id) : [...state.pinnedIds, id],\n };\n }),\n unpinAll: () => set({ pinnedIds: [] }),\n toggleCompactMode: () => set((s) => ({ compactMode: !s.compactMode })),\n setModelSwitcherOpen: (open) => set({ modelSwitcherOpen: open }),\n toggleFavoriteSession: (id) =>\n set((state) => {\n const has = state.favoriteSessionIds.includes(id);\n return {\n favoriteSessionIds: has\n ? state.favoriteSessionIds.filter((s) => s !== id)\n : [...state.favoriteSessionIds, id],\n };\n }),\n setSessionNickname: (id, nickname) =>\n set((state) => {\n const trimmed = nickname.trim();\n const next = { ...state.sessionNicknames };\n if (trimmed) next[id] = trimmed;\n else delete next[id];\n return { sessionNicknames: next };\n }),\n }),\n {\n name: 'wrongstack-ui',\n partialize: (s) => ({\n sidebarOpen: s.sidebarOpen,\n sidebarWidth: s.sidebarWidth,\n promptHistory: s.promptHistory,\n pinnedIds: s.pinnedIds,\n compactMode: s.compactMode,\n favoriteSessionIds: s.favoriteSessionIds,\n sessionNicknames: s.sessionNicknames,\n }),\n },\n ),\n);\n","import { create } from 'zustand';\nimport type { SessionHistoryEntry } from './types.js';\n\n// ============================================\n// History Store\n// ============================================\n\ninterface HistoryState {\n entries: SessionHistoryEntry[];\n loading: boolean;\n error: string | null;\n setEntries: (entries: SessionHistoryEntry[], error?: string | null) => void;\n setLoading: (loading: boolean) => void;\n removeEntry: (id: string) => void;\n clearHistory: () => void;\n}\n\nexport const useHistoryStore = create<HistoryState>()((set) => ({\n entries: [],\n loading: false,\n error: null,\n setEntries: (entries, error = null) => set({ entries, error, loading: false }),\n setLoading: (loading) => set({ loading }),\n removeEntry: (id) =>\n set((state) => ({\n entries: state.entries.filter((e) => e.id !== id),\n })),\n clearHistory: () => set({ entries: [] }),\n}));\n","import { create } from 'zustand';\nimport type { WorktreeHandleView } from '../types.js';\n\n// ── Worktree store (live backend state; not persisted) ──────────────────────\n\ninterface WorktreeActivity {\n handleId: string;\n kind: string;\n text: string;\n at: number;\n}\n\ninterface WorktreeState {\n worktrees: WorktreeHandleView[];\n baseBranch: string;\n activity: WorktreeActivity[];\n setSnapshot: (worktrees: WorktreeHandleView[], baseBranch: string) => void;\n pushEvent: (e: WorktreeActivity) => void;\n}\n\nexport const useWorktreeStore = create<WorktreeState>()((set) => ({\n worktrees: [],\n baseBranch: '',\n activity: [],\n setSnapshot: (worktrees, baseBranch) => set({ worktrees, baseBranch }),\n pushEvent: (e) => set((s) => ({ activity: [...s.activity, e].slice(-40) })),\n}));\n","import { create } from 'zustand';\nimport type { SubagentView, SubagentEvent } from './types.js';\n\n// ── Fleet store (live subagent roster; not persisted) ───────────────────────\n\ninterface FleetState {\n agents: Map<string, SubagentView>;\n applyEvent: (e: SubagentEvent) => void;\n clear: () => void;\n}\n\nfunction blankAgent(id: string, name?: string): SubagentView {\n return {\n id,\n name: name?.trim() || id,\n status: 'running',\n iteration: 0,\n toolCalls: 0,\n costUsd: 0,\n ctxPct: 0,\n ctxTokens: 0,\n maxContext: 0,\n extensions: 0,\n startedAt: Date.now(),\n };\n}\n\nexport const useFleetStore = create<FleetState>()((set) => ({\n agents: new Map(),\n clear: () => set({ agents: new Map() }),\n applyEvent: (e) =>\n set((state) => {\n const agents = new Map(state.agents);\n const prev = agents.get(e.subagentId) ?? blankAgent(e.subagentId, e.name);\n const next: SubagentView = { ...prev };\n switch (e.kind) {\n case 'spawned':\n next.name = e.name?.trim() || next.name;\n next.provider = e.provider ?? next.provider;\n next.model = e.model ?? next.model;\n next.description = e.description ?? next.description;\n next.taskId = e.taskId ?? next.taskId;\n next.status = 'running';\n break;\n case 'task_started':\n next.description = e.description ?? next.description;\n next.taskId = e.taskId ?? next.taskId;\n next.status = 'running';\n break;\n case 'tool_executed':\n next.lastTool = e.toolName ?? next.lastTool;\n next.toolCalls = next.toolCalls + 1;\n break;\n case 'iteration_summary':\n next.iteration = e.iteration ?? next.iteration;\n if (typeof e.toolCalls === 'number') next.toolCalls = e.toolCalls;\n if (typeof e.costUsd === 'number') next.costUsd = e.costUsd;\n next.currentTool = e.currentTool ?? next.currentTool;\n break;\n case 'budget_extended':\n next.extensions = e.totalExtensions ?? next.extensions + 1;\n break;\n case 'ctx_pct':\n next.ctxPct = Math.round(Math.min(1, Math.max(0, e.load ?? 0)) * 100);\n next.ctxTokens = e.tokens ?? next.ctxTokens;\n next.maxContext = e.maxContext ?? next.maxContext;\n break;\n case 'task_completed':\n next.status = e.status === 'success' ? 'completed' : (e.status ?? 'completed');\n if (typeof e.iterations === 'number') next.iteration = e.iterations;\n if (typeof e.toolCalls === 'number') next.toolCalls = e.toolCalls;\n next.error = e.error;\n next.currentTool = undefined;\n next.completedAt = Date.now();\n break;\n }\n agents.set(e.subagentId, next);\n return { agents };\n }),\n}));\n","import { installFaviconVisibilityReset } from '@/lib/favicon';\nimport { getWSClient } from '@/lib/ws-client';\nimport type { WrongStackWebSocketClient } from '@/lib/ws-client';\nimport { useChatStore, useConfigStore, useHistoryStore, useSessionStore, useUIStore } from '@/stores';\nimport { useCallback, useEffect, useRef } from 'react';\nimport { WS_HANDLERS } from './ws-handlers.js';\n\n/**\n * One-shot WebSocket handler installation.\n *\n * Critical: this is called by `useWebSocketBootstrap` from App.tsx EXACTLY\n * ONCE per page. Every other component that needs to talk to the backend uses\n * `useWebSocket()` (below) which only returns action methods — it does NOT\n * register handlers.\n *\n * The earlier design had every component that imported `useWebSocket()`\n * register its own copy of the handlers via `ws.on(type, handler)`. With\n * ChatInput + ConfirmDialog + SettingsPanel all using the hook, every\n * incoming WS message was processed three times — three identical tool\n * bubbles, three appends of the same text_delta, three clearMessages on\n * session.start. That's the \"duplicate tool bubble / repeated text\" bug\n * the user kept hitting. Singleton install fixes it at the root.\n */\nfunction installHandlers(ws: WrongStackWebSocketClient): () => void {\n const offs: Array<() => void> = [];\n for (const [type, handler] of Object.entries(WS_HANDLERS)) {\n offs.push(ws.on(type, handler));\n }\n return () => { for (const off of offs) off(); };\n}\n\n/**\n * Mounts the WebSocket connection and installs event handlers EXACTLY ONCE.\n * Call this from App.tsx (top of the tree) and nowhere else.\n */\nexport function useWebSocketBootstrap(): void {\n const { autoConnect, wsUrl } = useConfigStore();\n const setWsStatus = useConfigStore((s) => s.setWsStatus);\n const installed = useRef(false);\n\n useEffect(() => {\n if (!autoConnect) return;\n installFaviconVisibilityReset();\n const ws = getWSClient(wsUrl);\n\n const offStatus = ws.onStatus((s) => setWsStatus(s));\n\n ws.connect().catch((err) => {\n // eslint-disable-next-line no-console\n console.error('[WS] Connection failed:', err);\n });\n\n if (installed.current) {\n return () => { offStatus(); };\n }\n installed.current = true;\n const off = installHandlers(ws);\n return () => {\n off();\n offStatus();\n };\n }, [autoConnect, wsUrl, setWsStatus]);\n}\n\n/**\n * Cheap accessor for the singleton WS client and its imperative action\n * methods. Components call this freely; it does NOT register handlers.\n */\nexport function useWebSocket() {\n const { wsUrl } = useConfigStore();\n const client = getWSClient(wsUrl);\n\n const sendMessage = useCallback(\n (content: string) => {\n if (client.isConnected) return client.sendMessage(content);\n return null;\n },\n [client],\n );\n\n const sendAbort = useCallback(() => client.sendAbort(), [client]);\n\n const { hideConfirm } = useUIStore();\n const sendConfirm = useCallback(\n (id: string, decision: 'yes' | 'no' | 'always' | 'deny') => {\n client.sendConfirm(id, decision);\n hideConfirm();\n },\n [client, hideConfirm],\n );\n\n const switchModel = useCallback(\n (provider: string, model: string) => client.switchModel(provider, model),\n [client],\n );\n\n const listProviders = useCallback(() => client.listProviders(), [client]);\n const listProviderModels = useCallback(\n (providerId: string) => client.listProviderModels(providerId),\n [client],\n );\n const listSavedProviders = useCallback(() => client.listSavedProviders(), [client]);\n const addKey = useCallback(\n (providerId: string, label: string, apiKey: string) => client.addKey(providerId, label, apiKey),\n [client],\n );\n const updateKey = useCallback(\n (providerId: string, label: string, apiKey: string) =>\n client.updateKey(providerId, label, apiKey),\n [client],\n );\n const deleteKey = useCallback(\n (providerId: string, label: string) => client.deleteKey(providerId, label),\n [client],\n );\n const setActiveKey = useCallback(\n (providerId: string, label: string) => client.setActiveKey(providerId, label),\n [client],\n );\n const addProvider = useCallback(\n (id: string, family: string, baseUrl?: string, apiKey?: string) =>\n client.addProvider(id, family, baseUrl, apiKey),\n [client],\n );\n const removeProvider = useCallback(\n (providerId: string) => client.removeProvider(providerId),\n [client],\n );\n\n const listSessions = useCallback(\n (limit?: number) => {\n useHistoryStore.getState().setLoading(true);\n client.listSessions(limit);\n },\n [client],\n );\n const deleteSession = useCallback(\n (id: string) => {\n useHistoryStore.getState().removeEntry(id);\n client.deleteSession(id);\n },\n [client],\n );\n const resumeSession = useCallback((id: string) => client.resumeSessionById(id), [client]);\n const saveSession = useCallback(() => client.saveSession(), [client]);\n const listTools = useCallback(() => client.listTools(), [client]);\n const listMemory = useCallback(() => client.listMemory(), [client]);\n const listSkills = useCallback(() => client.listSkills(), [client]);\n const getDiag = useCallback(() => client.getDiag(), [client]);\n const getStats = useCallback(() => client.getStats(), [client]);\n const listModes = useCallback(() => client.listModes(), [client]);\n const switchMode = useCallback((id: string) => client.switchMode(id), [client]);\n const listContextModes = useCallback(() => client.listContextModes(), [client]);\n const switchContextMode = useCallback((id: string) => client.switchContextMode(id), [client]);\n const repairContext = useCallback(() => client.repairContext(), [client]);\n\n // AutoPhase\n const toggleAutoPhaseAutonomous = useCallback(\n (autonomous: boolean) => { client.send({ type: 'autophase.toggleAutonomous', payload: { autonomous } }); },\n [client],\n );\n const startAutoPhase = useCallback(\n (title: string, phases?: unknown[], autonomous = true) => { client.send({ type: 'autophase.start', payload: { title, phases, autonomous } }); },\n [client],\n );\n const pauseAutoPhase = useCallback(() => { client.send({ type: 'autophase.pause', payload: {} }); }, [client]);\n const resumeAutoPhase = useCallback(() => { client.send({ type: 'autophase.resume', payload: {} }); }, [client]);\n const stopAutoPhase = useCallback(() => { client.send({ type: 'autophase.stop', payload: {} }); }, [client]);\n const selectAutoPhase = useCallback(\n (phaseId: string) => { client.send({ type: 'autophase.selectPhase', payload: { phaseId } }); },\n [client],\n );\n\n return {\n client, sendMessage, sendAbort, sendConfirm, switchModel,\n listProviders, listProviderModels, listSavedProviders,\n addKey, updateKey, deleteKey, setActiveKey, addProvider, removeProvider,\n listSessions, deleteSession, resumeSession, saveSession,\n listTools, listMemory, listSkills, getDiag, getStats,\n listModes, switchMode, listContextModes, switchContextMode, repairContext,\n toggleAutoPhaseAutonomous, startAutoPhase, pauseAutoPhase, resumeAutoPhase, stopAutoPhase, selectAutoPhase,\n };\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { cn } from '@/lib/utils';\nimport { AlertTriangle, CheckCircle2, Info, X, XCircle } from 'lucide-react';\nimport { useEffect } from 'react';\nimport { create } from 'zustand';\n\n/**\n * Tiny toast store + portal. We resisted pulling in shadcn-ui's full\n * toast/sonner since it brings a tree of providers — this is one store,\n * one component, ~80 lines total. The store is exposed via `toast.success(...)`\n * etc. so non-React modules (ws-client handlers) can fire toasts without\n * the hook.\n */\n\nexport type ToastVariant = 'success' | 'error' | 'warn' | 'info';\n\ninterface ToastEntry {\n id: string;\n message: string;\n variant: ToastVariant;\n ttl: number;\n}\n\ninterface ToastState {\n toasts: ToastEntry[];\n push: (t: Omit<ToastEntry, 'id'>) => string;\n dismiss: (id: string) => void;\n}\n\nconst useToastStore = create<ToastState>((set) => ({\n toasts: [],\n push: (t) => {\n const id = `toast_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;\n set((state) => ({ toasts: [...state.toasts, { ...t, id }] }));\n return id;\n },\n dismiss: (id) => set((state) => ({ toasts: state.toasts.filter((x) => x.id !== id) })),\n}));\n\n/** Imperative API. Pass plain strings or arrays of strings for multi-line. */\nexport const toast = {\n success: (msg: string, ttl = 3500) =>\n useToastStore.getState().push({ message: msg, variant: 'success', ttl }),\n error: (msg: string, ttl = 6000) =>\n useToastStore.getState().push({ message: msg, variant: 'error', ttl }),\n warn: (msg: string, ttl = 4500) =>\n useToastStore.getState().push({ message: msg, variant: 'warn', ttl }),\n info: (msg: string, ttl = 3500) =>\n useToastStore.getState().push({ message: msg, variant: 'info', ttl }),\n dismiss: (id: string) => useToastStore.getState().dismiss(id),\n};\n\nfunction Icon({ variant }: { variant: ToastVariant }) {\n if (variant === 'success') return <CheckCircle2 className=\"h-4 w-4 text-green-500\" />;\n if (variant === 'error') return <XCircle className=\"h-4 w-4 text-destructive\" />;\n if (variant === 'warn') return <AlertTriangle className=\"h-4 w-4 text-amber-500\" />;\n return <Info className=\"h-4 w-4 text-blue-500\" />;\n}\n\nfunction ToastItem({ entry }: { entry: ToastEntry }) {\n const dismiss = useToastStore((s) => s.dismiss);\n useEffect(() => {\n const t = setTimeout(() => dismiss(entry.id), entry.ttl);\n return () => clearTimeout(t);\n }, [entry.id, entry.ttl, dismiss]);\n return (\n <div\n className={cn(\n 'flex items-start gap-2 rounded-lg border bg-popover shadow-lg px-3 py-2 text-sm max-w-sm',\n 'animate-message',\n entry.variant === 'error' && 'border-destructive/40',\n entry.variant === 'warn' && 'border-amber-500/40',\n entry.variant === 'success' && 'border-green-500/40',\n )}\n >\n <Icon variant={entry.variant} />\n <div className=\"flex-1 min-w-0 whitespace-pre-wrap break-words leading-snug\">\n {entry.message}\n </div>\n <button\n type=\"button\"\n onClick={() => dismiss(entry.id)}\n className=\"text-muted-foreground hover:text-foreground\"\n title=\"Dismiss\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n );\n}\n\nexport function Toaster() {\n const toasts = useToastStore((s) => s.toasts);\n if (toasts.length === 0) return null;\n return (\n <div className=\"fixed bottom-4 right-4 z-[60] flex flex-col gap-2 pointer-events-auto\">\n {toasts.map((t) => (\n <ToastItem key={t.id} entry={t} />\n ))}\n </div>\n );\n}\n","/**\n * Tiny soft chime played when a long-running agent run completes. We don't\n * ship an audio asset — the sound is synthesized with Web Audio so it's\n * zero-bytes-shipped and trivially tweakable.\n *\n * Tuned to be unobtrusive: two notes ascending, ~250ms total, ~-12dB\n * envelope. Quiet enough to not startle on a still office, audible enough\n * to cut through music. Browsers require a prior user interaction before\n * any audio plays — by the time the agent has actually finished a turn the\n * user has already typed, so the autoplay policy is satisfied.\n */\n\nlet ctx: AudioContext | null = null;\n\nfunction audio(): AudioContext | null {\n if (typeof window === 'undefined') return null;\n if (ctx) return ctx;\n // SSR/Test guard plus older Safari (webkit prefix).\n const Cls =\n window.AudioContext ||\n (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Cls) return null;\n try {\n ctx = new Cls();\n } catch {\n return null;\n }\n return ctx;\n}\n\nfunction tone(freq: number, startAt: number, durSec: number): void {\n const ac = audio();\n if (!ac) return;\n const t = ac.currentTime + startAt;\n const osc = ac.createOscillator();\n const gain = ac.createGain();\n osc.type = 'sine';\n osc.frequency.value = freq;\n // Quick attack, exponential decay — sounds like a soft \"bing\".\n gain.gain.setValueAtTime(0, t);\n gain.gain.linearRampToValueAtTime(0.18, t + 0.01);\n gain.gain.exponentialRampToValueAtTime(0.0001, t + durSec);\n osc.connect(gain).connect(ac.destination);\n osc.start(t);\n osc.stop(t + durSec + 0.02);\n}\n\nexport function playCompletionChime(): void {\n // Two-note arpeggio: E5 → A5 (a perfect fourth, pleasant + non-alarming).\n tone(659.25, 0, 0.18);\n tone(880, 0.12, 0.24);\n}\n\n/**\n * Urgent chime for permission requests. Louder and more insistent than\n * the completion chime — three ascending notes that say \"hey, I need\n * your input\". Always plays regardless of soundOnComplete preference,\n * because a missed permission prompt means the agent is stuck.\n */\nexport function playPermissionChime(): void {\n // Three-note ascending: C5 → E5 → G5 (C major arpeggio, attention-getting)\n tone(523.25, 0, 0.15);\n tone(659.25, 0.1, 0.15);\n tone(783.99, 0.2, 0.25);\n}\n","/**\n * Browser Notification API wrapper. We never pop a notification when the\n * tab is foreground — the user already sees the chat update, so an OS\n * popup would just be noise. The flow:\n *\n * 1. requestPermission() is called lazily on first run completion;\n * browsers require a user gesture for the prompt to be safe but\n * Chrome / Firefox accept it from any code path with relaxed rules.\n * 2. notifyIfHidden() short-circuits unless the page is `document.hidden`.\n * 3. Clicking the notification focuses the page (best-effort — some\n * browsers won't focus across tab groups).\n */\n\nlet permissionState: NotificationPermission | 'unsupported' = 'default';\n\nif (typeof window !== 'undefined' && 'Notification' in window) {\n permissionState = Notification.permission;\n} else {\n permissionState = 'unsupported';\n}\n\nexport async function ensureNotificationPermission(): Promise<\n NotificationPermission | 'unsupported'\n> {\n if (\n permissionState === 'unsupported' ||\n permissionState === 'granted' ||\n permissionState === 'denied'\n ) {\n return permissionState;\n }\n try {\n const result = await Notification.requestPermission();\n permissionState = result;\n return result;\n } catch {\n return 'denied';\n }\n}\n\nexport function notifyIfHidden(title: string, body?: string, tag?: string): void {\n if (typeof document === 'undefined' || !document.hidden) return;\n if (permissionState !== 'granted') return;\n try {\n const n = new Notification(title, {\n body,\n icon: '/favicon.ico',\n // Tag-collapse: if multiple notifications stack while the tab is\n // hidden, only the latest with the same tag shows up so we don't\n // litter the OS notification center. Permission alerts use a\n // separate tag so they don't get swallowed by run-completion.\n tag: tag ?? 'wrongstack-run',\n // Require interaction for permission alerts — the agent is stuck\n // until the user responds, so auto-dismiss would be harmful.\n requireInteraction: tag === 'wrongstack-confirm',\n });\n n.onclick = () => {\n window.focus();\n n.close();\n };\n } catch {\n // Some browsers (e.g. iOS Safari) throw — silently swallow.\n }\n}\n","import { toast } from '@/components/Toaster';\nimport { playCompletionChime, playPermissionChime } from '@/lib/chime';\nimport { setFaviconStatus } from '@/lib/favicon';\nimport { ensureNotificationPermission, notifyIfHidden } from '@/lib/notify';\nimport { getWSClient } from '@/lib/ws-client';\nimport type { WrongStackWebSocketClient } from '@/lib/ws-client';\nimport {\n type SessionHistoryEntry,\n type SubagentEvent,\n useChatStore,\n useConfigStore,\n useFleetStore,\n useHistoryStore,\n useSessionStore,\n useUIStore,\n useWorktreeStore,\n} from '@/stores';\nimport type { WorktreeHandleView, WSServerMessage } from '@/types';\n\n// ── Session handlers ──\n\nexport function handleSessionStart(msg: WSServerMessage) {\n const payload = msg.payload as {\n sessionId: string;\n model: string;\n provider: string;\n maxContext?: number;\n projectName?: string;\n cwd?: string;\n mode?: string;\n contextMode?: string;\n inputCost?: number;\n outputCost?: number;\n cacheReadCost?: number;\n reset?: boolean;\n };\n const prev = useSessionStore.getState().session?.id;\n const isNew = !prev || prev !== payload.sessionId;\n useSessionStore.getState().startSession({\n id: payload.sessionId,\n startedAt: Date.now(),\n model: payload.model,\n provider: payload.provider,\n });\n useSessionStore.getState().setEnv({\n maxContext: payload.maxContext,\n projectName: payload.projectName,\n mode: payload.mode,\n contextMode: payload.contextMode,\n inputCost: payload.inputCost,\n outputCost: payload.outputCost,\n cacheReadCost: payload.cacheReadCost,\n });\n useConfigStore.getState().setConfig({\n provider: payload.provider,\n model: payload.model,\n });\n if (isNew || payload.reset) {\n useChatStore.getState().clearMessages();\n useFleetStore.getState().clear();\n }\n // Resume hydration\n const replay = (payload as { replayMessages?: Array<{ role: string; content: unknown }> }).replayMessages;\n if (replay && replay.length > 0) {\n const chat = useChatStore.getState();\n for (const m of replay) {\n if (m.role === 'user' || m.role === 'assistant' || m.role === 'system') {\n let text = '';\n if (typeof m.content === 'string') {\n text = m.content;\n } else if (Array.isArray(m.content)) {\n for (const b of m.content as Array<Record<string, unknown>>) {\n if (b.type === 'text' && typeof b.text === 'string') {\n text += (text ? '\\n' : '') + b.text;\n } else if (b.type === 'tool_use') {\n if (text) { chat.addMessage({ role: m.role as 'user' | 'assistant', content: text }); text = ''; }\n chat.addMessage({ role: 'tool', content: '', toolName: String(b.name ?? 'tool'), toolInput: b.input, toolUseId: String(b.id ?? '') });\n } else if (b.type === 'tool_result') {\n const all = useChatStore.getState().messages;\n let last: { id: string } | undefined;\n for (let i = all.length - 1; i >= 0; i--) {\n if (all[i]!.toolUseId === String(b.tool_use_id ?? '')) { last = all[i]!; break; }\n }\n if (last) { chat.setToolResult(last.id, typeof b.content === 'string' ? b.content : JSON.stringify(b.content), !b.is_error); }\n }\n }\n }\n if (text) chat.addMessage({ role: m.role as 'user' | 'assistant', content: text });\n }\n }\n }\n}\n\n// ── Context handlers ──\n\nexport function handleContextDebug(msg: WSServerMessage) {\n const p = msg.payload as {\n total: number; systemPrompt: number;\n tools: { total: number; count: number; breakdown: Array<{ name: string; tokens: number }> };\n messages: { total: number; count: number; breakdown: Array<{ index: number; role: string; tokens: number; preview: string }> };\n };\n const fmt = (n: number) => n.toLocaleString();\n const topTools = [...p.tools.breakdown].sort((a, b) => b.tokens - a.tokens).slice(0, 8);\n const topMsgs = [...p.messages.breakdown].sort((a, b) => b.tokens - a.tokens).slice(0, 8);\n useChatStore.getState().addMessage({ role: 'assistant', content: [\n `📊 **Context breakdown** (heuristic — 4 chars/token)`, '',\n `**Total estimate:** ${fmt(p.total)} tokens`,\n `• System prompt: ${fmt(p.systemPrompt)}`,\n `• Tool schemas: ${fmt(p.tools.total)} (${p.tools.count} tools)`,\n `• Messages: ${fmt(p.messages.total)} (${p.messages.count} messages)`, '',\n `**Top tool schemas:**`, ...topTools.map((t) => ` · ${t.name}: ${fmt(t.tokens)}`), '',\n `**Top messages:**`, ...topMsgs.map((m) => ` · #${m.index} ${m.role}: ${fmt(m.tokens)} — ${m.preview || '(empty)'}`),\n ].join('\\n') });\n}\n\nexport function handleKeyOperationResult(msg: WSServerMessage) {\n const p = msg.payload as { success: boolean; message: string };\n if (p.success) toast.success(p.message);\n else toast.error(p.message);\n // Refresh saved providers after any key operation so the SettingsPanel\n // (and any other viewer) immediately sees the updated list.\n const client = getWSClient(useConfigStore.getState().wsUrl);\n client.listSavedProviders();\n}\n\nexport function handleContextCompacted(msg: WSServerMessage) {\n const payload = msg.payload as {\n before: number; after: number; saved: number;\n reductions: Array<{ phase: string; saved: number }>;\n repaired?: { removedToolUses: string[]; removedToolResults: string[]; removedMessages: number };\n };\n let summary = payload.reductions.length ? payload.reductions.map((r) => `${r.phase}: ${r.saved}`).join(', ') : 'no-op';\n if (payload.repaired) summary += `; repaired ${payload.repaired.removedToolUses.length} tool_use, ${payload.repaired.removedToolResults.length} tool_result, ${payload.repaired.removedMessages} empty messages`;\n useChatStore.getState().addMessage({ role: 'assistant', content: `🗜️ Context compacted: ${payload.before} → ${payload.after} tokens (saved ~${payload.saved}). ${summary}` });\n useSessionStore.setState({ lastInputTokens: payload.after });\n}\n\nexport function handleProviderResponse(msg: WSServerMessage) {\n const payload = msg.payload as { usage: { input: number; output: number; cacheRead?: number; cacheWrite?: number }; stopReason: string; messageId: string };\n\n // Update lastInputTokens from usage delta (was a separate handler)\n const u = payload.usage;\n const delta = (u.input ?? 0) + (u.cacheWrite ?? 0) - (u.cacheRead ?? 0);\n if (delta > 0) useSessionStore.setState({ lastInputTokens: delta });\n\n // Main response handler\n useSessionStore.getState().updateUsage(payload.usage);\n const { inputCost, outputCost, cacheReadCost } = useSessionStore.getState();\n const dCost = (payload.usage.input * inputCost + payload.usage.output * outputCost + (payload.usage.cacheRead ?? 0) * cacheReadCost) / 1_000_000;\n if (dCost > 0) useSessionStore.getState().addCost(dCost);\n if (payload.stopReason !== 'tool_use' && payload.stopReason !== 'tool_call') useChatStore.getState().setLoading(false);\n const id = useChatStore.getState().currentAssistantMessageId;\n if (id) {\n useChatStore.getState().finalizeMessage(id);\n if (payload.usage.output > 0) useChatStore.getState().updateMessage(id, { usage: payload.usage });\n }\n useChatStore.getState().setCurrentAssistantMessage(null);\n useChatStore.getState().clearThinking();\n}\n\nexport function handleContextRepaired(msg: WSServerMessage) {\n const payload = msg.payload as { removedToolUses: string[]; removedToolResults: string[]; removedMessages: number; beforeMessages?: number; afterMessages?: number };\n const removed = payload.removedToolUses.length + payload.removedToolResults.length + payload.removedMessages;\n const msgCount = payload.beforeMessages !== undefined && payload.afterMessages !== undefined ? ` Messages: ${payload.beforeMessages} -> ${payload.afterMessages}.` : '';\n useChatStore.getState().addMessage({ role: 'assistant', content: `Context repaired: removed ${removed} orphan protocol item(s).${msgCount} tool_use ${payload.removedToolUses.length}, tool_result ${payload.removedToolResults.length}.` });\n}\n\n// ── Agent handlers ──\n\nexport function handleSessionEnd() {\n useConfigStore.getState().setWsConnected(false);\n}\n\nexport function handleIterationStarted(msg: WSServerMessage) {\n const payload = msg.payload as { index: number; maxIterations?: number };\n useSessionStore.getState().setIteration({ index: payload.index, max: payload.maxIterations ?? 0 });\n useChatStore.getState().setLoading(true);\n if (typeof document !== 'undefined' && document.hidden) setFaviconStatus('running');\n if (useChatStore.getState().runStart === null) {\n useChatStore.getState().setRunStart({ at: Date.now(), cost: useSessionStore.getState().cost });\n }\n useChatStore.getState().setCurrentAssistantMessage(null);\n}\n\nexport function handleTextDelta(msg: WSServerMessage) {\n const payload = msg.payload as { text: string; messageId: string };\n useChatStore.getState().clearThinking();\n let id = useChatStore.getState().currentAssistantMessageId;\n if (!id) {\n id = useChatStore.getState().addMessage({ role: 'assistant', content: '', streaming: true });\n useChatStore.getState().setCurrentAssistantMessage(id);\n }\n useChatStore.getState().appendToMessage(id, payload.text);\n}\n\nexport function handleThinkingDelta(msg: WSServerMessage) {\n const payload = msg.payload as { text: string };\n if (!payload.text) return;\n useChatStore.getState().appendThinking(payload.text);\n}\n\nexport function handleToolStarted(msg: WSServerMessage) {\n const payload = msg.payload as { id: string; name: string; input?: unknown; messageId: string };\n const existing = useChatStore.getState().messages.find((m) => m.toolUseId === payload.id);\n if (existing) { useChatStore.getState().setCurrentToolId(existing.id); return; }\n useChatStore.getState().clearThinking();\n useChatStore.getState().setCurrentAssistantMessage(null);\n const id = useChatStore.getState().addMessage({ role: 'tool', content: '', toolName: payload.name, toolInput: payload.input, toolUseId: payload.id });\n useChatStore.getState().setCurrentToolId(id);\n useChatStore.getState().addExecution({ id: payload.id, name: payload.name, input: payload.input, ok: true, startedAt: Date.now() });\n}\n\nexport function handleToolProgress(msg: WSServerMessage) {\n const payload = msg.payload as { id: string; name: string; event: { type: string; text?: string } };\n const text = (payload.event?.text ?? '').trim();\n if (!text) return;\n const messages = useChatStore.getState().messages;\n const owner = messages.find((m) => m.toolUseId === payload.id);\n if (!owner) return;\n const prefix = payload.event?.type === 'warning' ? '⚠ ' : '';\n useChatStore.getState().appendToolProgress(owner.id, prefix + text);\n}\n\nexport function handleToolExecuted(msg: WSServerMessage) {\n const payload = msg.payload as { id?: string; name: string; durationMs: number; ok: boolean; input?: unknown; output?: string };\n const { messages, currentToolId } = useChatStore.getState();\n const owner = payload.id ? messages.find((m) => m.toolUseId === payload.id) : currentToolId ? messages.find((m) => m.id === currentToolId) : undefined;\n if (owner?.toolResult !== undefined) return;\n if (owner) {\n useChatStore.getState().setToolResult(owner.id, payload.output ?? '', payload.ok);\n useChatStore.getState().updateMessage(owner.id, { toolDurationMs: payload.durationMs });\n }\n if (payload.id) useChatStore.getState().updateExecution(payload.id, { completedAt: Date.now(), durationMs: payload.durationMs, output: payload.output, ok: payload.ok });\n if (currentToolId && owner && owner.id === currentToolId) useChatStore.getState().setCurrentToolId(null);\n}\n\nexport function handleToolConfirmNeeded(msg: WSServerMessage) {\n const payload = msg.payload as { id: string; toolName: string; input: unknown; suggestedPattern: string };\n useUIStore.getState().showConfirm({ id: payload.id, toolName: payload.toolName, input: payload.input, suggestedPattern: payload.suggestedPattern });\n try { playPermissionChime(); } catch { /* audio policy */ }\n void ensureNotificationPermission();\n notifyIfHidden('WrongStack needs approval', `Tool \"${payload.toolName}\" is waiting for your decision.`, 'wrongstack-confirm');\n if (typeof document !== 'undefined' && document.hidden) setFaviconStatus('attention');\n}\n\nexport function handleRunResult(msg: WSServerMessage) {\n const payload = msg.payload as { status: string; iterations: number; finalText?: string; error?: { code: string; message: string; recoverable: boolean } };\n useSessionStore.getState().setIteration(null);\n useChatStore.getState().setLoading(false);\n useChatStore.getState().setCurrentAssistantMessage(null);\n useChatStore.getState().clearThinking();\n const runStart = useChatStore.getState().runStart;\n if (runStart && payload.status === 'done') {\n const all = useChatStore.getState().messages;\n let lastAssistantIdx = -1;\n let toolCount = 0;\n for (let i = all.length - 1; i >= 0; i--) {\n const m = all[i]!;\n if (m.role === 'assistant' && lastAssistantIdx === -1 && m.content) lastAssistantIdx = i;\n if (m.role === 'tool' && m.timestamp >= runStart.at) toolCount += 1;\n if (m.role === 'user' && m.timestamp <= runStart.at) break;\n }\n if (lastAssistantIdx !== -1) {\n const sessionCost = useSessionStore.getState().cost;\n useChatStore.getState().updateMessage(all[lastAssistantIdx]!.id, { runSummary: { iterations: payload.iterations, tools: toolCount, durationMs: Date.now() - runStart.at, costDelta: Math.max(0, sessionCost - runStart.cost) } });\n }\n }\n useChatStore.getState().setRunStart(null);\n if (payload.status !== 'done' && payload.error) {\n useChatStore.getState().addMessage({ role: 'assistant', content: `Error: ${payload.error.message}`, isError: true });\n toast.error(`Run ended: ${payload.error.message}`);\n notifyIfHidden('WrongStack run failed', payload.error.message);\n if (typeof document !== 'undefined' && document.hidden) setFaviconStatus('error');\n } else if (payload.status === 'done') {\n if (typeof document !== 'undefined' && document.hidden) {\n toast.success(`Run completed in ${payload.iterations} iteration${payload.iterations === 1 ? '' : 's'}`);\n notifyIfHidden('WrongStack run finished', `Completed in ${payload.iterations} iteration${payload.iterations === 1 ? '' : 's'}.`);\n setFaviconStatus('ready');\n }\n void ensureNotificationPermission();\n if (useConfigStore.getState().soundOnComplete) {\n try { playCompletionChime(); } catch { /* audio policy */ }\n }\n }\n const next = useChatStore.getState().dequeue();\n if (next) {\n const client = getWSClient(useConfigStore.getState().wsUrl);\n useChatStore.getState().addMessage({ role: 'user', content: next });\n useChatStore.getState().setLoading(true);\n client.sendMessage(next);\n }\n}\n\n// ── Info / misc handlers ──\n\nexport function handleToolsList(msg: WSServerMessage) {\n const p = msg.payload as { tools: Array<{ name: string; description: string; params: string[] }> };\n useChatStore.getState().addMessage({ role: 'assistant', content: [\n `🛠️ **Registered tools** (${p.tools.length})`, '',\n ...p.tools.map((t) => `• \\`${t.name}\\`${t.params.length ? ` (${t.params.join(', ')})` : ''} — ${t.description || '_no description_'}`),\n ].join('\\n') });\n}\n\nexport function handleMemoryList(msg: WSServerMessage) {\n const p = msg.payload as { text: string; error?: string };\n const body = p.text?.trim();\n useChatStore.getState().addMessage({ role: 'assistant', content: p.error ? `Memory read failed: ${p.error}` : body ? `🧠 **Memory** \\n\\n${body}` : '🧠 **Memory** \\n\\n_empty — nothing remembered yet_' });\n}\n\nexport function handleSkillsList(msg: WSServerMessage) {\n const p = msg.payload as { enabled: boolean; error?: string; skills: Array<{ name: string; description: string; version: string; source: string; path: string; trigger: string; scope: string[] }> };\n if (!p.enabled) { useChatStore.getState().addMessage({ role: 'assistant', content: '🎯 **Skills** \\n\\n_disabled (config.features.skills = false)_' }); return; }\n const lines = [`🎯 **Skills** (${p.skills.length})`, '', ...(p.skills.length === 0 ? ['_none registered_'] : p.skills.map((s) => `• \\`${s.name}\\`${s.version ? ` v${s.version}` : ''} _(${s.source})_ — ${s.description || s.trigger || '_no description_'}`))];\n if (p.error) lines.push('', `⚠ ${p.error}`);\n useChatStore.getState().addMessage({ role: 'assistant', content: lines.join('\\n') });\n}\n\nexport function handleDiagGet(msg: WSServerMessage) {\n const p = msg.payload as { provider: string; model: string; cwd: string; sessionId: string; tools: { count: number; names: string[] }; features: { memory: boolean; skills: boolean; modelsRegistry: boolean }; mode: string; usage: { input: number; output: number; cacheRead?: number }; messages: number; todos: number };\n useChatStore.getState().addMessage({ role: 'assistant', content: [\n '🩺 **Runtime diagnostics**', '',\n `**Provider:** \\`${p.provider}\\` / \\`${p.model}\\``,\n `**Mode:** \\`${p.mode}\\``, `**Session:** \\`${p.sessionId}\\``, `**CWD:** \\`${p.cwd}\\``, '',\n `**Tools:** ${p.tools.count}`, `**Messages:** ${p.messages} · **Todos:** ${p.todos}`,\n `**Usage:** ${p.usage.input.toLocaleString()} in · ${p.usage.output.toLocaleString()} out${p.usage.cacheRead ? ` · ${p.usage.cacheRead.toLocaleString()} cache` : ''}`, '',\n `**Features:** memory=${p.features.memory ? '✓' : '✗'} · skills=${p.features.skills ? '✓' : '✗'} · modelsRegistry=${p.features.modelsRegistry ? '✓' : '✗'}`,\n ].join('\\n') });\n}\n\nexport function handleStatsGet(msg: WSServerMessage) {\n const p = msg.payload as { sessionId: string; provider: string; model: string; usage: { input: number; output: number; cacheRead?: number; cacheWrite?: number }; cache: { readTokens: number; writeTokens: number; hitRatio: number } | null; cost: number; messages: number; readFiles: number; tools: number; elapsedMs: number };\n const elapsedSec = Math.floor(p.elapsedMs / 1000);\n const elapsed = elapsedSec < 60 ? `${elapsedSec}s` : elapsedSec < 3600 ? `${Math.floor(elapsedSec / 60)}m ${elapsedSec % 60}s` : `${Math.floor(elapsedSec / 3600)}h ${Math.floor((elapsedSec % 3600) / 60)}m`;\n useChatStore.getState().addMessage({ role: 'assistant', content: [\n '📈 **Session stats**', '',\n `**Session:** \\`${p.sessionId}\\``, `**Provider/Model:** \\`${p.provider}\\` / \\`${p.model}\\``, `**Elapsed:** ${elapsed}`, '',\n `**Usage:** ${p.usage.input.toLocaleString()} in · ${p.usage.output.toLocaleString()} out`,\n ...(p.cache && p.cache.readTokens > 0 ? [`**Cache:** ${p.cache.readTokens.toLocaleString()} read · ${p.cache.writeTokens.toLocaleString()} write · hit ratio ${(p.cache.hitRatio * 100).toFixed(1)}%`] : []),\n `**Cost:** $${p.cost.toFixed(4)}`, '',\n `**Messages:** ${p.messages} · **Files read:** ${p.readFiles} · **Tools available:** ${p.tools}`,\n ].join('\\n') });\n}\n\nexport function handleTodosUpdated(msg: WSServerMessage) {\n const p = msg.payload as { todos: Array<{ id: string; content: string; status: 'pending' | 'in_progress' | 'completed'; activeForm?: string }> };\n useSessionStore.getState().setTodos(p.todos ?? []);\n}\n\nexport function handleModesList(msg: WSServerMessage) {\n const p = msg.payload as { modes: Array<{ id: string; name: string; description: string; isActive: boolean }>; activeId: string };\n useSessionStore.getState().setModes(p.modes.map((m) => ({ id: m.id, name: m.name, description: m.description })));\n useSessionStore.getState().setEnv({ mode: p.activeId });\n}\n\nexport function handleContextModesList(msg: WSServerMessage) {\n const p = msg.payload as { activeId: string; modes: Array<{ id: string; name: string; description: string; isActive: boolean; thresholds?: { warn: number; soft: number; hard: number }; preserveK?: number; eliseThreshold?: number }> };\n useSessionStore.getState().setContextModes(p.modes.map((m) => ({ id: m.id, name: m.name, description: m.description, thresholds: m.thresholds, preserveK: m.preserveK, eliseThreshold: m.eliseThreshold })));\n useSessionStore.getState().setEnv({ contextMode: p.activeId });\n}\n\nexport function handleContextModeChanged(msg: WSServerMessage) {\n const p = msg.payload as { id: string; name?: string };\n useSessionStore.getState().setEnv({ contextMode: p.id });\n}\n\nexport function handleSessionsList(msg: WSServerMessage) {\n const payload = msg.payload as { sessions: SessionHistoryEntry[]; error?: string };\n useHistoryStore.getState().setEntries(payload.sessions ?? [], payload.error ?? null);\n}\n\nexport function handleError(msg: WSServerMessage) {\n const payload = msg.payload as { phase: string; message: string };\n useChatStore.getState().addMessage({ role: 'assistant', content: `[${payload.phase}] ${payload.message}`, isError: true });\n useChatStore.getState().setLoading(false);\n}\n\n// ── Worktree / Fleet handlers ──\n\nexport function handleWorktreeState(msg: WSServerMessage) {\n const p = msg.payload as { worktrees: WorktreeHandleView[]; baseBranch: string };\n useWorktreeStore.getState().setSnapshot(p.worktrees ?? [], p.baseBranch ?? '');\n}\n\nexport function handleWorktreeEvent(msg: WSServerMessage) {\n const p = msg.payload as { kind: string; handleId: string; text: string; at: number };\n useWorktreeStore.getState().pushEvent(p);\n}\n\nexport function handleSubagentEvent(msg: WSServerMessage) {\n useFleetStore.getState().applyEvent(msg.payload as SubagentEvent);\n}\n\n// ── Handler registry: maps message types to handler functions ──\n\nexport const WS_HANDLERS: Record<string, (msg: WSServerMessage) => void> = {\n 'session.start': handleSessionStart,\n 'context.debug': handleContextDebug,\n 'key.operation_result': handleKeyOperationResult,\n 'context.compacted': handleContextCompacted,\n 'provider.response': handleProviderResponse,\n 'context.repaired': handleContextRepaired,\n 'session.end': handleSessionEnd,\n 'iteration.started': handleIterationStarted,\n 'provider.text_delta': handleTextDelta,\n 'provider.thinking_delta': handleThinkingDelta,\n 'tool.started': handleToolStarted,\n 'tool.progress': handleToolProgress,\n 'tool.executed': handleToolExecuted,\n 'tool.confirm_needed': handleToolConfirmNeeded,\n 'run.result': handleRunResult,\n 'tools.list': handleToolsList,\n 'memory.list': handleMemoryList,\n 'skills.list': handleSkillsList,\n 'diag.get': handleDiagGet,\n 'stats.get': handleStatsGet,\n 'todos.updated': handleTodosUpdated,\n 'modes.list': handleModesList,\n 'context.modes.list': handleContextModesList,\n 'context.mode.changed': handleContextModeChanged,\n 'sessions.list': handleSessionsList,\n 'error': handleError,\n 'worktree.state': handleWorktreeState,\n 'worktree.event': handleWorktreeEvent,\n 'subagent.event': handleSubagentEvent,\n};\n","import { useWebSocketBootstrap } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useChatStore, useConfigStore, useSessionStore, useUIStore } from '@/stores';\nimport { useEffect } from 'react';\nimport { ChatView } from './components/ChatView';\nimport { CollabPanel } from './components/CollabPanel';\nimport { CommandPalette, downloadChatAsMarkdown } from './components/CommandPalette';\nimport { ConfirmDialog } from './components/ConfirmDialog';\nimport { ConnectionBanner } from './components/ConnectionBanner';\nimport { ErrorBoundary } from './components/ErrorBoundary';\nimport { FleetPanel } from './components/FleetPanel';\nimport { QuickModelSwitcher } from './components/QuickModelSwitcher';\nimport { SettingsPanel } from './components/SettingsPanel';\nimport { ShortcutsOverlay } from './components/ShortcutsOverlay';\nimport { Sidebar } from './components/Sidebar';\nimport { ThemeProvider, useTheme } from './components/ThemeProvider';\nimport { Toaster } from './components/Toaster';\n\nfunction AppInner() {\n const { theme } = useTheme();\n const { currentView, sidebarOpen, toggleSidebar, setSearchOpen, setSidebarOpen } = useUIStore();\n const isLoading = useChatStore((s) => s.isLoading);\n const iteration = useSessionStore((s) => s.iteration);\n const projectName = useSessionStore((s) => s.projectName);\n const sessionTitle = useSessionStore((s) => s.session?.title);\n const sessionId = useSessionStore((s) => s.session?.id);\n // User-set local nickname for the current session — takes precedence\n // over the backend title in the tab strip and topbar.\n const nickname = useUIStore((s) => (sessionId ? s.sessionNicknames[sessionId] : undefined));\n\n // Mobile-friendly: collapse the sidebar automatically below the md\n // breakpoint (768px). Tracks viewport changes so a window resize behaves\n // the same as a fresh load. We only AUTO-close — re-opening (or keeping\n // it open) on small screens stays a user decision, so we never call\n // setSidebarOpen(true) here.\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const mq = window.matchMedia('(max-width: 768px)');\n const apply = () => {\n if (mq.matches && useUIStore.getState().sidebarOpen) {\n setSidebarOpen(false);\n }\n };\n apply();\n mq.addEventListener('change', apply);\n return () => mq.removeEventListener('change', apply);\n }, [setSidebarOpen]);\n // Install WS handlers exactly once for the whole app. Every other consumer\n // (ChatInput, ConfirmDialog, SettingsPanel) uses the cheap `useWebSocket()`\n // hook which returns action methods only — see hooks/useWebSocket.ts for\n // the duplicate-handler trap this avoids.\n useWebSocketBootstrap();\n\n // Reflect the agent's run state + session identity in the browser tab\n // title. Pinned/grouped tab strips become readable at a glance — the\n // project name surfaces first so multiple WrongStack windows on the same\n // bar can still be distinguished, then the session title (if any), then\n // the running indicator. Falls back gracefully when fields are missing.\n useEffect(() => {\n const parts: string[] = [];\n if (isLoading) {\n const it = iteration\n ? ` iter ${iteration.index}${iteration.max ? `/${iteration.max}` : ''}`\n : '';\n parts.push(`●${it}`);\n }\n const sessionLabel = nickname?.trim() || sessionTitle?.trim();\n const projectLabel = projectName?.trim();\n if (sessionLabel) parts.push(sessionLabel);\n if (projectLabel) parts.push(projectLabel);\n parts.push('WrongStack');\n const title = parts.filter(Boolean).join(' · ');\n document.title = title;\n return () => {\n document.title = 'WrongStack';\n };\n }, [isLoading, iteration, projectName, sessionTitle, nickname]);\n\n // Global keyboard shortcuts for the actions that don't have a dedicated\n // owner (palette/shortcuts handle their own). Bound here so they fire\n // anywhere except inside text inputs (where Ctrl+F should still search\n // the chat, but Ctrl+L would otherwise be a browser address-bar focus).\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const t = e.target as HTMLElement | null;\n const tag = t?.tagName?.toLowerCase();\n const inField = tag === 'input' || tag === 'textarea' || t?.isContentEditable;\n const mod = e.ctrlKey || e.metaKey;\n if (mod && e.key === '\\\\') {\n e.preventDefault();\n toggleSidebar();\n return;\n }\n if (mod && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n setSearchOpen(true);\n return;\n }\n if (mod && e.key.toLowerCase() === '/') {\n // Focus the chat textarea so the user can start typing without\n // hunting for it. Useful after closing palette/settings.\n e.preventDefault();\n const ta = document.querySelector('textarea');\n ta?.focus();\n return;\n }\n // The Ctrl-letter shortcuts skip when the user is typing in any\n // input — otherwise Ctrl+L wipes the chat while they're composing.\n // Access the WS client via the Zustand store instead of the `ws`\n // hook return value so we don't re-register this effect on every\n // render (useWebSocket() returns a fresh object each time).\n if (mod && !inField) {\n if (e.key.toLowerCase() === 'l') {\n e.preventDefault();\n useChatStore.getState().clearMessages();\n getWSClient(useConfigStore.getState().wsUrl)?.clearContext?.();\n } else if (e.key.toLowerCase() === 'n') {\n e.preventDefault();\n getWSClient(useConfigStore.getState().wsUrl)?.newSession?.();\n } else if (e.key.toLowerCase() === 'e') {\n e.preventDefault();\n downloadChatAsMarkdown();\n }\n }\n // Ctrl+Shift+D toggles compact UI density. Distinct from Ctrl+D\n // (which is reserved as the browser bookmark accelerator).\n if (mod && e.shiftKey && e.key.toLowerCase() === 'd') {\n e.preventDefault();\n useUIStore.getState().toggleCompactMode();\n }\n // Vim-style chat navigation: j/k step between bubbles, g goes to the\n // first message and G to the last. Skipped while typing so j/k inside\n // the textarea still inserts those letters. No modifier required —\n // this is the chat surface's primary input mode for keyboard users.\n if (!inField && !mod && !e.altKey) {\n const bubbles = Array.from(document.querySelectorAll<HTMLElement>('[data-message-id]'));\n if (bubbles.length === 0) return;\n const current = document.querySelector<HTMLElement>(\n '[data-message-id][data-focused=\"true\"]',\n );\n const idx = current ? bubbles.indexOf(current) : -1;\n const focusBubble = (target: HTMLElement) => {\n for (const b of bubbles) b.removeAttribute('data-focused');\n target.setAttribute('data-focused', 'true');\n target.scrollIntoView({ behavior: 'smooth', block: 'center' });\n };\n if (e.key === 'j' || e.key === 'ArrowDown') {\n // ArrowDown only intercepts when nothing else has focus AND the\n // user is not in a scrollable list context — the textarea check\n // above covers the only place arrows have meaningful default\n // behaviour for this app.\n const next = bubbles[Math.min(bubbles.length - 1, Math.max(0, idx + 1))];\n if (next) {\n e.preventDefault();\n focusBubble(next);\n }\n return;\n }\n if (e.key === 'k' || e.key === 'ArrowUp') {\n const prev = bubbles[Math.max(0, idx <= 0 ? 0 : idx - 1)];\n if (prev) {\n e.preventDefault();\n focusBubble(prev);\n }\n return;\n }\n if (e.key === 'g' && !e.shiftKey) {\n e.preventDefault();\n focusBubble(bubbles[0]!);\n return;\n }\n if (e.key === 'G' || (e.key === 'g' && e.shiftKey)) {\n e.preventDefault();\n focusBubble(bubbles[bubbles.length - 1]!);\n return;\n }\n if (e.key === 'Escape' && current) {\n e.preventDefault();\n current.removeAttribute('data-focused');\n return;\n }\n // `c` while a bubble is focused: copy its visible text. Useful\n // pairing with the j/k flow so power users can step + copy without\n // hunting for the in-bubble copy button.\n if (e.key === 'c' && current) {\n const text =\n current.querySelector<HTMLElement>('.markdown-content')?.innerText ?? current.innerText;\n if (text) {\n void navigator.clipboard?.writeText(text).catch(() => {});\n e.preventDefault();\n }\n return;\n }\n }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [toggleSidebar, setSearchOpen]);\n\n return (\n <div className={cn('flex h-screen', theme)}>\n {sidebarOpen && <Sidebar />}\n <main className=\"flex-1 flex flex-col overflow-hidden\">\n <ConnectionBanner />\n {currentView === 'chat' && (\n <>\n {sessionId && (\n <div className=\"px-4 pt-2 space-y-2\">\n <CollabPanel sessionId={sessionId} />\n {/* Live subagent roster — self-hides when no fleet is running. */}\n <FleetPanel />\n </div>\n )}\n <ChatView />\n </>\n )}\n {currentView === 'settings' && <SettingsPanel />}\n </main>\n\n {/* Global overlays */}\n <ConfirmDialog />\n <CommandPalette />\n <ShortcutsOverlay />\n <QuickModelSwitcher />\n <Toaster />\n </div>\n );\n}\n\nexport function App() {\n return (\n <ErrorBoundary>\n <ThemeProvider defaultTheme=\"system\">\n <AppInner />\n </ThemeProvider>\n </ErrorBoundary>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useChatStore, useSessionStore, useUIStore } from '@/stores';\nimport type { ChatMessage } from '@/stores';\nimport { useConfigStore } from '@/stores';\nimport {\n Activity,\n ArrowDown,\n ArrowUp,\n Bot,\n Command,\n Cpu,\n FolderOpen,\n PanelLeftOpen,\n Settings,\n Zap,\n} from 'lucide-react';\nimport { type ReactNode, useCallback, useEffect, useRef, useState } from 'react';\nimport { ChatInput } from '../ChatInput';\nimport { ConnectionChip } from '../ConnectionChip';\nimport { ContextModePicker } from '../ContextModePicker';\nimport { CostChip } from '../CostChip';\nimport { MessageBubble } from '../MessageBubble';\nimport { ModePicker } from '../ModePicker';\nimport { SearchOverlay } from '../SearchOverlay';\nimport { ThemeToggle } from '../ThemeToggle';\nimport { ToolGroup } from '../ToolGroup';\nimport { WelcomeScreen } from '../WelcomeScreen';\nimport { Button } from '../ui/button';\nimport { ScrollArea } from '../ui/scroll-area';\nimport { fmtTok } from './utils.js';\nimport { ThinkingBubble } from './ThinkingBubble.js';\n\nexport function ChatView() {\n const { messages, isLoading } = useChatStore();\n const setPaletteOpen = useUIStore((s) => s.setPaletteOpen);\n const setShortcutsOpen = useUIStore((s) => s.setShortcutsOpen);\n const sidebarOpen = useUIStore((s) => s.sidebarOpen);\n const toggleSidebar = useUIStore((s) => s.toggleSidebar);\n const compactMode = useUIStore((s) => s.compactMode);\n const { totalTokens, startTime, lastInputTokens, maxContext, projectName, iteration } =\n useSessionStore();\n const { wsConnected, wsStatus, provider, model } = useConfigStore();\n const { setCurrentView } = useUIStore();\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Context window usage\n const ctxPct =\n maxContext > 0 && lastInputTokens > 0\n ? Math.min(100, Math.round((lastInputTokens / maxContext) * 100))\n : 0;\n const ctxTone =\n ctxPct >= 85\n ? 'bg-red-500/15 text-red-600 dark:text-red-400'\n : ctxPct >= 70\n ? 'bg-amber-500/15 text-amber-600 dark:text-amber-400'\n : 'bg-muted text-muted-foreground';\n\n // Auto-scroll with \"user is reading older messages\" lock\n const [pinnedToBottom, setPinnedToBottom] = useState(true);\n const [unreadCount, setUnreadCount] = useState(0);\n const [scrolledDeep, setScrolledDeep] = useState(false);\n const lastSeenCount = useRef(messages.length);\n\n const getViewport = useCallback((): HTMLElement | null => {\n return scrollRef.current?.querySelector('[data-radix-scroll-area-viewport]') ?? null;\n }, []);\n\n useEffect(() => {\n const viewport = getViewport();\n if (!viewport) return;\n const onScroll = () => {\n const dist = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;\n const nowPinned = dist < 120;\n setPinnedToBottom(nowPinned);\n if (nowPinned) {\n setUnreadCount(0);\n lastSeenCount.current = messages.length;\n }\n const deep =\n viewport.scrollTop > viewport.clientHeight &&\n viewport.scrollHeight > viewport.clientHeight * 2.5;\n setScrolledDeep(deep);\n };\n viewport.addEventListener('scroll', onScroll, { passive: true });\n return () => viewport.removeEventListener('scroll', onScroll);\n }, [getViewport, messages.length]);\n\n useEffect(() => {\n const viewport = getViewport();\n if (!viewport) return;\n if (pinnedToBottom) {\n viewport.scrollTop = viewport.scrollHeight;\n lastSeenCount.current = messages.length;\n } else {\n const delta = messages.length - lastSeenCount.current;\n if (delta > 0) setUnreadCount(delta);\n }\n }, [messages, pinnedToBottom, getViewport]);\n\n const scrollToBottom = useCallback(() => {\n const viewport = getViewport();\n if (!viewport) return;\n viewport.scrollTo({ top: viewport.scrollHeight, behavior: 'smooth' });\n setPinnedToBottom(true);\n setUnreadCount(0);\n lastSeenCount.current = messages.length;\n }, [getViewport, messages.length]);\n\n const scrollToTop = useCallback(() => {\n const viewport = getViewport();\n if (!viewport) return;\n viewport.scrollTo({ top: 0, behavior: 'smooth' });\n }, [getViewport]);\n\n // Live \"agent is busy\" indicator\n const [runStartedAt, setRunStartedAt] = useState<number | null>(null);\n const [nowTick, setNowTick] = useState<number>(() => Date.now());\n const streamAnchor = useRef<{ id: string; at: number; len: number } | null>(null);\n useEffect(() => {\n if (isLoading && runStartedAt === null) setRunStartedAt(Date.now());\n if (!isLoading && runStartedAt !== null) setRunStartedAt(null);\n }, [isLoading, runStartedAt]);\n useEffect(() => {\n if (!isLoading) return;\n const t = setInterval(() => setNowTick(Date.now()), 500);\n return () => clearInterval(t);\n }, [isLoading]);\n\n const formatDuration = (start: number | null) => {\n if (!start) return '--';\n const seconds = Math.floor((Date.now() - start) / 1000);\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${minutes}m ${secs}s`;\n };\n\n const agentState = (() => {\n if (!isLoading) return 'idle' as const;\n const last = messages[messages.length - 1];\n const isStreaming = last?.role === 'assistant' && !!last.content && last.streaming;\n return isStreaming ? ('streaming' as const) : ('thinking' as const);\n })();\n const stateTone =\n agentState === 'idle'\n ? 'bg-muted text-muted-foreground'\n : agentState === 'streaming'\n ? 'bg-blue-500/10 text-blue-600 dark:text-blue-400'\n : 'bg-amber-500/10 text-amber-600 dark:text-amber-400';\n\n const hasStatusContent =\n (maxContext > 0 && lastInputTokens > 0) || totalTokens.input > 0 || !!startTime;\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Header */}\n <header className=\"flex flex-col border-b bg-card shrink-0\">\n <div className=\"flex items-center justify-between gap-2 px-3 py-2\">\n <div className=\"flex items-center gap-1.5 min-w-0 flex-1\">\n {!sidebarOpen && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 shrink-0\"\n onClick={toggleSidebar}\n title=\"Open sidebar (Ctrl+\\\\)\"\n >\n <PanelLeftOpen className=\"h-4 w-4\" />\n </Button>\n )}\n {!sidebarOpen && (\n <div className=\"flex items-center gap-1.5 shrink-0 mr-1\">\n <div className=\"w-5 h-5 rounded bg-primary flex items-center justify-center\">\n <Zap className=\"h-3 w-3 text-primary-foreground\" />\n </div>\n </div>\n )}\n <ConnectionChip wsStatus={wsStatus} wsConnected={wsConnected} />\n <span\n className={cn(\n 'flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0 tabular-nums',\n stateTone,\n )}\n title={`Agent state: ${agentState}`}\n >\n {agentState !== 'idle' && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-current animate-pulse\" />\n )}\n <span>{agentState}</span>\n </span>\n {projectName && (\n <span\n className=\"flex items-center gap-1 text-[11px] text-muted-foreground shrink-0 min-w-0\"\n title={`Project: ${projectName}`}\n >\n <FolderOpen className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate max-w-[12rem]\">{projectName}</span>\n </span>\n )}\n <button\n type=\"button\"\n onClick={() => useUIStore.getState().setModelSwitcherOpen(true)}\n className=\"group flex items-center gap-1 px-2 py-0.5 rounded-md border bg-background/50 hover:bg-accent hover:border-primary/40 transition-colors text-[11px] min-w-0 shrink-0\"\n title=\"Change provider / model (Ctrl+M)\"\n >\n <Cpu className=\"h-3 w-3 text-muted-foreground group-hover:text-foreground shrink-0\" />\n <span className=\"font-mono truncate max-w-[16rem]\">\n <span className=\"text-muted-foreground\">{provider || 'no-provider'}</span>\n <span className=\"text-muted-foreground/40 mx-0.5\">/</span>\n <span className=\"font-medium\">{model || 'no-model'}</span>\n </span>\n </button>\n <ModePicker />\n <ContextModePicker />\n {iteration && (\n <span\n className=\"flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium bg-primary/10 text-primary shrink-0\"\n title=\"Agent iteration\"\n >\n <Activity className=\"h-3 w-3 animate-pulse\" />\n iter {iteration.index}\n {iteration.max > 0 ? `/${iteration.max}` : ''}\n </span>\n )}\n </div>\n\n <div className=\"flex items-center gap-0.5 shrink-0\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7\"\n onClick={() => setPaletteOpen(true)}\n title=\"Command palette (Ctrl+K)\"\n >\n <Command className=\"h-4 w-4\" />\n </Button>\n <ThemeToggle className=\"mx-0.5\" />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 font-mono text-xs\"\n onClick={() => setShortcutsOpen(true)}\n title=\"Keyboard shortcuts (?)\"\n >\n ?\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7\"\n onClick={() => setCurrentView('settings')}\n title=\"Settings\"\n >\n <Settings className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n\n {hasStatusContent && (\n <div className=\"flex items-center justify-between gap-3 px-3 py-1 border-t bg-muted/20 text-[11px] text-muted-foreground\">\n <div className=\"flex items-center gap-3 min-w-0 flex-1 tabular-nums\">\n {maxContext > 0 && lastInputTokens > 0 && (\n <span\n className={cn(\n 'flex items-center gap-1 px-1.5 py-0.5 rounded-full font-medium shrink-0',\n ctxTone,\n )}\n title={`Last input: ${lastInputTokens.toLocaleString()} / ${maxContext.toLocaleString()} tokens`}\n >\n ctx {ctxPct}% · {fmtTok(lastInputTokens)}/{fmtTok(maxContext)}\n </span>\n )}\n {totalTokens.input > 0 && (\n <>\n <span className=\"flex items-center gap-1\">\n <span className=\"font-medium text-foreground\">{fmtTok(totalTokens.input)}</span>\n <span>in</span>\n </span>\n <span className=\"flex items-center gap-1\">\n <span className=\"font-medium text-foreground\">\n {fmtTok(totalTokens.output)}\n </span>\n <span>out</span>\n </span>\n {totalTokens.cacheRead &&\n totalTokens.cacheRead > 0 &&\n (() => {\n const denom = (totalTokens.cacheRead ?? 0) + totalTokens.input;\n const pct =\n denom > 0 ? Math.round(((totalTokens.cacheRead ?? 0) / denom) * 100) : 0;\n return (\n <span\n className=\"flex items-center gap-1\"\n title={`Cache hit ratio: ${pct}%`}\n >\n <span className=\"font-medium text-foreground\">\n {fmtTok(totalTokens.cacheRead)}\n </span>\n <span>cache ({pct}%)</span>\n </span>\n );\n })()}\n <CostChip />\n </>\n )}\n </div>\n {startTime && (\n <span className=\"text-muted-foreground/70 tabular-nums shrink-0\">\n {formatDuration(startTime)}\n </span>\n )}\n </div>\n )}\n </header>\n\n {/* Messages */}\n <div className=\"flex-1 relative overflow-hidden\">\n <SearchOverlay />\n {!pinnedToBottom && (\n <button\n type=\"button\"\n onClick={scrollToBottom}\n className={cn(\n 'absolute bottom-4 left-1/2 -translate-x-1/2 z-10',\n 'flex items-center gap-2 px-4 py-2 rounded-full shadow-lg',\n 'bg-primary text-primary-foreground text-xs font-medium',\n 'hover:bg-primary/90 transition-colors animate-message',\n )}\n >\n <ArrowDown className=\"h-3.5 w-3.5\" />\n {unreadCount > 0\n ? `${unreadCount} new message${unreadCount === 1 ? '' : 's'}`\n : 'Jump to latest'}\n </button>\n )}\n {scrolledDeep && (\n <button\n type=\"button\"\n onClick={scrollToTop}\n title=\"Scroll to top (oldest)\"\n className={cn(\n 'absolute top-3 right-3 z-10',\n 'flex items-center gap-1 px-2.5 py-1 rounded-full shadow-md border',\n 'bg-background/90 backdrop-blur-sm text-[11px] text-muted-foreground',\n 'hover:text-foreground hover:bg-background transition-colors animate-message',\n )}\n >\n <ArrowUp className=\"h-3 w-3\" />\n <span>Top</span>\n </button>\n )}\n <ScrollArea className=\"h-full\" ref={scrollRef}>\n <div\n className={cn(\n 'mx-auto pb-8',\n compactMode ? 'max-w-5xl p-3 space-y-3' : 'max-w-5xl p-4 space-y-6',\n )}\n >\n {messages.length === 0 && !isLoading && <WelcomeScreen />}\n\n {/* Two-pass grouping */}\n {(() => {\n type Group =\n | { kind: 'msg'; message: ChatMessage; isFirst: boolean }\n | { kind: 'tools'; tools: ChatMessage[]; key: string };\n const groups: Group[] = [];\n for (let i = 0; i < messages.length; i++) {\n const m = messages[i]!;\n if (m.role === 'tool') {\n const last = groups[groups.length - 1];\n if (last && last.kind === 'tools') {\n last.tools.push(m);\n } else {\n groups.push({ kind: 'tools', tools: [m], key: m.id });\n }\n } else {\n const prev = messages[i - 1];\n groups.push({\n kind: 'msg',\n message: m,\n isFirst: !prev || prev.role !== m.role,\n });\n }\n }\n type Turn =\n | { kind: 'user'; message: ChatMessage; key: string }\n | { kind: 'agent'; items: Group[]; key: string };\n const turns: Turn[] = [];\n for (const g of groups) {\n if (g.kind === 'msg' && g.message.role === 'user') {\n turns.push({ kind: 'user', message: g.message, key: g.message.id });\n continue;\n }\n const last = turns[turns.length - 1];\n if (last && last.kind === 'agent') {\n last.items.push(g);\n } else {\n const key = g.kind === 'msg' ? g.message.id : g.key;\n turns.push({ kind: 'agent', items: [g], key });\n }\n }\n let prevDay: string | null = null;\n const dayKey = (ts: number) => {\n const d = new Date(ts);\n return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;\n };\n const dayLabel = (ts: number) => {\n const d = new Date(ts);\n const today = new Date();\n const yest = new Date(Date.now() - 86_400_000);\n if (dayKey(ts) === dayKey(today.getTime())) return 'Today';\n if (dayKey(ts) === dayKey(yest.getTime())) return 'Yesterday';\n return d.toLocaleDateString(undefined, {\n weekday: 'short',\n month: 'short',\n day: 'numeric',\n year: d.getFullYear() === today.getFullYear() ? undefined : 'numeric',\n });\n };\n const turnTs = (t: Turn): number => {\n if (t.kind === 'user') return t.message.timestamp;\n const first = t.items[0]!;\n return first.kind === 'msg' ? first.message.timestamp : first.tools[0]!.timestamp;\n };\n const out: ReactNode[] = [];\n for (let idx = 0; idx < turns.length; idx++) {\n const t = turns[idx]!;\n const ts = turnTs(t);\n const day = dayKey(ts);\n if (day !== prevDay) {\n out.push(\n <div\n key={`day-${day}-${idx}`}\n className=\"flex items-center gap-3 py-1 text-[11px] text-muted-foreground/70 uppercase tracking-wider font-medium\"\n >\n <div className=\"flex-1 h-px bg-border/50\" />\n <span>{dayLabel(ts)}</span>\n <div className=\"flex-1 h-px bg-border/50\" />\n </div>,\n );\n prevDay = day;\n }\n if (t.kind === 'user') {\n out.push(<MessageBubble key={t.key} message={t.message} isFirst />);\n continue;\n }\n const isLastTurn = idx === turns.length - 1;\n out.push(\n <div key={t.key} className={cn(compactMode ? 'space-y-1' : 'space-y-1.5')}>\n {t.items.map((g, gi) => {\n const continuation = gi > 0;\n if (g.kind === 'msg') {\n return (\n <MessageBubble\n key={g.message.id}\n message={g.message}\n isFirst={!continuation && g.isFirst}\n isContinuation={continuation}\n />\n );\n }\n const isLatestRunning =\n isLastTurn &&\n gi === t.items.length - 1 &&\n isLoading &&\n g.tools.some((tt) => tt.toolResult === undefined);\n return (\n <ToolGroup\n key={g.key}\n tools={g.tools}\n defaultOpen={isLatestRunning}\n isContinuation={continuation}\n />\n );\n })}\n </div>,\n );\n }\n return out;\n })()}\n\n <ThinkingBubble />\n\n {/* Running status bubble */}\n {isLoading &&\n (() => {\n const last = messages[messages.length - 1];\n const runningTools = messages.filter(\n (m) => m.role === 'tool' && m.toolResult === undefined,\n );\n let label = 'Thinking…';\n if (runningTools.length > 0) {\n const names = Array.from(\n new Set(runningTools.map((t) => t.toolName).filter(Boolean) as string[]),\n );\n const preview = names.slice(0, 2).join(', ');\n const more = names.length > 2 ? ` +${names.length - 2}` : '';\n label =\n runningTools.length === 1\n ? `Running ${preview || 'tool'}…`\n : `Running ${runningTools.length} tools (${preview}${more})…`;\n } else if (last?.role === 'assistant' && last.content) {\n label = 'Writing reply…';\n } else if (last?.role === 'tool' && last.toolResult !== undefined) {\n label = 'Thinking about the next step…';\n }\n const elapsedSec = runStartedAt\n ? Math.max(0, Math.floor((nowTick - runStartedAt) / 1000))\n : 0;\n const elapsed =\n elapsedSec < 60\n ? `${elapsedSec}s`\n : `${Math.floor(elapsedSec / 60)}m ${elapsedSec % 60}s`;\n let speedLabel = '';\n const streamingBubble =\n last?.role === 'assistant' && last.streaming && last.content ? last : null;\n if (streamingBubble) {\n const anchor = streamAnchor.current;\n if (!anchor || anchor.id !== streamingBubble.id) {\n streamAnchor.current = {\n id: streamingBubble.id,\n at: Date.now(),\n len: streamingBubble.content.length,\n };\n } else {\n const dt = Math.max(1, nowTick - anchor.at);\n const dl = Math.max(0, streamingBubble.content.length - anchor.len);\n if (dt > 500 && dl > 0) {\n const cps = (dl * 1000) / dt;\n speedLabel =\n cps >= 1000\n ? `${(cps / 1000).toFixed(1)}k ch/s`\n : `${Math.round(cps)} ch/s`;\n }\n }\n } else if (streamAnchor.current) {\n streamAnchor.current = null;\n }\n return (\n <div className=\"flex gap-3 animate-message\">\n <div className=\"flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center bg-accent text-accent-foreground ring-2 ring-offset-2 ring-offset-background ring-accent/20\">\n <Bot className=\"h-4 w-4\" />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <div className=\"rounded-2xl px-4 py-3 bg-card border text-foreground\">\n <div className=\"flex items-center gap-3 text-sm\">\n <span className=\"flex gap-1\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-primary/70 animate-bounce [animation-delay:-0.3s]\" />\n <span className=\"h-1.5 w-1.5 rounded-full bg-primary/70 animate-bounce [animation-delay:-0.15s]\" />\n <span className=\"h-1.5 w-1.5 rounded-full bg-primary/70 animate-bounce\" />\n </span>\n <span className=\"text-foreground/90\">{label}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n {elapsed}\n </span>\n {iteration && (\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n · iter {iteration.index}\n {iteration.max > 0 ? `/${iteration.max}` : ''}\n </span>\n )}\n {speedLabel && (\n <span className=\"text-xs text-muted-foreground/80 tabular-nums\">\n · {speedLabel}\n </span>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n })()}\n </div>\n </ScrollArea>\n </div>\n\n {/* Input */}\n <div className=\"border-t bg-card/50 backdrop-blur supports-[backdrop-filter]:bg-card/50 p-4 shrink-0\">\n <div className=\"max-w-5xl mx-auto\">\n <ChatInput />\n <p className=\"text-xs text-center text-muted-foreground/50 mt-2\">\n Press Enter to send, Shift+Enter for new line\n </p>\n </div>\n </div>\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\r\nimport { cn } from '@/lib/utils';\r\nimport { useChatStore, useSessionStore, useUIStore } from '@/stores';\r\nimport { Pencil, Send, Square } from 'lucide-react';\r\nimport type React from 'react';\r\nimport { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { downloadChatAsMarkdown } from './CommandPalette';\r\nimport { FilePicker } from './FilePicker';\r\nimport { Button } from './ui/button';\r\n\r\nimport { type SlashCommandDef, SLASH_COMMANDS, SLASH_CATEGORY_ORDER, matchSlash, detectAtMention } from './ChatInput/slash-commands.js';\r\n\r\nexport function ChatInput() {\r\n const { isLoading, setLoading, addMessage, clearMessages } = useChatStore();\r\n const queue = useChatStore((s) => s.queue);\r\n const enqueue = useChatStore((s) => s.enqueue);\r\n const removeQueued = useChatStore((s) => s.removeQueued);\r\n const clearQueue = useChatStore((s) => s.clearQueue);\r\n const { setCurrentView } = useUIStore();\r\n const pushPrompt = useUIStore((s) => s.pushPrompt);\r\n const promptHistory = useUIStore((s) => s.promptHistory);\r\n const ws = useWebSocket();\r\n const { sendMessage, sendAbort, client } = ws;\r\n /** Live context-budget signals — drive the token-estimate chip beside\r\n * the character counter. The estimate uses the universal 4-char-per-token\r\n * heuristic which is wrong by ±25% for natural prose but accurate enough\r\n * to warn the user before they paste a 100k-char file into a 200k window.\r\n * The chip only renders past the threshold so short drafts stay clean. */\r\n const lastInputTokens = useSessionStore((s) => s.lastInputTokens);\r\n const maxContext = useSessionStore((s) => s.maxContext);\r\n const [input, setInput] = useState('');\r\n const [slashIndex, setSlashIndex] = useState(0);\r\n /** Cursor into promptHistory. -1 = \"live input, not browsing history\".\r\n * Reset to -1 whenever the user types something that's NOT a history\r\n * navigation. */\r\n const [historyIdx, setHistoryIdx] = useState(-1);\r\n /** Open `@`-mention picker state. We track the starting position of the\r\n * `@` in the textarea so on pick we can replace the partial token\r\n * (`@compa`) with the chosen path. Null = closed. */\r\n const [atMention, setAtMention] = useState<{ start: number; query: string } | null>(null);\r\n /** Transient hint shown after a large paste. The user can read it for a\r\n * few seconds then it auto-dismisses. We only surface it for genuinely\r\n * big drops (>800 chars) — smaller pastes don't need a callout. */\r\n const [pasteHint, setPasteHint] = useState<{ chars: number; lines: number } | null>(null);\r\n /** True while an OS-drag is hovering over the input area. Triggers the\r\n * drop overlay so the user gets visual confirmation they're about to\r\n * attach. Browsers don't expose full filesystem paths from drops for\r\n * security reasons, so we seed the @-mention picker with the file's\r\n * basename and let the user confirm the resolved workspace path. */\r\n const [draggingOver, setDraggingOver] = useState(false);\r\n const textareaRef = useRef<HTMLTextAreaElement>(null);\r\n\r\n const runSlashCommand = useCallback(\r\n (raw: string): boolean => {\r\n const trimmed = raw.trim();\r\n // Split into head (with leading slash) + the rest. Lowercase the\r\n // head so `/Todos` and `/TODOS` route the same; preserve case on\r\n // the args because the user might be inserting a content string.\r\n const sp = trimmed.indexOf(' ');\r\n const head = (sp === -1 ? trimmed : trimmed.slice(0, sp)).toLowerCase();\r\n const args = sp === -1 ? '' : trimmed.slice(sp + 1).trim();\r\n const cmd = head;\r\n switch (cmd) {\r\n case '/help': {\r\n // Render the registry inline as an assistant message.\r\n const lines = [\r\n '📖 **Slash commands**',\r\n '',\r\n ...SLASH_COMMANDS.map(\r\n (c) =>\r\n `• \\`${c.name}\\`${c.aliases?.length ? ` (${c.aliases.map((a) => `\\`${a}\\``).join(', ')})` : ''} — ${c.description}`,\r\n ),\r\n ];\r\n addMessage({ role: 'assistant', content: lines.join('\\n') });\r\n return true;\r\n }\r\n case '/clear':\r\n clearMessages();\r\n client?.clearContext?.();\r\n return true;\r\n case '/new':\r\n client?.newSession?.();\r\n return true;\r\n case '/compact':\r\n case '/compact!':\r\n client?.compactContext?.(cmd === '/compact!');\r\n return true;\r\n case '/repair':\r\n client?.repairContext?.();\r\n return true;\r\n case '/debug':\r\n case '/context':\r\n client?.debugContext?.();\r\n return true;\r\n case '/tools':\r\n ws.listTools();\r\n return true;\r\n case '/memory':\r\n ws.listMemory();\r\n return true;\r\n case '/skill':\r\n case '/skills':\r\n ws.listSkills();\r\n return true;\r\n case '/diag':\r\n ws.getDiag();\r\n return true;\r\n case '/stats':\r\n ws.getStats();\r\n return true;\r\n case '/save':\r\n ws.saveSession();\r\n return true;\r\n case '/todos': {\r\n // Sub-commands: `/todos` (default = list), `/todos clear`. We\r\n // pull live state from the session store so the rendered output\r\n // matches what the sidebar already shows — no separate fetch.\r\n const sub = args.toLowerCase();\r\n if (sub === 'clear') {\r\n client?.clearTodos?.();\r\n return true;\r\n }\r\n const list = useSessionStore.getState().todos;\r\n if (list.length === 0) {\r\n addMessage({\r\n role: 'assistant',\r\n content:\r\n \"✅ **Todos** — _empty. Ask the agent to plan something and they'll show up here._\",\r\n });\r\n return true;\r\n }\r\n const lines: string[] = [\r\n `✅ **Todos** (${list.filter((t) => t.status === 'completed').length}/${list.length} done)`,\r\n '',\r\n ];\r\n for (const t of list) {\r\n const mark =\r\n t.status === 'completed' ? '[x]' : t.status === 'in_progress' ? '[~]' : '[ ]';\r\n const text = t.status === 'in_progress' && t.activeForm ? t.activeForm : t.content;\r\n lines.push(`- ${mark} ${text}`);\r\n }\r\n lines.push('', '_Use `/todos clear` to wipe the list._');\r\n addMessage({ role: 'assistant', content: lines.join('\\n') });\r\n return true;\r\n }\r\n case '/export':\r\n downloadChatAsMarkdown();\r\n addMessage({ role: 'assistant', content: '📥 Chat exported to your downloads folder.' });\r\n return true;\r\n case '/abort':\r\n case '/stop':\r\n sendAbort();\r\n setLoading(false);\r\n return true;\r\n case '/settings':\r\n case '/model':\r\n setCurrentView('settings');\r\n return true;\r\n default:\r\n return false;\r\n }\r\n },\r\n [addMessage, clearMessages, client, sendAbort, setLoading, setCurrentView, ws],\r\n );\r\n\r\n // Suggest slash commands as the user types. Only when the buffer is\r\n // exactly a slash command head — `/foo bar` shouldn't open the popup.\r\n const slashSuggestions = input.startsWith('/') && !input.includes(' ') ? matchSlash(input) : [];\r\n\r\n // Reset the highlight when the visible list changes so ↑/↓ always starts\r\n // from the top of the new matches.\r\n useEffect(() => {\r\n if (slashIndex >= slashSuggestions.length) setSlashIndex(0);\r\n }, [slashSuggestions.length, slashIndex]);\r\n\r\n /** Direct textarea DOM clear — bypasses useState so the UI updates\r\n * even when React batches the state update. */\r\n const _clearTextarea = useCallback(() => {\r\n const ta = textareaRef.current;\r\n if (ta) {\r\n ta.value = '';\r\n ta.style.height = 'auto';\r\n ta.style.height = `${Math.min(ta.scrollHeight, 200)}px`;\r\n if (!isLoading) { ta.focus(); }\r\n }\r\n }, [isLoading]);\r\n\r\n const handleSubmit = useCallback(\r\n async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!input.trim()) return;\r\n\r\n const content = input.trim();\r\n\r\n if (content.startsWith('/') && runSlashCommand(content)) {\r\n pushPrompt(content);\r\n setInput('');\r\n setHistoryIdx(-1);\r\n _clearTextarea();\r\n return;\r\n }\r\n\r\n setInput('');\r\n setHistoryIdx(-1);\r\n _clearTextarea();\r\n pushPrompt(content);\r\n _clearTextarea(); // ensure textarea is cleared even if batching delays state\r\n\r\n // If the agent is still running, queue the follow-up instead of\r\n // dropping it. The run.result handler in useWebSocket drains the\r\n // queue one message at a time. We also enable the textarea while\r\n // running so this code path is reachable.\r\n if (isLoading) {\r\n enqueue(content);\r\n return;\r\n }\r\n\r\n try {\r\n if (client?.isConnected) {\r\n addMessage({ role: 'user', content });\r\n setLoading(true);\r\n sendMessage(content);\r\n } else {\r\n console.error('WebSocket not connected');\r\n }\r\n } catch (err) {\r\n console.error('Failed to send:', err);\r\n setLoading(false);\r\n }\r\n },\r\n [\r\n input,\r\n isLoading,\r\n enqueue,\r\n client,\r\n sendMessage,\r\n setLoading,\r\n addMessage,\r\n runSlashCommand,\r\n pushPrompt,\r\n _clearTextarea,\r\n ],\r\n );\r\n\r\n const handleAbort = useCallback(() => {\r\n sendAbort();\r\n setLoading(false);\r\n }, [sendAbort, setLoading]);\r\n\r\n /** \"Stop & edit\" — abort the in-flight run, then pull the last user\r\n * message back into the input so the user can rewrite the prompt and\r\n * resend. Saves the two-step dance of clicking Abort, waiting for the\r\n * agent to settle, then hunting for the original prompt. */\r\n const handleStopAndEdit = useCallback(() => {\r\n sendAbort();\r\n setLoading(false);\r\n const all = useChatStore.getState().messages;\r\n for (let i = all.length - 1; i >= 0; i--) {\r\n const m = all[i]!;\r\n if (m.role === 'user' && m.content) {\r\n setInput(m.content);\r\n requestAnimationFrame(() => {\r\n const ta = textareaRef.current;\r\n if (ta) {\r\n ta.style.height = 'auto';\r\n ta.style.height = `${Math.min(ta.scrollHeight, 200)}px`;\r\n ta.focus();\r\n ta.setSelectionRange(m.content.length, m.content.length);\r\n }\r\n });\r\n return;\r\n }\r\n }\r\n }, [sendAbort, setLoading]);\r\n\r\n const handleKeyDown = useCallback(\r\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\r\n // Terminal-style prompt history: ↑ pulls the previous user prompt,\r\n // ↓ steps forward. Only active when both popups are closed AND the\r\n // input is empty OR already showing a history entry. We keep the cursor\r\n // ergonomic — once the user starts editing, we drop out of history mode.\r\n if (slashSuggestions.length === 0 && !atMention && promptHistory.length > 0) {\r\n if (e.key === 'ArrowUp') {\r\n const ta = e.currentTarget;\r\n // Only steal ↑ if we're on the first line (so multi-line editing\r\n // can still navigate within the textarea naturally).\r\n const beforeCursor = ta.value.slice(0, ta.selectionStart);\r\n if (historyIdx >= 0 || beforeCursor.indexOf('\\n') === -1) {\r\n e.preventDefault();\r\n const next = Math.min(promptHistory.length - 1, historyIdx + 1);\r\n setHistoryIdx(next);\r\n const text = promptHistory[next] ?? '';\r\n setInput(text);\r\n requestAnimationFrame(() => {\r\n const el = textareaRef.current;\r\n if (el) {\r\n el.style.height = 'auto';\r\n el.style.height = `${Math.min(el.scrollHeight, 200)}px`;\r\n el.setSelectionRange(text.length, text.length);\r\n }\r\n });\r\n return;\r\n }\r\n }\r\n if (e.key === 'ArrowDown' && historyIdx >= 0) {\r\n e.preventDefault();\r\n const next = historyIdx - 1;\r\n if (next < 0) {\r\n setHistoryIdx(-1);\r\n setInput('');\r\n } else {\r\n setHistoryIdx(next);\r\n const text = promptHistory[next] ?? '';\r\n setInput(text);\r\n requestAnimationFrame(() => {\r\n const el = textareaRef.current;\r\n if (el) {\r\n el.style.height = 'auto';\r\n el.style.height = `${Math.min(el.scrollHeight, 200)}px`;\r\n el.setSelectionRange(text.length, text.length);\r\n }\r\n });\r\n }\r\n return;\r\n }\r\n }\r\n\r\n // Slash popup keyboard navigation: ↑/↓ to select, Tab/Enter to commit,\r\n // Esc to dismiss. Matches the TUI's slash menu UX one-for-one so users\r\n // moving between surfaces don't have to relearn anything.\r\n if (slashSuggestions.length > 0) {\r\n if (e.key === 'ArrowDown') {\r\n e.preventDefault();\r\n setSlashIndex((i) => (i + 1) % slashSuggestions.length);\r\n return;\r\n }\r\n if (e.key === 'ArrowUp') {\r\n e.preventDefault();\r\n setSlashIndex((i) => (i - 1 + slashSuggestions.length) % slashSuggestions.length);\r\n return;\r\n }\r\n if (e.key === 'Tab') {\r\n e.preventDefault();\r\n const pick = slashSuggestions[slashIndex];\r\n if (pick) {\r\n setInput(pick.name + ' ');\r\n setSlashIndex(0);\r\n }\r\n return;\r\n }\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n // Commit the highlighted suggestion if there's an exact match below\r\n // the cursor (or the user hasn't typed a full name yet). Otherwise\r\n // fall through to normal submit.\r\n const pick = slashSuggestions[slashIndex];\r\n if (pick && pick.name !== input.toLowerCase().trim()) {\r\n e.preventDefault();\r\n setInput('');\r\n runSlashCommand(pick.name);\r\n return;\r\n }\r\n }\r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n setInput('');\r\n return;\r\n }\r\n }\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSubmit(e);\r\n }\r\n },\r\n [slashSuggestions, slashIndex, atMention, promptHistory, historyIdx, input, runSlashCommand, handleSubmit],\r\n );\r\n\r\n const adjustTextareaHeight = () => {\r\n const textarea = textareaRef.current;\r\n if (textarea) {\r\n textarea.style.height = 'auto';\r\n textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"flex flex-col gap-2\">\r\n {/* Smart paste hint — transient, auto-dismisses after 4s. We don't\r\n *do* anything with it (no auto-attach), just inform; users who\r\n pasted by accident can still Cmd+Z. */}\r\n {pasteHint && (\r\n <div className=\"rounded-md border border-amber-500/30 bg-amber-500/5 text-amber-700 dark:text-amber-300 px-2.5 py-1.5 text-xs flex items-center justify-between gap-2 animate-message\">\r\n <span>\r\n Pasted{' '}\r\n <span className=\"font-mono tabular-nums\">{pasteHint.chars.toLocaleString()}</span> chars\r\n (<span className=\"font-mono tabular-nums\">{pasteHint.lines}</span> lines) — fenced code\r\n blocks render best with <span className=\"font-mono\">```</span>.\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={() => setPasteHint(null)}\r\n className=\"text-amber-600/70 hover:text-amber-600 dark:text-amber-300/70 dark:hover:text-amber-300 shrink-0\"\r\n title=\"Dismiss\"\r\n >\r\n ×\r\n </button>\r\n </div>\r\n )}\r\n {/* Queue visualization — shows messages the user stacked while the\r\n agent was still running. Each row has a remove button; the whole\r\n queue can be cleared. The hook below drains them after run.result. */}\r\n {queue.length > 0 && (\r\n <div className=\"rounded-lg border bg-muted/30 p-2 text-xs\">\r\n <div className=\"flex items-center justify-between mb-1.5\">\r\n <span className=\"text-[10px] uppercase tracking-wider text-muted-foreground font-medium\">\r\n Queued ({queue.length})\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={clearQueue}\r\n className=\"text-muted-foreground hover:text-destructive text-xs\"\r\n >\r\n Clear all\r\n </button>\r\n </div>\r\n <ul className=\"space-y-1\">\r\n {queue.map((q, i) => (\r\n <li\r\n // biome-ignore lint/suspicious/noArrayIndexKey: queue has stable order\r\n key={i}\r\n className=\"flex items-start justify-between gap-2 rounded bg-background/60 border px-2 py-1\"\r\n >\r\n <span className=\"truncate flex-1 min-w-0\">{q}</span>\r\n <button\r\n type=\"button\"\r\n onClick={() => removeQueued(i)}\r\n className=\"text-muted-foreground hover:text-destructive shrink-0\"\r\n title=\"Remove from queue\"\r\n >\r\n ×\r\n </button>\r\n </li>\r\n ))}\r\n </ul>\r\n </div>\r\n )}\r\n\r\n <form\r\n onSubmit={handleSubmit}\r\n onDragEnter={(e) => {\r\n // Only react to drags carrying files — text/uri-list drags from\r\n // other parts of the page shouldn't trip the overlay.\r\n if (!e.dataTransfer || !Array.from(e.dataTransfer.types).includes('Files')) return;\r\n e.preventDefault();\r\n setDraggingOver(true);\r\n }}\r\n onDragOver={(e) => {\r\n if (!e.dataTransfer || !Array.from(e.dataTransfer.types).includes('Files')) return;\r\n // preventDefault on dragover is what makes the area a valid drop\r\n // target — without it the browser navigates to the file instead.\r\n e.preventDefault();\r\n e.dataTransfer.dropEffect = 'copy';\r\n }}\r\n onDragLeave={(e) => {\r\n // dragleave fires when crossing child boundaries too; only clear if\r\n // the cursor genuinely left the form (relatedTarget outside or null).\r\n if (e.currentTarget.contains(e.relatedTarget as Node | null)) return;\r\n setDraggingOver(false);\r\n }}\r\n onDrop={(e) => {\r\n if (!e.dataTransfer) return;\r\n const files = Array.from(e.dataTransfer.files ?? []);\r\n if (files.length === 0) {\r\n setDraggingOver(false);\r\n return;\r\n }\r\n e.preventDefault();\r\n setDraggingOver(false);\r\n // Insert `@<filename>` per dropped file at the current cursor, with\r\n // spaces between them. Browsers strip the full path for security, so\r\n // we use the basename only — the FilePicker (opened by setting\r\n // atMention to the last inserted handle) will resolve it against\r\n // the workspace tree.\r\n const ta = textareaRef.current;\r\n const insertPos = ta?.selectionStart ?? input.length;\r\n const before = input.slice(0, insertPos);\r\n const after = input.slice(insertPos);\r\n const needsLeadingSpace = before.length > 0 && !/\\s$/.test(before);\r\n const lead = needsLeadingSpace ? ' ' : '';\r\n const tokens = files.map((f) => `@${f.name}`);\r\n const joined = tokens.join(' ');\r\n // Trailing space only when there isn't already one — keeps the\r\n // cursor neatly between insert and following text.\r\n const needsTrailingSpace = after.length === 0 || !/^\\s/.test(after);\r\n const trail = needsTrailingSpace ? ' ' : '';\r\n const insertion = `${lead}${joined}${trail}`;\r\n const next = before + insertion + after;\r\n setInput(next);\r\n // Open the FilePicker against the LAST dropped basename so the user\r\n // can replace the basename with the correctly-resolved workspace\r\n // path. Position the @-mention start at the `@` of the last token.\r\n const lastTokenStart =\r\n before.length +\r\n lead.length +\r\n tokens.slice(0, -1).join(' ').length +\r\n (tokens.length > 1 ? 1 : 0);\r\n const lastBasename = files[files.length - 1]!.name;\r\n requestAnimationFrame(() => {\r\n if (ta) {\r\n const cur = before.length + insertion.length - trail.length;\r\n ta.focus();\r\n ta.setSelectionRange(cur, cur);\r\n ta.style.height = 'auto';\r\n ta.style.height = `${Math.min(ta.scrollHeight, 200)}px`;\r\n }\r\n setAtMention({ start: lastTokenStart, query: lastBasename });\r\n });\r\n }}\r\n className={cn(\r\n 'flex items-end gap-2 relative rounded-lg transition-colors',\r\n draggingOver && 'ring-2 ring-primary ring-offset-2 ring-offset-background bg-primary/5',\r\n )}\r\n >\r\n {draggingOver && (\r\n <div className=\"absolute inset-0 z-20 flex items-center justify-center pointer-events-none rounded-lg bg-primary/10 text-primary text-sm font-medium\">\r\n Drop file{`(s)`} to attach as @-mention\r\n </div>\r\n )}\r\n <div className=\"relative flex-1\">\r\n {/* @-mention file picker — takes priority over the slash popup\r\n since `@` and `/` can't both be active at the cursor. */}\r\n {atMention && (\r\n <FilePicker\r\n query={atMention.query}\r\n onClose={() => setAtMention(null)}\r\n onPick={(p) => {\r\n // Replace the partial `@query` with `@<path> `, then move\r\n // the cursor after the inserted space so typing continues\r\n // naturally.\r\n const before = input.slice(0, atMention.start);\r\n const after = input.slice(atMention.start + 1 + atMention.query.length);\r\n const inserted = `@${p} `;\r\n const next = before + inserted + after;\r\n setInput(next);\r\n setAtMention(null);\r\n requestAnimationFrame(() => {\r\n const ta = textareaRef.current;\r\n if (ta) {\r\n const pos = before.length + inserted.length;\r\n ta.focus();\r\n ta.setSelectionRange(pos, pos);\r\n ta.style.height = 'auto';\r\n ta.style.height = `${Math.min(ta.scrollHeight, 200)}px`;\r\n }\r\n });\r\n }}\r\n />\r\n )}\r\n\r\n {/* Slash command popup — descriptions inline, ↑/↓ to select, Tab to\r\n autocomplete, Enter to dispatch directly. Click also works. */}\r\n {!atMention &&\r\n slashSuggestions.length > 0 &&\r\n (() => {\r\n // Bucket the suggestions by category and preserve the global\r\n // index across categories — the keyboard navigation (↑/↓) tracks\r\n // a flat index, so each rendered row needs to map back to its\r\n // position in the un-grouped `slashSuggestions` array.\r\n const byCategory: Record<string, Array<{ cmd: SlashCommandDef; idx: number }>> = {};\r\n slashSuggestions.forEach((cmd, idx) => {\r\n if (!byCategory[cmd.category]) byCategory[cmd.category] = [];\r\n byCategory[cmd.category]!.push({ cmd, idx });\r\n });\r\n const orderedCategories = SLASH_CATEGORY_ORDER.filter((c) => byCategory[c]?.length);\r\n return (\r\n <div className=\"absolute bottom-full left-0 right-0 mb-2 rounded-lg border bg-popover shadow-md p-1 text-sm max-h-72 overflow-auto\">\r\n <div className=\"px-3 py-1 text-[10px] uppercase tracking-wider text-muted-foreground border-b mb-1\">\r\n ↑/↓ select · Tab complete · Enter dispatch · Esc dismiss\r\n </div>\r\n {orderedCategories.map((cat) => (\r\n <div key={cat} className=\"mb-1\">\r\n <div className=\"px-3 pt-1 pb-0.5 text-[10px] uppercase tracking-wider text-muted-foreground/70 font-semibold\">\r\n {cat}\r\n </div>\r\n {byCategory[cat]!.map(({ cmd, idx }) => (\r\n <button\r\n type=\"button\"\r\n key={cmd.name}\r\n onClick={() => {\r\n setInput('');\r\n runSlashCommand(cmd.name);\r\n }}\r\n onMouseEnter={() => setSlashIndex(idx)}\r\n className={cn(\r\n 'w-full text-left px-3 py-1.5 rounded transition-colors flex items-center gap-3',\r\n idx === slashIndex\r\n ? 'bg-accent text-accent-foreground'\r\n : 'hover:bg-accent/40',\r\n )}\r\n >\r\n <span className=\"font-mono shrink-0\">{cmd.name}</span>\r\n {cmd.aliases?.length ? (\r\n <span className=\"text-xs text-muted-foreground/70 font-mono shrink-0\">\r\n ({cmd.aliases.join(', ')})\r\n </span>\r\n ) : null}\r\n <span className=\"text-xs text-muted-foreground truncate\">\r\n — {cmd.description}\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n })()}\r\n <textarea\r\n ref={textareaRef}\r\n value={input}\r\n onChange={(e) => {\r\n const v = e.target.value;\r\n setInput(v);\r\n adjustTextareaHeight();\r\n // Manual typing drops us out of history mode so the next\r\n // Enter sends the user's edits, not a stale history entry.\r\n if (historyIdx >= 0) setHistoryIdx(-1);\r\n // Detect / refresh @-mention based on cursor position.\r\n const cur = e.target.selectionStart ?? v.length;\r\n setAtMention(detectAtMention(v, cur));\r\n }}\r\n onSelect={(e) => {\r\n const ta = e.currentTarget;\r\n setAtMention(detectAtMention(ta.value, ta.selectionStart));\r\n }}\r\n onKeyDown={handleKeyDown}\r\n onPaste={(e) => {\r\n // Surface a tiny hint when the user drops a chunky payload —\r\n // helps them realize they pasted the wrong thing (e.g. an\r\n // entire file when they meant a snippet). 4-second TTL.\r\n const text = e.clipboardData?.getData('text') ?? '';\r\n if (text.length > 800) {\r\n const lines = text.split('\\n').length;\r\n setPasteHint({ chars: text.length, lines });\r\n setTimeout(() => setPasteHint(null), 4000);\r\n }\r\n }}\r\n placeholder={\r\n !client?.isConnected\r\n ? 'Connect to server first…'\r\n : isLoading\r\n ? 'Agent is running — type to queue a follow-up…'\r\n : 'Message WrongStack… (type / for commands, @ for files)'\r\n }\r\n className={cn(\r\n 'flex min-h-[44px] w-full resize-none rounded-lg border border-input bg-background px-4 py-3 pr-12',\r\n 'text-sm ring-offset-background placeholder:text-muted-foreground',\r\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\r\n 'disabled:cursor-not-allowed disabled:opacity-50',\r\n 'scrollbar-thin',\r\n )}\r\n rows={1}\r\n disabled={!client?.isConnected}\r\n />\r\n\r\n {input.length > 0 &&\r\n (() => {\r\n // Hide the token estimate until the draft is non-trivial — small\r\n // messages aren't worth a context warning, and the chip would\r\n // otherwise just flicker as the user types each character.\r\n const showTokens = input.length >= 400;\r\n const estTokens = Math.ceil(input.length / 4);\r\n // Project the next request's context usage: last sent + draft +\r\n // small overhead. If that crosses 85% of the configured window,\r\n // tint amber; past 100% turns red. Falls through to muted when\r\n // we don't have the window size yet (e.g. before first request).\r\n let tone = 'text-muted-foreground';\r\n let title: string | undefined;\r\n if (maxContext > 0 && showTokens) {\r\n const projected = lastInputTokens + estTokens + 64;\r\n const pct = (projected / maxContext) * 100;\r\n if (pct >= 100) {\r\n tone = 'text-red-600 dark:text-red-400 font-medium';\r\n title = `Projected ${Math.round(pct)}% of ${maxContext.toLocaleString()} ctx — will likely error or compact.`;\r\n } else if (pct >= 85) {\r\n tone = 'text-amber-600 dark:text-amber-400 font-medium';\r\n title = `Projected ${Math.round(pct)}% of ${maxContext.toLocaleString()} ctx — getting tight.`;\r\n } else {\r\n title = `≈ ${estTokens.toLocaleString()} tokens · projected ${Math.round(pct)}% of ${maxContext.toLocaleString()} ctx.`;\r\n }\r\n } else if (showTokens) {\r\n title = `≈ ${estTokens.toLocaleString()} tokens (4-char heuristic)`;\r\n }\r\n return (\r\n <span\r\n className={cn('absolute bottom-1.5 right-12 text-xs tabular-nums', tone)}\r\n title={title}\r\n >\r\n {input.length}\r\n {showTokens && (\r\n <span className=\"ml-1 opacity-70\">\r\n · ≈{estTokens >= 1000 ? `${(estTokens / 1000).toFixed(1)}k` : estTokens}t\r\n </span>\r\n )}\r\n </span>\r\n );\r\n })()}\r\n </div>\r\n\r\n <div className=\"flex gap-1\">\r\n {isLoading ? (\r\n <>\r\n <Button\r\n type=\"button\"\r\n size=\"icon\"\r\n variant=\"outline\"\r\n onClick={handleStopAndEdit}\r\n className=\"h-[44px] w-[44px] rounded-lg\"\r\n title=\"Stop run and edit the last prompt (reuse + rewrite)\"\r\n >\r\n <Pencil className=\"h-4 w-4\" />\r\n </Button>\r\n <Button\r\n type=\"button\"\r\n size=\"icon\"\r\n variant=\"destructive\"\r\n onClick={handleAbort}\r\n className=\"h-[44px] w-[44px] rounded-lg\"\r\n title=\"Abort the current run\"\r\n >\r\n <Square className=\"h-4 w-4 fill-current\" />\r\n </Button>\r\n </>\r\n ) : (\r\n <Button\r\n type=\"submit\"\r\n size=\"icon\"\r\n disabled={!input.trim() || !client?.isConnected}\r\n className=\"h-[44px] w-[44px] rounded-lg\"\r\n >\r\n <Send className=\"h-4 w-4\" />\r\n </Button>\r\n )}\r\n </div>\r\n </form>\r\n </div>\r\n );\r\n}\r\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { playCompletionChime } from '@/lib/chime';\nimport { cn } from '@/lib/utils';\nimport {\n useChatStore,\n useConfigStore,\n useHistoryStore,\n useUIStore,\n} from '@/stores';\nimport {\n ArchiveRestore,\n BarChart3,\n Brain,\n Cpu,\n Database,\n Download,\n Hash,\n History as HistoryIcon,\n type LucideIcon,\n Maximize2,\n Monitor,\n Moon,\n RotateCcw,\n Search,\n Settings as SettingsIcon,\n Sparkles,\n Stethoscope,\n Sun,\n Trash2,\n Volume2,\n VolumeX,\n Wrench,\n} from 'lucide-react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { downloadChatAsHtml, downloadChatAsMarkdown } from './export-utils.js';\n\ninterface PaletteItem {\n id: string;\n category: 'Command' | 'Session' | 'Theme' | 'Tool';\n label: string;\n hint?: string;\n icon: LucideIcon;\n keywords?: string[];\n run: () => void;\n}\n\nexport function CommandPalette() {\n const open = useUIStore((s) => s.paletteOpen);\n const setOpen = useUIStore((s) => s.setPaletteOpen);\n const setCurrentView = useUIStore((s) => s.setCurrentView);\n const setTheme = useConfigStore((s) => s.setTheme);\n const { entries: historyEntries } = useHistoryStore();\n const { addMessage, clearMessages } = useChatStore();\n const ws = useWebSocket();\n\n const [query, setQuery] = useState('');\n const [index, setIndex] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (open) {\n setQuery('');\n setIndex(0);\n requestAnimationFrame(() => inputRef.current?.focus());\n }\n }, [open]);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') {\n e.preventDefault();\n setOpen(!useUIStore.getState().paletteOpen);\n return;\n }\n if (e.key === 'Escape' && useUIStore.getState().paletteOpen) {\n e.preventDefault();\n setOpen(false);\n }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [setOpen]);\n\n const items = useMemo<PaletteItem[]>(() => {\n const base: PaletteItem[] = [\n {\n id: 'help', category: 'Command', label: 'Show slash commands',\n icon: Hash, keywords: ['help', 'commands', '?'],\n run: () => { addMessage({ role: 'assistant', content: 'Type `/` in the message box to see every slash command.' }); },\n },\n {\n id: 'tools', category: 'Command', label: 'List tools',\n icon: Wrench, keywords: ['tools', 'list'],\n run: () => ws.listTools(),\n },\n {\n id: 'memory', category: 'Command', label: 'Show memory',\n icon: Brain, keywords: ['memory', 'remember', 'notes'],\n run: () => ws.listMemory(),\n },\n {\n id: 'skills', category: 'Command', label: 'List skills',\n icon: Sparkles, keywords: ['skills'],\n run: () => ws.listSkills(),\n },\n {\n id: 'diag', category: 'Command', label: 'Runtime diagnostics',\n icon: Stethoscope, keywords: ['diag', 'diagnostics', 'debug'],\n run: () => ws.getDiag(),\n },\n {\n id: 'stats', category: 'Command', label: 'Session stats (tokens, cache, cost)',\n icon: BarChart3, keywords: ['stats', 'tokens', 'cost', 'cache'],\n run: () => ws.getStats(),\n },\n {\n id: 'clear', category: 'Session', label: 'Clear context',\n hint: 'Wipe in-memory context, keep session id',\n icon: Trash2, keywords: ['clear', 'reset', 'wipe'],\n run: () => { clearMessages(); ws.client?.clearContext?.(); },\n },\n {\n id: 'new', category: 'Session', label: 'New session',\n hint: 'Brand-new on disk + memory',\n icon: RotateCcw, keywords: ['new', 'fresh', 'session'],\n run: () => ws.client?.newSession?.(),\n },\n {\n id: 'compact', category: 'Session', label: 'Compact context',\n icon: Database, keywords: ['compact', 'shrink', 'context'],\n run: () => ws.client?.compactContext?.(),\n },\n {\n id: 'repair-context', category: 'Session', label: 'Repair context',\n hint: 'Remove orphan tool protocol blocks',\n icon: Wrench, keywords: ['repair', 'context', 'tool_use', 'tool_result'],\n run: () => ws.client?.repairContext?.(),\n },\n {\n id: 'export', category: 'Session', label: 'Export chat as markdown',\n icon: Download, keywords: ['export', 'save', 'markdown', 'download'],\n run: () => downloadChatAsMarkdown(),\n },\n {\n id: 'export-html', category: 'Session', label: 'Export chat as HTML',\n hint: 'Self-contained, opens in any browser',\n icon: Download, keywords: ['export', 'html', 'download', 'archive'],\n run: () => downloadChatAsHtml(),\n },\n {\n id: 'history', category: 'Command', label: 'Open history',\n icon: HistoryIcon, keywords: ['history', 'sessions'],\n run: () => setCurrentView('history'),\n },\n {\n id: 'settings', category: 'Command', label: 'Open settings',\n icon: SettingsIcon, keywords: ['settings', 'config'],\n run: () => setCurrentView('settings'),\n },\n {\n id: 'model', category: 'Command', label: 'Change provider/model',\n icon: Cpu, keywords: ['model', 'provider', 'change'],\n run: () => setCurrentView('settings'),\n },\n { id: 'theme-light', category: 'Theme', label: 'Theme: Light', icon: Sun, keywords: ['theme', 'light', 'mode'], run: () => setTheme('light') },\n { id: 'theme-dark', category: 'Theme', label: 'Theme: Dark', icon: Moon, keywords: ['theme', 'dark', 'mode'], run: () => setTheme('dark') },\n { id: 'theme-system', category: 'Theme', label: 'Theme: Follow system', icon: Monitor, keywords: ['theme', 'system', 'auto'], run: () => setTheme('system') },\n {\n id: 'compact-toggle', category: 'Command', label: 'Toggle compact density',\n icon: Maximize2, hint: 'Ctrl+Shift+D', keywords: ['compact', 'dense', 'density', 'size'],\n run: () => useUIStore.getState().toggleCompactMode(),\n },\n {\n id: 'sound-toggle', category: 'Command',\n label: useConfigStore.getState().soundOnComplete ? 'Sound on completion: ON — turn off' : 'Sound on completion: OFF — turn on',\n icon: useConfigStore.getState().soundOnComplete ? Volume2 : VolumeX,\n hint: 'Chime when a run finishes', keywords: ['sound', 'audio', 'chime', 'notify', 'beep'],\n run: () => {\n const next = !useConfigStore.getState().soundOnComplete;\n useConfigStore.getState().setSoundOnComplete(next);\n if (next) playCompletionChime();\n },\n },\n ];\n\n for (const entry of historyEntries.slice(0, 10)) {\n if (entry.isCurrent) continue;\n base.push({\n id: `resume-${entry.id}`, category: 'Session',\n label: `Resume: ${entry.title || '(empty)'}`,\n hint: `${entry.provider}/${entry.model}`,\n icon: ArchiveRestore,\n keywords: ['resume', entry.title, entry.id, entry.provider, entry.model],\n run: () => ws.resumeSession(entry.id),\n });\n }\n return base;\n }, [historyEntries, ws, setCurrentView, setTheme, addMessage, clearMessages]);\n\n const filtered = useMemo(() => {\n const q = query.toLowerCase().trim();\n if (!q) return items;\n return items.filter((it) => {\n const hay = [it.label, it.hint ?? '', it.category, ...(it.keywords ?? [])].join(' ').toLowerCase();\n return hay.includes(q);\n });\n }, [items, query]);\n\n useEffect(() => { if (index >= filtered.length) setIndex(0); }, [filtered.length, index]);\n\n if (!open) return null;\n\n const dispatchPick = (item: PaletteItem | undefined) => {\n if (!item) return;\n setOpen(false);\n item.run();\n };\n\n return (\n <div\n className=\"fixed inset-0 z-50 bg-background/60 backdrop-blur-sm flex items-start justify-center pt-[14vh] px-4\"\n onClick={() => setOpen(false)}\n onKeyDown={(e) => { if (e.key === 'Escape') setOpen(false); }}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n className=\"w-full max-w-2xl rounded-xl border bg-popover shadow-2xl overflow-hidden flex flex-col\"\n >\n <div className=\"flex items-center gap-2 px-4 py-3 border-b\">\n <Search className=\"h-4 w-4 text-muted-foreground\" />\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search commands, sessions, settings…\"\n className=\"flex-1 bg-transparent outline-none text-sm placeholder:text-muted-foreground\"\n onKeyDown={(e) => {\n if (e.key === 'ArrowDown') { e.preventDefault(); setIndex((i) => (i + 1) % Math.max(1, filtered.length)); }\n else if (e.key === 'ArrowUp') { e.preventDefault(); setIndex((i) => (i - 1 + Math.max(1, filtered.length)) % Math.max(1, filtered.length)); }\n else if (e.key === 'Enter') { e.preventDefault(); dispatchPick(filtered[index]); }\n }}\n />\n <kbd className=\"text-[10px] text-muted-foreground border rounded px-1.5 py-0.5\">Esc</kbd>\n </div>\n\n <div className=\"max-h-[60vh] overflow-y-auto\">\n {filtered.length === 0 ? (\n <div className=\"px-4 py-8 text-center text-sm text-muted-foreground\">No matches for \"{query}\"</div>\n ) : (\n renderGroupedList(filtered, index, dispatchPick, setIndex)\n )}\n </div>\n\n <div className=\"border-t px-4 py-2 text-[10px] uppercase tracking-wider text-muted-foreground flex items-center gap-3\">\n <span>↑↓ navigate</span>\n <span>↵ select</span>\n <span>Esc dismiss</span>\n </div>\n </div>\n </div>\n );\n}\n\nfunction renderGroupedList(\n filtered: PaletteItem[],\n index: number,\n dispatch: (it: PaletteItem) => void,\n setIndex: (i: number) => void,\n) {\n const groups: Record<string, Array<{ item: PaletteItem; globalIdx: number }>> = {};\n filtered.forEach((it, i) => {\n if (!groups[it.category]) groups[it.category] = [];\n groups[it.category]!.push({ item: it, globalIdx: i });\n });\n return (\n <div className=\"p-1\">\n {Object.entries(groups).map(([cat, rows]) => (\n <div key={cat}>\n <div className=\"px-3 pt-2 pb-1 text-[10px] uppercase tracking-wider text-muted-foreground\">{cat}</div>\n {rows.map(({ item, globalIdx }) => {\n const Icon = item.icon;\n const active = globalIdx === index;\n return (\n <button\n type=\"button\"\n key={item.id}\n onMouseEnter={() => setIndex(globalIdx)}\n onClick={() => dispatch(item)}\n className={cn(\n 'w-full flex items-center gap-3 px-3 py-2 rounded text-left text-sm transition-colors',\n active ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40',\n )}\n >\n <Icon className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <div className=\"flex-1 min-w-0\">\n <div className=\"truncate\">{item.label}</div>\n {item.hint && <div className=\"text-xs text-muted-foreground truncate\">{item.hint}</div>}\n </div>\n {active && <span className=\"text-[10px] text-muted-foreground\">↵</span>}\n </button>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n","import { useChatStore, useSessionStore } from '@/stores';\n\n/**\n * Build a markdown export of the current chat and trigger a browser download.\n */\nexport function downloadChatAsMarkdown(): void {\n const messages = useChatStore.getState().messages;\n const lines: string[] = [];\n const now = new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-');\n lines.push('# WrongStack chat export');\n lines.push(`*Exported: ${new Date().toISOString()}*`);\n lines.push('');\n for (const m of messages) {\n if (m.role === 'user') {\n lines.push('## 👤 User');\n lines.push('');\n lines.push(m.content);\n lines.push('');\n } else if (m.role === 'assistant') {\n lines.push('## 🤖 Assistant');\n lines.push('');\n lines.push(m.content);\n lines.push('');\n } else if (m.role === 'tool') {\n const status = m.isError ? '❌' : m.toolResult !== undefined ? '✅' : '⏳';\n lines.push(`### 🔧 Tool: \\`${m.toolName ?? 'unknown'}\\` ${status}`);\n if (m.toolInput !== undefined) {\n lines.push('```json');\n lines.push(JSON.stringify(m.toolInput, null, 2));\n lines.push('```');\n }\n if (m.toolResult) {\n lines.push('<details><summary>Output</summary>');\n lines.push('');\n lines.push('```');\n lines.push(m.toolResult);\n lines.push('```');\n lines.push('</details>');\n }\n lines.push('');\n }\n }\n const blob = new Blob([lines.join('\\n')], { type: 'text/markdown' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `wrongstack-chat-${now}.md`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n\n/**\n * Build a stand-alone HTML export of the current chat. Self-contained\n * (inline CSS, no external assets) so the file opens cleanly anywhere.\n */\nexport function downloadChatAsHtml(): void {\n const messages = useChatStore.getState().messages;\n const session = useSessionStore.getState();\n const now = new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-');\n const escapeHtml = (s: string) =>\n s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n\n const turns = messages.map((m) => {\n if (m.role === 'tool') {\n const status = m.isError ? '❌' : m.toolResult !== undefined ? '✅' : '⏳';\n return `\n <section class=\"bubble tool ${m.isError ? 'error' : ''}\">\n <header><span class=\"icon\">🔧</span><code>${escapeHtml(m.toolName ?? 'tool')}</code> ${status}</header>\n ${\n m.toolInput !== undefined\n ? `<details><summary>Input</summary><pre>${escapeHtml(JSON.stringify(m.toolInput, null, 2))}</pre></details>`\n : ''\n }\n ${\n m.toolResult\n ? `<details><summary>Output</summary><pre>${escapeHtml(m.toolResult)}</pre></details>`\n : ''\n }\n </section>`;\n }\n const cls = m.role === 'user' ? 'user' : 'assistant';\n const icon = m.role === 'user' ? '👤' : '🤖';\n const role = m.role === 'user' ? 'User' : 'Assistant';\n return `\n <section class=\"bubble ${cls}\">\n <header><span class=\"icon\">${icon}</span><strong>${role}</strong></header>\n <pre class=\"content\">${escapeHtml(m.content)}</pre>\n </section>`;\n });\n\n const html = `<!doctype html>\n<html lang=\"en\"><head>\n<meta charset=\"utf-8\">\n<title>WrongStack chat — ${escape(session.session?.title || session.projectName || 'export')}</title>\n<style>\n :root { color-scheme: light dark; }\n body { font: 14px/1.55 -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif; max-width: 920px; margin: 24px auto; padding: 0 16px; }\n h1 { font-size: 20px; margin-bottom: 4px; }\n .meta { color: #666; font-size: 12px; margin-bottom: 24px; }\n .bubble { margin: 12px 0; padding: 10px 14px; border-radius: 10px; border: 1px solid #ddd; }\n .bubble header { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: #666; margin-bottom: 6px; }\n .bubble header .icon { margin-right: 4px; }\n .bubble.user { background: #eef4ff; border-color: #c8d8f5; }\n .bubble.assistant { background: #fff; }\n .bubble.tool { background: #fafafa; }\n .bubble.tool.error { background: #fff5f5; border-color: #f5c8c8; }\n pre.content, .bubble pre { white-space: pre-wrap; word-break: break-word; font: 12px/1.5 ui-monospace, Menlo, Consolas, monospace; margin: 0; }\n details summary { cursor: pointer; color: #555; font-size: 12px; }\n details pre { margin-top: 6px; background: #f4f4f4; padding: 8px; border-radius: 6px; max-height: 360px; overflow: auto; }\n @media (prefers-color-scheme: dark) {\n body { background: #0d0d0f; color: #e6e6e6; }\n .bubble { border-color: #2a2a2e; }\n .bubble.user { background: #16213a; border-color: #2a3d6b; }\n .bubble.assistant { background: #161618; }\n .bubble.tool { background: #131315; }\n .bubble.tool.error { background: #2a1717; border-color: #5c2a2a; }\n details pre { background: #1a1a1c; }\n .meta, .bubble header, details summary { color: #999; }\n }\n</style>\n</head><body>\n<h1>WrongStack chat — ${escape(session.session?.title || session.projectName || 'export')}</h1>\n<div class=\"meta\">\n Exported ${new Date().toISOString()}${session.session?.provider ? ` · ${escape(session.session.provider)}/${escape(session.session.model)}` : ''} · ${messages.length} message${messages.length === 1 ? '' : 's'}\n</div>\n${turns.join('')}\n</body></html>`;\n const blob = new Blob([html], { type: 'text/html;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `wrongstack-chat-${now}.html`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore } from '@/stores';\nimport { FileText, Folder } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\ninterface FilePickerProps {\n /** Whatever the user typed after the `@` trigger (case-preserved). */\n query: string;\n /** Called when the user picks a file (Enter / Tab / click). */\n onPick: (relPath: string) => void;\n /** Called when the picker should close without inserting (Esc). */\n onClose: () => void;\n}\n\n/**\n * `@` file mention popup. Subscribes to the WS `files.list` response,\n * supports ↑/↓ Tab Enter Esc. Refetches on query change with a small\n * debounce so we don't spam the backend on every keystroke.\n */\nexport function FilePicker({ query, onPick, onClose }: FilePickerProps) {\n const ws = useWebSocket();\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const [files, setFiles] = useState<string[]>([]);\n const [index, setIndex] = useState(0);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wantHandle = useRef<{ resolve: (paths: string[]) => void } | null>(null);\n\n // Subscribe to the single `files.list` event for the lifetime of this\n // picker. We use the raw client.on() rather than the hook because the\n // hook installs handlers at boot — but `files.list` is picker-local and\n // the data shouldn't leak into other surfaces.\n useEffect(() => {\n const client = getWSClient(wsUrl);\n const off = client.on('files.list', (msg) => {\n const p = msg.payload as { files: string[] };\n setFiles(p.files ?? []);\n setIndex(0);\n wantHandle.current?.resolve(p.files ?? []);\n wantHandle.current = null;\n });\n return () => off();\n }, [wsUrl]);\n\n // Debounced fetch on query change.\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => {\n ws.client.listFiles(query, 50);\n }, 80);\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [query, ws.client]);\n\n // Keyboard nav at window level — ChatInput owns the textarea so we\n // intercept keys there and forward intent here via the imperative API.\n // We listen too so click+keyboard mixing works.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setIndex((i) => (i + 1) % Math.max(1, files.length));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setIndex((i) => (i - 1 + Math.max(1, files.length)) % Math.max(1, files.length));\n } else if (e.key === 'Enter' || e.key === 'Tab') {\n if (files.length === 0) return;\n e.preventDefault();\n onPick(files[index]!);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n }\n };\n window.addEventListener('keydown', onKey, true);\n return () => window.removeEventListener('keydown', onKey, true);\n }, [files, index, onPick, onClose]);\n\n return (\n <div className=\"absolute bottom-full left-0 right-0 mb-2 rounded-lg border bg-popover shadow-md p-1 text-sm max-h-72 overflow-auto\">\n <div className=\"px-3 py-1 text-[10px] uppercase tracking-wider text-muted-foreground border-b mb-1 flex items-center justify-between\">\n <span>@ Files {query && `· \"${query}\"`}</span>\n <span>↑/↓ select · ↵ insert · Esc dismiss</span>\n </div>\n {files.length === 0 ? (\n <div className=\"px-3 py-2 text-xs text-muted-foreground italic\">\n {query ? `No files match \"${query}\"` : 'Searching project…'}\n </div>\n ) : (\n files.map((p, i) => (\n <button\n key={p}\n type=\"button\"\n onClick={() => onPick(p)}\n onMouseEnter={() => setIndex(i)}\n className={cn(\n 'w-full text-left px-3 py-1.5 rounded transition-colors flex items-center gap-2 font-mono text-xs',\n i === index ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40',\n )}\n >\n {p.includes('/') ? (\n <Folder className=\"h-3.5 w-3.5 text-muted-foreground shrink-0\" />\n ) : (\n <FileText className=\"h-3.5 w-3.5 text-muted-foreground shrink-0\" />\n )}\n <span className=\"truncate\">{p}</span>\n </button>\n ))\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps, cva } from 'class-variance-authority';\nimport * as React from 'react';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />\n );\n },\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n","// Slash command registry and matching utilities for ChatInput\n\nexport type SlashCategory = 'Session' | 'Inspect' | 'Run' | 'App';\n\nexport interface SlashCommandDef {\n name: string;\n aliases?: string[];\n description: string;\n category: SlashCategory;\n}\n\nexport const SLASH_COMMANDS: SlashCommandDef[] = [\n { name: '/help', category: 'App', description: 'Show every slash command and what it does' },\n { name: '/export', category: 'Session', description: 'Download the current chat as markdown' },\n { name: '/todos', category: 'Inspect', description: 'List current todos (try `/todos clear` to reset)' },\n { name: '/clear', category: 'Session', description: 'Wipe current context (keeps session id, disk record stays)' },\n { name: '/new', category: 'Session', description: 'Start a brand-new session (fresh on disk and in memory)' },\n { name: '/compact', category: 'Session', description: 'Shrink context — elide ancient tool output' },\n { name: '/repair', category: 'Session', description: 'Repair orphan tool_use/tool_result blocks in context' },\n { name: '/debug', category: 'Inspect', aliases: ['/context'], description: 'Per-section context size breakdown' },\n { name: '/tools', category: 'Inspect', description: 'List every registered tool the model can call' },\n { name: '/memory', category: 'Inspect', description: 'Show all remembered notes (project + user scope)' },\n { name: '/skill', category: 'Inspect', aliases: ['/skills'], description: 'List active skills' },\n { name: '/diag', category: 'Inspect', description: 'Runtime diagnostics (provider, tools, features, mode, usage)' },\n { name: '/stats', category: 'Inspect', description: 'Session stats: tokens, cache hit ratio, cost, elapsed' },\n { name: '/save', category: 'Session', description: 'Force-flush the session (auto-saved already)' },\n { name: '/abort', category: 'Run', aliases: ['/stop'], description: 'Abort the current run' },\n { name: '/settings', category: 'App', aliases: ['/model'], description: 'Open settings (provider/model/keys)' },\n];\n\nexport const SLASH_CATEGORY_ORDER: SlashCategory[] = ['Run', 'Session', 'Inspect', 'App'];\n\nexport function matchSlash(query: string): SlashCommandDef[] {\n const q = query.toLowerCase();\n if (q === '/' || q === '') return SLASH_COMMANDS;\n return SLASH_COMMANDS.filter(\n (c) => c.name.startsWith(q) || (c.aliases?.some((a) => a.startsWith(q)) ?? false),\n );\n}\n\nexport function detectAtMention(value: string, cursor: number): { start: number; query: string } | null {\n let i = cursor - 1;\n while (i >= 0) {\n const c = value[i]!;\n if (c === '@') {\n const prev = i > 0 ? value[i - 1] : '';\n if (i === 0 || /\\s/.test(prev ?? '')) {\n return { start: i, query: value.slice(i + 1, cursor) };\n }\n return null;\n }\n if (/\\s/.test(c)) return null;\n i--;\n }\n return null;\n}\n","import { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport type { WsStatus } from '@/lib/ws-client';\nimport { useConfigStore } from '@/stores';\nimport { Loader2, RotateCcw, Wifi, WifiOff } from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\ninterface Props {\n wsStatus: WsStatus;\n wsConnected: boolean;\n}\n\n/**\n * Tiny status pill for the topbar. Renders four distinct visual states:\n *\n * • open — solid green Wi-Fi\n * • connecting — pulsing yellow spinner\n * • reconnecting — orange, attempt counter + live retry countdown,\n * click to retry immediately\n * • closed — red Wi-Fi-off, click to retry, tooltip shows error\n *\n * The countdown ticks live (every 500ms while `nextRetryAt` is in the\n * future) without forcing the whole topbar to re-render — we only re-run\n * the local timer effect.\n */\nexport function ConnectionChip({ wsStatus, wsConnected }: Props) {\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const [now, setNow] = useState(Date.now());\n\n // Keep a live clock running only while we're between retries, otherwise\n // we'd burn one render every 500ms in a happy-path session.\n useEffect(() => {\n if (wsStatus.state !== 'reconnecting') return;\n const id = setInterval(() => setNow(Date.now()), 500);\n return () => clearInterval(id);\n }, [wsStatus.state]);\n\n const retry = () => getWSClient(wsUrl).retryNow();\n\n if (wsStatus.state === 'open' && wsConnected) {\n return (\n <div\n className=\"flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0 bg-green-500/10 text-green-600 dark:text-green-400\"\n title=\"Backend connected\"\n >\n <Wifi className=\"h-3 w-3\" />\n </div>\n );\n }\n\n if (wsStatus.state === 'connecting') {\n return (\n <div\n className=\"flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0 bg-yellow-500/10 text-yellow-600 dark:text-yellow-400\"\n title=\"Connecting to backend\"\n >\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n <span>connecting</span>\n </div>\n );\n }\n\n if (wsStatus.state === 'reconnecting') {\n const remaining = Math.max(0, Math.ceil((wsStatus.nextRetryAt - now) / 1000));\n return (\n <button\n type=\"button\"\n onClick={retry}\n className={cn(\n 'flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0',\n 'bg-orange-500/10 text-orange-600 dark:text-orange-400 hover:bg-orange-500/20',\n 'transition-colors',\n )}\n title={\n wsStatus.lastError\n ? `Reconnecting — last error: ${wsStatus.lastError}. Click to retry now.`\n : 'Reconnecting — click to retry now.'\n }\n >\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n <span>\n retry #{wsStatus.attempt} in {remaining}s\n </span>\n </button>\n );\n }\n\n // closed\n return (\n <button\n type=\"button\"\n onClick={retry}\n className=\"flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0 bg-red-500/10 text-red-600 dark:text-red-400 hover:bg-red-500/20 transition-colors\"\n title={\n wsStatus.state === 'closed' && wsStatus.error\n ? `Disconnected: ${wsStatus.error}. Click to retry.`\n : 'Disconnected. Click to retry.'\n }\n >\n <WifiOff className=\"h-3 w-3\" />\n <span className=\"flex items-center gap-0.5\">\n offline\n <RotateCcw className=\"h-3 w-3 opacity-70\" />\n </span>\n </button>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { useSessionStore } from '@/stores';\nimport { Check, ChevronDown, Gauge } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\nconst FALLBACK_MODES = [\n {\n id: 'balanced',\n name: 'Balanced',\n description: 'Default rolling compaction',\n thresholds: { warn: 0.6, soft: 0.75, hard: 0.9 },\n preserveK: 10,\n eliseThreshold: 2000,\n },\n];\n\nexport function ContextModePicker() {\n const contextMode = useSessionStore((s) => s.contextMode);\n const contextModes = useSessionStore((s) => s.contextModes);\n const { listContextModes, switchContextMode } = useWebSocket();\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (open) listContextModes();\n }, [open, listContextModes]);\n\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('mousedown', onClick);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onClick);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n const items = contextModes.length > 0 ? contextModes : FALLBACK_MODES;\n const active = items.find((m) => m.id === contextMode) ?? items[0]!;\n\n return (\n <div ref={rootRef} className=\"relative shrink-0\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium',\n 'bg-emerald-500/10 text-emerald-700 dark:text-emerald-300 hover:bg-emerald-500/15 transition-colors border border-transparent hover:border-emerald-500/30',\n )}\n title=\"Context-window mode\"\n >\n <Gauge className=\"h-3 w-3\" />\n ctx: <span className=\"font-mono\">{contextMode || active.id}</span>\n <ChevronDown className=\"h-3 w-3 opacity-60\" />\n </button>\n {open && (\n <div className=\"absolute top-full left-0 mt-1 w-80 rounded-md border bg-popover shadow-lg z-30 py-1\">\n <div className=\"px-3 py-1.5 text-[10px] uppercase tracking-wider text-muted-foreground border-b\">\n Context Window\n </div>\n {items.map((m) => (\n <button\n key={m.id}\n type=\"button\"\n onClick={() => {\n switchContextMode(m.id);\n setOpen(false);\n }}\n className={cn(\n 'w-full text-left px-3 py-2 hover:bg-accent/40 flex items-start gap-2',\n m.id === contextMode && 'bg-accent/30',\n )}\n >\n <Check\n className={cn(\n 'h-3.5 w-3.5 mt-0.5 shrink-0',\n m.id === contextMode ? 'opacity-100 text-primary' : 'opacity-0',\n )}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-xs font-mono\">{m.id}</span>\n {m.thresholds && (\n <span className=\"text-[10px] text-muted-foreground tabular-nums\">\n {Math.round(m.thresholds.warn * 100)}/{Math.round(m.thresholds.soft * 100)}/\n {Math.round(m.thresholds.hard * 100)}%\n </span>\n )}\n </div>\n <div className=\"text-[11px] text-muted-foreground leading-snug\">\n {m.description}\n </div>\n {(m.preserveK || m.eliseThreshold) && (\n <div className=\"mt-1 text-[10px] text-muted-foreground/80\">\n keep {m.preserveK ?? '-'} recent · elide {m.eliseThreshold ?? '-'}+ tokens\n </div>\n )}\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useChatStore, useSessionStore } from '@/stores';\nimport { useEffect, useRef, useState } from 'react';\n\n/**\n * Clickable cost figure in the topbar. Tap to drop a small popover with a\n * per-turn breakdown sourced from `ChatMessage.runSummary` (attached by the\n * run.result handler). Helps the cost-conscious user trace where the\n * dollars actually went without spelunking through transcripts.\n *\n * We only render the popover after the user clicks — the cost chip itself\n * is identical to the plain span it replaces, so the topbar layout stays\n * unchanged.\n */\nexport function CostChip() {\n const cost = useSessionStore((s) => s.cost);\n const inputCost = useSessionStore((s) => s.inputCost);\n const outputCost = useSessionStore((s) => s.outputCost);\n const cacheReadCost = useSessionStore((s) => s.cacheReadCost);\n const messages = useChatStore((s) => s.messages);\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('mousedown', onClick);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onClick);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n /** Top expensive turns. We only consider messages with a runSummary —\n * the run.result handler attaches one per completed turn. costDelta is\n * the delta computed in that handler (session cost at end minus at\n * start of this turn). Falls back to nothing if no data yet. */\n const turns = (() => {\n const rows: Array<{\n id: string;\n preview: string;\n cost: number;\n tools: number;\n ms: number;\n ts: number;\n }> = [];\n for (const m of messages) {\n if (m.role === 'assistant' && m.runSummary && m.runSummary.costDelta > 0) {\n rows.push({\n id: m.id,\n preview: m.content.slice(0, 80).replace(/\\s+/g, ' ').trim() || '(empty)',\n cost: m.runSummary.costDelta,\n tools: m.runSummary.tools,\n ms: m.runSummary.durationMs,\n ts: m.timestamp,\n });\n }\n }\n rows.sort((a, b) => b.cost - a.cost);\n return rows.slice(0, 5);\n })();\n\n const fmt$ = (v: number) =>\n v >= 0.01\n ? `$${v.toFixed(4)}`\n : v > 0\n ? `$${v.toFixed(6).replace(/0+$/, '').replace(/\\.$/, '')}`\n : '$0';\n\n const haveRates = inputCost > 0 || outputCost > 0;\n\n return (\n <div ref={rootRef} className=\"relative inline-block\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'font-medium text-green-600 dark:text-green-400 hover:underline tabular-nums',\n )}\n title=\"Click for per-turn cost breakdown\"\n >\n ${cost.toFixed(4)}\n </button>\n {open && (\n <div className=\"absolute right-0 top-full mt-1 z-30 w-80 rounded-md border bg-popover shadow-lg p-3 text-foreground\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground font-medium\">\n Cost breakdown\n </span>\n <span className=\"font-mono tabular-nums text-sm font-semibold text-green-600 dark:text-green-400\">\n {fmt$(cost)}\n </span>\n </div>\n {haveRates ? (\n <div className=\"text-[11px] text-muted-foreground font-mono mb-3 border-b pb-2\">\n <div className=\"flex justify-between\">\n <span>input /1M</span>\n <span>${inputCost.toFixed(2)}</span>\n </div>\n <div className=\"flex justify-between\">\n <span>output /1M</span>\n <span>${outputCost.toFixed(2)}</span>\n </div>\n {cacheReadCost > 0 && (\n <div className=\"flex justify-between\">\n <span>cache /1M</span>\n <span>${cacheReadCost.toFixed(2)}</span>\n </div>\n )}\n </div>\n ) : (\n <div className=\"text-[11px] text-muted-foreground italic mb-3 border-b pb-2\">\n No pricing for the current model — cost figures are zero.\n </div>\n )}\n {turns.length === 0 ? (\n <div className=\"text-xs text-muted-foreground italic\">\n No completed turns yet. Run a prompt to see per-turn cost here.\n </div>\n ) : (\n <>\n <div className=\"text-[10px] uppercase tracking-wider text-muted-foreground/80 mb-1\">\n Top {turns.length} expensive turn{turns.length === 1 ? '' : 's'}\n </div>\n <ul className=\"space-y-1\">\n {turns.map((t) => (\n <li key={t.id}>\n <button\n type=\"button\"\n onClick={() => {\n const el = document.querySelector(`[data-message-id=\"${t.id}\"]`);\n if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n setOpen(false);\n }}\n className=\"w-full text-left rounded px-2 py-1.5 hover:bg-accent/40 transition-colors\"\n >\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-xs truncate\">{t.preview}</span>\n <span className=\"text-xs font-mono tabular-nums text-green-600 dark:text-green-400 shrink-0\">\n {fmt$(t.cost)}\n </span>\n </div>\n <div className=\"text-[10px] text-muted-foreground font-mono mt-0.5\">\n {t.tools} tool{t.tools === 1 ? '' : 's'} · {(t.ms / 1000).toFixed(1)}s\n </div>\n </button>\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Tool-aware one-line summary for the collapsed bubble. The whole point is\n * that 8 parallel `read` calls should NOT look identical, and a TodoWrite\n * call with 8 todos shouldn't dump 800 chars of JSON when \"8 todos · 3\n * done\" tells the whole story.\n *\n * Cases that earn a custom branch:\n * - TodoWrite → \"8 todos · 3 done · 2 in-progress\"\n * - edit / write → \"edit foo.ts (3 lines → 5 lines)\" / \"write …\"\n * - bash / shell → \"$ <command snippet>\"\n * - fetch / http → \"GET https://…\"\n * - grep / glob → pattern + scope\n * - batch_tool_use → \"N sub-tools\"\n * - read → \"path:N..M\" if offset/limit present\n *\n * Everything else falls back to the head-field-or-JSON heuristic the\n * collapsed view used before.\n */\n\nconst FALLBACK_HEAD_FIELDS = [\n 'path',\n 'file_path',\n 'pattern',\n 'command',\n 'cmd',\n 'url',\n 'query',\n 'description',\n 'content',\n];\n\nexport function summarizeToolInput(toolName: string | undefined, input: unknown): string {\n if (input === null || input === undefined) return '';\n if (typeof input !== 'object') return clip(String(input), 120);\n\n const obj = input as Record<string, unknown>;\n const name = (toolName ?? '').toLowerCase();\n\n // ---- TodoWrite ----------------------------------------------------\n if (/^todo(_?write)?$|^todos$/i.test(name) || Array.isArray(obj.todos)) {\n const todos = (obj.todos ?? []) as Array<{ status?: string; content?: string }>;\n if (Array.isArray(todos)) {\n const done = todos.filter((t) => t.status === 'completed').length;\n const wip = todos.filter((t) => t.status === 'in_progress').length;\n const parts = [`${todos.length} todo${todos.length === 1 ? '' : 's'}`];\n if (done > 0) parts.push(`${done} done`);\n if (wip > 0) parts.push(`${wip} in-progress`);\n return parts.join(' · ');\n }\n }\n\n // ---- batch_tool_use / parallel_tool_use ---------------------------\n if (/batch|parallel/.test(name) || Array.isArray(obj.tool_uses) || Array.isArray(obj.calls)) {\n const list = (obj.tool_uses ?? obj.calls ?? obj.batch) as unknown[];\n if (Array.isArray(list)) {\n const subNames = new Set<string>();\n for (const item of list) {\n if (item && typeof item === 'object' && 'name' in item) {\n subNames.add(String((item as { name: unknown }).name));\n }\n }\n const preview = [...subNames].slice(0, 3).join(', ');\n const more = subNames.size > 3 ? ` +${subNames.size - 3}` : '';\n return `${list.length} sub-tool${list.length === 1 ? '' : 's'}${preview ? ` · ${preview}${more}` : ''}`;\n }\n }\n\n // ---- edit / str_replace / patch -----------------------------------\n if (/^(edit|str_replace|edit_file|patch)$/.test(name)) {\n const fp = pickPath(obj);\n const oldS = typeof obj.old_string === 'string' ? obj.old_string : '';\n const newS = typeof obj.new_string === 'string' ? obj.new_string : '';\n const oldLines = oldS ? oldS.split('\\n').length : 0;\n const newLines = newS ? newS.split('\\n').length : 0;\n return `edit ${fp || '(file)'}${oldLines || newLines ? ` (${oldLines} → ${newLines} lines)` : ''}`;\n }\n\n // ---- write / write_file / create_file -----------------------------\n if (/^(write|write_file|create_file|new_file)$/.test(name)) {\n const fp = pickPath(obj);\n const c = typeof obj.content === 'string' ? obj.content : '';\n const lines = c ? c.split('\\n').length : 0;\n return `write ${fp || '(file)'}${lines ? ` · ${lines} lines` : ''}`;\n }\n\n // ---- bash / shell / exec / run ------------------------------------\n if (/^(bash|shell|exec|run|run_command|run_shell)$/.test(name)) {\n const cmd = (obj.command ?? obj.cmd ?? obj.script) as string | undefined;\n if (typeof cmd === 'string') return `$ ${clip(cmd, 110)}`;\n }\n\n // ---- fetch / http / web -------------------------------------------\n if (/^(fetch|http|web|webfetch|curl|request)$/.test(name)) {\n const url = obj.url as string | undefined;\n if (typeof url === 'string') {\n const method = (obj.method as string | undefined) ?? 'GET';\n return `${method.toUpperCase()} ${clip(url, 100)}`;\n }\n }\n\n // ---- grep / search ------------------------------------------------\n if (/^(grep|search|ripgrep)$/.test(name)) {\n const pattern = obj.pattern as string | undefined;\n const scope = (obj.path ?? obj.glob ?? obj.type) as string | undefined;\n if (typeof pattern === 'string') {\n return scope ? `grep ${clip(pattern, 60)} in ${scope}` : `grep ${clip(pattern, 100)}`;\n }\n }\n\n // ---- glob / find --------------------------------------------------\n if (/^(glob|find)$/.test(name)) {\n const p = (obj.pattern ?? obj.glob) as string | undefined;\n if (typeof p === 'string') return `glob ${clip(p, 100)}`;\n }\n\n // ---- read with offset/limit --------------------------------------\n if (/^(read|read_file|cat)$/.test(name)) {\n const fp = pickPath(obj);\n const offset = obj.offset as number | undefined;\n const limit = obj.limit as number | undefined;\n if (fp && (typeof offset === 'number' || typeof limit === 'number')) {\n const start = offset ?? 0;\n const end = typeof limit === 'number' ? start + limit : '';\n return `read ${fp} (${start}…${end})`;\n }\n if (fp) return `read ${fp}`;\n }\n\n // ---- Fallback: pick the first non-empty \"headline\" string field --\n for (const k of FALLBACK_HEAD_FIELDS) {\n const v = obj[k];\n if (typeof v === 'string' && v.length > 0) {\n return `${k}: ${clip(v, 100)}`;\n }\n }\n // Last resort: compact JSON.\n const json = safeJson(input);\n return clip(json, 120);\n}\n\nfunction clip(s: string, n: number): string {\n return s.length > n ? `${s.slice(0, n - 1)}…` : s;\n}\n\nfunction pickPath(obj: Record<string, unknown>): string {\n const p = obj.file_path ?? obj.path ?? obj.filepath;\n return typeof p === 'string' ? p : '';\n}\n\nfunction safeJson(v: unknown): string {\n try {\n return JSON.stringify(v);\n } catch {\n return String(v);\n }\n}\n","import { summarizeToolInput } from '@/lib/tool-summary';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport type { ChatMessage } from '@/stores';\nimport { useChatStore, useSessionStore, useUIStore } from '@/stores';\nimport { useConfigStore } from '@/stores';\nimport {\n Bot,\n CheckCircle2,\n ChevronDown,\n ChevronRight,\n Clock,\n Download,\n FileCode2,\n Pencil,\n Pin,\n PinOff,\n RotateCcw,\n Terminal,\n User,\n XCircle,\n} from 'lucide-react';\nimport { memo, useState } from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { DiffView, diffFromToolInput } from '../DiffView';\nimport { ToolResult } from '../ToolResult';\nimport { CopyButton } from './CopyButton.js';\nimport { ErrorBodyWithStack } from './ErrorBody.js';\nimport { ToolInputView } from './ToolInputView.js';\nimport { downloadTextFile, fileExtensionFor, formatToolDuration, markdownComponents } from './utils.js';\n\ninterface MessageBubbleProps {\n message: ChatMessage;\n isFirst?: boolean;\n isContinuation?: boolean;\n}\n\nexport const MessageBubble = memo(function MessageBubble({\n message,\n isFirst = false,\n isContinuation = false,\n}: MessageBubbleProps) {\n const [expandedTools, setExpandedTools] = useState<Record<string, boolean>>({});\n const [editing, setEditing] = useState(false);\n const [editValue, setEditValue] = useState('');\n const [showRaw, setShowRaw] = useState(false);\n const isUser = message.role === 'user';\n const isTool = message.role === 'tool';\n void message.role;\n\n const truncateAfter = useChatStore((s) => s.truncateAfter);\n const addMessage = useChatStore((s) => s.addMessage);\n const setLoading = useChatStore((s) => s.setLoading);\n const isLoading = useChatStore((s) => s.isLoading);\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const pinnedIds = useUIStore((s) => s.pinnedIds);\n const togglePin = useUIStore((s) => s.togglePin);\n const compactMode = useUIStore((s) => s.compactMode);\n const isPinned = pinnedIds.includes(message.id);\n const inputCost = useSessionStore((s) => s.inputCost);\n const outputCost = useSessionStore((s) => s.outputCost);\n const cacheReadCost = useSessionStore((s) => s.cacheReadCost);\n\n const isLatestAssistant = (() => {\n if (message.role !== 'assistant' || isLoading) return false;\n const all = useChatStore.getState().messages;\n for (let i = all.length - 1; i >= 0; i--) {\n const m = all[i]!;\n if (m.role === 'assistant') return m.id === message.id;\n }\n return false;\n })();\n\n const regenerate = () => {\n const all = useChatStore.getState().messages;\n const idx = all.findIndex((m) => m.id === message.id);\n if (idx === -1) return;\n let userIdx = -1;\n for (let i = idx - 1; i >= 0; i--) {\n if (all[i]!.role === 'user') {\n userIdx = i;\n break;\n }\n }\n if (userIdx === -1) return;\n const userMsg = all[userIdx]!;\n truncateAfter(userMsg.id);\n addMessage({ role: 'user', content: userMsg.content });\n setLoading(true);\n const client = getWSClient(wsUrl);\n client.sendMessage(userMsg.content);\n };\n\n const toggleTool = (id: string) => {\n setExpandedTools((prev) => ({ ...prev, [id]: !prev[id] }));\n };\n\n const startEdit = () => {\n setEditValue(message.content);\n setEditing(true);\n };\n const cancelEdit = () => {\n setEditing(false);\n setEditValue('');\n };\n const saveEdit = () => {\n const next = editValue.trim();\n if (!next) { cancelEdit(); return; }\n truncateAfter(message.id);\n addMessage({ role: 'user', content: next });\n setLoading(true);\n const client = getWSClient(wsUrl);\n client.sendMessage(next);\n setEditing(false);\n setEditValue('');\n };\n\n return (\n <div\n data-message-id={message.id}\n data-pinned={isPinned ? '1' : undefined}\n className={cn(\n 'group flex animate-message rounded-lg transition-shadow',\n compactMode ? 'gap-2' : 'gap-3',\n isUser ? 'flex-row-reverse' : 'flex-row',\n isPinned && 'ring-1 ring-amber-500/30 bg-amber-500/[0.02] px-1 -mx-1',\n )}\n >\n {isContinuation ? (\n <div className=\"flex-shrink-0 w-8 h-8\" aria-hidden />\n ) : (\n <div className={cn(\n 'flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center',\n 'ring-2 ring-offset-2 ring-offset-background',\n isUser ? 'bg-primary text-primary-foreground ring-primary/20' : isTool ? 'bg-secondary text-secondary-foreground ring-secondary/20' : 'bg-accent text-accent-foreground ring-accent/20',\n )}>\n {isUser ? <User className=\"h-4 w-4\" /> : isTool ? <Terminal className=\"h-4 w-4\" /> : <Bot className=\"h-4 w-4\" />}\n </div>\n )}\n\n <div className={cn('flex flex-col gap-1.5 max-w-[85%]', isUser && 'items-end')}>\n {isFirst && !isContinuation && (\n <span className={cn('text-xs font-medium px-1', isUser ? 'text-primary' : isTool ? 'text-secondary' : 'text-muted-foreground')}>\n {isUser ? 'You' : isTool ? 'Tool' : 'Assistant'}\n </span>\n )}\n\n {isTool && message.toolName && (\n <button type=\"button\" onClick={() => toggleTool(message.id)}\n className={cn('flex items-center gap-2 text-sm font-medium cursor-pointer select-none', 'hover:bg-muted/50 rounded-lg px-2 py-1 -mx-2 transition-colors', message.isError ? 'text-destructive' : 'text-foreground')}>\n <span className=\"text-muted-foreground/50\">{expandedTools[message.id] ? <ChevronDown className=\"h-3 w-3\" /> : <ChevronRight className=\"h-3 w-3\" />}</span>\n <Terminal className=\"h-3 w-3\" />\n <span className=\"font-mono\">{message.toolName}</span>\n {message.toolResult === undefined ? <span className=\"h-1.5 w-1.5 rounded-full bg-amber-500 animate-pulse\" aria-hidden /> : message.isError ? <XCircle className=\"h-3 w-3 text-destructive\" /> : <CheckCircle2 className=\"h-3 w-3 text-green-500\" />}\n {typeof message.toolDurationMs === 'number' && <span className=\"text-xs text-muted-foreground tabular-nums font-normal\">{formatToolDuration(message.toolDurationMs)}</span>}\n </button>\n )}\n\n <div className={cn('rounded-2xl', compactMode ? 'px-3 py-1.5' : 'px-4 py-3',\n isUser ? 'bg-primary text-primary-foreground rounded-br-md' : isTool ? message.isError ? 'bg-destructive/5 border border-destructive/20 text-destructive' : 'bg-muted/80 text-foreground' : 'bg-card border text-foreground',\n message.isError && !isTool && 'border-destructive/20')}>\n {isTool ? (() => {\n const expanded = !!expandedTools[message.id];\n const inputSummary = message.toolInput !== undefined ? summarizeToolInput(message.toolName, message.toolInput) : '';\n const lines = message.toolResult ? message.toolResult.split('\\n').length : 0;\n return (\n <div className=\"space-y-1\">\n {inputSummary && !expanded && <div className=\"text-xs text-muted-foreground font-mono truncate\">{inputSummary}</div>}\n {message.toolResult === undefined && message.progressLines && message.progressLines.length > 0 && (\n <div className=\"mt-1 rounded-md border border-amber-500/20 bg-amber-500/5 p-1.5 text-[11px] font-mono leading-snug max-h-32 overflow-auto\">\n {message.progressLines.slice(-6).map((line, i) => (<div key={i} className=\"truncate text-muted-foreground\">{line}</div>))}\n </div>\n )}\n {expanded && message.toolInput !== undefined && (() => {\n const diffArgs = diffFromToolInput(message.toolName, message.toolInput);\n if (diffArgs) return (<DiffView oldText={diffArgs.oldText} newText={diffArgs.newText} caption={diffArgs.caption} />);\n return (<div className=\"p-3 bg-muted/50 rounded-lg overflow-x-auto\"><div className=\"flex items-center gap-1 text-muted-foreground mb-2 text-xs\"><Clock className=\"h-3 w-3\" /><span>Input</span></div><ToolInputView input={message.toolInput} /></div>);\n })()}\n {expanded && message.toolResult !== undefined && message.toolResult.length > 0 && (\n <div className=\"relative group/tool\">\n <ToolResult toolName={message.toolName} result={message.toolResult} isError={message.isError} />\n <div className=\"absolute top-1.5 right-1.5 flex items-center gap-1 opacity-0 group-hover/tool:opacity-100 transition-opacity\">\n <CopyButton text={message.toolResult} label=\"\" className=\"bg-background/80 border rounded px-1.5 py-0.5\" />\n {message.toolResult.split('\\n').length > 5 && (\n <button type=\"button\" onClick={(ev) => { ev.stopPropagation(); const ext = fileExtensionFor(message.toolName); const base = (message.toolName ?? 'output').replace(/[^a-z0-9_-]+/gi, '-').toLowerCase(); downloadTextFile(`${base}-${new Date().toISOString().replace(/[:.]/g, '-')}.${ext}`, message.toolResult ?? ''); }}\n className=\"inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground bg-background/80 border rounded px-1.5 py-0.5\" title=\"Download as file\"><Download className=\"h-3 w-3\" /></button>\n )}\n </div>\n </div>\n )}\n {expanded && message.toolResult !== undefined && message.toolResult.length === 0 && <span className=\"text-xs text-muted-foreground italic\">(empty)</span>}\n {!expanded && message.isError && message.toolResult && <div className=\"text-xs font-mono text-destructive truncate\">{message.toolResult.split('\\n')[0]}</div>}\n {((message.toolResult !== undefined && message.toolResult.length > 0) || (message.toolInput !== undefined && Object.keys((message.toolInput as object) ?? {}).length > 0)) && (\n <button type=\"button\" onClick={() => toggleTool(message.id)} className=\"text-xs text-muted-foreground hover:text-foreground transition-colors\">\n {expanded ? 'Hide details' : `Show details${lines > 0 ? ` (${lines} line${lines === 1 ? '' : 's'})` : ''}`}\n </button>\n )}\n </div>\n );\n })() : editing && isUser ? (\n <div className=\"flex flex-col gap-2 min-w-[280px]\">\n <textarea value={editValue} onChange={(e) => setEditValue(e.target.value)}\n onKeyDown={(e) => { if (e.key === 'Escape') { e.preventDefault(); cancelEdit(); } else if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); saveEdit(); } }}\n rows={Math.min(8, Math.max(2, editValue.split('\\n').length))}\n className=\"w-full resize-none rounded-md border bg-background text-foreground px-2 py-1.5 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-ring\" />\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-[10px] text-primary-foreground/60\">⌘/Ctrl+Enter to save · Esc to cancel</span>\n <div className=\"flex gap-1\">\n <button type=\"button\" onClick={cancelEdit} className=\"text-xs px-2 py-0.5 rounded border border-primary-foreground/30 hover:bg-primary-foreground/10\">Cancel</button>\n <button type=\"button\" onClick={saveEdit} disabled={!editValue.trim()} className=\"text-xs px-2 py-0.5 rounded bg-primary-foreground text-primary disabled:opacity-50\">Save & resend</button>\n </div>\n </div>\n </div>\n ) : (\n <div className=\"text-sm leading-relaxed markdown-content\">\n {message.content ? (showRaw && message.role === 'assistant' ? (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-foreground/90 max-h-[40rem] overflow-auto\">{message.content}</pre>\n ) : message.role === 'assistant' && message.isError ? (\n <ErrorBodyWithStack text={message.content} />\n ) : (\n <ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>{message.content}</ReactMarkdown>\n )) : message.streaming ? (\n <span className=\"inline-block animate-pulse text-muted-foreground\">Typing...</span>\n ) : (\n <span className=\"text-muted-foreground italic\">No content</span>\n )}\n </div>\n )}\n </div>\n\n <div className={cn('flex items-center gap-2 px-1', isUser ? 'flex-row-reverse' : 'flex-row')}>\n <span className=\"text-xs text-muted-foreground/50\">{new Date(message.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</span>\n {message.runSummary && (\n <span className=\"text-[10px] text-muted-foreground/60 font-mono tabular-nums\"\n title={[`Iterations: ${message.runSummary.iterations}`, `Tool calls: ${message.runSummary.tools}`, `Elapsed: ${(message.runSummary.durationMs / 1000).toFixed(2)}s`, message.runSummary.costDelta > 0 ? `Cost: $${message.runSummary.costDelta.toFixed(4)}` : ''].filter(Boolean).join(' · ')}>\n {message.runSummary.iterations} iter{message.runSummary.tools > 0 ? ` · ${message.runSummary.tools} tool${message.runSummary.tools === 1 ? '' : 's'}` : ''} · {message.runSummary.durationMs < 60_000 ? `${(message.runSummary.durationMs / 1000).toFixed(1)}s` : `${Math.floor(message.runSummary.durationMs / 60_000)}m ${Math.floor((message.runSummary.durationMs % 60_000) / 1000)}s`}{message.runSummary.costDelta > 0 ? ` · $${message.runSummary.costDelta >= 0.01 ? message.runSummary.costDelta.toFixed(4) : message.runSummary.costDelta.toFixed(6).replace(/0+$/, '').replace(/\\.$/, '')}` : ''}\n </span>\n )}\n {message.usage && (message.usage.input > 0 || message.usage.output > 0) && (() => {\n const u = message.usage;\n const dollars = (u.input * inputCost + u.output * outputCost + (u.cacheRead ?? 0) * cacheReadCost) / 1_000_000;\n const haveCost = inputCost > 0 || outputCost > 0;\n const dollarStr = dollars >= 0.01 ? `$${dollars.toFixed(4)}` : dollars > 0 ? `$${dollars.toFixed(6).replace(/0+$/, '').replace(/\\.$/, '')}` : '';\n return (<span className=\"text-[10px] text-muted-foreground/60 font-mono tabular-nums\" title={[`Input: ${u.input.toLocaleString()}`, `Output: ${u.output.toLocaleString()}`, u.cacheRead ? `Cache read: ${u.cacheRead.toLocaleString()}` : '', haveCost ? `Cost: ${dollarStr}` : ''].filter(Boolean).join(' · ')}>\n {u.input.toLocaleString()}→{u.output.toLocaleString()}{u.cacheRead ? ` · ${u.cacheRead.toLocaleString()} ↺` : ''}{haveCost && dollarStr ? ` · ${dollarStr}` : ''}\n </span>);\n })()}\n {!isTool && message.content && !message.streaming && <CopyButton text={message.content} label=\"\" className=\"opacity-0 group-hover:opacity-100 transition-opacity\" />}\n {message.role === 'assistant' && message.content && !message.streaming && (\n <button type=\"button\" onClick={() => setShowRaw((v) => !v)} title={showRaw ? 'Show rendered markdown' : 'Show raw markdown source'}\n className={cn('text-xs inline-flex items-center gap-1 transition-opacity', showRaw ? 'text-primary hover:text-primary/80 opacity-100' : 'opacity-0 group-hover:opacity-100 text-muted-foreground hover:text-foreground')}>\n <FileCode2 className=\"h-3 w-3\" /><span>{showRaw ? 'Rendered' : 'Raw'}</span>\n </button>\n )}\n {isUser && !editing && !isLoading && message.content && (\n <button type=\"button\" onClick={startEdit} title=\"Edit & resend this prompt\" className=\"opacity-0 group-hover:opacity-100 transition-opacity text-xs text-muted-foreground hover:text-foreground inline-flex items-center gap-1\">\n <Pencil className=\"h-3 w-3\" /><span>Edit</span>\n </button>\n )}\n {message.role === 'assistant' && message.content && !message.streaming && (\n <button type=\"button\" onClick={() => togglePin(message.id)} title={isPinned ? 'Unpin' : 'Pin this answer'}\n className={cn('text-xs inline-flex items-center gap-1 transition-opacity', isPinned ? 'text-amber-500 hover:text-amber-600 opacity-100' : 'opacity-0 group-hover:opacity-100 text-muted-foreground hover:text-foreground')}>\n {isPinned ? <PinOff className=\"h-3 w-3\" /> : <Pin className=\"h-3 w-3\" />}<span>{isPinned ? 'Pinned' : 'Pin'}</span>\n </button>\n )}\n {isLatestAssistant && message.content && !message.streaming && (\n <button type=\"button\" onClick={regenerate} title=\"Regenerate this response\" className=\"opacity-0 group-hover:opacity-100 transition-opacity text-xs text-muted-foreground hover:text-foreground inline-flex items-center gap-1\">\n <RotateCcw className=\"h-3 w-3\" /><span>Retry</span>\n </button>\n )}\n </div>\n </div>\n </div>\n );\n});\n","import { cn } from '@/lib/utils';\nimport { memo, useMemo } from 'react';\n\ninterface DiffViewProps {\n oldText: string;\n newText: string;\n /** Optional caption shown above the diff (file path, \"write\" vs \"edit\", etc.) */\n caption?: string;\n}\n\n/**\n * Tiny line-based diff renderer. Computes the longest-common-subsequence\n * between `oldText` and `newText` line arrays, then walks both sides\n * emitting `add`/`remove`/`context` rows. Context lines are de-emphasised\n * so the eye lands on the changes. Not as pretty as a Myers diff but it's\n * one short function with no deps and good enough for a chat preview.\n *\n * Limits: text > 5000 lines is shown without a diff (just a \"too large\"\n * note); that's a UI guard, not a hard limit on the underlying tool.\n */\nexport const DiffView = memo(function DiffView({ oldText, newText, caption }: DiffViewProps) {\n const rows = useMemo(() => computeDiff(oldText, newText), [oldText, newText]);\n\n if (rows === null) {\n return (\n <div className=\"text-xs text-muted-foreground italic px-3 py-2\">\n Diff omitted (file too large to render inline).\n </div>\n );\n }\n\n const adds = rows.filter((r) => r.kind === 'add').length;\n const dels = rows.filter((r) => r.kind === 'del').length;\n\n return (\n <div className=\"rounded-lg border bg-background/40 overflow-hidden text-xs\">\n <div className=\"flex items-center justify-between px-3 py-1.5 border-b bg-muted/40\">\n <span className=\"font-mono text-muted-foreground truncate\">{caption ?? 'diff'}</span>\n <span className=\"font-mono shrink-0\">\n <span className=\"text-emerald-600 dark:text-emerald-400\">+{adds}</span>\n <span className=\"text-muted-foreground mx-1\">·</span>\n <span className=\"text-rose-600 dark:text-rose-400\">-{dels}</span>\n </span>\n </div>\n <div className=\"font-mono leading-relaxed max-h-96 overflow-auto\">\n {rows.map((r, i) => (\n <div\n // biome-ignore lint/suspicious/noArrayIndexKey: static diff rows\n key={i}\n className={cn(\n 'flex',\n r.kind === 'add' && 'bg-emerald-500/10',\n r.kind === 'del' && 'bg-rose-500/10',\n )}\n >\n <span\n className={cn(\n 'w-6 shrink-0 text-center select-none',\n r.kind === 'add' && 'text-emerald-600 dark:text-emerald-400',\n r.kind === 'del' && 'text-rose-600 dark:text-rose-400',\n r.kind === 'ctx' && 'text-muted-foreground/40',\n )}\n >\n {r.kind === 'add' ? '+' : r.kind === 'del' ? '-' : ' '}\n </span>\n <pre\n className={cn(\n 'whitespace-pre-wrap break-all flex-1 px-2',\n r.kind === 'ctx' && 'text-muted-foreground/70',\n )}\n >\n {r.text || ' '}\n </pre>\n </div>\n ))}\n </div>\n </div>\n );\n});\n\ninterface DiffRow {\n kind: 'add' | 'del' | 'ctx';\n text: string;\n}\n\nconst MAX_LINES = 5000;\n\n/**\n * Returns null when either side exceeds the line cap. Otherwise walks the\n * LCS table to produce a clean diff. LCS table is O(n*m) memory — fine for\n * a file edit (usually <500 lines), prohibitive for a full file rewrite of\n * a giant generated file (hence the cap).\n */\nfunction computeDiff(oldText: string, newText: string): DiffRow[] | null {\n const a = oldText.split('\\n');\n const b = newText.split('\\n');\n if (a.length > MAX_LINES || b.length > MAX_LINES) return null;\n const n = a.length;\n const m = b.length;\n // dp[i][j] = LCS length of a[i..] and b[j..]\n const dp: number[][] = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));\n for (let i = n - 1; i >= 0; i--) {\n for (let j = m - 1; j >= 0; j--) {\n if (a[i] === b[j]) dp[i]![j] = dp[i + 1]![j + 1]! + 1;\n else dp[i]![j] = Math.max(dp[i + 1]![j]!, dp[i]![j + 1]!);\n }\n }\n const rows: DiffRow[] = [];\n let i = 0;\n let j = 0;\n while (i < n && j < m) {\n if (a[i] === b[j]) {\n rows.push({ kind: 'ctx', text: a[i]! });\n i++;\n j++;\n } else if (dp[i + 1]![j]! >= dp[i]![j + 1]!) {\n rows.push({ kind: 'del', text: a[i]! });\n i++;\n } else {\n rows.push({ kind: 'add', text: b[j]! });\n j++;\n }\n }\n while (i < n) rows.push({ kind: 'del', text: a[i++]! });\n while (j < m) rows.push({ kind: 'add', text: b[j++]! });\n return rows;\n}\n\n/**\n * Recognise the WrongStack edit-family tools and pull a (oldText, newText,\n * caption) tuple out of their input. Returns null when the tool doesn't\n * carry diffable input. Caller uses this to decide whether to render the\n * DiffView at all.\n */\nexport function diffFromToolInput(\n toolName: string | undefined,\n input: unknown,\n): { oldText: string; newText: string; caption: string } | null {\n if (!toolName || typeof input !== 'object' || input === null) return null;\n const obj = input as Record<string, unknown>;\n const filePath = String(obj.file_path ?? obj.path ?? '');\n switch (toolName) {\n case 'edit':\n case 'str_replace':\n case 'edit_file': {\n const oldText = typeof obj.old_string === 'string' ? obj.old_string : '';\n const newText = typeof obj.new_string === 'string' ? obj.new_string : '';\n if (!oldText && !newText) return null;\n return { oldText, newText, caption: `edit ${filePath}` };\n }\n case 'write':\n case 'write_file':\n case 'create_file': {\n const content = typeof obj.content === 'string' ? obj.content : '';\n // For a fresh write there's no \"old\" — treat as additive so the\n // viewer shows everything green.\n return { oldText: '', newText: content, caption: `write ${filePath} (new)` };\n }\n default:\n return null;\n }\n}\n","import { cn } from '@/lib/utils';\nimport { ChevronDown, ChevronRight, ChevronsDown, ChevronsUp } from 'lucide-react';\nimport { memo, useMemo, useState } from 'react';\n\n/** When a tool dumps hundreds of lines of output, the chat turns into a\n * scroll-wall. This threshold gates the auto-collapse: anything longer\n * shows the first ~LONG_PEEK_LINES with a \"Show all N more\" toggle. */\nconst LONG_OUTPUT_THRESHOLD = 25;\nconst LONG_PEEK_LINES = 12;\n\n/**\n * Render `text` as a monospace block, auto-collapsing when it exceeds\n * LONG_OUTPUT_THRESHOLD lines. The first LONG_PEEK_LINES stay visible;\n * the rest expand on click. Keeping the wrap class configurable lets the\n * `numbered` path use `whitespace-pre` (no wrap) and the bash/plain path\n * use `whitespace-pre-wrap break-all` (wrap and break long URLs/paths).\n */\nfunction CollapsibleText({\n text,\n isError,\n className,\n wrapClass,\n showLineNumbers,\n}: {\n text: string;\n isError?: boolean;\n className?: string;\n wrapClass: string;\n /** Whether to render a left gutter with line numbers when the output is\n * long. Off for the numbered/Read-tool path (which already prefixes its\n * own line numbers in the content) and for wrap-mode bodies where a\n * fixed gutter can't stay aligned with wrapped lines. */\n showLineNumbers?: boolean;\n}) {\n const lines = useMemo(() => text.split('\\n'), [text]);\n const isLong = lines.length > LONG_OUTPUT_THRESHOLD;\n const [expanded, setExpanded] = useState(!isLong);\n const shown = expanded ? text : lines.slice(0, LONG_PEEK_LINES).join('\\n');\n // Only emit the gutter when the body won't wrap (alignment would break\n // otherwise) AND the user actually expanded it / it's not super short.\n const renderGutter = !!showLineNumbers && isLong && expanded;\n return (\n <div className={cn('rounded-md border bg-background/40 overflow-hidden', className)}>\n {renderGutter ? (\n // Force `whitespace-pre` inside the gutter view so the line numbers\n // stay 1:1 with content rows. Long horizontal lines scroll within\n // the shared overflow container rather than wrapping (which would\n // break alignment between the gutter and the body).\n <div className=\"flex max-h-96 overflow-auto\">\n <pre\n aria-hidden\n className=\"text-xs font-mono leading-[1.4] py-2 pl-2 pr-2 text-muted-foreground/50 select-none border-r border-border/40 bg-muted/20 tabular-nums text-right whitespace-pre shrink-0\"\n >\n {lines.map((_, i) => `${i + 1}`).join('\\n')}\n </pre>\n <pre\n className={cn(\n 'text-xs font-mono leading-[1.4] py-2 px-2 flex-1 whitespace-pre',\n isError ? 'text-destructive' : 'text-foreground',\n )}\n >\n {shown}\n </pre>\n </div>\n ) : (\n <pre\n className={cn(\n 'text-xs font-mono p-2 max-h-96 overflow-auto',\n wrapClass,\n isError ? 'text-destructive' : 'text-foreground',\n )}\n >\n {shown}\n </pre>\n )}\n {isLong && (\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"w-full flex items-center justify-center gap-1 px-2 py-1 border-t bg-muted/30 text-[11px] text-muted-foreground hover:text-foreground transition-colors\"\n >\n {expanded ? (\n <>\n <ChevronsUp className=\"h-3 w-3\" />\n Collapse to first {LONG_PEEK_LINES} lines\n </>\n ) : (\n <>\n <ChevronsDown className=\"h-3 w-3\" />\n Show all {lines.length} lines ({lines.length - LONG_PEEK_LINES} more)\n </>\n )}\n </button>\n )}\n </div>\n );\n}\n\ninterface Props {\n toolName?: string;\n result: string;\n isError?: boolean;\n className?: string;\n}\n\n/**\n * Decides which renderer to use for a tool result based on its shape /\n * tool name. The goal is to make output *legible at a glance*:\n * - Read tool with leading line numbers stays line-numbered, monospace.\n * - Bash output gets a \"exit code N\" footer split from stdout.\n * - Valid JSON gets pretty-printed and collapsible by default.\n * - Everything else falls back to raw monospace.\n */\nexport const ToolResult = memo(function ToolResult({\n toolName,\n result,\n isError,\n className,\n}: Props) {\n const shape = useMemo(() => detectShape(toolName, result), [toolName, result]);\n\n if (shape.kind === 'json') {\n return <JsonResult value={shape.value} isError={isError} className={className} />;\n }\n if (shape.kind === 'numbered') {\n return (\n <CollapsibleText\n text={result}\n isError={isError}\n className={className}\n wrapClass=\"whitespace-pre\"\n />\n );\n }\n if (shape.kind === 'bash') {\n return (\n <div className={cn('rounded-md border bg-background/40 overflow-hidden', className)}>\n {shape.stdout && (\n <CollapsibleText\n text={shape.stdout}\n isError={isError}\n // Nested CollapsibleText already adds border/bg; strip them here\n // so we get one outer frame, not two.\n className=\"border-0 rounded-none bg-transparent\"\n wrapClass=\"whitespace-pre-wrap break-all\"\n showLineNumbers\n />\n )}\n {(shape.exitCode !== undefined || shape.duration) && (\n <div\n className={cn(\n 'flex items-center gap-3 text-[11px] px-2 py-1 border-t bg-muted/30 tabular-nums',\n shape.exitCode && shape.exitCode !== 0 ? 'text-destructive' : 'text-muted-foreground',\n )}\n >\n {shape.exitCode !== undefined && (\n <span>\n exit code: <span className=\"font-mono\">{shape.exitCode}</span>\n </span>\n )}\n {shape.duration && <span>{shape.duration}</span>}\n </div>\n )}\n </div>\n );\n }\n return (\n <CollapsibleText\n text={result}\n isError={isError}\n className={className}\n wrapClass=\"whitespace-pre-wrap break-all\"\n showLineNumbers\n />\n );\n});\n\ninterface Shape {\n kind: 'numbered' | 'json' | 'bash' | 'plain';\n /** For JSON results. */\n value?: unknown;\n /** For bash-shape results. */\n stdout?: string;\n exitCode?: number;\n duration?: string;\n}\n\nfunction detectShape(toolName: string | undefined, result: string): Shape {\n const trimmed = result.trim();\n // ---- Read tool: lines like \" 42→ const foo = …\" -------------\n if (/^\\s*\\d+→/m.test(result.slice(0, 200))) {\n return { kind: 'numbered' };\n }\n // ---- JSON ---------------------------------------------------------\n if (\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n try {\n const parsed = JSON.parse(trimmed);\n if (typeof parsed === 'object' && parsed !== null) {\n return { kind: 'json', value: parsed };\n }\n } catch {\n /* fall through */\n }\n }\n // ---- Bash-ish -----------------------------------------------------\n const isBashTool = !!toolName && /^(bash|shell|exec|run)/i.test(toolName);\n // Many bash wrappers emit a trailing \"exit code: N\" or \"[exit 1]\" line.\n const exitMatch = result.match(/(?:^|\\n)\\s*(?:\\[?exit(?:\\s*code)?\\]?\\s*[:=]?\\s*)(\\d+)\\s*$/i);\n const durMatch = result.match(/(?:^|\\s)(\\d+\\s*ms|\\d+\\.\\d+s)\\s*$/i);\n if (isBashTool || exitMatch) {\n let stdout = result;\n if (exitMatch) stdout = result.slice(0, exitMatch.index).trimEnd();\n return {\n kind: 'bash',\n stdout,\n exitCode: exitMatch ? Number(exitMatch[1]) : undefined,\n duration: durMatch?.[1],\n };\n }\n return { kind: 'plain' };\n}\n\nfunction JsonResult({\n value,\n isError,\n className,\n}: {\n value: unknown;\n isError?: boolean;\n className?: string;\n}) {\n const pretty = useMemo(() => {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n }, [value]);\n const lineCount = pretty.split('\\n').length;\n const [expanded, setExpanded] = useState(lineCount < 30);\n return (\n <div\n className={cn(\n 'rounded-md border bg-background/40 overflow-hidden',\n isError && 'border-destructive/40',\n className,\n )}\n >\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"w-full flex items-center justify-between px-2 py-1 border-b bg-muted/30 text-[11px] text-muted-foreground hover:text-foreground\"\n >\n <span className=\"flex items-center gap-1\">\n {expanded ? <ChevronDown className=\"h-3 w-3\" /> : <ChevronRight className=\"h-3 w-3\" />}\n <span className=\"font-mono\">JSON · {lineCount} lines</span>\n </span>\n <span>{expanded ? 'collapse' : 'expand'}</span>\n </button>\n {expanded && (\n <pre\n className={cn(\n 'text-xs font-mono whitespace-pre p-2 max-h-96 overflow-auto',\n isError ? 'text-destructive' : 'text-foreground',\n )}\n >\n {pretty}\n </pre>\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { Copy, Check } from 'lucide-react';\nimport { useState } from 'react';\nimport { copyToClipboard } from './utils.js';\n\nexport function CopyButton({\n text,\n className,\n label = 'Copy',\n}: {\n text: string;\n className?: string;\n label?: string;\n}) {\n const [copied, setCopied] = useState(false);\n return (\n <button\n type=\"button\"\n onClick={async (ev) => {\n ev.stopPropagation();\n const ok = await copyToClipboard(text);\n if (ok) {\n setCopied(true);\n setTimeout(() => setCopied(false), 1400);\n }\n }}\n className={cn(\n 'inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors',\n className,\n )}\n title={label}\n >\n {copied ? (\n <>\n <Check className=\"h-3 w-3 text-green-500\" />\n <span>Copied</span>\n </>\n ) : (\n <>\n <Copy className=\"h-3 w-3\" />\n <span>{label}</span>\n </>\n )}\n </button>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { CopyButton } from './CopyButton.js';\nimport type React from 'react';\n\nexport { copyToClipboard };\n\nasync function copyToClipboard(text: string): Promise<boolean> {\n try {\n if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(text);\n return true;\n }\n } catch {\n /* fall through */\n }\n try {\n const ta = document.createElement('textarea');\n ta.value = text;\n ta.style.position = 'fixed';\n ta.style.opacity = '0';\n document.body.appendChild(ta);\n ta.select();\n const ok = document.execCommand('copy');\n document.body.removeChild(ta);\n return ok;\n } catch {\n return false;\n }\n}\n\nexport function downloadTextFile(filename: string, text: string): void {\n if (typeof document === 'undefined') return;\n const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n\nexport function fileExtensionFor(toolName: string | undefined): string {\n const t = (toolName ?? '').toLowerCase();\n if (/bash|shell|exec|run/.test(t)) return 'log';\n if (/grep|search|find/.test(t)) return 'txt';\n return 'txt';\n}\n\nexport function formatToolDuration(ms: number): string {\n if (ms < 1000) return `${ms} ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(ms < 10_000 ? 2 : 1)}s`;\n const m = Math.floor(ms / 60_000);\n const s = Math.floor((ms % 60_000) / 1000);\n return `${m}m ${s}s`;\n}\n\nexport const markdownComponents = {\n code({\n inline,\n className,\n children,\n ...props\n }: {\n inline?: boolean;\n className?: string;\n children?: React.ReactNode;\n }) {\n const match = /language-(\\w+)/.exec(className ?? '');\n const codeText = String(children ?? '').replace(/\\n$/, '');\n if (inline || !match) {\n return (\n <code className={cn('rounded bg-muted/60 px-1.5 py-0.5 text-[0.85em] font-mono', className)} {...props}>\n {children}\n </code>\n );\n }\n return (\n <div className=\"not-prose relative my-3 rounded-lg border bg-muted/30 overflow-hidden\">\n <div className=\"flex items-center justify-between px-3 py-1.5 border-b bg-muted/40 text-xs\">\n <span className=\"font-mono text-muted-foreground\">{match[1]}</span>\n <CopyButton text={codeText} label=\"\" />\n </div>\n <pre className=\"overflow-x-auto p-3 text-xs leading-relaxed font-mono max-h-[40rem]\">\n <code>{codeText}</code>\n </pre>\n </div>\n );\n },\n};\n","import { cn } from '@/lib/utils';\nimport type React from 'react';\nimport { useState } from 'react';\n\nfunction detectStackBoundary(text: string): number {\n const lines = text.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const ln = lines[i]!;\n if (/^\\s*at\\s+\\S+.*\\(.*:\\d+:\\d+\\)\\s*$/.test(ln)) return i;\n if (/^\\s*at\\s+\\S+\\.\\S+\\(\\S+\\.java:\\d+\\)\\s*$/.test(ln)) return i;\n if (/^\\s+File \"[^\"]+\", line \\d+/.test(ln)) return i;\n }\n return -1;\n}\n\nexport function ErrorBodyWithStack({ text }: { text: string }) {\n const idx = detectStackBoundary(text);\n const [open, setOpen] = useState(false);\n if (idx === -1) {\n return (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs leading-relaxed\">\n {text}\n </pre>\n );\n }\n const lines = text.split('\\n');\n const head = lines.slice(0, idx).join('\\n').trim();\n const stack = lines.slice(idx).join('\\n');\n const frameCount = stack.split('\\n').filter((l) => l.trim().length > 0).length;\n return (\n <div className=\"space-y-2\">\n {head && (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs leading-relaxed\">\n {head}\n </pre>\n )}\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"inline-flex items-center gap-1 text-xs text-destructive hover:text-destructive/80 font-medium\"\n >\n {open ? '▾' : '▸'} {open ? 'Hide' : 'Show'} stack trace ({frameCount} frame\n {frameCount === 1 ? '' : 's'})\n </button>\n {open && (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-[11px] leading-snug bg-destructive/5 border border-destructive/20 rounded p-2 max-h-80 overflow-auto\">\n {stack}\n </pre>\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useState } from 'react';\n\nexport function ToolInputView({ input }: { input: unknown }) {\n const [openKeys, setOpenKeys] = useState<Record<string, boolean>>({});\n if (input === null || input === undefined || typeof input !== 'object' || Array.isArray(input)) {\n return (\n <pre className=\"whitespace-pre-wrap break-all text-xs font-mono\">\n {JSON.stringify(input, null, 2)}\n </pre>\n );\n }\n const entries = Object.entries(input as Record<string, unknown>);\n if (entries.length === 0) {\n return <span className=\"text-xs text-muted-foreground italic\">(no params)</span>;\n }\n return (\n <div className=\"text-xs font-mono\">\n {entries.map(([k, v]) => {\n const isPrimitive =\n v === null || v === undefined || typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';\n if (isPrimitive) {\n const display = v === null ? 'null' : v === undefined ? 'undefined' : typeof v === 'string' ? v : String(v);\n const isLong = typeof v === 'string' && (display.length > 80 || display.includes('\\n'));\n return (\n <div key={k} className={cn('py-0.5', isLong ? 'flex flex-col gap-0.5' : 'flex items-baseline gap-2')}>\n <span className=\"text-muted-foreground shrink-0\">{k}:</span>\n <span\n className={cn(\n 'text-foreground',\n isLong ? 'whitespace-pre-wrap break-all bg-muted/40 rounded px-1.5 py-1' : 'truncate',\n typeof v === 'string' ? '' : 'text-amber-600 dark:text-amber-400',\n )}\n title={typeof v === 'string' && !isLong ? display : undefined}\n >\n {display}\n </span>\n </div>\n );\n }\n const open = !!openKeys[k];\n const summary = Array.isArray(v)\n ? `[${v.length} item${v.length === 1 ? '' : 's'}]`\n : `{${Object.keys(v as object).length} key${Object.keys(v as object).length === 1 ? '' : 's'}}`;\n return (\n <div key={k} className=\"py-0.5\">\n <button\n type=\"button\"\n onClick={() => setOpenKeys((p) => ({ ...p, [k]: !p[k] }))}\n className=\"flex items-baseline gap-2 hover:bg-muted/30 rounded px-1 -mx-1\"\n >\n <span className=\"text-muted-foreground/60 text-[10px]\">{open ? '▾' : '▸'}</span>\n <span className=\"text-muted-foreground\">{k}:</span>\n <span className=\"text-violet-600 dark:text-violet-400\">{summary}</span>\n </button>\n {open && (\n <pre className=\"ml-3 mt-1 whitespace-pre-wrap break-all text-[11px] bg-muted/40 rounded px-2 py-1.5\">\n {JSON.stringify(v, null, 2)}\n </pre>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { useSessionStore } from '@/stores';\nimport { Check, ChevronDown } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\n/**\n * Pill-shaped mode chip in the topbar. Click to drop a small picker with\n * the available modes (fetched lazily on first open from the backend's\n * modes.list handler). Selecting a mode broadcasts a session.start update\n * so the chip and the system-prompt context reflect the change without a\n * page reload.\n */\nexport function ModePicker() {\n const mode = useSessionStore((s) => s.mode);\n const modes = useSessionStore((s) => s.modes);\n const { listModes, switchMode } = useWebSocket();\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n // Lazy-fetch the modes list the first time the user clicks the chip\n // (and refresh on every open in case the user installed a new mode\n // through some other surface).\n if (open) listModes();\n }, [open, listModes]);\n\n // Close on outside click / Escape.\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('mousedown', onClick);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onClick);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n const items =\n modes.length > 0\n ? modes\n : [{ id: 'default', name: 'Default', description: 'Standard agent behaviour' }];\n\n return (\n <div ref={rootRef} className=\"relative shrink-0\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium',\n 'bg-accent/40 text-foreground hover:bg-accent transition-colors border border-transparent hover:border-primary/30',\n )}\n title=\"Active mode\"\n >\n mode: <span className=\"font-mono\">{mode || 'default'}</span>\n <ChevronDown className=\"h-3 w-3 opacity-60\" />\n </button>\n {open && (\n <div className=\"absolute top-full left-0 mt-1 w-64 rounded-md border bg-popover shadow-lg z-30 py-1\">\n <div className=\"px-3 py-1.5 text-[10px] uppercase tracking-wider text-muted-foreground border-b\">\n Mode\n </div>\n {items.map((m) => (\n <button\n key={m.id}\n type=\"button\"\n onClick={() => {\n switchMode(m.id);\n setOpen(false);\n }}\n className={cn(\n 'w-full text-left px-3 py-2 hover:bg-accent/40 flex items-start gap-2',\n m.id === mode && 'bg-accent/30',\n )}\n >\n <Check\n className={cn(\n 'h-3.5 w-3.5 mt-0.5 shrink-0',\n m.id === mode ? 'opacity-100 text-primary' : 'opacity-0',\n )}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-xs font-mono\">{m.id}</div>\n {m.description && (\n <div className=\"text-[11px] text-muted-foreground leading-snug\">\n {m.description}\n </div>\n )}\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useChatStore, useUIStore } from '@/stores';\nimport { ArrowDown, ArrowUp, Search, X } from 'lucide-react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\n\n/**\n * Ctrl+F overlay that searches the current chat transcript. Hits are\n * counted as the user types; ↑/↓ step between hits and Enter scrolls the\n * highlighted message into view. The actual highlight is handed off via a\n * DOM data attribute so we don't need to invasively rewrap message\n * rendering — see ChatView for where the active hit gets the highlight\n * class applied.\n */\nexport function SearchOverlay() {\n const open = useUIStore((s) => s.searchOpen);\n const setOpen = useUIStore((s) => s.setSearchOpen);\n const query = useUIStore((s) => s.searchQuery);\n const setQuery = useUIStore((s) => s.setSearchQuery);\n const messages = useChatStore((s) => s.messages);\n\n const inputRef = useRef<HTMLInputElement>(null);\n const [activeHit, setActiveHit] = useState(0);\n\n useEffect(() => {\n if (open) requestAnimationFrame(() => inputRef.current?.focus());\n }, [open]);\n\n const hits = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return [] as string[];\n return messages\n .filter((m) => {\n if (m.role === 'tool') {\n return (\n (m.toolName ?? '').toLowerCase().includes(q) ||\n (m.toolResult ?? '').toLowerCase().includes(q) ||\n JSON.stringify(m.toolInput ?? '')\n .toLowerCase()\n .includes(q)\n );\n }\n return m.content.toLowerCase().includes(q);\n })\n .map((m) => m.id);\n }, [messages, query]);\n\n useEffect(() => {\n if (activeHit >= hits.length) setActiveHit(0);\n }, [hits, activeHit]);\n\n // Paint every match of the current query inside chat bubbles using the\n // CSS Custom Highlights API. We walk the text nodes under every\n // `[data-message-id]` element, build Range objects per hit, then register\n // two highlights: `chat-search` covers everything, `chat-search-active`\n // covers only the message currently navigated to (so the user can see\n // where they are in the list). The registry is cleared on unmount and on\n // every query change so stale ranges don't linger.\n useEffect(() => {\n // Feature-detect — falls back to silent no-op on older browsers; the\n // ring-flash navigation behaviour below still works.\n const win = window as unknown as {\n CSS?: { highlights?: Map<string, unknown> };\n Highlight?: new (...ranges: Range[]) => unknown;\n };\n const highlights = win.CSS?.highlights;\n const HighlightCtor = win.Highlight;\n if (!highlights || !HighlightCtor) return;\n const clear = () => {\n highlights.delete('chat-search');\n highlights.delete('chat-search-active');\n };\n const q = query.trim();\n if (!q || !open) {\n clear();\n return;\n }\n const lcQuery = q.toLowerCase();\n const allRanges: Range[] = [];\n const activeRanges: Range[] = [];\n const activeId = hits[activeHit];\n for (const el of document.querySelectorAll('[data-message-id]')) {\n const id = (el as HTMLElement).dataset.messageId;\n const isActive = id === activeId;\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n let node = walker.nextNode() as Text | null;\n while (node) {\n const text = node.nodeValue ?? '';\n if (text.length > 0) {\n const lc = text.toLowerCase();\n let from = 0;\n while (from <= lc.length - lcQuery.length) {\n const at = lc.indexOf(lcQuery, from);\n if (at === -1) break;\n const range = document.createRange();\n range.setStart(node, at);\n range.setEnd(node, at + lcQuery.length);\n allRanges.push(range);\n if (isActive) activeRanges.push(range);\n from = at + lcQuery.length;\n }\n }\n node = walker.nextNode() as Text | null;\n }\n }\n if (allRanges.length > 0) {\n highlights.set('chat-search', new HighlightCtor(...allRanges) as never);\n } else {\n highlights.delete('chat-search');\n }\n if (activeRanges.length > 0) {\n highlights.set('chat-search-active', new HighlightCtor(...activeRanges) as never);\n } else {\n highlights.delete('chat-search-active');\n }\n return clear;\n }, [query, hits, activeHit, open]);\n\n useEffect(() => {\n const id = hits[activeHit];\n if (!id) return;\n const el = document.querySelector(`[data-message-id=\"${id}\"]`);\n if (el) {\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n }, [hits, activeHit]);\n\n if (!open) return null;\n\n const step = (dir: 1 | -1) => {\n if (hits.length === 0) return;\n setActiveHit((i) => (i + dir + hits.length) % hits.length);\n };\n\n return (\n <div className=\"absolute top-2 right-4 z-30 w-[28rem] max-w-[calc(100%-2rem)] rounded-lg border bg-popover shadow-xl\">\n <div className=\"flex items-center gap-2 px-3 py-2\">\n <Search className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n setOpen(false);\n } else if (e.key === 'Enter') {\n e.preventDefault();\n step(e.shiftKey ? -1 : 1);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n step(1);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n step(-1);\n }\n }}\n placeholder=\"Search in chat…\"\n className=\"flex-1 bg-transparent outline-none text-sm placeholder:text-muted-foreground\"\n />\n <span className=\"text-xs text-muted-foreground tabular-nums shrink-0\">\n {hits.length === 0 ? (query ? '0' : '') : `${activeHit + 1} / ${hits.length}`}\n </span>\n <button\n type=\"button\"\n onClick={() => step(-1)}\n disabled={hits.length === 0}\n className={cn(\n 'p-1 rounded hover:bg-muted disabled:opacity-30 disabled:cursor-not-allowed',\n )}\n title=\"Previous hit\"\n >\n <ArrowUp className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => step(1)}\n disabled={hits.length === 0}\n className={cn(\n 'p-1 rounded hover:bg-muted disabled:opacity-30 disabled:cursor-not-allowed',\n )}\n title=\"Next hit\"\n >\n <ArrowDown className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className=\"p-1 rounded hover:bg-muted text-muted-foreground\"\n title=\"Close (Esc)\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { Monitor, Moon, Sun } from 'lucide-react';\nimport { useTheme } from './ThemeProvider';\n\nconst OPTIONS = [\n { value: 'light', icon: Sun, label: 'Light' },\n { value: 'dark', icon: Moon, label: 'Dark' },\n { value: 'system', icon: Monitor, label: 'System' },\n] as const;\n\n/**\n * Segmented Light / Dark / System theme control. Instrument-style: a small\n * bezelled track with the active segment lit in signal-amber.\n */\nexport function ThemeToggle({ className }: { className?: string }) {\n const { theme, setTheme } = useTheme();\n return (\n <div\n className={cn(\n 'inline-flex items-center gap-0.5 rounded-lg border border-border bg-card/70 p-0.5 shadow-sm',\n className,\n )}\n role=\"radiogroup\"\n aria-label=\"Theme\"\n >\n {OPTIONS.map(({ value, icon: Icon, label }) => {\n const active = theme === value;\n return (\n <button\n key={value}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n title={`${label} theme`}\n aria-label={`${label} theme`}\n onClick={() => setTheme(value)}\n className={cn(\n 'grid h-7 w-7 place-items-center rounded-md transition-all duration-150',\n active\n ? 'bg-primary/15 text-primary shadow-[inset_0_0_0_1px_hsl(var(--primary)/0.35)]'\n : 'text-muted-foreground hover:bg-accent hover:text-foreground',\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" strokeWidth={2.2} />\n </button>\n );\n })}\n </div>\n );\n}\n","import { useConfigStore } from '@/stores';\nimport type React from 'react';\nimport { createContext, useContext, useEffect, useState } from 'react';\n\ntype Theme = 'light' | 'dark' | 'system';\n\ninterface ThemeProviderProps {\n children: React.ReactNode;\n defaultTheme?: Theme;\n storageKey?: string;\n}\n\ninterface ThemeProviderState {\n theme: Theme;\n setTheme: (theme: Theme) => void;\n}\n\nconst ThemeProviderContext = createContext<ThemeProviderState | undefined>(undefined);\n\nexport function ThemeProvider({\n children,\n defaultTheme = 'system',\n storageKey = 'wrongstack-theme',\n}: ThemeProviderProps) {\n const { setTheme: setStoreTheme } = useConfigStore();\n const [theme, setTheme] = useState<Theme>(() => {\n if (typeof window !== 'undefined') {\n return (localStorage.getItem(storageKey) as Theme) || defaultTheme;\n }\n return defaultTheme;\n });\n\n useEffect(() => {\n const root = window.document.documentElement;\n root.classList.remove('light', 'dark');\n\n if (theme === 'system') {\n const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light';\n root.classList.add(systemTheme);\n } else {\n root.classList.add(theme);\n }\n }, [theme]);\n\n const value = {\n theme,\n setTheme: (newTheme: Theme) => {\n localStorage.setItem(storageKey, newTheme);\n setTheme(newTheme);\n setStoreTheme(newTheme);\n },\n };\n\n return <ThemeProviderContext.Provider value={value}>{children}</ThemeProviderContext.Provider>;\n}\n\nexport function useTheme() {\n const context = useContext(ThemeProviderContext);\n if (context === undefined) {\n throw new Error('useTheme must be used within a ThemeProvider');\n }\n return context;\n}\n","import { cn } from '@/lib/utils';\nimport type { ChatMessage } from '@/stores';\nimport { CheckCircle2, ChevronDown, ChevronRight, Loader2, Terminal, XCircle } from 'lucide-react';\nimport { memo, useState } from 'react';\nimport { MessageBubble } from './MessageBubble';\n\ninterface ToolGroupProps {\n /** A run of consecutive tool messages (>=1). Rendered as one chip while\n * collapsed, expanded into the usual MessageBubble list on click. */\n tools: ChatMessage[];\n /** Force-expand the latest group so newly-running tools are visible by\n * default (otherwise users see \"5 tool calls\" pop in and have to click to\n * understand what's running). Older groups stay collapsed. */\n defaultOpen?: boolean;\n /** Render as a continuation of the previous item in the same agent turn —\n * hides the avatar column (replaced with a transparent spacer) and the\n * group's chrome stitches into the same flow as the surrounding text /\n * tool items instead of standing alone. */\n isContinuation?: boolean;\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(ms < 10_000 ? 2 : 1)}s`;\n const m = Math.floor(ms / 60_000);\n const s = Math.floor((ms % 60_000) / 1000);\n return `${m}m${s}s`;\n}\n\nexport const ToolGroup = memo(function ToolGroup({\n tools,\n defaultOpen = false,\n isContinuation = false,\n}: ToolGroupProps) {\n const [open, setOpen] = useState(defaultOpen);\n\n // Single tool? Render as a normal bubble — grouping overhead is just noise.\n if (tools.length === 1) {\n return <MessageBubble message={tools[0]!} isFirst isContinuation={isContinuation} />;\n }\n\n const running = tools.filter((t) => t.toolResult === undefined).length;\n const errored = tools.filter((t) => t.isError).length;\n const totalMs = tools.reduce((acc, t) => acc + (t.toolDurationMs ?? 0), 0);\n\n // Show the first few tool names so the user has a hint of what's inside\n // without expanding (\"Read, Grep, Bash …\").\n const names = Array.from(new Set(tools.map((t) => t.toolName).filter(Boolean) as string[]));\n const preview = names.slice(0, 3).join(', ');\n const more = names.length > 3 ? ` +${names.length - 3}` : '';\n\n return (\n <div className=\"flex gap-3 animate-message\">\n {isContinuation ? (\n <div className=\"flex-shrink-0 w-8 h-8\" aria-hidden />\n ) : (\n <div className=\"flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center bg-secondary text-secondary-foreground ring-2 ring-offset-2 ring-offset-background ring-secondary/20\">\n <Terminal className=\"h-4 w-4\" />\n </div>\n )}\n\n <div className=\"flex flex-col gap-1.5 max-w-[85%] flex-1 min-w-0\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'flex items-center gap-2 text-sm font-medium cursor-pointer select-none',\n 'hover:bg-muted/50 rounded-lg px-2 py-1.5 -mx-2 transition-colors',\n 'border border-border/40 bg-muted/30',\n )}\n >\n {open ? (\n <ChevronDown className=\"h-3.5 w-3.5 text-muted-foreground\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5 text-muted-foreground\" />\n )}\n <Terminal className=\"h-3.5 w-3.5 text-muted-foreground\" />\n <span className=\"font-mono text-xs\">\n {tools.length} tool call{tools.length === 1 ? '' : 's'}\n </span>\n {running > 0 ? (\n <Loader2 className=\"h-3 w-3 animate-spin text-amber-500\" />\n ) : errored > 0 ? (\n <XCircle className=\"h-3 w-3 text-destructive\" />\n ) : (\n <CheckCircle2 className=\"h-3 w-3 text-green-500\" />\n )}\n {totalMs > 0 && (\n <span className=\"text-xs text-muted-foreground tabular-nums font-normal\">\n {formatDuration(totalMs)}\n </span>\n )}\n {preview && (\n <span className=\"text-xs text-muted-foreground/80 font-mono truncate\">\n · {preview}\n {more}\n </span>\n )}\n </button>\n\n {open && (\n <div className=\"space-y-2 pl-3 border-l-2 border-border/40 ml-2\">\n {tools.map((tool) => (\n <MessageBubble key={tool.id} message={tool} isFirst={false} />\n ))}\n </div>\n )}\n </div>\n </div>\n );\n});\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore, useHistoryStore, useSessionStore, useUIStore } from '@/stores';\nimport type { WSServerMessage } from '@/types';\nimport type { LucideIcon } from 'lucide-react';\nimport {\n ArchiveRestore,\n ArrowRight,\n Bug,\n Clock,\n KeyRound,\n Keyboard,\n Search,\n Sparkles,\n Wrench,\n Zap,\n} from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\ninterface PromptCard {\n icon: LucideIcon;\n title: string;\n hint: string;\n tone: string;\n prompts: string[];\n}\n\nconst CARDS: PromptCard[] = [\n {\n icon: Search,\n title: 'Explore',\n hint: 'Understand the code before changing it',\n tone: 'text-blue-600 dark:text-blue-400 bg-blue-500/10 border-blue-500/20',\n prompts: [\n 'Walk me through this codebase: list the top-level packages, the role of each, and how they depend on one another. Highlight any cross-cutting abstractions I should understand first.',\n \"Find every place where the WebSocket protocol is defined or consumed (server handlers, client send/receive, type contracts). Show me the message-type table and any gaps where the type isn't enforced.\",\n 'Locate the entrypoint that boots the agent for normal runs. Trace the call chain from CLI launch all the way to the first model call — what middleware, hooks, and tools are wired along the way?',\n ],\n },\n {\n icon: Wrench,\n title: 'Build',\n hint: 'Add a feature end-to-end',\n tone: 'text-emerald-600 dark:text-emerald-400 bg-emerald-500/10 border-emerald-500/20',\n prompts: [\n \"Add a slash command `/export` that dumps the current chat (messages + tool calls + usage) as a markdown file to ~/.wrongstack/exports/ and surfaces a 'saved to X' toast. Wire backend + ws-client + slash menu entry.\",\n 'Create a notification toast system (Zustand store + portal-rendered <Toast/> component) and migrate every existing `key.operation_result` success/failure message to use it instead of dropping into chat.',\n 'Add structured JSON logging to the WebSocket server: each handler logs `{ts, level, type, payload}` to ~/.wrongstack/logs/webui.jsonl. Make it tail-friendly and respect the existing log.level config.',\n ],\n },\n {\n icon: Bug,\n title: 'Debug',\n hint: 'Track a problem to its root cause',\n tone: 'text-amber-600 dark:text-amber-400 bg-amber-500/10 border-amber-500/20',\n prompts: [\n 'Something feels off with token accounting — the cost chip and the per-message tally drift apart over a long session. Reproduce locally if you can, then propose a fix. Start by reading the TokenCounter + provider.response handler.',\n 'The WebSocket sometimes silently stops streaming text mid-response on lossy networks. Check the reconnect logic, message queue, and how we handle a half-completed text_delta stream after a reconnect.',\n 'I want to know why ctx % climbs so fast in long sessions. Use the existing /debug context breakdown to identify the largest contributors and propose three concrete pruning strategies (with token savings estimates).',\n ],\n },\n {\n icon: Sparkles,\n title: 'Refactor',\n hint: 'Clean up without breaking behavior',\n tone: 'text-violet-600 dark:text-violet-400 bg-violet-500/10 border-violet-500/20',\n prompts: [\n 'Find duplicated logic between packages/cli/src/webui-server.ts and packages/webui/src/server/index.ts. Extract the shared bits into a single source of truth (likely the webui package) and update the CLI to import it.',\n \"Look at the Zustand stores in packages/webui/src/stores/index.ts — anything that should be a derived selector instead of stored state? Anything persisted that shouldn't be? Propose a leaner shape and migration plan.\",\n \"Audit the slash command dispatcher: pull each command's run logic into its own module under packages/webui/src/commands/, make the registry data-driven, and ensure /help auto-generates from the registry (not a hardcoded list).\",\n ],\n },\n];\n\nconst SLASH_REFS: Array<{ name: string; hint: string }> = [\n { name: '/help', hint: 'list every slash command' },\n { name: '/diag', hint: 'runtime diagnostics' },\n { name: '/stats', hint: 'tokens · cache · cost · elapsed' },\n { name: '/tools', hint: 'show registered tools' },\n { name: '/memory', hint: 'show remembered notes' },\n { name: '/compact', hint: 'shrink context' },\n { name: '/clear', hint: 'wipe current context' },\n { name: '/new', hint: 'fresh session' },\n];\n\nfunction fillTextarea(text: string): void {\n const ta = document.querySelector('textarea');\n if (!ta) return;\n const setter = Object.getOwnPropertyDescriptor(\n window.HTMLTextAreaElement.prototype,\n 'value',\n )?.set;\n setter?.call(ta, text);\n ta.dispatchEvent(new Event('input', { bubbles: true }));\n ta.focus();\n}\n\nexport function WelcomeScreen() {\n const { projectName } = useSessionStore();\n const { provider, model } = useConfigStore();\n const wsConnected = useConfigStore((s) => s.wsConnected);\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const setCurrentView = useUIStore((s) => s.setCurrentView);\n /** Saved-provider count. We subscribe directly to `providers.saved`\n * because SettingsPanel is the canonical owner of that state but isn't\n * always mounted (only when the user is on the Settings tab). undefined\n * means \"not yet fetched\" — we skip the CTA in that state to avoid a\n * flash on first paint. */\n const [savedCount, setSavedCount] = useState<number | undefined>(undefined);\n useEffect(() => {\n if (!wsConnected) return;\n const client = getWSClient(wsUrl);\n const off = client.on('providers.saved', (msg: WSServerMessage) => {\n const p = msg.payload as { providers: unknown[] };\n setSavedCount(p.providers?.length ?? 0);\n });\n client.listSavedProviders();\n return () => {\n off();\n };\n }, [wsConnected, wsUrl]);\n /** Recent prompts harvested from the user's typing history. The same\n * store that powers ↑/↓ recall in the input — surfacing them here turns\n * a blank welcome screen into a useful \"pick up where you left off\"\n * surface, without any backend round-trip. Limited to 6 so it doesn't\n * dominate the page. */\n const promptHistory = useUIStore((s) => s.promptHistory);\n const recentPrompts = promptHistory.slice(0, 6);\n /** Recent sessions surfaced as one-click resume buttons. Drives the\n * \"pick back up\" workflow without sending the user to the History tab.\n * We fetch on first paint when connected; the listing is otherwise\n * populated by the History tab on demand. */\n const { listSessions, resumeSession } = useWebSocket();\n const historyEntries = useHistoryStore((s) => s.entries);\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only\n useEffect(() => {\n if (wsConnected && historyEntries.length === 0) listSessions(10);\n // Intentionally only fire on first connect — refreshing on every\n // historyEntries change would loop after the response lands.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [wsConnected]);\n const sessionNicknames = useUIStore((s) => s.sessionNicknames);\n const recentSessions = historyEntries.filter((e) => !e.isCurrent).slice(0, 4);\n\n return (\n <div className=\"flex flex-col gap-8 py-8 px-2 max-w-5xl mx-auto w-full\">\n {/* Hero */}\n <div className=\"flex flex-col items-center text-center gap-3\">\n <div className=\"relative\">\n <div className=\"w-14 h-14 rounded-2xl bg-gradient-to-br from-primary via-primary to-primary/60 flex items-center justify-center shadow-lg shadow-primary/20\">\n <Zap className=\"h-7 w-7 text-primary-foreground\" />\n </div>\n <div className=\"absolute -inset-3 bg-gradient-to-r from-transparent via-primary/10 to-transparent animate-pulse rounded-full -z-10\" />\n </div>\n <div>\n <h2 className=\"text-2xl font-semibold tracking-tight\">\n Where do you want to start\n {projectName ? (\n <>\n {' in '}\n <span className=\"text-primary\">{projectName}</span>\n </>\n ) : (\n ''\n )}\n ?\n </h2>\n <p className=\"text-sm text-muted-foreground mt-2 max-w-2xl mx-auto leading-relaxed\">\n WrongStack is connected to your project and ready to read, edit, run commands, search\n the codebase, track todos, and remember context across sessions. Pick a starting prompt\n below, write your own, or type <span className=\"font-mono text-foreground/80\">/</span>{' '}\n for the full command palette.\n </p>\n {provider && model && (\n <p className=\"text-xs text-muted-foreground/70 mt-2 font-mono\">\n {provider} / {model}\n </p>\n )}\n </div>\n </div>\n\n {/* No-keys CTA — shown only when the backend is connected and the\n providers.saved response confirmed zero registered keys. Lands\n above the prompt cards because clicking those won't work until\n the user adds a key. Quietly disappears once at least one\n provider is registered. */}\n {wsConnected && savedCount === 0 && (\n <button\n type=\"button\"\n onClick={() => setCurrentView('settings')}\n className={cn(\n 'group rounded-xl border bg-gradient-to-br from-amber-500/10 via-amber-500/5 to-transparent',\n 'border-amber-500/30 hover:border-amber-500/50 transition-colors',\n 'p-4 flex items-center gap-4 text-left',\n )}\n >\n <span className=\"flex items-center justify-center w-12 h-12 rounded-lg bg-amber-500/15 text-amber-600 dark:text-amber-400 shrink-0\">\n <KeyRound className=\"h-6 w-6\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-base font-semibold mb-1\">No API key configured yet</h3>\n <p className=\"text-sm text-muted-foreground leading-relaxed\">\n Register a provider in Settings before sending a message — otherwise the agent has\n nothing to talk to. Anthropic, OpenAI, Google, and any OpenAI-compatible endpoint all\n work.\n </p>\n </div>\n <span className=\"flex items-center gap-1 text-xs text-amber-600 dark:text-amber-400 font-medium shrink-0 group-hover:translate-x-0.5 transition-transform\">\n Open Settings <ArrowRight className=\"h-3.5 w-3.5\" />\n </span>\n </button>\n )}\n\n {/* Prompt cards */}\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\n {CARDS.map((card) => {\n const Icon = card.icon;\n return (\n <div\n key={card.title}\n className=\"rounded-xl border bg-card/40 backdrop-blur-sm p-4 flex flex-col gap-3\"\n >\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'flex items-center justify-center w-8 h-8 rounded-lg border',\n card.tone,\n )}\n >\n <Icon className=\"h-4 w-4\" />\n </span>\n <div>\n <h3 className=\"text-sm font-semibold\">{card.title}</h3>\n <p className=\"text-xs text-muted-foreground\">{card.hint}</p>\n </div>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n {card.prompts.map((p, i) => (\n <button\n // biome-ignore lint/suspicious/noArrayIndexKey: static list\n key={i}\n type=\"button\"\n onClick={() => fillTextarea(p)}\n className=\"text-left text-xs leading-relaxed text-foreground/80 hover:text-foreground border border-transparent hover:border-border/60 rounded-lg px-3 py-2 hover:bg-muted/40 transition-colors line-clamp-3\"\n title={p}\n >\n {p}\n </button>\n ))}\n </div>\n </div>\n );\n })}\n </div>\n\n {/* Recent sessions — one-click resume. We pull the most recent\n non-current sessions so the user can pick back up without leaving\n the welcome screen. Hidden when there's nothing to show (fresh\n install / first run). */}\n {recentSessions.length > 0 && (\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-center gap-2 mb-3\">\n <ArchiveRestore className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground font-medium\">\n Pick back up\n </span>\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2\">\n {recentSessions.map((entry) => (\n <button\n key={entry.id}\n type=\"button\"\n onClick={() => resumeSession(entry.id)}\n className=\"text-left rounded-lg border border-border/40 bg-background/60 hover:border-primary/40 hover:bg-accent/30 px-3 py-2 transition-colors group/sess\"\n title={entry.title}\n >\n <div className=\"text-sm font-medium truncate text-foreground group-hover/sess:text-primary\">\n {sessionNicknames[entry.id] || entry.title || '(empty)'}\n </div>\n <div className=\"text-[10px] text-muted-foreground font-mono truncate mt-0.5\">\n {entry.provider}/{entry.model}\n {entry.tokenTotal > 0 && (\n <span className=\"ml-2\">· {entry.tokenTotal.toLocaleString()} tok</span>\n )}\n </div>\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Recent prompts — your own past prompts as one-click refills. Slash\n commands aren't included (the quick-commands block below handles\n those). Shows nothing until you've actually typed something. */}\n {recentPrompts.length > 0 && (\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-center gap-2 mb-3\">\n <Clock className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground font-medium\">\n Recent prompts\n </span>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n {recentPrompts\n .filter((p) => !p.startsWith('/'))\n .slice(0, 5)\n .map((p, i) => (\n <button\n // biome-ignore lint/suspicious/noArrayIndexKey: static list\n key={i}\n type=\"button\"\n onClick={() => fillTextarea(p)}\n className=\"text-left text-xs leading-relaxed text-muted-foreground hover:text-foreground border border-transparent hover:border-border/60 rounded-lg px-3 py-2 hover:bg-background/60 transition-colors line-clamp-2\"\n title={p}\n >\n {p}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Slash command quick-ref */}\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-center gap-2 mb-3\">\n <Keyboard className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground font-medium\">\n Quick commands\n </span>\n </div>\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-2\">\n {SLASH_REFS.map((c) => (\n <button\n key={c.name}\n type=\"button\"\n onClick={() => fillTextarea(c.name)}\n className=\"text-left flex flex-col gap-0.5 rounded-md border border-border/40 bg-background/60 px-3 py-2 hover:border-primary/40 hover:bg-accent/40 transition-colors\"\n >\n <span className=\"font-mono text-xs text-foreground\">{c.name}</span>\n <span className=\"text-[11px] text-muted-foreground truncate\">{c.hint}</span>\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';\nimport * as React from 'react';\n\nconst ScrollArea = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>\n>(({ className, children, ...props }, ref) => (\n <ScrollAreaPrimitive.Root\n ref={ref}\n className={cn('relative overflow-hidden', className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport className=\"h-full w-full rounded-[inherit]\">\n {children}\n </ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n));\nScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;\n\nconst ScrollBar = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>\n>(({ className, orientation = 'vertical', ...props }, ref) => (\n <ScrollAreaPrimitive.ScrollAreaScrollbar\n ref={ref}\n orientation={orientation}\n className={cn(\n 'flex touch-none select-none transition-colors',\n orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-[1px]',\n orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-[1px]',\n className,\n )}\n {...props}\n >\n <ScrollAreaPrimitive.ScrollAreaThumb className=\"relative flex-1 rounded-full bg-border\" />\n </ScrollAreaPrimitive.ScrollAreaScrollbar>\n));\nScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;\n\nexport { ScrollArea, ScrollBar };\n","export function fmtTok(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1000) return `${(n / 1000).toFixed(n >= 10_000 ? 0 : 1)}k`;\n return String(n);\n}\n","import { useChatStore } from '@/stores';\nimport { Brain } from 'lucide-react';\n\n/**\n * Soft, ephemeral chip rendered while the model is mid-reasoning. Reads the\n * thinking buffer straight from the chat store so it stays in sync with the\n * stream without re-rendering the full message list.\n */\nexport function ThinkingBubble() {\n const buf = useChatStore((s) => s.thinkingBuffer);\n if (!buf) return null;\n const tailLines = buf.split('\\n').slice(-6);\n const tail = tailLines.join('\\n').trim();\n return (\n <div className=\"flex gap-3 animate-message\">\n <div className=\"flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center bg-violet-500/10 text-violet-600 dark:text-violet-400 ring-2 ring-offset-2 ring-offset-background ring-violet-500/20\">\n <Brain className=\"h-4 w-4 animate-pulse\" />\n </div>\n <div className=\"flex flex-col gap-1 max-w-[85%] min-w-0\">\n <span className=\"text-xs font-medium text-violet-600 dark:text-violet-400 px-1\">\n Thinking…\n </span>\n <div className=\"rounded-2xl rounded-bl-md px-3 py-2 bg-violet-500/[0.04] border border-violet-500/20 text-foreground/80\">\n <pre className=\"whitespace-pre-wrap break-words font-sans text-xs leading-relaxed italic max-h-32 overflow-hidden\">\n {tail || '…'}\n </pre>\n </div>\n </div>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore } from '@/stores';\nimport { Eye, LogIn, LogOut, MessageSquareWarning, Pause, Play, Users } from 'lucide-react';\nimport type React from 'react';\nimport type { CollabRole, WSCollabAnnotationAdded, WSCollabAnnotationResolved, WSCollabParticipantJoined, WSCollabParticipantLeft, WSCollabPauseGranted, WSCollabPauseReleased, WSCollabState, WSError, WSServerMessage } from '@/types';\nimport { useEffect, useState } from 'react';\n\nexport interface CollabPanelProps {\n /** Current session id — the panel joins this session on mount if the user opts in. */\n sessionId: string;\n /** Optional className for layout-level styling. */\n className?: string;\n}\n\nexport interface CollabParticipant {\n participantId: string;\n role: CollabRole;\n joinedAt: string;\n}\n\n/**\n * CollabPanel — read-only live observer indicator + join/leave control.\n *\n * Phase 1 of idea #13: a second human can join an active agent run and\n * watch a live mirror of kernel events (tool calls, iterations, subagent\n * spawns). The observer cannot modify the agent. Annotation and control\n * hand-off land in Phase 2/3.\n *\n * UX:\n * - 0 observers → muted \"Join as observer\" CTA\n * - 1+ observers → live dot + count + role chips + \"Leave\" button\n * - State stays in sync with the 2s server-side broadcast\n */\nexport function CollabPanel({ sessionId, className }: CollabPanelProps): React.ReactElement {\n const [participants, setParticipants] = useState<CollabParticipant[]>([]);\n const [joined, setJoined] = useState(false);\n const [joinedRole, setJoinedRole] = useState<'observer' | 'annotator' | 'controller' | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [openAnnotationCount, setOpenAnnotationCount] = useState(0);\n const [paused, setPaused] = useState(false);\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const client = getWSClient(wsUrl);\n\n useEffect(() => {\n const offs: Array<() => void> = [];\n\n // collab.state — full snapshot, sent on connect and every 2s.\n offs.push(\n client.on('collab.state', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabState['payload'];\n if (p.sessionId === sessionId) {\n setParticipants(p.participants ?? []);\n }\n }),\n );\n\n // collab.participant.joined — incremental add.\n offs.push(\n client.on('collab.participant.joined', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabParticipantJoined['payload'];\n if (p.sessionId !== sessionId) return;\n setParticipants((prev) => {\n if (prev.some((x) => x.participantId === p.participantId)) return prev;\n return [...prev, { participantId: p.participantId, role: p.role, joinedAt: p.joinedAt }];\n });\n }),\n );\n\n // collab.participant.left — incremental remove.\n offs.push(\n client.on('collab.participant.left', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabParticipantLeft['payload'];\n if (p.sessionId !== sessionId) return;\n const id = p.participantId;\n setParticipants((prev) => prev.filter((p) => p.participantId !== id));\n }),\n );\n\n // Surface collab-tagged server errors (e.g. role not available).\n offs.push(\n client.on('error', (msg: WSServerMessage) => {\n const p = msg.payload as WSError['payload'];\n if (p.phase === 'collab') {\n setError(p.message);\n // Optimistically mark as not joined so the user can retry.\n setJoined(false);\n }\n }),\n );\n\n // Suppress unhandled collab.event messages in the central dispatcher\n // (they're consumed by whoever renders the live activity strip).\n offs.push(client.on('collab.event', () => {}));\n\n // Phase 2: annotation count. We just track the local count of\n // unresolved annotations for a quick \"X notes\" indicator. The\n // full annotation timeline UI is a follow-up; the count gives\n // immediate visibility (\"are people reviewing this?\").\n offs.push(\n client.on('collab.annotation.added', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabAnnotationAdded['payload'];\n if (p.sessionId !== sessionId) return;\n if (p.annotation?.resolved) return;\n setOpenAnnotationCount((c) => c + 1);\n }),\n );\n offs.push(\n client.on('collab.annotation.resolved', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabAnnotationResolved['payload'];\n if (p.sessionId !== sessionId) return;\n setOpenAnnotationCount((c) => Math.max(0, c - 1));\n }),\n );\n\n // Phase 3: pause state. We track the local view of the bus\n // state and surface a small \"Paused\" chip. The actual pause/\n // resume actions are gated to controller participants.\n offs.push(\n client.on('collab.pause.granted', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabPauseGranted['payload'];\n if (p.sessionId !== sessionId) return;\n setPaused(true);\n }),\n );\n offs.push(\n client.on('collab.pause.released', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabPauseReleased['payload'];\n if (p.sessionId !== sessionId) return;\n setPaused(false);\n }),\n );\n\n return () => {\n for (const off of offs) off();\n };\n }, [client, sessionId]);\n\n const handleJoin = (role: 'observer' | 'annotator' | 'controller' = 'observer'): void => {\n setError(null);\n client.send({ type: 'collab.join', payload: { sessionId, role } });\n setJoined(true);\n setJoinedRole(role);\n };\n\n const handleRequestPause = (): void => {\n client.send({ type: 'collab.request_pause', payload: { sessionId } });\n };\n\n const handleResume = (): void => {\n client.send({ type: 'collab.resume', payload: { sessionId } });\n };\n\n const handleLeave = (): void => {\n client.send({ type: 'collab.leave', payload: { sessionId } });\n setJoined(false);\n setParticipants([]);\n };\n\n // Empty state: nobody watching, no errors.\n if (participants.length === 0 && !error) {\n return (\n <div\n className={cn(\n 'flex items-center gap-2 px-3 py-2 rounded-md border border-dashed border-border bg-card/40',\n className,\n )}\n >\n <Users className=\"w-4 h-4 text-muted-foreground\" />\n <span className=\"text-xs text-muted-foreground\">No live observers</span>\n <div className=\"ml-auto flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => handleJoin('observer')}\n className=\"inline-flex items-center gap-1 text-xs px-2 py-1 rounded bg-primary text-primary-foreground hover:bg-primary/90 transition-colors\"\n title=\"Join as a read-only observer (Phase 1)\"\n >\n <LogIn className=\"w-3 h-3\" />\n observer\n </button>\n <button\n type=\"button\"\n onClick={() => handleJoin('annotator')}\n className=\"inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-300 hover:bg-amber-500/20 transition-colors\"\n title=\"Join as an annotator — leave inline notes on tool calls (Phase 2)\"\n >\n <MessageSquareWarning className=\"w-3 h-3\" />\n annotator\n </button>\n <button\n type=\"button\"\n onClick={() => handleJoin('controller')}\n className=\"inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-rose-500/40 bg-rose-500/10 text-rose-700 dark:text-rose-300 hover:bg-rose-500/20 transition-colors\"\n title=\"Join as a controller — can pause the agent loop (Phase 3)\"\n >\n <Pause className=\"w-3 h-3\" />\n controller\n </button>\n </div>\n </div>\n );\n }\n\n // Error state: surface server's reason and let user retry.\n if (error) {\n return (\n <div\n className={cn(\n 'flex items-center gap-2 px-3 py-2 rounded-md border border-destructive/50 bg-destructive/10',\n className,\n )}\n role=\"alert\"\n >\n <span className=\"text-xs text-destructive\">Collab: {error}</span>\n <button\n type=\"button\"\n onClick={() => {\n setError(null);\n setJoined(false);\n }}\n className=\"ml-auto text-xs underline text-destructive\"\n >\n dismiss\n </button>\n </div>\n );\n }\n\n // Live state: at least one participant. Show count, live dot, role chips.\n return (\n <div\n className={cn(\n 'flex items-center gap-2 px-3 py-2 rounded-md border border-emerald-500/40 bg-emerald-500/5',\n className,\n )}\n >\n <span className=\"relative flex h-2 w-2\" aria-label=\"Live\">\n <span className=\"absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75 animate-ping\" />\n <span className=\"relative inline-flex rounded-full h-2 w-2 bg-emerald-500\" />\n </span>\n <Users className=\"w-4 h-4 text-emerald-700 dark:text-emerald-400\" />\n <span className=\"text-xs font-medium text-emerald-700 dark:text-emerald-300\">\n {participants.length} {participants.length === 1 ? 'observer' : 'observers'}\n </span>\n {openAnnotationCount > 0 && (\n <span\n title={`${openAnnotationCount} open annotation(s) — annotators reviewing this session`}\n className=\"ml-2 inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-amber-500/15 text-amber-700 dark:text-amber-300 border border-amber-500/30\"\n >\n <MessageSquareWarning className=\"w-3 h-3\" />\n {openAnnotationCount} note{openAnnotationCount === 1 ? '' : 's'}\n </span>\n )}\n {paused && (\n <span\n title=\"Agent loop is paused — a controller is reviewing\"\n className=\"ml-2 inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-rose-500/15 text-rose-700 dark:text-rose-300 border border-rose-500/40\"\n >\n <Pause className=\"w-3 h-3\" />\n paused\n </span>\n )}\n <div className=\"flex items-center gap-1 ml-2\">\n {participants.slice(0, 3).map((p) => (\n <span\n key={p.participantId}\n title={`Joined ${new Date(p.joinedAt).toLocaleTimeString()}`}\n className=\"inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/10 text-emerald-700 dark:text-emerald-300\"\n >\n <Eye className=\"w-3 h-3\" />\n {p.role}\n </span>\n ))}\n {participants.length > 3 && (\n <span className=\"text-[10px] text-muted-foreground\">+{participants.length - 3}</span>\n )}\n </div>\n {joined && joinedRole === 'controller' && (\n paused ? (\n <button\n type=\"button\"\n onClick={handleResume}\n className=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-rose-500/40 bg-rose-500/10 text-rose-700 dark:text-rose-300 hover:bg-rose-500/20 transition-colors\"\n title=\"Resume the agent loop\"\n >\n <Play className=\"w-3 h-3\" />\n Resume\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleRequestPause}\n className=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-300 hover:bg-amber-500/20 transition-colors\"\n title=\"Pause the agent before the next tool call\"\n >\n <Pause className=\"w-3 h-3\" />\n Pause agent\n </button>\n )\n )}\n {joined && joinedRole !== 'controller' && (\n <button\n type=\"button\"\n onClick={handleLeave}\n className=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-border hover:bg-muted transition-colors\"\n title=\"Leave the observer session\"\n >\n <LogOut className=\"w-3 h-3\" />\n Leave\n </button>\n )}\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { useUIStore } from '@/stores';\nimport { AlertTriangle, FileEdit, Globe, ShieldAlert, Terminal, Wrench } from 'lucide-react';\nimport { useEffect, useRef } from 'react';\nimport { DiffView, diffFromToolInput } from './DiffView';\nimport { Button } from './ui/button';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from './ui/dialog';\n\n/**\n * Pick the right hero icon for the tool being confirmed. Helps the user\n * see at a glance \"is this a file edit, a shell run, a network call?\".\n */\nfunction pickToolIcon(toolName: string) {\n if (/edit|write|create|patch/i.test(toolName)) return FileEdit;\n if (/bash|shell|exec|run|command/i.test(toolName)) return Terminal;\n if (/fetch|http|web|curl|request/i.test(toolName)) return Globe;\n return Wrench;\n}\n\n/**\n * Render the tool input intelligently. For edit/write we drop the JSON\n * dump and show a proper diff. For shell-like tools we surface the\n * command as a single mono line. Everything else falls back to JSON.\n */\nfunction SmartInputPreview({\n toolName,\n input,\n}: {\n toolName: string;\n input: unknown;\n}) {\n const diffArgs = diffFromToolInput(toolName, input);\n if (diffArgs) {\n return (\n <div className=\"rounded-lg overflow-hidden border\">\n <DiffView\n oldText={diffArgs.oldText}\n newText={diffArgs.newText}\n caption={diffArgs.caption}\n />\n </div>\n );\n }\n\n // Shell-like: pull out the command string so it shows as a real terminal\n // line instead of a JSON envelope.\n if (typeof input === 'object' && input !== null) {\n const obj = input as Record<string, unknown>;\n const cmd = (obj.command ?? obj.cmd ?? obj.script) as string | undefined;\n if (typeof cmd === 'string' && cmd.trim().length > 0) {\n return (\n <div className=\"rounded-lg border bg-background/40 overflow-hidden\">\n <div className=\"px-3 py-1.5 text-[10px] uppercase tracking-wider text-muted-foreground border-b bg-muted/40 flex items-center gap-1.5\">\n <Terminal className=\"h-3 w-3\" />\n <span>Command</span>\n </div>\n <pre className=\"px-3 py-2 text-xs font-mono whitespace-pre-wrap break-all max-h-40 overflow-auto\">\n ${cmd}\n </pre>\n </div>\n );\n }\n // url + method for fetch-like calls\n const url = obj.url as string | undefined;\n if (typeof url === 'string') {\n const method = (obj.method as string | undefined) ?? 'GET';\n return (\n <div className=\"rounded-lg border bg-background/40 px-3 py-2 text-xs font-mono\">\n <span className=\"text-muted-foreground\">{method.toUpperCase()}</span>{' '}\n <span className=\"break-all\">{url}</span>\n </div>\n );\n }\n }\n\n return (\n <div className=\"p-3 rounded-lg bg-muted/50 border text-xs font-mono\">\n <div className=\"text-muted-foreground mb-2\">Input:</div>\n <pre className=\"whitespace-pre-wrap break-all max-h-60 overflow-auto\">\n {JSON.stringify(input, null, 2)}\n </pre>\n </div>\n );\n}\n\nexport function ConfirmDialog() {\n const { showConfirmDialog, confirmInfo, hideConfirm } = useUIStore();\n const { sendConfirm } = useWebSocket();\n const dialogRef = useRef<HTMLDivElement>(null);\n\n const handleConfirm = (decision: 'yes' | 'no' | 'always' | 'deny') => {\n if (confirmInfo) {\n sendConfirm(confirmInfo.id, decision);\n }\n hideConfirm();\n };\n\n // Keyboard shortcuts: y/n/a/d/Esc — matches the CLI and TUI permission\n // prompts so muscle memory transfers directly across all surfaces.\n // biome-ignore lint/correctness/useExhaustiveDependencies: keyboard handler; handleConfirm stable\n useEffect(() => {\n if (!showConfirmDialog) return;\n const onKey = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement | null;\n const tag = target?.tagName?.toLowerCase();\n if (tag === 'input' || tag === 'textarea') return;\n if (e.key === 'y' || e.key === 'Y') {\n e.preventDefault();\n handleConfirm('yes');\n } else if (e.key === 'n' || e.key === 'N' || e.key === 'Escape') {\n e.preventDefault();\n handleConfirm('no');\n } else if (e.key === 'a' || e.key === 'A') {\n e.preventDefault();\n handleConfirm('always');\n } else if (e.key === 'd' || e.key === 'D') {\n e.preventDefault();\n handleConfirm('deny');\n }\n };\n window.addEventListener('keydown', onKey);\n // Focus the dialog container so keyboard shortcuts work immediately\n // without the user having to click into the dialog first.\n dialogRef.current?.focus();\n return () => window.removeEventListener('keydown', onKey);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [showConfirmDialog, confirmInfo?.id]);\n\n if (!confirmInfo) {\n return (\n <Dialog open={showConfirmDialog} onOpenChange={() => hideConfirm()}>\n <DialogContent />\n </Dialog>\n );\n }\n\n const Icon = pickToolIcon(confirmInfo.toolName);\n const isEdit = /edit|write/i.test(confirmInfo.toolName);\n\n return (\n <Dialog open={showConfirmDialog} onOpenChange={() => hideConfirm()}>\n <DialogContent className=\"sm:max-w-2xl border-yellow-500/50\" ref={dialogRef} tabIndex={-1}>\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <ShieldAlert className=\"h-5 w-5 text-yellow-500 animate-pulse\" />\n Approval required: {confirmInfo.toolName}\n </DialogTitle>\n <DialogDescription>\n The agent wants to {isEdit ? 'modify a file' : 'run this tool'}. Review the request\n below and decide whether to proceed.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"py-2 space-y-3\">\n <div className=\"flex items-center gap-3 p-3 rounded-lg bg-muted\">\n <Icon className=\"h-5 w-5 text-muted-foreground\" />\n <div className=\"min-w-0\">\n <div className=\"font-medium font-mono truncate\">{confirmInfo.toolName}</div>\n <div className=\"text-xs text-muted-foreground\">\n {isEdit ? 'File modification' : 'Tool execution'} — preview below\n </div>\n </div>\n </div>\n\n {confirmInfo.input !== undefined && (\n <SmartInputPreview toolName={confirmInfo.toolName} input={confirmInfo.input} />\n )}\n\n {confirmInfo.suggestedPattern && (\n <div className=\"flex items-start gap-2 p-3 rounded-lg bg-yellow-500/10 border border-yellow-500/20\">\n <AlertTriangle className=\"h-4 w-4 text-yellow-600 mt-0.5 shrink-0\" />\n <div className=\"text-sm min-w-0\">\n <div className=\"font-medium text-yellow-800 dark:text-yellow-200\">\n Trust pattern suggestion\n </div>\n <div className=\"font-mono text-xs mt-1 break-all\">\n {confirmInfo.suggestedPattern}\n </div>\n <div className=\"text-xs text-muted-foreground mt-1\">\n Picking <span className=\"font-medium\">Always</span> will whitelist matching calls\n for this project.\n </div>\n </div>\n </div>\n )}\n </div>\n\n <DialogFooter className=\"gap-2 sm:gap-2 flex-wrap\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleConfirm('deny')}\n title=\"Reject this and all future calls matching the pattern (d)\"\n >\n Deny always <kbd className=\"ml-1 text-[10px] border rounded px-1 bg-background\">d</kbd>\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleConfirm('no')}\n title=\"Reject this single call (Esc / n)\"\n >\n No <kbd className=\"ml-1 text-[10px] border rounded px-1 bg-background\">n</kbd>\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleConfirm('always')}\n title=\"Approve and remember the pattern for the project (a)\"\n >\n Always <kbd className=\"ml-1 text-[10px] border rounded px-1 bg-background\">a</kbd>\n </Button>\n <Button\n size=\"sm\"\n onClick={() => handleConfirm('yes')}\n title=\"Approve this single call (y)\"\n >\n Yes <kbd className=\"ml-1 text-[10px] border rounded px-1 bg-background/80\">y</kbd>\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","import { cn } from '@/lib/utils';\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\nimport { X } from 'lucide-react';\nimport * as React from 'react';\n\nconst Dialog = DialogPrimitive.Root;\nconst DialogTrigger = DialogPrimitive.Trigger;\nconst DialogPortal = DialogPrimitive.Portal;\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',\n className,\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)} {...props} />\n);\nDialogHeader.displayName = 'DialogHeader';\n\nconst DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}\n {...props}\n />\n);\nDialogFooter.displayName = 'DialogFooter';\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn('text-lg font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogClose,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n};\n","import { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore } from '@/stores';\nimport { Loader2, RotateCcw, WifiOff, X } from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\n/**\n * Prominent connection-lost banner. The ConnectionChip in the topbar is\n * easy to miss when the user is heads-down on the chat; this banner\n * stretches across the top, blocks the visual flow, and offers a \"retry\n * now\" button. Auto-hides as soon as the socket comes back open.\n *\n * Dismissable for the current outage (X button) — once dismissed, only\n * comes back if the socket recovers and then drops again. The chip in\n * the topbar still reflects the live state so the user isn't fully blind\n * after dismissing.\n */\nexport function ConnectionBanner() {\n const wsStatus = useConfigStore((s) => s.wsStatus);\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const [dismissed, setDismissed] = useState(false);\n const [now, setNow] = useState(Date.now());\n\n // Live retry countdown while reconnecting.\n useEffect(() => {\n if (wsStatus.state !== 'reconnecting') return;\n const id = setInterval(() => setNow(Date.now()), 500);\n return () => clearInterval(id);\n }, [wsStatus.state]);\n\n // Reset the dismissal flag every time the socket recovers — so the *next*\n // disconnection re-shows the banner. Without this the user would have to\n // refresh after dismissing to ever see the banner again.\n useEffect(() => {\n if (wsStatus.state === 'open') setDismissed(false);\n }, [wsStatus.state]);\n\n if (wsStatus.state === 'open' || wsStatus.state === 'connecting') return null;\n if (dismissed) return null;\n\n const retry = () => getWSClient(wsUrl).retryNow();\n const isReconnecting = wsStatus.state === 'reconnecting';\n const errorText =\n wsStatus.state === 'closed'\n ? wsStatus.error\n : wsStatus.state === 'reconnecting'\n ? wsStatus.lastError\n : undefined;\n const remaining = isReconnecting\n ? Math.max(0, Math.ceil((wsStatus.nextRetryAt - now) / 1000))\n : 0;\n\n return (\n <div\n className={cn(\n 'flex items-center gap-3 px-4 py-2 border-b text-sm',\n isReconnecting\n ? 'bg-orange-500/10 text-orange-700 dark:text-orange-300 border-orange-500/30'\n : 'bg-red-500/10 text-red-700 dark:text-red-300 border-red-500/30',\n )}\n >\n {isReconnecting ? (\n <Loader2 className=\"h-4 w-4 animate-spin shrink-0\" />\n ) : (\n <WifiOff className=\"h-4 w-4 shrink-0\" />\n )}\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-medium\">\n {isReconnecting\n ? `Reconnecting to backend (attempt ${wsStatus.attempt}) — retrying in ${remaining}s`\n : 'Disconnected from backend'}\n </div>\n {errorText && <div className=\"text-xs opacity-80 truncate\">{errorText}</div>}\n </div>\n <button\n type=\"button\"\n onClick={retry}\n className={cn(\n 'inline-flex items-center gap-1 px-2.5 py-1 rounded-md border text-xs font-medium',\n 'hover:bg-background/30 transition-colors shrink-0',\n isReconnecting ? 'border-orange-500/40' : 'border-red-500/40',\n )}\n title=\"Retry connection now\"\n >\n <RotateCcw className=\"h-3 w-3\" />\n Retry now\n </button>\n <button\n type=\"button\"\n onClick={() => setDismissed(true)}\n className=\"text-current/60 hover:text-current shrink-0\"\n title=\"Dismiss (chip in topbar still shows status)\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n );\n}\n","import { AlertTriangle, RefreshCw } from 'lucide-react';\nimport { Component, type ErrorInfo, type ReactNode } from 'react';\nimport { Button } from './ui/button';\n\ninterface Props {\n children: ReactNode;\n /** Optional callback when an error is caught — useful for telemetry. */\n onError?: (error: Error, info: ErrorInfo) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * Top-level error boundary for the entire app. Catches rendering errors in\n * any descendent component and shows a fallback UI instead of a white screen.\n * A single crash in a leaf component (e.g. a malformed markdown render) must\n * not take down the entire chat session.\n */\nexport class ErrorBoundary extends Component<Props, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n console.error('[ErrorBoundary]', error, info.componentStack);\n this.props.onError?.(error, info);\n }\n\n private handleReset = () => {\n this.setState({ error: null });\n };\n\n render() {\n if (this.state.error) {\n return (\n <div className=\"flex items-center justify-center h-screen bg-background\">\n <div className=\"flex flex-col items-center gap-4 p-8 max-w-md text-center\">\n <AlertTriangle className=\"h-12 w-12 text-destructive\" />\n <h1 className=\"text-lg font-semibold\">Something went wrong</h1>\n <p className=\"text-sm text-muted-foreground\">\n A rendering error occurred. Your session is still active on the server — reloading\n will pick up where you left off.\n </p>\n <pre className=\"text-xs font-mono text-muted-foreground bg-muted/50 rounded p-3 max-h-32 overflow-auto w-full text-left\">\n {this.state.error.message}\n </pre>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" variant=\"outline\" onClick={() => window.location.reload()}>\n <RefreshCw className=\"h-4 w-4 mr-1\" />\n Reload page\n </Button>\n <Button size=\"sm\" onClick={this.handleReset}>\n Try again\n </Button>\n </div>\n </div>\n </div>\n );\n }\n return this.props.children;\n }\n}\n","import { cn } from '@/lib/utils';\nimport { type SubagentView, useFleetStore } from '@/stores';\nimport { Bot, ChevronDown, ChevronRight, Cpu, Wrench, Zap } from 'lucide-react';\nimport { useMemo, useState } from 'react';\n\n/** Status → LED color + label. Running pulses; terminal states are steady. */\nconst STATUS_META: Record<\n SubagentView['status'],\n { tone: string; led: string; label: string; pulse: boolean }\n> = {\n running: {\n tone: 'text-[hsl(var(--success))]',\n led: 'text-[hsl(var(--success))]',\n label: 'running',\n pulse: true,\n },\n completed: {\n tone: 'text-muted-foreground',\n led: 'text-[hsl(var(--success))]',\n label: 'done',\n pulse: false,\n },\n failed: {\n tone: 'text-destructive',\n led: 'text-destructive',\n label: 'failed',\n pulse: false,\n },\n timeout: {\n tone: 'text-[hsl(var(--warning))]',\n led: 'text-[hsl(var(--warning))]',\n label: 'timeout',\n pulse: false,\n },\n stopped: {\n tone: 'text-muted-foreground',\n led: 'text-muted-foreground',\n label: 'stopped',\n pulse: false,\n },\n};\n\nfunction fmtCost(v: number): string {\n if (v <= 0) return '$0';\n if (v >= 0.01) return `$${v.toFixed(3)}`;\n return `$${v.toFixed(5).replace(/0+$/, '').replace(/\\.$/, '')}`;\n}\n\nfunction AgentCard({ a }: { a: SubagentView }): React.ReactElement {\n const meta = STATUS_META[a.status];\n const active = a.status === 'running';\n const tool = a.currentTool ?? a.lastTool;\n return (\n <div\n className={cn(\n 'flex min-w-[15rem] max-w-[18rem] flex-col gap-1.5 rounded-lg border p-2.5 transition-colors',\n active ? 'border-primary/30 bg-primary/[0.04]' : 'border-border bg-card opacity-90',\n )}\n >\n {/* Identity row */}\n <div className=\"flex items-center gap-2 min-w-0\">\n <span className={cn('led shrink-0', meta.led, meta.pulse && 'led-pulse')} />\n <span className=\"truncate text-xs font-semibold text-foreground\" title={a.name}>\n {a.name}\n </span>\n <span className={cn('ml-auto shrink-0 text-[10px] uppercase tracking-wider', meta.tone)}>\n {meta.label}\n </span>\n </div>\n\n {/* Model */}\n {a.model && (\n <div className=\"flex items-center gap-1 text-[10px] text-muted-foreground min-w-0\">\n <Cpu className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate font-mono\" title={`${a.provider ?? ''}/${a.model}`}>\n {a.model}\n </span>\n </div>\n )}\n\n {/* Live counters */}\n <div className=\"tabular flex items-center gap-2 text-[11px] text-muted-foreground\">\n <span title=\"iteration\">L{a.iteration}</span>\n <span className=\"text-border\">·</span>\n <span title=\"tool calls\">{a.toolCalls} tools</span>\n <span className=\"text-border\">·</span>\n <span className=\"text-foreground/80\" title=\"cost so far\">\n {fmtCost(a.costUsd)}\n </span>\n {a.extensions > 0 && (\n <span\n className=\"ml-auto inline-flex items-center gap-0.5 rounded bg-primary/15 px-1 text-[10px] text-primary\"\n title={`Self-extended budget ${a.extensions}×`}\n >\n <Zap className=\"h-2.5 w-2.5\" />\n {a.extensions}\n </span>\n )}\n </div>\n\n {/* Current/last tool */}\n {tool && (\n <div\n className={cn(\n 'flex items-center gap-1 text-[10px] truncate',\n active ? 'text-primary' : 'text-muted-foreground',\n )}\n title={a.currentTool ? `running ${tool}` : `last ran ${tool}`}\n >\n <Wrench className={cn('h-3 w-3 shrink-0', active && 'animate-pulse')} />\n <span className=\"truncate font-mono\">{tool}</span>\n </div>\n )}\n\n {/* Context fill bar */}\n {a.maxContext > 0 && (\n <div className=\"flex items-center gap-1.5\" title={`Context ${a.ctxPct}%`}>\n <div className=\"h-1 flex-1 overflow-hidden rounded-full bg-muted\">\n <div\n className={cn(\n 'h-full rounded-full transition-all duration-500',\n a.ctxPct >= 85\n ? 'bg-destructive'\n : a.ctxPct >= 70\n ? 'bg-[hsl(var(--warning))]'\n : 'bg-primary',\n )}\n style={{ width: `${Math.max(2, a.ctxPct)}%` }}\n />\n </div>\n <span className=\"tabular text-[9px] text-muted-foreground\">{a.ctxPct}%</span>\n </div>\n )}\n\n {/* Failure reason */}\n {a.error && (\n <div\n className=\"truncate rounded bg-destructive/10 px-1.5 py-0.5 text-[10px] text-destructive\"\n title={a.error.message}\n >\n {a.error.kind}: {a.error.message}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * FleetPanel — live roster of subagents spawned during a multi-agent run.\n *\n * Driven entirely by the `subagent.event` WS stream (reduced in useFleetStore).\n * Renders nothing when the fleet is empty, so a solo session is unaffected.\n * Collapsible so a large fleet doesn't dominate the chat column.\n */\nexport function FleetPanel({ className }: { className?: string }): React.ReactElement | null {\n const agents = useFleetStore((s) => s.agents);\n const [collapsed, setCollapsed] = useState(false);\n\n // Stable order: running first, then by start time. Recompute only when the\n // map identity changes (the store always sets a fresh Map on update).\n const list = useMemo(() => {\n const arr = Array.from(agents.values());\n arr.sort((x, y) => {\n const xa = x.status === 'running' ? 0 : 1;\n const ya = y.status === 'running' ? 0 : 1;\n if (xa !== ya) return xa - ya;\n return x.startedAt - y.startedAt;\n });\n return arr;\n }, [agents]);\n\n if (list.length === 0) return null;\n const activeCount = list.filter((a) => a.status === 'running').length;\n\n return (\n <div className={cn('rounded-lg border border-border bg-card/50 backdrop-blur-sm', className)}>\n <button\n type=\"button\"\n onClick={() => setCollapsed((v) => !v)}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left\"\n >\n <Bot className=\"h-4 w-4 text-primary\" />\n <span className=\"text-xs font-semibold text-foreground\">Fleet</span>\n <span className=\"tabular text-[10px] text-muted-foreground\">\n {list.length} agent{list.length === 1 ? '' : 's'}\n {activeCount > 0 && (\n <span className=\"text-[hsl(var(--success))]\"> · {activeCount} active</span>\n )}\n </span>\n {activeCount > 0 && (\n <span className=\"led led-pulse text-[hsl(var(--success))]\" aria-hidden />\n )}\n {collapsed ? (\n <ChevronRight className=\"ml-auto h-4 w-4 text-muted-foreground\" />\n ) : (\n <ChevronDown className=\"ml-auto h-4 w-4 text-muted-foreground\" />\n )}\n </button>\n {!collapsed && (\n <div className=\"flex gap-2 overflow-x-auto px-3 pb-3 pt-0.5\">\n {list.map((a) => (\n <AgentCard key={a.id} a={a} />\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore, useUIStore } from '@/stores';\nimport type { WSServerMessage } from '@/types';\nimport { ArrowRight, Cpu, Search } from 'lucide-react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\n\ninterface SavedProvider {\n id: string;\n apiKeys: Array<{ label: string; isActive: boolean }>;\n}\ninterface CatalogModel {\n id: string;\n name: string;\n contextWindow?: number;\n}\n\n/**\n * Ctrl/Cmd+M — flat searchable provider/model picker. Drops a 3-click\n * trip through Settings down to one shortcut. Pulls the list of *saved*\n * providers (the ones that actually have a registered key) and lazy-loads\n * each provider's models when the overlay opens. The active model is\n * highlighted; Enter switches via the existing model.switch WS handler\n * (which atomically swaps provider+model on the backend).\n */\nexport function QuickModelSwitcher() {\n const open = useUIStore((s) => s.modelSwitcherOpen);\n const setOpen = useUIStore((s) => s.setModelSwitcherOpen);\n const [query, setQuery] = useState('');\n const [selected, setSelected] = useState(0);\n const [saved, setSaved] = useState<SavedProvider[]>([]);\n const [modelsByProvider, setModelsByProvider] = useState<Record<string, CatalogModel[]>>({});\n const inputRef = useRef<HTMLInputElement>(null);\n\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const currentProvider = useConfigStore((s) => s.provider);\n const currentModel = useConfigStore((s) => s.model);\n const paletteOpen = useUIStore((s) => s.paletteOpen);\n const ws = useWebSocket();\n\n // Ctrl/Cmd+M opens. Skip when the command palette is already open so\n // the two overlays don't fight for focus.\n // biome-ignore lint/correctness/useExhaustiveDependencies: setOpen is stable\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const mod = e.ctrlKey || e.metaKey;\n if (mod && e.key.toLowerCase() === 'm' && !e.shiftKey && !e.altKey) {\n if (paletteOpen) return;\n e.preventDefault();\n setOpen(!open);\n return;\n }\n if (e.key === 'Escape' && open) {\n e.preventDefault();\n setOpen(false);\n }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [open, paletteOpen]);\n\n // Wire up WS listeners + fetch on open. We listen unconditionally so a\n // late response (e.g. the user opened then closed before models arrived)\n // still populates state for the next open.\n useEffect(() => {\n const client = getWSClient(wsUrl);\n const offSaved = client.on('providers.saved', (msg: WSServerMessage) => {\n const p = msg.payload as { providers: SavedProvider[] };\n setSaved(p.providers ?? []);\n });\n const offModels = client.on('provider.models', (msg: WSServerMessage) => {\n const p = msg.payload as { provider: string; models: CatalogModel[] };\n setModelsByProvider((prev) => ({ ...prev, [p.provider]: p.models }));\n });\n return () => {\n offSaved();\n offModels();\n };\n }, [wsUrl]);\n\n useEffect(() => {\n if (!open) return;\n setQuery('');\n setSelected(0);\n ws.listSavedProviders();\n // Auto-focus the search input after the dialog paints. requestAnimationFrame\n // because the input ref isn't mounted on the same tick we flip `open`.\n requestAnimationFrame(() => inputRef.current?.focus());\n }, [open, ws]);\n\n // Lazy-load models per saved provider once we know what's saved.\n useEffect(() => {\n if (!open) return;\n for (const sp of saved) {\n if (!modelsByProvider[sp.id]) {\n ws.listProviderModels(sp.id);\n }\n }\n }, [open, saved, modelsByProvider, ws]);\n\n /** Flatten into a single list of {provider, model} candidates, then apply\n * the search filter. The active row floats to the top so the user can\n * see what they're currently on. */\n const candidates = useMemo(() => {\n const list: Array<{\n provider: string;\n model: string;\n modelName: string;\n contextWindow?: number;\n isCurrent: boolean;\n }> = [];\n for (const sp of saved) {\n const models = modelsByProvider[sp.id] ?? [];\n for (const m of models) {\n list.push({\n provider: sp.id,\n model: m.id,\n modelName: m.name || m.id,\n contextWindow: m.contextWindow,\n isCurrent: sp.id === currentProvider && m.id === currentModel,\n });\n }\n }\n const q = query.toLowerCase().trim();\n const filtered = q\n ? list.filter(\n (c) =>\n c.provider.toLowerCase().includes(q) ||\n c.model.toLowerCase().includes(q) ||\n c.modelName.toLowerCase().includes(q),\n )\n : list;\n return filtered.sort((a, b) => {\n if (a.isCurrent !== b.isCurrent) return a.isCurrent ? -1 : 1;\n return a.provider.localeCompare(b.provider) || a.model.localeCompare(b.model);\n });\n }, [saved, modelsByProvider, query, currentProvider, currentModel]);\n\n useEffect(() => {\n if (selected >= candidates.length) setSelected(0);\n }, [candidates.length, selected]);\n\n const commit = (idx: number) => {\n const pick = candidates[idx];\n if (!pick) return;\n ws.switchModel(pick.provider, pick.model);\n setOpen(false);\n };\n\n if (!open) return null;\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-start justify-center bg-background/60 backdrop-blur-sm pt-[15vh]\"\n onClick={(e) => {\n if (e.target === e.currentTarget) setOpen(false);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setOpen(false);\n }}\n >\n <div className=\"w-full max-w-xl rounded-xl border bg-popover shadow-2xl overflow-hidden\">\n <div className=\"flex items-center gap-2 border-b px-3 py-2\">\n <Search className=\"h-4 w-4 text-muted-foreground\" />\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n setSelected(0);\n }}\n onKeyDown={(e) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelected((i) => Math.min(candidates.length - 1, i + 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelected((i) => Math.max(0, i - 1));\n } else if (e.key === 'Enter') {\n e.preventDefault();\n commit(selected);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setOpen(false);\n }\n }}\n placeholder=\"Filter providers and models…\"\n className=\"flex-1 bg-transparent outline-none text-sm placeholder:text-muted-foreground\"\n />\n <span className=\"text-[10px] text-muted-foreground font-mono\">↑↓ · Enter · Esc</span>\n </div>\n <div className=\"max-h-[50vh] overflow-y-auto py-1\">\n {candidates.length === 0 ? (\n <div className=\"px-4 py-8 text-center text-sm text-muted-foreground\">\n {saved.length === 0\n ? 'No saved providers — register a key in Settings first.'\n : 'Loading models…'}\n </div>\n ) : (\n candidates.map((c, idx) => (\n <button\n type=\"button\"\n key={`${c.provider}:${c.model}`}\n onClick={() => commit(idx)}\n onMouseEnter={() => setSelected(idx)}\n className={cn(\n 'w-full flex items-center gap-3 px-3 py-2 text-left text-sm transition-colors',\n idx === selected ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40',\n c.isCurrent && 'font-medium',\n )}\n >\n <Cpu\n className={cn(\n 'h-4 w-4 shrink-0',\n c.isCurrent ? 'text-primary' : 'text-muted-foreground',\n )}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate\">\n <span className=\"text-muted-foreground\">{c.provider}</span>\n <span className=\"mx-1 text-muted-foreground/40\">·</span>\n <span>{c.modelName}</span>\n </div>\n {c.contextWindow && (\n <div className=\"text-[10px] text-muted-foreground font-mono\">\n {c.model} · ctx {c.contextWindow.toLocaleString()}\n </div>\n )}\n </div>\n {c.isCurrent ? (\n <span className=\"text-[10px] uppercase tracking-wide text-primary font-semibold\">\n active\n </span>\n ) : (\n <ArrowRight className=\"h-3.5 w-3.5 text-muted-foreground opacity-0 group-hover:opacity-100\" />\n )}\n </button>\n ))\n )}\n </div>\n </div>\n </div>\n );\n}\n","import { toast } from '@/components/Toaster';\nimport { useWebSocket } from '@/hooks/useWebSocket';\nimport { useConfigStore, useUIStore } from '@/stores';\nimport type { WSServerMessage } from '@/types';\nimport {\n Cpu,\n Globe,\n Monitor,\n Moon,\n Network,\n Palette,\n Sun,\n X,\n} from 'lucide-react';\nimport { useState, useEffect, useCallback } from 'react';\nimport { useTheme } from '../ThemeProvider';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { ScrollArea } from '../ui/scroll-area';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs';\nimport { PreferenceToggle } from './PreferenceToggle';\nimport {\n ProviderSection,\n type CatalogProvider,\n type SavedProvider,\n type ProviderTab,\n} from './ProviderSection';\nimport { ModelSection } from './ModelSection';\n\ninterface CatalogModel {\n id: string;\n name: string;\n releaseDate?: string;\n contextWindow?: number;\n inputCost?: number;\n outputCost?: number;\n capabilities: string[];\n}\n\nexport function SettingsPanel() {\n const { setCurrentView } = useUIStore();\n const { provider, model, setProvider, setModel, wsConnected } = useConfigStore();\n const { theme, setTheme } = useTheme();\n const ws = useWebSocket();\n const wsClient = ws.client;\n\n // Catalog data\n const [catalogProviders, setCatalogProviders] = useState<CatalogProvider[]>([]);\n const [catalogModels, setCatalogModels] = useState<Record<string, CatalogModel[]>>({});\n const [savedProviders, setSavedProviders] = useState<SavedProvider[]>([]);\n const [isLoadingCatalog, setIsLoadingCatalog] = useState(false);\n const [isLoadingModels, setIsLoadingModels] = useState(false);\n const [isLoadingSaved, setIsLoadingSaved] = useState(false);\n\n const [providerTab, setProviderTab] = useState<ProviderTab>('catalog');\n const [catalogQuery, setCatalogQuery] = useState('');\n\n const currentCatalogProvider = catalogProviders.find((p) => p.id === provider);\n\n // WS event subscriptions\n useEffect(() => {\n const handleProviderCatalog = (msg: WSServerMessage) => {\n if (msg.type === 'provider.catalog') {\n const payload = msg.payload as { providers: CatalogProvider[] };\n setCatalogProviders(payload.providers.sort((a, b) => a.id.localeCompare(b.id)));\n setIsLoadingCatalog(false);\n }\n };\n\n const handleProviderModels = (msg: WSServerMessage) => {\n if (msg.type === 'provider.models') {\n const payload = msg.payload as { provider: string; models: CatalogModel[] };\n setCatalogModels((prev) => ({ ...prev, [payload.provider]: payload.models }));\n setIsLoadingModels(false);\n }\n };\n\n const handleSavedProviders = (msg: WSServerMessage) => {\n if (msg.type === 'providers.saved') {\n const payload = msg.payload as { providers: SavedProvider[] };\n const next = payload.providers.sort((a, b) => a.id.localeCompare(b.id));\n setSavedProviders(next);\n setIsLoadingSaved(false);\n if (next.length > 0) setProviderTab('saved');\n }\n };\n\n if (!wsConnected || !wsClient) return;\n\n const off1 = wsClient.on('provider.catalog', handleProviderCatalog);\n const off2 = wsClient.on('provider.models', handleProviderModels);\n const off3 = wsClient.on('providers.saved', handleSavedProviders);\n\n setIsLoadingCatalog(true);\n setIsLoadingSaved(true);\n wsClient.listProviders();\n wsClient.listSavedProviders();\n\n return () => {\n off1?.();\n off2?.();\n off3?.();\n };\n }, [wsConnected, wsClient]);\n\n // Provider selection\n const handleProviderSelect = useCallback(\n (providerId: string) => {\n setProvider(providerId);\n if (!catalogModels[providerId]) {\n setIsLoadingModels(true);\n ws.listProviderModels?.(providerId);\n }\n },\n [catalogModels, setProvider, ws],\n );\n\n // Model selection\n const handleModelSelect = useCallback(\n (modelId: string) => {\n setModel(modelId);\n const currentProvider = useConfigStore.getState().provider;\n ws.switchModel?.(currentProvider, modelId);\n toast.success(`Switching to ${currentProvider} / ${modelId}…`);\n },\n [setModel, ws],\n );\n\n // Key management callbacks\n const handleAddKey = useCallback(\n (providerId: string, label: string, value: string) => {\n ws.addKey?.(providerId, label, value);\n },\n [ws],\n );\n\n const handleDeleteKey = useCallback(\n (providerId: string, label: string) => {\n ws.deleteKey?.(providerId, label);\n },\n [ws],\n );\n\n const handleSetActiveKey = useCallback(\n (providerId: string, label: string) => {\n ws.setActiveKey?.(providerId, label);\n },\n [ws],\n );\n\n const handleAddProvider = useCallback(\n (id: string, family: string, baseUrl?: string, apiKey?: string) => {\n ws.addProvider?.(id, family, baseUrl, apiKey);\n },\n [ws],\n );\n\n const handleRemoveProvider = useCallback(\n (providerId: string) => {\n ws.removeProvider?.(providerId);\n },\n [ws],\n );\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Header */}\n <header className=\"flex items-center justify-between px-4 py-3 border-b bg-card shrink-0\">\n <h1 className=\"text-lg font-semibold\">Settings</h1>\n <Button variant=\"ghost\" size=\"icon\" onClick={() => setCurrentView('chat')}>\n <X className=\"h-4 w-4\" />\n </Button>\n </header>\n\n {/* Content */}\n <ScrollArea className=\"flex-1\">\n <div className=\"p-6 max-w-2xl mx-auto\">\n <Tabs defaultValue=\"provider\">\n <TabsList className=\"w-full justify-start mb-6 grid grid-cols-4\">\n <TabsTrigger value=\"provider\" className=\"gap-2\">\n <Network className=\"h-4 w-4\" />\n Provider\n </TabsTrigger>\n <TabsTrigger value=\"model\" className=\"gap-2\">\n <Cpu className=\"h-4 w-4\" />\n Model\n </TabsTrigger>\n <TabsTrigger value=\"connection\" className=\"gap-2\">\n <Globe className=\"h-4 w-4\" />\n Connection\n </TabsTrigger>\n <TabsTrigger value=\"appearance\" className=\"gap-2\">\n <Palette className=\"h-4 w-4\" />\n Appearance\n </TabsTrigger>\n </TabsList>\n\n {/* Provider Tab */}\n <TabsContent value=\"provider\" className=\"space-y-4\">\n <ProviderSection\n activeProvider={provider}\n catalogProviders={catalogProviders}\n isLoadingCatalog={isLoadingCatalog}\n savedProviders={savedProviders}\n isLoadingSaved={isLoadingSaved}\n providerTab={providerTab}\n setProviderTab={setProviderTab}\n onSelectProvider={handleProviderSelect}\n onAddKey={handleAddKey}\n onDeleteKey={handleDeleteKey}\n onSetActiveKey={handleSetActiveKey}\n onAddProvider={handleAddProvider}\n onRemoveProvider={handleRemoveProvider}\n catalogQuery={catalogQuery}\n setCatalogQuery={setCatalogQuery}\n />\n </TabsContent>\n\n {/* Model Tab */}\n <TabsContent value=\"model\" className=\"space-y-4\">\n <ModelSection\n provider={provider}\n catalogModels={catalogModels}\n currentCatalogProvider={currentCatalogProvider}\n isLoadingModels={isLoadingModels}\n setIsLoadingModels={setIsLoadingModels}\n onModelSelect={handleModelSelect}\n refreshModels={(pid) => ws.listProviderModels?.(pid)}\n />\n </TabsContent>\n\n {/* Connection Tab */}\n <TabsContent value=\"connection\" className=\"space-y-4\">\n <div className=\"space-y-3\">\n <label\n htmlFor=\"websocket-url\"\n className=\"text-sm font-medium flex items-center gap-2\"\n >\n <Globe className=\"h-4 w-4 text-muted-foreground\" />\n WebSocket Server URL\n </label>\n <Input\n id=\"websocket-url\"\n value={useConfigStore.getState().wsUrl}\n onChange={(e) => useConfigStore.getState().setConfig({ wsUrl: e.target.value })}\n placeholder=\"ws://localhost:3457\"\n className=\"font-mono text-sm\"\n />\n <p className=\"text-xs text-muted-foreground\">\n URL of the WrongStack WebSocket server. The server runs alongside the CLI.\n </p>\n </div>\n\n <div className=\"p-4 rounded-lg border bg-muted/50\">\n <h4 className=\"text-sm font-medium mb-2\">Starting the WebSocket Server</h4>\n <p className=\"text-xs text-muted-foreground mb-3\">\n Standalone: run <code className=\"bg-muted px-1 py-0.5 rounded\">./dev.ps1</code>{' '}\n from the repo root, or set WS_HOST/WS_PORT before launching{' '}\n <code className=\"bg-muted px-1 py-0.5 rounded\">\n node packages/webui/dist/server/entry.js\n </code>\n . Or alongside the CLI:{' '}\n <code className=\"bg-muted px-1 py-0.5 rounded\">wstack --webui</code>.\n </p>\n </div>\n </TabsContent>\n\n {/* Appearance Tab */}\n <TabsContent value=\"appearance\" className=\"space-y-4\">\n <div>\n <h3 className=\"text-sm font-semibold mb-3\">Theme</h3>\n <div className=\"grid grid-cols-3 gap-2 max-w-md\">\n <Button\n variant={theme === 'light' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setTheme('light')}\n >\n <Sun className=\"h-4 w-4 mr-1\" />\n Light\n </Button>\n <Button\n variant={theme === 'dark' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setTheme('dark')}\n >\n <Moon className=\"h-4 w-4 mr-1\" />\n Dark\n </Button>\n <Button\n variant={theme === 'system' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setTheme('system')}\n >\n <Monitor className=\"h-4 w-4 mr-1\" />\n System\n </Button>\n </div>\n <p className=\"text-xs text-muted-foreground mt-2\">\n System follows your OS-level light/dark preference.\n </p>\n </div>\n\n <div className=\"pt-2 border-t\">\n <h3 className=\"text-sm font-semibold mb-3 mt-3\">Preferences</h3>\n <PreferenceToggle\n label=\"Compact density\"\n hint=\"Tighter spacing throughout the chat. Toggle anywhere with Ctrl+Shift+D.\"\n selector={(s) => s.compactMode}\n onChange={() => useUIStore.getState().toggleCompactMode()}\n />\n <PreferenceToggle\n label=\"Sound on completion\"\n hint=\"Play a soft chime when a run finishes — useful when working in another tab.\"\n selector={null}\n configKey=\"soundOnComplete\"\n />\n </div>\n </TabsContent>\n </Tabs>\n </div>\n </ScrollArea>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport * as React from 'react';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nInput.displayName = 'Input';\n\nexport { Input };\n","import { cn } from '@/lib/utils';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport * as React from 'react';\n\nconst Tabs = TabsPrimitive.Root;\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.List\n ref={ref}\n className={cn(\n 'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',\n className,\n )}\n {...props}\n />\n));\nTabsList.displayName = TabsPrimitive.List.displayName;\n\nconst TabsTrigger = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n 'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm',\n className,\n )}\n {...props}\n />\n));\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName;\n\nconst TabsContent = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n 'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className,\n )}\n {...props}\n />\n));\nTabsContent.displayName = TabsPrimitive.Content.displayName;\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent };\n","import { playCompletionChime } from '@/lib/chime';\nimport { cn } from '@/lib/utils';\nimport { useConfigStore, useUIStore } from '@/stores';\n\n/**\n * One row in the Preferences section. Renders a label / hint pair on the\n * left and a small switch on the right.\n */\nexport function PreferenceToggle({\n label,\n hint,\n selector,\n onChange,\n configKey,\n}: {\n label: string;\n hint?: string;\n selector: ((s: ReturnType<typeof useUIStore.getState>) => boolean) | null;\n onChange?: () => void;\n configKey?: 'soundOnComplete';\n}) {\n const uiVal = useUIStore((s) => (selector ? selector(s) : false));\n const cfgVal = useConfigStore((s) => (configKey ? (s[configKey] as boolean) : false));\n const on = selector ? uiVal : cfgVal;\n const handleToggle = () => {\n if (selector) onChange?.();\n else if (configKey === 'soundOnComplete') {\n const next = !useConfigStore.getState().soundOnComplete;\n useConfigStore.getState().setSoundOnComplete(next);\n if (next) {\n playCompletionChime();\n }\n }\n };\n return (\n <div className=\"flex items-start justify-between gap-3 py-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm font-medium\">{label}</div>\n {hint && <div className=\"text-xs text-muted-foreground mt-0.5\">{hint}</div>}\n </div>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={on}\n onClick={handleToggle}\n className={cn(\n 'shrink-0 relative inline-flex h-5 w-9 rounded-full border transition-colors',\n on ? 'bg-primary border-primary' : 'bg-muted border-input hover:bg-muted/80',\n )}\n >\n <span\n className={cn(\n 'absolute top-0.5 left-0.5 h-3.5 w-3.5 rounded-full bg-background shadow transition-transform',\n on && 'translate-x-4',\n )}\n />\n </button>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport {\n CheckCircle2,\n Eye,\n EyeOff,\n Globe,\n Key,\n Loader2,\n Plus,\n Trash2,\n} from 'lucide-react';\nimport { useState, useCallback } from 'react';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\n\n// ── Types (shared with index) ──\n\nexport interface CatalogProvider {\n id: string;\n name: string;\n family: string;\n apiBase?: string;\n envVars: string[];\n modelCount: number;\n hasApiKey: boolean;\n}\n\nexport interface SavedProvider {\n id: string;\n family?: string;\n baseUrl?: string;\n apiKeys: Array<{\n label: string;\n maskedKey: string;\n isActive: boolean;\n createdAt: string;\n }>;\n}\n\nexport type ProviderTab = 'catalog' | 'saved';\n\nexport const PROVIDER_FAMILIES = ['anthropic', 'openai', 'google', 'openai-compatible'] as const;\n\n// ── Props ──\n\nexport interface ProviderSectionProps {\n /** Currently selected provider id. */\n activeProvider: string;\n /** Catalog providers list. */\n catalogProviders: CatalogProvider[];\n /** Loading flag. */\n isLoadingCatalog: boolean;\n /** Saved providers list. */\n savedProviders: SavedProvider[];\n /** Loading flag. */\n isLoadingSaved: boolean;\n /** Which sub-tab is active. */\n providerTab: ProviderTab;\n setProviderTab: (v: ProviderTab) => void;\n /** Called when a catalog provider is selected. */\n onSelectProvider: (id: string) => void;\n /** Called to add an API key. */\n onAddKey: (providerId: string, label: string, value: string) => void;\n /** Called to delete an API key. */\n onDeleteKey: (providerId: string, label: string) => void;\n /** Called to set a key as active. */\n onSetActiveKey: (providerId: string, label: string) => void;\n /** Called to add a custom provider. */\n onAddProvider: (id: string, family: string, baseUrl?: string, apiKey?: string) => void;\n /** Called to remove a saved provider. */\n onRemoveProvider: (providerId: string) => void;\n /** Search filter text. */\n catalogQuery: string;\n setCatalogQuery: (v: string) => void;\n}\n\n// ── Component ──\n\nexport function ProviderSection({\n activeProvider,\n catalogProviders,\n isLoadingCatalog,\n savedProviders,\n isLoadingSaved,\n providerTab,\n setProviderTab,\n onSelectProvider,\n onAddKey,\n onDeleteKey,\n onSetActiveKey,\n onAddProvider,\n onRemoveProvider,\n catalogQuery,\n setCatalogQuery,\n}: ProviderSectionProps) {\n // Key management form state\n const [showAddKeyForm, setShowAddKeyForm] = useState<string | null>(null);\n const [newKeyLabel, setNewKeyLabel] = useState('');\n const [newKeyValue, setNewKeyValue] = useState('');\n const [showNewKeyValue, setShowNewKeyValue] = useState(false);\n\n // Add provider form state\n const [showAddProviderForm, setShowAddProviderForm] = useState(false);\n const [newProviderId, setNewProviderId] = useState('');\n const [newProviderFamily, setNewProviderFamily] = useState('openai-compatible');\n const [newProviderBaseUrl, setNewProviderBaseUrl] = useState('');\n const [newProviderApiKey, setNewProviderApiKey] = useState('');\n\n const handleAddKey = useCallback(\n (providerId: string) => {\n if (!newKeyLabel.trim() || !newKeyValue.trim()) return;\n onAddKey(providerId, newKeyLabel.trim(), newKeyValue.trim());\n setNewKeyLabel('');\n setNewKeyValue('');\n setShowAddKeyForm(null);\n },\n [onAddKey, newKeyLabel, newKeyValue],\n );\n\n const handleAddProvider = useCallback(() => {\n if (!newProviderId.trim()) return;\n onAddProvider(newProviderId.trim(), newProviderFamily, newProviderBaseUrl || undefined, newProviderApiKey || undefined);\n setNewProviderId('');\n setNewProviderFamily('openai-compatible');\n setNewProviderBaseUrl('');\n setNewProviderApiKey('');\n setShowAddProviderForm(false);\n }, [onAddProvider, newProviderId, newProviderFamily, newProviderBaseUrl, newProviderApiKey]);\n\n // ── Filter + group catalog ──\n\n const filteredCatalog = catalogQuery.trim()\n ? catalogProviders.filter((p) => {\n const q = catalogQuery.trim().toLowerCase();\n return (\n p.id.toLowerCase().includes(q) ||\n p.name.toLowerCase().includes(q) ||\n p.family.toLowerCase().includes(q)\n );\n })\n : catalogProviders;\n\n const catalogByFamily = filteredCatalog.reduce(\n (acc, p) => {\n if (!acc[p.family]) acc[p.family] = [];\n acc[p.family]!.push(p);\n return acc;\n },\n {} as Record<string, CatalogProvider[]>,\n );\n\n // ── Render ──\n\n return (\n <div className=\"space-y-4\">\n {/* Provider source toggle */}\n <div className=\"flex gap-2 mb-4\">\n <Button\n variant={providerTab === 'catalog' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setProviderTab('catalog')}\n >\n <Globe className=\"h-4 w-4 mr-1\" />\n Catalog\n </Button>\n <Button\n variant={providerTab === 'saved' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setProviderTab('saved')}\n >\n <Key className=\"h-4 w-4 mr-1\" />\n Saved ({savedProviders.length})\n </Button>\n </div>\n\n {/* Catalog View */}\n {providerTab === 'catalog' && (\n <div className=\"space-y-4\">\n <Input\n placeholder={`Search ${catalogProviders.length} providers (name / id / family)…`}\n value={catalogQuery}\n onChange={(e) => setCatalogQuery(e.target.value)}\n className=\"text-sm\"\n />\n {isLoadingCatalog && catalogProviders.length === 0 ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n <span className=\"ml-2 text-muted-foreground\">Loading catalog...</span>\n </div>\n ) : filteredCatalog.length === 0 && catalogQuery ? (\n <div className=\"text-center py-8 text-muted-foreground text-sm\">\n No providers match \"<span className=\"font-mono\">{catalogQuery}</span>\".\n </div>\n ) : (\n <>\n {PROVIDER_FAMILIES.map((family) => {\n const providers = catalogByFamily[family];\n if (!providers?.length) return null;\n return (\n <div key={family} className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold text-muted-foreground uppercase tracking-wider\">\n {family}\n </h3>\n <div className=\"grid grid-cols-1 gap-2\">\n {providers.map((p) => (\n <button\n type=\"button\"\n key={p.id}\n onClick={() => onSelectProvider(p.id)}\n className={cn(\n 'flex flex-col items-start p-3 rounded-lg border text-left transition-all',\n activeProvider === p.id\n ? 'border-primary bg-primary/5 ring-2 ring-primary/20'\n : 'border-border hover:bg-muted',\n )}\n >\n <div className=\"flex w-full justify-between items-start\">\n <div>\n <span className=\"font-medium\">{p.name}</span>\n <span className=\"ml-2 text-xs text-muted-foreground\">\n ({p.id})\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n {p.hasApiKey && (\n <span className=\"text-xs bg-green-500/10 text-green-600 px-2 py-0.5 rounded\">\n <Key className=\"h-3 w-3 inline mr-1\" />\n Configured\n </span>\n )}\n {p.envVars[0] && (\n <span className=\"text-xs text-muted-foreground\">\n ENV: {p.envVars[0]}\n </span>\n )}\n {activeProvider === p.id && (\n <CheckCircle2 className=\"h-4 w-4 text-primary\" />\n )}\n </div>\n </div>\n <div className=\"text-xs text-muted-foreground mt-1\">\n {p.modelCount} models\n {p.apiBase && ` · ${p.apiBase}`}\n </div>\n </button>\n ))}\n </div>\n </div>\n );\n })}\n </>\n )}\n </div>\n )}\n\n {/* Saved Providers View */}\n {providerTab === 'saved' && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-between items-center\">\n <p className=\"text-sm text-muted-foreground\">\n Manage your API keys and provider configurations\n </p>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setShowAddProviderForm(!showAddProviderForm)}\n >\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Provider\n </Button>\n </div>\n\n {/* Add Provider Form */}\n {showAddProviderForm && (\n <div className=\"p-4 border rounded-lg space-y-3 bg-muted/50\">\n <h4 className=\"font-medium\">Add Custom Provider</h4>\n <Input\n placeholder=\"Provider ID (e.g. my-llm-server)\"\n value={newProviderId}\n onChange={(e) => setNewProviderId(e.target.value)}\n />\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={newProviderFamily}\n onChange={(e) => setNewProviderFamily(e.target.value)}\n >\n <option value=\"anthropic\">Anthropic</option>\n <option value=\"openai\">OpenAI</option>\n <option value=\"openai-compatible\">OpenAI Compatible</option>\n <option value=\"google\">Google</option>\n </select>\n <Input\n placeholder=\"Base URL (optional, e.g. http://localhost:11434/v1)\"\n value={newProviderBaseUrl}\n onChange={(e) => setNewProviderBaseUrl(e.target.value)}\n />\n <Input\n type=\"password\"\n placeholder=\"API Key (optional)\"\n value={newProviderApiKey}\n onChange={(e) => setNewProviderApiKey(e.target.value)}\n />\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={handleAddProvider} disabled={!newProviderId.trim()}>\n Add\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setShowAddProviderForm(false)}>\n Cancel\n </Button>\n </div>\n </div>\n )}\n\n {isLoadingSaved ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n </div>\n ) : savedProviders.length === 0 ? (\n <div className=\"text-center py-8 text-muted-foreground\">\n <Key className=\"h-8 w-8 mx-auto mb-2 opacity-50\" />\n <p>No saved providers yet</p>\n <p className=\"text-sm\">Add a provider to get started</p>\n </div>\n ) : (\n savedProviders.map((sp) => (\n <div key={sp.id} className=\"border rounded-lg p-4 space-y-3\">\n <div className=\"flex justify-between items-start\">\n <div>\n <h4 className=\"font-medium\">{sp.id}</h4>\n {sp.family && <span className=\"text-xs text-muted-foreground\">{sp.family}</span>}\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"icon\" variant=\"ghost\" onClick={() => onRemoveProvider(sp.id)}>\n <Trash2 className=\"h-4 w-4 text-destructive\" />\n </Button>\n </div>\n </div>\n\n {sp.baseUrl && (\n <div className=\"text-xs text-muted-foreground\">\n <Globe className=\"h-3 w-3 inline mr-1\" />\n {sp.baseUrl}\n </div>\n )}\n\n {/* API Keys */}\n <div className=\"space-y-2\">\n <div className=\"flex justify-between items-center\">\n <span className=\"text-sm font-medium\">API Keys</span>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setShowAddKeyForm(showAddKeyForm === sp.id ? null : sp.id)}\n >\n <Plus className=\"h-3 w-3 mr-1\" />\n Add Key\n </Button>\n </div>\n\n {sp.apiKeys.length === 0 && !showAddKeyForm && (\n <p className=\"text-xs text-muted-foreground\">No keys configured</p>\n )}\n\n {sp.apiKeys.map((key) => (\n <div key={key.label} className=\"flex items-center justify-between p-2 bg-muted/50 rounded\">\n <div>\n <span className=\"text-sm font-medium\">{key.label}</span>\n {key.isActive && (\n <span className=\"ml-2 text-xs bg-green-500/10 text-green-600 px-1.5 py-0.5 rounded\">\n Active\n </span>\n )}\n <div className=\"text-xs text-muted-foreground font-mono\">{key.maskedKey}</div>\n </div>\n <div className=\"flex gap-1\">\n {!key.isActive && (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onSetActiveKey(sp.id, key.label)}>\n Set Active\n </Button>\n )}\n <Button size=\"icon\" variant=\"ghost\" onClick={() => onDeleteKey(sp.id, key.label)}>\n <Trash2 className=\"h-3 w-3 text-destructive\" />\n </Button>\n </div>\n </div>\n ))}\n\n {/* Add Key Form */}\n {showAddKeyForm === sp.id && (\n <div className=\"p-3 border rounded space-y-2 bg-background\">\n <Input\n placeholder=\"Key label (e.g. default, production)\"\n value={newKeyLabel}\n onChange={(e) => setNewKeyLabel(e.target.value)}\n />\n <div className=\"flex gap-2\">\n <Input\n type={showNewKeyValue ? 'text' : 'password'}\n placeholder=\"API key\"\n value={newKeyValue}\n onChange={(e) => setNewKeyValue(e.target.value)}\n />\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={() => setShowNewKeyValue(!showNewKeyValue)}\n >\n {showNewKeyValue ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n </Button>\n </div>\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n onClick={() => handleAddKey(sp.id)}\n disabled={!newKeyLabel.trim() || !newKeyValue.trim()}\n >\n Save Key\n </Button>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => {\n setShowAddKeyForm(null);\n setNewKeyLabel('');\n setNewKeyValue('');\n }}\n >\n Cancel\n </Button>\n </div>\n </div>\n )}\n </div>\n </div>\n ))\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { useConfigStore } from '@/stores';\nimport { CheckCircle2, Cpu, Loader2, RefreshCw } from 'lucide-react';\nimport { Button } from '../ui/button';\n\ninterface CatalogModel {\n id: string;\n name: string;\n releaseDate?: string;\n contextWindow?: number;\n inputCost?: number;\n outputCost?: number;\n capabilities: string[];\n}\n\ninterface CatalogProvider {\n id: string;\n name: string;\n}\n\nexport interface ModelSectionProps {\n /** Current provider id. */\n provider: string;\n /** Provider → models cache. */\n catalogModels: Record<string, CatalogModel[]>;\n /** The current catalog provider object (for displaying name). */\n currentCatalogProvider: CatalogProvider | undefined;\n /** Loading flag. */\n isLoadingModels: boolean;\n setIsLoadingModels: (v: boolean) => void;\n /** Called when a model is selected. */\n onModelSelect: (modelId: string) => void;\n /** Refresh model list from backend. */\n refreshModels: (providerId: string) => void;\n}\n\nexport function ModelSection({\n provider,\n catalogModels,\n currentCatalogProvider,\n isLoadingModels,\n setIsLoadingModels,\n onModelSelect,\n refreshModels,\n}: ModelSectionProps) {\n const model = useConfigStore((s) => s.model);\n\n return (\n <div className=\"space-y-4\">\n {provider ? (\n <>\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm font-medium\">\n {currentCatalogProvider?.name || provider}\n </p>\n <p className=\"text-xs text-muted-foreground\">{provider}</p>\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => {\n setIsLoadingModels(true);\n refreshModels(provider);\n }}\n >\n <RefreshCw className={cn('h-4 w-4', isLoadingModels && 'animate-spin')} />\n </Button>\n </div>\n\n {isLoadingModels && !catalogModels[provider] ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n <span className=\"ml-2 text-muted-foreground\">Loading models...</span>\n </div>\n ) : (\n <div className=\"space-y-1\">\n {(catalogModels[provider] || []).map((m) => (\n <button\n type=\"button\"\n key={m.id}\n onClick={() => onModelSelect(m.id)}\n className={cn(\n 'w-full flex items-center justify-between p-3 rounded-lg border text-left transition-all',\n model === m.id\n ? 'border-primary bg-primary/5 ring-2 ring-primary/20'\n : 'border-border hover:bg-muted',\n )}\n >\n <div>\n <span className=\"font-medium\">{m.name || m.id}</span>\n <div className=\"flex gap-2 mt-1\">\n {m.capabilities.map((cap) => (\n <span key={cap} className=\"text-xs bg-muted px-1.5 py-0.5 rounded\">\n {cap}\n </span>\n ))}\n </div>\n </div>\n <div className=\"text-right text-xs text-muted-foreground\">\n {m.contextWindow && <div>{m.contextWindow / 1000}k context</div>}\n {m.inputCost && m.outputCost && (\n <div>\n ${m.inputCost}/${m.outputCost}\n </div>\n )}\n {model === m.id && (\n <CheckCircle2 className=\"h-4 w-4 text-primary mt-1\" />\n )}\n </div>\n </button>\n ))}\n\n {catalogModels[provider]?.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n No models found for this provider. The catalog might be empty or still\n loading.\n </p>\n )}\n </div>\n )}\n </>\n ) : (\n <div className=\"text-center py-8 text-muted-foreground\">\n <Cpu className=\"h-8 w-8 mx-auto mb-2 opacity-50\" />\n <p>Select a provider first</p>\n </div>\n )}\n </div>\n );\n}\n","import { useUIStore } from '@/stores';\nimport { Keyboard, X } from 'lucide-react';\nimport { useEffect } from 'react';\n\ninterface Shortcut {\n keys: string[];\n description: string;\n}\n\nconst SHORTCUTS: Array<{ section: string; items: Shortcut[] }> = [\n {\n section: 'Global',\n items: [\n { keys: ['Ctrl', 'K'], description: 'Open command palette' },\n { keys: ['?'], description: 'Show this shortcuts overlay' },\n { keys: ['Ctrl', '\\\\'], description: 'Toggle sidebar' },\n { keys: ['Ctrl', '/'], description: 'Focus the message input' },\n ],\n },\n {\n section: 'Chat input',\n items: [\n { keys: ['Enter'], description: 'Send message' },\n { keys: ['Shift', 'Enter'], description: 'Insert a newline' },\n { keys: ['↑'], description: 'Recall previous prompt (in empty input)' },\n { keys: ['↓'], description: 'Recall next prompt' },\n { keys: ['/'], description: 'Open slash command popup' },\n { keys: ['Tab'], description: 'Autocomplete highlighted command' },\n { keys: ['Esc'], description: 'Dismiss popup / clear input' },\n ],\n },\n {\n section: 'Chat',\n items: [\n { keys: ['Ctrl', 'F'], description: 'Search within current chat' },\n { keys: ['Ctrl', 'L'], description: 'Clear context (same as /clear)' },\n { keys: ['Ctrl', 'N'], description: 'Start a new session (same as /new)' },\n { keys: ['Ctrl', 'E'], description: 'Export chat as markdown' },\n { keys: ['Ctrl', 'M'], description: 'Quick model switcher overlay' },\n { keys: ['Ctrl', 'Shift', 'D'], description: 'Toggle compact UI density' },\n { keys: ['Esc'], description: 'Abort the current run (when running)' },\n ],\n },\n {\n section: 'Chat navigation (when not typing)',\n items: [\n { keys: ['j'], description: 'Focus next message (alias: ↓)' },\n { keys: ['k'], description: 'Focus previous message (alias: ↑)' },\n { keys: ['g'], description: 'Jump to first message' },\n { keys: ['Shift', 'G'], description: 'Jump to last message' },\n { keys: ['c'], description: 'Copy focused message text' },\n { keys: ['Esc'], description: 'Clear focused message' },\n ],\n },\n];\n\nexport function ShortcutsOverlay() {\n const open = useUIStore((s) => s.shortcutsOpen);\n const setOpen = useUIStore((s) => s.setShortcutsOpen);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n // \"?\" — but only when the user isn't typing in an input. Otherwise\n // typing a literal \"?\" into the chat would open this overlay.\n const target = e.target as HTMLElement | null;\n const tag = target?.tagName?.toLowerCase();\n const isTyping = tag === 'input' || tag === 'textarea' || target?.isContentEditable;\n if (!isTyping && e.key === '?' && !e.ctrlKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n setOpen(!useUIStore.getState().shortcutsOpen);\n return;\n }\n if (e.key === 'Escape' && useUIStore.getState().shortcutsOpen) {\n e.preventDefault();\n setOpen(false);\n }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [setOpen]);\n\n if (!open) return null;\n\n return (\n <div\n className=\"fixed inset-0 z-50 bg-background/60 backdrop-blur-sm flex items-center justify-center px-4\"\n onClick={() => setOpen(false)}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setOpen(false);\n }}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n className=\"w-full max-w-2xl rounded-xl border bg-popover shadow-2xl overflow-hidden flex flex-col max-h-[80vh]\"\n >\n <div className=\"flex items-center justify-between px-5 py-4 border-b\">\n <div className=\"flex items-center gap-2\">\n <Keyboard className=\"h-4 w-4 text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold\">Keyboard shortcuts</h2>\n </div>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className=\"text-muted-foreground hover:text-foreground p-1 rounded hover:bg-muted\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n <div className=\"overflow-y-auto px-5 py-4 space-y-6\">\n {SHORTCUTS.map((group) => (\n <div key={group.section}>\n <div className=\"text-[10px] uppercase tracking-wider text-muted-foreground mb-2\">\n {group.section}\n </div>\n <div className=\"grid grid-cols-1 gap-1.5\">\n {group.items.map((s) => (\n <div\n key={s.description}\n className=\"flex items-center justify-between gap-3 text-sm px-2 py-1.5 rounded hover:bg-muted/40\"\n >\n <span className=\"text-foreground/80\">{s.description}</span>\n <span className=\"flex items-center gap-1 shrink-0\">\n {s.keys.map((k, ki) => (\n <span key={k} className=\"flex items-center gap-1\">\n {ki > 0 && <span className=\"text-muted-foreground/40 text-xs\">+</span>}\n <kbd className=\"font-mono text-[10px] border rounded px-1.5 py-0.5 bg-background\">\n {k}\n </kbd>\n </span>\n ))}\n </span>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n <div className=\"border-t px-5 py-3 text-xs text-muted-foreground\">\n Press{' '}\n <kbd className=\"font-mono text-[10px] border rounded px-1 py-0.5 bg-background\">?</kbd>{' '}\n any time to reopen this list.\n </div>\n </div>\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { useConfigStore, useHistoryStore, useSessionStore, useUIStore } from '@/stores';\nimport {\n History,\n MessageSquare,\n PanelLeftClose,\n Settings as SettingsIcon,\n Zap,\n} from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { Button } from '../ui/button';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs';\nimport { ConfigSection } from './ConfigSection.js';\nimport { SessionActions } from './SessionActions.js';\nimport { SessionList } from './SessionList.js';\n\nexport function Sidebar() {\n const { toggleSidebar, currentView, setCurrentView } = useUIStore();\n const sidebarWidth = useUIStore((s) => s.sidebarWidth);\n const setSidebarWidth = useUIStore((s) => s.setSidebarWidth);\n const { wsConnected, wsUrl } = useConfigStore();\n const { entries: historyEntries, loading: historyLoading, error: historyError } = useHistoryStore();\n const { listSessions, deleteSession, resumeSession, client } = useWebSocket();\n const session = useSessionStore((s) => s.session);\n\n const [historyQuery, setHistoryQuery] = useState('');\n const activeSessionId = session?.id;\n\n useEffect(() => {\n if (wsConnected) client?.getTodos?.();\n }, [wsConnected, client]);\n\n useEffect(() => {\n void activeSessionId;\n if (currentView === 'history' && wsConnected) listSessions(50);\n }, [currentView, wsConnected, activeSessionId, listSessions]);\n\n const formatDuration = (start: number | null) => {\n if (!start) return '--';\n const seconds = Math.floor((Date.now() - start) / 1000);\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n return `${minutes}m`;\n };\n\n // Drag handle\n const startDrag = (e: React.MouseEvent) => {\n e.preventDefault();\n const startX = e.clientX;\n const startWidth = sidebarWidth;\n const onMove = (ev: MouseEvent) => { setSidebarWidth(startWidth + (ev.clientX - startX)); };\n const onUp = () => {\n window.removeEventListener('mousemove', onMove);\n window.removeEventListener('mouseup', onUp);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n };\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', onUp);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n };\n\n return (\n <aside style={{ width: `${sidebarWidth}px` }} className=\"relative border-r bg-card flex flex-col shrink-0\">\n {/* Drag handle */}\n <div\n onMouseDown={startDrag}\n onDoubleClick={() => setSidebarWidth(288)}\n className=\"group/handle absolute top-0 right-0 h-full w-2 cursor-col-resize z-10 flex items-center justify-end\"\n title=\"Drag to resize · double-click to reset\"\n >\n <div className=\"h-full w-px bg-border group-hover/handle:bg-primary/60 group-hover/handle:w-0.5 transition-all\" />\n <div className=\"absolute right-0 top-1/2 -translate-y-1/2 flex flex-col gap-0.5 opacity-0 group-hover/handle:opacity-100 transition-opacity pr-0.5\">\n <span className=\"h-1 w-1 rounded-full bg-primary/70\" />\n <span className=\"h-1 w-1 rounded-full bg-primary/70\" />\n <span className=\"h-1 w-1 rounded-full bg-primary/70\" />\n </div>\n </div>\n\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"relative w-7 h-7 rounded-md bg-primary flex items-center justify-center shadow-[0_0_0_1px_hsl(var(--primary)/0.4),0_2px_8px_-2px_hsl(var(--primary)/0.5)]\">\n <Zap className=\"h-4 w-4 text-primary-foreground\" strokeWidth={2.4} />\n </div>\n <div className=\"flex flex-col leading-none\">\n <span className=\"text-sm font-semibold tracking-tight\">WrongStack</span>\n <span className=\"flex items-center gap-1 text-[10px] text-muted-foreground mt-0.5\">\n <span className={cn('led', wsConnected ? 'text-[hsl(var(--success))] led-pulse' : 'text-[hsl(var(--warning))]')} />\n <span className=\"tabular font-medium uppercase tracking-wider\">{wsConnected ? 'online' : 'offline'}</span>\n </span>\n </div>\n </div>\n <Button variant=\"ghost\" size=\"icon\" onClick={toggleSidebar} title=\"Collapse sidebar (Ctrl+\\\\)\">\n <PanelLeftClose className=\"h-4 w-4\" />\n </Button>\n </div>\n\n <Tabs value={currentView === 'settings' ? 'chat' : currentView} onValueChange={(v) => setCurrentView(v as 'chat' | 'history')} className=\"flex-1 flex flex-col\">\n <TabsList className=\"w-full rounded-none bg-transparent p-2 h-auto grid grid-cols-2\">\n <TabsTrigger value=\"chat\" className=\"flex-col gap-1.5 py-2 data-[state=active]:bg-primary/10\">\n <MessageSquare className=\"h-4 w-4\" /><span className=\"text-xs\">Chat</span>\n </TabsTrigger>\n <TabsTrigger value=\"history\" className=\"flex-col gap-1.5 py-2 data-[state=active]:bg-primary/10\">\n <History className=\"h-4 w-4\" /><span className=\"text-xs\">History</span>\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"chat\" className=\"flex-1 flex flex-col m-0 overflow-hidden\">\n <ConfigSection formatDuration={formatDuration} />\n <SessionActions wsConnected={wsConnected} />\n <div className=\"flex-1\" />\n <div className=\"px-3 py-3 border-t\">\n <Button variant=\"ghost\" size=\"sm\" className=\"w-full justify-start\" onClick={() => setCurrentView('settings')}>\n <SettingsIcon className=\"h-4 w-4 mr-2\" />Settings\n </Button>\n </div>\n </TabsContent>\n\n <TabsContent value=\"history\" className=\"flex-1 m-0 flex flex-col overflow-hidden\">\n <SessionList\n historyQuery={historyQuery}\n setHistoryQuery={setHistoryQuery}\n historyEntries={historyEntries}\n historyLoading={historyLoading}\n historyError={historyError}\n wsConnected={wsConnected}\n listSessions={listSessions}\n resumeSession={resumeSession}\n deleteSession={deleteSession}\n />\n </TabsContent>\n </Tabs>\n </aside>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useChatStore, useConfigStore, useSessionStore, useUIStore } from '@/stores';\nimport {\n CheckCircle2,\n Circle,\n CircleDot,\n Database,\n ListTodo,\n Pin,\n Wifi,\n WifiOff,\n} from 'lucide-react';\nimport { Button } from '../ui/button';\n\ninterface ConfigSectionProps {\n formatDuration: (start: number | null) => string;\n}\n\nexport function ConfigSection({ formatDuration }: ConfigSectionProps) {\n const { wsConnected, wsUrl, provider, model } = useConfigStore();\n const { totalTokens, cost, session, todos } = useSessionStore();\n const { messages } = useChatStore();\n const pinnedIds = useUIStore((s) => s.pinnedIds);\n const unpinAll = useUIStore((s) => s.unpinAll);\n const setCurrentView = useUIStore((s) => s.setCurrentView);\n\n const pinnedRows = pinnedIds\n .map((id) => messages.find((m) => m.id === id))\n .filter((m): m is NonNullable<typeof m> => !!m && m.content.length > 0);\n\n return (\n <>\n {/* Connection status */}\n <div className=\"px-4 py-3 border-b\">\n <div className={cn('flex items-center gap-2 px-3 py-2 rounded-lg text-sm', wsConnected ? 'bg-green-500/10 text-green-600 dark:text-green-400' : 'bg-yellow-500/10 text-yellow-600 dark:text-yellow-400')}>\n {wsConnected ? <Wifi className=\"h-4 w-4\" /> : <WifiOff className=\"h-4 w-4\" />}\n <span className=\"font-medium\">{wsConnected ? 'Connected' : 'Disconnected'}</span>\n </div>\n <div className=\"text-xs text-muted-foreground mt-2 px-1 font-mono\">{wsUrl}</div>\n </div>\n\n {/* Active model */}\n <button type=\"button\" onClick={() => setCurrentView('settings')} className=\"px-4 py-3 border-b text-left hover:bg-muted/40 transition-colors\">\n <div className=\"text-[10px] uppercase tracking-wider text-muted-foreground mb-1\">Active model</div>\n <div className=\"font-mono text-xs truncate\">\n <span className=\"text-muted-foreground\">{provider || '—'}</span>\n <span className=\"text-muted-foreground/40 mx-1\">/</span>\n <span className=\"font-medium\">{model || '—'}</span>\n </div>\n </button>\n\n {/* Session Stats */}\n <div className=\"px-4 py-3 border-b space-y-3\">\n <h3 className=\"text-sm font-medium flex items-center gap-2\">\n <Database className=\"h-4 w-4 text-muted-foreground\" />\n Session\n </h3>\n <div className=\"grid grid-cols-2 gap-2 text-xs\">\n <div className=\"flex flex-col p-2 rounded-lg bg-muted/50\">\n <span className=\"text-muted-foreground\">Messages</span>\n <span className=\"text-lg font-semibold\">{messages.length}</span>\n </div>\n <div className=\"flex flex-col p-2 rounded-lg bg-muted/50\">\n <span className=\"text-muted-foreground\">Duration</span>\n <span className=\"text-lg font-semibold\">{formatDuration(session?.startedAt ?? null)}</span>\n </div>\n <div className=\"flex flex-col p-2 rounded-lg bg-muted/50\">\n <span className=\"text-muted-foreground\">Input</span>\n <span className=\"text-lg font-semibold\">{totalTokens.input.toLocaleString()}</span>\n </div>\n <div className=\"flex flex-col p-2 rounded-lg bg-muted/50\">\n <span className=\"text-muted-foreground\">Output</span>\n <span className=\"text-lg font-semibold\">{totalTokens.output.toLocaleString()}</span>\n </div>\n </div>\n {cost > 0 && (\n <div className=\"flex justify-between items-center p-2 rounded-lg bg-green-500/10\">\n <span className=\"text-sm text-muted-foreground\">Cost</span>\n <span className=\"text-lg font-semibold text-green-600 dark:text-green-400\">${cost.toFixed(4)}</span>\n </div>\n )}\n </div>\n\n {/* Live TODO list */}\n {todos.length > 0 && (() => {\n const done = todos.filter((t) => t.status === 'completed').length;\n const running = todos.filter((t) => t.status === 'in_progress').length;\n const pct = todos.length > 0 ? Math.round((done / todos.length) * 100) : 0;\n const allDone = done === todos.length;\n return (\n <div className=\"px-4 py-3 border-b space-y-2.5\">\n <h3 className=\"text-sm font-medium flex items-center justify-between\">\n <span className=\"flex items-center gap-2\"><ListTodo className=\"h-4 w-4 text-muted-foreground\" />Plan</span>\n <span className=\"tabular text-[10px] text-muted-foreground\">{done}/{todos.length}</span>\n </h3>\n <div className={cn('relative h-1.5 w-full overflow-hidden rounded-full bg-muted', running > 0 && 'bar-sweep')} title={`${pct}% complete`}>\n <div className={cn('h-full rounded-full transition-all duration-500', allDone ? 'bg-[hsl(var(--success))]' : 'bg-primary')} style={{ width: `${Math.max(pct, running > 0 ? 4 : 0)}%` }} />\n </div>\n <ul className=\"space-y-0.5 max-h-56 overflow-y-auto pr-1 -mx-1\">\n {todos.map((t) => {\n const Icon = t.status === 'completed' ? CheckCircle2 : t.status === 'in_progress' ? CircleDot : Circle;\n const active = t.status === 'in_progress';\n const tone = t.status === 'completed' ? 'text-[hsl(var(--success))] line-through opacity-60' : active ? 'text-foreground' : 'text-muted-foreground';\n return (\n <li key={t.id} className={cn('flex items-start gap-2 text-xs leading-snug rounded-md px-1.5 py-1 transition-colors', active && 'bg-primary/10 ring-1 ring-inset ring-primary/20', tone)}>\n <Icon className={cn('h-3.5 w-3.5 mt-0.5 shrink-0', active && 'text-primary animate-pulse')} />\n <span className=\"break-words\">{active && t.activeForm ? t.activeForm : t.content}</span>\n </li>\n );\n })}\n </ul>\n </div>\n );\n })()}\n\n {/* Pinned answers */}\n {pinnedRows.length > 0 && (\n <div className=\"px-4 py-3 border-b space-y-2\">\n <h3 className=\"text-sm font-medium flex items-center justify-between\">\n <span className=\"flex items-center gap-2\"><Pin className=\"h-4 w-4 text-amber-500\" />Pinned</span>\n <button type=\"button\" onClick={unpinAll} className=\"text-[10px] text-muted-foreground hover:text-destructive\">Clear</button>\n </h3>\n <ul className=\"space-y-1 max-h-48 overflow-y-auto pr-1\">\n {pinnedRows.map((m) => {\n const preview = m.content.replace(/\\s+/g, ' ').slice(0, 80);\n return (\n <li key={m.id}>\n <button\n type=\"button\"\n onClick={() => {\n const el = document.querySelector(`[data-message-id=\"${m.id}\"]`);\n if (!el) return;\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n el.classList.add('ring-2', 'ring-amber-500/60');\n setTimeout(() => { el.classList.remove('ring-2', 'ring-amber-500/60'); }, 1600);\n }}\n className=\"w-full text-left text-xs px-2 py-1.5 rounded bg-muted/40 hover:bg-muted/70 border border-amber-500/20 leading-snug\"\n title={m.content.slice(0, 400)}\n >\n {preview}{m.content.length > 80 ? '…' : ''}\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { useChatStore } from '@/stores';\nimport { Database, RotateCcw, Trash2 } from 'lucide-react';\nimport { Button } from '../ui/button';\n\ninterface SessionActionsProps {\n wsConnected: boolean;\n}\n\nexport function SessionActions({ wsConnected }: SessionActionsProps) {\n const clearMessages = useChatStore((s) => s.clearMessages);\n const { client } = useWebSocket();\n\n return (\n <div className=\"px-4 py-3 border-b space-y-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full justify-start text-destructive hover:text-destructive\"\n onClick={() => { clearMessages(); client?.clearContext?.(); }}\n >\n <Trash2 className=\"h-4 w-4 mr-2\" />\n Clear context\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full justify-start\"\n onClick={() => client?.newSession?.()}\n disabled={!wsConnected}\n >\n <RotateCcw className=\"h-4 w-4 mr-2\" />\n New session\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full justify-start\"\n onClick={() => client?.compactContext?.()}\n disabled={!wsConnected}\n >\n <Database className=\"h-4 w-4 mr-2\" />\n Compact context\n </Button>\n </div>\n );\n}\n","import type { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { type useHistoryStore, useUIStore } from '@/stores';\nimport {\n History,\n Loader2,\n RefreshCw,\n Search,\n Star,\n Trash2,\n X,\n} from 'lucide-react';\nimport { useState } from 'react';\nimport { ScrollArea } from '../ui/scroll-area';\n\ninterface SessionListProps {\n historyQuery: string;\n setHistoryQuery: (v: string) => void;\n historyEntries: ReturnType<typeof useHistoryStore.getState>['entries'];\n historyLoading: boolean;\n historyError: string | null;\n wsConnected: boolean;\n listSessions: ReturnType<typeof useWebSocket>['listSessions'];\n resumeSession: ReturnType<typeof useWebSocket>['resumeSession'];\n deleteSession: ReturnType<typeof useWebSocket>['deleteSession'];\n}\n\nconst formatRelative = (iso: string): string => {\n const ts = Date.parse(iso);\n if (Number.isNaN(ts)) return '';\n const diff = Date.now() - ts;\n if (diff < 60_000) return 'just now';\n if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m ago`;\n if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h ago`;\n const days = Math.floor(diff / 86_400_000);\n if (days < 7) return `${days}d ago`;\n return new Date(ts).toLocaleDateString();\n};\n\nexport function SessionList({\n historyQuery,\n setHistoryQuery,\n historyEntries,\n historyLoading,\n historyError,\n wsConnected,\n listSessions,\n resumeSession,\n deleteSession,\n}: SessionListProps) {\n const favoriteSessionIds = useUIStore((s) => s.favoriteSessionIds);\n const toggleFavoriteSession = useUIStore((s) => s.toggleFavoriteSession);\n const sessionNicknames = useUIStore((s) => s.sessionNicknames);\n const setSessionNickname = useUIStore((s) => s.setSessionNickname);\n const [renamingId, setRenamingId] = useState<string | null>(null);\n const [renameDraft, setRenameDraft] = useState('');\n\n const groupedHistory = (() => {\n const q = historyQuery.trim().toLowerCase();\n const filtered = q\n ? historyEntries.filter(\n (e) =>\n e.title.toLowerCase().includes(q) ||\n e.model.toLowerCase().includes(q) ||\n e.provider.toLowerCase().includes(q) ||\n e.id.toLowerCase().includes(q),\n )\n : historyEntries;\n const startOfDay = new Date();\n startOfDay.setHours(0, 0, 0, 0);\n const todayStart = startOfDay.getTime();\n const yesterdayStart = todayStart - 86_400_000;\n const weekStart = todayStart - 6 * 86_400_000;\n const buckets = { today: [] as typeof historyEntries, yesterday: [] as typeof historyEntries, week: [] as typeof historyEntries, older: [] as typeof historyEntries };\n for (const e of filtered) {\n const ts = Date.parse(e.startedAt);\n if (Number.isNaN(ts)) { buckets.older.push(e); continue; }\n if (ts >= todayStart) buckets.today.push(e);\n else if (ts >= yesterdayStart) buckets.yesterday.push(e);\n else if (ts >= weekStart) buckets.week.push(e);\n else buckets.older.push(e);\n }\n const favSet = new Set(favoriteSessionIds);\n const favorites = filtered.filter((e) => favSet.has(e.id));\n const out: Array<{ label: string; rows: typeof historyEntries; star?: boolean }> = [];\n if (favorites.length) out.push({ label: 'Favorites', rows: favorites, star: true });\n const dedupe = (arr: typeof historyEntries) => arr.filter((e) => !favSet.has(e.id));\n const today = dedupe(buckets.today);\n const yesterday = dedupe(buckets.yesterday);\n const week = dedupe(buckets.week);\n const older = dedupe(buckets.older);\n if (today.length) out.push({ label: 'Today', rows: today });\n if (yesterday.length) out.push({ label: 'Yesterday', rows: yesterday });\n if (week.length) out.push({ label: 'This week', rows: week });\n if (older.length) out.push({ label: 'Earlier', rows: older });\n return out;\n })();\n\n return (\n <>\n <div className=\"flex items-center justify-between px-4 py-2 border-b\">\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground\">Recent sessions</span>\n <button\n type=\"button\"\n className=\"h-6 w-6 inline-flex items-center justify-center rounded-md hover:bg-muted\"\n onClick={() => listSessions(50)}\n disabled={!wsConnected}\n title=\"Refresh\"\n >\n {historyLoading ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" /> : <RefreshCw className=\"h-3.5 w-3.5\" />}\n </button>\n </div>\n {historyEntries.length > 3 && (\n <div className=\"px-3 py-2 border-b\">\n <div className=\"relative\">\n <Search className=\"absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground/60\" />\n <input\n type=\"text\"\n value={historyQuery}\n onChange={(e) => setHistoryQuery(e.target.value)}\n placeholder=\"Filter title, model, provider…\"\n className=\"w-full pl-7 pr-7 py-1 text-xs rounded-md bg-muted/40 border border-transparent focus:bg-background focus:border-input focus:outline-none focus:ring-1 focus:ring-ring placeholder:text-muted-foreground/50\"\n />\n {historyQuery && (\n <button type=\"button\" onClick={() => setHistoryQuery('')} className=\"absolute right-1 top-1/2 -translate-y-1/2 text-muted-foreground/60 hover:text-foreground p-0.5\" title=\"Clear filter\">\n <X className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n </div>\n )}\n {historyError && (\n <div className=\"px-4 py-2 text-xs text-destructive bg-destructive/5 border-b\">{historyError}</div>\n )}\n <ScrollArea className=\"flex-1\">\n {historyEntries.length === 0 && !historyLoading ? (\n <div className=\"text-center text-muted-foreground py-8 px-4\">\n <History className=\"h-8 w-8 mx-auto mb-3 opacity-20\" />\n <p className=\"text-sm font-medium\">No history yet</p>\n <p className=\"text-xs mt-1\">Your conversations will appear here</p>\n </div>\n ) : groupedHistory.length === 0 ? (\n <div className=\"text-center text-muted-foreground py-8 px-4\">\n <Search className=\"h-8 w-8 mx-auto mb-3 opacity-20\" />\n <p className=\"text-sm font-medium\">No matches</p>\n <p className=\"text-xs mt-1\">Try a different filter</p>\n </div>\n ) : (\n <div className=\"p-2 space-y-3\">\n {groupedHistory.map((group) => (\n <div key={group.label} className=\"space-y-1\">\n <div className={cn('sticky top-0 z-[1] px-1 pb-1 text-[10px] uppercase tracking-wider font-semibold bg-card/90 backdrop-blur-sm flex items-center gap-1', group.star ? 'text-amber-500' : 'text-muted-foreground/80')}>\n {group.star && <Star className=\"h-3 w-3 fill-current\" />}\n {group.label} <span className=\"text-muted-foreground/50 font-normal normal-case ml-1\">({group.rows.length})</span>\n </div>\n {group.rows.map((entry) => (\n <div key={entry.id} className={cn('group relative rounded-md border text-sm transition-colors', entry.isCurrent ? 'bg-primary/5 border-primary/40' : 'bg-card border-border/60 hover:bg-muted/40 hover:border-primary/40')}>\n <button\n type=\"button\"\n disabled={entry.isCurrent || renamingId === entry.id}\n onClick={() => resumeSession(entry.id)}\n onDoubleClick={(e) => { e.stopPropagation(); setRenamingId(entry.id); setRenameDraft(sessionNicknames[entry.id] ?? entry.title ?? ''); }}\n className=\"block w-full rounded-md px-3 py-2 pr-16 text-left disabled:cursor-default focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <div className=\"min-w-0 flex-1\">\n {renamingId === entry.id ? (\n <input\n value={renameDraft}\n onChange={(e) => setRenameDraft(e.target.value)}\n onClick={(e) => e.stopPropagation()}\n onBlur={() => { setSessionNickname(entry.id, renameDraft); setRenamingId(null); }}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); setSessionNickname(entry.id, renameDraft); setRenamingId(null); } else if (e.key === 'Escape') { e.preventDefault(); setRenamingId(null); } }}\n placeholder={entry.title || 'Nickname'}\n className=\"w-full text-sm bg-background border border-input rounded px-1.5 py-0.5 focus:outline-none focus:ring-1 focus:ring-ring\"\n />\n ) : (\n <div className=\"font-medium truncate text-foreground\" title={sessionNicknames[entry.id] ? `${sessionNicknames[entry.id]} — original: ${entry.title}` : `${entry.title}\\n\\nDouble-click to rename`}>\n {sessionNicknames[entry.id] || entry.title || '(empty)'}\n </div>\n )}\n <div className=\"text-[10px] text-muted-foreground font-mono truncate mt-0.5\">{entry.provider}/{entry.model}</div>\n <div className=\"flex items-center gap-2 text-[10px] text-muted-foreground/80 mt-0.5\">\n <span>{formatRelative(entry.startedAt)}</span>\n {entry.tokenTotal > 0 && <><span>·</span><span className=\"tabular-nums\">{entry.tokenTotal.toLocaleString()} tok</span></>}\n {entry.isCurrent && <><span>·</span><span className=\"text-primary font-medium\">active</span></>}\n </div>\n </div>\n </button>\n <div className=\"absolute right-2 top-2 flex items-center gap-1\">\n <button type=\"button\" onClick={() => toggleFavoriteSession(entry.id)} className={cn('transition-opacity hover:text-amber-500', favoriteSessionIds.includes(entry.id) ? 'opacity-100 text-amber-500' : 'opacity-0 group-hover:opacity-100 text-muted-foreground')} title={favoriteSessionIds.includes(entry.id) ? 'Unfavorite' : 'Mark as favorite'}>\n <Star className={cn('h-3.5 w-3.5', favoriteSessionIds.includes(entry.id) && 'fill-current')} />\n </button>\n {!entry.isCurrent && (\n <button type=\"button\" onClick={() => { if (window.confirm(`Delete session \"${entry.title}\"?`)) deleteSession(entry.id); }} className=\"opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-destructive\" title=\"Delete session\">\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n ))}\n </div>\n )}\n </ScrollArea>\n </>\n );\n}\n"],"mappings":"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","names":["React","create","persist","create","persist","create","persist","create","create","create","useEffect","create","client","useEffect","client","useEffect","ArrowDown","ArrowUp","Bot","Cpu","Zap","useCallback","useEffect","useRef","useState","useCallback","useEffect","useRef","useState","useEffect","useRef","jsx","jsxs","useRef","useEffect","Icon","useEffect","useRef","useState","jsx","jsxs","client","jsx","jsx","jsxs","client","useState","useRef","useCallback","useEffect","tone","RotateCcw","useEffect","useState","jsx","jsxs","useEffect","useRef","useState","jsx","jsxs","useEffect","useRef","useState","Fragment","jsx","jsxs","CheckCircle2","ChevronDown","ChevronRight","Download","Pencil","RotateCcw","XCircle","memo","useState","useMemo","jsx","jsxs","DiffView","i","j","ChevronDown","memo","useMemo","useState","Fragment","jsx","jsxs","ToolResult","Check","useState","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","useState","Check","useState","jsx","jsxs","useState","jsx","jsxs","jsx","jsxs","memo","MessageBubble","useState","client","ChevronDown","ChevronRight","XCircle","CheckCircle2","Download","Pencil","RotateCcw","Check","ChevronDown","useEffect","useRef","useState","jsx","jsxs","Search","X","useEffect","useMemo","useRef","useState","jsx","jsxs","Monitor","Moon","Sun","useEffect","useState","jsx","jsx","Sun","Moon","Monitor","Icon","CheckCircle2","ChevronDown","ChevronRight","Loader2","Terminal","XCircle","memo","useState","jsx","jsxs","memo","ToolGroup","useState","Terminal","ChevronDown","ChevronRight","Loader2","XCircle","CheckCircle2","ArchiveRestore","Clock","Search","Sparkles","Wrench","useEffect","useState","Fragment","jsx","jsxs","client","Icon","React","jsx","jsxs","Brain","jsx","jsxs","Fragment","jsx","jsxs","useRef","useState","useCallback","useEffect","formatDuration","Zap","Cpu","ArrowDown","ArrowUp","Bot","useEffect","useState","jsx","jsxs","client","p","AlertTriangle","Terminal","Wrench","useEffect","useRef","X","React","jsx","jsxs","jsx","jsxs","X","jsx","jsxs","Terminal","Wrench","useRef","useEffect","Icon","AlertTriangle","Loader2","RotateCcw","WifiOff","X","useEffect","useState","jsx","jsxs","AlertTriangle","jsx","jsxs","AlertTriangle","Bot","ChevronDown","ChevronRight","Cpu","Wrench","Zap","useMemo","useState","jsx","jsxs","ArrowRight","Cpu","Search","useEffect","useMemo","useRef","useState","jsx","jsxs","client","Cpu","Globe","Monitor","Moon","Sun","X","useState","useEffect","useCallback","React","jsx","React","jsx","jsx","jsxs","CheckCircle2","Eye","Globe","Loader2","Trash2","useState","useCallback","Fragment","jsx","jsxs","useState","useCallback","Globe","Loader2","CheckCircle2","Trash2","Eye","CheckCircle2","Cpu","Loader2","RefreshCw","Fragment","jsx","jsxs","RefreshCw","Loader2","CheckCircle2","Cpu","jsx","jsxs","useState","useEffect","useCallback","X","Cpu","Globe","Sun","Moon","Monitor","Keyboard","X","useEffect","jsx","jsxs","History","SettingsIcon","Zap","useEffect","useState","CheckCircle2","Database","Pin","Wifi","WifiOff","Fragment","jsx","jsxs","formatDuration","Icon","tone","Database","RotateCcw","Trash2","jsx","jsxs","client","Trash2","RotateCcw","Database","Loader2","RefreshCw","Search","Trash2","X","useState","Fragment","jsx","jsxs","useState","Loader2","RefreshCw","Search","X","Trash2","jsx","jsxs","client","useState","useEffect","formatDuration","Zap","History","SettingsIcon","Fragment","jsx","jsxs","useEffect","jsx","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/main.tsx","../src/lib/favicon.ts","../src/lib/ws-client.ts","../src/stores/chat-store.ts","../src/stores/config-store.ts","../src/stores/session-store.ts","../src/stores/ui-store.ts","../src/stores/history-store.ts","../src/stores/worktree-store.ts","../src/stores/fleet-store.ts","../src/hooks/useWebSocket.ts","../src/lib/utils.ts","../src/components/Toaster.tsx","../src/lib/chime.ts","../src/lib/notify.ts","../src/hooks/ws-handlers.ts","../src/App.tsx","../src/components/ChatView/index.tsx","../src/components/ChatInput.tsx","../src/components/CommandPalette/index.tsx","../src/components/CommandPalette/export-utils.ts","../src/components/FilePicker.tsx","../src/components/ui/button.tsx","../src/components/ChatInput/slash-commands.ts","../src/components/ConnectionChip.tsx","../src/components/ContextModePicker.tsx","../src/components/CostChip.tsx","../src/lib/tool-summary.ts","../src/components/MessageBubble/index.tsx","../src/components/DiffView.tsx","../src/components/ToolResult.tsx","../src/components/MessageBubble/CopyButton.tsx","../src/components/MessageBubble/utils.tsx","../src/components/MessageBubble/ErrorBody.tsx","../src/components/MessageBubble/ToolInputView.tsx","../src/components/ModePicker.tsx","../src/components/SearchOverlay.tsx","../src/components/ThemeToggle.tsx","../src/components/ThemeProvider.tsx","../src/components/ToolGroup.tsx","../src/components/WelcomeScreen.tsx","../src/components/ui/scroll-area.tsx","../src/components/ChatView/utils.ts","../src/components/ChatView/ThinkingBubble.tsx","../src/components/CollabPanel.tsx","../src/components/ConfirmDialog.tsx","../src/components/ui/dialog.tsx","../src/components/ConnectionBanner.tsx","../src/components/ErrorBoundary.tsx","../src/components/FleetPanel.tsx","../src/components/QuickModelSwitcher.tsx","../src/components/SettingsPanel/index.tsx","../src/components/ui/input.tsx","../src/components/ui/tabs.tsx","../src/components/SettingsPanel/PreferenceToggle.tsx","../src/components/SettingsPanel/ProviderSection.tsx","../src/components/SettingsPanel/ModelSection.tsx","../src/components/ShortcutsOverlay.tsx","../src/components/Sidebar/index.tsx","../src/components/Sidebar/ConfigSection.tsx","../src/components/Sidebar/SessionActions.tsx","../src/components/Sidebar/SessionList.tsx","../src/components/TodosPanel.tsx"],"sourcesContent":["import React from 'react';\nimport ReactDOM from 'react-dom/client';\n// Self-hosted fonts (CSP-clean: served from 'self'). IBM Plex gives the UI an\n// engineering-instrument character — Plex Sans (variable) for UI text, Plex\n// Mono for data readouts, labels, and code.\nimport '@fontsource-variable/ibm-plex-sans';\nimport '@fontsource/ibm-plex-mono/400.css';\nimport '@fontsource/ibm-plex-mono/500.css';\nimport '@fontsource/ibm-plex-mono/600.css';\nimport { App } from './App';\nimport './index.css';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\nReactDOM.createRoot(expectDefined(document.getElementById('root'))).render(\n <React.StrictMode>\n <App />\n </React.StrictMode>,\n);\n","/**\n * Dynamic favicon helper. We don't ship a `.ico` file — the icon is built at\n * runtime as an inline SVG data URL so it can be re-rendered with or without\n * a status badge.\n *\n * setFaviconStatus('idle') → plain \"W\" mark\n * setFaviconStatus('running') → \"W\" + amber pulse dot (running indicator)\n * setFaviconStatus('ready') → \"W\" + green dot (run finished, tab hidden)\n * setFaviconStatus('error') → \"W\" + red dot (run failed, tab hidden)\n * setFaviconStatus('attention') → \"W\" + yellow dot (approval needed, tab hidden)\n *\n * The status auto-resets to 'idle' on the next visibilitychange where the\n * tab becomes visible — so the badge only persists while the user is away.\n */\n\nexport type FaviconStatus = 'idle' | 'running' | 'ready' | 'error' | 'attention';\n\nconst BASE_BG = '#4f46e5'; // indigo-600, matches the topbar Zap mark.\n\nfunction buildSvg(status: FaviconStatus): string {\n const badge = (() => {\n if (status === 'ready')\n return '<circle cx=\"50\" cy=\"14\" r=\"14\" fill=\"#22c55e\" stroke=\"#fff\" stroke-width=\"3\" />';\n if (status === 'error')\n return '<circle cx=\"50\" cy=\"14\" r=\"14\" fill=\"#ef4444\" stroke=\"#fff\" stroke-width=\"3\" />';\n if (status === 'running')\n return '<circle cx=\"50\" cy=\"14\" r=\"14\" fill=\"#f59e0b\" stroke=\"#fff\" stroke-width=\"3\" />';\n if (status === 'attention')\n return '<circle cx=\"50\" cy=\"14\" r=\"14\" fill=\"#eab308\" stroke=\"#fff\" stroke-width=\"3\"><animate attributeName=\"opacity\" values=\"1;0.3;1\" dur=\"1s\" repeatCount=\"indefinite\"/></circle>';\n return '';\n })();\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 64 64\">\n <rect x=\"2\" y=\"2\" width=\"60\" height=\"60\" rx=\"14\" fill=\"${BASE_BG}\" />\n <text x=\"32\" y=\"44\" text-anchor=\"middle\" font-family=\"-apple-system,Segoe UI,Roboto,sans-serif\" font-size=\"38\" font-weight=\"700\" fill=\"#fff\">W</text>\n ${badge}\n </svg>`;\n}\n\nfunction svgToDataUrl(svg: string): string {\n // encodeURIComponent keeps the URL valid across browsers; btoa would\n // also work but breaks on non-ASCII (not a concern here, but cleaner).\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;\n}\n\nfunction ensureLink(): HTMLLinkElement | null {\n if (typeof document === 'undefined') return null;\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"icon\"]');\n if (!link) {\n link = document.createElement('link');\n link.rel = 'icon';\n link.type = 'image/svg+xml';\n document.head.appendChild(link);\n }\n return link;\n}\n\nlet currentStatus: FaviconStatus = 'idle';\n\nexport function setFaviconStatus(status: FaviconStatus): void {\n currentStatus = status;\n const link = ensureLink();\n if (!link) return;\n link.href = svgToDataUrl(buildSvg(status));\n}\n\nlet visibilityHookInstalled = false;\n\n/** Install the visibilitychange listener once. When the user comes back to\n * the tab we clear any \"ready/error\" badge so they don't see a stale\n * notification dot after they've already returned. */\nexport function installFaviconVisibilityReset(): void {\n if (visibilityHookInstalled || typeof document === 'undefined') return;\n visibilityHookInstalled = true;\n document.addEventListener('visibilitychange', () => {\n if (!document.hidden && (currentStatus === 'ready' || currentStatus === 'error' || currentStatus === 'attention')) {\n setFaviconStatus('idle');\n }\n });\n}\n","import type { WSClientMessage, WSServerMessage } from '../types';\r\n\r\ntype EventHandler = (msg: WSServerMessage) => void;\r\n\r\ninterface PendingConfirm {\r\n resolve: (decision: 'yes' | 'no' | 'always' | 'deny') => void;\r\n}\r\n\r\n/** Internal connection lifecycle states the UI subscribes to. */\r\nexport type WsStatus =\r\n | { state: 'connecting' }\r\n | { state: 'open' }\r\n | { state: 'closed'; error?: string | undefined }\r\n | { state: 'reconnecting'; attempt: number; nextRetryAt: number; lastError?: string | undefined };\r\n\r\nconst WS_TOKEN_KEY = 'ws_token';\r\n\r\n/** Read wsToken from sessionStorage (survives page refresh, cleared on tab close). */\r\nfunction getStoredToken(): string | null {\r\n try {\r\n return sessionStorage.getItem(WS_TOKEN_KEY);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** Store wsToken in sessionStorage. */\r\nfunction setStoredToken(token: string): void {\r\n try {\r\n sessionStorage.setItem(WS_TOKEN_KEY, token);\r\n } catch {\r\n /* sessionStorage unavailable (private browsing quota, etc.) — degrade gracefully */\r\n }\r\n}\r\n\r\n/** Clear wsToken from sessionStorage. */\r\nfunction clearStoredToken(): void {\r\n try {\r\n sessionStorage.removeItem(WS_TOKEN_KEY);\r\n } catch {\r\n /* best-effort */\r\n }\r\n}\r\n\r\nexport class WrongStackWebSocketClient {\r\n private ws: WebSocket | null = null;\r\n private url: string;\r\n private handlers: Map<string, Set<EventHandler>> = new Map();\r\n private reconnectAttempts = 0;\r\n private maxReconnectAttempts = 10;\r\n private reconnectDelay = 1000;\r\n private shouldReconnect = true;\r\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\r\n private messageQueue: WSClientMessage[] = [];\r\n private pendingConfirms: Map<string, PendingConfirm> = new Map();\r\n private sessionId: string | null = null;\r\n /** Stored last close reason / error message so the UI can show \"what\r\n * went wrong\" while reconnecting instead of a generic spinner. */\r\n private lastErrorText: string | undefined;\r\n private statusListeners = new Set<(s: WsStatus) => void>();\r\n private currentStatus: WsStatus = { state: 'connecting' };\r\n\r\n onStatus(fn: (s: WsStatus) => void): () => void {\r\n this.statusListeners.add(fn);\r\n fn(this.currentStatus);\r\n return () => this.statusListeners.delete(fn);\r\n }\r\n\r\n get status(): WsStatus {\r\n return this.currentStatus;\r\n }\r\n\r\n private setStatus(s: WsStatus) {\r\n this.currentStatus = s;\r\n for (const fn of this.statusListeners) {\r\n try {\r\n fn(s);\r\n } catch {\r\n /* listener errors must not break the socket */\r\n }\r\n }\r\n }\r\n\r\n constructor(url?: string) {\r\n this.url = url ?? defaultWsUrl();\r\n }\r\n\r\n async connect(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n if (this.ws?.readyState === WebSocket.OPEN) {\r\n resolve();\r\n return;\r\n }\r\n\r\n this.setStatus({ state: 'connecting' });\r\n\r\n try {\r\n // Include auth token from sessionStorage if available (from session.start).\r\n // Initial connect to loopback is exempt, but reconnections should\r\n // carry the token for defense-in-depth.\r\n const storedToken = getStoredToken();\r\n const wsUrl = storedToken\r\n ? `${this.url}${this.url.includes('?') ? '&' : '?'}token=${storedToken}`\r\n : this.url;\r\n this.ws = new WebSocket(wsUrl);\r\n this.ws.binaryType = 'arraybuffer';\r\n\r\n const connectTimeout = setTimeout(() => {\r\n reject(new Error('Connection timeout'));\r\n }, 10000);\r\n\r\n // Track whether the connection was ever established so onerror and\r\n // onclose know whether to reject the promise or just attempt a\r\n // reconnect. Without this, a connection failure leaves callers\r\n // awaiting connect() hanging forever.\r\n let established = false;\r\n\r\n this.ws.onopen = () => {\r\n clearTimeout(connectTimeout);\r\n established = true;\r\n console.log('[WS Client] Connected');\r\n this.reconnectAttempts = 0;\r\n this.lastErrorText = undefined;\r\n this.setStatus({ state: 'open' });\r\n this.flushMessageQueue();\r\n resolve();\r\n };\r\n\r\n this.ws.onmessage = (event) => {\r\n try {\r\n const msg = JSON.parse(event.data) as WSServerMessage;\r\n this.handleMessage(msg);\r\n } catch (err) {\r\n console.error('[WS Client] Failed to parse message', err);\r\n }\r\n };\r\n\r\n this.ws.onerror = (error) => {\r\n console.error('[WS Client] Error', error);\r\n // ErrorEvent in browsers is intentionally opaque — Chrome won't\r\n // expose the underlying reason for security. We stash a generic\r\n // hint so the UI has something to display.\r\n this.lastErrorText = 'Connection error (see browser devtools)';\r\n if (!established) {\r\n clearTimeout(connectTimeout);\r\n reject(new Error(this.lastErrorText));\r\n }\r\n };\r\n\r\n this.ws.onclose = (ev) => {\r\n console.log('[WS Client] Disconnected', ev.code, ev.reason);\r\n if (!established) {\r\n clearTimeout(connectTimeout);\r\n const reason = ev.reason || `Closed with code ${ev.code}`;\r\n this.lastErrorText = reason;\r\n reject(new Error(reason));\r\n return;\r\n }\r\n if (ev.reason && !this.lastErrorText) {\r\n this.lastErrorText = `${ev.reason} (code ${ev.code})`;\r\n } else if (!this.lastErrorText && ev.code !== 1000) {\r\n this.lastErrorText = `Closed with code ${ev.code}`;\r\n }\r\n this.attemptReconnect();\r\n };\r\n } catch (err) {\r\n this.lastErrorText = err instanceof Error ? err.message : String(err);\r\n this.setStatus({ state: 'closed', error: this.lastErrorText });\r\n reject(err);\r\n }\r\n });\r\n }\r\n\r\n private attemptReconnect() {\r\n if (!this.shouldReconnect || this.reconnectAttempts >= this.maxReconnectAttempts) {\r\n console.log('[WS Client] Not reconnecting');\r\n this.reconnectTimer = null;\r\n this.setStatus({ state: 'closed', error: this.lastErrorText ?? 'Disconnected' });\r\n return;\r\n }\r\n\r\n this.reconnectAttempts++;\r\n const delay = Math.min(this.reconnectDelay * 2 ** (this.reconnectAttempts - 1), 30000);\r\n const nextRetryAt = Date.now() + delay;\r\n console.log(`[WS Client] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\r\n this.setStatus({\r\n state: 'reconnecting',\r\n attempt: this.reconnectAttempts,\r\n nextRetryAt,\r\n lastError: this.lastErrorText,\r\n });\r\n\r\n this.reconnectTimer = setTimeout(async () => {\r\n if (this.shouldReconnect) {\r\n try {\r\n await this.connect();\r\n } catch (err) {\r\n console.error('[WS Client] Reconnect failed', err);\r\n }\r\n }\r\n }, delay);\r\n }\r\n\r\n /** Force an immediate reconnect attempt, bypassing the backoff timer. */\r\n retryNow(): void {\r\n if (this.currentStatus.state === 'open') return;\r\n if (this.reconnectTimer) {\r\n clearTimeout(this.reconnectTimer);\r\n this.reconnectTimer = null;\r\n }\r\n this.reconnectAttempts = 0;\r\n void this.connect().catch(() => undefined);\r\n }\r\n\r\n private flushMessageQueue() {\r\n while (this.messageQueue.length > 0) {\r\n const msg = this.messageQueue.shift();\r\n if (msg) this.send(msg);\r\n }\r\n }\r\n\r\n private handleMessage(msg: WSServerMessage) {\r\n if (msg.type === 'tool.confirm_needed') {\r\n const payload = msg.payload as unknown as {\r\n id: string;\r\n toolName: string;\r\n input: unknown;\r\n suggestedPattern: string;\r\n resolve: (d: 'yes' | 'no' | 'always' | 'deny') => void;\r\n };\r\n\r\n this.pendingConfirms.set(payload.id, {\r\n resolve: payload.resolve,\r\n });\r\n\r\n const msgForHandler = {\r\n ...msg,\r\n payload: {\r\n ...payload,\r\n resolve: () => {},\r\n },\r\n };\r\n\r\n this.emit(msgForHandler as WSServerMessage);\r\n return;\r\n }\r\n\r\n if (msg.type === 'session.start') {\r\n const payload = msg.payload as { sessionId: string; wsToken?: string | undefined };\r\n this.sessionId = payload.sessionId;\r\n if (payload.wsToken) {\r\n setStoredToken(payload.wsToken);\r\n }\r\n }\r\n\r\n this.emit(msg);\r\n }\r\n\r\n private emit(msg: WSServerMessage) {\r\n const handlers = this.handlers.get(msg.type);\r\n if (handlers) {\r\n for (const handler of handlers) {\r\n try {\r\n handler(msg);\r\n } catch (err) {\r\n console.error(`[WS Client] Handler error for ${msg.type}`, err);\r\n }\r\n }\r\n }\r\n }\r\n\r\n send(message: WSClientMessage) {\r\n if (this.ws?.readyState === WebSocket.OPEN) {\r\n this.ws.send(JSON.stringify(message));\r\n } else {\r\n this.messageQueue.push(message);\r\n }\r\n }\r\n\r\n on(eventType: string, handler: EventHandler): () => void {\r\n let handlers = this.handlers.get(eventType);\r\n if (!handlers) {\r\n handlers = new Set();\r\n this.handlers.set(eventType, handlers);\r\n }\r\n handlers.add(handler);\r\n return () => handlers?.delete(handler);\r\n }\r\n\r\n off(eventType: string, handler: EventHandler) {\r\n this.handlers.get(eventType)?.delete(handler);\r\n }\r\n\r\n sendMessage(content: string): string {\r\n const id = `msg_${Date.now()}_${crypto.randomUUID().slice(0, 8)}`;\r\n this.send({\r\n type: 'user_message',\r\n payload: {\r\n id,\r\n content,\r\n timestamp: Date.now(),\r\n },\r\n });\r\n return id;\r\n }\r\n\r\n sendAbort() {\r\n this.send({\r\n type: 'abort',\r\n payload: {},\r\n } as unknown as WSClientMessage);\r\n }\r\n\r\n sendConfirm(id: string, decision: 'yes' | 'no' | 'always' | 'deny') {\r\n const pending = this.pendingConfirms.get(id);\r\n if (pending) {\r\n pending.resolve(decision);\r\n this.pendingConfirms.delete(id);\r\n }\r\n this.send({\r\n type: 'tool.confirm_result',\r\n payload: { id, decision },\r\n });\r\n }\r\n\r\n switchModel(provider: string, model: string) {\r\n this.send({\r\n type: 'model.switch',\r\n payload: { provider, model },\r\n });\r\n }\r\n\r\n // ---- Provider/Model/Key management (mirrors TUI/CLI auth-menu) ----\r\n\r\n listProviders() {\r\n this.send({ type: 'providers.list' });\r\n }\r\n\r\n listProviderModels(providerId: string) {\r\n this.send({ type: 'provider.models', payload: { providerId } });\r\n }\r\n\r\n listSavedProviders() {\r\n this.send({ type: 'providers.saved' });\r\n }\r\n\r\n addKey(providerId: string, label: string, apiKey: string) {\r\n this.send({ type: 'key.add', payload: { providerId, label, apiKey } });\r\n }\r\n\r\n updateKey(providerId: string, label: string, apiKey: string) {\r\n this.send({ type: 'key.update', payload: { providerId, label, apiKey } });\r\n }\r\n\r\n deleteKey(providerId: string, label: string) {\r\n this.send({ type: 'key.delete', payload: { providerId, label } });\r\n }\r\n\r\n setActiveKey(providerId: string, label: string) {\r\n this.send({ type: 'key.set_active', payload: { providerId, label } });\r\n }\r\n\r\n addProvider(id: string, family: string, baseUrl?: string | undefined, apiKey?: string) {\r\n this.send({ type: 'provider.add', payload: { id, family, baseUrl, apiKey } });\r\n }\r\n\r\n removeProvider(providerId: string) {\r\n this.send({ type: 'provider.remove', payload: { providerId } });\r\n }\r\n\r\n newSession() {\r\n this.send({ type: 'session.new' });\r\n }\r\n\r\n clearContext() {\r\n this.send({ type: 'context.clear' });\r\n }\r\n\r\n compactContext(aggressive = false) {\r\n this.send({ type: 'context.compact', payload: { aggressive } });\r\n }\r\n\r\n repairContext() {\r\n this.send({ type: 'context.repair' });\r\n }\r\n\r\n debugContext() {\r\n this.send({ type: 'context.debug' });\r\n }\r\n\r\n listContextModes() {\r\n this.send({ type: 'context.modes.list' });\r\n }\r\n\r\n switchContextMode(id: string) {\r\n this.send({ type: 'context.mode.switch', payload: { id } });\r\n }\r\n\r\n // ---- Inspect commands (mirror TUI/CLI's /tools /memory /skill /diag /stats) ----\r\n\r\n listTools() {\r\n this.send({ type: 'tools.list' });\r\n }\r\n\r\n listMemory() {\r\n this.send({ type: 'memory.list' });\r\n }\r\n\r\n remember(text: string, scope?: 'project-agents' | 'project-memory' | 'user-memory') {\r\n this.send({ type: 'memory.remember', payload: { text, scope } });\r\n }\r\n\r\n forget(text: string, scope?: 'project-agents' | 'project-memory' | 'user-memory') {\r\n this.send({ type: 'memory.forget', payload: { text, scope } });\r\n }\r\n\r\n listSkills() {\r\n this.send({ type: 'skills.list' });\r\n }\r\n\r\n getDiag() {\r\n this.send({ type: 'diag.get' });\r\n }\r\n\r\n getStats() {\r\n this.send({ type: 'stats.get' });\r\n }\r\n\r\n saveSession() {\r\n this.send({ type: 'session.save' });\r\n }\r\n\r\n resumeSessionById(id: string) {\r\n this.send({ type: 'session.resume', payload: { id } });\r\n }\r\n\r\n listModes() {\r\n this.send({ type: 'modes.list' });\r\n }\r\n\r\n switchMode(id: string) {\r\n this.send({ type: 'mode.switch', payload: { id } });\r\n }\r\n\r\n listFiles(query?: string, limit?: number) {\r\n this.send({ type: 'files.list', payload: { query, limit } });\r\n }\r\n\r\n getTodos() {\r\n this.send({ type: 'todos.get' });\r\n }\r\n\r\n clearTodos() {\r\n this.send({ type: 'todos.clear' });\r\n }\r\n\r\n removeTodo(idOrIndex: string | number) {\r\n const payload = typeof idOrIndex === 'number'\r\n ? { index: idOrIndex }\r\n : { id: idOrIndex };\r\n this.send({ type: 'todos.remove', payload });\r\n }\r\n\r\n listSessions(limit = 50) {\r\n this.send({ type: 'sessions.list', payload: { limit } });\r\n }\r\n\r\n deleteSession(id: string) {\r\n this.send({ type: 'session.delete', payload: { id } });\r\n }\r\n\r\n resumeSession(sessionId: string) {\r\n this.send({\r\n type: 'session.resume',\r\n payload: { id: sessionId },\r\n });\r\n }\r\n\r\n ping() {\r\n this.send({ type: 'ping' });\r\n }\r\n\r\n disconnect() {\r\n this.shouldReconnect = false;\r\n if (this.reconnectTimer) {\r\n clearTimeout(this.reconnectTimer);\r\n this.reconnectTimer = null;\r\n }\r\n this.ws?.close();\r\n this.ws = null;\r\n clearStoredToken();\r\n }\r\n\r\n get isConnected(): boolean {\r\n return this.ws?.readyState === WebSocket.OPEN;\r\n }\r\n\r\n get currentSessionId(): string | null {\r\n return this.sessionId;\r\n }\r\n}\r\n\r\nlet client: WrongStackWebSocketClient | null = null;\r\n\r\n/**\r\n * Default WS URL derived from the page's host.\r\n *\r\n * Subtle gotcha on Windows: when the page is loaded from `http://localhost:3456`,\r\n * the browser resolves `localhost` *itself* and on Windows it tries IPv6 `[::1]`\r\n * before IPv4 `127.0.0.1`. If the backend listens only on `127.0.0.1`, every\r\n * connection attempt to `ws://localhost:3457` first hits the IPv6 socket\r\n * (refused) and then either gives up or flaps — symptom: \"ws disconnect hep\".\r\n *\r\n * Fix: when the page is on a loopback host (`localhost` / `127.0.0.1` / `::1`),\r\n * force the WS URL to use the literal IPv4 loopback address. That bypasses the\r\n * DNS dance entirely. For any other hostname (LAN IP, custom WS_HOST override)\r\n * we keep the page's hostname so things still \"just work\".\r\n *\r\n * The WS port is NOT hardcoded: the HTTP server stamps the live port into the\r\n * served HTML as `<meta name=\"wrongstack-ws-port\">` (see http-server.ts), so\r\n * several WebUI instances can run on different PORT/WS_PORT pairs at once. We\r\n * fall back to 3457 only when the tag is absent (e.g. the vite dev server).\r\n */\r\nconst DEFAULT_WS_PORT = 3457;\r\n\r\nfunction resolveWsPort(): number {\r\n if (typeof document === 'undefined') return DEFAULT_WS_PORT;\r\n const raw = document\r\n .querySelector('meta[name=\"wrongstack-ws-port\"]')\r\n ?.getAttribute('content');\r\n const parsed = raw ? Number.parseInt(raw, 10) : Number.NaN;\r\n return Number.isFinite(parsed) && parsed > 0 && parsed < 65536 ? parsed : DEFAULT_WS_PORT;\r\n}\r\n\r\nfunction defaultWsUrl(): string {\r\n const port = resolveWsPort();\r\n if (typeof window === 'undefined' || !window.location?.hostname) {\r\n return `ws://127.0.0.1:${port}`;\r\n }\r\n const host = window.location.hostname.toLowerCase();\r\n if (host === 'localhost' || host === '127.0.0.1' || host === '[::1]' || host === '::1') {\r\n return `ws://127.0.0.1:${port}`;\r\n }\r\n return `ws://${window.location.hostname}:${port}`;\r\n}\r\n\r\nexport function getWSClient(url?: string): WrongStackWebSocketClient {\r\n if (!client) {\r\n client = new WrongStackWebSocketClient(url);\r\n }\r\n return client;\r\n}\r\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport type { ChatMessage } from './types.js';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\n/**\n * Strip immediately-repeated paragraphs/lines from an assistant reply.\n * MiniMax-M2.7 (and other smaller open models) sometimes emit the same\n * paragraph twice in one stream — we don't want that to land in the chat.\n * We only collapse *consecutive* duplicates so legitimate repetition\n * elsewhere in the message is preserved.\n */\nfunction dedupeRepeatedBlocks(text: string): string {\n if (!text) return text;\n const paraSplit = text.split(/\\n{2,}/);\n const paras: string[] = [];\n for (const p of paraSplit) {\n if (paras.length > 0 && paras[paras.length - 1]?.trim() === p.trim()) continue;\n paras.push(p);\n }\n const cleaned = paras.map((p) => {\n const lines = p.split('\\n');\n const out: string[] = [];\n for (const line of lines) {\n if (out.length > 0 && line.trim().length > 0 && out[out.length - 1]?.trim() === line.trim()) {\n continue;\n }\n out.push(line);\n }\n return out.join('\\n');\n });\n return cleaned.join('\\n\\n');\n}\n\n// ============================================\n// Chat Store\n// ============================================\n\ninterface ChatState {\n messages: ChatMessage[];\n currentAssistantMessageId: string | null;\n currentToolId: string | null;\n isLoading: boolean;\n abortController: AbortController | null;\n executions: Map<string, ToolExecution>;\n /** Messages typed while the agent was running. Drained one-at-a-time\n * after run.result lands so the user can stack up follow-ups without\n * waiting for each turn to finish. */\n queue: string[];\n /** Snapshot taken at the start of the current run (first iteration.started\n * after idle). Used by run.result to compute the per-turn summary —\n * duration is now-at minus this `at`, cost delta is the difference\n * between the session's current cost and the cost captured here. Null\n * while idle. */\n runStart: { at: number; cost: number } | null;\n /** Transient extended-thinking buffer. Populated by provider.thinking_delta\n * events and shown as a soft, ephemeral bubble below the chat tail while\n * the model is reasoning. Cleared the moment the model produces user-\n * facing output (text_delta) or starts a tool — and at provider.response /\n * run.result. Never persisted into `messages`, so refresh wipes it. */\n thinkingBuffer: string;\n /** Wall-clock ms when the current thinking burst started, for the chip's\n * elapsed timer. Reset alongside `thinkingBuffer`. */\n thinkingStartedAt: number | null;\n\n addMessage: (msg: Omit<ChatMessage, 'id' | 'timestamp'>) => string;\n updateMessage: (id: string, updates: Partial<ChatMessage>) => void;\n appendToMessage: (id: string, text: string) => void;\n finalizeMessage: (id: string) => void;\n setToolResult: (id: string, result: string, ok: boolean) => void;\n appendToolProgress: (id: string, line: string) => void;\n setLoading: (loading: boolean) => void;\n setAbortController: (ctrl: AbortController | null) => void;\n clearMessages: () => void;\n setCurrentAssistantMessage: (id: string | null) => void;\n setCurrentToolId: (id: string | null) => void;\n truncateAfter: (id: string) => void;\n addExecution: (exec: ToolExecution) => void;\n updateExecution: (id: string, updates: Partial<ToolExecution>) => void;\n enqueue: (text: string) => void;\n dequeue: () => string | null;\n removeQueued: (idx: number) => void;\n clearQueue: () => void;\n setRunStart: (s: { at: number; cost: number } | null) => void;\n appendThinking: (text: string) => void;\n clearThinking: () => void;\n}\n\ninterface ToolExecution {\n id: string;\n name: string;\n input?: unknown | undefined;\n output?: string | undefined;\n durationMs?: number | undefined;\n ok: boolean;\n startedAt: number;\n completedAt?: number | undefined;\n}\n\nexport const useChatStore = create<ChatState>()(\n persist(\n (set, get) => ({\n messages: [],\n currentAssistantMessageId: null,\n currentToolId: null,\n isLoading: false,\n abortController: null,\n executions: new Map(),\n queue: [],\n runStart: null,\n thinkingBuffer: '',\n thinkingStartedAt: null,\n\n addMessage: (msg) => {\n const id = `msg_${Date.now()}_${crypto.randomUUID().slice(0, 8)}`;\n const fullMsg: ChatMessage = { ...msg, id, timestamp: Date.now() };\n set((state) => ({\n messages: [...state.messages, fullMsg],\n currentAssistantMessageId:\n msg.role === 'assistant' ? id : state.currentAssistantMessageId,\n }));\n return id;\n },\n\n updateMessage: (id, updates) => {\n set((state) => ({\n messages: state.messages.map((m) => (m.id === id ? { ...m, ...updates } : m)),\n }));\n },\n\n appendToMessage: (id, text) => {\n set((state) => ({\n messages: state.messages.map((m) =>\n m.id === id ? { ...m, content: m.content + text } : m,\n ),\n }));\n },\n\n finalizeMessage: (id) => {\n set((state) => ({\n messages: state.messages.map((m) =>\n m.id === id ? { ...m, content: dedupeRepeatedBlocks(m.content), streaming: false } : m,\n ),\n }));\n },\n\n setToolResult: (id, result, ok) => {\n set((state) => ({\n messages: state.messages.map((m) =>\n m.id === id ? { ...m, toolResult: result, isError: !ok, progressLines: undefined } : m,\n ),\n }));\n },\n\n appendToolProgress: (id, line) => {\n set((state) => ({\n messages: state.messages.map((m) => {\n if (m.id !== id) return m;\n const prev = m.progressLines ?? [];\n const next = [...prev, line];\n const trimmed = next.length > 30 ? next.slice(next.length - 30) : next;\n return { ...m, progressLines: trimmed };\n }),\n }));\n },\n\n setLoading: (loading) => set({ isLoading: loading }),\n setAbortController: (ctrl) => set({ abortController: ctrl }),\n\n clearMessages: () =>\n set({\n messages: [],\n currentAssistantMessageId: null,\n currentToolId: null,\n executions: new Map(),\n }),\n\n setCurrentAssistantMessage: (id) => set({ currentAssistantMessageId: id }),\n setCurrentToolId: (id) => set({ currentToolId: id }),\n\n truncateAfter: (id) =>\n set((state) => {\n const idx = state.messages.findIndex((m) => m.id === id);\n if (idx === -1) return state;\n return {\n messages: state.messages.slice(0, idx),\n currentAssistantMessageId: null,\n currentToolId: null,\n };\n }),\n\n addExecution: (exec) => {\n set((state) => {\n const newExecutions = new Map(state.executions);\n newExecutions.set(exec.id, exec);\n return { executions: newExecutions };\n });\n },\n\n updateExecution: (id, updates) => {\n set((state) => {\n const newExecutions = new Map(state.executions);\n const existing = newExecutions.get(id);\n if (existing) {\n newExecutions.set(id, { ...existing, ...updates });\n }\n return { executions: newExecutions };\n });\n },\n\n enqueue: (text) => set((state) => ({ queue: [...state.queue, text] })),\n dequeue: () => {\n const { queue } = get();\n if (queue.length === 0) return null;\n const [next, ...rest] = queue;\n set({ queue: rest });\n return expectDefined(next);\n },\n removeQueued: (idx) => set((state) => ({ queue: state.queue.filter((_, i) => i !== idx) })),\n clearQueue: () => set({ queue: [] }),\n setRunStart: (s) => set({ runStart: s }),\n appendThinking: (text) =>\n set((state) => ({\n thinkingBuffer: state.thinkingBuffer + text,\n thinkingStartedAt: state.thinkingStartedAt ?? Date.now(),\n })),\n clearThinking: () => set({ thinkingBuffer: '', thinkingStartedAt: null }),\n }),\n {\n name: 'wrongstack-chat',\n partialize: () => ({}),\n },\n ),\n);\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\n\n// ============================================\n// Config Store\n// ============================================\n\nexport interface ConfigState {\n provider: string;\n model: string;\n baseUrl?: string | undefined;\n apiKey?: string | undefined;\n wsUrl: string;\n wsConnected: boolean;\n /** Fine-grained connection state from the WS client. Drives the topbar's\n * reconnect indicator. */\n wsStatus:\n | { state: 'connecting' }\n | { state: 'open' }\n | { state: 'closed'; error?: string | undefined }\n | { state: 'reconnecting'; attempt: number; nextRetryAt: number; lastError?: string | undefined };\n theme: 'light' | 'dark' | 'system';\n autoConnect: boolean;\n /** Play a soft synthesized chime when run.result lands with status=done.\n * Off by default — opt-in via the Command Palette. Persisted so the\n * preference survives reloads. Actual playback only fires after the\n * user has interacted with the page (Web Audio autoplay policy). */\n soundOnComplete: boolean;\n\n setProvider: (provider: string) => void;\n setModel: (model: string) => void;\n setConfig: (\n config: Partial<Omit<ConfigState, 'setProvider' | 'setModel' | 'setConfig' | 'setTheme'>>,\n ) => void;\n setTheme: (theme: 'light' | 'dark' | 'system') => void;\n setWsConnected: (connected: boolean) => void;\n setWsStatus: (s: ConfigState['wsStatus']) => void;\n setSoundOnComplete: (on: boolean) => void;\n}\n\nexport const useConfigStore = create<ConfigState>()(\n persist(\n (set) => ({\n provider: 'anthropic',\n model: 'claude-sonnet-4-20250514',\n wsUrl: (() => {\n if (typeof window === 'undefined' || !window.location?.hostname) {\n return 'ws://127.0.0.1:3457';\n }\n const h = window.location.hostname.toLowerCase();\n if (h === 'localhost' || h === '127.0.0.1' || h === '[::1]' || h === '::1') {\n return 'ws://127.0.0.1:3457';\n }\n return `ws://${window.location.hostname}:3457`;\n })(),\n wsConnected: false,\n wsStatus: { state: 'connecting' },\n theme: 'system',\n autoConnect: true,\n soundOnComplete: false,\n setProvider: (provider) => set({ provider }),\n setModel: (model) => set({ model }),\n setConfig: (config) => set(config),\n setTheme: (theme) => set({ theme }),\n setWsConnected: (connected) => set({ wsConnected: connected }),\n setWsStatus: (wsStatus) => set({ wsStatus, wsConnected: wsStatus.state === 'open' }),\n setSoundOnComplete: (on) => set({ soundOnComplete: on }),\n }),\n {\n name: 'wrongstack-config',\n },\n ),\n);\n","import type { Usage } from '@wrongstack/core';\nimport { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport type { SessionInfo } from './types.js';\n\n// ============================================\n// Session Store\n// ============================================\n\ninterface SessionState {\n session: SessionInfo | null;\n totalTokens: Usage;\n /** Input tokens of the LAST provider response — used as the \"live context\n * size\" indicator in the topbar (matches what TUI's ContextChip shows). */\n lastInputTokens: number;\n cost: number;\n startTime: number | null;\n /** Model max context window, from models.dev catalog. 0 = unknown. */\n maxContext: number;\n /** USD per 1M tokens — used to compute cost deltas on every provider.response. */\n inputCost: number;\n outputCost: number;\n cacheReadCost: number;\n /** basename(projectRoot) for the topbar. */\n projectName: string;\n /** Active mode id (default | code | …). */\n mode: string;\n /** All modes the backend knows about, populated by modes.list. The\n * topbar mode chip uses this to render a picker; empty until the\n * backend responds. */\n modes: Array<{ id: string; name: string; description: string }>;\n /** Active context-window policy id (balanced | frugal | deep | archival). */\n contextMode: string;\n /** Context-window policy presets from the backend. */\n contextModes: Array<{\n id: string;\n name: string;\n description: string;\n thresholds?: { warn: number | undefined; soft: number; hard: number };\n preserveK?: number | undefined;\n eliseThreshold?: number | undefined;\n }>;\n /** Iteration progress while the agent is running. Resets on run.result. */\n iteration: { index: number; max: number } | null;\n /** Live snapshot of context.todos — backend broadcasts on every\n * tool.executed, and the sidebar/overlay reads from here. */\n todos: Array<{\n id: string;\n content: string;\n status: 'pending' | 'in_progress' | 'completed';\n activeForm?: string | undefined;\n }>;\n\n setSession: (session: SessionInfo | null) => void;\n updateUsage: (usage: Usage) => void;\n addCost: (cost: number) => void;\n startSession: (session: SessionInfo) => void;\n endSession: () => void;\n setEnv: (env: {\n maxContext?: number | undefined;\n projectName?: string | undefined;\n mode?: string | undefined;\n contextMode?: string | undefined;\n inputCost?: number | undefined;\n outputCost?: number | undefined;\n cacheReadCost?: number | undefined;\n }) => void;\n setIteration: (it: { index: number; max: number } | null) => void;\n setModes: (modes: Array<{ id: string; name: string; description: string }>) => void;\n setContextModes: (modes: SessionState['contextModes']) => void;\n setTodos: (todos: SessionState['todos']) => void;\n}\n\nexport const useSessionStore = create<SessionState>()(\n persist(\n (set) => ({\n session: null,\n totalTokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n lastInputTokens: 0,\n cost: 0,\n startTime: null,\n maxContext: 0,\n inputCost: 0,\n outputCost: 0,\n cacheReadCost: 0,\n projectName: '',\n mode: 'default',\n modes: [],\n contextMode: 'balanced',\n contextModes: [],\n iteration: null,\n todos: [],\n\n setSession: (session) => set({ session }),\n\n updateUsage: (usage) =>\n set((state) => {\n const inputDelta = usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);\n const cacheReadDelta = usage.cacheRead ?? 0;\n const cacheWriteDelta = usage.cacheWrite ?? 0;\n return {\n totalTokens: {\n input: state.totalTokens.input + usage.input,\n output: state.totalTokens.output + usage.output,\n cacheRead: (state.totalTokens.cacheRead ?? 0) + cacheReadDelta,\n cacheWrite: (state.totalTokens.cacheWrite ?? 0) + cacheWriteDelta,\n },\n lastInputTokens: inputDelta || state.lastInputTokens,\n };\n }),\n\n addCost: (cost) => set((state) => ({ cost: state.cost + cost })),\n\n startSession: (session) =>\n set({\n session,\n startTime: Date.now(),\n iteration: null,\n lastInputTokens: 0,\n totalTokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n cost: 0,\n }),\n\n endSession: () =>\n set({\n session: null,\n startTime: null,\n iteration: null,\n }),\n\n setEnv: (env) =>\n set((state) => ({\n maxContext: env.maxContext ?? state.maxContext,\n projectName: env.projectName ?? state.projectName,\n mode: env.mode ?? state.mode,\n contextMode: env.contextMode ?? state.contextMode,\n inputCost: env.inputCost ?? state.inputCost,\n outputCost: env.outputCost ?? state.outputCost,\n cacheReadCost: env.cacheReadCost ?? state.cacheReadCost,\n })),\n\n setIteration: (iteration) => set({ iteration }),\n setModes: (modes) => set({ modes }),\n setContextModes: (contextModes) => set({ contextModes }),\n setTodos: (todos) => set({ todos }),\n }),\n {\n name: 'wrongstack-session',\n partialize: () => ({}),\n },\n ),\n);\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\n\n// ============================================\n// UI Store\n// ============================================\n\ninterface UIState {\n sidebarOpen: boolean;\n settingsOpen: boolean;\n currentView: 'chat' | 'history' | 'settings';\n showConfirmDialog: boolean;\n confirmInfo: {\n id: string;\n toolName: string;\n input: unknown;\n suggestedPattern: string;\n } | null;\n paletteOpen: boolean;\n shortcutsOpen: boolean;\n searchOpen: boolean;\n searchQuery: string;\n promptHistory: string[];\n sidebarWidth: number;\n pinnedIds: string[];\n compactMode: boolean;\n modelSwitcherOpen: boolean;\n favoriteSessionIds: string[];\n sessionNicknames: Record<string, string>;\n\n toggleSidebar: () => void;\n setSidebarOpen: (open: boolean) => void;\n setSettingsOpen: (open: boolean) => void;\n setCurrentView: (view: 'chat' | 'history' | 'settings') => void;\n showConfirm: (info: UIState['confirmInfo']) => void;\n hideConfirm: () => void;\n setPaletteOpen: (open: boolean) => void;\n setShortcutsOpen: (open: boolean) => void;\n setSearchOpen: (open: boolean) => void;\n setSearchQuery: (q: string) => void;\n pushPrompt: (text: string) => void;\n setSidebarWidth: (px: number) => void;\n togglePin: (id: string) => void;\n unpinAll: () => void;\n toggleCompactMode: () => void;\n setModelSwitcherOpen: (open: boolean) => void;\n toggleFavoriteSession: (id: string) => void;\n setSessionNickname: (id: string, nickname: string) => void;\n}\n\nexport const useUIStore = create<UIState>()(\n persist(\n (set) => ({\n sidebarOpen: true,\n settingsOpen: false,\n currentView: 'chat',\n showConfirmDialog: false,\n confirmInfo: null,\n paletteOpen: false,\n shortcutsOpen: false,\n searchOpen: false,\n searchQuery: '',\n promptHistory: [],\n sidebarWidth: 288,\n pinnedIds: [],\n compactMode: false,\n modelSwitcherOpen: false,\n favoriteSessionIds: [],\n sessionNicknames: {},\n\n toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),\n setSidebarOpen: (open) => set({ sidebarOpen: open }),\n setSettingsOpen: (open) => set({ settingsOpen: open }),\n setCurrentView: (view) => set({ currentView: view }),\n showConfirm: (info) => set({ showConfirmDialog: true, confirmInfo: info }),\n hideConfirm: () => set({ showConfirmDialog: false, confirmInfo: null }),\n setPaletteOpen: (open) => set({ paletteOpen: open }),\n setShortcutsOpen: (open) => set({ shortcutsOpen: open }),\n setSearchOpen: (open) => set({ searchOpen: open, searchQuery: open ? '' : '' }),\n setSearchQuery: (q) => set({ searchQuery: q }),\n pushPrompt: (text) =>\n set((state) => {\n const trimmed = text.trim();\n if (!trimmed) return state;\n const filtered = state.promptHistory.filter((p) => p !== trimmed);\n return { promptHistory: [trimmed, ...filtered].slice(0, 50) };\n }),\n setSidebarWidth: (px) => set({ sidebarWidth: Math.max(200, Math.min(480, Math.round(px))) }),\n togglePin: (id) =>\n set((state) => {\n const has = state.pinnedIds.includes(id);\n return {\n pinnedIds: has ? state.pinnedIds.filter((p) => p !== id) : [...state.pinnedIds, id],\n };\n }),\n unpinAll: () => set({ pinnedIds: [] }),\n toggleCompactMode: () => set((s) => ({ compactMode: !s.compactMode })),\n setModelSwitcherOpen: (open) => set({ modelSwitcherOpen: open }),\n toggleFavoriteSession: (id) =>\n set((state) => {\n const has = state.favoriteSessionIds.includes(id);\n return {\n favoriteSessionIds: has\n ? state.favoriteSessionIds.filter((s) => s !== id)\n : [...state.favoriteSessionIds, id],\n };\n }),\n setSessionNickname: (id, nickname) =>\n set((state) => {\n const trimmed = nickname.trim();\n const next = { ...state.sessionNicknames };\n if (trimmed) next[id] = trimmed;\n else delete next[id];\n return { sessionNicknames: next };\n }),\n }),\n {\n name: 'wrongstack-ui',\n partialize: (s) => ({\n sidebarOpen: s.sidebarOpen,\n sidebarWidth: s.sidebarWidth,\n promptHistory: s.promptHistory,\n pinnedIds: s.pinnedIds,\n compactMode: s.compactMode,\n favoriteSessionIds: s.favoriteSessionIds,\n sessionNicknames: s.sessionNicknames,\n }),\n },\n ),\n);\n","import { create } from 'zustand';\nimport type { SessionHistoryEntry } from './types.js';\n\n// ============================================\n// History Store\n// ============================================\n\ninterface HistoryState {\n entries: SessionHistoryEntry[];\n loading: boolean;\n error: string | null;\n setEntries: (entries: SessionHistoryEntry[], error?: string | null) => void;\n setLoading: (loading: boolean) => void;\n removeEntry: (id: string) => void;\n clearHistory: () => void;\n}\n\nexport const useHistoryStore = create<HistoryState>()((set) => ({\n entries: [],\n loading: false,\n error: null,\n setEntries: (entries, error = null) => set({ entries, error, loading: false }),\n setLoading: (loading) => set({ loading }),\n removeEntry: (id) =>\n set((state) => ({\n entries: state.entries.filter((e) => e.id !== id),\n })),\n clearHistory: () => set({ entries: [] }),\n}));\n","import { create } from 'zustand';\nimport type { WorktreeHandleView } from '../types.js';\n\n// ── Worktree store (live backend state; not persisted) ──────────────────────\n\ninterface WorktreeActivity {\n handleId: string;\n kind: string;\n text: string;\n at: number;\n}\n\ninterface WorktreeState {\n worktrees: WorktreeHandleView[];\n baseBranch: string;\n activity: WorktreeActivity[];\n setSnapshot: (worktrees: WorktreeHandleView[], baseBranch: string) => void;\n pushEvent: (e: WorktreeActivity) => void;\n}\n\nexport const useWorktreeStore = create<WorktreeState>()((set) => ({\n worktrees: [],\n baseBranch: '',\n activity: [],\n setSnapshot: (worktrees, baseBranch) => set({ worktrees, baseBranch }),\n pushEvent: (e) => set((s) => ({ activity: [...s.activity, e].slice(-40) })),\n}));\n","import { create } from 'zustand';\nimport type { SubagentView, SubagentEvent } from './types.js';\n\n// ── Fleet store (live subagent roster; not persisted) ───────────────────────\n\ninterface FleetState {\n agents: Map<string, SubagentView>;\n applyEvent: (e: SubagentEvent) => void;\n clear: () => void;\n}\n\nfunction blankAgent(id: string, name?: string): SubagentView {\n return {\n id,\n name: name?.trim() || id,\n status: 'running',\n iteration: 0,\n toolCalls: 0,\n costUsd: 0,\n ctxPct: 0,\n ctxTokens: 0,\n maxContext: 0,\n extensions: 0,\n startedAt: Date.now(),\n };\n}\n\nexport const useFleetStore = create<FleetState>()((set) => ({\n agents: new Map(),\n clear: () => set({ agents: new Map() }),\n applyEvent: (e) =>\n set((state) => {\n const agents = new Map(state.agents);\n const prev = agents.get(e.subagentId) ?? blankAgent(e.subagentId, e.name);\n const next: SubagentView = { ...prev };\n switch (e.kind) {\n case 'spawned':\n next.name = e.name?.trim() || next.name;\n next.provider = e.provider ?? next.provider;\n next.model = e.model ?? next.model;\n next.description = e.description ?? next.description;\n next.taskId = e.taskId ?? next.taskId;\n next.status = 'running';\n break;\n case 'task_started':\n next.description = e.description ?? next.description;\n next.taskId = e.taskId ?? next.taskId;\n next.status = 'running';\n break;\n case 'tool_executed':\n next.lastTool = e.toolName ?? next.lastTool;\n next.toolCalls = next.toolCalls + 1;\n break;\n case 'iteration_summary':\n next.iteration = e.iteration ?? next.iteration;\n if (typeof e.toolCalls === 'number') next.toolCalls = e.toolCalls;\n if (typeof e.costUsd === 'number') next.costUsd = e.costUsd;\n next.currentTool = e.currentTool ?? next.currentTool;\n break;\n case 'budget_extended':\n next.extensions = e.totalExtensions ?? next.extensions + 1;\n break;\n case 'ctx_pct':\n next.ctxPct = Math.round(Math.min(1, Math.max(0, e.load ?? 0)) * 100);\n next.ctxTokens = e.tokens ?? next.ctxTokens;\n next.maxContext = e.maxContext ?? next.maxContext;\n break;\n case 'task_completed':\n next.status = e.status === 'success' ? 'completed' : (e.status ?? 'completed');\n if (typeof e.iterations === 'number') next.iteration = e.iterations;\n if (typeof e.toolCalls === 'number') next.toolCalls = e.toolCalls;\n next.error = e.error;\n next.currentTool = undefined;\n next.completedAt = Date.now();\n break;\n }\n agents.set(e.subagentId, next);\n return { agents };\n }),\n}));\n","import { installFaviconVisibilityReset } from '@/lib/favicon';\nimport { getWSClient } from '@/lib/ws-client';\nimport type { WrongStackWebSocketClient } from '@/lib/ws-client';\nimport { useChatStore, useConfigStore, useHistoryStore, useSessionStore, useUIStore } from '@/stores';\nimport { useCallback, useEffect, useRef } from 'react';\nimport { WS_HANDLERS } from './ws-handlers.js';\n\n/**\n * One-shot WebSocket handler installation.\n *\n * Critical: this is called by `useWebSocketBootstrap` from App.tsx EXACTLY\n * ONCE per page. Every other component that needs to talk to the backend uses\n * `useWebSocket()` (below) which only returns action methods — it does NOT\n * register handlers.\n *\n * The earlier design had every component that imported `useWebSocket()`\n * register its own copy of the handlers via `ws.on(type, handler)`. With\n * ChatInput + ConfirmDialog + SettingsPanel all using the hook, every\n * incoming WS message was processed three times — three identical tool\n * bubbles, three appends of the same text_delta, three clearMessages on\n * session.start. That's the \"duplicate tool bubble / repeated text\" bug\n * the user kept hitting. Singleton install fixes it at the root.\n */\nfunction installHandlers(ws: WrongStackWebSocketClient): () => void {\n const offs: Array<() => void> = [];\n for (const [type, handler] of Object.entries(WS_HANDLERS)) {\n offs.push(ws.on(type, handler));\n }\n return () => { for (const off of offs) off(); };\n}\n\n/**\n * Mounts the WebSocket connection and installs event handlers EXACTLY ONCE.\n * Call this from App.tsx (top of the tree) and nowhere else.\n */\nexport function useWebSocketBootstrap(): void {\n const { autoConnect, wsUrl } = useConfigStore();\n const setWsStatus = useConfigStore((s) => s.setWsStatus);\n const installed = useRef(false);\n\n useEffect(() => {\n if (!autoConnect) return;\n installFaviconVisibilityReset();\n const ws = getWSClient(wsUrl);\n\n const offStatus = ws.onStatus((s) => setWsStatus(s));\n\n ws.connect().catch((err) => {\n // eslint-disable-next-line no-console\n console.error('[WS] Connection failed:', err);\n });\n\n if (installed.current) {\n return () => { offStatus(); };\n }\n installed.current = true;\n const off = installHandlers(ws);\n return () => {\n off();\n offStatus();\n };\n }, [autoConnect, wsUrl, setWsStatus]);\n}\n\n/**\n * Cheap accessor for the singleton WS client and its imperative action\n * methods. Components call this freely; it does NOT register handlers.\n */\nexport function useWebSocket() {\n const { wsUrl } = useConfigStore();\n const client = getWSClient(wsUrl);\n\n const sendMessage = useCallback(\n (content: string) => {\n if (client.isConnected) return client.sendMessage(content);\n return null;\n },\n [client],\n );\n\n const sendAbort = useCallback(() => client.sendAbort(), [client]);\n\n const { hideConfirm } = useUIStore();\n const sendConfirm = useCallback(\n (id: string, decision: 'yes' | 'no' | 'always' | 'deny') => {\n client.sendConfirm(id, decision);\n hideConfirm();\n },\n [client, hideConfirm],\n );\n\n const switchModel = useCallback(\n (provider: string, model: string) => client.switchModel(provider, model),\n [client],\n );\n\n const listProviders = useCallback(() => client.listProviders(), [client]);\n const listProviderModels = useCallback(\n (providerId: string) => client.listProviderModels(providerId),\n [client],\n );\n const listSavedProviders = useCallback(() => client.listSavedProviders(), [client]);\n const addKey = useCallback(\n (providerId: string, label: string, apiKey: string) => client.addKey(providerId, label, apiKey),\n [client],\n );\n const updateKey = useCallback(\n (providerId: string, label: string, apiKey: string) =>\n client.updateKey(providerId, label, apiKey),\n [client],\n );\n const deleteKey = useCallback(\n (providerId: string, label: string) => client.deleteKey(providerId, label),\n [client],\n );\n const setActiveKey = useCallback(\n (providerId: string, label: string) => client.setActiveKey(providerId, label),\n [client],\n );\n const addProvider = useCallback(\n (id: string, family: string, baseUrl?: string | undefined, apiKey?: string) =>\n client.addProvider(id, family, baseUrl, apiKey),\n [client],\n );\n const removeProvider = useCallback(\n (providerId: string) => client.removeProvider(providerId),\n [client],\n );\n\n const listSessions = useCallback(\n (limit?: number) => {\n useHistoryStore.getState().setLoading(true);\n client.listSessions(limit);\n },\n [client],\n );\n const deleteSession = useCallback(\n (id: string) => {\n useHistoryStore.getState().removeEntry(id);\n client.deleteSession(id);\n },\n [client],\n );\n const resumeSession = useCallback((id: string) => client.resumeSessionById(id), [client]);\n const saveSession = useCallback(() => client.saveSession(), [client]);\n const listTools = useCallback(() => client.listTools(), [client]);\n const listMemory = useCallback(() => client.listMemory(), [client]);\n const listSkills = useCallback(() => client.listSkills(), [client]);\n const getDiag = useCallback(() => client.getDiag(), [client]);\n const getStats = useCallback(() => client.getStats(), [client]);\n const listModes = useCallback(() => client.listModes(), [client]);\n const switchMode = useCallback((id: string) => client.switchMode(id), [client]);\n const listContextModes = useCallback(() => client.listContextModes(), [client]);\n const switchContextMode = useCallback((id: string) => client.switchContextMode(id), [client]);\n const repairContext = useCallback(() => client.repairContext(), [client]);\n\n // AutoPhase\n const toggleAutoPhaseAutonomous = useCallback(\n (autonomous: boolean) => { client.send({ type: 'autophase.toggleAutonomous', payload: { autonomous } }); },\n [client],\n );\n const startAutoPhase = useCallback(\n (title: string, phases?: unknown[] | undefined, autonomous = true) => { client.send({ type: 'autophase.start', payload: { title, phases, autonomous } }); },\n [client],\n );\n const pauseAutoPhase = useCallback(() => { client.send({ type: 'autophase.pause', payload: {} }); }, [client]);\n const resumeAutoPhase = useCallback(() => { client.send({ type: 'autophase.resume', payload: {} }); }, [client]);\n const stopAutoPhase = useCallback(() => { client.send({ type: 'autophase.stop', payload: {} }); }, [client]);\n const selectAutoPhase = useCallback(\n (phaseId: string) => { client.send({ type: 'autophase.selectPhase', payload: { phaseId } }); },\n [client],\n );\n\n return {\n client, sendMessage, sendAbort, sendConfirm, switchModel,\n listProviders, listProviderModels, listSavedProviders,\n addKey, updateKey, deleteKey, setActiveKey, addProvider, removeProvider,\n listSessions, deleteSession, resumeSession, saveSession,\n listTools, listMemory, listSkills, getDiag, getStats,\n listModes, switchMode, listContextModes, switchContextMode, repairContext,\n toggleAutoPhaseAutonomous, startAutoPhase, pauseAutoPhase, resumeAutoPhase, stopAutoPhase, selectAutoPhase,\n };\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { cn } from '@/lib/utils';\nimport { AlertTriangle, CheckCircle2, Info, X, XCircle } from 'lucide-react';\nimport { useEffect } from 'react';\nimport { create } from 'zustand';\n\n/**\n * Tiny toast store + portal. We resisted pulling in shadcn-ui's full\n * toast/sonner since it brings a tree of providers — this is one store,\n * one component, ~80 lines total. The store is exposed via `toast.success(...)`\n * etc. so non-React modules (ws-client handlers) can fire toasts without\n * the hook.\n */\n\nexport type ToastVariant = 'success' | 'error' | 'warn' | 'info';\n\ninterface ToastEntry {\n id: string;\n message: string;\n variant: ToastVariant;\n ttl: number;\n}\n\ninterface ToastState {\n toasts: ToastEntry[];\n push: (t: Omit<ToastEntry, 'id'>) => string;\n dismiss: (id: string) => void;\n}\n\nconst useToastStore = create<ToastState>((set) => ({\n toasts: [],\n push: (t) => {\n const id = `toast_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;\n set((state) => ({ toasts: [...state.toasts, { ...t, id }] }));\n return id;\n },\n dismiss: (id) => set((state) => ({ toasts: state.toasts.filter((x) => x.id !== id) })),\n}));\n\n/** Imperative API. Pass plain strings or arrays of strings for multi-line. */\nexport const toast = {\n success: (msg: string, ttl = 3500) =>\n useToastStore.getState().push({ message: msg, variant: 'success', ttl }),\n error: (msg: string, ttl = 6000) =>\n useToastStore.getState().push({ message: msg, variant: 'error', ttl }),\n warn: (msg: string, ttl = 4500) =>\n useToastStore.getState().push({ message: msg, variant: 'warn', ttl }),\n info: (msg: string, ttl = 3500) =>\n useToastStore.getState().push({ message: msg, variant: 'info', ttl }),\n dismiss: (id: string) => useToastStore.getState().dismiss(id),\n};\n\nfunction Icon({ variant }: { variant: ToastVariant }) {\n if (variant === 'success') return <CheckCircle2 className=\"h-4 w-4 text-green-500\" />;\n if (variant === 'error') return <XCircle className=\"h-4 w-4 text-destructive\" />;\n if (variant === 'warn') return <AlertTriangle className=\"h-4 w-4 text-amber-500\" />;\n return <Info className=\"h-4 w-4 text-blue-500\" />;\n}\n\nfunction ToastItem({ entry }: { entry: ToastEntry }) {\n const dismiss = useToastStore((s) => s.dismiss);\n useEffect(() => {\n const t = setTimeout(() => dismiss(entry.id), entry.ttl);\n return () => clearTimeout(t);\n }, [entry.id, entry.ttl, dismiss]);\n return (\n <div\n className={cn(\n 'flex items-start gap-2 rounded-lg border bg-popover shadow-lg px-3 py-2 text-sm max-w-sm',\n 'animate-message',\n entry.variant === 'error' && 'border-destructive/40',\n entry.variant === 'warn' && 'border-amber-500/40',\n entry.variant === 'success' && 'border-green-500/40',\n )}\n >\n <Icon variant={entry.variant} />\n <div className=\"flex-1 min-w-0 whitespace-pre-wrap break-words leading-snug\">\n {entry.message}\n </div>\n <button\n type=\"button\"\n onClick={() => dismiss(entry.id)}\n className=\"text-muted-foreground hover:text-foreground\"\n title=\"Dismiss\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n );\n}\n\nexport function Toaster() {\n const toasts = useToastStore((s) => s.toasts);\n if (toasts.length === 0) return null;\n return (\n <div className=\"fixed bottom-4 right-4 z-[60] flex flex-col gap-2 pointer-events-auto\">\n {toasts.map((t) => (\n <ToastItem key={t.id} entry={t} />\n ))}\n </div>\n );\n}\n","/**\n * Tiny soft chime played when a long-running agent run completes. We don't\n * ship an audio asset — the sound is synthesized with Web Audio so it's\n * zero-bytes-shipped and trivially tweakable.\n *\n * Tuned to be unobtrusive: two notes ascending, ~250ms total, ~-12dB\n * envelope. Quiet enough to not startle on a still office, audible enough\n * to cut through music. Browsers require a prior user interaction before\n * any audio plays — by the time the agent has actually finished a turn the\n * user has already typed, so the autoplay policy is satisfied.\n */\n\nlet ctx: AudioContext | null = null;\n\nfunction audio(): AudioContext | null {\n if (typeof window === 'undefined') return null;\n if (ctx) return ctx;\n // SSR/Test guard plus older Safari (webkit prefix).\n const Cls =\n window.AudioContext ||\n (window as unknown as { webkitAudioContext?: typeof AudioContext | undefined }).webkitAudioContext;\n if (!Cls) return null;\n try {\n ctx = new Cls();\n } catch {\n return null;\n }\n return ctx;\n}\n\nfunction tone(freq: number, startAt: number, durSec: number): void {\n const ac = audio();\n if (!ac) return;\n const t = ac.currentTime + startAt;\n const osc = ac.createOscillator();\n const gain = ac.createGain();\n osc.type = 'sine';\n osc.frequency.value = freq;\n // Quick attack, exponential decay — sounds like a soft \"bing\".\n gain.gain.setValueAtTime(0, t);\n gain.gain.linearRampToValueAtTime(0.18, t + 0.01);\n gain.gain.exponentialRampToValueAtTime(0.0001, t + durSec);\n osc.connect(gain).connect(ac.destination);\n osc.start(t);\n osc.stop(t + durSec + 0.02);\n}\n\nexport function playCompletionChime(): void {\n // Two-note arpeggio: E5 → A5 (a perfect fourth, pleasant + non-alarming).\n tone(659.25, 0, 0.18);\n tone(880, 0.12, 0.24);\n}\n\n/**\n * Urgent chime for permission requests. Louder and more insistent than\n * the completion chime — three ascending notes that say \"hey, I need\n * your input\". Always plays regardless of soundOnComplete preference,\n * because a missed permission prompt means the agent is stuck.\n */\nexport function playPermissionChime(): void {\n // Three-note ascending: C5 → E5 → G5 (C major arpeggio, attention-getting)\n tone(523.25, 0, 0.15);\n tone(659.25, 0.1, 0.15);\n tone(783.99, 0.2, 0.25);\n}\n","/**\n * Browser Notification API wrapper. We never pop a notification when the\n * tab is foreground — the user already sees the chat update, so an OS\n * popup would just be noise. The flow:\n *\n * 1. requestPermission() is called lazily on first run completion;\n * browsers require a user gesture for the prompt to be safe but\n * Chrome / Firefox accept it from any code path with relaxed rules.\n * 2. notifyIfHidden() short-circuits unless the page is `document.hidden`.\n * 3. Clicking the notification focuses the page (best-effort — some\n * browsers won't focus across tab groups).\n */\n\nlet permissionState: NotificationPermission | 'unsupported' = 'default';\n\nif (typeof window !== 'undefined' && 'Notification' in window) {\n permissionState = Notification.permission;\n} else {\n permissionState = 'unsupported';\n}\n\nexport async function ensureNotificationPermission(): Promise<\n NotificationPermission | 'unsupported'\n> {\n if (\n permissionState === 'unsupported' ||\n permissionState === 'granted' ||\n permissionState === 'denied'\n ) {\n return permissionState;\n }\n try {\n const result = await Notification.requestPermission();\n permissionState = result;\n return result;\n } catch {\n return 'denied';\n }\n}\n\nexport function notifyIfHidden(title: string, body?: string | undefined, tag?: string): void {\n if (typeof document === 'undefined' || !document.hidden) return;\n if (permissionState !== 'granted') return;\n try {\n const n = new Notification(title, {\n body,\n icon: '/favicon.ico',\n // Tag-collapse: if multiple notifications stack while the tab is\n // hidden, only the latest with the same tag shows up so we don't\n // litter the OS notification center. Permission alerts use a\n // separate tag so they don't get swallowed by run-completion.\n tag: tag ?? 'wrongstack-run',\n // Require interaction for permission alerts — the agent is stuck\n // until the user responds, so auto-dismiss would be harmful.\n requireInteraction: tag === 'wrongstack-confirm',\n });\n n.onclick = () => {\n window.focus();\n n.close();\n };\n } catch {\n // Some browsers (e.g. iOS Safari) throw — silently swallow.\n }\n}\n","import { toast } from '@/components/Toaster';\nimport { playCompletionChime, playPermissionChime } from '@/lib/chime';\nimport { setFaviconStatus } from '@/lib/favicon';\nimport { ensureNotificationPermission, notifyIfHidden } from '@/lib/notify';\nimport { getWSClient } from '@/lib/ws-client';\nimport type { WrongStackWebSocketClient } from '@/lib/ws-client';\nimport {\n type SessionHistoryEntry,\n type SubagentEvent,\n useChatStore,\n useConfigStore,\n useFleetStore,\n useHistoryStore,\n useSessionStore,\n useUIStore,\n useWorktreeStore,\n} from '@/stores';\nimport type { WorktreeHandleView, WSServerMessage } from '@/types';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\n// ── Session handlers ──\n\nexport function handleSessionStart(msg: WSServerMessage) {\n const payload = msg.payload as {\n sessionId: string;\n model: string;\n provider: string;\n maxContext?: number | undefined;\n projectName?: string | undefined;\n cwd?: string | undefined;\n mode?: string | undefined;\n contextMode?: string | undefined;\n inputCost?: number | undefined;\n outputCost?: number | undefined;\n cacheReadCost?: number | undefined;\n reset?: boolean | undefined;\n };\n const prev = useSessionStore.getState().session?.id;\n const isNew = !prev || prev !== payload.sessionId;\n useSessionStore.getState().startSession({\n id: payload.sessionId,\n startedAt: Date.now(),\n model: payload.model,\n provider: payload.provider,\n });\n useSessionStore.getState().setEnv({\n maxContext: payload.maxContext,\n projectName: payload.projectName,\n mode: payload.mode,\n contextMode: payload.contextMode,\n inputCost: payload.inputCost,\n outputCost: payload.outputCost,\n cacheReadCost: payload.cacheReadCost,\n });\n useConfigStore.getState().setConfig({\n provider: payload.provider,\n model: payload.model,\n });\n if (isNew || payload.reset) {\n useChatStore.getState().clearMessages();\n useFleetStore.getState().clear();\n }\n // Resume hydration\n const replay = (payload as { replayMessages?: Array<{ role: string | undefined; content: unknown }> }).replayMessages;\n if (replay && replay.length > 0) {\n const chat = useChatStore.getState();\n for (const m of replay) {\n if (m.role === 'user' || m.role === 'assistant' || m.role === 'system') {\n let text = '';\n if (typeof m.content === 'string') {\n text = m.content;\n } else if (Array.isArray(m.content)) {\n for (const b of m.content as Array<Record<string, unknown>>) {\n if (b.type === 'text' && typeof b.text === 'string') {\n text += (text ? '\\n' : '') + b.text;\n } else if (b.type === 'tool_use') {\n if (text) { chat.addMessage({ role: m.role as 'user' | 'assistant', content: text }); text = ''; }\n chat.addMessage({ role: 'tool', content: '', toolName: String(b.name ?? 'tool'), toolInput: b.input, toolUseId: String(b.id ?? '') });\n } else if (b.type === 'tool_result') {\n const all = useChatStore.getState().messages;\n let last: { id: string } | undefined;\n for (let i = all.length - 1; i >= 0; i--) {\n if (all[i]?.toolUseId === String(b.tool_use_id ?? '')) { last = expectDefined(all[i]); break; }\n }\n if (last) { chat.setToolResult(last.id, typeof b.content === 'string' ? b.content : JSON.stringify(b.content), !b.is_error); }\n }\n }\n }\n if (text) chat.addMessage({ role: m.role as 'user' | 'assistant', content: text });\n }\n }\n }\n}\n\n// ── Context handlers ──\n\nexport function handleContextDebug(msg: WSServerMessage) {\n const p = msg.payload as {\n total: number; systemPrompt: number;\n tools: { total: number; count: number; breakdown: Array<{ name: string; tokens: number }> };\n messages: { total: number; count: number; breakdown: Array<{ index: number; role: string; tokens: number; preview: string }> };\n };\n const fmt = (n: number) => n.toLocaleString();\n const topTools = [...p.tools.breakdown].sort((a, b) => b.tokens - a.tokens).slice(0, 8);\n const topMsgs = [...p.messages.breakdown].sort((a, b) => b.tokens - a.tokens).slice(0, 8);\n useChatStore.getState().addMessage({ role: 'assistant', content: [\n `📊 **Context breakdown** (heuristic — 4 chars/token)`, '',\n `**Total estimate:** ${fmt(p.total)} tokens`,\n `• System prompt: ${fmt(p.systemPrompt)}`,\n `• Tool schemas: ${fmt(p.tools.total)} (${p.tools.count} tools)`,\n `• Messages: ${fmt(p.messages.total)} (${p.messages.count} messages)`, '',\n `**Top tool schemas:**`, ...topTools.map((t) => ` · ${t.name}: ${fmt(t.tokens)}`), '',\n `**Top messages:**`, ...topMsgs.map((m) => ` · #${m.index} ${m.role}: ${fmt(m.tokens)} — ${m.preview || '(empty)'}`),\n ].join('\\n') });\n}\n\nexport function handleKeyOperationResult(msg: WSServerMessage) {\n const p = msg.payload as { success: boolean; message: string };\n if (p.success) toast.success(p.message);\n else toast.error(p.message);\n // Refresh saved providers after any key operation so the SettingsPanel\n // (and any other viewer) immediately sees the updated list.\n const client = getWSClient(useConfigStore.getState().wsUrl);\n client.listSavedProviders();\n}\n\nexport function handleContextCompacted(msg: WSServerMessage) {\n const payload = msg.payload as {\n before: number; after: number; saved: number;\n reductions: Array<{ phase: string; saved: number }>;\n repaired?: { removedToolUses: string[] | undefined; removedToolResults: string[]; removedMessages: number };\n };\n let summary = payload.reductions.length ? payload.reductions.map((r) => `${r.phase}: ${r.saved}`).join(', ') : 'no-op';\n if (payload.repaired) summary += `; repaired ${payload.repaired.removedToolUses?.length ?? 0} tool_use, ${payload.repaired.removedToolResults?.length ?? 0} tool_result, ${payload.repaired.removedMessages} empty messages`;\n useChatStore.getState().addMessage({ role: 'assistant', content: `🗜️ Context compacted: ${payload.before} → ${payload.after} tokens (saved ~${payload.saved}). ${summary}` });\n useSessionStore.setState({ lastInputTokens: payload.after });\n}\n\nexport function handleProviderResponse(msg: WSServerMessage) {\n const payload = msg.payload as { usage: { input: number; output: number; cacheRead?: number | undefined; cacheWrite?: number | undefined }; stopReason: string; messageId: string };\n\n // Update lastInputTokens from usage delta (was a separate handler)\n const u = payload.usage;\n const delta = (u.input ?? 0) + (u.cacheWrite ?? 0) - (u.cacheRead ?? 0);\n if (delta > 0) useSessionStore.setState({ lastInputTokens: delta });\n\n // Main response handler\n useSessionStore.getState().updateUsage(payload.usage);\n const { inputCost, outputCost, cacheReadCost } = useSessionStore.getState();\n const dCost = (payload.usage.input * inputCost + payload.usage.output * outputCost + (payload.usage.cacheRead ?? 0) * cacheReadCost) / 1_000_000;\n if (dCost > 0) useSessionStore.getState().addCost(dCost);\n if (payload.stopReason !== 'tool_use' && payload.stopReason !== 'tool_call') useChatStore.getState().setLoading(false);\n const id = useChatStore.getState().currentAssistantMessageId;\n if (id) {\n useChatStore.getState().finalizeMessage(id);\n if (payload.usage.output > 0) useChatStore.getState().updateMessage(id, { usage: payload.usage });\n }\n useChatStore.getState().setCurrentAssistantMessage(null);\n useChatStore.getState().clearThinking();\n}\n\nexport function handleContextRepaired(msg: WSServerMessage) {\n const payload = msg.payload as { removedToolUses: string[]; removedToolResults: string[]; removedMessages: number; beforeMessages?: number | undefined; afterMessages?: number | undefined };\n const removed = payload.removedToolUses.length + payload.removedToolResults.length + payload.removedMessages;\n const msgCount = payload.beforeMessages !== undefined && payload.afterMessages !== undefined ? ` Messages: ${payload.beforeMessages} -> ${payload.afterMessages}.` : '';\n useChatStore.getState().addMessage({ role: 'assistant', content: `Context repaired: removed ${removed} orphan protocol item(s).${msgCount} tool_use ${payload.removedToolUses.length}, tool_result ${payload.removedToolResults.length}.` });\n}\n\n// ── Agent handlers ──\n\nexport function handleSessionEnd() {\n useConfigStore.getState().setWsConnected(false);\n}\n\nexport function handleIterationStarted(msg: WSServerMessage) {\n const payload = msg.payload as { index: number; maxIterations?: number | undefined };\n useSessionStore.getState().setIteration({ index: payload.index, max: payload.maxIterations ?? 0 });\n useChatStore.getState().setLoading(true);\n if (typeof document !== 'undefined' && document.hidden) setFaviconStatus('running');\n if (useChatStore.getState().runStart === null) {\n useChatStore.getState().setRunStart({ at: Date.now(), cost: useSessionStore.getState().cost });\n }\n useChatStore.getState().setCurrentAssistantMessage(null);\n}\n\nexport function handleTextDelta(msg: WSServerMessage) {\n const payload = msg.payload as { text: string; messageId: string };\n useChatStore.getState().clearThinking();\n let id = useChatStore.getState().currentAssistantMessageId;\n if (!id) {\n id = useChatStore.getState().addMessage({ role: 'assistant', content: '', streaming: true });\n useChatStore.getState().setCurrentAssistantMessage(id);\n }\n useChatStore.getState().appendToMessage(id, payload.text);\n}\n\nexport function handleThinkingDelta(msg: WSServerMessage) {\n const payload = msg.payload as { text: string };\n if (!payload.text) return;\n useChatStore.getState().appendThinking(payload.text);\n}\n\nexport function handleToolStarted(msg: WSServerMessage) {\n const payload = msg.payload as { id: string; name: string; input?: unknown | undefined; messageId: string };\n const existing = useChatStore.getState().messages.find((m) => m.toolUseId === payload.id);\n if (existing) { useChatStore.getState().setCurrentToolId(existing.id); return; }\n useChatStore.getState().clearThinking();\n useChatStore.getState().setCurrentAssistantMessage(null);\n const id = useChatStore.getState().addMessage({ role: 'tool', content: '', toolName: payload.name, toolInput: payload.input, toolUseId: payload.id });\n useChatStore.getState().setCurrentToolId(id);\n useChatStore.getState().addExecution({ id: payload.id, name: payload.name, input: payload.input, ok: true, startedAt: Date.now() });\n}\n\nexport function handleToolProgress(msg: WSServerMessage) {\n const payload = msg.payload as { id: string; name: string; event: { type: string; text?: string | undefined } };\n const text = (payload.event?.text ?? '').trim();\n if (!text) return;\n const messages = useChatStore.getState().messages;\n const owner = messages.find((m) => m.toolUseId === payload.id);\n if (!owner) return;\n const prefix = payload.event?.type === 'warning' ? '⚠ ' : '';\n useChatStore.getState().appendToolProgress(owner.id, prefix + text);\n}\n\nexport function handleToolExecuted(msg: WSServerMessage) {\n const payload = msg.payload as { id?: string | undefined; name: string; durationMs: number; ok: boolean; input?: unknown | undefined; output?: string | undefined };\n const { messages, currentToolId } = useChatStore.getState();\n const owner = payload.id ? messages.find((m) => m.toolUseId === payload.id) : currentToolId ? messages.find((m) => m.id === currentToolId) : undefined;\n if (owner?.toolResult !== undefined) return;\n if (owner) {\n useChatStore.getState().setToolResult(owner.id, payload.output ?? '', payload.ok);\n useChatStore.getState().updateMessage(owner.id, { toolDurationMs: payload.durationMs });\n }\n if (payload.id) useChatStore.getState().updateExecution(payload.id, { completedAt: Date.now(), durationMs: payload.durationMs, output: payload.output, ok: payload.ok });\n if (currentToolId && owner && owner.id === currentToolId) useChatStore.getState().setCurrentToolId(null);\n}\n\nexport function handleToolConfirmNeeded(msg: WSServerMessage) {\n const payload = msg.payload as { id: string; toolName: string; input: unknown; suggestedPattern: string };\n useUIStore.getState().showConfirm({ id: payload.id, toolName: payload.toolName, input: payload.input, suggestedPattern: payload.suggestedPattern });\n try { playPermissionChime(); } catch { /* audio policy */ }\n void ensureNotificationPermission();\n notifyIfHidden('WrongStack needs approval', `Tool \"${payload.toolName}\" is waiting for your decision.`, 'wrongstack-confirm');\n if (typeof document !== 'undefined' && document.hidden) setFaviconStatus('attention');\n}\n\nexport function handleRunResult(msg: WSServerMessage) {\n const payload = msg.payload as { status: string; iterations: number; finalText?: string | undefined; error?: { code: string | undefined; message: string; recoverable: boolean } };\n useSessionStore.getState().setIteration(null);\n useChatStore.getState().setLoading(false);\n useChatStore.getState().setCurrentAssistantMessage(null);\n useChatStore.getState().clearThinking();\n const runStart = useChatStore.getState().runStart;\n if (runStart && payload.status === 'done') {\n const all = useChatStore.getState().messages;\n let lastAssistantIdx = -1;\n let toolCount = 0;\n for (let i = all.length - 1; i >= 0; i--) {\n const m = expectDefined(all[i]);\n if (m.role === 'assistant' && lastAssistantIdx === -1 && m.content) lastAssistantIdx = i;\n if (m.role === 'tool' && m.timestamp >= runStart.at) toolCount += 1;\n if (m.role === 'user' && m.timestamp <= runStart.at) break;\n }\n if (lastAssistantIdx !== -1) {\n const sessionCost = useSessionStore.getState().cost;\n useChatStore.getState().updateMessage(all[lastAssistantIdx]?.id, { runSummary: { iterations: payload.iterations, tools: toolCount, durationMs: Date.now() - runStart.at, costDelta: Math.max(0, sessionCost - runStart.cost) } });\n }\n }\n useChatStore.getState().setRunStart(null);\n if (payload.status !== 'done' && payload.error) {\n useChatStore.getState().addMessage({ role: 'assistant', content: `Error: ${payload.error.message}`, isError: true });\n toast.error(`Run ended: ${payload.error.message}`);\n notifyIfHidden('WrongStack run failed', payload.error.message);\n if (typeof document !== 'undefined' && document.hidden) setFaviconStatus('error');\n } else if (payload.status === 'done') {\n if (typeof document !== 'undefined' && document.hidden) {\n toast.success(`Run completed in ${payload.iterations} iteration${payload.iterations === 1 ? '' : 's'}`);\n notifyIfHidden('WrongStack run finished', `Completed in ${payload.iterations} iteration${payload.iterations === 1 ? '' : 's'}.`);\n setFaviconStatus('ready');\n }\n void ensureNotificationPermission();\n if (useConfigStore.getState().soundOnComplete) {\n try { playCompletionChime(); } catch { /* audio policy */ }\n }\n }\n const next = useChatStore.getState().dequeue();\n if (next) {\n const client = getWSClient(useConfigStore.getState().wsUrl);\n useChatStore.getState().addMessage({ role: 'user', content: next });\n useChatStore.getState().setLoading(true);\n client.sendMessage(next);\n }\n}\n\n// ── Info / misc handlers ──\n\nexport function handleToolsList(msg: WSServerMessage) {\n const p = msg.payload as { tools: Array<{ name: string; description: string; params: string[] }> };\n useChatStore.getState().addMessage({ role: 'assistant', content: [\n `🛠️ **Registered tools** (${p.tools.length})`, '',\n ...p.tools.map((t) => `• \\`${t.name}\\`${t.params.length ? ` (${t.params.join(', ')})` : ''} — ${t.description || '_no description_'}`),\n ].join('\\n') });\n}\n\nexport function handleMemoryList(msg: WSServerMessage) {\n const p = msg.payload as { text: string; error?: string | undefined };\n const body = p.text?.trim();\n useChatStore.getState().addMessage({ role: 'assistant', content: p.error ? `Memory read failed: ${p.error}` : body ? `🧠 **Memory** \\n\\n${body}` : '🧠 **Memory** \\n\\n_empty — nothing remembered yet_' });\n}\n\nexport function handleSkillsList(msg: WSServerMessage) {\n const p = msg.payload as { enabled: boolean; error?: string | undefined; skills: Array<{ name: string; description: string; version: string; source: string; path: string; trigger: string; scope: string[] }> };\n if (!p.enabled) { useChatStore.getState().addMessage({ role: 'assistant', content: '🎯 **Skills** \\n\\n_disabled (config.features.skills = false)_' }); return; }\n const lines = [`🎯 **Skills** (${p.skills.length})`, '', ...(p.skills.length === 0 ? ['_none registered_'] : p.skills.map((s) => `• \\`${s.name}\\`${s.version ? ` v${s.version}` : ''} _(${s.source})_ — ${s.description || s.trigger || '_no description_'}`))];\n if (p.error) lines.push('', `⚠ ${p.error}`);\n useChatStore.getState().addMessage({ role: 'assistant', content: lines.join('\\n') });\n}\n\nexport function handleDiagGet(msg: WSServerMessage) {\n const p = msg.payload as { provider: string; model: string; cwd: string; sessionId: string; tools: { count: number; names: string[] }; features: { memory: boolean; skills: boolean; modelsRegistry: boolean }; mode: string; usage: { input: number; output: number; cacheRead?: number | undefined }; messages: number; todos: number };\n useChatStore.getState().addMessage({ role: 'assistant', content: [\n '🩺 **Runtime diagnostics**', '',\n `**Provider:** \\`${p.provider}\\` / \\`${p.model}\\``,\n `**Mode:** \\`${p.mode}\\``, `**Session:** \\`${p.sessionId}\\``, `**CWD:** \\`${p.cwd}\\``, '',\n `**Tools:** ${p.tools.count}`, `**Messages:** ${p.messages} · **Todos:** ${p.todos}`,\n `**Usage:** ${p.usage.input.toLocaleString()} in · ${p.usage.output.toLocaleString()} out${p.usage.cacheRead ? ` · ${p.usage.cacheRead.toLocaleString()} cache` : ''}`, '',\n `**Features:** memory=${p.features.memory ? '✓' : '✗'} · skills=${p.features.skills ? '✓' : '✗'} · modelsRegistry=${p.features.modelsRegistry ? '✓' : '✗'}`,\n ].join('\\n') });\n}\n\nexport function handleStatsGet(msg: WSServerMessage) {\n const p = msg.payload as { sessionId: string; provider: string; model: string; usage: { input: number; output: number; cacheRead?: number | undefined; cacheWrite?: number | undefined }; cache: { readTokens: number; writeTokens: number; hitRatio: number } | null; cost: number; messages: number; readFiles: number; tools: number; elapsedMs: number };\n const elapsedSec = Math.floor(p.elapsedMs / 1000);\n const elapsed = elapsedSec < 60 ? `${elapsedSec}s` : elapsedSec < 3600 ? `${Math.floor(elapsedSec / 60)}m ${elapsedSec % 60}s` : `${Math.floor(elapsedSec / 3600)}h ${Math.floor((elapsedSec % 3600) / 60)}m`;\n useChatStore.getState().addMessage({ role: 'assistant', content: [\n '📈 **Session stats**', '',\n `**Session:** \\`${p.sessionId}\\``, `**Provider/Model:** \\`${p.provider}\\` / \\`${p.model}\\``, `**Elapsed:** ${elapsed}`, '',\n `**Usage:** ${p.usage.input.toLocaleString()} in · ${p.usage.output.toLocaleString()} out`,\n ...(p.cache && p.cache.readTokens > 0 ? [`**Cache:** ${p.cache.readTokens.toLocaleString()} read · ${p.cache.writeTokens.toLocaleString()} write · hit ratio ${(p.cache.hitRatio * 100).toFixed(1)}%`] : []),\n `**Cost:** $${p.cost.toFixed(4)}`, '',\n `**Messages:** ${p.messages} · **Files read:** ${p.readFiles} · **Tools available:** ${p.tools}`,\n ].join('\\n') });\n}\n\nexport function handleTodosUpdated(msg: WSServerMessage) {\n const p = msg.payload as { todos: Array<{ id: string; content: string; status: 'pending' | 'in_progress' | 'completed'; activeForm?: string | undefined }> };\n useSessionStore.getState().setTodos(p.todos ?? []);\n}\n\nexport function handleModesList(msg: WSServerMessage) {\n const p = msg.payload as { modes: Array<{ id: string; name: string; description: string; isActive: boolean }>; activeId: string };\n useSessionStore.getState().setModes(p.modes.map((m) => ({ id: m.id, name: m.name, description: m.description })));\n useSessionStore.getState().setEnv({ mode: p.activeId });\n}\n\nexport function handleContextModesList(msg: WSServerMessage) {\n const p = msg.payload as { activeId: string; modes: Array<{ id: string; name: string; description: string; isActive: boolean; thresholds?: { warn: number | undefined; soft: number; hard: number }; preserveK?: number | undefined; eliseThreshold?: number | undefined }> };\n useSessionStore.getState().setContextModes(p.modes.map((m) => ({ id: m.id, name: m.name, description: m.description, thresholds: m.thresholds, preserveK: m.preserveK, eliseThreshold: m.eliseThreshold })));\n useSessionStore.getState().setEnv({ contextMode: p.activeId });\n}\n\nexport function handleContextModeChanged(msg: WSServerMessage) {\n const p = msg.payload as { id: string; name?: string | undefined };\n useSessionStore.getState().setEnv({ contextMode: p.id });\n}\n\nexport function handleSessionsList(msg: WSServerMessage) {\n const payload = msg.payload as { sessions: SessionHistoryEntry[]; error?: string | undefined };\n useHistoryStore.getState().setEntries(payload.sessions ?? [], payload.error ?? null);\n}\n\nexport function handleError(msg: WSServerMessage) {\n const payload = msg.payload as { phase: string; message: string };\n useChatStore.getState().addMessage({ role: 'assistant', content: `[${payload.phase}] ${payload.message}`, isError: true });\n useChatStore.getState().setLoading(false);\n}\n\n// ── Worktree / Fleet handlers ──\n\nexport function handleWorktreeState(msg: WSServerMessage) {\n const p = msg.payload as { worktrees: WorktreeHandleView[]; baseBranch: string };\n useWorktreeStore.getState().setSnapshot(p.worktrees ?? [], p.baseBranch ?? '');\n}\n\nexport function handleWorktreeEvent(msg: WSServerMessage) {\n const p = msg.payload as { kind: string; handleId: string; text: string; at: number };\n useWorktreeStore.getState().pushEvent(p);\n}\n\nexport function handleSubagentEvent(msg: WSServerMessage) {\n useFleetStore.getState().applyEvent(msg.payload as SubagentEvent);\n}\n\n// ── Handler registry: maps message types to handler functions ──\n\nexport const WS_HANDLERS: Record<string, (msg: WSServerMessage) => void> = {\n 'session.start': handleSessionStart,\n 'context.debug': handleContextDebug,\n 'key.operation_result': handleKeyOperationResult,\n 'context.compacted': handleContextCompacted,\n 'provider.response': handleProviderResponse,\n 'context.repaired': handleContextRepaired,\n 'session.end': handleSessionEnd,\n 'iteration.started': handleIterationStarted,\n 'provider.text_delta': handleTextDelta,\n 'provider.thinking_delta': handleThinkingDelta,\n 'tool.started': handleToolStarted,\n 'tool.progress': handleToolProgress,\n 'tool.executed': handleToolExecuted,\n 'tool.confirm_needed': handleToolConfirmNeeded,\n 'run.result': handleRunResult,\n 'tools.list': handleToolsList,\n 'memory.list': handleMemoryList,\n 'skills.list': handleSkillsList,\n 'diag.get': handleDiagGet,\n 'stats.get': handleStatsGet,\n 'todos.updated': handleTodosUpdated,\n 'modes.list': handleModesList,\n 'context.modes.list': handleContextModesList,\n 'context.mode.changed': handleContextModeChanged,\n 'sessions.list': handleSessionsList,\n 'error': handleError,\n 'worktree.state': handleWorktreeState,\n 'worktree.event': handleWorktreeEvent,\n 'subagent.event': handleSubagentEvent,\n};\n","import { useWebSocketBootstrap } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useChatStore, useConfigStore, useSessionStore, useUIStore } from '@/stores';\nimport { useEffect } from 'react';\nimport { ChatView } from './components/ChatView';\nimport { CollabPanel } from './components/CollabPanel';\nimport { CommandPalette, downloadChatAsMarkdown } from './components/CommandPalette';\nimport { ConfirmDialog } from './components/ConfirmDialog';\nimport { ConnectionBanner } from './components/ConnectionBanner';\nimport { ErrorBoundary } from './components/ErrorBoundary';\nimport { FleetPanel } from './components/FleetPanel';\nimport { QuickModelSwitcher } from './components/QuickModelSwitcher';\nimport { SettingsPanel } from './components/SettingsPanel';\nimport { ShortcutsOverlay } from './components/ShortcutsOverlay';\nimport { Sidebar } from './components/Sidebar';\nimport { ThemeProvider, useTheme } from './components/ThemeProvider';\nimport { Toaster } from './components/Toaster';\nimport { TodosPanel } from './components/TodosPanel';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\nfunction AppInner() {\n const { theme } = useTheme();\n const { currentView, sidebarOpen, toggleSidebar, setSearchOpen, setSidebarOpen } = useUIStore();\n const isLoading = useChatStore((s) => s.isLoading);\n const iteration = useSessionStore((s) => s.iteration);\n const projectName = useSessionStore((s) => s.projectName);\n const sessionTitle = useSessionStore((s) => s.session?.title);\n const sessionId = useSessionStore((s) => s.session?.id);\n // User-set local nickname for the current session — takes precedence\n // over the backend title in the tab strip and topbar.\n const nickname = useUIStore((s) => (sessionId ? s.sessionNicknames[sessionId] : undefined));\n\n // Mobile-friendly: collapse the sidebar automatically below the md\n // breakpoint (768px). Tracks viewport changes so a window resize behaves\n // the same as a fresh load. We only AUTO-close — re-opening (or keeping\n // it open) on small screens stays a user decision, so we never call\n // setSidebarOpen(true) here.\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const mq = window.matchMedia('(max-width: 768px)');\n const apply = () => {\n if (mq.matches && useUIStore.getState().sidebarOpen) {\n setSidebarOpen(false);\n }\n };\n apply();\n mq.addEventListener('change', apply);\n return () => mq.removeEventListener('change', apply);\n }, [setSidebarOpen]);\n // Install WS handlers exactly once for the whole app. Every other consumer\n // (ChatInput, ConfirmDialog, SettingsPanel) uses the cheap `useWebSocket()`\n // hook which returns action methods only — see hooks/useWebSocket.ts for\n // the duplicate-handler trap this avoids.\n useWebSocketBootstrap();\n\n // Reflect the agent's run state + session identity in the browser tab\n // title. Pinned/grouped tab strips become readable at a glance — the\n // project name surfaces first so multiple WrongStack windows on the same\n // bar can still be distinguished, then the session title (if any), then\n // the running indicator. Falls back gracefully when fields are missing.\n useEffect(() => {\n const parts: string[] = [];\n if (isLoading) {\n const it = iteration\n ? ` iter ${iteration.index}${iteration.max ? `/${iteration.max}` : ''}`\n : '';\n parts.push(`●${it}`);\n }\n const sessionLabel = nickname?.trim() || sessionTitle?.trim();\n const projectLabel = projectName?.trim();\n if (sessionLabel) parts.push(sessionLabel);\n if (projectLabel) parts.push(projectLabel);\n parts.push('WrongStack');\n const title = parts.filter(Boolean).join(' · ');\n document.title = title;\n return () => {\n document.title = 'WrongStack';\n };\n }, [isLoading, iteration, projectName, sessionTitle, nickname]);\n\n // Global keyboard shortcuts for the actions that don't have a dedicated\n // owner (palette/shortcuts handle their own). Bound here so they fire\n // anywhere except inside text inputs (where Ctrl+F should still search\n // the chat, but Ctrl+L would otherwise be a browser address-bar focus).\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const t = e.target as HTMLElement | null;\n const tag = t?.tagName?.toLowerCase();\n const inField = tag === 'input' || tag === 'textarea' || t?.isContentEditable;\n const mod = e.ctrlKey || e.metaKey;\n if (mod && e.key === '\\\\') {\n e.preventDefault();\n toggleSidebar();\n return;\n }\n if (mod && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n setSearchOpen(true);\n return;\n }\n if (mod && e.key.toLowerCase() === '/') {\n // Focus the chat textarea so the user can start typing without\n // hunting for it. Useful after closing palette/settings.\n e.preventDefault();\n const ta = document.querySelector('textarea');\n ta?.focus();\n return;\n }\n // The Ctrl-letter shortcuts skip when the user is typing in any\n // input — otherwise Ctrl+L wipes the chat while they're composing.\n // Access the WS client via the Zustand store instead of the `ws`\n // hook return value so we don't re-register this effect on every\n // render (useWebSocket() returns a fresh object each time).\n if (mod && !inField) {\n if (e.key.toLowerCase() === 'l') {\n e.preventDefault();\n useChatStore.getState().clearMessages();\n getWSClient(useConfigStore.getState().wsUrl)?.clearContext?.();\n } else if (e.key.toLowerCase() === 'n') {\n e.preventDefault();\n getWSClient(useConfigStore.getState().wsUrl)?.newSession?.();\n } else if (e.key.toLowerCase() === 'e') {\n e.preventDefault();\n downloadChatAsMarkdown();\n }\n }\n // Ctrl+Shift+D toggles compact UI density. Distinct from Ctrl+D\n // (which is reserved as the browser bookmark accelerator).\n if (mod && e.shiftKey && e.key.toLowerCase() === 'd') {\n e.preventDefault();\n useUIStore.getState().toggleCompactMode();\n }\n // Vim-style chat navigation: j/k step between bubbles, g goes to the\n // first message and G to the last. Skipped while typing so j/k inside\n // the textarea still inserts those letters. No modifier required —\n // this is the chat surface's primary input mode for keyboard users.\n if (!inField && !mod && !e.altKey) {\n const bubbles = Array.from(document.querySelectorAll<HTMLElement>('[data-message-id]'));\n if (bubbles.length === 0) return;\n const current = document.querySelector<HTMLElement>(\n '[data-message-id][data-focused=\"true\"]',\n );\n const idx = current ? bubbles.indexOf(current) : -1;\n const focusBubble = (target: HTMLElement) => {\n for (const b of bubbles) b.removeAttribute('data-focused');\n target.setAttribute('data-focused', 'true');\n target.scrollIntoView({ behavior: 'smooth', block: 'center' });\n };\n if (e.key === 'j' || e.key === 'ArrowDown') {\n // ArrowDown only intercepts when nothing else has focus AND the\n // user is not in a scrollable list context — the textarea check\n // above covers the only place arrows have meaningful default\n // behaviour for this app.\n const next = bubbles[Math.min(bubbles.length - 1, Math.max(0, idx + 1))];\n if (next) {\n e.preventDefault();\n focusBubble(next);\n }\n return;\n }\n if (e.key === 'k' || e.key === 'ArrowUp') {\n const prev = bubbles[Math.max(0, idx <= 0 ? 0 : idx - 1)];\n if (prev) {\n e.preventDefault();\n focusBubble(prev);\n }\n return;\n }\n if (e.key === 'g' && !e.shiftKey) {\n e.preventDefault();\n focusBubble(expectDefined(bubbles[0]));\n return;\n }\n if (e.key === 'G' || (e.key === 'g' && e.shiftKey)) {\n e.preventDefault();\n focusBubble(expectDefined(bubbles[bubbles.length - 1]));\n return;\n }\n if (e.key === 'Escape' && current) {\n e.preventDefault();\n current.removeAttribute('data-focused');\n return;\n }\n // `c` while a bubble is focused: copy its visible text. Useful\n // pairing with the j/k flow so power users can step + copy without\n // hunting for the in-bubble copy button.\n if (e.key === 'c' && current) {\n const text =\n current.querySelector<HTMLElement>('.markdown-content')?.innerText ?? current.innerText;\n if (text) {\n void navigator.clipboard?.writeText(text).catch(() => {});\n e.preventDefault();\n }\n return;\n }\n }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [toggleSidebar, setSearchOpen]);\n\n return (\n <div className={cn('flex h-screen', theme)}>\n {sidebarOpen && <Sidebar />}\n <main className=\"flex-1 flex flex-col overflow-hidden\">\n <ConnectionBanner />\n {currentView === 'chat' && (\n <>\n {sessionId && (\n <div className=\"px-4 pt-2 space-y-2\">\n <CollabPanel sessionId={sessionId} />\n {/* Live subagent roster — self-hides when no fleet is running. */}\n <FleetPanel />\n {/* Live agent todo list — self-hides when empty. */}\n <TodosPanel />\n </div>\n )}\n <ChatView />\n </>\n )}\n {currentView === 'settings' && <SettingsPanel />}\n </main>\n\n {/* Global overlays */}\n <ConfirmDialog />\n <CommandPalette />\n <ShortcutsOverlay />\n <QuickModelSwitcher />\n <Toaster />\n </div>\n );\n}\n\nexport function App() {\n return (\n <ErrorBoundary>\n <ThemeProvider defaultTheme=\"system\">\n <AppInner />\n </ThemeProvider>\n </ErrorBoundary>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useChatStore, useSessionStore, useUIStore } from '@/stores';\nimport type { ChatMessage } from '@/stores';\nimport { useConfigStore } from '@/stores';\nimport {\n Activity,\n ArrowDown,\n ArrowUp,\n Bot,\n Command,\n Cpu,\n FolderOpen,\n PanelLeftOpen,\n Settings,\n Zap,\n} from 'lucide-react';\nimport { type ReactNode, useCallback, useEffect, useRef, useState } from 'react';\nimport { ChatInput } from '../ChatInput';\nimport { ConnectionChip } from '../ConnectionChip';\nimport { ContextModePicker } from '../ContextModePicker';\nimport { CostChip } from '../CostChip';\nimport { MessageBubble } from '../MessageBubble';\nimport { ModePicker } from '../ModePicker';\nimport { SearchOverlay } from '../SearchOverlay';\nimport { ThemeToggle } from '../ThemeToggle';\nimport { ToolGroup } from '../ToolGroup';\nimport { WelcomeScreen } from '../WelcomeScreen';\nimport { Button } from '../ui/button';\nimport { ScrollArea } from '../ui/scroll-area';\nimport { fmtTok } from './utils.js';\nimport { ThinkingBubble } from './ThinkingBubble.js';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\nexport function ChatView() {\n const { messages, isLoading } = useChatStore();\n const setPaletteOpen = useUIStore((s) => s.setPaletteOpen);\n const setShortcutsOpen = useUIStore((s) => s.setShortcutsOpen);\n const sidebarOpen = useUIStore((s) => s.sidebarOpen);\n const toggleSidebar = useUIStore((s) => s.toggleSidebar);\n const compactMode = useUIStore((s) => s.compactMode);\n const { totalTokens, startTime, lastInputTokens, maxContext, projectName, iteration } =\n useSessionStore();\n const { wsConnected, wsStatus, provider, model } = useConfigStore();\n const { setCurrentView } = useUIStore();\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Context window usage\n const ctxPct =\n maxContext > 0 && lastInputTokens > 0\n ? Math.min(100, Math.round((lastInputTokens / maxContext) * 100))\n : 0;\n const ctxTone =\n ctxPct >= 85\n ? 'bg-red-500/15 text-red-600 dark:text-red-400'\n : ctxPct >= 70\n ? 'bg-amber-500/15 text-amber-600 dark:text-amber-400'\n : 'bg-muted text-muted-foreground';\n\n // Auto-scroll with \"user is reading older messages\" lock\n const [pinnedToBottom, setPinnedToBottom] = useState(true);\n const [unreadCount, setUnreadCount] = useState(0);\n const [scrolledDeep, setScrolledDeep] = useState(false);\n const lastSeenCount = useRef(messages.length);\n\n const getViewport = useCallback((): HTMLElement | null => {\n return scrollRef.current?.querySelector('[data-radix-scroll-area-viewport]') ?? null;\n }, []);\n\n useEffect(() => {\n const viewport = getViewport();\n if (!viewport) return;\n const onScroll = () => {\n const dist = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;\n const nowPinned = dist < 120;\n setPinnedToBottom(nowPinned);\n if (nowPinned) {\n setUnreadCount(0);\n lastSeenCount.current = messages.length;\n }\n const deep =\n viewport.scrollTop > viewport.clientHeight &&\n viewport.scrollHeight > viewport.clientHeight * 2.5;\n setScrolledDeep(deep);\n };\n viewport.addEventListener('scroll', onScroll, { passive: true });\n return () => viewport.removeEventListener('scroll', onScroll);\n }, [getViewport, messages.length]);\n\n useEffect(() => {\n const viewport = getViewport();\n if (!viewport) return;\n if (pinnedToBottom) {\n viewport.scrollTop = viewport.scrollHeight;\n lastSeenCount.current = messages.length;\n } else {\n const delta = messages.length - lastSeenCount.current;\n if (delta > 0) setUnreadCount(delta);\n }\n }, [messages, pinnedToBottom, getViewport]);\n\n const scrollToBottom = useCallback(() => {\n const viewport = getViewport();\n if (!viewport) return;\n viewport.scrollTo({ top: viewport.scrollHeight, behavior: 'smooth' });\n setPinnedToBottom(true);\n setUnreadCount(0);\n lastSeenCount.current = messages.length;\n }, [getViewport, messages.length]);\n\n const scrollToTop = useCallback(() => {\n const viewport = getViewport();\n if (!viewport) return;\n viewport.scrollTo({ top: 0, behavior: 'smooth' });\n }, [getViewport]);\n\n // Live \"agent is busy\" indicator\n const [runStartedAt, setRunStartedAt] = useState<number | null>(null);\n const [nowTick, setNowTick] = useState<number>(() => Date.now());\n const streamAnchor = useRef<{ id: string; at: number; len: number } | null>(null);\n useEffect(() => {\n if (isLoading && runStartedAt === null) setRunStartedAt(Date.now());\n if (!isLoading && runStartedAt !== null) setRunStartedAt(null);\n }, [isLoading, runStartedAt]);\n useEffect(() => {\n if (!isLoading) return;\n const t = setInterval(() => setNowTick(Date.now()), 500);\n return () => clearInterval(t);\n }, [isLoading]);\n\n const formatDuration = (start: number | null) => {\n if (!start) return '--';\n const seconds = Math.floor((Date.now() - start) / 1000);\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${minutes}m ${secs}s`;\n };\n\n const agentState = (() => {\n if (!isLoading) return 'idle' as const;\n const last = messages[messages.length - 1];\n const isStreaming = last?.role === 'assistant' && !!last.content && last.streaming;\n return isStreaming ? ('streaming' as const) : ('thinking' as const);\n })();\n const stateTone =\n agentState === 'idle'\n ? 'bg-muted text-muted-foreground'\n : agentState === 'streaming'\n ? 'bg-blue-500/10 text-blue-600 dark:text-blue-400'\n : 'bg-amber-500/10 text-amber-600 dark:text-amber-400';\n\n const hasStatusContent =\n (maxContext > 0 && lastInputTokens > 0) || totalTokens.input > 0 || !!startTime;\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Header */}\n <header className=\"flex flex-col border-b bg-card shrink-0\">\n <div className=\"flex items-center justify-between gap-2 px-3 py-2\">\n <div className=\"flex items-center gap-1.5 min-w-0 flex-1\">\n {!sidebarOpen && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 shrink-0\"\n onClick={toggleSidebar}\n title=\"Open sidebar (Ctrl+\\\\)\"\n >\n <PanelLeftOpen className=\"h-4 w-4\" />\n </Button>\n )}\n {!sidebarOpen && (\n <div className=\"flex items-center gap-1.5 shrink-0 mr-1\">\n <div className=\"w-5 h-5 rounded bg-primary flex items-center justify-center\">\n <Zap className=\"h-3 w-3 text-primary-foreground\" />\n </div>\n </div>\n )}\n <ConnectionChip wsStatus={wsStatus} wsConnected={wsConnected} />\n <span\n className={cn(\n 'flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0 tabular-nums',\n stateTone,\n )}\n title={`Agent state: ${agentState}`}\n >\n {agentState !== 'idle' && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-current animate-pulse\" />\n )}\n <span>{agentState}</span>\n </span>\n {projectName && (\n <span\n className=\"flex items-center gap-1 text-[11px] text-muted-foreground shrink-0 min-w-0\"\n title={`Project: ${projectName}`}\n >\n <FolderOpen className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate max-w-[12rem]\">{projectName}</span>\n </span>\n )}\n <button\n type=\"button\"\n onClick={() => useUIStore.getState().setModelSwitcherOpen(true)}\n className=\"group flex items-center gap-1 px-2 py-0.5 rounded-md border bg-background/50 hover:bg-accent hover:border-primary/40 transition-colors text-[11px] min-w-0 shrink-0\"\n title=\"Change provider / model (Ctrl+M)\"\n >\n <Cpu className=\"h-3 w-3 text-muted-foreground group-hover:text-foreground shrink-0\" />\n <span className=\"font-mono truncate max-w-[16rem]\">\n <span className=\"text-muted-foreground\">{provider || 'no-provider'}</span>\n <span className=\"text-muted-foreground/40 mx-0.5\">/</span>\n <span className=\"font-medium\">{model || 'no-model'}</span>\n </span>\n </button>\n <ModePicker />\n <ContextModePicker />\n {iteration && (\n <span\n className=\"flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium bg-primary/10 text-primary shrink-0\"\n title=\"Agent iteration\"\n >\n <Activity className=\"h-3 w-3 animate-pulse\" />\n iter {iteration.index}\n {iteration.max > 0 ? `/${iteration.max}` : ''}\n </span>\n )}\n </div>\n\n <div className=\"flex items-center gap-0.5 shrink-0\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7\"\n onClick={() => setPaletteOpen(true)}\n title=\"Command palette (Ctrl+K)\"\n >\n <Command className=\"h-4 w-4\" />\n </Button>\n <ThemeToggle className=\"mx-0.5\" />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 font-mono text-xs\"\n onClick={() => setShortcutsOpen(true)}\n title=\"Keyboard shortcuts (?)\"\n >\n ?\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7\"\n onClick={() => setCurrentView('settings')}\n title=\"Settings\"\n >\n <Settings className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n\n {hasStatusContent && (\n <div className=\"flex items-center justify-between gap-3 px-3 py-1 border-t bg-muted/20 text-[11px] text-muted-foreground\">\n <div className=\"flex items-center gap-3 min-w-0 flex-1 tabular-nums\">\n {maxContext > 0 && lastInputTokens > 0 && (\n <span\n className={cn(\n 'flex items-center gap-1 px-1.5 py-0.5 rounded-full font-medium shrink-0',\n ctxTone,\n )}\n title={`Last input: ${lastInputTokens.toLocaleString()} / ${maxContext.toLocaleString()} tokens`}\n >\n ctx {ctxPct}% · {fmtTok(lastInputTokens)}/{fmtTok(maxContext)}\n </span>\n )}\n {totalTokens.input > 0 && (\n <>\n <span className=\"flex items-center gap-1\">\n <span className=\"font-medium text-foreground\">{fmtTok(totalTokens.input)}</span>\n <span>in</span>\n </span>\n <span className=\"flex items-center gap-1\">\n <span className=\"font-medium text-foreground\">\n {fmtTok(totalTokens.output)}\n </span>\n <span>out</span>\n </span>\n {totalTokens.cacheRead &&\n totalTokens.cacheRead > 0 &&\n (() => {\n const denom = (totalTokens.cacheRead ?? 0) + totalTokens.input;\n const pct =\n denom > 0 ? Math.round(((totalTokens.cacheRead ?? 0) / denom) * 100) : 0;\n return (\n <span\n className=\"flex items-center gap-1\"\n title={`Cache hit ratio: ${pct}%`}\n >\n <span className=\"font-medium text-foreground\">\n {fmtTok(totalTokens.cacheRead)}\n </span>\n <span>cache ({pct}%)</span>\n </span>\n );\n })()}\n <CostChip />\n </>\n )}\n </div>\n {startTime && (\n <span className=\"text-muted-foreground/70 tabular-nums shrink-0\">\n {formatDuration(startTime)}\n </span>\n )}\n </div>\n )}\n </header>\n\n {/* Messages */}\n <div className=\"flex-1 relative overflow-hidden\">\n <SearchOverlay />\n {!pinnedToBottom && (\n <button\n type=\"button\"\n onClick={scrollToBottom}\n className={cn(\n 'absolute bottom-4 left-1/2 -translate-x-1/2 z-10',\n 'flex items-center gap-2 px-4 py-2 rounded-full shadow-lg',\n 'bg-primary text-primary-foreground text-xs font-medium',\n 'hover:bg-primary/90 transition-colors animate-message',\n )}\n >\n <ArrowDown className=\"h-3.5 w-3.5\" />\n {unreadCount > 0\n ? `${unreadCount} new message${unreadCount === 1 ? '' : 's'}`\n : 'Jump to latest'}\n </button>\n )}\n {scrolledDeep && (\n <button\n type=\"button\"\n onClick={scrollToTop}\n title=\"Scroll to top (oldest)\"\n className={cn(\n 'absolute top-3 right-3 z-10',\n 'flex items-center gap-1 px-2.5 py-1 rounded-full shadow-md border',\n 'bg-background/90 backdrop-blur-sm text-[11px] text-muted-foreground',\n 'hover:text-foreground hover:bg-background transition-colors animate-message',\n )}\n >\n <ArrowUp className=\"h-3 w-3\" />\n <span>Top</span>\n </button>\n )}\n <ScrollArea className=\"h-full\" ref={scrollRef}>\n <div\n className={cn(\n 'mx-auto pb-8',\n compactMode ? 'max-w-5xl p-3 space-y-3' : 'max-w-5xl p-4 space-y-6',\n )}\n >\n {messages.length === 0 && !isLoading && <WelcomeScreen />}\n\n {/* Two-pass grouping */}\n {(() => {\n type Group =\n | { kind: 'msg'; message: ChatMessage; isFirst: boolean }\n | { kind: 'tools'; tools: ChatMessage[]; key: string };\n const groups: Group[] = [];\n for (let i = 0; i < messages.length; i++) {\n const m = expectDefined(messages[i]);\n if (m.role === 'tool') {\n const last = groups[groups.length - 1];\n if (last && last.kind === 'tools') {\n last.tools.push(m);\n } else {\n groups.push({ kind: 'tools', tools: [m], key: m.id });\n }\n } else {\n const prev = messages[i - 1];\n groups.push({\n kind: 'msg',\n message: m,\n isFirst: !prev || prev.role !== m.role,\n });\n }\n }\n type Turn =\n | { kind: 'user'; message: ChatMessage; key: string }\n | { kind: 'agent'; items: Group[]; key: string };\n const turns: Turn[] = [];\n for (const g of groups) {\n if (g.kind === 'msg' && g.message.role === 'user') {\n turns.push({ kind: 'user', message: g.message, key: g.message.id });\n continue;\n }\n const last = turns[turns.length - 1];\n if (last && last.kind === 'agent') {\n last.items.push(g);\n } else {\n const key = g.kind === 'msg' ? g.message.id : g.key;\n turns.push({ kind: 'agent', items: [g], key });\n }\n }\n let prevDay: string | null = null;\n const dayKey = (ts: number) => {\n const d = new Date(ts);\n return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;\n };\n const dayLabel = (ts: number) => {\n const d = new Date(ts);\n const today = new Date();\n const yest = new Date(Date.now() - 86_400_000);\n if (dayKey(ts) === dayKey(today.getTime())) return 'Today';\n if (dayKey(ts) === dayKey(yest.getTime())) return 'Yesterday';\n return d.toLocaleDateString(undefined, {\n weekday: 'short',\n month: 'short',\n day: 'numeric',\n year: d.getFullYear() === today.getFullYear() ? undefined : 'numeric',\n });\n };\n const turnTs = (t: Turn): number => {\n if (t.kind === 'user') return t.message.timestamp;\n const first = expectDefined(t.items[0]);\n return first.kind === 'msg' ? first.message.timestamp : first.tools[0]?.timestamp;\n };\n const out: ReactNode[] = [];\n for (let idx = 0; idx < turns.length; idx++) {\n const t = expectDefined(turns[idx]);\n const ts = turnTs(t);\n const day = dayKey(ts);\n if (day !== prevDay) {\n out.push(\n <div\n key={`day-${day}-${idx}`}\n className=\"flex items-center gap-3 py-1 text-[11px] text-muted-foreground/70 uppercase tracking-wider font-medium\"\n >\n <div className=\"flex-1 h-px bg-border/50\" />\n <span>{dayLabel(ts)}</span>\n <div className=\"flex-1 h-px bg-border/50\" />\n </div>,\n );\n prevDay = day;\n }\n if (t.kind === 'user') {\n out.push(<MessageBubble key={t.key} message={t.message} isFirst />);\n continue;\n }\n const isLastTurn = idx === turns.length - 1;\n out.push(\n <div key={t.key} className={cn(compactMode ? 'space-y-1' : 'space-y-1.5')}>\n {t.items.map((g, gi) => {\n const continuation = gi > 0;\n if (g.kind === 'msg') {\n return (\n <MessageBubble\n key={g.message.id}\n message={g.message}\n isFirst={!continuation && g.isFirst}\n isContinuation={continuation}\n />\n );\n }\n const isLatestRunning =\n isLastTurn &&\n gi === t.items.length - 1 &&\n isLoading &&\n g.tools.some((tt) => tt.toolResult === undefined);\n return (\n <ToolGroup\n key={g.key}\n tools={g.tools}\n defaultOpen={isLatestRunning}\n isContinuation={continuation}\n />\n );\n })}\n </div>,\n );\n }\n return out;\n })()}\n\n <ThinkingBubble />\n\n {/* Running status bubble */}\n {isLoading &&\n (() => {\n const last = messages[messages.length - 1];\n const runningTools = messages.filter(\n (m) => m.role === 'tool' && m.toolResult === undefined,\n );\n let label = 'Thinking…';\n if (runningTools.length > 0) {\n const names = Array.from(\n new Set(runningTools.map((t) => t.toolName).filter(Boolean) as string[]),\n );\n const preview = names.slice(0, 2).join(', ');\n const more = names.length > 2 ? ` +${names.length - 2}` : '';\n label =\n runningTools.length === 1\n ? `Running ${preview || 'tool'}…`\n : `Running ${runningTools.length} tools (${preview}${more})…`;\n } else if (last?.role === 'assistant' && last.content) {\n label = 'Writing reply…';\n } else if (last?.role === 'tool' && last.toolResult !== undefined) {\n label = 'Thinking about the next step…';\n }\n const elapsedSec = runStartedAt\n ? Math.max(0, Math.floor((nowTick - runStartedAt) / 1000))\n : 0;\n const elapsed =\n elapsedSec < 60\n ? `${elapsedSec}s`\n : `${Math.floor(elapsedSec / 60)}m ${elapsedSec % 60}s`;\n let speedLabel = '';\n const streamingBubble =\n last?.role === 'assistant' && last.streaming && last.content ? last : null;\n if (streamingBubble) {\n const anchor = streamAnchor.current;\n if (!anchor || anchor.id !== streamingBubble.id) {\n streamAnchor.current = {\n id: streamingBubble.id,\n at: Date.now(),\n len: streamingBubble.content.length,\n };\n } else {\n const dt = Math.max(1, nowTick - anchor.at);\n const dl = Math.max(0, streamingBubble.content.length - anchor.len);\n if (dt > 500 && dl > 0) {\n const cps = (dl * 1000) / dt;\n speedLabel =\n cps >= 1000\n ? `${(cps / 1000).toFixed(1)}k ch/s`\n : `${Math.round(cps)} ch/s`;\n }\n }\n } else if (streamAnchor.current) {\n streamAnchor.current = null;\n }\n return (\n <div className=\"flex gap-3 animate-message\">\n <div className=\"flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center bg-accent text-accent-foreground ring-2 ring-offset-2 ring-offset-background ring-accent/20\">\n <Bot className=\"h-4 w-4\" />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <div className=\"rounded-2xl px-4 py-3 bg-card border text-foreground\">\n <div className=\"flex items-center gap-3 text-sm\">\n <span className=\"flex gap-1\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-primary/70 animate-bounce [animation-delay:-0.3s]\" />\n <span className=\"h-1.5 w-1.5 rounded-full bg-primary/70 animate-bounce [animation-delay:-0.15s]\" />\n <span className=\"h-1.5 w-1.5 rounded-full bg-primary/70 animate-bounce\" />\n </span>\n <span className=\"text-foreground/90\">{label}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n {elapsed}\n </span>\n {iteration && (\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n · iter {iteration.index}\n {iteration.max > 0 ? `/${iteration.max}` : ''}\n </span>\n )}\n {speedLabel && (\n <span className=\"text-xs text-muted-foreground/80 tabular-nums\">\n · {speedLabel}\n </span>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n })()}\n </div>\n </ScrollArea>\n </div>\n\n {/* Input */}\n <div className=\"border-t bg-card/50 backdrop-blur supports-[backdrop-filter]:bg-card/50 p-4 shrink-0\">\n <div className=\"max-w-5xl mx-auto\">\n <ChatInput />\n <p className=\"text-xs text-center text-muted-foreground/50 mt-2\">\n Press Enter to send, Shift+Enter for new line\n </p>\n </div>\n </div>\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\r\nimport { cn } from '@/lib/utils';\r\nimport { useChatStore, useSessionStore, useUIStore } from '@/stores';\r\nimport { Pencil, Send, Square } from 'lucide-react';\r\nimport type React from 'react';\r\nimport { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { downloadChatAsMarkdown } from './CommandPalette';\r\nimport { FilePicker } from './FilePicker';\r\nimport { Button } from './ui/button';\r\n\r\nimport { type SlashCommandDef, SLASH_COMMANDS, SLASH_CATEGORY_ORDER, matchSlash, detectAtMention } from './ChatInput/slash-commands.js';\r\n\r\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\nexport function ChatInput() {\r\n const { isLoading, setLoading, addMessage, clearMessages } = useChatStore();\r\n const queue = useChatStore((s) => s.queue);\r\n const enqueue = useChatStore((s) => s.enqueue);\r\n const removeQueued = useChatStore((s) => s.removeQueued);\r\n const clearQueue = useChatStore((s) => s.clearQueue);\r\n const { setCurrentView } = useUIStore();\r\n const pushPrompt = useUIStore((s) => s.pushPrompt);\r\n const promptHistory = useUIStore((s) => s.promptHistory);\r\n const ws = useWebSocket();\r\n const { sendMessage, sendAbort, client } = ws;\r\n /** Live context-budget signals — drive the token-estimate chip beside\r\n * the character counter. The estimate uses the universal 4-char-per-token\r\n * heuristic which is wrong by ±25% for natural prose but accurate enough\r\n * to warn the user before they paste a 100k-char file into a 200k window.\r\n * The chip only renders past the threshold so short drafts stay clean. */\r\n const lastInputTokens = useSessionStore((s) => s.lastInputTokens);\r\n const maxContext = useSessionStore((s) => s.maxContext);\r\n const [input, setInput] = useState('');\r\n const [slashIndex, setSlashIndex] = useState(0);\r\n /** Cursor into promptHistory. -1 = \"live input, not browsing history\".\r\n * Reset to -1 whenever the user types something that's NOT a history\r\n * navigation. */\r\n const [historyIdx, setHistoryIdx] = useState(-1);\r\n /** Open `@`-mention picker state. We track the starting position of the\r\n * `@` in the textarea so on pick we can replace the partial token\r\n * (`@compa`) with the chosen path. Null = closed. */\r\n const [atMention, setAtMention] = useState<{ start: number; query: string } | null>(null);\r\n /** Transient hint shown after a large paste. The user can read it for a\r\n * few seconds then it auto-dismisses. We only surface it for genuinely\r\n * big drops (>800 chars) — smaller pastes don't need a callout. */\r\n const [pasteHint, setPasteHint] = useState<{ chars: number; lines: number } | null>(null);\r\n /** True while an OS-drag is hovering over the input area. Triggers the\r\n * drop overlay so the user gets visual confirmation they're about to\r\n * attach. Browsers don't expose full filesystem paths from drops for\r\n * security reasons, so we seed the @-mention picker with the file's\r\n * basename and let the user confirm the resolved workspace path. */\r\n const [draggingOver, setDraggingOver] = useState(false);\r\n const textareaRef = useRef<HTMLTextAreaElement>(null);\r\n\r\n const runSlashCommand = useCallback(\r\n (raw: string): boolean => {\r\n const trimmed = raw.trim();\r\n // Split into head (with leading slash) + the rest. Lowercase the\r\n // head so `/Todos` and `/TODOS` route the same; preserve case on\r\n // the args because the user might be inserting a content string.\r\n const sp = trimmed.indexOf(' ');\r\n const head = (sp === -1 ? trimmed : trimmed.slice(0, sp)).toLowerCase();\r\n const args = sp === -1 ? '' : trimmed.slice(sp + 1).trim();\r\n const cmd = head;\r\n switch (cmd) {\r\n case '/help': {\r\n // Render the registry inline as an assistant message.\r\n const lines = [\r\n '📖 **Slash commands**',\r\n '',\r\n ...SLASH_COMMANDS.map(\r\n (c) =>\r\n `• \\`${c.name}\\`${c.aliases?.length ? ` (${c.aliases.map((a) => `\\`${a}\\``).join(', ')})` : ''} — ${c.description}`,\r\n ),\r\n ];\r\n addMessage({ role: 'assistant', content: lines.join('\\n') });\r\n return true;\r\n }\r\n case '/clear':\r\n clearMessages();\r\n client?.clearContext?.();\r\n return true;\r\n case '/new':\r\n client?.newSession?.();\r\n return true;\r\n case '/compact':\r\n case '/compact!':\r\n client?.compactContext?.(cmd === '/compact!');\r\n return true;\r\n case '/repair':\r\n client?.repairContext?.();\r\n return true;\r\n case '/debug':\r\n case '/context':\r\n client?.debugContext?.();\r\n return true;\r\n case '/tools':\r\n ws.listTools();\r\n return true;\r\n case '/memory':\r\n ws.listMemory();\r\n return true;\r\n case '/skill':\r\n case '/skills':\r\n ws.listSkills();\r\n return true;\r\n case '/diag':\r\n ws.getDiag();\r\n return true;\r\n case '/stats':\r\n ws.getStats();\r\n return true;\r\n case '/save':\r\n ws.saveSession();\r\n return true;\r\n case '/todos': {\r\n // Sub-commands: `/todos` (default = list), `/todos clear`. We\r\n // pull live state from the session store so the rendered output\r\n // matches what the sidebar already shows — no separate fetch.\r\n const sub = args.toLowerCase();\r\n if (sub === 'clear') {\r\n client?.clearTodos?.();\r\n return true;\r\n }\r\n const list = useSessionStore.getState().todos;\r\n if (list.length === 0) {\r\n addMessage({\r\n role: 'assistant',\r\n content:\r\n \"✅ **Todos** — _empty. Ask the agent to plan something and they'll show up here._\",\r\n });\r\n return true;\r\n }\r\n const lines: string[] = [\r\n `✅ **Todos** (${list.filter((t) => t.status === 'completed').length}/${list.length} done)`,\r\n '',\r\n ];\r\n for (const t of list) {\r\n const mark =\r\n t.status === 'completed' ? '[x]' : t.status === 'in_progress' ? '[~]' : '[ ]';\r\n const text = t.status === 'in_progress' && t.activeForm ? t.activeForm : t.content;\r\n lines.push(`- ${mark} ${text}`);\r\n }\r\n lines.push('', '_Use `/todos clear` to wipe the list._');\r\n addMessage({ role: 'assistant', content: lines.join('\\n') });\r\n return true;\r\n }\r\n case '/export':\r\n downloadChatAsMarkdown();\r\n addMessage({ role: 'assistant', content: '📥 Chat exported to your downloads folder.' });\r\n return true;\r\n case '/abort':\r\n case '/stop':\r\n sendAbort();\r\n setLoading(false);\r\n return true;\r\n case '/settings':\r\n case '/model':\r\n setCurrentView('settings');\r\n return true;\r\n default:\r\n return false;\r\n }\r\n },\r\n [addMessage, clearMessages, client, sendAbort, setLoading, setCurrentView, ws],\r\n );\r\n\r\n // Suggest slash commands as the user types. Only when the buffer is\r\n // exactly a slash command head — `/foo bar` shouldn't open the popup.\r\n const slashSuggestions = input.startsWith('/') && !input.includes(' ') ? matchSlash(input) : [];\r\n\r\n // Reset the highlight when the visible list changes so ↑/↓ always starts\r\n // from the top of the new matches.\r\n useEffect(() => {\r\n if (slashIndex >= slashSuggestions.length) setSlashIndex(0);\r\n }, [slashSuggestions.length, slashIndex]);\r\n\r\n /** Direct textarea DOM clear — bypasses useState so the UI updates\r\n * even when React batches the state update. */\r\n const _clearTextarea = useCallback(() => {\r\n const ta = textareaRef.current;\r\n if (ta) {\r\n ta.value = '';\r\n ta.style.height = 'auto';\r\n ta.style.height = `${Math.min(ta.scrollHeight, 200)}px`;\r\n if (!isLoading) { ta.focus(); }\r\n }\r\n }, [isLoading]);\r\n\r\n const handleSubmit = useCallback(\r\n async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!input.trim()) return;\r\n\r\n const content = input.trim();\r\n\r\n if (content.startsWith('/') && runSlashCommand(content)) {\r\n pushPrompt(content);\r\n setInput('');\r\n setHistoryIdx(-1);\r\n _clearTextarea();\r\n return;\r\n }\r\n\r\n setInput('');\r\n setHistoryIdx(-1);\r\n _clearTextarea();\r\n pushPrompt(content);\r\n _clearTextarea(); // ensure textarea is cleared even if batching delays state\r\n\r\n // If the agent is still running, queue the follow-up instead of\r\n // dropping it. The run.result handler in useWebSocket drains the\r\n // queue one message at a time. We also enable the textarea while\r\n // running so this code path is reachable.\r\n if (isLoading) {\r\n enqueue(content);\r\n return;\r\n }\r\n\r\n try {\r\n if (client?.isConnected) {\r\n addMessage({ role: 'user', content });\r\n setLoading(true);\r\n sendMessage(content);\r\n } else {\r\n console.error('WebSocket not connected');\r\n }\r\n } catch (err) {\r\n console.error('Failed to send:', err);\r\n setLoading(false);\r\n }\r\n },\r\n [\r\n input,\r\n isLoading,\r\n enqueue,\r\n client,\r\n sendMessage,\r\n setLoading,\r\n addMessage,\r\n runSlashCommand,\r\n pushPrompt,\r\n _clearTextarea,\r\n ],\r\n );\r\n\r\n const handleAbort = useCallback(() => {\r\n sendAbort();\r\n setLoading(false);\r\n }, [sendAbort, setLoading]);\r\n\r\n /** \"Stop & edit\" — abort the in-flight run, then pull the last user\r\n * message back into the input so the user can rewrite the prompt and\r\n * resend. Saves the two-step dance of clicking Abort, waiting for the\r\n * agent to settle, then hunting for the original prompt. */\r\n const handleStopAndEdit = useCallback(() => {\r\n sendAbort();\r\n setLoading(false);\r\n const all = useChatStore.getState().messages;\r\n for (let i = all.length - 1; i >= 0; i--) {\r\n const m = expectDefined(all[i]);\r\n if (m.role === 'user' && m.content) {\r\n setInput(m.content);\r\n requestAnimationFrame(() => {\r\n const ta = textareaRef.current;\r\n if (ta) {\r\n ta.style.height = 'auto';\r\n ta.style.height = `${Math.min(ta.scrollHeight, 200)}px`;\r\n ta.focus();\r\n ta.setSelectionRange(m.content.length, m.content.length);\r\n }\r\n });\r\n return;\r\n }\r\n }\r\n }, [sendAbort, setLoading]);\r\n\r\n const handleKeyDown = useCallback(\r\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\r\n // Terminal-style prompt history: ↑ pulls the previous user prompt,\r\n // ↓ steps forward. Only active when both popups are closed AND the\r\n // input is empty OR already showing a history entry. We keep the cursor\r\n // ergonomic — once the user starts editing, we drop out of history mode.\r\n if (slashSuggestions.length === 0 && !atMention && promptHistory.length > 0) {\r\n if (e.key === 'ArrowUp') {\r\n const ta = e.currentTarget;\r\n // Only steal ↑ if we're on the first line (so multi-line editing\r\n // can still navigate within the textarea naturally).\r\n const beforeCursor = ta.value.slice(0, ta.selectionStart);\r\n if (historyIdx >= 0 || beforeCursor.indexOf('\\n') === -1) {\r\n e.preventDefault();\r\n const next = Math.min(promptHistory.length - 1, historyIdx + 1);\r\n setHistoryIdx(next);\r\n const text = promptHistory[next] ?? '';\r\n setInput(text);\r\n requestAnimationFrame(() => {\r\n const el = textareaRef.current;\r\n if (el) {\r\n el.style.height = 'auto';\r\n el.style.height = `${Math.min(el.scrollHeight, 200)}px`;\r\n el.setSelectionRange(text.length, text.length);\r\n }\r\n });\r\n return;\r\n }\r\n }\r\n if (e.key === 'ArrowDown' && historyIdx >= 0) {\r\n e.preventDefault();\r\n const next = historyIdx - 1;\r\n if (next < 0) {\r\n setHistoryIdx(-1);\r\n setInput('');\r\n } else {\r\n setHistoryIdx(next);\r\n const text = promptHistory[next] ?? '';\r\n setInput(text);\r\n requestAnimationFrame(() => {\r\n const el = textareaRef.current;\r\n if (el) {\r\n el.style.height = 'auto';\r\n el.style.height = `${Math.min(el.scrollHeight, 200)}px`;\r\n el.setSelectionRange(text.length, text.length);\r\n }\r\n });\r\n }\r\n return;\r\n }\r\n }\r\n\r\n // Slash popup keyboard navigation: ↑/↓ to select, Tab/Enter to commit,\r\n // Esc to dismiss. Matches the TUI's slash menu UX one-for-one so users\r\n // moving between surfaces don't have to relearn anything.\r\n if (slashSuggestions.length > 0) {\r\n if (e.key === 'ArrowDown') {\r\n e.preventDefault();\r\n setSlashIndex((i) => (i + 1) % slashSuggestions.length);\r\n return;\r\n }\r\n if (e.key === 'ArrowUp') {\r\n e.preventDefault();\r\n setSlashIndex((i) => (i - 1 + slashSuggestions.length) % slashSuggestions.length);\r\n return;\r\n }\r\n if (e.key === 'Tab') {\r\n e.preventDefault();\r\n const pick = slashSuggestions[slashIndex];\r\n if (pick) {\r\n setInput(pick.name + ' ');\r\n setSlashIndex(0);\r\n }\r\n return;\r\n }\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n // Commit the highlighted suggestion if there's an exact match below\r\n // the cursor (or the user hasn't typed a full name yet). Otherwise\r\n // fall through to normal submit.\r\n const pick = slashSuggestions[slashIndex];\r\n if (pick && pick.name !== input.toLowerCase().trim()) {\r\n e.preventDefault();\r\n setInput('');\r\n runSlashCommand(pick.name);\r\n return;\r\n }\r\n }\r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n setInput('');\r\n return;\r\n }\r\n }\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSubmit(e);\r\n }\r\n },\r\n [slashSuggestions, slashIndex, atMention, promptHistory, historyIdx, input, runSlashCommand, handleSubmit],\r\n );\r\n\r\n const adjustTextareaHeight = () => {\r\n const textarea = textareaRef.current;\r\n if (textarea) {\r\n textarea.style.height = 'auto';\r\n textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"flex flex-col gap-2\">\r\n {/* Smart paste hint — transient, auto-dismisses after 4s. We don't\r\n *do* anything with it (no auto-attach), just inform; users who\r\n pasted by accident can still Cmd+Z. */}\r\n {pasteHint && (\r\n <div className=\"rounded-md border border-amber-500/30 bg-amber-500/5 text-amber-700 dark:text-amber-300 px-2.5 py-1.5 text-xs flex items-center justify-between gap-2 animate-message\">\r\n <span>\r\n Pasted{' '}\r\n <span className=\"font-mono tabular-nums\">{pasteHint.chars.toLocaleString()}</span> chars\r\n (<span className=\"font-mono tabular-nums\">{pasteHint.lines}</span> lines) — fenced code\r\n blocks render best with <span className=\"font-mono\">```</span>.\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={() => setPasteHint(null)}\r\n className=\"text-amber-600/70 hover:text-amber-600 dark:text-amber-300/70 dark:hover:text-amber-300 shrink-0\"\r\n title=\"Dismiss\"\r\n >\r\n ×\r\n </button>\r\n </div>\r\n )}\r\n {/* Queue visualization — shows messages the user stacked while the\r\n agent was still running. Each row has a remove button; the whole\r\n queue can be cleared. The hook below drains them after run.result. */}\r\n {queue.length > 0 && (\r\n <div className=\"rounded-lg border bg-muted/30 p-2 text-xs\">\r\n <div className=\"flex items-center justify-between mb-1.5\">\r\n <span className=\"text-[10px] uppercase tracking-wider text-muted-foreground font-medium\">\r\n Queued ({queue.length})\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={clearQueue}\r\n className=\"text-muted-foreground hover:text-destructive text-xs\"\r\n >\r\n Clear all\r\n </button>\r\n </div>\r\n <ul className=\"space-y-1\">\r\n {queue.map((q, i) => (\r\n <li\r\n // biome-ignore lint/suspicious/noArrayIndexKey: queue has stable order\r\n key={i}\r\n className=\"flex items-start justify-between gap-2 rounded bg-background/60 border px-2 py-1\"\r\n >\r\n <span className=\"truncate flex-1 min-w-0\">{q}</span>\r\n <button\r\n type=\"button\"\r\n onClick={() => removeQueued(i)}\r\n className=\"text-muted-foreground hover:text-destructive shrink-0\"\r\n title=\"Remove from queue\"\r\n >\r\n ×\r\n </button>\r\n </li>\r\n ))}\r\n </ul>\r\n </div>\r\n )}\r\n\r\n <form\r\n onSubmit={handleSubmit}\r\n onDragEnter={(e) => {\r\n // Only react to drags carrying files — text/uri-list drags from\r\n // other parts of the page shouldn't trip the overlay.\r\n if (!e.dataTransfer || !Array.from(e.dataTransfer.types).includes('Files')) return;\r\n e.preventDefault();\r\n setDraggingOver(true);\r\n }}\r\n onDragOver={(e) => {\r\n if (!e.dataTransfer || !Array.from(e.dataTransfer.types).includes('Files')) return;\r\n // preventDefault on dragover is what makes the area a valid drop\r\n // target — without it the browser navigates to the file instead.\r\n e.preventDefault();\r\n e.dataTransfer.dropEffect = 'copy';\r\n }}\r\n onDragLeave={(e) => {\r\n // dragleave fires when crossing child boundaries too; only clear if\r\n // the cursor genuinely left the form (relatedTarget outside or null).\r\n if (e.currentTarget.contains(e.relatedTarget as Node | null)) return;\r\n setDraggingOver(false);\r\n }}\r\n onDrop={(e) => {\r\n if (!e.dataTransfer) return;\r\n const files = Array.from(e.dataTransfer.files ?? []);\r\n if (files.length === 0) {\r\n setDraggingOver(false);\r\n return;\r\n }\r\n e.preventDefault();\r\n setDraggingOver(false);\r\n // Insert `@<filename>` per dropped file at the current cursor, with\r\n // spaces between them. Browsers strip the full path for security, so\r\n // we use the basename only — the FilePicker (opened by setting\r\n // atMention to the last inserted handle) will resolve it against\r\n // the workspace tree.\r\n const ta = textareaRef.current;\r\n const insertPos = ta?.selectionStart ?? input.length;\r\n const before = input.slice(0, insertPos);\r\n const after = input.slice(insertPos);\r\n const needsLeadingSpace = before.length > 0 && !/\\s$/.test(before);\r\n const lead = needsLeadingSpace ? ' ' : '';\r\n const tokens = files.map((f) => `@${f.name}`);\r\n const joined = tokens.join(' ');\r\n // Trailing space only when there isn't already one — keeps the\r\n // cursor neatly between insert and following text.\r\n const needsTrailingSpace = after.length === 0 || !/^\\s/.test(after);\r\n const trail = needsTrailingSpace ? ' ' : '';\r\n const insertion = `${lead}${joined}${trail}`;\r\n const next = before + insertion + after;\r\n setInput(next);\r\n // Open the FilePicker against the LAST dropped basename so the user\r\n // can replace the basename with the correctly-resolved workspace\r\n // path. Position the @-mention start at the `@` of the last token.\r\n const lastTokenStart =\r\n before.length +\r\n lead.length +\r\n tokens.slice(0, -1).join(' ').length +\r\n (tokens.length > 1 ? 1 : 0);\r\n const lastBasename = files[files.length - 1]?.name;\r\n requestAnimationFrame(() => {\r\n if (ta) {\r\n const cur = before.length + insertion.length - trail.length;\r\n ta.focus();\r\n ta.setSelectionRange(cur, cur);\r\n ta.style.height = 'auto';\r\n ta.style.height = `${Math.min(ta.scrollHeight, 200)}px`;\r\n }\r\n setAtMention({ start: lastTokenStart, query: lastBasename });\r\n });\r\n }}\r\n className={cn(\r\n 'flex items-end gap-2 relative rounded-lg transition-colors',\r\n draggingOver && 'ring-2 ring-primary ring-offset-2 ring-offset-background bg-primary/5',\r\n )}\r\n >\r\n {draggingOver && (\r\n <div className=\"absolute inset-0 z-20 flex items-center justify-center pointer-events-none rounded-lg bg-primary/10 text-primary text-sm font-medium\">\r\n Drop file{`(s)`} to attach as @-mention\r\n </div>\r\n )}\r\n <div className=\"relative flex-1\">\r\n {/* @-mention file picker — takes priority over the slash popup\r\n since `@` and `/` can't both be active at the cursor. */}\r\n {atMention && (\r\n <FilePicker\r\n query={atMention.query}\r\n onClose={() => setAtMention(null)}\r\n onPick={(p) => {\r\n // Replace the partial `@query` with `@<path> `, then move\r\n // the cursor after the inserted space so typing continues\r\n // naturally.\r\n const before = input.slice(0, atMention.start);\r\n const after = input.slice(atMention.start + 1 + atMention.query.length);\r\n const inserted = `@${p} `;\r\n const next = before + inserted + after;\r\n setInput(next);\r\n setAtMention(null);\r\n requestAnimationFrame(() => {\r\n const ta = textareaRef.current;\r\n if (ta) {\r\n const pos = before.length + inserted.length;\r\n ta.focus();\r\n ta.setSelectionRange(pos, pos);\r\n ta.style.height = 'auto';\r\n ta.style.height = `${Math.min(ta.scrollHeight, 200)}px`;\r\n }\r\n });\r\n }}\r\n />\r\n )}\r\n\r\n {/* Slash command popup — descriptions inline, ↑/↓ to select, Tab to\r\n autocomplete, Enter to dispatch directly. Click also works. */}\r\n {!atMention &&\r\n slashSuggestions.length > 0 &&\r\n (() => {\r\n // Bucket the suggestions by category and preserve the global\r\n // index across categories — the keyboard navigation (↑/↓) tracks\r\n // a flat index, so each rendered row needs to map back to its\r\n // position in the un-grouped `slashSuggestions` array.\r\n const byCategory: Record<string, Array<{ cmd: SlashCommandDef; idx: number }>> = {};\r\n slashSuggestions.forEach((cmd, idx) => {\r\n if (!byCategory[cmd.category]) byCategory[cmd.category] = [];\r\n byCategory[cmd.category]?.push({ cmd, idx });\r\n });\r\n const orderedCategories = SLASH_CATEGORY_ORDER.filter((c) => byCategory[c]?.length);\r\n return (\r\n <div className=\"absolute bottom-full left-0 right-0 mb-2 rounded-lg border bg-popover shadow-md p-1 text-sm max-h-72 overflow-auto\">\r\n <div className=\"px-3 py-1 text-[10px] uppercase tracking-wider text-muted-foreground border-b mb-1\">\r\n ↑/↓ select · Tab complete · Enter dispatch · Esc dismiss\r\n </div>\r\n {orderedCategories.map((cat) => (\r\n <div key={cat} className=\"mb-1\">\r\n <div className=\"px-3 pt-1 pb-0.5 text-[10px] uppercase tracking-wider text-muted-foreground/70 font-semibold\">\r\n {cat}\r\n </div>\r\n {byCategory[cat]?.map(({ cmd, idx }) => (\r\n <button\r\n type=\"button\"\r\n key={cmd.name}\r\n onClick={() => {\r\n setInput('');\r\n runSlashCommand(cmd.name);\r\n }}\r\n onMouseEnter={() => setSlashIndex(idx)}\r\n className={cn(\r\n 'w-full text-left px-3 py-1.5 rounded transition-colors flex items-center gap-3',\r\n idx === slashIndex\r\n ? 'bg-accent text-accent-foreground'\r\n : 'hover:bg-accent/40',\r\n )}\r\n >\r\n <span className=\"font-mono shrink-0\">{cmd.name}</span>\r\n {cmd.aliases?.length ? (\r\n <span className=\"text-xs text-muted-foreground/70 font-mono shrink-0\">\r\n ({cmd.aliases.join(', ')})\r\n </span>\r\n ) : null}\r\n <span className=\"text-xs text-muted-foreground truncate\">\r\n — {cmd.description}\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n })()}\r\n <textarea\r\n ref={textareaRef}\r\n value={input}\r\n onChange={(e) => {\r\n const v = e.target.value;\r\n setInput(v);\r\n adjustTextareaHeight();\r\n // Manual typing drops us out of history mode so the next\r\n // Enter sends the user's edits, not a stale history entry.\r\n if (historyIdx >= 0) setHistoryIdx(-1);\r\n // Detect / refresh @-mention based on cursor position.\r\n const cur = e.target.selectionStart ?? v.length;\r\n setAtMention(detectAtMention(v, cur));\r\n }}\r\n onSelect={(e) => {\r\n const ta = e.currentTarget;\r\n setAtMention(detectAtMention(ta.value, ta.selectionStart));\r\n }}\r\n onKeyDown={handleKeyDown}\r\n onPaste={(e) => {\r\n // Surface a tiny hint when the user drops a chunky payload —\r\n // helps them realize they pasted the wrong thing (e.g. an\r\n // entire file when they meant a snippet). 4-second TTL.\r\n const text = e.clipboardData?.getData('text') ?? '';\r\n if (text.length > 800) {\r\n const lines = text.split('\\n').length;\r\n setPasteHint({ chars: text.length, lines });\r\n setTimeout(() => setPasteHint(null), 4000);\r\n }\r\n }}\r\n placeholder={\r\n !client?.isConnected\r\n ? 'Connect to server first…'\r\n : isLoading\r\n ? 'Agent is running — type to queue a follow-up…'\r\n : 'Message WrongStack… (type / for commands, @ for files)'\r\n }\r\n className={cn(\r\n 'flex min-h-[44px] w-full resize-none rounded-lg border border-input bg-background px-4 py-3 pr-12',\r\n 'text-sm ring-offset-background placeholder:text-muted-foreground',\r\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\r\n 'disabled:cursor-not-allowed disabled:opacity-50',\r\n 'scrollbar-thin',\r\n )}\r\n rows={1}\r\n disabled={!client?.isConnected}\r\n />\r\n\r\n {input.length > 0 &&\r\n (() => {\r\n // Hide the token estimate until the draft is non-trivial — small\r\n // messages aren't worth a context warning, and the chip would\r\n // otherwise just flicker as the user types each character.\r\n const showTokens = input.length >= 400;\r\n const estTokens = Math.ceil(input.length / 4);\r\n // Project the next request's context usage: last sent + draft +\r\n // small overhead. If that crosses 85% of the configured window,\r\n // tint amber; past 100% turns red. Falls through to muted when\r\n // we don't have the window size yet (e.g. before first request).\r\n let tone = 'text-muted-foreground';\r\n let title: string | undefined;\r\n if (maxContext > 0 && showTokens) {\r\n const projected = lastInputTokens + estTokens + 64;\r\n const pct = (projected / maxContext) * 100;\r\n if (pct >= 100) {\r\n tone = 'text-red-600 dark:text-red-400 font-medium';\r\n title = `Projected ${Math.round(pct)}% of ${maxContext.toLocaleString()} ctx — will likely error or compact.`;\r\n } else if (pct >= 85) {\r\n tone = 'text-amber-600 dark:text-amber-400 font-medium';\r\n title = `Projected ${Math.round(pct)}% of ${maxContext.toLocaleString()} ctx — getting tight.`;\r\n } else {\r\n title = `≈ ${estTokens.toLocaleString()} tokens · projected ${Math.round(pct)}% of ${maxContext.toLocaleString()} ctx.`;\r\n }\r\n } else if (showTokens) {\r\n title = `≈ ${estTokens.toLocaleString()} tokens (4-char heuristic)`;\r\n }\r\n return (\r\n <span\r\n className={cn('absolute bottom-1.5 right-12 text-xs tabular-nums', tone)}\r\n title={title}\r\n >\r\n {input.length}\r\n {showTokens && (\r\n <span className=\"ml-1 opacity-70\">\r\n · ≈{estTokens >= 1000 ? `${(estTokens / 1000).toFixed(1)}k` : estTokens}t\r\n </span>\r\n )}\r\n </span>\r\n );\r\n })()}\r\n </div>\r\n\r\n <div className=\"flex gap-1\">\r\n {isLoading ? (\r\n <>\r\n <Button\r\n type=\"button\"\r\n size=\"icon\"\r\n variant=\"outline\"\r\n onClick={handleStopAndEdit}\r\n className=\"h-[44px] w-[44px] rounded-lg\"\r\n title=\"Stop run and edit the last prompt (reuse + rewrite)\"\r\n >\r\n <Pencil className=\"h-4 w-4\" />\r\n </Button>\r\n <Button\r\n type=\"button\"\r\n size=\"icon\"\r\n variant=\"destructive\"\r\n onClick={handleAbort}\r\n className=\"h-[44px] w-[44px] rounded-lg\"\r\n title=\"Abort the current run\"\r\n >\r\n <Square className=\"h-4 w-4 fill-current\" />\r\n </Button>\r\n </>\r\n ) : (\r\n <Button\r\n type=\"submit\"\r\n size=\"icon\"\r\n disabled={!input.trim() || !client?.isConnected}\r\n className=\"h-[44px] w-[44px] rounded-lg\"\r\n >\r\n <Send className=\"h-4 w-4\" />\r\n </Button>\r\n )}\r\n </div>\r\n </form>\r\n </div>\r\n );\r\n}\r\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { playCompletionChime } from '@/lib/chime';\nimport { cn } from '@/lib/utils';\nimport {\n useChatStore,\n useConfigStore,\n useHistoryStore,\n useUIStore,\n} from '@/stores';\nimport {\n ArchiveRestore,\n BarChart3,\n Brain,\n Cpu,\n Database,\n Download,\n Hash,\n History as HistoryIcon,\n type LucideIcon,\n Maximize2,\n Monitor,\n Moon,\n RotateCcw,\n Search,\n Settings as SettingsIcon,\n Sparkles,\n Stethoscope,\n Sun,\n Trash2,\n Volume2,\n VolumeX,\n Wrench,\n} from 'lucide-react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { downloadChatAsHtml, downloadChatAsMarkdown } from './export-utils.js';\n\ninterface PaletteItem {\n id: string;\n category: 'Command' | 'Session' | 'Theme' | 'Tool';\n label: string;\n hint?: string | undefined;\n icon: LucideIcon;\n keywords?: string[] | undefined;\n run: () => void;\n}\n\nexport function CommandPalette() {\n const open = useUIStore((s) => s.paletteOpen);\n const setOpen = useUIStore((s) => s.setPaletteOpen);\n const setCurrentView = useUIStore((s) => s.setCurrentView);\n const setTheme = useConfigStore((s) => s.setTheme);\n const { entries: historyEntries } = useHistoryStore();\n const { addMessage, clearMessages } = useChatStore();\n const ws = useWebSocket();\n\n const [query, setQuery] = useState('');\n const [index, setIndex] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (open) {\n setQuery('');\n setIndex(0);\n requestAnimationFrame(() => inputRef.current?.focus());\n }\n }, [open]);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') {\n e.preventDefault();\n setOpen(!useUIStore.getState().paletteOpen);\n return;\n }\n if (e.key === 'Escape' && useUIStore.getState().paletteOpen) {\n e.preventDefault();\n setOpen(false);\n }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [setOpen]);\n\n const items = useMemo<PaletteItem[]>(() => {\n const base: PaletteItem[] = [\n {\n id: 'help', category: 'Command', label: 'Show slash commands',\n icon: Hash, keywords: ['help', 'commands', '?'],\n run: () => { addMessage({ role: 'assistant', content: 'Type `/` in the message box to see every slash command.' }); },\n },\n {\n id: 'tools', category: 'Command', label: 'List tools',\n icon: Wrench, keywords: ['tools', 'list'],\n run: () => ws.listTools(),\n },\n {\n id: 'memory', category: 'Command', label: 'Show memory',\n icon: Brain, keywords: ['memory', 'remember', 'notes'],\n run: () => ws.listMemory(),\n },\n {\n id: 'skills', category: 'Command', label: 'List skills',\n icon: Sparkles, keywords: ['skills'],\n run: () => ws.listSkills(),\n },\n {\n id: 'diag', category: 'Command', label: 'Runtime diagnostics',\n icon: Stethoscope, keywords: ['diag', 'diagnostics', 'debug'],\n run: () => ws.getDiag(),\n },\n {\n id: 'stats', category: 'Command', label: 'Session stats (tokens, cache, cost)',\n icon: BarChart3, keywords: ['stats', 'tokens', 'cost', 'cache'],\n run: () => ws.getStats(),\n },\n {\n id: 'clear', category: 'Session', label: 'Clear context',\n hint: 'Wipe in-memory context, keep session id',\n icon: Trash2, keywords: ['clear', 'reset', 'wipe'],\n run: () => { clearMessages(); ws.client?.clearContext?.(); },\n },\n {\n id: 'new', category: 'Session', label: 'New session',\n hint: 'Brand-new on disk + memory',\n icon: RotateCcw, keywords: ['new', 'fresh', 'session'],\n run: () => ws.client?.newSession?.(),\n },\n {\n id: 'compact', category: 'Session', label: 'Compact context',\n icon: Database, keywords: ['compact', 'shrink', 'context'],\n run: () => ws.client?.compactContext?.(),\n },\n {\n id: 'repair-context', category: 'Session', label: 'Repair context',\n hint: 'Remove orphan tool protocol blocks',\n icon: Wrench, keywords: ['repair', 'context', 'tool_use', 'tool_result'],\n run: () => ws.client?.repairContext?.(),\n },\n {\n id: 'export', category: 'Session', label: 'Export chat as markdown',\n icon: Download, keywords: ['export', 'save', 'markdown', 'download'],\n run: () => downloadChatAsMarkdown(),\n },\n {\n id: 'export-html', category: 'Session', label: 'Export chat as HTML',\n hint: 'Self-contained, opens in any browser',\n icon: Download, keywords: ['export', 'html', 'download', 'archive'],\n run: () => downloadChatAsHtml(),\n },\n {\n id: 'history', category: 'Command', label: 'Open history',\n icon: HistoryIcon, keywords: ['history', 'sessions'],\n run: () => setCurrentView('history'),\n },\n {\n id: 'settings', category: 'Command', label: 'Open settings',\n icon: SettingsIcon, keywords: ['settings', 'config'],\n run: () => setCurrentView('settings'),\n },\n {\n id: 'model', category: 'Command', label: 'Change provider/model',\n icon: Cpu, keywords: ['model', 'provider', 'change'],\n run: () => setCurrentView('settings'),\n },\n { id: 'theme-light', category: 'Theme', label: 'Theme: Light', icon: Sun, keywords: ['theme', 'light', 'mode'], run: () => setTheme('light') },\n { id: 'theme-dark', category: 'Theme', label: 'Theme: Dark', icon: Moon, keywords: ['theme', 'dark', 'mode'], run: () => setTheme('dark') },\n { id: 'theme-system', category: 'Theme', label: 'Theme: Follow system', icon: Monitor, keywords: ['theme', 'system', 'auto'], run: () => setTheme('system') },\n {\n id: 'compact-toggle', category: 'Command', label: 'Toggle compact density',\n icon: Maximize2, hint: 'Ctrl+Shift+D', keywords: ['compact', 'dense', 'density', 'size'],\n run: () => useUIStore.getState().toggleCompactMode(),\n },\n {\n id: 'sound-toggle', category: 'Command',\n label: useConfigStore.getState().soundOnComplete ? 'Sound on completion: ON — turn off' : 'Sound on completion: OFF — turn on',\n icon: useConfigStore.getState().soundOnComplete ? Volume2 : VolumeX,\n hint: 'Chime when a run finishes', keywords: ['sound', 'audio', 'chime', 'notify', 'beep'],\n run: () => {\n const next = !useConfigStore.getState().soundOnComplete;\n useConfigStore.getState().setSoundOnComplete(next);\n if (next) playCompletionChime();\n },\n },\n ];\n\n for (const entry of historyEntries.slice(0, 10)) {\n if (entry.isCurrent) continue;\n base.push({\n id: `resume-${entry.id}`, category: 'Session',\n label: `Resume: ${entry.title || '(empty)'}`,\n hint: `${entry.provider}/${entry.model}`,\n icon: ArchiveRestore,\n keywords: ['resume', entry.title, entry.id, entry.provider, entry.model],\n run: () => ws.resumeSession(entry.id),\n });\n }\n return base;\n }, [historyEntries, ws, setCurrentView, setTheme, addMessage, clearMessages]);\n\n const filtered = useMemo(() => {\n const q = query.toLowerCase().trim();\n if (!q) return items;\n return items.filter((it) => {\n const hay = [it.label, it.hint ?? '', it.category, ...(it.keywords ?? [])].join(' ').toLowerCase();\n return hay.includes(q);\n });\n }, [items, query]);\n\n useEffect(() => { if (index >= filtered.length) setIndex(0); }, [filtered.length, index]);\n\n if (!open) return null;\n\n const dispatchPick = (item: PaletteItem | undefined) => {\n if (!item) return;\n setOpen(false);\n item.run();\n };\n\n return (\n <div\n className=\"fixed inset-0 z-50 bg-background/60 backdrop-blur-sm flex items-start justify-center pt-[14vh] px-4\"\n onClick={() => setOpen(false)}\n onKeyDown={(e) => { if (e.key === 'Escape') setOpen(false); }}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n className=\"w-full max-w-2xl rounded-xl border bg-popover shadow-2xl overflow-hidden flex flex-col\"\n >\n <div className=\"flex items-center gap-2 px-4 py-3 border-b\">\n <Search className=\"h-4 w-4 text-muted-foreground\" />\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search commands, sessions, settings…\"\n className=\"flex-1 bg-transparent outline-none text-sm placeholder:text-muted-foreground\"\n onKeyDown={(e) => {\n if (e.key === 'ArrowDown') { e.preventDefault(); setIndex((i) => (i + 1) % Math.max(1, filtered.length)); }\n else if (e.key === 'ArrowUp') { e.preventDefault(); setIndex((i) => (i - 1 + Math.max(1, filtered.length)) % Math.max(1, filtered.length)); }\n else if (e.key === 'Enter') { e.preventDefault(); dispatchPick(filtered[index]); }\n }}\n />\n <kbd className=\"text-[10px] text-muted-foreground border rounded px-1.5 py-0.5\">Esc</kbd>\n </div>\n\n <div className=\"max-h-[60vh] overflow-y-auto\">\n {filtered.length === 0 ? (\n <div className=\"px-4 py-8 text-center text-sm text-muted-foreground\">No matches for \"{query}\"</div>\n ) : (\n renderGroupedList(filtered, index, dispatchPick, setIndex)\n )}\n </div>\n\n <div className=\"border-t px-4 py-2 text-[10px] uppercase tracking-wider text-muted-foreground flex items-center gap-3\">\n <span>↑↓ navigate</span>\n <span>↵ select</span>\n <span>Esc dismiss</span>\n </div>\n </div>\n </div>\n );\n}\n\nfunction renderGroupedList(\n filtered: PaletteItem[],\n index: number,\n dispatch: (it: PaletteItem) => void,\n setIndex: (i: number) => void,\n) {\n const groups: Record<string, Array<{ item: PaletteItem; globalIdx: number }>> = {};\n filtered.forEach((it, i) => {\n if (!groups[it.category]) groups[it.category] = [];\n groups[it.category]?.push({ item: it, globalIdx: i });\n });\n return (\n <div className=\"p-1\">\n {Object.entries(groups).map(([cat, rows]) => (\n <div key={cat}>\n <div className=\"px-3 pt-2 pb-1 text-[10px] uppercase tracking-wider text-muted-foreground\">{cat}</div>\n {rows.map(({ item, globalIdx }) => {\n const Icon = item.icon;\n const active = globalIdx === index;\n return (\n <button\n type=\"button\"\n key={item.id}\n onMouseEnter={() => setIndex(globalIdx)}\n onClick={() => dispatch(item)}\n className={cn(\n 'w-full flex items-center gap-3 px-3 py-2 rounded text-left text-sm transition-colors',\n active ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40',\n )}\n >\n <Icon className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <div className=\"flex-1 min-w-0\">\n <div className=\"truncate\">{item.label}</div>\n {item.hint && <div className=\"text-xs text-muted-foreground truncate\">{item.hint}</div>}\n </div>\n {active && <span className=\"text-[10px] text-muted-foreground\">↵</span>}\n </button>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n","import { useChatStore, useSessionStore } from '@/stores';\n\n/**\n * Build a markdown export of the current chat and trigger a browser download.\n */\nexport function downloadChatAsMarkdown(): void {\n const messages = useChatStore.getState().messages;\n const lines: string[] = [];\n const now = new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-');\n lines.push('# WrongStack chat export');\n lines.push(`*Exported: ${new Date().toISOString()}*`);\n lines.push('');\n for (const m of messages) {\n if (m.role === 'user') {\n lines.push('## 👤 User');\n lines.push('');\n lines.push(m.content);\n lines.push('');\n } else if (m.role === 'assistant') {\n lines.push('## 🤖 Assistant');\n lines.push('');\n lines.push(m.content);\n lines.push('');\n } else if (m.role === 'tool') {\n const status = m.isError ? '❌' : m.toolResult !== undefined ? '✅' : '⏳';\n lines.push(`### 🔧 Tool: \\`${m.toolName ?? 'unknown'}\\` ${status}`);\n if (m.toolInput !== undefined) {\n lines.push('```json');\n lines.push(JSON.stringify(m.toolInput, null, 2));\n lines.push('```');\n }\n if (m.toolResult) {\n lines.push('<details><summary>Output</summary>');\n lines.push('');\n lines.push('```');\n lines.push(m.toolResult);\n lines.push('```');\n lines.push('</details>');\n }\n lines.push('');\n }\n }\n const blob = new Blob([lines.join('\\n')], { type: 'text/markdown' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `wrongstack-chat-${now}.md`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n\n/**\n * Build a stand-alone HTML export of the current chat. Self-contained\n * (inline CSS, no external assets) so the file opens cleanly anywhere.\n */\nexport function downloadChatAsHtml(): void {\n const messages = useChatStore.getState().messages;\n const session = useSessionStore.getState();\n const now = new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-');\n const escapeHtml = (s: string) =>\n s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n\n const turns = messages.map((m) => {\n if (m.role === 'tool') {\n const status = m.isError ? '❌' : m.toolResult !== undefined ? '✅' : '⏳';\n return `\n <section class=\"bubble tool ${m.isError ? 'error' : ''}\">\n <header><span class=\"icon\">🔧</span><code>${escapeHtml(m.toolName ?? 'tool')}</code> ${status}</header>\n ${\n m.toolInput !== undefined\n ? `<details><summary>Input</summary><pre>${escapeHtml(JSON.stringify(m.toolInput, null, 2))}</pre></details>`\n : ''\n }\n ${\n m.toolResult\n ? `<details><summary>Output</summary><pre>${escapeHtml(m.toolResult)}</pre></details>`\n : ''\n }\n </section>`;\n }\n const cls = m.role === 'user' ? 'user' : 'assistant';\n const icon = m.role === 'user' ? '👤' : '🤖';\n const role = m.role === 'user' ? 'User' : 'Assistant';\n return `\n <section class=\"bubble ${cls}\">\n <header><span class=\"icon\">${icon}</span><strong>${role}</strong></header>\n <pre class=\"content\">${escapeHtml(m.content)}</pre>\n </section>`;\n });\n\n const html = `<!doctype html>\n<html lang=\"en\"><head>\n<meta charset=\"utf-8\">\n<title>WrongStack chat — ${escape(session.session?.title || session.projectName || 'export')}</title>\n<style>\n :root { color-scheme: light dark; }\n body { font: 14px/1.55 -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif; max-width: 920px; margin: 24px auto; padding: 0 16px; }\n h1 { font-size: 20px; margin-bottom: 4px; }\n .meta { color: #666; font-size: 12px; margin-bottom: 24px; }\n .bubble { margin: 12px 0; padding: 10px 14px; border-radius: 10px; border: 1px solid #ddd; }\n .bubble header { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: #666; margin-bottom: 6px; }\n .bubble header .icon { margin-right: 4px; }\n .bubble.user { background: #eef4ff; border-color: #c8d8f5; }\n .bubble.assistant { background: #fff; }\n .bubble.tool { background: #fafafa; }\n .bubble.tool.error { background: #fff5f5; border-color: #f5c8c8; }\n pre.content, .bubble pre { white-space: pre-wrap; word-break: break-word; font: 12px/1.5 ui-monospace, Menlo, Consolas, monospace; margin: 0; }\n details summary { cursor: pointer; color: #555; font-size: 12px; }\n details pre { margin-top: 6px; background: #f4f4f4; padding: 8px; border-radius: 6px; max-height: 360px; overflow: auto; }\n @media (prefers-color-scheme: dark) {\n body { background: #0d0d0f; color: #e6e6e6; }\n .bubble { border-color: #2a2a2e; }\n .bubble.user { background: #16213a; border-color: #2a3d6b; }\n .bubble.assistant { background: #161618; }\n .bubble.tool { background: #131315; }\n .bubble.tool.error { background: #2a1717; border-color: #5c2a2a; }\n details pre { background: #1a1a1c; }\n .meta, .bubble header, details summary { color: #999; }\n }\n</style>\n</head><body>\n<h1>WrongStack chat — ${escape(session.session?.title || session.projectName || 'export')}</h1>\n<div class=\"meta\">\n Exported ${new Date().toISOString()}${session.session?.provider ? ` · ${escape(session.session.provider)}/${escape(session.session.model)}` : ''} · ${messages.length} message${messages.length === 1 ? '' : 's'}\n</div>\n${turns.join('')}\n</body></html>`;\n const blob = new Blob([html], { type: 'text/html;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `wrongstack-chat-${now}.html`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore } from '@/stores';\nimport { FileText, Folder } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\ninterface FilePickerProps {\n /** Whatever the user typed after the `@` trigger (case-preserved). */\n query: string;\n /** Called when the user picks a file (Enter / Tab / click). */\n onPick: (relPath: string) => void;\n /** Called when the picker should close without inserting (Esc). */\n onClose: () => void;\n}\n\n/**\n * `@` file mention popup. Subscribes to the WS `files.list` response,\n * supports ↑/↓ Tab Enter Esc. Refetches on query change with a small\n * debounce so we don't spam the backend on every keystroke.\n */\nexport function FilePicker({ query, onPick, onClose }: FilePickerProps) {\n const ws = useWebSocket();\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const [files, setFiles] = useState<string[]>([]);\n const [index, setIndex] = useState(0);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wantHandle = useRef<{ resolve: (paths: string[]) => void } | null>(null);\n\n // Subscribe to the single `files.list` event for the lifetime of this\n // picker. We use the raw client.on() rather than the hook because the\n // hook installs handlers at boot — but `files.list` is picker-local and\n // the data shouldn't leak into other surfaces.\n useEffect(() => {\n const client = getWSClient(wsUrl);\n const off = client.on('files.list', (msg) => {\n const p = msg.payload as { files: string[] };\n setFiles(p.files ?? []);\n setIndex(0);\n wantHandle.current?.resolve(p.files ?? []);\n wantHandle.current = null;\n });\n return () => off();\n }, [wsUrl]);\n\n // Debounced fetch on query change.\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => {\n ws.client.listFiles(query, 50);\n }, 80);\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [query, ws.client]);\n\n // Keyboard nav at window level — ChatInput owns the textarea so we\n // intercept keys there and forward intent here via the imperative API.\n // We listen too so click+keyboard mixing works.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setIndex((i) => (i + 1) % Math.max(1, files.length));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setIndex((i) => (i - 1 + Math.max(1, files.length)) % Math.max(1, files.length));\n } else if (e.key === 'Enter' || e.key === 'Tab') {\n if (files.length === 0) return;\n e.preventDefault();\n onPick(expectDefined(files[index]));\n } else if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n }\n };\n window.addEventListener('keydown', onKey, true);\n return () => window.removeEventListener('keydown', onKey, true);\n }, [files, index, onPick, onClose]);\n\n return (\n <div className=\"absolute bottom-full left-0 right-0 mb-2 rounded-lg border bg-popover shadow-md p-1 text-sm max-h-72 overflow-auto\">\n <div className=\"px-3 py-1 text-[10px] uppercase tracking-wider text-muted-foreground border-b mb-1 flex items-center justify-between\">\n <span>@ Files {query && `· \"${query}\"`}</span>\n <span>↑/↓ select · ↵ insert · Esc dismiss</span>\n </div>\n {files.length === 0 ? (\n <div className=\"px-3 py-2 text-xs text-muted-foreground italic\">\n {query ? `No files match \"${query}\"` : 'Searching project…'}\n </div>\n ) : (\n files.map((p, i) => (\n <button\n key={p}\n type=\"button\"\n onClick={() => onPick(p)}\n onMouseEnter={() => setIndex(i)}\n className={cn(\n 'w-full text-left px-3 py-1.5 rounded transition-colors flex items-center gap-2 font-mono text-xs',\n i === index ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40',\n )}\n >\n {p.includes('/') ? (\n <Folder className=\"h-3.5 w-3.5 text-muted-foreground shrink-0\" />\n ) : (\n <FileText className=\"h-3.5 w-3.5 text-muted-foreground shrink-0\" />\n )}\n <span className=\"truncate\">{p}</span>\n </button>\n ))\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps, cva } from 'class-variance-authority';\nimport * as React from 'react';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean | undefined;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />\n );\n },\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n","function expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\n// Slash command registry and matching utilities for ChatInput\n\nexport type SlashCategory = 'Run' | 'Session' | 'Inspect' | 'Agent' | 'Config' | 'App';\n\nexport interface SlashCommandDef {\n name: string;\n aliases?: string[] | undefined;\n description: string;\n category: SlashCategory;\n}\n\nexport const SLASH_COMMANDS: SlashCommandDef[] = [\n // Run\n { name: '/abort', category: 'Run', aliases: ['/stop'], description: 'Abort the current run' },\n\n // Session\n { name: '/new', category: 'Session', description: 'Start a brand-new session (fresh on disk and in memory)' },\n { name: '/clear', category: 'Session', description: 'Wipe current context (keeps session id, disk record stays)' },\n { name: '/compact', category: 'Session', description: 'Shrink context — elide ancient tool output' },\n { name: '/repair', category: 'Session', description: 'Repair orphan tool_use/tool_result blocks in context' },\n { name: '/save', category: 'Session', description: 'Force-flush the session (auto-saved already)' },\n { name: '/load', category: 'Session', aliases: ['/resume'], description: 'Resume a previous session from disk' },\n { name: '/prune', category: 'Session', description: 'Delete old sessions (default older than 30 days)' },\n { name: '/export', category: 'Session', description: 'Download the current chat as markdown' },\n\n // Inspect\n { name: '/debug', category: 'Inspect', aliases: ['/context'], description: 'Per-section context size breakdown' },\n { name: '/tools', category: 'Inspect', description: 'List every registered tool the model can call' },\n { name: '/memory', category: 'Inspect', description: 'Show all remembered notes (project + user scope)' },\n { name: '/skill', category: 'Inspect', aliases: ['/skills'], description: 'List active skills' },\n { name: '/diag', category: 'Inspect', description: 'Runtime diagnostics (provider, tools, features, mode, usage)' },\n { name: '/stats', category: 'Inspect', description: 'Session stats: tokens, cache hit ratio, cost, elapsed' },\n { name: '/todos', category: 'Inspect', description: 'List current todos (try `/todos clear` to reset)' },\n { name: '/codebase-reindex', category: 'Inspect', aliases: ['/reindex'], description: 'Rebuild the codebase symbol index' },\n\n // Agent\n { name: '/spawn', category: 'Agent', description: 'Spawn an isolated subagent to handle a task' },\n { name: '/agents', category: 'Agent', description: 'Show status of spawned subagents' },\n { name: '/fleet', category: 'Agent', description: 'Inspect and control the agent fleet' },\n { name: '/director', category: 'Agent', description: 'Promote to director mode at runtime' },\n { name: '/autonomy', category: 'Agent', description: 'Toggle or query autonomy mode (self-driving agent)' },\n { name: '/goal', category: 'Agent', description: 'Set, inspect, or clear the autonomous mission' },\n { name: '/autophase', category: 'Agent', description: 'Autonomous phase-based workflow with subagents' },\n { name: '/fix', category: 'Agent', description: 'Diagnose and fix a reported error or bug' },\n { name: '/sdd', category: 'Agent', description: 'AI-driven Specification-Driven Development workflow' },\n { name: '/btw', category: 'Agent', description: 'Drop a mid-run note without interrupting the agent' },\n { name: '/collab', category: 'Agent', description: 'Live collaboration helpers (status / invite / history)' },\n\n // Config\n { name: '/settings', category: 'Config', aliases: ['/model'], description: 'Open settings (provider/model/keys)' },\n { name: '/setmodel', category: 'Config', description: 'Quick-switch the active provider/model' },\n { name: '/models', category: 'Config', description: 'List available providers and models' },\n { name: '/mode', category: 'Config', description: 'Switch the active mode (persona/skill set)' },\n { name: '/yolo', category: 'Config', description: 'Toggle or query YOLO (auto-approve) mode' },\n { name: '/next', category: 'Config', description: 'Toggle next-task prediction after each turn' },\n { name: '/enhance', category: 'Config', description: 'Toggle prompt refinement before sending' },\n { name: '/mcp', category: 'Config', aliases: ['/mcp-servers'], description: 'Manage MCP servers' },\n { name: '/plugin', category: 'Config', aliases: ['/plugins'], description: 'Manage plugins' },\n { name: '/statusline', category: 'Config', aliases: ['/sl'], description: 'Customize status bar chips' },\n { name: '/telegram-setup', category: 'Config', aliases: ['/tg-setup'], description: 'Configure Telegram bot token and chat' },\n { name: '/init', category: 'Config', description: 'Create or update .wrongstack/AGENTS.md project context' },\n { name: '/worktree', category: 'Config', aliases: ['/wt'], description: 'Inspect/manage git worktrees for AutoPhase' },\n\n // App\n { name: '/help', category: 'App', description: 'Show every slash command and what it does' },\n { name: '/exit', category: 'App', description: 'Exit the current session' },\n];\n\nexport const SLASH_CATEGORY_ORDER: SlashCategory[] = ['Run', 'Session', 'Inspect', 'Agent', 'Config', 'App'];\n\nexport function matchSlash(query: string): SlashCommandDef[] {\n const q = query.toLowerCase();\n if (q === '/' || q === '') return SLASH_COMMANDS;\n return SLASH_COMMANDS.filter(\n (c) => c.name.startsWith(q) || (c.aliases?.some((a) => a.startsWith(q)) ?? false),\n );\n}\n\nexport function detectAtMention(value: string, cursor: number): { start: number; query: string } | null {\n let i = cursor - 1;\n while (i >= 0) {\n const c = expectDefined(value[i]);\n if (c === '@') {\n const prev = i > 0 ? value[i - 1] : '';\n if (i === 0 || /\\s/.test(prev ?? '')) {\n return { start: i, query: value.slice(i + 1, cursor) };\n }\n return null;\n }\n if (/\\s/.test(c)) return null;\n i--;\n }\n return null;\n}\n","import { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport type { WsStatus } from '@/lib/ws-client';\nimport { useConfigStore } from '@/stores';\nimport { Loader2, RotateCcw, Wifi, WifiOff } from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\ninterface Props {\n wsStatus: WsStatus;\n wsConnected: boolean;\n}\n\n/**\n * Tiny status pill for the topbar. Renders four distinct visual states:\n *\n * • open — solid green Wi-Fi\n * • connecting — pulsing yellow spinner\n * • reconnecting — orange, attempt counter + live retry countdown,\n * click to retry immediately\n * • closed — red Wi-Fi-off, click to retry, tooltip shows error\n *\n * The countdown ticks live (every 500ms while `nextRetryAt` is in the\n * future) without forcing the whole topbar to re-render — we only re-run\n * the local timer effect.\n */\nexport function ConnectionChip({ wsStatus, wsConnected }: Props) {\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const [now, setNow] = useState(Date.now());\n\n // Keep a live clock running only while we're between retries, otherwise\n // we'd burn one render every 500ms in a happy-path session.\n useEffect(() => {\n if (wsStatus.state !== 'reconnecting') return;\n const id = setInterval(() => setNow(Date.now()), 500);\n return () => clearInterval(id);\n }, [wsStatus.state]);\n\n const retry = () => getWSClient(wsUrl).retryNow();\n\n if (wsStatus.state === 'open' && wsConnected) {\n return (\n <div\n className=\"flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0 bg-green-500/10 text-green-600 dark:text-green-400\"\n title=\"Backend connected\"\n >\n <Wifi className=\"h-3 w-3\" />\n </div>\n );\n }\n\n if (wsStatus.state === 'connecting') {\n return (\n <div\n className=\"flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0 bg-yellow-500/10 text-yellow-600 dark:text-yellow-400\"\n title=\"Connecting to backend\"\n >\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n <span>connecting</span>\n </div>\n );\n }\n\n if (wsStatus.state === 'reconnecting') {\n const remaining = Math.max(0, Math.ceil((wsStatus.nextRetryAt - now) / 1000));\n return (\n <button\n type=\"button\"\n onClick={retry}\n className={cn(\n 'flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0',\n 'bg-orange-500/10 text-orange-600 dark:text-orange-400 hover:bg-orange-500/20',\n 'transition-colors',\n )}\n title={\n wsStatus.lastError\n ? `Reconnecting — last error: ${wsStatus.lastError}. Click to retry now.`\n : 'Reconnecting — click to retry now.'\n }\n >\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n <span>\n retry #{wsStatus.attempt} in {remaining}s\n </span>\n </button>\n );\n }\n\n // closed\n return (\n <button\n type=\"button\"\n onClick={retry}\n className=\"flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium shrink-0 bg-red-500/10 text-red-600 dark:text-red-400 hover:bg-red-500/20 transition-colors\"\n title={\n wsStatus.state === 'closed' && wsStatus.error\n ? `Disconnected: ${wsStatus.error}. Click to retry.`\n : 'Disconnected. Click to retry.'\n }\n >\n <WifiOff className=\"h-3 w-3\" />\n <span className=\"flex items-center gap-0.5\">\n offline\n <RotateCcw className=\"h-3 w-3 opacity-70\" />\n </span>\n </button>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { useSessionStore } from '@/stores';\nimport { Check, ChevronDown, Gauge } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\nconst FALLBACK_MODES = [\n {\n id: 'balanced',\n name: 'Balanced',\n description: 'Default rolling compaction',\n thresholds: { warn: 0.6, soft: 0.75, hard: 0.9 },\n preserveK: 10,\n eliseThreshold: 2000,\n },\n];\n\nexport function ContextModePicker() {\n const contextMode = useSessionStore((s) => s.contextMode);\n const contextModes = useSessionStore((s) => s.contextModes);\n const { listContextModes, switchContextMode } = useWebSocket();\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (open) listContextModes();\n }, [open, listContextModes]);\n\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('mousedown', onClick);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onClick);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n const items = contextModes.length > 0 ? contextModes : FALLBACK_MODES;\n const active = items.find((m) => m.id === contextMode) ?? expectDefined(items[0]);\n\n return (\n <div ref={rootRef} className=\"relative shrink-0\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium',\n 'bg-emerald-500/10 text-emerald-700 dark:text-emerald-300 hover:bg-emerald-500/15 transition-colors border border-transparent hover:border-emerald-500/30',\n )}\n title=\"Context-window mode\"\n >\n <Gauge className=\"h-3 w-3\" />\n ctx: <span className=\"font-mono\">{contextMode || active.id}</span>\n <ChevronDown className=\"h-3 w-3 opacity-60\" />\n </button>\n {open && (\n <div className=\"absolute top-full left-0 mt-1 w-80 rounded-md border bg-popover shadow-lg z-30 py-1\">\n <div className=\"px-3 py-1.5 text-[10px] uppercase tracking-wider text-muted-foreground border-b\">\n Context Window\n </div>\n {items.map((m) => (\n <button\n key={m.id}\n type=\"button\"\n onClick={() => {\n switchContextMode(m.id);\n setOpen(false);\n }}\n className={cn(\n 'w-full text-left px-3 py-2 hover:bg-accent/40 flex items-start gap-2',\n m.id === contextMode && 'bg-accent/30',\n )}\n >\n <Check\n className={cn(\n 'h-3.5 w-3.5 mt-0.5 shrink-0',\n m.id === contextMode ? 'opacity-100 text-primary' : 'opacity-0',\n )}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-xs font-mono\">{m.id}</span>\n {m.thresholds?.warn !== undefined && (\n <span className=\"text-[10px] text-muted-foreground tabular-nums\">\n {Math.round(m.thresholds.warn * 100)}/{Math.round(m.thresholds.soft * 100)}/\n {Math.round(m.thresholds.hard * 100)}%\n </span>\n )}\n </div>\n <div className=\"text-[11px] text-muted-foreground leading-snug\">\n {m.description}\n </div>\n {(m.preserveK || m.eliseThreshold) && (\n <div className=\"mt-1 text-[10px] text-muted-foreground/80\">\n keep {m.preserveK ?? '-'} recent · elide {m.eliseThreshold ?? '-'}+ tokens\n </div>\n )}\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useChatStore, useSessionStore } from '@/stores';\nimport { useEffect, useRef, useState } from 'react';\n\n/**\n * Clickable cost figure in the topbar. Tap to drop a small popover with a\n * per-turn breakdown sourced from `ChatMessage.runSummary` (attached by the\n * run.result handler). Helps the cost-conscious user trace where the\n * dollars actually went without spelunking through transcripts.\n *\n * We only render the popover after the user clicks — the cost chip itself\n * is identical to the plain span it replaces, so the topbar layout stays\n * unchanged.\n */\nexport function CostChip() {\n const cost = useSessionStore((s) => s.cost);\n const inputCost = useSessionStore((s) => s.inputCost);\n const outputCost = useSessionStore((s) => s.outputCost);\n const cacheReadCost = useSessionStore((s) => s.cacheReadCost);\n const messages = useChatStore((s) => s.messages);\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('mousedown', onClick);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onClick);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n /** Top expensive turns. We only consider messages with a runSummary —\n * the run.result handler attaches one per completed turn. costDelta is\n * the delta computed in that handler (session cost at end minus at\n * start of this turn). Falls back to nothing if no data yet. */\n const turns = (() => {\n const rows: Array<{\n id: string;\n preview: string;\n cost: number;\n tools: number;\n ms: number;\n ts: number;\n }> = [];\n for (const m of messages) {\n if (m.role === 'assistant' && m.runSummary && m.runSummary.costDelta > 0) {\n rows.push({\n id: m.id,\n preview: m.content.slice(0, 80).replace(/\\s+/g, ' ').trim() || '(empty)',\n cost: m.runSummary.costDelta,\n tools: m.runSummary.tools,\n ms: m.runSummary.durationMs,\n ts: m.timestamp,\n });\n }\n }\n rows.sort((a, b) => b.cost - a.cost);\n return rows.slice(0, 5);\n })();\n\n const fmt$ = (v: number) =>\n v >= 0.01\n ? `$${v.toFixed(4)}`\n : v > 0\n ? `$${v.toFixed(6).replace(/0+$/, '').replace(/\\.$/, '')}`\n : '$0';\n\n const haveRates = inputCost > 0 || outputCost > 0;\n\n return (\n <div ref={rootRef} className=\"relative inline-block\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'font-medium text-green-600 dark:text-green-400 hover:underline tabular-nums',\n )}\n title=\"Click for per-turn cost breakdown\"\n >\n ${cost.toFixed(4)}\n </button>\n {open && (\n <div className=\"absolute right-0 top-full mt-1 z-30 w-80 rounded-md border bg-popover shadow-lg p-3 text-foreground\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground font-medium\">\n Cost breakdown\n </span>\n <span className=\"font-mono tabular-nums text-sm font-semibold text-green-600 dark:text-green-400\">\n {fmt$(cost)}\n </span>\n </div>\n {haveRates ? (\n <div className=\"text-[11px] text-muted-foreground font-mono mb-3 border-b pb-2\">\n <div className=\"flex justify-between\">\n <span>input /1M</span>\n <span>${inputCost.toFixed(2)}</span>\n </div>\n <div className=\"flex justify-between\">\n <span>output /1M</span>\n <span>${outputCost.toFixed(2)}</span>\n </div>\n {cacheReadCost > 0 && (\n <div className=\"flex justify-between\">\n <span>cache /1M</span>\n <span>${cacheReadCost.toFixed(2)}</span>\n </div>\n )}\n </div>\n ) : (\n <div className=\"text-[11px] text-muted-foreground italic mb-3 border-b pb-2\">\n No pricing for the current model — cost figures are zero.\n </div>\n )}\n {turns.length === 0 ? (\n <div className=\"text-xs text-muted-foreground italic\">\n No completed turns yet. Run a prompt to see per-turn cost here.\n </div>\n ) : (\n <>\n <div className=\"text-[10px] uppercase tracking-wider text-muted-foreground/80 mb-1\">\n Top {turns.length} expensive turn{turns.length === 1 ? '' : 's'}\n </div>\n <ul className=\"space-y-1\">\n {turns.map((t) => (\n <li key={t.id}>\n <button\n type=\"button\"\n onClick={() => {\n const el = document.querySelector(`[data-message-id=\"${t.id}\"]`);\n if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n setOpen(false);\n }}\n className=\"w-full text-left rounded px-2 py-1.5 hover:bg-accent/40 transition-colors\"\n >\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-xs truncate\">{t.preview}</span>\n <span className=\"text-xs font-mono tabular-nums text-green-600 dark:text-green-400 shrink-0\">\n {fmt$(t.cost)}\n </span>\n </div>\n <div className=\"text-[10px] text-muted-foreground font-mono mt-0.5\">\n {t.tools} tool{t.tools === 1 ? '' : 's'} · {(t.ms / 1000).toFixed(1)}s\n </div>\n </button>\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Tool-aware one-line summary for the collapsed bubble. The whole point is\n * that 8 parallel `read` calls should NOT look identical, and a TodoWrite\n * call with 8 todos shouldn't dump 800 chars of JSON when \"8 todos · 3\n * done\" tells the whole story.\n *\n * Cases that earn a custom branch:\n * - TodoWrite → \"8 todos · 3 done · 2 in-progress\"\n * - edit / write → \"edit foo.ts (3 lines → 5 lines)\" / \"write …\"\n * - bash / shell → \"$ <command snippet>\"\n * - fetch / http → \"GET https://…\"\n * - grep / glob → pattern + scope\n * - batch_tool_use → \"N sub-tools\"\n * - read → \"path:N..M\" if offset/limit present\n *\n * Everything else falls back to the head-field-or-JSON heuristic the\n * collapsed view used before.\n */\n\nconst FALLBACK_HEAD_FIELDS = [\n 'path',\n 'file_path',\n 'pattern',\n 'command',\n 'cmd',\n 'url',\n 'query',\n 'description',\n 'content',\n];\n\nexport function summarizeToolInput(toolName: string | undefined, input: unknown): string {\n if (input === null || input === undefined) return '';\n if (typeof input !== 'object') return clip(String(input), 120);\n\n const obj = input as Record<string, unknown>;\n const name = (toolName ?? '').toLowerCase();\n\n // ---- TodoWrite ----------------------------------------------------\n if (/^todo(_?write)?$|^todos$/i.test(name) || Array.isArray(obj.todos)) {\n const todos = (obj.todos ?? []) as Array<{ status?: string | undefined; content?: string | undefined }>;\n if (Array.isArray(todos)) {\n const done = todos.filter((t) => t.status === 'completed').length;\n const wip = todos.filter((t) => t.status === 'in_progress').length;\n const parts = [`${todos.length} todo${todos.length === 1 ? '' : 's'}`];\n if (done > 0) parts.push(`${done} done`);\n if (wip > 0) parts.push(`${wip} in-progress`);\n return parts.join(' · ');\n }\n }\n\n // ---- batch_tool_use / parallel_tool_use ---------------------------\n if (/batch|parallel/.test(name) || Array.isArray(obj.tool_uses) || Array.isArray(obj.calls)) {\n const list = (obj.tool_uses ?? obj.calls ?? obj.batch) as unknown[];\n if (Array.isArray(list)) {\n const subNames = new Set<string>();\n for (const item of list) {\n if (item && typeof item === 'object' && 'name' in item) {\n subNames.add(String((item as { name: unknown }).name));\n }\n }\n const preview = [...subNames].slice(0, 3).join(', ');\n const more = subNames.size > 3 ? ` +${subNames.size - 3}` : '';\n return `${list.length} sub-tool${list.length === 1 ? '' : 's'}${preview ? ` · ${preview}${more}` : ''}`;\n }\n }\n\n // ---- edit / str_replace / patch -----------------------------------\n if (/^(edit|str_replace|edit_file|patch)$/.test(name)) {\n const fp = pickPath(obj);\n const oldS = typeof obj.old_string === 'string' ? obj.old_string : '';\n const newS = typeof obj.new_string === 'string' ? obj.new_string : '';\n const oldLines = oldS ? oldS.split('\\n').length : 0;\n const newLines = newS ? newS.split('\\n').length : 0;\n return `edit ${fp || '(file)'}${oldLines || newLines ? ` (${oldLines} → ${newLines} lines)` : ''}`;\n }\n\n // ---- write / write_file / create_file -----------------------------\n if (/^(write|write_file|create_file|new_file)$/.test(name)) {\n const fp = pickPath(obj);\n const c = typeof obj.content === 'string' ? obj.content : '';\n const lines = c ? c.split('\\n').length : 0;\n return `write ${fp || '(file)'}${lines ? ` · ${lines} lines` : ''}`;\n }\n\n // ---- bash / shell / exec / run ------------------------------------\n if (/^(bash|shell|exec|run|run_command|run_shell)$/.test(name)) {\n const cmd = (obj.command ?? obj.cmd ?? obj.script) as string | undefined;\n if (typeof cmd === 'string') return `$ ${clip(cmd, 110)}`;\n }\n\n // ---- fetch / http / web -------------------------------------------\n if (/^(fetch|http|web|webfetch|curl|request)$/.test(name)) {\n const url = obj.url as string | undefined;\n if (typeof url === 'string') {\n const method = (obj.method as string | undefined) ?? 'GET';\n return `${method.toUpperCase()} ${clip(url, 100)}`;\n }\n }\n\n // ---- grep / search ------------------------------------------------\n if (/^(grep|search|ripgrep)$/.test(name)) {\n const pattern = obj.pattern as string | undefined;\n const scope = (obj.path ?? obj.glob ?? obj.type) as string | undefined;\n if (typeof pattern === 'string') {\n return scope ? `grep ${clip(pattern, 60)} in ${scope}` : `grep ${clip(pattern, 100)}`;\n }\n }\n\n // ---- glob / find --------------------------------------------------\n if (/^(glob|find)$/.test(name)) {\n const p = (obj.pattern ?? obj.glob) as string | undefined;\n if (typeof p === 'string') return `glob ${clip(p, 100)}`;\n }\n\n // ---- read with offset/limit --------------------------------------\n if (/^(read|read_file|cat)$/.test(name)) {\n const fp = pickPath(obj);\n const offset = obj.offset as number | undefined;\n const limit = obj.limit as number | undefined;\n if (fp && (typeof offset === 'number' || typeof limit === 'number')) {\n const start = offset ?? 0;\n const end = typeof limit === 'number' ? start + limit : '';\n return `read ${fp} (${start}…${end})`;\n }\n if (fp) return `read ${fp}`;\n }\n\n // ---- Fallback: pick the first non-empty \"headline\" string field --\n for (const k of FALLBACK_HEAD_FIELDS) {\n const v = obj[k];\n if (typeof v === 'string' && v.length > 0) {\n return `${k}: ${clip(v, 100)}`;\n }\n }\n // Last resort: compact JSON.\n const json = safeJson(input);\n return clip(json, 120);\n}\n\nfunction clip(s: string, n: number): string {\n return s.length > n ? `${s.slice(0, n - 1)}…` : s;\n}\n\nfunction pickPath(obj: Record<string, unknown>): string {\n const p = obj.file_path ?? obj.path ?? obj.filepath;\n return typeof p === 'string' ? p : '';\n}\n\nfunction safeJson(v: unknown): string {\n try {\n return JSON.stringify(v);\n } catch {\n return String(v);\n }\n}\n","import { summarizeToolInput } from '@/lib/tool-summary';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport type { ChatMessage } from '@/stores';\nimport { useChatStore, useSessionStore, useUIStore } from '@/stores';\nimport { useConfigStore } from '@/stores';\nimport {\n Bot,\n CheckCircle2,\n ChevronDown,\n ChevronRight,\n Clock,\n Download,\n FileCode2,\n Pencil,\n Pin,\n PinOff,\n RotateCcw,\n Terminal,\n User,\n XCircle,\n} from 'lucide-react';\nimport { memo, useState } from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { DiffView, diffFromToolInput } from '../DiffView';\nimport { ToolResult } from '../ToolResult';\nimport { CopyButton } from './CopyButton.js';\nimport { ErrorBodyWithStack } from './ErrorBody.js';\nimport { ToolInputView } from './ToolInputView.js';\nimport { downloadTextFile, fileExtensionFor, formatToolDuration, markdownComponents } from './utils.js';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\ninterface MessageBubbleProps {\n message: ChatMessage;\n isFirst?: boolean | undefined;\n isContinuation?: boolean | undefined;\n}\n\nexport const MessageBubble = memo(function MessageBubble({\n message,\n isFirst = false,\n isContinuation = false,\n}: MessageBubbleProps) {\n const [expandedTools, setExpandedTools] = useState<Record<string, boolean>>({});\n const [editing, setEditing] = useState(false);\n const [editValue, setEditValue] = useState('');\n const [showRaw, setShowRaw] = useState(false);\n const isUser = message.role === 'user';\n const isTool = message.role === 'tool';\n void message.role;\n\n const truncateAfter = useChatStore((s) => s.truncateAfter);\n const addMessage = useChatStore((s) => s.addMessage);\n const setLoading = useChatStore((s) => s.setLoading);\n const isLoading = useChatStore((s) => s.isLoading);\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const pinnedIds = useUIStore((s) => s.pinnedIds);\n const togglePin = useUIStore((s) => s.togglePin);\n const compactMode = useUIStore((s) => s.compactMode);\n const isPinned = pinnedIds.includes(message.id);\n const inputCost = useSessionStore((s) => s.inputCost);\n const outputCost = useSessionStore((s) => s.outputCost);\n const cacheReadCost = useSessionStore((s) => s.cacheReadCost);\n\n const isLatestAssistant = (() => {\n if (message.role !== 'assistant' || isLoading) return false;\n const all = useChatStore.getState().messages;\n for (let i = all.length - 1; i >= 0; i--) {\n const m = expectDefined(all[i]);\n if (m.role === 'assistant') return m.id === message.id;\n }\n return false;\n })();\n\n const regenerate = () => {\n const all = useChatStore.getState().messages;\n const idx = all.findIndex((m) => m.id === message.id);\n if (idx === -1) return;\n let userIdx = -1;\n for (let i = idx - 1; i >= 0; i--) {\n if (all[i]?.role === 'user') {\n userIdx = i;\n break;\n }\n }\n if (userIdx === -1) return;\n const userMsg = expectDefined(all[userIdx]);\n truncateAfter(userMsg.id);\n addMessage({ role: 'user', content: userMsg.content });\n setLoading(true);\n const client = getWSClient(wsUrl);\n client.sendMessage(userMsg.content);\n };\n\n const toggleTool = (id: string) => {\n setExpandedTools((prev) => ({ ...prev, [id]: !prev[id] }));\n };\n\n const startEdit = () => {\n setEditValue(message.content);\n setEditing(true);\n };\n const cancelEdit = () => {\n setEditing(false);\n setEditValue('');\n };\n const saveEdit = () => {\n const next = editValue.trim();\n if (!next) { cancelEdit(); return; }\n truncateAfter(message.id);\n addMessage({ role: 'user', content: next });\n setLoading(true);\n const client = getWSClient(wsUrl);\n client.sendMessage(next);\n setEditing(false);\n setEditValue('');\n };\n\n return (\n <div\n data-message-id={message.id}\n data-pinned={isPinned ? '1' : undefined}\n className={cn(\n 'group flex animate-message rounded-lg transition-shadow',\n compactMode ? 'gap-2' : 'gap-3',\n isUser ? 'flex-row-reverse' : 'flex-row',\n isPinned && 'ring-1 ring-amber-500/30 bg-amber-500/[0.02] px-1 -mx-1',\n )}\n >\n {isContinuation ? (\n <div className=\"flex-shrink-0 w-8 h-8\" aria-hidden />\n ) : (\n <div className={cn(\n 'flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center',\n 'ring-2 ring-offset-2 ring-offset-background',\n isUser ? 'bg-primary text-primary-foreground ring-primary/20' : isTool ? 'bg-secondary text-secondary-foreground ring-secondary/20' : 'bg-accent text-accent-foreground ring-accent/20',\n )}>\n {isUser ? <User className=\"h-4 w-4\" /> : isTool ? <Terminal className=\"h-4 w-4\" /> : <Bot className=\"h-4 w-4\" />}\n </div>\n )}\n\n <div className={cn('flex flex-col gap-1.5 max-w-[85%]', isUser && 'items-end')}>\n {isFirst && !isContinuation && (\n <span className={cn('text-xs font-medium px-1', isUser ? 'text-primary' : isTool ? 'text-secondary' : 'text-muted-foreground')}>\n {isUser ? 'You' : isTool ? 'Tool' : 'Assistant'}\n </span>\n )}\n\n {isTool && message.toolName && (\n <button type=\"button\" onClick={() => toggleTool(message.id)}\n className={cn('flex items-center gap-2 text-sm font-medium cursor-pointer select-none', 'hover:bg-muted/50 rounded-lg px-2 py-1 -mx-2 transition-colors', message.isError ? 'text-destructive' : 'text-foreground')}>\n <span className=\"text-muted-foreground/50\">{expandedTools[message.id] ? <ChevronDown className=\"h-3 w-3\" /> : <ChevronRight className=\"h-3 w-3\" />}</span>\n <Terminal className=\"h-3 w-3\" />\n <span className=\"font-mono\">{message.toolName}</span>\n {message.toolResult === undefined ? <span className=\"h-1.5 w-1.5 rounded-full bg-amber-500 animate-pulse\" aria-hidden /> : message.isError ? <XCircle className=\"h-3 w-3 text-destructive\" /> : <CheckCircle2 className=\"h-3 w-3 text-green-500\" />}\n {typeof message.toolDurationMs === 'number' && <span className=\"text-xs text-muted-foreground tabular-nums font-normal\">{formatToolDuration(message.toolDurationMs)}</span>}\n </button>\n )}\n\n <div className={cn('rounded-2xl', compactMode ? 'px-3 py-1.5' : 'px-4 py-3',\n isUser ? 'bg-primary text-primary-foreground rounded-br-md' : isTool ? message.isError ? 'bg-destructive/5 border border-destructive/20 text-destructive' : 'bg-muted/80 text-foreground' : 'bg-card border text-foreground',\n message.isError && !isTool && 'border-destructive/20')}>\n {isTool ? (() => {\n const expanded = !!expandedTools[message.id];\n const inputSummary = message.toolInput !== undefined ? summarizeToolInput(message.toolName, message.toolInput) : '';\n const lines = message.toolResult ? message.toolResult.split('\\n').length : 0;\n return (\n <div className=\"space-y-1\">\n {inputSummary && !expanded && <div className=\"text-xs text-muted-foreground font-mono truncate\">{inputSummary}</div>}\n {message.toolResult === undefined && message.progressLines && message.progressLines.length > 0 && (\n <div className=\"mt-1 rounded-md border border-amber-500/20 bg-amber-500/5 p-1.5 text-[11px] font-mono leading-snug max-h-32 overflow-auto\">\n {(() => {\n const seen = new Map<string, number>();\n return message.progressLines.slice(-6).map((line) => {\n const occurrence = seen.get(line) ?? 0;\n seen.set(line, occurrence + 1);\n return (<div key={`${line}-${occurrence}`} className=\"truncate text-muted-foreground\">{line}</div>);\n });\n })()}\n </div>\n )}\n {expanded && message.toolInput !== undefined && (() => {\n const diffArgs = diffFromToolInput(message.toolName, message.toolInput);\n if (diffArgs) return (<DiffView oldText={diffArgs.oldText} newText={diffArgs.newText} caption={diffArgs.caption} />);\n return (<div className=\"p-3 bg-muted/50 rounded-lg overflow-x-auto\"><div className=\"flex items-center gap-1 text-muted-foreground mb-2 text-xs\"><Clock className=\"h-3 w-3\" /><span>Input</span></div><ToolInputView input={message.toolInput} /></div>);\n })()}\n {expanded && message.toolResult !== undefined && message.toolResult.length > 0 && (\n <div className=\"relative group/tool\">\n <ToolResult toolName={message.toolName} result={message.toolResult} isError={message.isError} />\n <div className=\"absolute top-1.5 right-1.5 flex items-center gap-1 opacity-0 group-hover/tool:opacity-100 transition-opacity\">\n <CopyButton text={message.toolResult} label=\"\" className=\"bg-background/80 border rounded px-1.5 py-0.5\" />\n {message.toolResult.split('\\n').length > 5 && (\n <button type=\"button\" onClick={(ev) => { ev.stopPropagation(); const ext = fileExtensionFor(message.toolName); const base = (message.toolName ?? 'output').replace(/[^a-z0-9_-]+/gi, '-').toLowerCase(); downloadTextFile(`${base}-${new Date().toISOString().replace(/[:.]/g, '-')}.${ext}`, message.toolResult ?? ''); }}\n className=\"inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground bg-background/80 border rounded px-1.5 py-0.5\" title=\"Download as file\"><Download className=\"h-3 w-3\" /></button>\n )}\n </div>\n </div>\n )}\n {expanded && message.toolResult !== undefined && message.toolResult.length === 0 && <span className=\"text-xs text-muted-foreground italic\">(empty)</span>}\n {!expanded && message.isError && message.toolResult && <div className=\"text-xs font-mono text-destructive truncate\">{message.toolResult.split('\\n')[0]}</div>}\n {((message.toolResult !== undefined && message.toolResult.length > 0) || (message.toolInput !== undefined && Object.keys((message.toolInput as object) ?? {}).length > 0)) && (\n <button type=\"button\" onClick={() => toggleTool(message.id)} className=\"text-xs text-muted-foreground hover:text-foreground transition-colors\">\n {expanded ? 'Hide details' : `Show details${lines > 0 ? ` (${lines} line${lines === 1 ? '' : 's'})` : ''}`}\n </button>\n )}\n </div>\n );\n })() : editing && isUser ? (\n <div className=\"flex flex-col gap-2 min-w-[280px]\">\n <textarea value={editValue} onChange={(e) => setEditValue(e.target.value)}\n onKeyDown={(e) => { if (e.key === 'Escape') { e.preventDefault(); cancelEdit(); } else if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); saveEdit(); } }}\n rows={Math.min(8, Math.max(2, editValue.split('\\n').length))}\n className=\"w-full resize-none rounded-md border bg-background text-foreground px-2 py-1.5 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-ring\" />\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-[10px] text-primary-foreground/60\">⌘/Ctrl+Enter to save · Esc to cancel</span>\n <div className=\"flex gap-1\">\n <button type=\"button\" onClick={cancelEdit} className=\"text-xs px-2 py-0.5 rounded border border-primary-foreground/30 hover:bg-primary-foreground/10\">Cancel</button>\n <button type=\"button\" onClick={saveEdit} disabled={!editValue.trim()} className=\"text-xs px-2 py-0.5 rounded bg-primary-foreground text-primary disabled:opacity-50\">Save & resend</button>\n </div>\n </div>\n </div>\n ) : (\n <div className=\"text-sm leading-relaxed markdown-content\">\n {message.content ? (showRaw && message.role === 'assistant' ? (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-foreground/90 max-h-[40rem] overflow-auto\">{message.content}</pre>\n ) : message.role === 'assistant' && message.isError ? (\n <ErrorBodyWithStack text={message.content} />\n ) : (\n <ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>{message.content}</ReactMarkdown>\n )) : message.streaming ? (\n <span className=\"inline-block animate-pulse text-muted-foreground\">Typing...</span>\n ) : (\n <span className=\"text-muted-foreground italic\">No content</span>\n )}\n </div>\n )}\n </div>\n\n <div className={cn('flex items-center gap-2 px-1', isUser ? 'flex-row-reverse' : 'flex-row')}>\n <span className=\"text-xs text-muted-foreground/50\">{new Date(message.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</span>\n {message.runSummary && (\n <span className=\"text-[10px] text-muted-foreground/60 font-mono tabular-nums\"\n title={[`Iterations: ${message.runSummary.iterations}`, `Tool calls: ${message.runSummary.tools}`, `Elapsed: ${(message.runSummary.durationMs / 1000).toFixed(2)}s`, message.runSummary.costDelta > 0 ? `Cost: $${message.runSummary.costDelta.toFixed(4)}` : ''].filter(Boolean).join(' · ')}>\n {message.runSummary.iterations} iter{message.runSummary.tools > 0 ? ` · ${message.runSummary.tools} tool${message.runSummary.tools === 1 ? '' : 's'}` : ''} · {message.runSummary.durationMs < 60_000 ? `${(message.runSummary.durationMs / 1000).toFixed(1)}s` : `${Math.floor(message.runSummary.durationMs / 60_000)}m ${Math.floor((message.runSummary.durationMs % 60_000) / 1000)}s`}{message.runSummary.costDelta > 0 ? ` · $${message.runSummary.costDelta >= 0.01 ? message.runSummary.costDelta.toFixed(4) : message.runSummary.costDelta.toFixed(6).replace(/0+$/, '').replace(/\\.$/, '')}` : ''}\n </span>\n )}\n {message.usage && (message.usage.input > 0 || message.usage.output > 0) && (() => {\n const u = message.usage;\n const dollars = (u.input * inputCost + u.output * outputCost + (u.cacheRead ?? 0) * cacheReadCost) / 1_000_000;\n const haveCost = inputCost > 0 || outputCost > 0;\n const dollarStr = dollars >= 0.01 ? `$${dollars.toFixed(4)}` : dollars > 0 ? `$${dollars.toFixed(6).replace(/0+$/, '').replace(/\\.$/, '')}` : '';\n return (<span className=\"text-[10px] text-muted-foreground/60 font-mono tabular-nums\" title={[`Input: ${u.input.toLocaleString()}`, `Output: ${u.output.toLocaleString()}`, u.cacheRead ? `Cache read: ${u.cacheRead.toLocaleString()}` : '', haveCost ? `Cost: ${dollarStr}` : ''].filter(Boolean).join(' · ')}>\n {u.input.toLocaleString()}→{u.output.toLocaleString()}{u.cacheRead ? ` · ${u.cacheRead.toLocaleString()} ↺` : ''}{haveCost && dollarStr ? ` · ${dollarStr}` : ''}\n </span>);\n })()}\n {!isTool && message.content && !message.streaming && <CopyButton text={message.content} label=\"\" className=\"opacity-0 group-hover:opacity-100 transition-opacity\" />}\n {message.role === 'assistant' && message.content && !message.streaming && (\n <button type=\"button\" onClick={() => setShowRaw((v) => !v)} title={showRaw ? 'Show rendered markdown' : 'Show raw markdown source'}\n className={cn('text-xs inline-flex items-center gap-1 transition-opacity', showRaw ? 'text-primary hover:text-primary/80 opacity-100' : 'opacity-0 group-hover:opacity-100 text-muted-foreground hover:text-foreground')}>\n <FileCode2 className=\"h-3 w-3\" /><span>{showRaw ? 'Rendered' : 'Raw'}</span>\n </button>\n )}\n {isUser && !editing && !isLoading && message.content && (\n <button type=\"button\" onClick={startEdit} title=\"Edit & resend this prompt\" className=\"opacity-0 group-hover:opacity-100 transition-opacity text-xs text-muted-foreground hover:text-foreground inline-flex items-center gap-1\">\n <Pencil className=\"h-3 w-3\" /><span>Edit</span>\n </button>\n )}\n {message.role === 'assistant' && message.content && !message.streaming && (\n <button type=\"button\" onClick={() => togglePin(message.id)} title={isPinned ? 'Unpin' : 'Pin this answer'}\n className={cn('text-xs inline-flex items-center gap-1 transition-opacity', isPinned ? 'text-amber-500 hover:text-amber-600 opacity-100' : 'opacity-0 group-hover:opacity-100 text-muted-foreground hover:text-foreground')}>\n {isPinned ? <PinOff className=\"h-3 w-3\" /> : <Pin className=\"h-3 w-3\" />}<span>{isPinned ? 'Pinned' : 'Pin'}</span>\n </button>\n )}\n {isLatestAssistant && message.content && !message.streaming && (\n <button type=\"button\" onClick={regenerate} title=\"Regenerate this response\" className=\"opacity-0 group-hover:opacity-100 transition-opacity text-xs text-muted-foreground hover:text-foreground inline-flex items-center gap-1\">\n <RotateCcw className=\"h-3 w-3\" /><span>Retry</span>\n </button>\n )}\n </div>\n </div>\n </div>\n );\n});\n","import { cn } from '@/lib/utils';\nimport { memo, useMemo } from 'react';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\ninterface DiffViewProps {\n oldText: string;\n newText: string;\n /** Optional caption shown above the diff (file path, \"write\" vs \"edit\", etc.) */\n caption?: string | undefined;\n}\n\n/**\n * Tiny line-based diff renderer. Computes the longest-common-subsequence\n * between `oldText` and `newText` line arrays, then walks both sides\n * emitting `add`/`remove`/`context` rows. Context lines are de-emphasised\n * so the eye lands on the changes. Not as pretty as a Myers diff but it's\n * one short function with no deps and good enough for a chat preview.\n *\n * Limits: text > 5000 lines is shown without a diff (just a \"too large\"\n * note); that's a UI guard, not a hard limit on the underlying tool.\n */\nexport const DiffView = memo(function DiffView({ oldText, newText, caption }: DiffViewProps) {\n const rows = useMemo(() => computeDiff(oldText, newText), [oldText, newText]);\n\n if (rows === null) {\n return (\n <div className=\"text-xs text-muted-foreground italic px-3 py-2\">\n Diff omitted (file too large to render inline).\n </div>\n );\n }\n\n const adds = rows.filter((r) => r.kind === 'add').length;\n const dels = rows.filter((r) => r.kind === 'del').length;\n\n return (\n <div className=\"rounded-lg border bg-background/40 overflow-hidden text-xs\">\n <div className=\"flex items-center justify-between px-3 py-1.5 border-b bg-muted/40\">\n <span className=\"font-mono text-muted-foreground truncate\">{caption ?? 'diff'}</span>\n <span className=\"font-mono shrink-0\">\n <span className=\"text-emerald-600 dark:text-emerald-400\">+{adds}</span>\n <span className=\"text-muted-foreground mx-1\">·</span>\n <span className=\"text-rose-600 dark:text-rose-400\">-{dels}</span>\n </span>\n </div>\n <div className=\"font-mono leading-relaxed max-h-96 overflow-auto\">\n {rows.map((r, i) => (\n <div\n // biome-ignore lint/suspicious/noArrayIndexKey: static diff rows\n key={i}\n className={cn(\n 'flex',\n r.kind === 'add' && 'bg-emerald-500/10',\n r.kind === 'del' && 'bg-rose-500/10',\n )}\n >\n <span\n className={cn(\n 'w-6 shrink-0 text-center select-none',\n r.kind === 'add' && 'text-emerald-600 dark:text-emerald-400',\n r.kind === 'del' && 'text-rose-600 dark:text-rose-400',\n r.kind === 'ctx' && 'text-muted-foreground/40',\n )}\n >\n {r.kind === 'add' ? '+' : r.kind === 'del' ? '-' : ' '}\n </span>\n <pre\n className={cn(\n 'whitespace-pre-wrap break-all flex-1 px-2',\n r.kind === 'ctx' && 'text-muted-foreground/70',\n )}\n >\n {r.text || ' '}\n </pre>\n </div>\n ))}\n </div>\n </div>\n );\n});\n\ninterface DiffRow {\n kind: 'add' | 'del' | 'ctx';\n text: string;\n}\n\nconst MAX_LINES = 5000;\n\n/**\n * Returns null when either side exceeds the line cap. Otherwise walks the\n * LCS table to produce a clean diff. LCS table is O(n*m) memory — fine for\n * a file edit (usually <500 lines), prohibitive for a full file rewrite of\n * a giant generated file (hence the cap).\n */\nfunction computeDiff(oldText: string, newText: string): DiffRow[] | null {\n const a = oldText.split('\\n');\n const b = newText.split('\\n');\n if (a.length > MAX_LINES || b.length > MAX_LINES) return null;\n const n = a.length;\n const m = b.length;\n // dp[i][j] = LCS length of a[i..] and b[j..]\n const dp: number[][] = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));\n for (let i = n - 1; i >= 0; i--) {\n for (let j = m - 1; j >= 0; j--) {\n if (a[i] === b[j]) expectDefined(dp[i])[j] = expectDefined(dp[i + 1]?.[j + 1]) + 1;\n else expectDefined(dp[i])[j] = Math.max(expectDefined(dp[i + 1]?.[j]), expectDefined(dp[i]?.[j + 1]));\n }\n }\n const rows: DiffRow[] = [];\n let i = 0;\n let j = 0;\n while (i < n && j < m) {\n if (a[i] === b[j]) {\n rows.push({ kind: 'ctx', text: expectDefined(a[i]) });\n i++;\n j++;\n } else if (expectDefined(dp[i + 1]?.[j]) >= expectDefined(dp[i]?.[j + 1])) {\n rows.push({ kind: 'del', text: expectDefined(a[i]) });\n i++;\n } else {\n rows.push({ kind: 'add', text: expectDefined(b[j]) });\n j++;\n }\n }\n while (i < n) rows.push({ kind: 'del', text: expectDefined(a[i++]) });\n while (j < m) rows.push({ kind: 'add', text: expectDefined(b[j++]) });\n return rows;\n}\n\n/**\n * Recognise the WrongStack edit-family tools and pull a (oldText, newText,\n * caption) tuple out of their input. Returns null when the tool doesn't\n * carry diffable input. Caller uses this to decide whether to render the\n * DiffView at all.\n */\nexport function diffFromToolInput(\n toolName: string | undefined,\n input: unknown,\n): { oldText: string; newText: string; caption: string } | null {\n if (!toolName || typeof input !== 'object' || input === null) return null;\n const obj = input as Record<string, unknown>;\n const filePath = String(obj.file_path ?? obj.path ?? '');\n switch (toolName) {\n case 'edit':\n case 'str_replace':\n case 'edit_file': {\n const oldText = typeof obj.old_string === 'string' ? obj.old_string : '';\n const newText = typeof obj.new_string === 'string' ? obj.new_string : '';\n if (!oldText && !newText) return null;\n return { oldText, newText, caption: `edit ${filePath}` };\n }\n case 'write':\n case 'write_file':\n case 'create_file': {\n const content = typeof obj.content === 'string' ? obj.content : '';\n // For a fresh write there's no \"old\" — treat as additive so the\n // viewer shows everything green.\n return { oldText: '', newText: content, caption: `write ${filePath} (new)` };\n }\n default:\n return null;\n }\n}\n","import { cn } from '@/lib/utils';\nimport { ChevronDown, ChevronRight, ChevronsDown, ChevronsUp } from 'lucide-react';\nimport { memo, useMemo, useState } from 'react';\n\n/** When a tool dumps hundreds of lines of output, the chat turns into a\n * scroll-wall. This threshold gates the auto-collapse: anything longer\n * shows the first ~LONG_PEEK_LINES with a \"Show all N more\" toggle. */\nconst LONG_OUTPUT_THRESHOLD = 25;\nconst LONG_PEEK_LINES = 12;\n\n/**\n * Render `text` as a monospace block, auto-collapsing when it exceeds\n * LONG_OUTPUT_THRESHOLD lines. The first LONG_PEEK_LINES stay visible;\n * the rest expand on click. Keeping the wrap class configurable lets the\n * `numbered` path use `whitespace-pre` (no wrap) and the bash/plain path\n * use `whitespace-pre-wrap break-all` (wrap and break long URLs/paths).\n */\nfunction CollapsibleText({\n text,\n isError,\n className,\n wrapClass,\n showLineNumbers,\n}: {\n text: string;\n isError?: boolean | undefined;\n className?: string | undefined;\n wrapClass: string;\n /** Whether to render a left gutter with line numbers when the output is\n * long. Off for the numbered/Read-tool path (which already prefixes its\n * own line numbers in the content) and for wrap-mode bodies where a\n * fixed gutter can't stay aligned with wrapped lines. */\n showLineNumbers?: boolean | undefined;\n}) {\n const lines = useMemo(() => text.split('\\n'), [text]);\n const isLong = lines.length > LONG_OUTPUT_THRESHOLD;\n const [expanded, setExpanded] = useState(!isLong);\n const shown = expanded ? text : lines.slice(0, LONG_PEEK_LINES).join('\\n');\n // Only emit the gutter when the body won't wrap (alignment would break\n // otherwise) AND the user actually expanded it / it's not super short.\n const renderGutter = !!showLineNumbers && isLong && expanded;\n return (\n <div className={cn('rounded-md border bg-background/40 overflow-hidden', className)}>\n {renderGutter ? (\n // Force `whitespace-pre` inside the gutter view so the line numbers\n // stay 1:1 with content rows. Long horizontal lines scroll within\n // the shared overflow container rather than wrapping (which would\n // break alignment between the gutter and the body).\n <div className=\"flex max-h-96 overflow-auto\">\n <pre\n aria-hidden\n className=\"text-xs font-mono leading-[1.4] py-2 pl-2 pr-2 text-muted-foreground/50 select-none border-r border-border/40 bg-muted/20 tabular-nums text-right whitespace-pre shrink-0\"\n >\n {lines.map((_, i) => `${i + 1}`).join('\\n')}\n </pre>\n <pre\n className={cn(\n 'text-xs font-mono leading-[1.4] py-2 px-2 flex-1 whitespace-pre',\n isError ? 'text-destructive' : 'text-foreground',\n )}\n >\n {shown}\n </pre>\n </div>\n ) : (\n <pre\n className={cn(\n 'text-xs font-mono p-2 max-h-96 overflow-auto',\n wrapClass,\n isError ? 'text-destructive' : 'text-foreground',\n )}\n >\n {shown}\n </pre>\n )}\n {isLong && (\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"w-full flex items-center justify-center gap-1 px-2 py-1 border-t bg-muted/30 text-[11px] text-muted-foreground hover:text-foreground transition-colors\"\n >\n {expanded ? (\n <>\n <ChevronsUp className=\"h-3 w-3\" />\n Collapse to first {LONG_PEEK_LINES} lines\n </>\n ) : (\n <>\n <ChevronsDown className=\"h-3 w-3\" />\n Show all {lines.length} lines ({lines.length - LONG_PEEK_LINES} more)\n </>\n )}\n </button>\n )}\n </div>\n );\n}\n\ninterface Props {\n toolName?: string | undefined;\n result: string;\n isError?: boolean | undefined;\n className?: string | undefined;\n}\n\n/**\n * Decides which renderer to use for a tool result based on its shape /\n * tool name. The goal is to make output *legible at a glance*:\n * - Read tool with leading line numbers stays line-numbered, monospace.\n * - Bash output gets a \"exit code N\" footer split from stdout.\n * - Valid JSON gets pretty-printed and collapsible by default.\n * - Everything else falls back to raw monospace.\n */\nexport const ToolResult = memo(function ToolResult({\n toolName,\n result,\n isError,\n className,\n}: Props) {\n const shape = useMemo(() => detectShape(toolName, result), [toolName, result]);\n\n if (shape.kind === 'json') {\n return <JsonResult value={shape.value} isError={isError} className={className} />;\n }\n if (shape.kind === 'numbered') {\n return (\n <CollapsibleText\n text={result}\n isError={isError}\n className={className}\n wrapClass=\"whitespace-pre\"\n />\n );\n }\n if (shape.kind === 'bash') {\n return (\n <div className={cn('rounded-md border bg-background/40 overflow-hidden', className)}>\n {shape.stdout && (\n <CollapsibleText\n text={shape.stdout}\n isError={isError}\n // Nested CollapsibleText already adds border/bg; strip them here\n // so we get one outer frame, not two.\n className=\"border-0 rounded-none bg-transparent\"\n wrapClass=\"whitespace-pre-wrap break-all\"\n showLineNumbers\n />\n )}\n {(shape.exitCode !== undefined || shape.duration) && (\n <div\n className={cn(\n 'flex items-center gap-3 text-[11px] px-2 py-1 border-t bg-muted/30 tabular-nums',\n shape.exitCode && shape.exitCode !== 0 ? 'text-destructive' : 'text-muted-foreground',\n )}\n >\n {shape.exitCode !== undefined && (\n <span>\n exit code: <span className=\"font-mono\">{shape.exitCode}</span>\n </span>\n )}\n {shape.duration && <span>{shape.duration}</span>}\n </div>\n )}\n </div>\n );\n }\n return (\n <CollapsibleText\n text={result}\n isError={isError}\n className={className}\n wrapClass=\"whitespace-pre-wrap break-all\"\n showLineNumbers\n />\n );\n});\n\ninterface Shape {\n kind: 'numbered' | 'json' | 'bash' | 'plain';\n /** For JSON results. */\n value?: unknown | undefined;\n /** For bash-shape results. */\n stdout?: string | undefined;\n exitCode?: number | undefined;\n duration?: string | undefined;\n}\n\nfunction detectShape(toolName: string | undefined, result: string): Shape {\n const trimmed = result.trim();\n // ---- Read tool: lines like \" 42→ const foo = …\" -------------\n if (/^\\s*\\d+→/m.test(result.slice(0, 200))) {\n return { kind: 'numbered' };\n }\n // ---- JSON ---------------------------------------------------------\n if (\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n try {\n const parsed = JSON.parse(trimmed);\n if (typeof parsed === 'object' && parsed !== null) {\n return { kind: 'json', value: parsed };\n }\n } catch {\n /* fall through */\n }\n }\n // ---- Bash-ish -----------------------------------------------------\n const isBashTool = !!toolName && /^(bash|shell|exec|run)/i.test(toolName);\n // Many bash wrappers emit a trailing \"exit code: N\" or \"[exit 1]\" line.\n const exitMatch = result.match(/(?:^|\\n)\\s*(?:\\[?exit(?:\\s*code)?\\]?\\s*[:=]?\\s*)(\\d+)\\s*$/i);\n const durMatch = result.match(/(?:^|\\s)(\\d+\\s*ms|\\d+\\.\\d+s)\\s*$/i);\n if (isBashTool || exitMatch) {\n let stdout = result;\n if (exitMatch) stdout = result.slice(0, exitMatch.index).trimEnd();\n return {\n kind: 'bash',\n stdout,\n exitCode: exitMatch ? Number(exitMatch[1]) : undefined,\n duration: durMatch?.[1],\n };\n }\n return { kind: 'plain' };\n}\n\nfunction JsonResult({\n value,\n isError,\n className,\n}: {\n value: unknown;\n isError?: boolean | undefined;\n className?: string | undefined;\n}) {\n const pretty = useMemo(() => {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n }, [value]);\n const lineCount = pretty.split('\\n').length;\n const [expanded, setExpanded] = useState(lineCount < 30);\n return (\n <div\n className={cn(\n 'rounded-md border bg-background/40 overflow-hidden',\n isError && 'border-destructive/40',\n className,\n )}\n >\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"w-full flex items-center justify-between px-2 py-1 border-b bg-muted/30 text-[11px] text-muted-foreground hover:text-foreground\"\n >\n <span className=\"flex items-center gap-1\">\n {expanded ? <ChevronDown className=\"h-3 w-3\" /> : <ChevronRight className=\"h-3 w-3\" />}\n <span className=\"font-mono\">JSON · {lineCount} lines</span>\n </span>\n <span>{expanded ? 'collapse' : 'expand'}</span>\n </button>\n {expanded && (\n <pre\n className={cn(\n 'text-xs font-mono whitespace-pre p-2 max-h-96 overflow-auto',\n isError ? 'text-destructive' : 'text-foreground',\n )}\n >\n {pretty}\n </pre>\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { Copy, Check } from 'lucide-react';\nimport { useState } from 'react';\nimport { copyToClipboard } from './utils.js';\n\nexport function CopyButton({\n text,\n className,\n label = 'Copy',\n}: {\n text: string;\n className?: string | undefined;\n label?: string | undefined;\n}) {\n const [copied, setCopied] = useState(false);\n return (\n <button\n type=\"button\"\n onClick={async (ev) => {\n ev.stopPropagation();\n const ok = await copyToClipboard(text);\n if (ok) {\n setCopied(true);\n setTimeout(() => setCopied(false), 1400);\n }\n }}\n className={cn(\n 'inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors',\n className,\n )}\n title={label}\n >\n {copied ? (\n <>\n <Check className=\"h-3 w-3 text-green-500\" />\n <span>Copied</span>\n </>\n ) : (\n <>\n <Copy className=\"h-3 w-3\" />\n <span>{label}</span>\n </>\n )}\n </button>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { CopyButton } from './CopyButton.js';\nimport type React from 'react';\n\nexport { copyToClipboard };\n\nasync function copyToClipboard(text: string): Promise<boolean> {\n try {\n if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(text);\n return true;\n }\n } catch {\n /* fall through */\n }\n try {\n const ta = document.createElement('textarea');\n ta.value = text;\n ta.style.position = 'fixed';\n ta.style.opacity = '0';\n document.body.appendChild(ta);\n ta.select();\n const ok = document.execCommand('copy');\n document.body.removeChild(ta);\n return ok;\n } catch {\n return false;\n }\n}\n\nexport function downloadTextFile(filename: string, text: string): void {\n if (typeof document === 'undefined') return;\n const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n\nexport function fileExtensionFor(toolName: string | undefined): string {\n const t = (toolName ?? '').toLowerCase();\n if (/bash|shell|exec|run/.test(t)) return 'log';\n if (/grep|search|find/.test(t)) return 'txt';\n return 'txt';\n}\n\nexport function formatToolDuration(ms: number): string {\n if (ms < 1000) return `${ms} ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(ms < 10_000 ? 2 : 1)}s`;\n const m = Math.floor(ms / 60_000);\n const s = Math.floor((ms % 60_000) / 1000);\n return `${m}m ${s}s`;\n}\n\nexport const markdownComponents = {\n code({\n inline,\n className,\n children,\n ...props\n }: {\n inline?: boolean | undefined;\n className?: string | undefined;\n children?: React.ReactNode | undefined;\n }) {\n const match = /language-(\\w+)/.exec(className ?? '');\n const codeText = String(children ?? '').replace(/\\n$/, '');\n if (inline || !match) {\n return (\n <code className={cn('rounded bg-muted/60 px-1.5 py-0.5 text-[0.85em] font-mono', className)} {...props}>\n {children}\n </code>\n );\n }\n return (\n <div className=\"not-prose relative my-3 rounded-lg border bg-muted/30 overflow-hidden\">\n <div className=\"flex items-center justify-between px-3 py-1.5 border-b bg-muted/40 text-xs\">\n <span className=\"font-mono text-muted-foreground\">{match[1]}</span>\n <CopyButton text={codeText} label=\"\" />\n </div>\n <pre className=\"overflow-x-auto p-3 text-xs leading-relaxed font-mono max-h-[40rem]\">\n <code>{codeText}</code>\n </pre>\n </div>\n );\n },\n};\n","import { cn } from '@/lib/utils';\nimport type React from 'react';\nimport { useState } from 'react';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\nfunction detectStackBoundary(text: string): number {\n const lines = text.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const ln = expectDefined(lines[i]);\n if (/^\\s*at\\s+\\S+.*\\(.*:\\d+:\\d+\\)\\s*$/.test(ln)) return i;\n if (/^\\s*at\\s+\\S+\\.\\S+\\(\\S+\\.java:\\d+\\)\\s*$/.test(ln)) return i;\n if (/^\\s+File \"[^\"]+\", line \\d+/.test(ln)) return i;\n }\n return -1;\n}\n\nexport function ErrorBodyWithStack({ text }: { text: string }) {\n const idx = detectStackBoundary(text);\n const [open, setOpen] = useState(false);\n if (idx === -1) {\n return (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs leading-relaxed\">\n {text}\n </pre>\n );\n }\n const lines = text.split('\\n');\n const head = lines.slice(0, idx).join('\\n').trim();\n const stack = lines.slice(idx).join('\\n');\n const frameCount = stack.split('\\n').filter((l) => l.trim().length > 0).length;\n return (\n <div className=\"space-y-2\">\n {head && (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs leading-relaxed\">\n {head}\n </pre>\n )}\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"inline-flex items-center gap-1 text-xs text-destructive hover:text-destructive/80 font-medium\"\n >\n {open ? '▾' : '▸'} {open ? 'Hide' : 'Show'} stack trace ({frameCount} frame\n {frameCount === 1 ? '' : 's'})\n </button>\n {open && (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-[11px] leading-snug bg-destructive/5 border border-destructive/20 rounded p-2 max-h-80 overflow-auto\">\n {stack}\n </pre>\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useState } from 'react';\n\nexport function ToolInputView({ input }: { input: unknown }) {\n const [openKeys, setOpenKeys] = useState<Record<string, boolean>>({});\n if (input === null || input === undefined || typeof input !== 'object' || Array.isArray(input)) {\n return (\n <pre className=\"whitespace-pre-wrap break-all text-xs font-mono\">\n {JSON.stringify(input, null, 2)}\n </pre>\n );\n }\n const entries = Object.entries(input as Record<string, unknown>);\n if (entries.length === 0) {\n return <span className=\"text-xs text-muted-foreground italic\">(no params)</span>;\n }\n return (\n <div className=\"text-xs font-mono\">\n {entries.map(([k, v]) => {\n const isPrimitive =\n v === null || v === undefined || typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';\n if (isPrimitive) {\n const display = v === null ? 'null' : v === undefined ? 'undefined' : typeof v === 'string' ? v : String(v);\n const isLong = typeof v === 'string' && (display.length > 80 || display.includes('\\n'));\n return (\n <div key={k} className={cn('py-0.5', isLong ? 'flex flex-col gap-0.5' : 'flex items-baseline gap-2')}>\n <span className=\"text-muted-foreground shrink-0\">{k}:</span>\n <span\n className={cn(\n 'text-foreground',\n isLong ? 'whitespace-pre-wrap break-all bg-muted/40 rounded px-1.5 py-1' : 'truncate',\n typeof v === 'string' ? '' : 'text-amber-600 dark:text-amber-400',\n )}\n title={typeof v === 'string' && !isLong ? display : undefined}\n >\n {display}\n </span>\n </div>\n );\n }\n const open = !!openKeys[k];\n const summary = Array.isArray(v)\n ? `[${v.length} item${v.length === 1 ? '' : 's'}]`\n : `{${Object.keys(v as object).length} key${Object.keys(v as object).length === 1 ? '' : 's'}}`;\n return (\n <div key={k} className=\"py-0.5\">\n <button\n type=\"button\"\n onClick={() => setOpenKeys((p) => ({ ...p, [k]: !p[k] }))}\n className=\"flex items-baseline gap-2 hover:bg-muted/30 rounded px-1 -mx-1\"\n >\n <span className=\"text-muted-foreground/60 text-[10px]\">{open ? '▾' : '▸'}</span>\n <span className=\"text-muted-foreground\">{k}:</span>\n <span className=\"text-violet-600 dark:text-violet-400\">{summary}</span>\n </button>\n {open && (\n <pre className=\"ml-3 mt-1 whitespace-pre-wrap break-all text-[11px] bg-muted/40 rounded px-2 py-1.5\">\n {JSON.stringify(v, null, 2)}\n </pre>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { useSessionStore } from '@/stores';\nimport { Check, ChevronDown } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\n/**\n * Pill-shaped mode chip in the topbar. Click to drop a small picker with\n * the available modes (fetched lazily on first open from the backend's\n * modes.list handler). Selecting a mode broadcasts a session.start update\n * so the chip and the system-prompt context reflect the change without a\n * page reload.\n */\nexport function ModePicker() {\n const mode = useSessionStore((s) => s.mode);\n const modes = useSessionStore((s) => s.modes);\n const { listModes, switchMode } = useWebSocket();\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n // Lazy-fetch the modes list the first time the user clicks the chip\n // (and refresh on every open in case the user installed a new mode\n // through some other surface).\n if (open) listModes();\n }, [open, listModes]);\n\n // Close on outside click / Escape.\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('mousedown', onClick);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onClick);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n const items =\n modes.length > 0\n ? modes\n : [{ id: 'default', name: 'Default', description: 'Standard agent behaviour' }];\n\n return (\n <div ref={rootRef} className=\"relative shrink-0\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium',\n 'bg-accent/40 text-foreground hover:bg-accent transition-colors border border-transparent hover:border-primary/30',\n )}\n title=\"Active mode\"\n >\n mode: <span className=\"font-mono\">{mode || 'default'}</span>\n <ChevronDown className=\"h-3 w-3 opacity-60\" />\n </button>\n {open && (\n <div className=\"absolute top-full left-0 mt-1 w-64 rounded-md border bg-popover shadow-lg z-30 py-1\">\n <div className=\"px-3 py-1.5 text-[10px] uppercase tracking-wider text-muted-foreground border-b\">\n Mode\n </div>\n {items.map((m) => (\n <button\n key={m.id}\n type=\"button\"\n onClick={() => {\n switchMode(m.id);\n setOpen(false);\n }}\n className={cn(\n 'w-full text-left px-3 py-2 hover:bg-accent/40 flex items-start gap-2',\n m.id === mode && 'bg-accent/30',\n )}\n >\n <Check\n className={cn(\n 'h-3.5 w-3.5 mt-0.5 shrink-0',\n m.id === mode ? 'opacity-100 text-primary' : 'opacity-0',\n )}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-xs font-mono\">{m.id}</div>\n {m.description && (\n <div className=\"text-[11px] text-muted-foreground leading-snug\">\n {m.description}\n </div>\n )}\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useChatStore, useUIStore } from '@/stores';\nimport { ArrowDown, ArrowUp, Search, X } from 'lucide-react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\n\n/**\n * Ctrl+F overlay that searches the current chat transcript. Hits are\n * counted as the user types; ↑/↓ step between hits and Enter scrolls the\n * highlighted message into view. The actual highlight is handed off via a\n * DOM data attribute so we don't need to invasively rewrap message\n * rendering — see ChatView for where the active hit gets the highlight\n * class applied.\n */\nexport function SearchOverlay() {\n const open = useUIStore((s) => s.searchOpen);\n const setOpen = useUIStore((s) => s.setSearchOpen);\n const query = useUIStore((s) => s.searchQuery);\n const setQuery = useUIStore((s) => s.setSearchQuery);\n const messages = useChatStore((s) => s.messages);\n\n const inputRef = useRef<HTMLInputElement>(null);\n const [activeHit, setActiveHit] = useState(0);\n\n useEffect(() => {\n if (open) requestAnimationFrame(() => inputRef.current?.focus());\n }, [open]);\n\n const hits = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return [] as string[];\n return messages\n .filter((m) => {\n if (m.role === 'tool') {\n return (\n (m.toolName ?? '').toLowerCase().includes(q) ||\n (m.toolResult ?? '').toLowerCase().includes(q) ||\n JSON.stringify(m.toolInput ?? '')\n .toLowerCase()\n .includes(q)\n );\n }\n return m.content.toLowerCase().includes(q);\n })\n .map((m) => m.id);\n }, [messages, query]);\n\n useEffect(() => {\n if (activeHit >= hits.length) setActiveHit(0);\n }, [hits, activeHit]);\n\n // Paint every match of the current query inside chat bubbles using the\n // CSS Custom Highlights API. We walk the text nodes under every\n // `[data-message-id]` element, build Range objects per hit, then register\n // two highlights: `chat-search` covers everything, `chat-search-active`\n // covers only the message currently navigated to (so the user can see\n // where they are in the list). The registry is cleared on unmount and on\n // every query change so stale ranges don't linger.\n useEffect(() => {\n // Feature-detect — falls back to silent no-op on older browsers; the\n // ring-flash navigation behaviour below still works.\n const win = window as unknown as {\n CSS?: { highlights?: Map<string, unknown> };\n Highlight?: new (...ranges: Range[]) => unknown | undefined;\n };\n const highlights = win.CSS?.highlights;\n const HighlightCtor = win.Highlight;\n if (!highlights || !HighlightCtor) return;\n const clear = () => {\n highlights.delete('chat-search');\n highlights.delete('chat-search-active');\n };\n const q = query.trim();\n if (!q || !open) {\n clear();\n return;\n }\n const lcQuery = q.toLowerCase();\n const allRanges: Range[] = [];\n const activeRanges: Range[] = [];\n const activeId = hits[activeHit];\n for (const el of document.querySelectorAll('[data-message-id]')) {\n const id = (el as HTMLElement).dataset.messageId;\n const isActive = id === activeId;\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n let node = walker.nextNode() as Text | null;\n while (node) {\n const text = node.nodeValue ?? '';\n if (text.length > 0) {\n const lc = text.toLowerCase();\n let from = 0;\n while (from <= lc.length - lcQuery.length) {\n const at = lc.indexOf(lcQuery, from);\n if (at === -1) break;\n const range = document.createRange();\n range.setStart(node, at);\n range.setEnd(node, at + lcQuery.length);\n allRanges.push(range);\n if (isActive) activeRanges.push(range);\n from = at + lcQuery.length;\n }\n }\n node = walker.nextNode() as Text | null;\n }\n }\n if (allRanges.length > 0) {\n highlights.set('chat-search', new HighlightCtor(...allRanges) as never);\n } else {\n highlights.delete('chat-search');\n }\n if (activeRanges.length > 0) {\n highlights.set('chat-search-active', new HighlightCtor(...activeRanges) as never);\n } else {\n highlights.delete('chat-search-active');\n }\n return clear;\n }, [query, hits, activeHit, open]);\n\n useEffect(() => {\n const id = hits[activeHit];\n if (!id) return;\n const el = document.querySelector(`[data-message-id=\"${id}\"]`);\n if (el) {\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n }, [hits, activeHit]);\n\n if (!open) return null;\n\n const step = (dir: 1 | -1) => {\n if (hits.length === 0) return;\n setActiveHit((i) => (i + dir + hits.length) % hits.length);\n };\n\n return (\n <div className=\"absolute top-2 right-4 z-30 w-[28rem] max-w-[calc(100%-2rem)] rounded-lg border bg-popover shadow-xl\">\n <div className=\"flex items-center gap-2 px-3 py-2\">\n <Search className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n setOpen(false);\n } else if (e.key === 'Enter') {\n e.preventDefault();\n step(e.shiftKey ? -1 : 1);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n step(1);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n step(-1);\n }\n }}\n placeholder=\"Search in chat…\"\n className=\"flex-1 bg-transparent outline-none text-sm placeholder:text-muted-foreground\"\n />\n <span className=\"text-xs text-muted-foreground tabular-nums shrink-0\">\n {hits.length === 0 ? (query ? '0' : '') : `${activeHit + 1} / ${hits.length}`}\n </span>\n <button\n type=\"button\"\n onClick={() => step(-1)}\n disabled={hits.length === 0}\n className={cn(\n 'p-1 rounded hover:bg-muted disabled:opacity-30 disabled:cursor-not-allowed',\n )}\n title=\"Previous hit\"\n >\n <ArrowUp className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => step(1)}\n disabled={hits.length === 0}\n className={cn(\n 'p-1 rounded hover:bg-muted disabled:opacity-30 disabled:cursor-not-allowed',\n )}\n title=\"Next hit\"\n >\n <ArrowDown className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className=\"p-1 rounded hover:bg-muted text-muted-foreground\"\n title=\"Close (Esc)\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { Monitor, Moon, Sun } from 'lucide-react';\nimport { useTheme } from './ThemeProvider';\n\nconst OPTIONS = [\n { value: 'light', icon: Sun, label: 'Light' },\n { value: 'dark', icon: Moon, label: 'Dark' },\n { value: 'system', icon: Monitor, label: 'System' },\n] as const;\n\n/**\n * Segmented Light / Dark / System theme control. Instrument-style: a small\n * bezelled track with the active segment lit in signal-amber.\n */\nexport function ThemeToggle({ className }: { className?: string | undefined }) {\n const { theme, setTheme } = useTheme();\n return (\n <div\n className={cn(\n 'inline-flex items-center gap-0.5 rounded-lg border border-border bg-card/70 p-0.5 shadow-sm',\n className,\n )}\n aria-label=\"Theme\"\n >\n {OPTIONS.map(({ value, icon: Icon, label }) => {\n const active = theme === value;\n return (\n <button\n key={value}\n type=\"button\"\n aria-pressed={active}\n title={`${label} theme`}\n aria-label={`${label} theme`}\n onClick={() => setTheme(value)}\n className={cn(\n 'grid h-7 w-7 place-items-center rounded-md transition-all duration-150',\n active\n ? 'bg-primary/15 text-primary shadow-[inset_0_0_0_1px_hsl(var(--primary)/0.35)]'\n : 'text-muted-foreground hover:bg-accent hover:text-foreground',\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" strokeWidth={2.2} />\n </button>\n );\n })}\n </div>\n );\n}\n","import { useConfigStore } from '@/stores';\nimport type React from 'react';\nimport { createContext, useContext, useEffect, useState } from 'react';\n\ntype Theme = 'light' | 'dark' | 'system';\n\ninterface ThemeProviderProps {\n children: React.ReactNode;\n defaultTheme?: Theme | undefined;\n storageKey?: string | undefined;\n}\n\ninterface ThemeProviderState {\n theme: Theme;\n setTheme: (theme: Theme) => void;\n}\n\nconst ThemeProviderContext = createContext<ThemeProviderState | undefined>(undefined);\n\nexport function ThemeProvider({\n children,\n defaultTheme = 'system',\n storageKey = 'wrongstack-theme',\n}: ThemeProviderProps) {\n const { setTheme: setStoreTheme } = useConfigStore();\n const [theme, setTheme] = useState<Theme>(() => {\n if (typeof window !== 'undefined') {\n return (localStorage.getItem(storageKey) as Theme) || defaultTheme;\n }\n return defaultTheme;\n });\n\n useEffect(() => {\n const root = window.document.documentElement;\n root.classList.remove('light', 'dark');\n\n if (theme === 'system') {\n const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light';\n root.classList.add(systemTheme);\n } else {\n root.classList.add(theme);\n }\n }, [theme]);\n\n const value = {\n theme,\n setTheme: (newTheme: Theme) => {\n localStorage.setItem(storageKey, newTheme);\n setTheme(newTheme);\n setStoreTheme(newTheme);\n },\n };\n\n return <ThemeProviderContext.Provider value={value}>{children}</ThemeProviderContext.Provider>;\n}\n\nexport function useTheme() {\n const context = useContext(ThemeProviderContext);\n if (context === undefined) {\n throw new Error('useTheme must be used within a ThemeProvider');\n }\n return context;\n}\n","import { cn } from '@/lib/utils';\nimport type { ChatMessage } from '@/stores';\nimport { CheckCircle2, ChevronDown, ChevronRight, Loader2, Terminal, XCircle } from 'lucide-react';\nimport { memo, useState } from 'react';\nimport { MessageBubble } from './MessageBubble';\n\n\n\nfunction expectDefined<T>(value: T | null | undefined): T {\n if (value === null || value === undefined) {\n throw new Error('Expected value to be defined');\n }\n return value;\n}\n\ninterface ToolGroupProps {\n /** A run of consecutive tool messages (>=1). Rendered as one chip while\n * collapsed, expanded into the usual MessageBubble list on click. */\n tools: ChatMessage[];\n /** Force-expand the latest group so newly-running tools are visible by\n * default (otherwise users see \"5 tool calls\" pop in and have to click to\n * understand what's running). Older groups stay collapsed. */\n defaultOpen?: boolean | undefined;\n /** Render as a continuation of the previous item in the same agent turn —\n * hides the avatar column (replaced with a transparent spacer) and the\n * group's chrome stitches into the same flow as the surrounding text /\n * tool items instead of standing alone. */\n isContinuation?: boolean | undefined;\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(ms < 10_000 ? 2 : 1)}s`;\n const m = Math.floor(ms / 60_000);\n const s = Math.floor((ms % 60_000) / 1000);\n return `${m}m${s}s`;\n}\n\nexport const ToolGroup = memo(function ToolGroup({\n tools,\n defaultOpen = false,\n isContinuation = false,\n}: ToolGroupProps) {\n const [open, setOpen] = useState(defaultOpen);\n\n // Single tool? Render as a normal bubble — grouping overhead is just noise.\n if (tools.length === 1) {\n return <MessageBubble message={expectDefined(tools[0])} isFirst isContinuation={isContinuation} />;\n }\n\n const running = tools.filter((t) => t.toolResult === undefined).length;\n const errored = tools.filter((t) => t.isError).length;\n const totalMs = tools.reduce((acc, t) => acc + (t.toolDurationMs ?? 0), 0);\n\n // Show the first few tool names so the user has a hint of what's inside\n // without expanding (\"Read, Grep, Bash …\").\n const names = Array.from(new Set(tools.map((t) => t.toolName).filter(Boolean) as string[]));\n const preview = names.slice(0, 3).join(', ');\n const more = names.length > 3 ? ` +${names.length - 3}` : '';\n\n return (\n <div className=\"flex gap-3 animate-message\">\n {isContinuation ? (\n <div className=\"flex-shrink-0 w-8 h-8\" aria-hidden />\n ) : (\n <div className=\"flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center bg-secondary text-secondary-foreground ring-2 ring-offset-2 ring-offset-background ring-secondary/20\">\n <Terminal className=\"h-4 w-4\" />\n </div>\n )}\n\n <div className=\"flex flex-col gap-1.5 max-w-[85%] flex-1 min-w-0\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'flex items-center gap-2 text-sm font-medium cursor-pointer select-none',\n 'hover:bg-muted/50 rounded-lg px-2 py-1.5 -mx-2 transition-colors',\n 'border border-border/40 bg-muted/30',\n )}\n >\n {open ? (\n <ChevronDown className=\"h-3.5 w-3.5 text-muted-foreground\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5 text-muted-foreground\" />\n )}\n <Terminal className=\"h-3.5 w-3.5 text-muted-foreground\" />\n <span className=\"font-mono text-xs\">\n {tools.length} tool call{tools.length === 1 ? '' : 's'}\n </span>\n {running > 0 ? (\n <Loader2 className=\"h-3 w-3 animate-spin text-amber-500\" />\n ) : errored > 0 ? (\n <XCircle className=\"h-3 w-3 text-destructive\" />\n ) : (\n <CheckCircle2 className=\"h-3 w-3 text-green-500\" />\n )}\n {totalMs > 0 && (\n <span className=\"text-xs text-muted-foreground tabular-nums font-normal\">\n {formatDuration(totalMs)}\n </span>\n )}\n {preview && (\n <span className=\"text-xs text-muted-foreground/80 font-mono truncate\">\n · {preview}\n {more}\n </span>\n )}\n </button>\n\n {open && (\n <div className=\"space-y-2 pl-3 border-l-2 border-border/40 ml-2\">\n {tools.map((tool) => (\n <MessageBubble key={tool.id} message={tool} isFirst={false} />\n ))}\n </div>\n )}\n </div>\n </div>\n );\n});\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore, useHistoryStore, useSessionStore, useUIStore } from '@/stores';\nimport type { WSServerMessage } from '@/types';\nimport type { LucideIcon } from 'lucide-react';\nimport {\n ArchiveRestore,\n ArrowRight,\n Bug,\n Clock,\n KeyRound,\n Keyboard,\n Search,\n Sparkles,\n Wrench,\n Zap,\n} from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\ninterface PromptCard {\n icon: LucideIcon;\n title: string;\n hint: string;\n tone: string;\n prompts: string[];\n}\n\nconst CARDS: PromptCard[] = [\n {\n icon: Search,\n title: 'Explore',\n hint: 'Understand the code before changing it',\n tone: 'text-blue-600 dark:text-blue-400 bg-blue-500/10 border-blue-500/20',\n prompts: [\n 'Walk me through this codebase: list the top-level packages, the role of each, and how they depend on one another. Highlight any cross-cutting abstractions I should understand first.',\n \"Find every place where the WebSocket protocol is defined or consumed (server handlers, client send/receive, type contracts). Show me the message-type table and any gaps where the type isn't enforced.\",\n 'Locate the entrypoint that boots the agent for normal runs. Trace the call chain from CLI launch all the way to the first model call — what middleware, hooks, and tools are wired along the way?',\n ],\n },\n {\n icon: Wrench,\n title: 'Build',\n hint: 'Add a feature end-to-end',\n tone: 'text-emerald-600 dark:text-emerald-400 bg-emerald-500/10 border-emerald-500/20',\n prompts: [\n \"Add a slash command `/export` that dumps the current chat (messages + tool calls + usage) as a markdown file to ~/.wrongstack/exports/ and surfaces a 'saved to X' toast. Wire backend + ws-client + slash menu entry.\",\n 'Create a notification toast system (Zustand store + portal-rendered <Toast/> component) and migrate every existing `key.operation_result` success/failure message to use it instead of dropping into chat.',\n 'Add structured JSON logging to the WebSocket server: each handler logs `{ts, level, type, payload}` to ~/.wrongstack/logs/webui.jsonl. Make it tail-friendly and respect the existing log.level config.',\n ],\n },\n {\n icon: Bug,\n title: 'Debug',\n hint: 'Track a problem to its root cause',\n tone: 'text-amber-600 dark:text-amber-400 bg-amber-500/10 border-amber-500/20',\n prompts: [\n 'Something feels off with token accounting — the cost chip and the per-message tally drift apart over a long session. Reproduce locally if you can, then propose a fix. Start by reading the TokenCounter + provider.response handler.',\n 'The WebSocket sometimes silently stops streaming text mid-response on lossy networks. Check the reconnect logic, message queue, and how we handle a half-completed text_delta stream after a reconnect.',\n 'I want to know why ctx % climbs so fast in long sessions. Use the existing /debug context breakdown to identify the largest contributors and propose three concrete pruning strategies (with token savings estimates).',\n ],\n },\n {\n icon: Sparkles,\n title: 'Refactor',\n hint: 'Clean up without breaking behavior',\n tone: 'text-violet-600 dark:text-violet-400 bg-violet-500/10 border-violet-500/20',\n prompts: [\n 'Find duplicated logic between packages/cli/src/webui-server.ts and packages/webui/src/server/index.ts. Extract the shared bits into a single source of truth (likely the webui package) and update the CLI to import it.',\n \"Look at the Zustand stores in packages/webui/src/stores/index.ts — anything that should be a derived selector instead of stored state? Anything persisted that shouldn't be? Propose a leaner shape and migration plan.\",\n \"Audit the slash command dispatcher: pull each command's run logic into its own module under packages/webui/src/commands/, make the registry data-driven, and ensure /help auto-generates from the registry (not a hardcoded list).\",\n ],\n },\n];\n\nconst SLASH_REFS: Array<{ name: string; hint: string }> = [\n { name: '/help', hint: 'list every slash command' },\n { name: '/diag', hint: 'runtime diagnostics' },\n { name: '/stats', hint: 'tokens · cache · cost · elapsed' },\n { name: '/tools', hint: 'show registered tools' },\n { name: '/memory', hint: 'show remembered notes' },\n { name: '/compact', hint: 'shrink context' },\n { name: '/clear', hint: 'wipe current context' },\n { name: '/new', hint: 'fresh session' },\n];\n\nfunction fillTextarea(text: string): void {\n const ta = document.querySelector('textarea');\n if (!ta) return;\n const setter = Object.getOwnPropertyDescriptor(\n window.HTMLTextAreaElement.prototype,\n 'value',\n )?.set;\n setter?.call(ta, text);\n ta.dispatchEvent(new Event('input', { bubbles: true }));\n ta.focus();\n}\n\nexport function WelcomeScreen() {\n const { projectName } = useSessionStore();\n const { provider, model } = useConfigStore();\n const wsConnected = useConfigStore((s) => s.wsConnected);\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const setCurrentView = useUIStore((s) => s.setCurrentView);\n /** Saved-provider count. We subscribe directly to `providers.saved`\n * because SettingsPanel is the canonical owner of that state but isn't\n * always mounted (only when the user is on the Settings tab). undefined\n * means \"not yet fetched\" — we skip the CTA in that state to avoid a\n * flash on first paint. */\n const [savedCount, setSavedCount] = useState<number | undefined>(undefined);\n useEffect(() => {\n if (!wsConnected) return;\n const client = getWSClient(wsUrl);\n const off = client.on('providers.saved', (msg: WSServerMessage) => {\n const p = msg.payload as { providers: unknown[] };\n setSavedCount(p.providers?.length ?? 0);\n });\n client.listSavedProviders();\n return () => {\n off();\n };\n }, [wsConnected, wsUrl]);\n /** Recent prompts harvested from the user's typing history. The same\n * store that powers ↑/↓ recall in the input — surfacing them here turns\n * a blank welcome screen into a useful \"pick up where you left off\"\n * surface, without any backend round-trip. Limited to 6 so it doesn't\n * dominate the page. */\n const promptHistory = useUIStore((s) => s.promptHistory);\n const recentPrompts = promptHistory.slice(0, 6);\n /** Recent sessions surfaced as one-click resume buttons. Drives the\n * \"pick back up\" workflow without sending the user to the History tab.\n * We fetch on first paint when connected; the listing is otherwise\n * populated by the History tab on demand. */\n const { listSessions, resumeSession } = useWebSocket();\n const historyEntries = useHistoryStore((s) => s.entries);\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only\n useEffect(() => {\n if (wsConnected && historyEntries.length === 0) listSessions(10);\n // Intentionally only fire on first connect — refreshing on every\n // historyEntries change would loop after the response lands.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [wsConnected]);\n const sessionNicknames = useUIStore((s) => s.sessionNicknames);\n const recentSessions = historyEntries.filter((e) => !e.isCurrent).slice(0, 4);\n\n return (\n <div className=\"flex flex-col gap-8 py-8 px-2 max-w-5xl mx-auto w-full\">\n {/* Hero */}\n <div className=\"flex flex-col items-center text-center gap-3\">\n <div className=\"relative\">\n <div className=\"w-14 h-14 rounded-2xl bg-gradient-to-br from-primary via-primary to-primary/60 flex items-center justify-center shadow-lg shadow-primary/20\">\n <Zap className=\"h-7 w-7 text-primary-foreground\" />\n </div>\n <div className=\"absolute -inset-3 bg-gradient-to-r from-transparent via-primary/10 to-transparent animate-pulse rounded-full -z-10\" />\n </div>\n <div>\n <h2 className=\"text-2xl font-semibold tracking-tight\">\n Where do you want to start\n {projectName ? (\n <>\n {' in '}\n <span className=\"text-primary\">{projectName}</span>\n </>\n ) : (\n ''\n )}\n ?\n </h2>\n <p className=\"text-sm text-muted-foreground mt-2 max-w-2xl mx-auto leading-relaxed\">\n WrongStack is connected to your project and ready to read, edit, run commands, search\n the codebase, track todos, and remember context across sessions. Pick a starting prompt\n below, write your own, or type <span className=\"font-mono text-foreground/80\">/</span>{' '}\n for the full command palette.\n </p>\n {provider && model && (\n <p className=\"text-xs text-muted-foreground/70 mt-2 font-mono\">\n {provider} / {model}\n </p>\n )}\n </div>\n </div>\n\n {/* No-keys CTA — shown only when the backend is connected and the\n providers.saved response confirmed zero registered keys. Lands\n above the prompt cards because clicking those won't work until\n the user adds a key. Quietly disappears once at least one\n provider is registered. */}\n {wsConnected && savedCount === 0 && (\n <button\n type=\"button\"\n onClick={() => setCurrentView('settings')}\n className={cn(\n 'group rounded-xl border bg-gradient-to-br from-amber-500/10 via-amber-500/5 to-transparent',\n 'border-amber-500/30 hover:border-amber-500/50 transition-colors',\n 'p-4 flex items-center gap-4 text-left',\n )}\n >\n <span className=\"flex items-center justify-center w-12 h-12 rounded-lg bg-amber-500/15 text-amber-600 dark:text-amber-400 shrink-0\">\n <KeyRound className=\"h-6 w-6\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-base font-semibold mb-1\">No API key configured yet</h3>\n <p className=\"text-sm text-muted-foreground leading-relaxed\">\n Register a provider in Settings before sending a message — otherwise the agent has\n nothing to talk to. Anthropic, OpenAI, Google, and any OpenAI-compatible endpoint all\n work.\n </p>\n </div>\n <span className=\"flex items-center gap-1 text-xs text-amber-600 dark:text-amber-400 font-medium shrink-0 group-hover:translate-x-0.5 transition-transform\">\n Open Settings <ArrowRight className=\"h-3.5 w-3.5\" />\n </span>\n </button>\n )}\n\n {/* Prompt cards */}\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\n {CARDS.map((card) => {\n const Icon = card.icon;\n return (\n <div\n key={card.title}\n className=\"rounded-xl border bg-card/40 backdrop-blur-sm p-4 flex flex-col gap-3\"\n >\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'flex items-center justify-center w-8 h-8 rounded-lg border',\n card.tone,\n )}\n >\n <Icon className=\"h-4 w-4\" />\n </span>\n <div>\n <h3 className=\"text-sm font-semibold\">{card.title}</h3>\n <p className=\"text-xs text-muted-foreground\">{card.hint}</p>\n </div>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n {card.prompts.map((p, i) => (\n <button\n // biome-ignore lint/suspicious/noArrayIndexKey: static list\n key={i}\n type=\"button\"\n onClick={() => fillTextarea(p)}\n className=\"text-left text-xs leading-relaxed text-foreground/80 hover:text-foreground border border-transparent hover:border-border/60 rounded-lg px-3 py-2 hover:bg-muted/40 transition-colors line-clamp-3\"\n title={p}\n >\n {p}\n </button>\n ))}\n </div>\n </div>\n );\n })}\n </div>\n\n {/* Recent sessions — one-click resume. We pull the most recent\n non-current sessions so the user can pick back up without leaving\n the welcome screen. Hidden when there's nothing to show (fresh\n install / first run). */}\n {recentSessions.length > 0 && (\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-center gap-2 mb-3\">\n <ArchiveRestore className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground font-medium\">\n Pick back up\n </span>\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2\">\n {recentSessions.map((entry) => (\n <button\n key={entry.id}\n type=\"button\"\n onClick={() => resumeSession(entry.id)}\n className=\"text-left rounded-lg border border-border/40 bg-background/60 hover:border-primary/40 hover:bg-accent/30 px-3 py-2 transition-colors group/sess\"\n title={entry.title}\n >\n <div className=\"text-sm font-medium truncate text-foreground group-hover/sess:text-primary\">\n {sessionNicknames[entry.id] || entry.title || '(empty)'}\n </div>\n <div className=\"text-[10px] text-muted-foreground font-mono truncate mt-0.5\">\n {entry.provider}/{entry.model}\n {entry.tokenTotal > 0 && (\n <span className=\"ml-2\">· {entry.tokenTotal.toLocaleString()} tok</span>\n )}\n </div>\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Recent prompts — your own past prompts as one-click refills. Slash\n commands aren't included (the quick-commands block below handles\n those). Shows nothing until you've actually typed something. */}\n {recentPrompts.length > 0 && (\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-center gap-2 mb-3\">\n <Clock className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground font-medium\">\n Recent prompts\n </span>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n {recentPrompts\n .filter((p) => !p.startsWith('/'))\n .slice(0, 5)\n .map((p, i) => (\n <button\n // biome-ignore lint/suspicious/noArrayIndexKey: static list\n key={i}\n type=\"button\"\n onClick={() => fillTextarea(p)}\n className=\"text-left text-xs leading-relaxed text-muted-foreground hover:text-foreground border border-transparent hover:border-border/60 rounded-lg px-3 py-2 hover:bg-background/60 transition-colors line-clamp-2\"\n title={p}\n >\n {p}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Slash command quick-ref */}\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-center gap-2 mb-3\">\n <Keyboard className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground font-medium\">\n Quick commands\n </span>\n </div>\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-2\">\n {SLASH_REFS.map((c) => (\n <button\n key={c.name}\n type=\"button\"\n onClick={() => fillTextarea(c.name)}\n className=\"text-left flex flex-col gap-0.5 rounded-md border border-border/40 bg-background/60 px-3 py-2 hover:border-primary/40 hover:bg-accent/40 transition-colors\"\n >\n <span className=\"font-mono text-xs text-foreground\">{c.name}</span>\n <span className=\"text-[11px] text-muted-foreground truncate\">{c.hint}</span>\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';\nimport * as React from 'react';\n\nconst ScrollArea = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>\n>(({ className, children, ...props }, ref) => (\n <ScrollAreaPrimitive.Root\n ref={ref}\n className={cn('relative overflow-hidden', className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport className=\"h-full w-full rounded-[inherit]\">\n {children}\n </ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n));\nScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;\n\nconst ScrollBar = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>\n>(({ className, orientation = 'vertical', ...props }, ref) => (\n <ScrollAreaPrimitive.ScrollAreaScrollbar\n ref={ref}\n orientation={orientation}\n className={cn(\n 'flex touch-none select-none transition-colors',\n orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-[1px]',\n orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-[1px]',\n className,\n )}\n {...props}\n >\n <ScrollAreaPrimitive.ScrollAreaThumb className=\"relative flex-1 rounded-full bg-border\" />\n </ScrollAreaPrimitive.ScrollAreaScrollbar>\n));\nScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;\n\nexport { ScrollArea, ScrollBar };\n","export function fmtTok(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1000) return `${(n / 1000).toFixed(n >= 10_000 ? 0 : 1)}k`;\n return String(n);\n}\n","import { useChatStore } from '@/stores';\nimport { Brain } from 'lucide-react';\n\n/**\n * Soft, ephemeral chip rendered while the model is mid-reasoning. Reads the\n * thinking buffer straight from the chat store so it stays in sync with the\n * stream without re-rendering the full message list.\n */\nexport function ThinkingBubble() {\n const buf = useChatStore((s) => s.thinkingBuffer);\n if (!buf) return null;\n const tailLines = buf.split('\\n').slice(-6);\n const tail = tailLines.join('\\n').trim();\n return (\n <div className=\"flex gap-3 animate-message\">\n <div className=\"flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center bg-violet-500/10 text-violet-600 dark:text-violet-400 ring-2 ring-offset-2 ring-offset-background ring-violet-500/20\">\n <Brain className=\"h-4 w-4 animate-pulse\" />\n </div>\n <div className=\"flex flex-col gap-1 max-w-[85%] min-w-0\">\n <span className=\"text-xs font-medium text-violet-600 dark:text-violet-400 px-1\">\n Thinking…\n </span>\n <div className=\"rounded-2xl rounded-bl-md px-3 py-2 bg-violet-500/[0.04] border border-violet-500/20 text-foreground/80\">\n <pre className=\"whitespace-pre-wrap break-words font-sans text-xs leading-relaxed italic max-h-32 overflow-hidden\">\n {tail || '…'}\n </pre>\n </div>\n </div>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore } from '@/stores';\nimport { Eye, LogIn, LogOut, MessageSquareWarning, Pause, Play, Users } from 'lucide-react';\nimport type React from 'react';\nimport type { CollabRole, WSCollabAnnotationAdded, WSCollabAnnotationResolved, WSCollabParticipantJoined, WSCollabParticipantLeft, WSCollabPauseGranted, WSCollabPauseReleased, WSCollabState, WSError, WSServerMessage } from '@/types';\nimport { useEffect, useState } from 'react';\n\nexport interface CollabPanelProps {\n /** Current session id — the panel joins this session on mount if the user opts in. */\n sessionId: string;\n /** Optional className for layout-level styling. */\n className?: string | undefined;\n}\n\nexport interface CollabParticipant {\n participantId: string;\n role: CollabRole;\n joinedAt: string;\n}\n\n/**\n * CollabPanel — read-only live observer indicator + join/leave control.\n *\n * Phase 1 of idea #13: a second human can join an active agent run and\n * watch a live mirror of kernel events (tool calls, iterations, subagent\n * spawns). The observer cannot modify the agent. Annotation and control\n * hand-off land in Phase 2/3.\n *\n * UX:\n * - 0 observers → muted \"Join as observer\" CTA\n * - 1+ observers → live dot + count + role chips + \"Leave\" button\n * - State stays in sync with the 2s server-side broadcast\n */\nexport function CollabPanel({ sessionId, className }: CollabPanelProps): React.ReactElement {\n const [participants, setParticipants] = useState<CollabParticipant[]>([]);\n const [joined, setJoined] = useState(false);\n const [joinedRole, setJoinedRole] = useState<'observer' | 'annotator' | 'controller' | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [openAnnotationCount, setOpenAnnotationCount] = useState(0);\n const [paused, setPaused] = useState(false);\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const client = getWSClient(wsUrl);\n\n useEffect(() => {\n const offs: Array<() => void> = [];\n\n // collab.state — full snapshot, sent on connect and every 2s.\n offs.push(\n client.on('collab.state', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabState['payload'];\n if (p.sessionId === sessionId) {\n setParticipants(p.participants ?? []);\n }\n }),\n );\n\n // collab.participant.joined — incremental add.\n offs.push(\n client.on('collab.participant.joined', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabParticipantJoined['payload'];\n if (p.sessionId !== sessionId) return;\n setParticipants((prev) => {\n if (prev.some((x) => x.participantId === p.participantId)) return prev;\n return [...prev, { participantId: p.participantId, role: p.role, joinedAt: p.joinedAt }];\n });\n }),\n );\n\n // collab.participant.left — incremental remove.\n offs.push(\n client.on('collab.participant.left', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabParticipantLeft['payload'];\n if (p.sessionId !== sessionId) return;\n const id = p.participantId;\n setParticipants((prev) => prev.filter((p) => p.participantId !== id));\n }),\n );\n\n // Surface collab-tagged server errors (e.g. role not available).\n offs.push(\n client.on('error', (msg: WSServerMessage) => {\n const p = msg.payload as WSError['payload'];\n if (p.phase === 'collab') {\n setError(p.message);\n // Optimistically mark as not joined so the user can retry.\n setJoined(false);\n }\n }),\n );\n\n // Suppress unhandled collab.event messages in the central dispatcher\n // (they're consumed by whoever renders the live activity strip).\n offs.push(client.on('collab.event', () => {}));\n\n // Phase 2: annotation count. We just track the local count of\n // unresolved annotations for a quick \"X notes\" indicator. The\n // full annotation timeline UI is a follow-up; the count gives\n // immediate visibility (\"are people reviewing this?\").\n offs.push(\n client.on('collab.annotation.added', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabAnnotationAdded['payload'];\n if (p.sessionId !== sessionId) return;\n if (p.annotation?.resolved) return;\n setOpenAnnotationCount((c) => c + 1);\n }),\n );\n offs.push(\n client.on('collab.annotation.resolved', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabAnnotationResolved['payload'];\n if (p.sessionId !== sessionId) return;\n setOpenAnnotationCount((c) => Math.max(0, c - 1));\n }),\n );\n\n // Phase 3: pause state. We track the local view of the bus\n // state and surface a small \"Paused\" chip. The actual pause/\n // resume actions are gated to controller participants.\n offs.push(\n client.on('collab.pause.granted', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabPauseGranted['payload'];\n if (p.sessionId !== sessionId) return;\n setPaused(true);\n }),\n );\n offs.push(\n client.on('collab.pause.released', (msg: WSServerMessage) => {\n const p = msg.payload as WSCollabPauseReleased['payload'];\n if (p.sessionId !== sessionId) return;\n setPaused(false);\n }),\n );\n\n return () => {\n for (const off of offs) off();\n };\n }, [client, sessionId]);\n\n const handleJoin = (role: 'observer' | 'annotator' | 'controller' = 'observer'): void => {\n setError(null);\n client.send({ type: 'collab.join', payload: { sessionId, role } });\n setJoined(true);\n setJoinedRole(role);\n };\n\n const handleRequestPause = (): void => {\n client.send({ type: 'collab.request_pause', payload: { sessionId } });\n };\n\n const handleResume = (): void => {\n client.send({ type: 'collab.resume', payload: { sessionId } });\n };\n\n const handleLeave = (): void => {\n client.send({ type: 'collab.leave', payload: { sessionId } });\n setJoined(false);\n setParticipants([]);\n };\n\n // Empty state: nobody watching, no errors.\n if (participants.length === 0 && !error) {\n return (\n <div\n className={cn(\n 'flex items-center gap-2 px-3 py-2 rounded-md border border-dashed border-border bg-card/40',\n className,\n )}\n >\n <Users className=\"w-4 h-4 text-muted-foreground\" />\n <span className=\"text-xs text-muted-foreground\">No live observers</span>\n <div className=\"ml-auto flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => handleJoin('observer')}\n className=\"inline-flex items-center gap-1 text-xs px-2 py-1 rounded bg-primary text-primary-foreground hover:bg-primary/90 transition-colors\"\n title=\"Join as a read-only observer (Phase 1)\"\n >\n <LogIn className=\"w-3 h-3\" />\n observer\n </button>\n <button\n type=\"button\"\n onClick={() => handleJoin('annotator')}\n className=\"inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-300 hover:bg-amber-500/20 transition-colors\"\n title=\"Join as an annotator — leave inline notes on tool calls (Phase 2)\"\n >\n <MessageSquareWarning className=\"w-3 h-3\" />\n annotator\n </button>\n <button\n type=\"button\"\n onClick={() => handleJoin('controller')}\n className=\"inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-rose-500/40 bg-rose-500/10 text-rose-700 dark:text-rose-300 hover:bg-rose-500/20 transition-colors\"\n title=\"Join as a controller — can pause the agent loop (Phase 3)\"\n >\n <Pause className=\"w-3 h-3\" />\n controller\n </button>\n </div>\n </div>\n );\n }\n\n // Error state: surface server's reason and let user retry.\n if (error) {\n return (\n <div\n className={cn(\n 'flex items-center gap-2 px-3 py-2 rounded-md border border-destructive/50 bg-destructive/10',\n className,\n )}\n role=\"alert\"\n >\n <span className=\"text-xs text-destructive\">Collab: {error}</span>\n <button\n type=\"button\"\n onClick={() => {\n setError(null);\n setJoined(false);\n }}\n className=\"ml-auto text-xs underline text-destructive\"\n >\n dismiss\n </button>\n </div>\n );\n }\n\n // Live state: at least one participant. Show count, live dot, role chips.\n return (\n <div\n className={cn(\n 'flex items-center gap-2 px-3 py-2 rounded-md border border-emerald-500/40 bg-emerald-500/5',\n className,\n )}\n >\n <span className=\"relative flex h-2 w-2\" aria-label=\"Live\">\n <span className=\"absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75 animate-ping\" />\n <span className=\"relative inline-flex rounded-full h-2 w-2 bg-emerald-500\" />\n </span>\n <Users className=\"w-4 h-4 text-emerald-700 dark:text-emerald-400\" />\n <span className=\"text-xs font-medium text-emerald-700 dark:text-emerald-300\">\n {participants.length} {participants.length === 1 ? 'observer' : 'observers'}\n </span>\n {openAnnotationCount > 0 && (\n <span\n title={`${openAnnotationCount} open annotation(s) — annotators reviewing this session`}\n className=\"ml-2 inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-amber-500/15 text-amber-700 dark:text-amber-300 border border-amber-500/30\"\n >\n <MessageSquareWarning className=\"w-3 h-3\" />\n {openAnnotationCount} note{openAnnotationCount === 1 ? '' : 's'}\n </span>\n )}\n {paused && (\n <span\n title=\"Agent loop is paused — a controller is reviewing\"\n className=\"ml-2 inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-rose-500/15 text-rose-700 dark:text-rose-300 border border-rose-500/40\"\n >\n <Pause className=\"w-3 h-3\" />\n paused\n </span>\n )}\n <div className=\"flex items-center gap-1 ml-2\">\n {participants.slice(0, 3).map((p) => (\n <span\n key={p.participantId}\n title={`Joined ${new Date(p.joinedAt).toLocaleTimeString()}`}\n className=\"inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/10 text-emerald-700 dark:text-emerald-300\"\n >\n <Eye className=\"w-3 h-3\" />\n {p.role}\n </span>\n ))}\n {participants.length > 3 && (\n <span className=\"text-[10px] text-muted-foreground\">+{participants.length - 3}</span>\n )}\n </div>\n {joined && joinedRole === 'controller' && (\n paused ? (\n <button\n type=\"button\"\n onClick={handleResume}\n className=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-rose-500/40 bg-rose-500/10 text-rose-700 dark:text-rose-300 hover:bg-rose-500/20 transition-colors\"\n title=\"Resume the agent loop\"\n >\n <Play className=\"w-3 h-3\" />\n Resume\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleRequestPause}\n className=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-300 hover:bg-amber-500/20 transition-colors\"\n title=\"Pause the agent before the next tool call\"\n >\n <Pause className=\"w-3 h-3\" />\n Pause agent\n </button>\n )\n )}\n {joined && joinedRole !== 'controller' && (\n <button\n type=\"button\"\n onClick={handleLeave}\n className=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-border hover:bg-muted transition-colors\"\n title=\"Leave the observer session\"\n >\n <LogOut className=\"w-3 h-3\" />\n Leave\n </button>\n )}\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { useUIStore } from '@/stores';\nimport { AlertTriangle, FileEdit, Globe, ShieldAlert, Terminal, Wrench } from 'lucide-react';\nimport { useEffect, useRef } from 'react';\nimport { DiffView, diffFromToolInput } from './DiffView';\nimport { Button } from './ui/button';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from './ui/dialog';\n\n/**\n * Pick the right hero icon for the tool being confirmed. Helps the user\n * see at a glance \"is this a file edit, a shell run, a network call?\".\n */\nfunction pickToolIcon(toolName: string) {\n if (/edit|write|create|patch/i.test(toolName)) return FileEdit;\n if (/bash|shell|exec|run|command/i.test(toolName)) return Terminal;\n if (/fetch|http|web|curl|request/i.test(toolName)) return Globe;\n return Wrench;\n}\n\n/**\n * Render the tool input intelligently. For edit/write we drop the JSON\n * dump and show a proper diff. For shell-like tools we surface the\n * command as a single mono line. Everything else falls back to JSON.\n */\nfunction SmartInputPreview({\n toolName,\n input,\n}: {\n toolName: string;\n input: unknown;\n}) {\n const diffArgs = diffFromToolInput(toolName, input);\n if (diffArgs) {\n return (\n <div className=\"rounded-lg overflow-hidden border\">\n <DiffView\n oldText={diffArgs.oldText}\n newText={diffArgs.newText}\n caption={diffArgs.caption}\n />\n </div>\n );\n }\n\n // Shell-like: pull out the command string so it shows as a real terminal\n // line instead of a JSON envelope.\n if (typeof input === 'object' && input !== null) {\n const obj = input as Record<string, unknown>;\n const cmd = (obj.command ?? obj.cmd ?? obj.script) as string | undefined;\n if (typeof cmd === 'string' && cmd.trim().length > 0) {\n return (\n <div className=\"rounded-lg border bg-background/40 overflow-hidden\">\n <div className=\"px-3 py-1.5 text-[10px] uppercase tracking-wider text-muted-foreground border-b bg-muted/40 flex items-center gap-1.5\">\n <Terminal className=\"h-3 w-3\" />\n <span>Command</span>\n </div>\n <pre className=\"px-3 py-2 text-xs font-mono whitespace-pre-wrap break-all max-h-40 overflow-auto\">\n ${cmd}\n </pre>\n </div>\n );\n }\n // url + method for fetch-like calls\n const url = obj.url as string | undefined;\n if (typeof url === 'string') {\n const method = (obj.method as string | undefined) ?? 'GET';\n return (\n <div className=\"rounded-lg border bg-background/40 px-3 py-2 text-xs font-mono\">\n <span className=\"text-muted-foreground\">{method.toUpperCase()}</span>{' '}\n <span className=\"break-all\">{url}</span>\n </div>\n );\n }\n }\n\n return (\n <div className=\"p-3 rounded-lg bg-muted/50 border text-xs font-mono\">\n <div className=\"text-muted-foreground mb-2\">Input:</div>\n <pre className=\"whitespace-pre-wrap break-all max-h-60 overflow-auto\">\n {JSON.stringify(input, null, 2)}\n </pre>\n </div>\n );\n}\n\nexport function ConfirmDialog() {\n const { showConfirmDialog, confirmInfo, hideConfirm } = useUIStore();\n const { sendConfirm } = useWebSocket();\n const dialogRef = useRef<HTMLDivElement>(null);\n\n const handleConfirm = (decision: 'yes' | 'no' | 'always' | 'deny') => {\n if (confirmInfo) {\n sendConfirm(confirmInfo.id, decision);\n }\n hideConfirm();\n };\n\n // Keyboard shortcuts: y/n/a/d/Esc — matches the CLI and TUI permission\n // prompts so muscle memory transfers directly across all surfaces.\n // biome-ignore lint/correctness/useExhaustiveDependencies: keyboard handler; handleConfirm stable\n useEffect(() => {\n if (!showConfirmDialog) return;\n const onKey = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement | null;\n const tag = target?.tagName?.toLowerCase();\n if (tag === 'input' || tag === 'textarea') return;\n if (e.key === 'y' || e.key === 'Y') {\n e.preventDefault();\n handleConfirm('yes');\n } else if (e.key === 'n' || e.key === 'N' || e.key === 'Escape') {\n e.preventDefault();\n handleConfirm('no');\n } else if (e.key === 'a' || e.key === 'A') {\n e.preventDefault();\n handleConfirm('always');\n } else if (e.key === 'd' || e.key === 'D') {\n e.preventDefault();\n handleConfirm('deny');\n }\n };\n window.addEventListener('keydown', onKey);\n // Focus the dialog container so keyboard shortcuts work immediately\n // without the user having to click into the dialog first.\n dialogRef.current?.focus();\n return () => window.removeEventListener('keydown', onKey);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [showConfirmDialog, confirmInfo?.id]);\n\n if (!confirmInfo) {\n return (\n <Dialog open={showConfirmDialog} onOpenChange={() => hideConfirm()}>\n <DialogContent />\n </Dialog>\n );\n }\n\n const Icon = pickToolIcon(confirmInfo.toolName);\n const isEdit = /edit|write/i.test(confirmInfo.toolName);\n\n return (\n <Dialog open={showConfirmDialog} onOpenChange={() => hideConfirm()}>\n <DialogContent className=\"sm:max-w-2xl border-yellow-500/50\" ref={dialogRef} tabIndex={-1}>\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <ShieldAlert className=\"h-5 w-5 text-yellow-500 animate-pulse\" />\n Approval required: {confirmInfo.toolName}\n </DialogTitle>\n <DialogDescription>\n The agent wants to {isEdit ? 'modify a file' : 'run this tool'}. Review the request\n below and decide whether to proceed.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"py-2 space-y-3\">\n <div className=\"flex items-center gap-3 p-3 rounded-lg bg-muted\">\n <Icon className=\"h-5 w-5 text-muted-foreground\" />\n <div className=\"min-w-0\">\n <div className=\"font-medium font-mono truncate\">{confirmInfo.toolName}</div>\n <div className=\"text-xs text-muted-foreground\">\n {isEdit ? 'File modification' : 'Tool execution'} — preview below\n </div>\n </div>\n </div>\n\n {confirmInfo.input !== undefined && (\n <SmartInputPreview toolName={confirmInfo.toolName} input={confirmInfo.input} />\n )}\n\n {confirmInfo.suggestedPattern && (\n <div className=\"flex items-start gap-2 p-3 rounded-lg bg-yellow-500/10 border border-yellow-500/20\">\n <AlertTriangle className=\"h-4 w-4 text-yellow-600 mt-0.5 shrink-0\" />\n <div className=\"text-sm min-w-0\">\n <div className=\"font-medium text-yellow-800 dark:text-yellow-200\">\n Trust pattern suggestion\n </div>\n <div className=\"font-mono text-xs mt-1 break-all\">\n {confirmInfo.suggestedPattern}\n </div>\n <div className=\"text-xs text-muted-foreground mt-1\">\n Picking <span className=\"font-medium\">Always</span> will whitelist matching calls\n for this project.\n </div>\n </div>\n </div>\n )}\n </div>\n\n <DialogFooter className=\"gap-2 sm:gap-2 flex-wrap\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleConfirm('deny')}\n title=\"Reject this and all future calls matching the pattern (d)\"\n >\n Deny always <kbd className=\"ml-1 text-[10px] border rounded px-1 bg-background\">d</kbd>\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleConfirm('no')}\n title=\"Reject this single call (Esc / n)\"\n >\n No <kbd className=\"ml-1 text-[10px] border rounded px-1 bg-background\">n</kbd>\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleConfirm('always')}\n title=\"Approve and remember the pattern for the project (a)\"\n >\n Always <kbd className=\"ml-1 text-[10px] border rounded px-1 bg-background\">a</kbd>\n </Button>\n <Button\n size=\"sm\"\n onClick={() => handleConfirm('yes')}\n title=\"Approve this single call (y)\"\n >\n Yes <kbd className=\"ml-1 text-[10px] border rounded px-1 bg-background/80\">y</kbd>\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","import { cn } from '@/lib/utils';\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\nimport { X } from 'lucide-react';\nimport * as React from 'react';\n\nconst Dialog = DialogPrimitive.Root;\nconst DialogTrigger = DialogPrimitive.Trigger;\nconst DialogPortal = DialogPrimitive.Portal;\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',\n className,\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)} {...props} />\n);\nDialogHeader.displayName = 'DialogHeader';\n\nconst DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}\n {...props}\n />\n);\nDialogFooter.displayName = 'DialogFooter';\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn('text-lg font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogClose,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n};\n","import { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore } from '@/stores';\nimport { Loader2, RotateCcw, WifiOff, X } from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\n/**\n * Prominent connection-lost banner. The ConnectionChip in the topbar is\n * easy to miss when the user is heads-down on the chat; this banner\n * stretches across the top, blocks the visual flow, and offers a \"retry\n * now\" button. Auto-hides as soon as the socket comes back open.\n *\n * Dismissable for the current outage (X button) — once dismissed, only\n * comes back if the socket recovers and then drops again. The chip in\n * the topbar still reflects the live state so the user isn't fully blind\n * after dismissing.\n */\nexport function ConnectionBanner() {\n const wsStatus = useConfigStore((s) => s.wsStatus);\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const [dismissed, setDismissed] = useState(false);\n const [now, setNow] = useState(Date.now());\n\n // Live retry countdown while reconnecting.\n useEffect(() => {\n if (wsStatus.state !== 'reconnecting') return;\n const id = setInterval(() => setNow(Date.now()), 500);\n return () => clearInterval(id);\n }, [wsStatus.state]);\n\n // Reset the dismissal flag every time the socket recovers — so the *next*\n // disconnection re-shows the banner. Without this the user would have to\n // refresh after dismissing to ever see the banner again.\n useEffect(() => {\n if (wsStatus.state === 'open') setDismissed(false);\n }, [wsStatus.state]);\n\n if (wsStatus.state === 'open' || wsStatus.state === 'connecting') return null;\n if (dismissed) return null;\n\n const retry = () => getWSClient(wsUrl).retryNow();\n const isReconnecting = wsStatus.state === 'reconnecting';\n const errorText =\n wsStatus.state === 'closed'\n ? wsStatus.error\n : wsStatus.state === 'reconnecting'\n ? wsStatus.lastError\n : undefined;\n const remaining = isReconnecting\n ? Math.max(0, Math.ceil((wsStatus.nextRetryAt - now) / 1000))\n : 0;\n\n return (\n <div\n className={cn(\n 'flex items-center gap-3 px-4 py-2 border-b text-sm',\n isReconnecting\n ? 'bg-orange-500/10 text-orange-700 dark:text-orange-300 border-orange-500/30'\n : 'bg-red-500/10 text-red-700 dark:text-red-300 border-red-500/30',\n )}\n >\n {isReconnecting ? (\n <Loader2 className=\"h-4 w-4 animate-spin shrink-0\" />\n ) : (\n <WifiOff className=\"h-4 w-4 shrink-0\" />\n )}\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-medium\">\n {isReconnecting\n ? `Reconnecting to backend (attempt ${wsStatus.attempt}) — retrying in ${remaining}s`\n : 'Disconnected from backend'}\n </div>\n {errorText && <div className=\"text-xs opacity-80 truncate\">{errorText}</div>}\n </div>\n <button\n type=\"button\"\n onClick={retry}\n className={cn(\n 'inline-flex items-center gap-1 px-2.5 py-1 rounded-md border text-xs font-medium',\n 'hover:bg-background/30 transition-colors shrink-0',\n isReconnecting ? 'border-orange-500/40' : 'border-red-500/40',\n )}\n title=\"Retry connection now\"\n >\n <RotateCcw className=\"h-3 w-3\" />\n Retry now\n </button>\n <button\n type=\"button\"\n onClick={() => setDismissed(true)}\n className=\"text-current/60 hover:text-current shrink-0\"\n title=\"Dismiss (chip in topbar still shows status)\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n );\n}\n","import { AlertTriangle, RefreshCw } from 'lucide-react';\nimport { Component, type ErrorInfo, type ReactNode } from 'react';\nimport { Button } from './ui/button';\n\ninterface Props {\n children: ReactNode;\n /** Optional callback when an error is caught — useful for telemetry. */\n onError?: (error: Error, info: ErrorInfo) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * Top-level error boundary for the entire app. Catches rendering errors in\n * any descendent component and shows a fallback UI instead of a white screen.\n * A single crash in a leaf component (e.g. a malformed markdown render) must\n * not take down the entire chat session.\n */\nexport class ErrorBoundary extends Component<Props, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n console.error('[ErrorBoundary]', error, info.componentStack);\n this.props.onError?.(error, info);\n }\n\n private handleReset = () => {\n this.setState({ error: null });\n };\n\n render() {\n if (this.state.error) {\n return (\n <div className=\"flex items-center justify-center h-screen bg-background\">\n <div className=\"flex flex-col items-center gap-4 p-8 max-w-md text-center\">\n <AlertTriangle className=\"h-12 w-12 text-destructive\" />\n <h1 className=\"text-lg font-semibold\">Something went wrong</h1>\n <p className=\"text-sm text-muted-foreground\">\n A rendering error occurred. Your session is still active on the server — reloading\n will pick up where you left off.\n </p>\n <pre className=\"text-xs font-mono text-muted-foreground bg-muted/50 rounded p-3 max-h-32 overflow-auto w-full text-left\">\n {this.state.error.message}\n </pre>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" variant=\"outline\" onClick={() => window.location.reload()}>\n <RefreshCw className=\"h-4 w-4 mr-1\" />\n Reload page\n </Button>\n <Button size=\"sm\" onClick={this.handleReset}>\n Try again\n </Button>\n </div>\n </div>\n </div>\n );\n }\n return this.props.children;\n }\n}\n","import { cn } from '@/lib/utils';\nimport { type SubagentView, useFleetStore } from '@/stores';\nimport { Bot, ChevronDown, ChevronRight, Cpu, Wrench, Zap } from 'lucide-react';\nimport { useMemo, useState } from 'react';\n\n/** Status → LED color + label. Running pulses; terminal states are steady. */\nconst STATUS_META: Record<\n SubagentView['status'],\n { tone: string; led: string; label: string; pulse: boolean }\n> = {\n running: {\n tone: 'text-[hsl(var(--success))]',\n led: 'text-[hsl(var(--success))]',\n label: 'running',\n pulse: true,\n },\n completed: {\n tone: 'text-muted-foreground',\n led: 'text-[hsl(var(--success))]',\n label: 'done',\n pulse: false,\n },\n failed: {\n tone: 'text-destructive',\n led: 'text-destructive',\n label: 'failed',\n pulse: false,\n },\n timeout: {\n tone: 'text-[hsl(var(--warning))]',\n led: 'text-[hsl(var(--warning))]',\n label: 'timeout',\n pulse: false,\n },\n stopped: {\n tone: 'text-muted-foreground',\n led: 'text-muted-foreground',\n label: 'stopped',\n pulse: false,\n },\n};\n\nfunction fmtCost(v: number): string {\n if (v <= 0) return '$0';\n if (v >= 0.01) return `$${v.toFixed(3)}`;\n return `$${v.toFixed(5).replace(/0+$/, '').replace(/\\.$/, '')}`;\n}\n\nfunction AgentCard({ a }: { a: SubagentView }): React.ReactElement {\n const meta = STATUS_META[a.status];\n const active = a.status === 'running';\n const tool = a.currentTool ?? a.lastTool;\n return (\n <div\n className={cn(\n 'flex min-w-[15rem] max-w-[18rem] flex-col gap-1.5 rounded-lg border p-2.5 transition-colors',\n active ? 'border-primary/30 bg-primary/[0.04]' : 'border-border bg-card opacity-90',\n )}\n >\n {/* Identity row */}\n <div className=\"flex items-center gap-2 min-w-0\">\n <span className={cn('led shrink-0', meta.led, meta.pulse && 'led-pulse')} />\n <span className=\"truncate text-xs font-semibold text-foreground\" title={a.name}>\n {a.name}\n </span>\n <span className={cn('ml-auto shrink-0 text-[10px] uppercase tracking-wider', meta.tone)}>\n {meta.label}\n </span>\n </div>\n\n {/* Model */}\n {a.model && (\n <div className=\"flex items-center gap-1 text-[10px] text-muted-foreground min-w-0\">\n <Cpu className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate font-mono\" title={`${a.provider ?? ''}/${a.model}`}>\n {a.model}\n </span>\n </div>\n )}\n\n {/* Live counters */}\n <div className=\"tabular flex items-center gap-2 text-[11px] text-muted-foreground\">\n <span title=\"iteration\">L{a.iteration}</span>\n <span className=\"text-border\">·</span>\n <span title=\"tool calls\">{a.toolCalls} tools</span>\n <span className=\"text-border\">·</span>\n <span className=\"text-foreground/80\" title=\"cost so far\">\n {fmtCost(a.costUsd)}\n </span>\n {a.extensions > 0 && (\n <span\n className=\"ml-auto inline-flex items-center gap-0.5 rounded bg-primary/15 px-1 text-[10px] text-primary\"\n title={`Self-extended budget ${a.extensions}×`}\n >\n <Zap className=\"h-2.5 w-2.5\" />\n {a.extensions}\n </span>\n )}\n </div>\n\n {/* Current/last tool */}\n {tool && (\n <div\n className={cn(\n 'flex items-center gap-1 text-[10px] truncate',\n active ? 'text-primary' : 'text-muted-foreground',\n )}\n title={a.currentTool ? `running ${tool}` : `last ran ${tool}`}\n >\n <Wrench className={cn('h-3 w-3 shrink-0', active && 'animate-pulse')} />\n <span className=\"truncate font-mono\">{tool}</span>\n </div>\n )}\n\n {/* Context fill bar */}\n {a.maxContext > 0 && (\n <div className=\"flex items-center gap-1.5\" title={`Context ${a.ctxPct}%`}>\n <div className=\"h-1 flex-1 overflow-hidden rounded-full bg-muted\">\n <div\n className={cn(\n 'h-full rounded-full transition-all duration-500',\n a.ctxPct >= 85\n ? 'bg-destructive'\n : a.ctxPct >= 70\n ? 'bg-[hsl(var(--warning))]'\n : 'bg-primary',\n )}\n style={{ width: `${Math.max(2, a.ctxPct)}%` }}\n />\n </div>\n <span className=\"tabular text-[9px] text-muted-foreground\">{a.ctxPct}%</span>\n </div>\n )}\n\n {/* Failure reason */}\n {a.error && (\n <div\n className=\"truncate rounded bg-destructive/10 px-1.5 py-0.5 text-[10px] text-destructive\"\n title={a.error.message}\n >\n {a.error.kind}: {a.error.message}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * FleetPanel — live roster of subagents spawned during a multi-agent run.\n *\n * Driven entirely by the `subagent.event` WS stream (reduced in useFleetStore).\n * Renders nothing when the fleet is empty, so a solo session is unaffected.\n * Collapsible so a large fleet doesn't dominate the chat column.\n */\nexport function FleetPanel({ className }: { className?: string | undefined }): React.ReactElement | null {\n const agents = useFleetStore((s) => s.agents);\n const [collapsed, setCollapsed] = useState(false);\n\n // Stable order: running first, then by start time. Recompute only when the\n // map identity changes (the store always sets a fresh Map on update).\n const list = useMemo(() => {\n const arr = Array.from(agents.values());\n arr.sort((x, y) => {\n const xa = x.status === 'running' ? 0 : 1;\n const ya = y.status === 'running' ? 0 : 1;\n if (xa !== ya) return xa - ya;\n return x.startedAt - y.startedAt;\n });\n return arr;\n }, [agents]);\n\n if (list.length === 0) return null;\n const activeCount = list.filter((a) => a.status === 'running').length;\n\n return (\n <div className={cn('rounded-lg border border-border bg-card/50 backdrop-blur-sm', className)}>\n <button\n type=\"button\"\n onClick={() => setCollapsed((v) => !v)}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left\"\n >\n <Bot className=\"h-4 w-4 text-primary\" />\n <span className=\"text-xs font-semibold text-foreground\">Fleet</span>\n <span className=\"tabular text-[10px] text-muted-foreground\">\n {list.length} agent{list.length === 1 ? '' : 's'}\n {activeCount > 0 && (\n <span className=\"text-[hsl(var(--success))]\"> · {activeCount} active</span>\n )}\n </span>\n {activeCount > 0 && (\n <span className=\"led led-pulse text-[hsl(var(--success))]\" aria-hidden />\n )}\n {collapsed ? (\n <ChevronRight className=\"ml-auto h-4 w-4 text-muted-foreground\" />\n ) : (\n <ChevronDown className=\"ml-auto h-4 w-4 text-muted-foreground\" />\n )}\n </button>\n {!collapsed && (\n <div className=\"flex gap-2 overflow-x-auto px-3 pb-3 pt-0.5\">\n {list.map((a) => (\n <AgentCard key={a.id} a={a} />\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { getWSClient } from '@/lib/ws-client';\nimport { useConfigStore, useUIStore } from '@/stores';\nimport type { WSServerMessage } from '@/types';\nimport { ArrowRight, Cpu, Search } from 'lucide-react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\n\ninterface SavedProvider {\n id: string;\n apiKeys: Array<{ label: string; isActive: boolean }>;\n}\ninterface CatalogModel {\n id: string;\n name: string;\n contextWindow?: number | undefined;\n}\n\n/**\n * Ctrl/Cmd+M — flat searchable provider/model picker. Drops a 3-click\n * trip through Settings down to one shortcut. Pulls the list of *saved*\n * providers (the ones that actually have a registered key) and lazy-loads\n * each provider's models when the overlay opens. The active model is\n * highlighted; Enter switches via the existing model.switch WS handler\n * (which atomically swaps provider+model on the backend).\n */\nexport function QuickModelSwitcher() {\n const open = useUIStore((s) => s.modelSwitcherOpen);\n const setOpen = useUIStore((s) => s.setModelSwitcherOpen);\n const [query, setQuery] = useState('');\n const [selected, setSelected] = useState(0);\n const [saved, setSaved] = useState<SavedProvider[]>([]);\n const [modelsByProvider, setModelsByProvider] = useState<Record<string, CatalogModel[]>>({});\n const inputRef = useRef<HTMLInputElement>(null);\n\n const wsUrl = useConfigStore((s) => s.wsUrl);\n const currentProvider = useConfigStore((s) => s.provider);\n const currentModel = useConfigStore((s) => s.model);\n const paletteOpen = useUIStore((s) => s.paletteOpen);\n const ws = useWebSocket();\n\n // Ctrl/Cmd+M opens. Skip when the command palette is already open so\n // the two overlays don't fight for focus.\n // biome-ignore lint/correctness/useExhaustiveDependencies: setOpen is stable\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const mod = e.ctrlKey || e.metaKey;\n if (mod && e.key.toLowerCase() === 'm' && !e.shiftKey && !e.altKey) {\n if (paletteOpen) return;\n e.preventDefault();\n setOpen(!open);\n return;\n }\n if (e.key === 'Escape' && open) {\n e.preventDefault();\n setOpen(false);\n }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [open, paletteOpen]);\n\n // Wire up WS listeners + fetch on open. We listen unconditionally so a\n // late response (e.g. the user opened then closed before models arrived)\n // still populates state for the next open.\n useEffect(() => {\n const client = getWSClient(wsUrl);\n const offSaved = client.on('providers.saved', (msg: WSServerMessage) => {\n const p = msg.payload as { providers: SavedProvider[] };\n setSaved(p.providers ?? []);\n });\n const offModels = client.on('provider.models', (msg: WSServerMessage) => {\n const p = msg.payload as { provider: string; models: CatalogModel[] };\n setModelsByProvider((prev) => ({ ...prev, [p.provider]: p.models }));\n });\n return () => {\n offSaved();\n offModels();\n };\n }, [wsUrl]);\n\n useEffect(() => {\n if (!open) return;\n setQuery('');\n setSelected(0);\n ws.listSavedProviders();\n // Auto-focus the search input after the dialog paints. requestAnimationFrame\n // because the input ref isn't mounted on the same tick we flip `open`.\n requestAnimationFrame(() => inputRef.current?.focus());\n }, [open, ws]);\n\n // Lazy-load models per saved provider once we know what's saved.\n useEffect(() => {\n if (!open) return;\n for (const sp of saved) {\n if (!modelsByProvider[sp.id]) {\n ws.listProviderModels(sp.id);\n }\n }\n }, [open, saved, modelsByProvider, ws]);\n\n /** Flatten into a single list of {provider, model} candidates, then apply\n * the search filter. The active row floats to the top so the user can\n * see what they're currently on. */\n const candidates = useMemo(() => {\n const list: Array<{\n provider: string;\n model: string;\n modelName: string;\n contextWindow?: number | undefined;\n isCurrent: boolean;\n }> = [];\n for (const sp of saved) {\n const models = modelsByProvider[sp.id] ?? [];\n for (const m of models) {\n list.push({\n provider: sp.id,\n model: m.id,\n modelName: m.name || m.id,\n contextWindow: m.contextWindow,\n isCurrent: sp.id === currentProvider && m.id === currentModel,\n });\n }\n }\n const q = query.toLowerCase().trim();\n const filtered = q\n ? list.filter(\n (c) =>\n c.provider.toLowerCase().includes(q) ||\n c.model.toLowerCase().includes(q) ||\n c.modelName.toLowerCase().includes(q),\n )\n : list;\n return filtered.sort((a, b) => {\n if (a.isCurrent !== b.isCurrent) return a.isCurrent ? -1 : 1;\n return a.provider.localeCompare(b.provider) || a.model.localeCompare(b.model);\n });\n }, [saved, modelsByProvider, query, currentProvider, currentModel]);\n\n useEffect(() => {\n if (selected >= candidates.length) setSelected(0);\n }, [candidates.length, selected]);\n\n const commit = (idx: number) => {\n const pick = candidates[idx];\n if (!pick) return;\n ws.switchModel(pick.provider, pick.model);\n setOpen(false);\n };\n\n if (!open) return null;\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-start justify-center bg-background/60 backdrop-blur-sm pt-[15vh]\"\n onClick={(e) => {\n if (e.target === e.currentTarget) setOpen(false);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setOpen(false);\n }}\n >\n <div className=\"w-full max-w-xl rounded-xl border bg-popover shadow-2xl overflow-hidden\">\n <div className=\"flex items-center gap-2 border-b px-3 py-2\">\n <Search className=\"h-4 w-4 text-muted-foreground\" />\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n setSelected(0);\n }}\n onKeyDown={(e) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelected((i) => Math.min(candidates.length - 1, i + 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelected((i) => Math.max(0, i - 1));\n } else if (e.key === 'Enter') {\n e.preventDefault();\n commit(selected);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setOpen(false);\n }\n }}\n placeholder=\"Filter providers and models…\"\n className=\"flex-1 bg-transparent outline-none text-sm placeholder:text-muted-foreground\"\n />\n <span className=\"text-[10px] text-muted-foreground font-mono\">↑↓ · Enter · Esc</span>\n </div>\n <div className=\"max-h-[50vh] overflow-y-auto py-1\">\n {candidates.length === 0 ? (\n <div className=\"px-4 py-8 text-center text-sm text-muted-foreground\">\n {saved.length === 0\n ? 'No saved providers — register a key in Settings first.'\n : 'Loading models…'}\n </div>\n ) : (\n candidates.map((c, idx) => (\n <button\n type=\"button\"\n key={`${c.provider}:${c.model}`}\n onClick={() => commit(idx)}\n onMouseEnter={() => setSelected(idx)}\n className={cn(\n 'w-full flex items-center gap-3 px-3 py-2 text-left text-sm transition-colors',\n idx === selected ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40',\n c.isCurrent && 'font-medium',\n )}\n >\n <Cpu\n className={cn(\n 'h-4 w-4 shrink-0',\n c.isCurrent ? 'text-primary' : 'text-muted-foreground',\n )}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate\">\n <span className=\"text-muted-foreground\">{c.provider}</span>\n <span className=\"mx-1 text-muted-foreground/40\">·</span>\n <span>{c.modelName}</span>\n </div>\n {c.contextWindow && (\n <div className=\"text-[10px] text-muted-foreground font-mono\">\n {c.model} · ctx {c.contextWindow.toLocaleString()}\n </div>\n )}\n </div>\n {c.isCurrent ? (\n <span className=\"text-[10px] uppercase tracking-wide text-primary font-semibold\">\n active\n </span>\n ) : (\n <ArrowRight className=\"h-3.5 w-3.5 text-muted-foreground opacity-0 group-hover:opacity-100\" />\n )}\n </button>\n ))\n )}\n </div>\n </div>\n </div>\n );\n}\n","import { toast } from '@/components/Toaster';\nimport { useWebSocket } from '@/hooks/useWebSocket';\nimport { useConfigStore, useUIStore } from '@/stores';\nimport type { WSServerMessage } from '@/types';\nimport {\n Cpu,\n Globe,\n Monitor,\n Moon,\n Network,\n Palette,\n Sun,\n X,\n} from 'lucide-react';\nimport { useState, useEffect, useCallback } from 'react';\nimport { useTheme } from '../ThemeProvider';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { ScrollArea } from '../ui/scroll-area';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs';\nimport { PreferenceToggle } from './PreferenceToggle';\nimport {\n ProviderSection,\n type CatalogProvider,\n type SavedProvider,\n type ProviderTab,\n} from './ProviderSection';\nimport { ModelSection } from './ModelSection';\n\ninterface CatalogModel {\n id: string;\n name: string;\n releaseDate?: string | undefined;\n contextWindow?: number | undefined;\n inputCost?: number | undefined;\n outputCost?: number | undefined;\n capabilities: string[];\n}\n\nexport function SettingsPanel() {\n const { setCurrentView } = useUIStore();\n const { provider, model, setProvider, setModel, wsConnected } = useConfigStore();\n const { theme, setTheme } = useTheme();\n const ws = useWebSocket();\n const wsClient = ws.client;\n\n // Catalog data\n const [catalogProviders, setCatalogProviders] = useState<CatalogProvider[]>([]);\n const [catalogModels, setCatalogModels] = useState<Record<string, CatalogModel[]>>({});\n const [savedProviders, setSavedProviders] = useState<SavedProvider[]>([]);\n const [isLoadingCatalog, setIsLoadingCatalog] = useState(false);\n const [isLoadingModels, setIsLoadingModels] = useState(false);\n const [isLoadingSaved, setIsLoadingSaved] = useState(false);\n\n const [providerTab, setProviderTab] = useState<ProviderTab>('catalog');\n const [catalogQuery, setCatalogQuery] = useState('');\n\n const currentCatalogProvider = catalogProviders.find((p) => p.id === provider);\n\n // WS event subscriptions\n useEffect(() => {\n const handleProviderCatalog = (msg: WSServerMessage) => {\n if (msg.type === 'provider.catalog') {\n const payload = msg.payload as { providers: CatalogProvider[] };\n setCatalogProviders(payload.providers.sort((a, b) => a.id.localeCompare(b.id)));\n setIsLoadingCatalog(false);\n }\n };\n\n const handleProviderModels = (msg: WSServerMessage) => {\n if (msg.type === 'provider.models') {\n const payload = msg.payload as { provider: string; models: CatalogModel[] };\n setCatalogModels((prev) => ({ ...prev, [payload.provider]: payload.models }));\n setIsLoadingModels(false);\n }\n };\n\n const handleSavedProviders = (msg: WSServerMessage) => {\n if (msg.type === 'providers.saved') {\n const payload = msg.payload as { providers: SavedProvider[] };\n const next = payload.providers.sort((a, b) => a.id.localeCompare(b.id));\n setSavedProviders(next);\n setIsLoadingSaved(false);\n if (next.length > 0) setProviderTab('saved');\n }\n };\n\n if (!wsConnected || !wsClient) return;\n\n const off1 = wsClient.on('provider.catalog', handleProviderCatalog);\n const off2 = wsClient.on('provider.models', handleProviderModels);\n const off3 = wsClient.on('providers.saved', handleSavedProviders);\n\n setIsLoadingCatalog(true);\n setIsLoadingSaved(true);\n wsClient.listProviders();\n wsClient.listSavedProviders();\n\n return () => {\n off1?.();\n off2?.();\n off3?.();\n };\n }, [wsConnected, wsClient]);\n\n // Provider selection\n const handleProviderSelect = useCallback(\n (providerId: string) => {\n setProvider(providerId);\n if (!catalogModels[providerId]) {\n setIsLoadingModels(true);\n ws.listProviderModels?.(providerId);\n }\n },\n [catalogModels, setProvider, ws],\n );\n\n // Model selection\n const handleModelSelect = useCallback(\n (modelId: string) => {\n setModel(modelId);\n const currentProvider = useConfigStore.getState().provider;\n ws.switchModel?.(currentProvider, modelId);\n toast.success(`Switching to ${currentProvider} / ${modelId}…`);\n },\n [setModel, ws],\n );\n\n // Key management callbacks\n const handleAddKey = useCallback(\n (providerId: string, label: string, value: string) => {\n ws.addKey?.(providerId, label, value);\n },\n [ws],\n );\n\n const handleDeleteKey = useCallback(\n (providerId: string, label: string) => {\n ws.deleteKey?.(providerId, label);\n },\n [ws],\n );\n\n const handleSetActiveKey = useCallback(\n (providerId: string, label: string) => {\n ws.setActiveKey?.(providerId, label);\n },\n [ws],\n );\n\n const handleAddProvider = useCallback(\n (id: string, family: string, baseUrl?: string | undefined, apiKey?: string) => {\n ws.addProvider?.(id, family, baseUrl, apiKey);\n },\n [ws],\n );\n\n const handleRemoveProvider = useCallback(\n (providerId: string) => {\n ws.removeProvider?.(providerId);\n },\n [ws],\n );\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Header */}\n <header className=\"flex items-center justify-between px-4 py-3 border-b bg-card shrink-0\">\n <h1 className=\"text-lg font-semibold\">Settings</h1>\n <Button variant=\"ghost\" size=\"icon\" onClick={() => setCurrentView('chat')}>\n <X className=\"h-4 w-4\" />\n </Button>\n </header>\n\n {/* Content */}\n <ScrollArea className=\"flex-1\">\n <div className=\"p-6 max-w-2xl mx-auto\">\n <Tabs defaultValue=\"provider\">\n <TabsList className=\"w-full justify-start mb-6 grid grid-cols-4\">\n <TabsTrigger value=\"provider\" className=\"gap-2\">\n <Network className=\"h-4 w-4\" />\n Provider\n </TabsTrigger>\n <TabsTrigger value=\"model\" className=\"gap-2\">\n <Cpu className=\"h-4 w-4\" />\n Model\n </TabsTrigger>\n <TabsTrigger value=\"connection\" className=\"gap-2\">\n <Globe className=\"h-4 w-4\" />\n Connection\n </TabsTrigger>\n <TabsTrigger value=\"appearance\" className=\"gap-2\">\n <Palette className=\"h-4 w-4\" />\n Appearance\n </TabsTrigger>\n </TabsList>\n\n {/* Provider Tab */}\n <TabsContent value=\"provider\" className=\"space-y-4\">\n <ProviderSection\n activeProvider={provider}\n catalogProviders={catalogProviders}\n isLoadingCatalog={isLoadingCatalog}\n savedProviders={savedProviders}\n isLoadingSaved={isLoadingSaved}\n providerTab={providerTab}\n setProviderTab={setProviderTab}\n onSelectProvider={handleProviderSelect}\n onAddKey={handleAddKey}\n onDeleteKey={handleDeleteKey}\n onSetActiveKey={handleSetActiveKey}\n onAddProvider={handleAddProvider}\n onRemoveProvider={handleRemoveProvider}\n catalogQuery={catalogQuery}\n setCatalogQuery={setCatalogQuery}\n />\n </TabsContent>\n\n {/* Model Tab */}\n <TabsContent value=\"model\" className=\"space-y-4\">\n <ModelSection\n provider={provider}\n catalogModels={catalogModels}\n currentCatalogProvider={currentCatalogProvider}\n isLoadingModels={isLoadingModels}\n setIsLoadingModels={setIsLoadingModels}\n onModelSelect={handleModelSelect}\n refreshModels={(pid) => ws.listProviderModels?.(pid)}\n />\n </TabsContent>\n\n {/* Connection Tab */}\n <TabsContent value=\"connection\" className=\"space-y-4\">\n <div className=\"space-y-3\">\n <label\n htmlFor=\"websocket-url\"\n className=\"text-sm font-medium flex items-center gap-2\"\n >\n <Globe className=\"h-4 w-4 text-muted-foreground\" />\n WebSocket Server URL\n </label>\n <Input\n id=\"websocket-url\"\n value={useConfigStore.getState().wsUrl}\n onChange={(e) => useConfigStore.getState().setConfig({ wsUrl: e.target.value })}\n placeholder=\"ws://localhost:3457\"\n className=\"font-mono text-sm\"\n />\n <p className=\"text-xs text-muted-foreground\">\n URL of the WrongStack WebSocket server. The server runs alongside the CLI.\n </p>\n </div>\n\n <div className=\"p-4 rounded-lg border bg-muted/50\">\n <h4 className=\"text-sm font-medium mb-2\">Starting the WebSocket Server</h4>\n <p className=\"text-xs text-muted-foreground mb-3\">\n Standalone: run <code className=\"bg-muted px-1 py-0.5 rounded\">./dev.ps1</code>{' '}\n from the repo root, or set WS_HOST/WS_PORT before launching{' '}\n <code className=\"bg-muted px-1 py-0.5 rounded\">\n node packages/webui/dist/server/entry.js\n </code>\n . Or alongside the CLI:{' '}\n <code className=\"bg-muted px-1 py-0.5 rounded\">wstack --webui</code>.\n </p>\n </div>\n </TabsContent>\n\n {/* Appearance Tab */}\n <TabsContent value=\"appearance\" className=\"space-y-4\">\n <div>\n <h3 className=\"text-sm font-semibold mb-3\">Theme</h3>\n <div className=\"grid grid-cols-3 gap-2 max-w-md\">\n <Button\n variant={theme === 'light' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setTheme('light')}\n >\n <Sun className=\"h-4 w-4 mr-1\" />\n Light\n </Button>\n <Button\n variant={theme === 'dark' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setTheme('dark')}\n >\n <Moon className=\"h-4 w-4 mr-1\" />\n Dark\n </Button>\n <Button\n variant={theme === 'system' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setTheme('system')}\n >\n <Monitor className=\"h-4 w-4 mr-1\" />\n System\n </Button>\n </div>\n <p className=\"text-xs text-muted-foreground mt-2\">\n System follows your OS-level light/dark preference.\n </p>\n </div>\n\n <div className=\"pt-2 border-t\">\n <h3 className=\"text-sm font-semibold mb-3 mt-3\">Preferences</h3>\n <PreferenceToggle\n label=\"Compact density\"\n hint=\"Tighter spacing throughout the chat. Toggle anywhere with Ctrl+Shift+D.\"\n selector={(s) => s.compactMode}\n onChange={() => useUIStore.getState().toggleCompactMode()}\n />\n <PreferenceToggle\n label=\"Sound on completion\"\n hint=\"Play a soft chime when a run finishes — useful when working in another tab.\"\n selector={null}\n configKey=\"soundOnComplete\"\n />\n </div>\n </TabsContent>\n </Tabs>\n </div>\n </ScrollArea>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport * as React from 'react';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nInput.displayName = 'Input';\n\nexport { Input };\n","import { cn } from '@/lib/utils';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport * as React from 'react';\n\nconst Tabs = TabsPrimitive.Root;\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.List\n ref={ref}\n className={cn(\n 'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',\n className,\n )}\n {...props}\n />\n));\nTabsList.displayName = TabsPrimitive.List.displayName;\n\nconst TabsTrigger = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n 'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm',\n className,\n )}\n {...props}\n />\n));\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName;\n\nconst TabsContent = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n 'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className,\n )}\n {...props}\n />\n));\nTabsContent.displayName = TabsPrimitive.Content.displayName;\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent };\n","import { playCompletionChime } from '@/lib/chime';\nimport { cn } from '@/lib/utils';\nimport { useConfigStore, useUIStore } from '@/stores';\n\n/**\n * One row in the Preferences section. Renders a label / hint pair on the\n * left and a small switch on the right.\n */\nexport function PreferenceToggle({\n label,\n hint,\n selector,\n onChange,\n configKey,\n}: {\n label: string;\n hint?: string | undefined;\n selector: ((s: ReturnType<typeof useUIStore.getState>) => boolean) | null;\n onChange?: (() => void) | undefined;\n configKey?: 'soundOnComplete' | undefined;\n}) {\n const uiVal = useUIStore((s) => (selector ? selector(s) : false));\n const cfgVal = useConfigStore((s) => (configKey ? (s[configKey] as boolean) : false));\n const on = selector ? uiVal : cfgVal;\n const handleToggle = () => {\n if (selector) onChange?.();\n else if (configKey === 'soundOnComplete') {\n const next = !useConfigStore.getState().soundOnComplete;\n useConfigStore.getState().setSoundOnComplete(next);\n if (next) {\n playCompletionChime();\n }\n }\n };\n return (\n <div className=\"flex items-start justify-between gap-3 py-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm font-medium\">{label}</div>\n {hint && <div className=\"text-xs text-muted-foreground mt-0.5\">{hint}</div>}\n </div>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={on}\n onClick={handleToggle}\n className={cn(\n 'shrink-0 relative inline-flex h-5 w-9 rounded-full border transition-colors',\n on ? 'bg-primary border-primary' : 'bg-muted border-input hover:bg-muted/80',\n )}\n >\n <span\n className={cn(\n 'absolute top-0.5 left-0.5 h-3.5 w-3.5 rounded-full bg-background shadow transition-transform',\n on && 'translate-x-4',\n )}\n />\n </button>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\nimport {\n CheckCircle2,\n Eye,\n EyeOff,\n Globe,\n Key,\n Loader2,\n Plus,\n Trash2,\n} from 'lucide-react';\nimport { useState, useCallback } from 'react';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\n\n// ── Types (shared with index) ──\n\nexport interface CatalogProvider {\n id: string;\n name: string;\n family: string;\n apiBase?: string | undefined;\n envVars: string[];\n modelCount: number;\n hasApiKey: boolean;\n}\n\nexport interface SavedProvider {\n id: string;\n family?: string | undefined;\n baseUrl?: string | undefined;\n apiKeys: Array<{\n label: string;\n maskedKey: string;\n isActive: boolean;\n createdAt: string;\n }>;\n}\n\nexport type ProviderTab = 'catalog' | 'saved';\n\nexport const PROVIDER_FAMILIES = ['anthropic', 'openai', 'google', 'openai-compatible'] as const;\n\n// ── Props ──\n\nexport interface ProviderSectionProps {\n /** Currently selected provider id. */\n activeProvider: string;\n /** Catalog providers list. */\n catalogProviders: CatalogProvider[];\n /** Loading flag. */\n isLoadingCatalog: boolean;\n /** Saved providers list. */\n savedProviders: SavedProvider[];\n /** Loading flag. */\n isLoadingSaved: boolean;\n /** Which sub-tab is active. */\n providerTab: ProviderTab;\n setProviderTab: (v: ProviderTab) => void;\n /** Called when a catalog provider is selected. */\n onSelectProvider: (id: string) => void;\n /** Called to add an API key. */\n onAddKey: (providerId: string, label: string, value: string) => void;\n /** Called to delete an API key. */\n onDeleteKey: (providerId: string, label: string) => void;\n /** Called to set a key as active. */\n onSetActiveKey: (providerId: string, label: string) => void;\n /** Called to add a custom provider. */\n onAddProvider: (id: string, family: string, baseUrl?: string | undefined, apiKey?: string) => void;\n /** Called to remove a saved provider. */\n onRemoveProvider: (providerId: string) => void;\n /** Search filter text. */\n catalogQuery: string;\n setCatalogQuery: (v: string) => void;\n}\n\n// ── Component ──\n\nexport function ProviderSection({\n activeProvider,\n catalogProviders,\n isLoadingCatalog,\n savedProviders,\n isLoadingSaved,\n providerTab,\n setProviderTab,\n onSelectProvider,\n onAddKey,\n onDeleteKey,\n onSetActiveKey,\n onAddProvider,\n onRemoveProvider,\n catalogQuery,\n setCatalogQuery,\n}: ProviderSectionProps) {\n // Key management form state\n const [showAddKeyForm, setShowAddKeyForm] = useState<string | null>(null);\n const [newKeyLabel, setNewKeyLabel] = useState('');\n const [newKeyValue, setNewKeyValue] = useState('');\n const [showNewKeyValue, setShowNewKeyValue] = useState(false);\n\n // Add provider form state\n const [showAddProviderForm, setShowAddProviderForm] = useState(false);\n const [newProviderId, setNewProviderId] = useState('');\n const [newProviderFamily, setNewProviderFamily] = useState('openai-compatible');\n const [newProviderBaseUrl, setNewProviderBaseUrl] = useState('');\n const [newProviderApiKey, setNewProviderApiKey] = useState('');\n\n const handleAddKey = useCallback(\n (providerId: string) => {\n if (!newKeyLabel.trim() || !newKeyValue.trim()) return;\n onAddKey(providerId, newKeyLabel.trim(), newKeyValue.trim());\n setNewKeyLabel('');\n setNewKeyValue('');\n setShowAddKeyForm(null);\n },\n [onAddKey, newKeyLabel, newKeyValue],\n );\n\n const handleAddProvider = useCallback(() => {\n if (!newProviderId.trim()) return;\n onAddProvider(newProviderId.trim(), newProviderFamily, newProviderBaseUrl || undefined, newProviderApiKey || undefined);\n setNewProviderId('');\n setNewProviderFamily('openai-compatible');\n setNewProviderBaseUrl('');\n setNewProviderApiKey('');\n setShowAddProviderForm(false);\n }, [onAddProvider, newProviderId, newProviderFamily, newProviderBaseUrl, newProviderApiKey]);\n\n // ── Filter + group catalog ──\n\n const filteredCatalog = catalogQuery.trim()\n ? catalogProviders.filter((p) => {\n const q = catalogQuery.trim().toLowerCase();\n return (\n p.id.toLowerCase().includes(q) ||\n p.name.toLowerCase().includes(q) ||\n p.family.toLowerCase().includes(q)\n );\n })\n : catalogProviders;\n\n const catalogByFamily = filteredCatalog.reduce(\n (acc, p) => {\n if (!acc[p.family]) acc[p.family] = [];\n acc[p.family]?.push(p);\n return acc;\n },\n {} as Record<string, CatalogProvider[]>,\n );\n\n // ── Render ──\n\n return (\n <div className=\"space-y-4\">\n {/* Provider source toggle */}\n <div className=\"flex gap-2 mb-4\">\n <Button\n variant={providerTab === 'catalog' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setProviderTab('catalog')}\n >\n <Globe className=\"h-4 w-4 mr-1\" />\n Catalog\n </Button>\n <Button\n variant={providerTab === 'saved' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setProviderTab('saved')}\n >\n <Key className=\"h-4 w-4 mr-1\" />\n Saved ({savedProviders.length})\n </Button>\n </div>\n\n {/* Catalog View */}\n {providerTab === 'catalog' && (\n <div className=\"space-y-4\">\n <Input\n placeholder={`Search ${catalogProviders.length} providers (name / id / family)…`}\n value={catalogQuery}\n onChange={(e) => setCatalogQuery(e.target.value)}\n className=\"text-sm\"\n />\n {isLoadingCatalog && catalogProviders.length === 0 ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n <span className=\"ml-2 text-muted-foreground\">Loading catalog...</span>\n </div>\n ) : filteredCatalog.length === 0 && catalogQuery ? (\n <div className=\"text-center py-8 text-muted-foreground text-sm\">\n No providers match \"<span className=\"font-mono\">{catalogQuery}</span>\".\n </div>\n ) : (\n <>\n {PROVIDER_FAMILIES.map((family) => {\n const providers = catalogByFamily[family];\n if (!providers?.length) return null;\n return (\n <div key={family} className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold text-muted-foreground uppercase tracking-wider\">\n {family}\n </h3>\n <div className=\"grid grid-cols-1 gap-2\">\n {providers.map((p) => (\n <button\n type=\"button\"\n key={p.id}\n onClick={() => onSelectProvider(p.id)}\n className={cn(\n 'flex flex-col items-start p-3 rounded-lg border text-left transition-all',\n activeProvider === p.id\n ? 'border-primary bg-primary/5 ring-2 ring-primary/20'\n : 'border-border hover:bg-muted',\n )}\n >\n <div className=\"flex w-full justify-between items-start\">\n <div>\n <span className=\"font-medium\">{p.name}</span>\n <span className=\"ml-2 text-xs text-muted-foreground\">\n ({p.id})\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n {p.hasApiKey && (\n <span className=\"text-xs bg-green-500/10 text-green-600 px-2 py-0.5 rounded\">\n <Key className=\"h-3 w-3 inline mr-1\" />\n Configured\n </span>\n )}\n {p.envVars[0] && (\n <span className=\"text-xs text-muted-foreground\">\n ENV: {p.envVars[0]}\n </span>\n )}\n {activeProvider === p.id && (\n <CheckCircle2 className=\"h-4 w-4 text-primary\" />\n )}\n </div>\n </div>\n <div className=\"text-xs text-muted-foreground mt-1\">\n {p.modelCount} models\n {p.apiBase && ` · ${p.apiBase}`}\n </div>\n </button>\n ))}\n </div>\n </div>\n );\n })}\n </>\n )}\n </div>\n )}\n\n {/* Saved Providers View */}\n {providerTab === 'saved' && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-between items-center\">\n <p className=\"text-sm text-muted-foreground\">\n Manage your API keys and provider configurations\n </p>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setShowAddProviderForm(!showAddProviderForm)}\n >\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Provider\n </Button>\n </div>\n\n {/* Add Provider Form */}\n {showAddProviderForm && (\n <div className=\"p-4 border rounded-lg space-y-3 bg-muted/50\">\n <h4 className=\"font-medium\">Add Custom Provider</h4>\n <Input\n placeholder=\"Provider ID (e.g. my-llm-server)\"\n value={newProviderId}\n onChange={(e) => setNewProviderId(e.target.value)}\n />\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={newProviderFamily}\n onChange={(e) => setNewProviderFamily(e.target.value)}\n >\n <option value=\"anthropic\">Anthropic</option>\n <option value=\"openai\">OpenAI</option>\n <option value=\"openai-compatible\">OpenAI Compatible</option>\n <option value=\"google\">Google</option>\n </select>\n <Input\n placeholder=\"Base URL (optional, e.g. http://localhost:11434/v1)\"\n value={newProviderBaseUrl}\n onChange={(e) => setNewProviderBaseUrl(e.target.value)}\n />\n <Input\n type=\"password\"\n placeholder=\"API Key (optional)\"\n value={newProviderApiKey}\n onChange={(e) => setNewProviderApiKey(e.target.value)}\n />\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={handleAddProvider} disabled={!newProviderId.trim()}>\n Add\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setShowAddProviderForm(false)}>\n Cancel\n </Button>\n </div>\n </div>\n )}\n\n {isLoadingSaved ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n </div>\n ) : savedProviders.length === 0 ? (\n <div className=\"text-center py-8 text-muted-foreground\">\n <Key className=\"h-8 w-8 mx-auto mb-2 opacity-50\" />\n <p>No saved providers yet</p>\n <p className=\"text-sm\">Add a provider to get started</p>\n </div>\n ) : (\n savedProviders.map((sp) => (\n <div key={sp.id} className=\"border rounded-lg p-4 space-y-3\">\n <div className=\"flex justify-between items-start\">\n <div>\n <h4 className=\"font-medium\">{sp.id}</h4>\n {sp.family && <span className=\"text-xs text-muted-foreground\">{sp.family}</span>}\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"icon\" variant=\"ghost\" onClick={() => onRemoveProvider(sp.id)}>\n <Trash2 className=\"h-4 w-4 text-destructive\" />\n </Button>\n </div>\n </div>\n\n {sp.baseUrl && (\n <div className=\"text-xs text-muted-foreground\">\n <Globe className=\"h-3 w-3 inline mr-1\" />\n {sp.baseUrl}\n </div>\n )}\n\n {/* API Keys */}\n <div className=\"space-y-2\">\n <div className=\"flex justify-between items-center\">\n <span className=\"text-sm font-medium\">API Keys</span>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setShowAddKeyForm(showAddKeyForm === sp.id ? null : sp.id)}\n >\n <Plus className=\"h-3 w-3 mr-1\" />\n Add Key\n </Button>\n </div>\n\n {sp.apiKeys.length === 0 && !showAddKeyForm && (\n <p className=\"text-xs text-muted-foreground\">No keys configured</p>\n )}\n\n {sp.apiKeys.map((key) => (\n <div key={key.label} className=\"flex items-center justify-between p-2 bg-muted/50 rounded\">\n <div>\n <span className=\"text-sm font-medium\">{key.label}</span>\n {key.isActive && (\n <span className=\"ml-2 text-xs bg-green-500/10 text-green-600 px-1.5 py-0.5 rounded\">\n Active\n </span>\n )}\n <div className=\"text-xs text-muted-foreground font-mono\">{key.maskedKey}</div>\n </div>\n <div className=\"flex gap-1\">\n {!key.isActive && (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onSetActiveKey(sp.id, key.label)}>\n Set Active\n </Button>\n )}\n <Button size=\"icon\" variant=\"ghost\" onClick={() => onDeleteKey(sp.id, key.label)}>\n <Trash2 className=\"h-3 w-3 text-destructive\" />\n </Button>\n </div>\n </div>\n ))}\n\n {/* Add Key Form */}\n {showAddKeyForm === sp.id && (\n <div className=\"p-3 border rounded space-y-2 bg-background\">\n <Input\n placeholder=\"Key label (e.g. default, production)\"\n value={newKeyLabel}\n onChange={(e) => setNewKeyLabel(e.target.value)}\n />\n <div className=\"flex gap-2\">\n <Input\n type={showNewKeyValue ? 'text' : 'password'}\n placeholder=\"API key\"\n value={newKeyValue}\n onChange={(e) => setNewKeyValue(e.target.value)}\n />\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={() => setShowNewKeyValue(!showNewKeyValue)}\n >\n {showNewKeyValue ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n </Button>\n </div>\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n onClick={() => handleAddKey(sp.id)}\n disabled={!newKeyLabel.trim() || !newKeyValue.trim()}\n >\n Save Key\n </Button>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => {\n setShowAddKeyForm(null);\n setNewKeyLabel('');\n setNewKeyValue('');\n }}\n >\n Cancel\n </Button>\n </div>\n </div>\n )}\n </div>\n </div>\n ))\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { useConfigStore } from '@/stores';\nimport { CheckCircle2, Cpu, Loader2, RefreshCw } from 'lucide-react';\nimport { Button } from '../ui/button';\n\ninterface CatalogModel {\n id: string;\n name: string;\n releaseDate?: string | undefined;\n contextWindow?: number | undefined;\n inputCost?: number | undefined;\n outputCost?: number | undefined;\n capabilities: string[];\n}\n\ninterface CatalogProvider {\n id: string;\n name: string;\n}\n\nexport interface ModelSectionProps {\n /** Current provider id. */\n provider: string;\n /** Provider → models cache. */\n catalogModels: Record<string, CatalogModel[]>;\n /** The current catalog provider object (for displaying name). */\n currentCatalogProvider: CatalogProvider | undefined;\n /** Loading flag. */\n isLoadingModels: boolean;\n setIsLoadingModels: (v: boolean) => void;\n /** Called when a model is selected. */\n onModelSelect: (modelId: string) => void;\n /** Refresh model list from backend. */\n refreshModels: (providerId: string) => void;\n}\n\nexport function ModelSection({\n provider,\n catalogModels,\n currentCatalogProvider,\n isLoadingModels,\n setIsLoadingModels,\n onModelSelect,\n refreshModels,\n}: ModelSectionProps) {\n const model = useConfigStore((s) => s.model);\n\n return (\n <div className=\"space-y-4\">\n {provider ? (\n <>\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm font-medium\">\n {currentCatalogProvider?.name || provider}\n </p>\n <p className=\"text-xs text-muted-foreground\">{provider}</p>\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => {\n setIsLoadingModels(true);\n refreshModels(provider);\n }}\n >\n <RefreshCw className={cn('h-4 w-4', isLoadingModels && 'animate-spin')} />\n </Button>\n </div>\n\n {isLoadingModels && !catalogModels[provider] ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n <span className=\"ml-2 text-muted-foreground\">Loading models...</span>\n </div>\n ) : (\n <div className=\"space-y-1\">\n {(catalogModels[provider] || []).map((m) => (\n <button\n type=\"button\"\n key={m.id}\n onClick={() => onModelSelect(m.id)}\n className={cn(\n 'w-full flex items-center justify-between p-3 rounded-lg border text-left transition-all',\n model === m.id\n ? 'border-primary bg-primary/5 ring-2 ring-primary/20'\n : 'border-border hover:bg-muted',\n )}\n >\n <div>\n <span className=\"font-medium\">{m.name || m.id}</span>\n <div className=\"flex gap-2 mt-1\">\n {m.capabilities.map((cap) => (\n <span key={cap} className=\"text-xs bg-muted px-1.5 py-0.5 rounded\">\n {cap}\n </span>\n ))}\n </div>\n </div>\n <div className=\"text-right text-xs text-muted-foreground\">\n {m.contextWindow && <div>{m.contextWindow / 1000}k context</div>}\n {m.inputCost && m.outputCost && (\n <div>\n ${m.inputCost}/${m.outputCost}\n </div>\n )}\n {model === m.id && (\n <CheckCircle2 className=\"h-4 w-4 text-primary mt-1\" />\n )}\n </div>\n </button>\n ))}\n\n {catalogModels[provider]?.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n No models found for this provider. The catalog might be empty or still\n loading.\n </p>\n )}\n </div>\n )}\n </>\n ) : (\n <div className=\"text-center py-8 text-muted-foreground\">\n <Cpu className=\"h-8 w-8 mx-auto mb-2 opacity-50\" />\n <p>Select a provider first</p>\n </div>\n )}\n </div>\n );\n}\n","import { useUIStore } from '@/stores';\nimport { Keyboard, X } from 'lucide-react';\nimport { useEffect } from 'react';\n\ninterface Shortcut {\n keys: string[];\n description: string;\n}\n\nconst SHORTCUTS: Array<{ section: string; items: Shortcut[] }> = [\n {\n section: 'Global',\n items: [\n { keys: ['Ctrl', 'K'], description: 'Open command palette' },\n { keys: ['?'], description: 'Show this shortcuts overlay' },\n { keys: ['Ctrl', '\\\\'], description: 'Toggle sidebar' },\n { keys: ['Ctrl', '/'], description: 'Focus the message input' },\n ],\n },\n {\n section: 'Chat input',\n items: [\n { keys: ['Enter'], description: 'Send message' },\n { keys: ['Shift', 'Enter'], description: 'Insert a newline' },\n { keys: ['↑'], description: 'Recall previous prompt (in empty input)' },\n { keys: ['↓'], description: 'Recall next prompt' },\n { keys: ['/'], description: 'Open slash command popup' },\n { keys: ['Tab'], description: 'Autocomplete highlighted command' },\n { keys: ['Esc'], description: 'Dismiss popup / clear input' },\n ],\n },\n {\n section: 'Chat',\n items: [\n { keys: ['Ctrl', 'F'], description: 'Search within current chat' },\n { keys: ['Ctrl', 'L'], description: 'Clear context (same as /clear)' },\n { keys: ['Ctrl', 'N'], description: 'Start a new session (same as /new)' },\n { keys: ['Ctrl', 'E'], description: 'Export chat as markdown' },\n { keys: ['Ctrl', 'M'], description: 'Quick model switcher overlay' },\n { keys: ['Ctrl', 'Shift', 'D'], description: 'Toggle compact UI density' },\n { keys: ['Esc'], description: 'Abort the current run (when running)' },\n ],\n },\n {\n section: 'Chat navigation (when not typing)',\n items: [\n { keys: ['j'], description: 'Focus next message (alias: ↓)' },\n { keys: ['k'], description: 'Focus previous message (alias: ↑)' },\n { keys: ['g'], description: 'Jump to first message' },\n { keys: ['Shift', 'G'], description: 'Jump to last message' },\n { keys: ['c'], description: 'Copy focused message text' },\n { keys: ['Esc'], description: 'Clear focused message' },\n ],\n },\n];\n\nexport function ShortcutsOverlay() {\n const open = useUIStore((s) => s.shortcutsOpen);\n const setOpen = useUIStore((s) => s.setShortcutsOpen);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n // \"?\" — but only when the user isn't typing in an input. Otherwise\n // typing a literal \"?\" into the chat would open this overlay.\n const target = e.target as HTMLElement | null;\n const tag = target?.tagName?.toLowerCase();\n const isTyping = tag === 'input' || tag === 'textarea' || target?.isContentEditable;\n if (!isTyping && e.key === '?' && !e.ctrlKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n setOpen(!useUIStore.getState().shortcutsOpen);\n return;\n }\n if (e.key === 'Escape' && useUIStore.getState().shortcutsOpen) {\n e.preventDefault();\n setOpen(false);\n }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [setOpen]);\n\n if (!open) return null;\n\n return (\n <div\n className=\"fixed inset-0 z-50 bg-background/60 backdrop-blur-sm flex items-center justify-center px-4\"\n onClick={() => setOpen(false)}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setOpen(false);\n }}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n className=\"w-full max-w-2xl rounded-xl border bg-popover shadow-2xl overflow-hidden flex flex-col max-h-[80vh]\"\n >\n <div className=\"flex items-center justify-between px-5 py-4 border-b\">\n <div className=\"flex items-center gap-2\">\n <Keyboard className=\"h-4 w-4 text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold\">Keyboard shortcuts</h2>\n </div>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className=\"text-muted-foreground hover:text-foreground p-1 rounded hover:bg-muted\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n <div className=\"overflow-y-auto px-5 py-4 space-y-6\">\n {SHORTCUTS.map((group) => (\n <div key={group.section}>\n <div className=\"text-[10px] uppercase tracking-wider text-muted-foreground mb-2\">\n {group.section}\n </div>\n <div className=\"grid grid-cols-1 gap-1.5\">\n {group.items.map((s) => (\n <div\n key={s.description}\n className=\"flex items-center justify-between gap-3 text-sm px-2 py-1.5 rounded hover:bg-muted/40\"\n >\n <span className=\"text-foreground/80\">{s.description}</span>\n <span className=\"flex items-center gap-1 shrink-0\">\n {s.keys.map((k, ki) => (\n <span key={k} className=\"flex items-center gap-1\">\n {ki > 0 && <span className=\"text-muted-foreground/40 text-xs\">+</span>}\n <kbd className=\"font-mono text-[10px] border rounded px-1.5 py-0.5 bg-background\">\n {k}\n </kbd>\n </span>\n ))}\n </span>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n <div className=\"border-t px-5 py-3 text-xs text-muted-foreground\">\n Press{' '}\n <kbd className=\"font-mono text-[10px] border rounded px-1 py-0.5 bg-background\">?</kbd>{' '}\n any time to reopen this list.\n </div>\n </div>\n </div>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { useConfigStore, useHistoryStore, useSessionStore, useUIStore } from '@/stores';\nimport {\n History,\n MessageSquare,\n PanelLeftClose,\n Settings as SettingsIcon,\n Zap,\n} from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { Button } from '../ui/button';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs';\nimport { ConfigSection } from './ConfigSection.js';\nimport { SessionActions } from './SessionActions.js';\nimport { SessionList } from './SessionList.js';\n\nexport function Sidebar() {\n const { toggleSidebar, currentView, setCurrentView } = useUIStore();\n const sidebarWidth = useUIStore((s) => s.sidebarWidth);\n const setSidebarWidth = useUIStore((s) => s.setSidebarWidth);\n const { wsConnected, wsUrl } = useConfigStore();\n const { entries: historyEntries, loading: historyLoading, error: historyError } = useHistoryStore();\n const { listSessions, deleteSession, resumeSession, client } = useWebSocket();\n const session = useSessionStore((s) => s.session);\n\n const [historyQuery, setHistoryQuery] = useState('');\n const activeSessionId = session?.id;\n\n useEffect(() => {\n if (wsConnected) client?.getTodos?.();\n }, [wsConnected, client]);\n\n useEffect(() => {\n void activeSessionId;\n if (currentView === 'history' && wsConnected) listSessions(50);\n }, [currentView, wsConnected, activeSessionId, listSessions]);\n\n const formatDuration = (start: number | null) => {\n if (!start) return '--';\n const seconds = Math.floor((Date.now() - start) / 1000);\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n return `${minutes}m`;\n };\n\n // Drag handle\n const startDrag = (e: React.MouseEvent) => {\n e.preventDefault();\n const startX = e.clientX;\n const startWidth = sidebarWidth;\n const onMove = (ev: MouseEvent) => { setSidebarWidth(startWidth + (ev.clientX - startX)); };\n const onUp = () => {\n window.removeEventListener('mousemove', onMove);\n window.removeEventListener('mouseup', onUp);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n };\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', onUp);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n };\n\n return (\n <aside style={{ width: `${sidebarWidth}px` }} className=\"relative border-r bg-card flex flex-col shrink-0\">\n {/* Drag handle */}\n <div\n onMouseDown={startDrag}\n onDoubleClick={() => setSidebarWidth(288)}\n className=\"group/handle absolute top-0 right-0 h-full w-2 cursor-col-resize z-10 flex items-center justify-end\"\n title=\"Drag to resize · double-click to reset\"\n >\n <div className=\"h-full w-px bg-border group-hover/handle:bg-primary/60 group-hover/handle:w-0.5 transition-all\" />\n <div className=\"absolute right-0 top-1/2 -translate-y-1/2 flex flex-col gap-0.5 opacity-0 group-hover/handle:opacity-100 transition-opacity pr-0.5\">\n <span className=\"h-1 w-1 rounded-full bg-primary/70\" />\n <span className=\"h-1 w-1 rounded-full bg-primary/70\" />\n <span className=\"h-1 w-1 rounded-full bg-primary/70\" />\n </div>\n </div>\n\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"relative w-7 h-7 rounded-md bg-primary flex items-center justify-center shadow-[0_0_0_1px_hsl(var(--primary)/0.4),0_2px_8px_-2px_hsl(var(--primary)/0.5)]\">\n <Zap className=\"h-4 w-4 text-primary-foreground\" strokeWidth={2.4} />\n </div>\n <div className=\"flex flex-col leading-none\">\n <span className=\"text-sm font-semibold tracking-tight\">WrongStack</span>\n <span className=\"flex items-center gap-1 text-[10px] text-muted-foreground mt-0.5\">\n <span className={cn('led', wsConnected ? 'text-[hsl(var(--success))] led-pulse' : 'text-[hsl(var(--warning))]')} />\n <span className=\"tabular font-medium uppercase tracking-wider\">{wsConnected ? 'online' : 'offline'}</span>\n </span>\n </div>\n </div>\n <Button variant=\"ghost\" size=\"icon\" onClick={toggleSidebar} title=\"Collapse sidebar (Ctrl+\\\\)\">\n <PanelLeftClose className=\"h-4 w-4\" />\n </Button>\n </div>\n\n <Tabs value={currentView === 'settings' ? 'chat' : currentView} onValueChange={(v) => setCurrentView(v as 'chat' | 'history')} className=\"flex-1 flex flex-col\">\n <TabsList className=\"w-full rounded-none bg-transparent p-2 h-auto grid grid-cols-2\">\n <TabsTrigger value=\"chat\" className=\"flex-col gap-1.5 py-2 data-[state=active]:bg-primary/10\">\n <MessageSquare className=\"h-4 w-4\" /><span className=\"text-xs\">Chat</span>\n </TabsTrigger>\n <TabsTrigger value=\"history\" className=\"flex-col gap-1.5 py-2 data-[state=active]:bg-primary/10\">\n <History className=\"h-4 w-4\" /><span className=\"text-xs\">History</span>\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"chat\" className=\"flex-1 flex flex-col m-0 overflow-hidden\">\n <ConfigSection formatDuration={formatDuration} />\n <SessionActions wsConnected={wsConnected} />\n <div className=\"flex-1\" />\n <div className=\"px-3 py-3 border-t\">\n <Button variant=\"ghost\" size=\"sm\" className=\"w-full justify-start\" onClick={() => setCurrentView('settings')}>\n <SettingsIcon className=\"h-4 w-4 mr-2\" />Settings\n </Button>\n </div>\n </TabsContent>\n\n <TabsContent value=\"history\" className=\"flex-1 m-0 flex flex-col overflow-hidden\">\n <SessionList\n historyQuery={historyQuery}\n setHistoryQuery={setHistoryQuery}\n historyEntries={historyEntries}\n historyLoading={historyLoading}\n historyError={historyError}\n wsConnected={wsConnected}\n listSessions={listSessions}\n resumeSession={resumeSession}\n deleteSession={deleteSession}\n />\n </TabsContent>\n </Tabs>\n </aside>\n );\n}\n","import { cn } from '@/lib/utils';\nimport { useChatStore, useConfigStore, useSessionStore, useUIStore } from '@/stores';\nimport {\n CheckCircle2,\n Circle,\n CircleDot,\n Database,\n ListTodo,\n Pin,\n Wifi,\n WifiOff,\n} from 'lucide-react';\nimport { Button } from '../ui/button';\n\ninterface ConfigSectionProps {\n formatDuration: (start: number | null) => string;\n}\n\nexport function ConfigSection({ formatDuration }: ConfigSectionProps) {\n const { wsConnected, wsUrl, provider, model } = useConfigStore();\n const { totalTokens, cost, session, todos } = useSessionStore();\n const { messages } = useChatStore();\n const pinnedIds = useUIStore((s) => s.pinnedIds);\n const unpinAll = useUIStore((s) => s.unpinAll);\n const setCurrentView = useUIStore((s) => s.setCurrentView);\n\n const pinnedRows = pinnedIds\n .map((id) => messages.find((m) => m.id === id))\n .filter((m): m is NonNullable<typeof m> => !!m && m.content.length > 0);\n\n return (\n <>\n {/* Connection status */}\n <div className=\"px-4 py-3 border-b\">\n <div className={cn('flex items-center gap-2 px-3 py-2 rounded-lg text-sm', wsConnected ? 'bg-green-500/10 text-green-600 dark:text-green-400' : 'bg-yellow-500/10 text-yellow-600 dark:text-yellow-400')}>\n {wsConnected ? <Wifi className=\"h-4 w-4\" /> : <WifiOff className=\"h-4 w-4\" />}\n <span className=\"font-medium\">{wsConnected ? 'Connected' : 'Disconnected'}</span>\n </div>\n <div className=\"text-xs text-muted-foreground mt-2 px-1 font-mono\">{wsUrl}</div>\n </div>\n\n {/* Active model */}\n <button type=\"button\" onClick={() => setCurrentView('settings')} className=\"px-4 py-3 border-b text-left hover:bg-muted/40 transition-colors\">\n <div className=\"text-[10px] uppercase tracking-wider text-muted-foreground mb-1\">Active model</div>\n <div className=\"font-mono text-xs truncate\">\n <span className=\"text-muted-foreground\">{provider || '—'}</span>\n <span className=\"text-muted-foreground/40 mx-1\">/</span>\n <span className=\"font-medium\">{model || '—'}</span>\n </div>\n </button>\n\n {/* Session Stats */}\n <div className=\"px-4 py-3 border-b space-y-3\">\n <h3 className=\"text-sm font-medium flex items-center gap-2\">\n <Database className=\"h-4 w-4 text-muted-foreground\" />\n Session\n </h3>\n <div className=\"grid grid-cols-2 gap-2 text-xs\">\n <div className=\"flex flex-col p-2 rounded-lg bg-muted/50\">\n <span className=\"text-muted-foreground\">Messages</span>\n <span className=\"text-lg font-semibold\">{messages.length}</span>\n </div>\n <div className=\"flex flex-col p-2 rounded-lg bg-muted/50\">\n <span className=\"text-muted-foreground\">Duration</span>\n <span className=\"text-lg font-semibold\">{formatDuration(session?.startedAt ?? null)}</span>\n </div>\n <div className=\"flex flex-col p-2 rounded-lg bg-muted/50\">\n <span className=\"text-muted-foreground\">Input</span>\n <span className=\"text-lg font-semibold\">{totalTokens.input.toLocaleString()}</span>\n </div>\n <div className=\"flex flex-col p-2 rounded-lg bg-muted/50\">\n <span className=\"text-muted-foreground\">Output</span>\n <span className=\"text-lg font-semibold\">{totalTokens.output.toLocaleString()}</span>\n </div>\n </div>\n {cost > 0 && (\n <div className=\"flex justify-between items-center p-2 rounded-lg bg-green-500/10\">\n <span className=\"text-sm text-muted-foreground\">Cost</span>\n <span className=\"text-lg font-semibold text-green-600 dark:text-green-400\">${cost.toFixed(4)}</span>\n </div>\n )}\n </div>\n\n {/* Live TODO list */}\n {todos.length > 0 && (() => {\n const done = todos.filter((t) => t.status === 'completed').length;\n const running = todos.filter((t) => t.status === 'in_progress').length;\n const pct = todos.length > 0 ? Math.round((done / todos.length) * 100) : 0;\n const allDone = done === todos.length;\n return (\n <div className=\"px-4 py-3 border-b space-y-2.5\">\n <h3 className=\"text-sm font-medium flex items-center justify-between\">\n <span className=\"flex items-center gap-2\"><ListTodo className=\"h-4 w-4 text-muted-foreground\" />Plan</span>\n <span className=\"tabular text-[10px] text-muted-foreground\">{done}/{todos.length}</span>\n </h3>\n <div className={cn('relative h-1.5 w-full overflow-hidden rounded-full bg-muted', running > 0 && 'bar-sweep')} title={`${pct}% complete`}>\n <div className={cn('h-full rounded-full transition-all duration-500', allDone ? 'bg-[hsl(var(--success))]' : 'bg-primary')} style={{ width: `${Math.max(pct, running > 0 ? 4 : 0)}%` }} />\n </div>\n <ul className=\"space-y-0.5 max-h-56 overflow-y-auto pr-1 -mx-1\">\n {todos.map((t) => {\n const Icon = t.status === 'completed' ? CheckCircle2 : t.status === 'in_progress' ? CircleDot : Circle;\n const active = t.status === 'in_progress';\n const tone = t.status === 'completed' ? 'text-[hsl(var(--success))] line-through opacity-60' : active ? 'text-foreground' : 'text-muted-foreground';\n return (\n <li key={t.id} className={cn('flex items-start gap-2 text-xs leading-snug rounded-md px-1.5 py-1 transition-colors', active && 'bg-primary/10 ring-1 ring-inset ring-primary/20', tone)}>\n <Icon className={cn('h-3.5 w-3.5 mt-0.5 shrink-0', active && 'text-primary animate-pulse')} />\n <span className=\"break-words\">{active && t.activeForm ? t.activeForm : t.content}</span>\n </li>\n );\n })}\n </ul>\n </div>\n );\n })()}\n\n {/* Pinned answers */}\n {pinnedRows.length > 0 && (\n <div className=\"px-4 py-3 border-b space-y-2\">\n <h3 className=\"text-sm font-medium flex items-center justify-between\">\n <span className=\"flex items-center gap-2\"><Pin className=\"h-4 w-4 text-amber-500\" />Pinned</span>\n <button type=\"button\" onClick={unpinAll} className=\"text-[10px] text-muted-foreground hover:text-destructive\">Clear</button>\n </h3>\n <ul className=\"space-y-1 max-h-48 overflow-y-auto pr-1\">\n {pinnedRows.map((m) => {\n const preview = m.content.replace(/\\s+/g, ' ').slice(0, 80);\n return (\n <li key={m.id}>\n <button\n type=\"button\"\n onClick={() => {\n const el = document.querySelector(`[data-message-id=\"${m.id}\"]`);\n if (!el) return;\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n el.classList.add('ring-2', 'ring-amber-500/60');\n setTimeout(() => { el.classList.remove('ring-2', 'ring-amber-500/60'); }, 1600);\n }}\n className=\"w-full text-left text-xs px-2 py-1.5 rounded bg-muted/40 hover:bg-muted/70 border border-amber-500/20 leading-snug\"\n title={m.content.slice(0, 400)}\n >\n {preview}{m.content.length > 80 ? '…' : ''}\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </>\n );\n}\n","import { useWebSocket } from '@/hooks/useWebSocket';\nimport { useChatStore } from '@/stores';\nimport { Database, RotateCcw, Trash2 } from 'lucide-react';\nimport { Button } from '../ui/button';\n\ninterface SessionActionsProps {\n wsConnected: boolean;\n}\n\nexport function SessionActions({ wsConnected }: SessionActionsProps) {\n const clearMessages = useChatStore((s) => s.clearMessages);\n const { client } = useWebSocket();\n\n return (\n <div className=\"px-4 py-3 border-b space-y-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full justify-start text-destructive hover:text-destructive\"\n onClick={() => { clearMessages(); client?.clearContext?.(); }}\n >\n <Trash2 className=\"h-4 w-4 mr-2\" />\n Clear context\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full justify-start\"\n onClick={() => client?.newSession?.()}\n disabled={!wsConnected}\n >\n <RotateCcw className=\"h-4 w-4 mr-2\" />\n New session\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full justify-start\"\n onClick={() => client?.compactContext?.()}\n disabled={!wsConnected}\n >\n <Database className=\"h-4 w-4 mr-2\" />\n Compact context\n </Button>\n </div>\n );\n}\n","import type { useWebSocket } from '@/hooks/useWebSocket';\nimport { cn } from '@/lib/utils';\nimport { type useHistoryStore, useUIStore } from '@/stores';\nimport {\n History,\n Loader2,\n RefreshCw,\n Search,\n Star,\n Trash2,\n X,\n} from 'lucide-react';\nimport { useState } from 'react';\nimport { ScrollArea } from '../ui/scroll-area';\n\ninterface SessionListProps {\n historyQuery: string;\n setHistoryQuery: (v: string) => void;\n historyEntries: ReturnType<typeof useHistoryStore.getState>['entries'];\n historyLoading: boolean;\n historyError: string | null;\n wsConnected: boolean;\n listSessions: ReturnType<typeof useWebSocket>['listSessions'];\n resumeSession: ReturnType<typeof useWebSocket>['resumeSession'];\n deleteSession: ReturnType<typeof useWebSocket>['deleteSession'];\n}\n\nconst formatRelative = (iso: string): string => {\n const ts = Date.parse(iso);\n if (Number.isNaN(ts)) return '';\n const diff = Date.now() - ts;\n if (diff < 60_000) return 'just now';\n if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m ago`;\n if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h ago`;\n const days = Math.floor(diff / 86_400_000);\n if (days < 7) return `${days}d ago`;\n return new Date(ts).toLocaleDateString();\n};\n\nexport function SessionList({\n historyQuery,\n setHistoryQuery,\n historyEntries,\n historyLoading,\n historyError,\n wsConnected,\n listSessions,\n resumeSession,\n deleteSession,\n}: SessionListProps) {\n const favoriteSessionIds = useUIStore((s) => s.favoriteSessionIds);\n const toggleFavoriteSession = useUIStore((s) => s.toggleFavoriteSession);\n const sessionNicknames = useUIStore((s) => s.sessionNicknames);\n const setSessionNickname = useUIStore((s) => s.setSessionNickname);\n const [renamingId, setRenamingId] = useState<string | null>(null);\n const [renameDraft, setRenameDraft] = useState('');\n\n const groupedHistory = (() => {\n const q = historyQuery.trim().toLowerCase();\n const filtered = q\n ? historyEntries.filter(\n (e) =>\n e.title.toLowerCase().includes(q) ||\n e.model.toLowerCase().includes(q) ||\n e.provider.toLowerCase().includes(q) ||\n e.id.toLowerCase().includes(q),\n )\n : historyEntries;\n const startOfDay = new Date();\n startOfDay.setHours(0, 0, 0, 0);\n const todayStart = startOfDay.getTime();\n const yesterdayStart = todayStart - 86_400_000;\n const weekStart = todayStart - 6 * 86_400_000;\n const buckets = { today: [] as typeof historyEntries, yesterday: [] as typeof historyEntries, week: [] as typeof historyEntries, older: [] as typeof historyEntries };\n for (const e of filtered) {\n const ts = Date.parse(e.startedAt);\n if (Number.isNaN(ts)) { buckets.older.push(e); continue; }\n if (ts >= todayStart) buckets.today.push(e);\n else if (ts >= yesterdayStart) buckets.yesterday.push(e);\n else if (ts >= weekStart) buckets.week.push(e);\n else buckets.older.push(e);\n }\n const favSet = new Set(favoriteSessionIds);\n const favorites = filtered.filter((e) => favSet.has(e.id));\n const out: Array<{ label: string; rows: typeof historyEntries; star?: boolean | undefined }> = [];\n if (favorites.length) out.push({ label: 'Favorites', rows: favorites, star: true });\n const dedupe = (arr: typeof historyEntries) => arr.filter((e) => !favSet.has(e.id));\n const today = dedupe(buckets.today);\n const yesterday = dedupe(buckets.yesterday);\n const week = dedupe(buckets.week);\n const older = dedupe(buckets.older);\n if (today.length) out.push({ label: 'Today', rows: today });\n if (yesterday.length) out.push({ label: 'Yesterday', rows: yesterday });\n if (week.length) out.push({ label: 'This week', rows: week });\n if (older.length) out.push({ label: 'Earlier', rows: older });\n return out;\n })();\n\n return (\n <>\n <div className=\"flex items-center justify-between px-4 py-2 border-b\">\n <span className=\"text-xs uppercase tracking-wider text-muted-foreground\">Recent sessions</span>\n <button\n type=\"button\"\n className=\"h-6 w-6 inline-flex items-center justify-center rounded-md hover:bg-muted\"\n onClick={() => listSessions(50)}\n disabled={!wsConnected}\n title=\"Refresh\"\n >\n {historyLoading ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" /> : <RefreshCw className=\"h-3.5 w-3.5\" />}\n </button>\n </div>\n {historyEntries.length > 3 && (\n <div className=\"px-3 py-2 border-b\">\n <div className=\"relative\">\n <Search className=\"absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground/60\" />\n <input\n type=\"text\"\n value={historyQuery}\n onChange={(e) => setHistoryQuery(e.target.value)}\n placeholder=\"Filter title, model, provider…\"\n className=\"w-full pl-7 pr-7 py-1 text-xs rounded-md bg-muted/40 border border-transparent focus:bg-background focus:border-input focus:outline-none focus:ring-1 focus:ring-ring placeholder:text-muted-foreground/50\"\n />\n {historyQuery && (\n <button type=\"button\" onClick={() => setHistoryQuery('')} className=\"absolute right-1 top-1/2 -translate-y-1/2 text-muted-foreground/60 hover:text-foreground p-0.5\" title=\"Clear filter\">\n <X className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n </div>\n )}\n {historyError && (\n <div className=\"px-4 py-2 text-xs text-destructive bg-destructive/5 border-b\">{historyError}</div>\n )}\n <ScrollArea className=\"flex-1\">\n {historyEntries.length === 0 && !historyLoading ? (\n <div className=\"text-center text-muted-foreground py-8 px-4\">\n <History className=\"h-8 w-8 mx-auto mb-3 opacity-20\" />\n <p className=\"text-sm font-medium\">No history yet</p>\n <p className=\"text-xs mt-1\">Your conversations will appear here</p>\n </div>\n ) : groupedHistory.length === 0 ? (\n <div className=\"text-center text-muted-foreground py-8 px-4\">\n <Search className=\"h-8 w-8 mx-auto mb-3 opacity-20\" />\n <p className=\"text-sm font-medium\">No matches</p>\n <p className=\"text-xs mt-1\">Try a different filter</p>\n </div>\n ) : (\n <div className=\"p-2 space-y-3\">\n {groupedHistory.map((group) => (\n <div key={group.label} className=\"space-y-1\">\n <div className={cn('sticky top-0 z-[1] px-1 pb-1 text-[10px] uppercase tracking-wider font-semibold bg-card/90 backdrop-blur-sm flex items-center gap-1', group.star ? 'text-amber-500' : 'text-muted-foreground/80')}>\n {group.star && <Star className=\"h-3 w-3 fill-current\" />}\n {group.label} <span className=\"text-muted-foreground/50 font-normal normal-case ml-1\">({group.rows.length})</span>\n </div>\n {group.rows.map((entry) => (\n <div key={entry.id} className={cn('group relative rounded-md border text-sm transition-colors', entry.isCurrent ? 'bg-primary/5 border-primary/40' : 'bg-card border-border/60 hover:bg-muted/40 hover:border-primary/40')}>\n <button\n type=\"button\"\n disabled={entry.isCurrent || renamingId === entry.id}\n onClick={() => resumeSession(entry.id)}\n onDoubleClick={(e) => { e.stopPropagation(); setRenamingId(entry.id); setRenameDraft(sessionNicknames[entry.id] ?? entry.title ?? ''); }}\n className=\"block w-full rounded-md px-3 py-2 pr-16 text-left disabled:cursor-default focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <div className=\"min-w-0 flex-1\">\n {renamingId === entry.id ? (\n <input\n value={renameDraft}\n onChange={(e) => setRenameDraft(e.target.value)}\n onClick={(e) => e.stopPropagation()}\n onBlur={() => { setSessionNickname(entry.id, renameDraft); setRenamingId(null); }}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); setSessionNickname(entry.id, renameDraft); setRenamingId(null); } else if (e.key === 'Escape') { e.preventDefault(); setRenamingId(null); } }}\n placeholder={entry.title || 'Nickname'}\n className=\"w-full text-sm bg-background border border-input rounded px-1.5 py-0.5 focus:outline-none focus:ring-1 focus:ring-ring\"\n />\n ) : (\n <div className=\"font-medium truncate text-foreground\" title={sessionNicknames[entry.id] ? `${sessionNicknames[entry.id]} — original: ${entry.title}` : `${entry.title}\\n\\nDouble-click to rename`}>\n {sessionNicknames[entry.id] || entry.title || '(empty)'}\n </div>\n )}\n <div className=\"text-[10px] text-muted-foreground font-mono truncate mt-0.5\">{entry.provider}/{entry.model}</div>\n <div className=\"flex items-center gap-2 text-[10px] text-muted-foreground/80 mt-0.5\">\n <span>{formatRelative(entry.startedAt)}</span>\n {entry.tokenTotal > 0 && <><span>·</span><span className=\"tabular-nums\">{entry.tokenTotal.toLocaleString()} tok</span></>}\n {entry.isCurrent && <><span>·</span><span className=\"text-primary font-medium\">active</span></>}\n </div>\n </div>\n </button>\n <div className=\"absolute right-2 top-2 flex items-center gap-1\">\n <button type=\"button\" onClick={() => toggleFavoriteSession(entry.id)} className={cn('transition-opacity hover:text-amber-500', favoriteSessionIds.includes(entry.id) ? 'opacity-100 text-amber-500' : 'opacity-0 group-hover:opacity-100 text-muted-foreground')} title={favoriteSessionIds.includes(entry.id) ? 'Unfavorite' : 'Mark as favorite'}>\n <Star className={cn('h-3.5 w-3.5', favoriteSessionIds.includes(entry.id) && 'fill-current')} />\n </button>\n {!entry.isCurrent && (\n <button type=\"button\" onClick={() => { if (window.confirm(`Delete session \"${entry.title}\"?`)) deleteSession(entry.id); }} className=\"opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-destructive\" title=\"Delete session\">\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n ))}\n </div>\n )}\n </ScrollArea>\n </>\n );\n}\n","import { getWSClient } from '@/lib/ws-client';\nimport { CheckCircle2, Circle, Clock, X } from 'lucide-react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\ninterface TodoItem {\n id: string;\n content: string;\n status: 'pending' | 'in_progress' | 'completed';\n activeForm?: string | undefined;\n}\n\n/**\n * Live agent todo list panel. Connects to the WebSocket on mount,\n * requests the current todo snapshot, and stays in sync via\n * `todos.updated` events broadcast by the server on every tool.executed.\n *\n * Self-contained — no store needed. Uses the singleton WS client\n * directly and manages its own React state.\n */\nexport function TodosPanel(): React.ReactElement {\n const [todos, setTodos] = useState<TodoItem[]>([]);\n const ws = getWSClient();\n const offRef = useRef<(() => void) | null>(null);\n\n useEffect(() => {\n // Request current snapshot\n ws.send({ type: 'todos.get' });\n\n // Listen for live updates\n offRef.current = ws.on('todos.updated', (msg: unknown) => {\n const payload = (msg as { payload?: { todos?: TodoItem[] | undefined } })?.payload;\n if (payload?.todos) setTodos(payload.todos);\n });\n\n return () => {\n offRef.current?.();\n };\n }, [ws]);\n\n const handleRemove = useCallback(\n (id: string) => {\n ws.removeTodo(id);\n },\n [ws],\n );\n\n const pending = todos.filter((t) => t.status === 'pending');\n const inProgress = todos.filter((t) => t.status === 'in_progress');\n const completed = todos.filter((t) => t.status === 'completed');\n\n return (\n <div className=\"flex flex-col h-full bg-background\">\n {/* Header */}\n <div className=\"px-4 py-3 border-b border-border flex items-center justify-between shrink-0\">\n <div className=\"flex items-center gap-2\">\n <h2 className=\"text-sm font-semibold text-foreground\">TODOS</h2>\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n {completed.length}/{todos.length}\n </span>\n </div>\n <div className=\"flex items-center gap-2 text-xs\">\n {inProgress.length > 0 && (\n <span className=\"flex items-center gap-1 text-yellow-600 dark:text-yellow-400\">\n <Clock className=\"w-3 h-3\" />\n {inProgress.length}\n </span>\n )}\n {pending.length > 0 && (\n <span className=\"flex items-center gap-1 text-muted-foreground\">\n <Circle className=\"w-3 h-3\" />\n {pending.length}\n </span>\n )}\n {completed.length > 0 && (\n <span className=\"flex items-center gap-1 text-emerald-600 dark:text-emerald-400\">\n <CheckCircle2 className=\"w-3 h-3\" />\n {completed.length}\n </span>\n )}\n </div>\n </div>\n\n {/* List */}\n <div className=\"flex-1 overflow-y-auto\">\n {todos.length === 0 ? (\n <p className=\"px-4 py-8 text-xs text-muted-foreground text-center\">\n No todos yet. The agent will create them as it plans work.\n </p>\n ) : (\n <div className=\"py-1\">\n {todos.map((t) => {\n const label = t.status === 'in_progress' && t.activeForm ? t.activeForm : t.content;\n const isInProgress = t.status === 'in_progress';\n const isCompleted = t.status === 'completed';\n\n return (\n <div\n key={t.id}\n className={`px-4 py-2 flex items-start gap-2.5 text-sm border-l-2 group ${\n isInProgress\n ? 'border-l-yellow-500 bg-yellow-50/40 dark:bg-yellow-950/20'\n : isCompleted\n ? 'border-l-emerald-500 bg-emerald-50/30 dark:bg-emerald-950/15'\n : 'border-l-transparent'\n }`}\n >\n <span className=\"mt-0.5 shrink-0\">\n {isCompleted ? (\n <CheckCircle2 className=\"w-3.5 h-3.5 text-emerald-500\" />\n ) : isInProgress ? (\n <Clock className=\"w-3.5 h-3.5 text-yellow-500 animate-spin\" />\n ) : (\n <Circle className=\"w-3.5 h-3.5 text-muted-foreground/50\" />\n )}\n </span>\n <span\n className={`leading-snug flex-1 ${\n isInProgress\n ? 'text-yellow-800 dark:text-yellow-200 font-medium'\n : isCompleted\n ? 'text-muted-foreground line-through'\n : 'text-foreground'\n }`}\n >\n {label}\n </span>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleRemove(t.id);\n }}\n className=\"shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-60 hover:opacity-100 hover:bg-muted transition-all\"\n title=\"Remove\"\n >\n <X className=\"w-3 h-3 text-muted-foreground\" />\n </button>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["React","create","persist","create","persist","create","persist","create","create","create","useEffect","create","expectDefined","client","useEffect","client","useEffect","ArrowDown","ArrowUp","Bot","Cpu","Zap","useCallback","useEffect","useRef","useState","useCallback","useEffect","useRef","useState","useEffect","useRef","jsx","jsxs","useRef","useEffect","Icon","useEffect","useRef","useState","jsx","jsxs","expectDefined","client","jsx","expectDefined","jsx","jsxs","expectDefined","client","useState","useRef","useCallback","useEffect","tone","RotateCcw","useEffect","useState","jsx","jsxs","useEffect","useRef","useState","jsx","jsxs","expectDefined","useEffect","useRef","useState","Fragment","jsx","jsxs","CheckCircle2","ChevronDown","ChevronRight","Download","Pencil","RotateCcw","XCircle","memo","useState","useMemo","jsx","jsxs","expectDefined","DiffView","i","j","ChevronDown","memo","useMemo","useState","Fragment","jsx","jsxs","ToolResult","Check","useState","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","useState","Check","useState","jsx","jsxs","expectDefined","useState","jsx","jsxs","jsx","jsxs","expectDefined","memo","MessageBubble","useState","client","ChevronDown","ChevronRight","XCircle","CheckCircle2","Download","Pencil","RotateCcw","Check","ChevronDown","useEffect","useRef","useState","jsx","jsxs","Search","X","useEffect","useMemo","useRef","useState","jsx","jsxs","Monitor","Moon","Sun","useEffect","useState","jsx","jsx","Sun","Moon","Monitor","Icon","CheckCircle2","ChevronDown","ChevronRight","Loader2","Terminal","XCircle","memo","useState","jsx","jsxs","expectDefined","memo","ToolGroup","useState","Terminal","ChevronDown","ChevronRight","Loader2","XCircle","CheckCircle2","ArchiveRestore","Clock","Search","Sparkles","Wrench","useEffect","useState","Fragment","jsx","jsxs","client","Icon","React","jsx","jsxs","Brain","jsx","jsxs","Fragment","jsx","jsxs","expectDefined","useRef","useState","useCallback","useEffect","formatDuration","Zap","Cpu","ArrowDown","ArrowUp","Bot","useEffect","useState","jsx","jsxs","client","p","AlertTriangle","Terminal","Wrench","useEffect","useRef","X","React","jsx","jsxs","jsx","jsxs","X","jsx","jsxs","Terminal","Wrench","useRef","useEffect","Icon","AlertTriangle","Loader2","RotateCcw","WifiOff","X","useEffect","useState","jsx","jsxs","AlertTriangle","jsx","jsxs","AlertTriangle","Bot","ChevronDown","ChevronRight","Cpu","Wrench","Zap","useMemo","useState","jsx","jsxs","ArrowRight","Cpu","Search","useEffect","useMemo","useRef","useState","jsx","jsxs","client","Cpu","Globe","Monitor","Moon","Sun","X","useState","useEffect","useCallback","React","jsx","React","jsx","jsx","jsxs","CheckCircle2","Eye","Globe","Loader2","Trash2","useState","useCallback","Fragment","jsx","jsxs","useState","useCallback","Globe","Loader2","CheckCircle2","Trash2","Eye","CheckCircle2","Cpu","Loader2","RefreshCw","Fragment","jsx","jsxs","RefreshCw","Loader2","CheckCircle2","Cpu","jsx","jsxs","useState","useEffect","useCallback","X","Cpu","Globe","Sun","Moon","Monitor","Keyboard","X","useEffect","jsx","jsxs","History","SettingsIcon","Zap","useEffect","useState","CheckCircle2","Database","Pin","Wifi","WifiOff","Fragment","jsx","jsxs","formatDuration","Icon","tone","Database","RotateCcw","Trash2","jsx","jsxs","client","Trash2","RotateCcw","Database","Loader2","RefreshCw","Search","Trash2","X","useState","Fragment","jsx","jsxs","useState","Loader2","RefreshCw","Search","X","Trash2","jsx","jsxs","client","useState","useEffect","formatDuration","Zap","History","SettingsIcon","CheckCircle2","Circle","Clock","X","useCallback","useEffect","useRef","useState","jsx","jsxs","Fragment","jsx","jsxs","expectDefined","useEffect","jsx","expectDefined","React"]}
|