feat: mid-session status updates — ticket notes, client updates, email drafts

Engineers can now generate AI-powered status updates during active FlowPilot
sessions and after resolve/escalate. Three audiences (Ticket Notes, Client
Update, Email Draft) with Quick/Detailed length options. Copy to clipboard
with one click. Client names auto-inserted from intake/PSA context.

Backend: new endpoint POST /ai-sessions/{id}/status-update with audience-aware
system prompts. Frontend: StatusUpdateModal with 2-step selection flow,
Share Update button in action bar, Share Resolution/Escalation on completed
sessions. Also updates Solutions Library spec with Community tier design.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-23 06:26:32 +00:00
parent 0d78410dea
commit fab25456a5
13 changed files with 1560 additions and 5 deletions

View File

@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from 'react'
import { Network, Clock, Hash, Play, Ticket, ChevronDown, ChevronUp } from 'lucide-react'
import { Network, Clock, Hash, Play, Ticket, ChevronDown, ChevronUp, FileText } from 'lucide-react'
import type {
AISessionDetail,
AISessionStepResponse,
@@ -7,12 +7,17 @@ import type {
ResolveSessionRequest,
EscalateSessionRequest,
SessionDocumentation,
StatusUpdateAudience,
StatusUpdateLength,
StatusUpdateContext,
StatusUpdateResponse,
} from '@/types/ai-session'
import { ConfidenceIndicator } from './ConfidenceIndicator'
import { FlowPilotStepCard } from './FlowPilotStepCard'
import { FlowPilotActionBar } from './FlowPilotActionBar'
import { FlowPilotMessageBar } from './FlowPilotMessageBar'
import { SessionDocView } from './SessionDocView'
import { StatusUpdateModal } from './StatusUpdateModal'
import { SessionTicketCard } from './SessionTicketCard'
import { SimilarSessions } from './SimilarSessions'
import { TicketPickerModal } from '@/components/session/TicketPickerModal'
@@ -39,6 +44,7 @@ interface FlowPilotSessionProps {
onAbandon?: () => Promise<void>
onRate: (rating: number) => void
onReloadSession?: () => Promise<void>
onGenerateStatusUpdate?: (audience: StatusUpdateAudience, length: StatusUpdateLength, context: StatusUpdateContext) => Promise<StatusUpdateResponse>
}
export function FlowPilotSession({
@@ -60,10 +66,12 @@ export function FlowPilotSession({
onAbandon,
onRate,
onReloadSession,
onGenerateStatusUpdate,
}: FlowPilotSessionProps) {
const scrollRef = useRef<HTMLDivElement>(null)
const [showTicketPicker, setShowTicketPicker] = useState(false)
const [linkingTicket, setLinkingTicket] = useState(false)
const [showShareCommunication, setShowShareCommunication] = useState(false)
const [showMobileSidebar, setShowMobileSidebar] = useState(false)
const handleLinkTicket = async (ticketId: string, _ticket: PSATicketInfo) => {
@@ -115,9 +123,24 @@ export function FlowPilotSession({
// Show documentation view for completed sessions
if (isCompleted && documentation) {
const shareContext = session.status === 'resolved' ? 'resolution' as const : 'escalation' as const
const shareLabel = session.status === 'resolved' ? 'Share Resolution' : 'Share Escalation'
return (
<div className="flex h-full flex-col">
<div className="flex-1 overflow-y-auto p-3 sm:p-4 lg:p-6">
{/* Share Resolution/Escalation button */}
{onGenerateStatusUpdate && (
<div className="mb-4">
<button
onClick={() => setShowShareCommunication(true)}
className="flex items-center gap-2 rounded-lg bg-cyan-500/10 border border-cyan-500/20 px-4 py-2.5 text-sm font-medium text-cyan-400 hover:bg-cyan-500/20 transition-colors"
>
<FileText size={16} />
{shareLabel}
</button>
</div>
)}
<SessionDocView
documentation={documentation}
onRate={onRate}
@@ -129,6 +152,17 @@ export function FlowPilotSession({
ticketId={session.psa_ticket_id}
/>
</div>
{/* Share communication modal for resolved/escalated sessions */}
{onGenerateStatusUpdate && (
<StatusUpdateModal
open={showShareCommunication}
onClose={() => setShowShareCommunication(false)}
onGenerate={onGenerateStatusUpdate}
context={shareContext}
hasPsaTicket={!!session.psa_ticket_id}
/>
)}
</div>
)
}
@@ -320,10 +354,12 @@ export function FlowPilotSession({
isProcessing={isProcessing}
hasPsaTicket={!!session.psa_ticket_id}
sessionId={session.id}
canShareUpdate={allSteps.length >= 2}
onResolve={onResolve}
onEscalate={onEscalate}
onPause={onPause}
onAbandon={onAbandon}
onGenerateStatusUpdate={onGenerateStatusUpdate}
/>
)}