import * as React from "react" import { useAgentClient, partsFromResponseBlocks } from "@agents24/react" import { AgentResponseTimeline } from "@agents24/chat-react/ui" import { useDelegationTasks, type DelegationHistory, type DelegationTask } from "@agents24/chat-react/runtime" import { Button } from "../ui/button" export function SubagentTasks({ threadId }: { threadId: string | null }) { const client = useAgentClient() const source = React.useMemo(() => ({ events: (input: { threadId: string; after: number; signal: AbortSignal }) => client.threads.delegations.events(input) }), [client]) const { tasks, error, refresh } = useDelegationTasks({ threadId, source }) const [selection, setSelection] = React.useState<{ threadId: string | null; handle: string | null }>({ threadId: null, handle: null }) const selected = selection.threadId === threadId ? selection.handle : null if (!threadId || (!tasks.length && !error)) return null return
Tasks ({tasks.length}) {error ?

Task updates are unavailable. Retrying…

: null} {tasks.filter(task => task.handle === selected).map(task => )}
} function TaskConversation({ threadId, task, onChanged }: { threadId: string; task: DelegationTask; onChanged: () => void }) { const client = useAgentClient() const [history, setHistory] = React.useState(null) const [earlier, setEarlier] = React.useState([]) const historyInitialized = React.useRef(false) const [before, setBefore] = React.useState(null) const [error, setError] = React.useState(null) const [busy, setBusy] = React.useState(false) const operation = React.useRef<{ action: "interrupt" | "cancel"; id: string } | null>(null) React.useEffect(() => { const controller = new AbortController() let timer: ReturnType const refresh = async () => { try { const page = await client.threads.delegations.history({ threadId, handle: task.handle, signal: controller.signal }) if (controller.signal.aborted) return setHistory(page) if (!historyInitialized.current) { historyInitialized.current = true setBefore(page.paging.next_before_turn_index) } } catch { if (!controller.signal.aborted) setError("Task history could not be loaded.") } finally { if (!controller.signal.aborted) timer = setTimeout(refresh, 2000) } } void refresh() return () => { controller.abort(); clearTimeout(timer) } }, [client, threadId, task.handle]) const loadEarlier = async () => { if (before === null) return setBusy(true) try { const page = await client.threads.delegations.history({ threadId, handle: task.handle, before }) setEarlier(current => [...page.turns, ...current]) setBefore(page.paging.next_before_turn_index) } catch { setError("Earlier task history could not be loaded.") } finally { setBusy(false) } } const act = async (action: "interrupt" | "cancel") => { setBusy(true); setError(null) if (operation.current?.action !== action) operation.current = { action, id: crypto.randomUUID() } try { await client.threads.delegations.act({ threadId, handle: task.handle, action: { action, operation_id: operation.current.id } }) operation.current = null onChanged() } catch { setError("The task action could not be completed. Try again.") } finally { setBusy(false) } } const turns = Array.from(new Map([...earlier, ...(history?.turns || [])].map(turn => [turn.id, turn])).values()) .sort((a, b) => a.turn_index - b.turn_index) return

{task.name}

{error ?

{error}

: null}
{task.capabilities.interrupt ? : null} {task.capabilities.cancel ? : null} {before !== null ? : null}
{turns.map(turn =>
{turn.assignment_instruction ?

{turn.assignment_instruction}

: null} {turn.user_input_text ?

{turn.user_input_text}

: null} {turn.exchanges?.map(exchange =>

{exchange.sender === "parent" ? "Parent Agent" : "Subagent update"}

{exchange.text}
)}
)}
}