Files
resolutionflow/frontend/src/api/aiSessions.ts
chihlasm b414502062 feat: unified sessions — merge assistant chat into ai_sessions table
Add session_type ('guided'|'chat') and title columns to ai_sessions,
enabling both FlowPilot guided sessions and assistant chat sessions to
live in a single table. This is the foundation for a unified session
history and consistent UX across both interaction modes.

Backend:
- Migration 066: session_type + title columns
- unified_chat_service: chat sessions on ai_sessions with same AI/RAG
- POST /ai-sessions supports session_type='chat' creation
- POST /ai-sessions/{id}/chat for chat messages
- DELETE /ai-sessions/{id} for session deletion
- session_type filter on GET /ai-sessions

Frontend:
- AssistantChatPage rewired to aiSessionsApi (no more assistantChatApi)
- /assistant/:sessionId route for deep-linking
- Session history: type filter pills (All/Guided/Chat), type icons
- Dashboard: both types shown with correct routing and icons
- Fixed glass-border → border-default in dashboard components

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 17:29:25 +00:00

176 lines
5.5 KiB
TypeScript

import apiClient from './client'
import type {
AISessionCreateRequest,
AISessionCreateResponse,
StepResponseRequest,
StepResponseResponse,
ResolveSessionRequest,
EscalateSessionRequest,
SessionCloseResponse,
SessionDocumentation,
AISessionSummary,
AISessionDetail,
AISessionSearchResult,
SimilarSession,
PickupSessionRequest,
StatusUpdateRequest,
StatusUpdateResponse,
ChatSessionCreateResponse,
ChatMessageRequest,
ChatMessageResponse,
} from '@/types/ai-session'
export const aiSessionsApi = {
async createSession(data: AISessionCreateRequest): Promise<AISessionCreateResponse> {
const response = await apiClient.post<AISessionCreateResponse>('/ai-sessions', data)
return response.data
},
async createChatSession(data: AISessionCreateRequest): Promise<ChatSessionCreateResponse> {
const response = await apiClient.post<ChatSessionCreateResponse>('/ai-sessions', {
...data,
session_type: 'chat',
})
return response.data
},
async sendChatMessage(sessionId: string, data: ChatMessageRequest): Promise<ChatMessageResponse> {
const response = await apiClient.post<ChatMessageResponse>(
`/ai-sessions/${sessionId}/chat`,
data
)
return response.data
},
async respondToStep(sessionId: string, data: StepResponseRequest): Promise<StepResponseResponse> {
const response = await apiClient.post<StepResponseResponse>(
`/ai-sessions/${sessionId}/respond`,
data
)
return response.data
},
async resolveSession(sessionId: string, data: ResolveSessionRequest): Promise<SessionCloseResponse> {
const response = await apiClient.post<SessionCloseResponse>(
`/ai-sessions/${sessionId}/resolve`,
data
)
return response.data
},
async escalateSession(sessionId: string, data: EscalateSessionRequest): Promise<SessionCloseResponse> {
const response = await apiClient.post<SessionCloseResponse>(
`/ai-sessions/${sessionId}/escalate`,
data
)
return response.data
},
async listSessions(params?: {
status?: string
session_type?: string
skip?: number
limit?: number
problem_domain?: string
matched_flow_id?: string
confidence_tier?: string
ticket_id?: string
date_from?: string
date_to?: string
q?: string
}): Promise<AISessionSummary[]> {
// Strip empty string values so they aren't sent as empty query params
const cleanParams = params
? Object.fromEntries(Object.entries(params).filter(([, v]) => v !== '' && v !== undefined))
: undefined
const response = await apiClient.get<AISessionSummary[]>('/ai-sessions', { params: cleanParams })
return response.data
},
async getSession(sessionId: string): Promise<AISessionDetail> {
const response = await apiClient.get<AISessionDetail>(`/ai-sessions/${sessionId}`)
return response.data
},
async getDocumentation(sessionId: string): Promise<SessionDocumentation> {
const response = await apiClient.get<SessionDocumentation>(
`/ai-sessions/${sessionId}/documentation`
)
return response.data
},
async rateSession(sessionId: string, data: { rating: number; feedback?: string }): Promise<void> {
await apiClient.post(`/ai-sessions/${sessionId}/rate`, data)
},
async retryPsaPush(sessionId: string): Promise<{ psa_push_status: string; psa_push_error: string | null }> {
const response = await apiClient.post<{ psa_push_status: string; psa_push_error: string | null }>(
`/ai-sessions/${sessionId}/retry-psa-push`
)
return response.data
},
async pauseSession(sessionId: string): Promise<void> {
await apiClient.post(`/ai-sessions/${sessionId}/pause`)
},
async resumeSession(sessionId: string): Promise<void> {
await apiClient.post(`/ai-sessions/${sessionId}/resume`)
},
async abandonSession(sessionId: string, reason?: string): Promise<void> {
await apiClient.post(`/ai-sessions/${sessionId}/abandon`, null, {
params: reason ? { reason } : undefined,
})
},
async deleteSession(sessionId: string): Promise<void> {
await apiClient.delete(`/ai-sessions/${sessionId}`)
},
async pickupSession(sessionId: string, data: PickupSessionRequest): Promise<StepResponseResponse> {
const response = await apiClient.post<StepResponseResponse>(
`/ai-sessions/${sessionId}/pickup`,
data
)
return response.data
},
async linkTicket(sessionId: string, data: { psa_ticket_id: string; psa_connection_id: string }): Promise<AISessionDetail> {
const response = await apiClient.post<AISessionDetail>(
`/ai-sessions/${sessionId}/link-ticket`,
data
)
return response.data
},
async getEscalationQueue(): Promise<AISessionSummary[]> {
const response = await apiClient.get<AISessionSummary[]>('/ai-sessions/escalation-queue')
return response.data
},
async search(q: string, limit: number = 5): Promise<AISessionSearchResult[]> {
const response = await apiClient.get<AISessionSearchResult[]>('/ai-sessions/search', {
params: { q, limit },
})
return response.data
},
async getSimilar(sessionId: string, limit: number = 5): Promise<SimilarSession[]> {
const response = await apiClient.get<SimilarSession[]>(`/ai-sessions/${sessionId}/similar`, {
params: { limit },
})
return response.data
},
async generateStatusUpdate(sessionId: string, data: StatusUpdateRequest): Promise<StatusUpdateResponse> {
const response = await apiClient.post<StatusUpdateResponse>(
`/ai-sessions/${sessionId}/status-update`,
data
)
return response.data
},
}
export default aiSessionsApi