# AI Chat Stop Button 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:** Add a stop button to the AI chat panel that cancels in-flight streaming, removes the pending messages from the UI, and ensures nothing is saved to the database or submitted. **Architecture:** When the user clicks stop, the frontend pops the unsaved user message from the UI, resets streaming state, and closes the WebSocket. The backend's existing `disconnect()` handler deletes the in-progress user message from the DB; the assistant message and Submission are never created because `complete` is never sent. **Tech Stack:** Vue 3, TypeScript, Naive UI, WebSocket (Django Channels) --- ## File Map | File | Change | |---|---| | `client/src/store/prompt.ts` | Store `_currentTaskId`; set `streaming=true` on send; add `stopPrompt()` | | `client/src/components/ai/PromptPanel.vue` | Import `stopPrompt`; swap Send/Stop buttons based on `streaming` | --- ### Task 1: Update `store/prompt.ts` **Files:** - Modify: `client/src/store/prompt.ts` - [ ] **Step 1: Store `_currentTaskId` and set it in `connectPrompt`** In `client/src/store/prompt.ts`, after the line `let ws: WebSocket | null = null`, add: ```typescript let _currentTaskId = 0 ``` Then inside `connectPrompt(taskId: number)`, add as the very first line of the function body: ```typescript _currentTaskId = taskId ``` Result — the start of `connectPrompt` becomes: ```typescript export function connectPrompt(taskId: number) { _currentTaskId = taskId if (ws) ws.close() // ... rest unchanged ``` - [ ] **Step 2: Set `streaming = true` immediately on send** In `sendPrompt()`, add `streaming.value = true` as the first statement before the `push`: ```typescript export function sendPrompt(content: string, model: string = "") { if (!ws || ws.readyState !== WebSocket.OPEN) return streaming.value = true messages.value.push({ role: "user", content }) ws.send(JSON.stringify({ type: "message", content, model })) } ``` - [ ] **Step 3: Add `stopPrompt()` function** After `sendPrompt`, add: ```typescript export function stopPrompt() { // Remove the user message added to UI (not yet saved in DB) if ( messages.value.length > 0 && messages.value[messages.value.length - 1].role === "user" ) { messages.value.pop() } streaming.value = false streamingContent.value = "" // Closing triggers backend disconnect() which deletes the DB user message if (ws) { ws.close() ws = null } // Reconnect immediately so the next message can be sent if (_currentTaskId) { connectPrompt(_currentTaskId) } } ``` - [ ] **Step 4: Verify the file looks correct** Open `client/src/store/prompt.ts` and confirm: - `_currentTaskId` is declared after `let ws` - `connectPrompt` sets `_currentTaskId = taskId` as its first line - `sendPrompt` sets `streaming.value = true` before the push - `stopPrompt` is exported and appears between `sendPrompt` and the private `applyCode` - [ ] **Step 5: Commit** ```bash cd /home/xuyue/Projects/webpreview git add client/src/store/prompt.ts git commit -m "feat: add stopPrompt() and track currentTaskId in prompt store" ``` --- ### Task 2: Add Stop button to `PromptPanel.vue` **Files:** - Modify: `client/src/components/ai/PromptPanel.vue` - [ ] **Step 1: Import `stopPrompt`** Find the import line in `