diff --git a/docs/superpowers/plans/2026-04-03-chatpanel-unification.md b/docs/superpowers/plans/2026-04-03-chatpanel-unification.md new file mode 100644 index 0000000..cac0f63 --- /dev/null +++ b/docs/superpowers/plans/2026-04-03-chatpanel-unification.md @@ -0,0 +1,2141 @@ +# ChatPanel Unification Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Replace four divergent chat surfaces with a single `ChatPanel` component so every fix and feature applies everywhere automatically. + +**Architecture:** Extract `ChatInputBar.vue` (input + note picker + PTT) and `ChatStreamingBubble.vue` (streaming state display), then build `ChatPanel.vue` with `variant="full"` and `variant="widget"`, and migrate each view to use it. ChatPanel reads from `useChatStore` directly — no prop-drilling of messages or streaming state. + +**Tech Stack:** Vue 3 Composition API, TypeScript, Pinia (useChatStore), existing composables (useStreamingTts, useVoiceRecorder, useVoiceAudio, useListenMode) + +**Important context:** +- `ChatPanel.vue` already exists but is orphaned (zero usages). Overwrite it completely. +- `InlineAssistPanel.vue` and `HistoryPanel.vue` are also orphaned — ignore them. +- `chatStore.sendMessage(content, contextNoteId?, includeNoteIds?, think?, contextNoteTitle?, excludeNoteIds?, ragProjectId?, workspaceProjectId?)` — always pass `think: true` +- The store adds an optimistic user message immediately in `sendMessage`, so no manual optimistic push needed. +- TypeScript check command: `cd frontend && npm run typecheck` (or `make typecheck` from repo root) + +--- + +## File Map + +| File | Action | Purpose | +|---|---|---| +| `frontend/src/components/ChatInputBar.vue` | **Create** | Unified input bar: textarea, note picker, PTT, send/abort | +| `frontend/src/components/ChatStreamingBubble.vue` | **Create** | Streaming state: tool calls, think block, content, typing indicator | +| `frontend/src/components/ChatPanel.vue` | **Overwrite** | Full+widget chat panel, owns TTS/listen/scroll | +| `frontend/src/views/ChatView.vue` | **Modify** | Replace chat-main section with `` | +| `frontend/src/views/BriefingView.vue` | **Modify** | Replace briefing-center chat with `` | +| `frontend/src/views/WorkspaceView.vue` | **Modify** | Replace inline chat with `` | +| `frontend/src/views/HomeView.vue` | **Modify** | Replace DashboardChatInput + response section with `` | +| `frontend/src/components/DashboardChatInput.vue` | **Delete** | Replaced by ChatPanel widget | + +--- + +### Task 1: Create `ChatInputBar.vue` + +**Files:** +- Create: `frontend/src/components/ChatInputBar.vue` + +- [ ] **Step 1: Create the file** + +```vue + + + + + +``` + +- [ ] **Step 2: TypeScript check** + +```bash +cd /path/to/project/frontend && npm run typecheck 2>&1 | tail -20 +``` +Expected: no errors related to `ChatInputBar.vue`. + +- [ ] **Step 3: Commit** + +```bash +git add frontend/src/components/ChatInputBar.vue +git commit -m "feat: add ChatInputBar unified input bar component" +``` + +--- + +### Task 2: Create `ChatStreamingBubble.vue` + +**Files:** +- Create: `frontend/src/components/ChatStreamingBubble.vue` + +- [ ] **Step 1: Create the file** + +This extracts the identical streaming bubble HTML that currently lives in both `ChatView.vue` and `WorkspaceView.vue`. + +```vue + + + + + +``` + +- [ ] **Step 2: TypeScript check** + +```bash +cd /path/to/project/frontend && npm run typecheck 2>&1 | tail -20 +``` +Expected: no errors. + +- [ ] **Step 3: Commit** + +```bash +git add frontend/src/components/ChatStreamingBubble.vue +git commit -m "feat: add ChatStreamingBubble extracted streaming state component" +``` + +--- + +### Task 3: Rewrite `ChatPanel.vue` — full variant + +**Files:** +- Overwrite: `frontend/src/components/ChatPanel.vue` + +The existing `ChatPanel.vue` is orphaned (zero usages) — overwrite it entirely. + +**Context for this component:** +- `chatStore.sendMessage(content, contextNoteId?, includeNoteIds?, think?, contextNoteTitle?, excludeNoteIds?, ragProjectId?, workspaceProjectId?)` +- Always pass `think: true` +- For workspace: both `ragProjectId` and `workspaceProjectId` = `props.projectId` +- For briefing: no extra args beyond content +- For full chat: pass `includedNoteIds`, `excludedNoteIds`, `store.ragProjectId` + +- [ ] **Step 1: Write the full variant implementation** + +```vue + + + + + +``` + +- [ ] **Step 2: TypeScript check** + +```bash +cd /path/to/project/frontend && npm run typecheck 2>&1 | tail -30 +``` +Expected: no errors in `ChatPanel.vue`, `ChatInputBar.vue`, or `ChatStreamingBubble.vue`. + +- [ ] **Step 3: Commit** + +```bash +git add frontend/src/components/ChatPanel.vue +git commit -m "feat: rewrite ChatPanel with full and widget variants" +``` + +--- + +### Task 4: Migrate `ChatView.vue` + +**Files:** +- Modify: `frontend/src/views/ChatView.vue` + +ChatView keeps: sidebar (conversation list, bulk delete), route wiring, `onMounted`/`watch(convId)`, summarize button, research modal. It removes: all input bar HTML, streaming bubble HTML, scroll management, TTS/PTT/listen wiring, note context state. + +- [ ] **Step 1: Remove imports that ChatPanel now owns** + +In `