fix: add missing branching files and TypeScript fix

- Add BranchRevivalCard, BranchTransitionBar, useHandoff, useResolutionOutputs, SessionQueuePage
- Fix useFlowPilotSession: add is_branching/active_branch_id defaults

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-03-24 13:40:13 +00:00
parent c8778bb4e7
commit 19283fdeb6
6 changed files with 196 additions and 0 deletions

View File

@@ -92,6 +92,8 @@ export function useFlowPilotSession(): UseFlowPilotSession {
ticket_data: null,
steps: [firstStep],
conversation_messages: [],
is_branching: false,
active_branch_id: null,
})
setAllSteps([firstStep])
setCurrentStep(firstStep)

View File

@@ -0,0 +1,49 @@
import { useState, useCallback } from 'react'
import { handoffsApi } from '@/api'
import type { HandoffCreateRequest, HandoffResponse, QueueItemResponse } from '@/types/branching'
import { toast } from '@/lib/toast'
export function useHandoff() {
const [isSubmitting, setIsSubmitting] = useState(false)
const [queue, setQueue] = useState<QueueItemResponse[]>([])
const [isLoadingQueue, setIsLoadingQueue] = useState(false)
const createHandoff = useCallback(async (sessionId: string, data: HandoffCreateRequest): Promise<HandoffResponse | null> => {
setIsSubmitting(true)
try {
const result = await handoffsApi.createHandoff(sessionId, data)
toast.success(data.intent === 'park' ? 'Session parked' : 'Session escalated')
return result
} catch {
toast.error('Failed to hand off session')
return null
} finally {
setIsSubmitting(false)
}
}, [])
const claimHandoff = useCallback(async (sessionId: string, handoffId: string): Promise<HandoffResponse | null> => {
try {
const result = await handoffsApi.claimHandoff(sessionId, handoffId)
toast.success('Session claimed')
return result
} catch {
toast.error('Failed to claim session')
return null
}
}, [])
const loadQueue = useCallback(async () => {
setIsLoadingQueue(true)
try {
const items = await handoffsApi.getQueue()
setQueue(items)
} catch {
toast.error('Failed to load queue')
} finally {
setIsLoadingQueue(false)
}
}, [])
return { isSubmitting, queue, isLoadingQueue, createHandoff, claimHandoff, loadQueue }
}

View File

@@ -0,0 +1,43 @@
import { useState, useCallback } from 'react'
import { resolutionsApi } from '@/api'
import type { ResolutionOutputResponse, PushDestination } from '@/types/branching'
import { toast } from '@/lib/toast'
export function useResolutionOutputs(sessionId: string) {
const [outputs, setOutputs] = useState<ResolutionOutputResponse[]>([])
const [isLoading, setIsLoading] = useState(false)
const loadOutputs = useCallback(async () => {
setIsLoading(true)
try {
const data = await resolutionsApi.getOutputs(sessionId)
setOutputs(data.outputs)
} catch {
toast.error('Failed to load resolution outputs')
} finally {
setIsLoading(false)
}
}, [sessionId])
const editOutput = useCallback(async (outputId: string, content: string) => {
try {
const updated = await resolutionsApi.editOutput(sessionId, outputId, { edited_content: content })
setOutputs(prev => prev.map(o => o.id === updated.id ? updated : o))
toast.success('Changes saved')
} catch {
toast.error('Failed to save changes')
}
}, [sessionId])
const pushOutput = useCallback(async (outputId: string, destination: PushDestination) => {
try {
await resolutionsApi.pushOutput(sessionId, outputId, { destination })
toast.success(`Pushed to ${destination}`)
await loadOutputs()
} catch {
toast.error('Failed to push output')
}
}, [sessionId, loadOutputs])
return { outputs, isLoading, loadOutputs, editOutput, pushOutput }
}