feat: BooCode 2.0 UI — Ember theme, brand banner, coder tabs, model-attribution chips

- Ember theme (Obsidian charcoal + #ff7a18 orange), now DEFAULT_THEME_ID; server theme_id whitelist gains 'ember'
- Brand banner: transparent Westie mascot + >_BooCode wordmark, big/edge-to-edge (flood-filled to transparency + cropped)
- Coder panes are multi-tab: + opens a BooCode tab, split opens a pane (shared ChatTabBar via tabKind + createCoderTab; closeOtherTabs/tab-numbering extended to coder)
- Model-attribution: new messages.model column stamped at finalizeCompletion (BooChat/native coder) + dispatcher assistant-row creation (external coder); surfaced via view + wire types + live frame; rendered as a subtle shortened-name chip (shortenModelName)
- Composer Web toggle moved into a boxed focus-ringed input; glowing accent dot on tool rows
- Claude SDK follow-ups (1M context, follow-up-message fix, collapsed thinking/tool chips) + CLAUDE_SDK_BACKEND=1

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 22:30:47 +00:00
parent 7098014261
commit 3a646fd6df
34 changed files with 482 additions and 163 deletions

View File

@@ -53,6 +53,9 @@ interface MessageRow {
role: string;
content: string | null;
status: string | null;
model: string | null;
ctx_used: number | null;
ctx_max: number | null;
tool_calls: Array<{ id: string; name: string; args?: Record<string, unknown> }> | null;
tool_results: {
tool_call_id: string;
@@ -88,6 +91,9 @@ function mapCoderMessageRow(row: MessageRow) {
role: row.role as 'user' | 'assistant' | 'system',
content: row.content ?? '',
status: (row.status ?? 'complete') as 'streaming' | 'complete' | 'failed',
...(row.model ? { model: row.model } : {}),
...(row.ctx_used != null ? { ctx_used: row.ctx_used } : {}),
...(row.ctx_max != null ? { ctx_max: row.ctx_max } : {}),
...(reasoningText ? { reasoning_text: reasoningText } : {}),
...(tool_calls?.length ? { tool_calls } : {}),
};
@@ -126,13 +132,13 @@ export function registerMessageRoutes(
const rows = chatId
? await sql<MessageRow[]>`
SELECT id, role, content, status, tool_calls, tool_results, reasoning_parts
SELECT id, role, content, status, model, ctx_used, ctx_max, tool_calls, tool_results, reasoning_parts
FROM messages_with_parts
WHERE session_id = ${sessionId} AND chat_id = ${chatId}
ORDER BY created_at ASC, id ASC
`
: await sql<MessageRow[]>`
SELECT id, role, content, status, tool_calls, tool_results, reasoning_parts
SELECT id, role, content, status, model, ctx_used, ctx_max, tool_calls, tool_results, reasoning_parts
FROM messages_with_parts
WHERE session_id = ${sessionId}
ORDER BY created_at ASC, id ASC