docs: add spec and implementation plan for task lane minimize + resolve streaming

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-03-28 22:33:47 +00:00
parent 0483b6f0f5
commit af2a41830c
2 changed files with 1224 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
# Task Lane Minimize/Reopen + Resolve Documentation Streaming
**Date:** 2026-03-28
**Status:** Approved
---
## Problem
Two UX issues in the Assistant Chat page:
1. **Task Lane close destroys state.** The X button calls `clearTaskState()` and hides the panel. There's no way to bring it back without getting a new AI response with markers. Engineers lose in-progress task responses.
2. **Conclude → Resolved hangs.** The resolve flow blocks on an LLM call to generate documentation. The modal shows "Generating..." for 2-5s+ with no progressive feedback. The generated output needs to be structured ticket notes engineers can copy into their PSA.
---
## Feature 1: Task Lane Minimize/Reopen
### Close Button Change
- Replace the X icon (`X` from Lucide) with `PanelRightClose` to signal "collapse" not "destroy."
- On click: set `showTaskLane = false`. Do NOT call `clearTaskState(sessionId)`.
- Task state (questions, actions, user responses) remains in sessionStorage and backend `pending_task_lane`.
### Reopen Pill on Input Toolbar
- New pill button in the chat input toolbar row, alongside Attach / Paste Logs / Conclude.
- **Visibility condition:** `(activeQuestions.length > 0 || activeActions.length > 0) && !showTaskLane`
- **Label:** `Tasks (N)` where N = `activeQuestions.length + activeActions.length`
- **Icon:** `ListChecks` from Lucide
- **Action:** `setShowTaskLane(true)`
- **Style:** Same ghost button style as Attach/Paste Logs — muted text, hover highlight.
### Files Changed
| File | Change |
|------|--------|
| `frontend/src/components/assistant/TaskLane.tsx` | Replace `X` icon with `PanelRightClose` in header |
| `frontend/src/pages/AssistantChatPage.tsx` | Remove `clearTaskState()` from onClose handler; add Tasks pill to input toolbar |
---
## Feature 2: Resolve with Streaming Documentation
### Two-Phase Resolve Flow
**Phase 1 — Instant resolve:**
1. User clicks Resolve in `ConcludeSessionModal`, enters optional notes, confirms.
2. Frontend calls `POST /ai-sessions/{id}/resolve` with `{ resolution_summary }`.
3. Backend sets session status to `resolved`, saves summary, returns immediately. No LLM call on this path.
4. Modal transitions to the summary step instantly, showing a skeleton loading state for "Ticket Notes."
**Phase 2 — Streamed doc generation:**
1. Immediately after phase 1, frontend opens an SSE connection to `GET /ai-sessions/{id}/documentation/stream`.
2. Backend streams the structured ticket notes as they generate, token by token.
3. Frontend renders chunks progressively into the summary step using `MarkdownContent`.
4. When stream completes, show a "Copy to Clipboard" button.
### Ticket Notes Format
The LLM generates four structured sections:
```markdown
## Problem Summary
[What the engineer reported / intake context]
## Steps Taken
[Key diagnostic steps and findings from conversation]
## Resolution
[What fixed it / final action taken]
## Next Steps
[Follow-up items, if any — or "None"]
```
### Fallback Behavior
- If SSE stream fails or times out (30s): fall back to non-streaming `GET /ai-sessions/{id}/documentation`.
- If that also fails: show "Documentation unavailable" with a "Copy Conversation" button that formats the raw `conversation_messages` into a basic structured summary (no LLM, pure template).
### Copy to Clipboard
- Prominent button below the rendered ticket notes.
- Copies the full markdown text.
- Toast confirmation: "Ticket notes copied."
### AI Optimizations
**1. Streaming (SSE endpoint):**
- New endpoint: `GET /ai-sessions/{id}/documentation/stream`
- Returns `text/event-stream` via FastAPI `StreamingResponse`.
- Uses Anthropic's `client.messages.stream()` for token-level streaming.
- Time-to-first-byte drops from ~2-5s to ~200ms.
**2. Prompt caching:**
- Apply `cache_control: {"type": "ephemeral"}` to the system prompt and conversation context prefix in the documentation generation call.
- Pattern already exists in `assistant_chat_service.py` (`_call_anthropic_cached`).
- Repeat calls for the same session (regenerate, different doc types) hit cache — up to 85% faster, 90% cheaper on input tokens.
**3. Client reuse:**
- Singleton `AsyncAnthropic` client instead of creating a new one per call.
- Eliminates connection setup overhead.
**Model tier:** Haiku (already configured as `quick_action` tier) — fastest model, appropriate for summarization.
### Backend Changes
| File | Change |
|------|--------|
| `backend/app/api/endpoints/ai_sessions.py` | Modify `resolve_session` to only set status + save summary (remove the blocking `get_session_documentation` call); add new SSE streaming endpoint for doc generation |
| `backend/app/services/flowpilot_engine.py` | Add `stream_session_documentation()` generator function using `client.messages.stream()` |
| `backend/app/core/ai_provider.py` | Add `generate_text_stream()` method returning async iterator; singleton client |
| `backend/app/services/flowpilot_engine.py` | Add prompt caching to `_build_status_update_prompt` call path |
### Frontend Changes
| File | Change |
|------|--------|
| `frontend/src/components/assistant/ConcludeSessionModal.tsx` | Two-phase flow: instant resolve → streaming doc render with skeleton → copy button |
| `frontend/src/api/aiSessions.ts` | Add `streamDocumentation(sessionId)` using fetch + ReadableStream |
| `frontend/src/pages/AssistantChatPage.tsx` | Update `handleConclude` to not await documentation |
### ConcludeSessionModal Summary Step Layout
```
┌─────────────────────────────────────┐
│ Session Resolved │
│ │
│ ┌─ Ticket Notes ─────────────────┐ │
│ │ ## Problem Summary │ │
│ │ [streaming text...] │ │
│ │ │ │
│ │ ## Steps Taken │ │
│ │ [streaming text...] │ │
│ │ │ │
│ │ ## Resolution │ │
│ │ [streaming text...] │ │
│ │ │ │
│ │ ## Next Steps │ │
│ │ [streaming text...] │ │
│ └────────────────────────────────┘ │
│ │
│ [ Copy to Clipboard ] [ Done ] │
└─────────────────────────────────────┘
```
---
## Out of Scope
- Client-facing update generation (future feature, different audience prompt)
- Direct PSA posting (requires ConnectWise integration to be wired to sessions)
- Task lane drag-to-reorder
- Task lane persistence across browser tabs (sessionStorage is per-tab by design)