CI surfaced react-hooks/set-state-in-effect on the synchronous setState(computeState(token)) inside the useEffect body. The earlier shape mirrored token -> state via an effect, which is exactly the "you might not need an effect" pattern React 19's eslint rule now flags. Switch to derived state: compute during render, use a useReducer tick to force re-render on the 30s cadence (so relative timestamps stay current even when token props don't change). Same observable behavior, no cascading renders. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
131 lines
5.7 KiB
Markdown
131 lines
5.7 KiB
Markdown
# Unified Sessions — Migration Plan
|
|
|
|
> **Date:** 2026-03-23
|
|
> **Status:** Implementation ready
|
|
> **Goal:** Merge assistant chat into the ai_sessions system so both guided (FlowPilot) and free-form (chat) sessions share the same data model, history, and action system.
|
|
|
|
## Problem
|
|
|
|
Three separate conversation systems exist:
|
|
1. `assistant_chats` — free-form chat, JSONB messages inline, no steps
|
|
2. `ai_sessions` + `ai_session_steps` — guided FlowPilot, separate steps table
|
|
3. `ai_chat_sessions` — flow builder (unrelated, leave alone)
|
|
|
|
This causes:
|
|
- No unified session history
|
|
- Assistant chats missing Resolve/Escalate/Update actions
|
|
- Dashboard can't show assistant chats in active/recent
|
|
- Two separate API surfaces to maintain
|
|
|
|
## Solution
|
|
|
|
Add `session_type` to `ai_sessions`. Chat sessions use `conversation_messages` JSONB for message history (already exists). Both types share the same status, PSA, escalation, and documentation features.
|
|
|
|
## Data Model Changes
|
|
|
|
### Migration: Add `session_type` to `ai_sessions`
|
|
|
|
```sql
|
|
ALTER TABLE ai_sessions ADD COLUMN session_type VARCHAR(10) NOT NULL DEFAULT 'guided';
|
|
-- Values: 'guided' (FlowPilot), 'chat' (assistant)
|
|
```
|
|
|
|
### How chat sessions use ai_sessions
|
|
|
|
| ai_sessions column | Chat usage |
|
|
|---|---|
|
|
| `session_type` | `'chat'` |
|
|
| `intake_type` | `'free_text'` |
|
|
| `intake_content` | `{text: "first message"}` |
|
|
| `conversation_messages` | Full chat history as JSONB array `[{role, content}]` |
|
|
| `status` | Same: active/resolved/escalated/paused/abandoned |
|
|
| `problem_summary` | AI-generated from first few messages |
|
|
| `problem_domain` | AI-detected domain |
|
|
| `step_count` | Message count (for display) |
|
|
| `resolution_summary` | Set on resolve |
|
|
| `escalation_reason` | Set on escalate |
|
|
| All PSA fields | Same — can link tickets, push notes |
|
|
| All timestamps | Same |
|
|
|
|
### What chat sessions DON'T use
|
|
|
|
- `ai_session_steps` table — no steps, messages are in `conversation_messages`
|
|
- `matched_flow_id` / `match_score` — no flow matching
|
|
- `confidence_tier` / `confidence_score` — no structured confidence
|
|
- `system_prompt_snapshot` — could store chat system prompt
|
|
|
|
### New field on ai_sessions
|
|
|
|
- `title` (String 255, nullable) — chat sessions need a title for the sidebar. Guided sessions can use `problem_summary`.
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 1: Backend — Model & Migration
|
|
- [ ] Alembic migration: add `session_type` VARCHAR(10) default 'guided', add `title` VARCHAR(255) nullable
|
|
- [ ] Update AISession model with new columns
|
|
- [ ] Update schemas: add `session_type` and `title` to response schemas
|
|
- [ ] Add session_type filter to GET /ai-sessions endpoint
|
|
|
|
### Phase 2: Backend — Chat API on ai_sessions
|
|
- [ ] Create new endpoints or extend existing:
|
|
- `POST /ai-sessions` with `session_type: 'chat'` — creates a chat session
|
|
- `POST /ai-sessions/{id}/chat` — send message, get AI response (appends to conversation_messages)
|
|
- Reuse existing: resolve, escalate, pause, abandon, status-update
|
|
- [ ] Chat AI service: takes conversation_messages, calls Anthropic, appends response
|
|
- [ ] Auto-generate title from first message (like current assistant chat does)
|
|
- [ ] Auto-detect problem_domain from conversation
|
|
|
|
### Phase 3: Frontend — Unified Session History
|
|
- [ ] Update SessionHistoryPage to show both types
|
|
- [ ] Add type icon: compass/route for guided, message-circle for chat
|
|
- [ ] Session detail page routes correctly based on type
|
|
- [ ] Add session_type filter option
|
|
|
|
### Phase 4: Frontend — Assistant Chat on ai_sessions
|
|
- [ ] Update AssistantChatPage to use ai_sessions API instead of assistant_chats
|
|
- [ ] Chat sidebar queries ai_sessions with `session_type=chat`
|
|
- [ ] Messages read from / write to `conversation_messages`
|
|
- [ ] Add header actions: Resolve / Escalate / Share Update / Pause / Close
|
|
- [ ] Status update modal works the same as FlowPilot
|
|
|
|
### Phase 5: Frontend — Dashboard Integration
|
|
- [ ] ActiveFlowPilotSessions includes chat sessions (both types)
|
|
- [ ] RecentFlowPilotSessions includes resolved chats
|
|
- [ ] Type icon on each card so users see the difference at a glance
|
|
|
|
### Phase 6: Cleanup
|
|
- [ ] Migrate existing assistant_chat data to ai_sessions (optional — could just start fresh for pilot)
|
|
- [ ] Deprecate /assistant/* API endpoints
|
|
- [ ] Remove assistant_chats model (post-pilot)
|
|
|
|
## Visual Differentiators
|
|
|
|
| Type | Icon | Badge color | Label |
|
|
|------|------|------------|-------|
|
|
| Guided (FlowPilot) | `<Route size={14} />` | cyan | "Guided" |
|
|
| Chat (Assistant) | `<MessageCircle size={14} />` | purple/violet | "Chat" |
|
|
|
|
## API Surface (after migration)
|
|
|
|
All under `/ai-sessions`:
|
|
|
|
| Endpoint | Both types? | Notes |
|
|
|----------|------------|-------|
|
|
| `POST /ai-sessions` | Yes | `session_type` field determines behavior |
|
|
| `GET /ai-sessions` | Yes | Filter by `session_type` optional |
|
|
| `GET /ai-sessions/{id}` | Yes | Returns full session with messages or steps |
|
|
| `POST /ai-sessions/{id}/chat` | Chat only | Send/receive messages |
|
|
| `POST /ai-sessions/{id}/respond` | Guided only | Step response |
|
|
| `POST /ai-sessions/{id}/resolve` | Both | Same resolve flow |
|
|
| `POST /ai-sessions/{id}/escalate` | Both | Same escalation |
|
|
| `POST /ai-sessions/{id}/pause` | Both | Same pause |
|
|
| `POST /ai-sessions/{id}/abandon` | Both | Same abandon |
|
|
| `POST /ai-sessions/{id}/status-update` | Both | Same status updates |
|
|
|
|
## Risk Assessment
|
|
|
|
- **Low risk:** Adding columns to ai_sessions is additive, no existing data changes
|
|
- **Medium risk:** Frontend routing — need to route to correct page based on session_type
|
|
- **Data migration:** Can skip for pilot — start with fresh chat sessions on new system. Old assistant_chats remain accessible via old API until removed.
|
|
- **Rollback:** session_type column is additive, old assistant_chat endpoints can stay as fallback
|