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:
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
Reference in New Issue
Block a user