v2.0.0: BooCoder frontend — chat pane + diff pane + session picker

Integrates BooCoder as a 'coder' workspace pane within the existing
BooChat SPA at code.indifferentketchup.com. Renamed the placeholder
'agent' pane kind to 'coder' across all types, menus, hooks, and
mobile switcher (Icon: Code instead of Bot).

CoderPane.tsx: split layout with chat area (messages via WS to
boocoder:9502, input bar posting to /api/coder/sessions/:id/messages)
and diff panel (pending changes with Approve/Reject per change plus
Approve All/Reject All). Reuses MarkdownRenderer for message content.

Proxy: Vite dev config adds /api/coder → boocoder:9502 (ordered above
/api per CLAUDE.md proxy-ordering rule). Production: Fastify route in
apps/server/src/index.ts proxies /api/coder/* to http://boocoder:3000
via fetch() pass-through. WS connects directly to :9502 (same
Tailscale network, no proxy needed for WebSocket upgrade).

WorkspacePaneKind mirror updated in both apps/web and apps/server
types. useWorkspacePanes gains coderPane() factory (replaces the old
agent toast stub). Workspace.tsx switch renders CoderPane for
pane.kind === 'coder'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-25 03:24:49 +00:00
parent 78455b7efc
commit 457c59fb06
11 changed files with 512 additions and 30 deletions

View File

@@ -1,5 +1,5 @@
import { useState } from 'react';
import { Bot, History, MessageSquare, Plus, Terminal, X } from 'lucide-react';
import { Code, History, MessageSquare, Plus, Terminal, X } from 'lucide-react';
import type { Chat, WorkspacePane } from '@/api/types';
import { StatusDot } from '@/components/StatusDot';
import {
@@ -26,7 +26,7 @@ interface Props {
onCloseOthers: (chatId: string) => void;
onCloseToRight: (chatId: string) => void;
onCloseAll: () => void;
onAddPane: (kind: 'chat' | 'terminal' | 'agent') => void;
onAddPane: (kind: 'chat' | 'terminal' | 'coder') => void;
onShowHistory: () => void;
onRename: (chatId: string, name: string) => Promise<void>;
onRemovePane?: () => void;
@@ -188,8 +188,8 @@ export function ChatTabBar({
<DropdownMenuItem onSelect={() => onAddPane('terminal')}>
<Terminal size={14} /> New terminal
</DropdownMenuItem>
<DropdownMenuItem onSelect={() => onAddPane('agent')}>
<Bot size={14} /> New agent
<DropdownMenuItem onSelect={() => onAddPane('coder')}>
<Code size={14} /> New coder
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>