fix: stabilize cockpit and assistant session handoff

This commit is contained in:
chihlasm
2026-04-03 04:00:47 +00:00
parent b07dfb7603
commit ed6e6cd1ed
2 changed files with 44 additions and 16 deletions

View File

@@ -310,23 +310,34 @@ export function useAssistantSession() {
// Callback for pages to handle triage updates from chat responses. // Callback for pages to handle triage updates from chat responses.
const onTriageUpdateRef = useRef<((update: TriageUpdate) => void) | null>(null) const onTriageUpdateRef = useRef<((update: TriageUpdate) => void) | null>(null)
const handleSend = async () => { const sendMessage = useCallback(async (
if (!input.trim() || !activeChatId || loadingRef.current) return rawMessage: string,
options?: {
uploadIds?: string[]
clearComposer?: boolean
}
) => {
const message = rawMessage.trim()
if (!message || !activeChatId || loadingRef.current) return
loadingRef.current = true loadingRef.current = true
const sendChatId = activeChatId const sendChatId = activeChatId
const userMessage = input.trim() const uploadIds = options?.uploadIds
const completedUploadIds = pendingUploads const completedUploadIds = uploadIds ?? pendingUploads
.filter((u) => u.status === 'done' && u.result?.id) .filter((u) => u.status === 'done' && u.result?.id)
.map((u) => u.result!.id) .map((u) => u.result!.id)
setInput('') if (options?.clearComposer !== false) {
setPendingUploads([]) setInput('')
setMessages(prev => [...prev, { role: 'user', content: userMessage }]) if (!uploadIds) {
setPendingUploads([])
}
}
setMessages(prev => [...prev, { role: 'user', content: message }])
setLoading(true) setLoading(true)
try { try {
const response = await aiSessionsApi.sendChatMessage(sendChatId, { const response = await aiSessionsApi.sendChatMessage(sendChatId, {
message: userMessage, message,
upload_ids: completedUploadIds.length > 0 ? completedUploadIds : undefined, upload_ids: completedUploadIds.length > 0 ? completedUploadIds : undefined,
}) })
if (currentChatRef.current !== sendChatId) return if (currentChatRef.current !== sendChatId) return
@@ -335,7 +346,7 @@ export function useAssistantSession() {
setChats(prev => setChats(prev =>
prev.map(c => prev.map(c =>
c.id === sendChatId c.id === sendChatId
? { ...c, message_count: c.message_count + 2, title: c.message_count === 0 ? userMessage.slice(0, 100) : c.title, updated_at: new Date().toISOString() } ? { ...c, message_count: c.message_count + 2, title: c.message_count === 0 ? message.slice(0, 100) : c.title, updated_at: new Date().toISOString() }
: c : c
) )
) )
@@ -353,12 +364,17 @@ export function useAssistantSession() {
requestAnimationFrame(() => inputRef.current?.focus()) requestAnimationFrame(() => inputRef.current?.focus())
} }
} }
}, [activeChatId, pendingUploads, processResponse])
const handleSend = async () => {
await sendMessage(input)
} }
// Handle prefill from command palette / dashboard handoff // Handle prefill from command palette / dashboard handoff
const handlePrefill = useCallback((_prefillRoute: string) => { const handlePrefill = useCallback((_prefillRoute: string) => {
const state = location.state as { prefill?: string; uploadIds?: string[] } | null const state = location.state as { prefill?: string; logs?: string; uploadIds?: string[] } | null
const prefill = state?.prefill const prefill = state?.prefill
const logs = state?.logs?.trim()
const uploadIds = state?.uploadIds const uploadIds = state?.uploadIds
if (!prefill || prefillHandledRef.current) return if (!prefill || prefillHandledRef.current) return
prefillHandledRef.current = true prefillHandledRef.current = true
@@ -372,11 +388,18 @@ export function useAssistantSession() {
setActiveQuestions([]) setActiveQuestions([])
setActiveActions([]) setActiveActions([])
setLoading(true) setLoading(true)
if (logs) {
setShowLogs(true)
setLogContent(logs)
}
try { try {
const initialMessage = logs
? `${prefill}\n\nAttached logs/output:\n\`\`\`\n${logs}\n\`\`\``
: prefill
const session = await aiSessionsApi.createChatSession({ const session = await aiSessionsApi.createChatSession({
intake_type: 'free_text', intake_type: 'free_text',
intake_content: { text: prefill }, intake_content: { text: initialMessage },
}) })
const prefillChatId = session.session_id const prefillChatId = session.session_id
currentChatRef.current = prefillChatId currentChatRef.current = prefillChatId
@@ -390,10 +413,10 @@ export function useAssistantSession() {
} }
setChats(prev => [chatItem, ...prev]) setChats(prev => [chatItem, ...prev])
setActiveChatId(prefillChatId) setActiveChatId(prefillChatId)
setMessages([{ role: 'user', content: prefill }]) setMessages([{ role: 'user', content: initialMessage }])
const response = await aiSessionsApi.sendChatMessage(prefillChatId, { const response = await aiSessionsApi.sendChatMessage(prefillChatId, {
message: prefill, message: initialMessage,
upload_ids: uploadIds?.length ? uploadIds : undefined, upload_ids: uploadIds?.length ? uploadIds : undefined,
}) })
if (currentChatRef.current !== prefillChatId) return if (currentChatRef.current !== prefillChatId) return
@@ -561,7 +584,7 @@ export function useAssistantSession() {
setShowTaskLane, setActiveQuestions, setActiveActions, setShowTaskLane, setActiveQuestions, setActiveActions,
// Handlers // Handlers
loadChats, selectChat, handleNewChat, handleDeleteChat, handleTogglePin, loadChats, selectChat, handleNewChat, handleDeleteChat, handleTogglePin,
handleSend, handleConclude, handleResumeNew, handleSend, sendMessage, handleConclude, handleResumeNew,
handleKeyDown, handlePaste, handleKeyDown, handlePaste,
handleDragOver, handleDragEnter, handleDragLeave, handleDrop, handleDragOver, handleDragEnter, handleDragLeave, handleDrop,
handleFileSelect, handleRemoveUpload, retryUpload, handleFileSelect, handleRemoveUpload, retryUpload,

View File

@@ -85,6 +85,12 @@ export default function CockpitPage() {
prevMessageCountRef.current = session.messages.length prevMessageCountRef.current = session.messages.length
}, [session.messages.length, showOnboarding]) }, [session.messages.length, showOnboarding])
// Reset local step UI when switching cases or when a new action set arrives.
useEffect(() => {
setActiveStepIndex(0)
setCompletedSteps(new Set())
}, [session.activeChatId, session.activeActions])
// ── Triage handlers ── // ── Triage handlers ──
const handleTriageFieldSave = useCallback(async (field: keyof TriageMeta, value: string) => { const handleTriageFieldSave = useCallback(async (field: keyof TriageMeta, value: string) => {
@@ -306,8 +312,7 @@ export default function CockpitPage() {
<FlowPilotAsks <FlowPilotAsks
questions={session.activeQuestions} questions={session.activeQuestions}
onAnswer={(answer) => { onAnswer={(answer) => {
session.setInput(answer) void session.sendMessage(answer, { clearComposer: false })
setTimeout(() => session.handleSend(), 10)
}} }}
loading={session.loading} loading={session.loading}
/> />