feat: persist task lane across submits and session reloads

Task lane questions/actions are now saved to a pending_task_lane JSONB
column on ai_sessions, restoring them on session switch or page reload.
Partial submit no longer force-clears the lane — the AI response
controls what stays. Also removes redundant "New Session" button from
the sidebar (dashboard already provides this).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-03-27 21:48:06 +00:00
parent 217e70cb81
commit ecd7393646
8 changed files with 67 additions and 30 deletions

View File

@@ -5,7 +5,7 @@ import {
LayoutGrid, Clock, AlertTriangle, GitBranch, Code2, Wand2,
ListChecks, Download, BarChart3,
Settings, Pin, PinOff,
Plus, History, FileText,
History, FileText,
} from 'lucide-react'
import { cn } from '@/lib/utils'
import { useUserPreferencesStore } from '@/store/userPreferencesStore'
@@ -363,17 +363,6 @@ export function Sidebar() {
style={{ background: 'var(--color-bg-sidebar)', borderRight: '1px solid var(--color-border-default)' }}
onWheel={handleWheel}
>
{/* New Session button */}
<div className="px-3 pt-3 pb-1">
<Link
to="/"
className="flex items-center justify-center gap-2 w-full rounded-lg bg-amber-400/15 py-2.5 text-sm font-semibold text-amber-400 hover:bg-amber-400/25 transition-colors"
>
<Plus size={16} strokeWidth={2} />
New Session
</Link>
</div>
{/* Pinned sidebar content */}
<div className="px-3 py-2 space-y-0.5">
{sections.map((section, si) => (
@@ -420,18 +409,6 @@ export function Sidebar() {
style={{ background: 'var(--color-bg-sidebar)', borderRight: '1px solid var(--color-border-default)', width: '72px' }}
onWheel={handleWheel}
>
{/* New Session button */}
<div className="w-full px-2 pt-4 pb-2">
<Link
to="/"
className="flex flex-col items-center justify-center w-full rounded-lg bg-amber-400/15 py-2.5 text-amber-400 hover:bg-amber-400/25 transition-colors"
title="New Session"
>
<Plus size={20} strokeWidth={2} />
<span className="mt-1 text-[0.5625rem] font-sans font-semibold">New</span>
</Link>
</div>
{/* Nav items */}
<div className="flex flex-col items-center w-full px-1 space-y-1.5">
{railGroups.map((item, i) => renderRailItem(item, `rail-${i}`))}

View File

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

View File

@@ -160,7 +160,7 @@ export default function AssistantChatPage() {
const selectChat = useCallback(async (chatId: string) => {
setActiveChatId(chatId)
// Clear TaskLane when switching chats
// Clear TaskLane when switching chats — will restore from backend if available
setShowTaskLane(false)
setActiveQuestions([])
setActiveActions([])
@@ -172,6 +172,16 @@ export default function AssistantChatPage() {
content: m.content,
}))
)
// Restore task lane from persisted state
if (detail.pending_task_lane) {
const q = detail.pending_task_lane.questions || []
const a = detail.pending_task_lane.actions || []
if (q.length > 0 || a.length > 0) {
setActiveQuestions(q)
setActiveActions(a)
setShowTaskLane(true)
}
}
} catch {
setMessages([])
}
@@ -288,11 +298,6 @@ export default function AssistantChatPage() {
}
const userMessage = parts.join('\n\n')
// Close the task lane
setShowTaskLane(false)
setActiveQuestions([])
setActiveActions([])
setMessages(prev => [...prev, { role: 'user', content: userMessage }])
setLoading(true)

View File

@@ -195,6 +195,7 @@ export interface AISessionDetail extends AISessionSummary {
ticket_data: Record<string, unknown> | null
steps: AISessionStepResponse[]
conversation_messages: Array<{ role: string; content: string }>
pending_task_lane: { questions: QuestionItem[]; actions: ActionItem[] } | null
is_branching: boolean
active_branch_id: string | null
}