@athenaintel/react 0.38.0 → 0.38.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"StatewireQueuedMessages.cjs","sources":["../../src/chat/StatewireQueuedMessages.tsx"],"sourcesContent":["import { useAui, useAuiState } from '@assistant-ui/react';\nimport type { StatewireThread } from '@assistant-ui/react-statewire';\nimport {\n useStatewireRuns,\n useStatewireSendCommand,\n useStatewireState,\n} from '@assistant-ui/react-statewire';\nimport {\n buildQueueEditCommand,\n buildStatewireQueueRows,\n type DeepAgentThreadStatus,\n describeQueueSendFailure,\n hasStatewireThreadExtras,\n isFailedSendEntryRace,\n isQueueEntryUnsettled,\n isServerUpdateStopSource,\n QUEUE_AUTO_CONTINUE_DELAY_MS,\n queueEntryText,\n queueLaneFlags,\n readDeepAgentStreamValues,\n readPrioritizedQueueIds,\n readRetryableRunRefusal,\n readRunMarkerFromSourceMessages,\n requireStatewireFailedActions,\n type StatewireFailedActions,\n showQueueRowSendNow,\n useDeepAgentThreadStatus,\n userStopBlocksQueueAutoContinue,\n} from '@athenaintel/agent-runtime';\nimport {\n AlertCircleIcon,\n CheckIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n CircleIcon,\n Loader2Icon,\n PencilIcon,\n RotateCcwIcon,\n SendIcon,\n Trash2Icon,\n XIcon,\n ZapIcon,\n} from 'lucide-react';\nimport {\n type FC,\n type KeyboardEvent,\n type MutableRefObject,\n type ReactNode,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { mentionsToPlainText, parseMentionsInText } from '../chat-ui/mentions/mention-chip';\nimport { ContinuePill } from '../chat-ui/messages/continue-pill';\nimport { cn } from '../lib/utils';\n\ndeclare module '@assistant-ui/core' {\n namespace Assistant {\n interface Commands {\n /**\n * The ⚡ on a queued row (`DeepAgentThread.run_prioritize`). With\n * `priority: true` the host moves the entry to the head of the queue\n * lane (behind entries prioritized before it), records it durably, and\n * the live run ends at its next model-call boundary — after the\n * in-flight tool chain, never mid-tool — so the settle delivers the\n * entry on top of the finished tool results instead of after the whole\n * turn. `priority: false` withdraws the request and leaves the entry\n * where it is.\n */\n runPrioritize: {\n type: 'run/prioritize';\n runId: string;\n messageId: string;\n priority: boolean;\n };\n }\n }\n}\n\n/**\n * The one queued-messages tray for the server-owned statewire queue and steer\n * lanes, mounted by the SDK's `AthenaChat`, the Chrome side panel, the Office\n * task pane, and Olympus.\n *\n * A message sent mid-run queues behind the active run. Rows offer \"Send now\"\n * (a steer-lane move — the host stops the run and dispatches it once the run\n * settles; on a stopped/errored thread the same move dispatches immediately),\n * \"Prioritize\" (`run/prioritize`, the ⚡ — the non-interrupting analog: the\n * live run ends at its next model-call boundary so the entry lands on top of\n * the finished tool results), inline edit (re-sent under the entry's own id\n * on its own lane, which the host folds as an in-place content update), and\n * remove (`run/dequeue`). While the thread rests stopped/errored, stranded\n * steer-lane entries list ahead of the queue (they dispatch first, as one\n * batch, so they carry Remove but no per-row Send now) and a Continue pill\n * steer-promotes the queue head — a steer entry moved onto its own lane is a\n * no-op, so a steer-only rest state gets no dead button.\n *\n * A row whose send has not settled yet (`isQueueEntryUnsettled` — this\n * client's optimistic fold, not a host-admitted lane entry) renders as\n * \"Sending…\" with no acting affordances: admission is server-side and can\n * still refuse the message. Failed run sends (`runs.failed`) list after the\n * lanes with Retry (`retryFailed`) and Discard (`discardFailed`).\n *\n * With `autoContinue`, an ordinary stranded settle promotes the queue head\n * once after `QUEUE_AUTO_CONTINUE_DELAY_MS`. User stops remain manual;\n * infrastructure pauses and retryable dispatch refusals recover on the server.\n *\n * Renders nothing on the legacy transport or when every lane is empty.\n */\n\nexport type StatewireQueueEvent =\n | {\n type: 'auto-continued';\n threadId: string | null;\n status: DeepAgentThreadStatus;\n headEntryId: string;\n }\n | {\n type: 'failed-send-action-raced';\n threadId: string | null;\n messageId: string;\n action: 'retry' | 'discard';\n error: string;\n };\n\nexport interface StatewireQueueRowContentContext {\n text: string;\n index: number;\n item: StatewireThread.RunsQueueEntry;\n}\n\nexport interface StatewireQueueRowMarkerContext {\n item: StatewireThread.RunsQueueEntry;\n lane: 'queue' | 'steer';\n index: number;\n /** This client's optimistic fold, not yet admitted by the host (renders \"Sending…\"). */\n isUnsettled: boolean;\n}\n\nexport interface StatewireQueueEditorContext {\n value: string;\n /** The entry being edited, for an editor that reads its metadata (e.g. the composer markdown it was sent from). */\n item: StatewireThread.RunsQueueEntry;\n onChange: (value: string) => void;\n /**\n * Save the edit; a blank or unchanged message sends nothing but closes the\n * editor. `metadata`, when given, replaces the entry's message metadata.\n */\n onSave: (text: string, options?: { metadata?: Record<string, unknown> }) => void;\n onCancel: () => void;\n}\n\nexport interface StatewireQueuedMessagesProps {\n /** Surface-styling overrides merged onto the default classes. */\n classNames?: {\n /** The tray container. */\n root?: string;\n /** The row list. */\n list?: string;\n };\n /**\n * Steer-promote a stranded queue head automatically after a settle (see the\n * component docs). Off by default: a host opts in to dispatching runs on the\n * user's behalf. Pass `{ delayMs }` to tune the grace before the promotion\n * (defaults to `QUEUE_AUTO_CONTINUE_DELAY_MS`).\n */\n autoContinue?: boolean | { delayMs?: number };\n /** Identifies the thread for once-per-entry auto-continue attempts and events. */\n threadId?: string | null;\n /** Telemetry sink for the tray's notable moments. */\n onEvent?: (event: StatewireQueueEvent) => void;\n /** Replace the plain-text row body (e.g. a mention-aware renderer). */\n renderContent?: (context: StatewireQueueRowContentContext) => ReactNode;\n /** Replace the plain textarea inline editor (e.g. the host's composer editor). */\n renderEditor?: (context: StatewireQueueEditorContext) => ReactNode;\n /**\n * Replace a lane row's leading marker (the bullet, or the spinner while the\n * send is unsettled) — e.g. the submitter's avatar on a shared thread.\n * Returning `null`/`undefined` keeps the default marker for that row.\n */\n renderRowMarker?: (context: StatewireQueueRowMarkerContext) => ReactNode;\n}\n\nexport const StatewireQueuedMessages: FC<StatewireQueuedMessagesProps> = (props) => {\n const extras = useAuiState((s) => s.thread.extras);\n if (!hasStatewireThreadExtras(extras)) return null;\n return <StatewireQueuedMessagesInner {...props} />;\n};\n\nconst StatewireQueuedMessagesInner: FC<StatewireQueuedMessagesProps> = ({\n classNames,\n autoContinue = false,\n threadId = null,\n onEvent,\n renderContent,\n renderEditor,\n renderRowMarker,\n}) => {\n // The QUEUE lane only: composer.queue prepends the steer lane, whose entries\n // already render in the message list. A non-empty queue implies a live run\n // entry (the host retires runId only once both lanes drain), so the row\n // controls can always send.\n const runs = useStatewireRuns();\n const { queue, steerQueue, runId } = runs;\n // `failed` joined the runs projection in react-statewire 0.24; a projection\n // without it (an older lib, a stubbed runs read) must not crash the tray.\n const failed = runs.failed ?? [];\n // The host's durable prioritized-id record: a raw path read (the selector\n // must return a stable reference), with the lookup set derived below.\n const rawPrioritizedQueueIds = useStatewireState(\n (state) => readDeepAgentStreamValues(state).prioritizedQueueIds,\n );\n const prioritizedQueueIds = useMemo(\n () => new Set(readPrioritizedQueueIds(rawPrioritizedQueueIds)),\n [rawPrioritizedQueueIds],\n );\n const status = useDeepAgentThreadStatus();\n const { isRunning, isContinuable } = queueLaneFlags(status);\n const aui = useAui();\n const sendCommand = useStatewireSendCommand();\n const listId = useId();\n const [expanded, setExpanded] = useState(true);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editingText, setEditingText] = useState('');\n // Head entries already auto-promoted once on this mount: an attempt whose\n // continue run dies and re-strands the SAME entry must not loop — the manual\n // Continue pill is the fallback for a repeatedly failing dispatch. Kept on\n // the tray (not the auto-continue child) so it survives the empty-lane\n // renders between a promotion and its outcome.\n const autoContinuedRef = useRef<Set<string>>(new Set());\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n\n const rows = buildStatewireQueueRows({ queue, steerQueue, isContinuable });\n // Continue promotes the QUEUE head only: a queue→steer move dispatches the\n // stranded steer lane plus this entry, while a steer entry moved onto its\n // own lane is a no-op.\n const queueHeadId = queue[0]?.id ?? null;\n const retryableRefusal = readRetryableRunRefusal(runs.error) !== null;\n const autoContinueOptions = autoContinue === true ? {} : autoContinue || null;\n\n /**\n * Re-send the entry under its own id on its own lane: the host replaces the\n * queued message's content in place, leaving its queue position and lane\n * untouched (a same-id send never dispatches).\n */\n const saveEdit = (\n item: StatewireThread.RunsQueueEntry,\n lane: 'queue' | 'steer',\n text: string,\n metadata?: Record<string, unknown>,\n ): void => {\n setEditingId(null);\n setEditingText('');\n const command = buildQueueEditCommand({ item, lane, runId, text, metadata });\n if (command !== null) sendCommand(command);\n };\n\n /**\n * Retry/Discard act on a rendered lane snapshot that can trail the session\n * record; acting on an entry statewire already dropped throws. Nothing is\n * lost in that race, so it is recorded instead of crashing the click.\n */\n const runFailedSendAction = ({\n action,\n messageId,\n run,\n }: {\n action: 'retry' | 'discard';\n messageId: string;\n run: (actions: StatewireFailedActions) => void;\n }): void => {\n try {\n run(requireStatewireFailedActions(aui.thread().getState().extras));\n } catch (error) {\n if (!(error instanceof Error) || !isFailedSendEntryRace(error)) throw error;\n onEvent?.({\n type: 'failed-send-action-raced',\n threadId,\n messageId,\n action,\n error: error.message,\n });\n }\n };\n\n if (rows.length === 0 && failed.length === 0) return null;\n\n const renderRowContent = (context: StatewireQueueRowContentContext): ReactNode =>\n renderContent ? renderContent(context) : <QueueRowText text={context.text} />;\n\n return (\n <section\n aria-label=\"Queued messages\"\n className={cn(\n 'aui-statewire-queue w-full rounded-xl border border-border/70 bg-muted/30 px-2 py-1.5',\n classNames?.root,\n )}\n >\n {autoContinueOptions ? (\n <QueueAutoContinue\n delayMs={autoContinueOptions.delayMs ?? QUEUE_AUTO_CONTINUE_DELAY_MS}\n queueHeadId={queueHeadId}\n retryableRefusal={retryableRefusal}\n isContinuable={isContinuable}\n status={status}\n threadId={threadId}\n editing={editingId !== null}\n continuedRef={autoContinuedRef}\n onEventRef={onEventRef}\n />\n ) : null}\n <div className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={() => setExpanded((value) => !value)}\n aria-expanded={expanded}\n aria-controls={listId}\n className=\"flex items-center gap-1 rounded px-1 py-1 font-medium text-muted-foreground text-xs hover:text-foreground\"\n >\n {expanded ? (\n <ChevronDownIcon className=\"size-3.5\" />\n ) : (\n <ChevronRightIcon className=\"size-3.5\" />\n )}\n {rows.length + failed.length} queued\n </button>\n {isContinuable && queueHeadId !== null ? (\n <ContinuePill\n ariaLabel=\"Continue with queued messages\"\n onClick={() => aui.composer.queueItem({ id: queueHeadId }).move({ lane: 'steer' })}\n />\n ) : null}\n </div>\n {expanded ? (\n <ul\n id={listId}\n className={cn('max-h-40 overflow-y-auto', classNames?.list)}\n data-testid=\"athena-statewire-queue\"\n >\n {rows.map(({ item, lane }, index) => {\n const text = queueEntryText(item.parts);\n const isUnsettled = isQueueEntryUnsettled(item);\n const isEditing = editingId === item.id;\n const showSendNow =\n !isUnsettled && showQueueRowSendNow({ lane, index, isRunning, isContinuable });\n const showPrioritize = !isUnsettled && lane === 'queue' && isRunning && runId !== null;\n const isPrioritized = prioritizedQueueIds.has(item.id);\n const marker = renderRowMarker?.({ item, lane, index, isUnsettled });\n const editorContext: StatewireQueueEditorContext = {\n value: editingText,\n item,\n onChange: setEditingText,\n onSave: (next, options) => saveEdit(item, lane, next, options?.metadata),\n onCancel: () => {\n setEditingId(null);\n setEditingText('');\n },\n };\n return (\n <li\n key={item.id}\n className=\"group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background\"\n >\n {marker != null ? (\n marker\n ) : isUnsettled ? (\n <Loader2Icon className=\"mt-0.5 size-3.5 shrink-0 animate-spin text-muted-foreground/60\" />\n ) : (\n <CircleIcon className=\"mt-0.5 size-3.5 shrink-0 text-muted-foreground/40\" />\n )}\n {isEditing ? (\n renderEditor ? (\n renderEditor(editorContext)\n ) : (\n <DefaultQueueEditor {...editorContext} />\n )\n ) : (\n renderRowContent({ text, index, item })\n )}\n <div\n className={cn('flex shrink-0 items-center gap-1', isEditing && 'hidden')}\n data-testid=\"statewire-queue-row-actions\"\n >\n {isUnsettled ? (\n <span\n className=\"px-1 text-[10px] text-muted-foreground\"\n data-testid=\"statewire-queued-message-sending\"\n >\n Sending…\n </span>\n ) : null}\n {showSendNow ? (\n <button\n type=\"button\"\n aria-label=\"Send now\"\n onClick={() =>\n aui.composer.queueItem({ id: item.id }).move({ lane: 'steer' })\n }\n className=\"inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5\"\n >\n <SendIcon className=\"size-2.5\" />\n Send now\n </button>\n ) : null}\n {showPrioritize ? (\n <button\n type=\"button\"\n aria-label={isPrioritized ? 'Remove priority' : 'Prioritize'}\n aria-pressed={isPrioritized}\n title={\n isPrioritized\n ? 'Remove priority'\n : 'Prioritize this message. Delivered as soon as the current step ends.'\n }\n onClick={() => {\n if (runId === null) return;\n sendCommand({\n type: 'run/prioritize',\n runId,\n messageId: item.id,\n priority: !isPrioritized,\n });\n }}\n className={cn(\n 'rounded p-1 transition-colors',\n isPrioritized\n ? 'text-amber-500 hover:text-amber-600'\n : 'text-muted-foreground hover:text-amber-500',\n )}\n >\n <ZapIcon className=\"size-3\" />\n </button>\n ) : null}\n {!isUnsettled ? (\n <button\n type=\"button\"\n aria-label=\"Edit queued message\"\n onClick={() => {\n setEditingId(item.id);\n setEditingText(text);\n }}\n className=\"rounded p-1 text-muted-foreground transition-colors hover:text-primary\"\n >\n <PencilIcon className=\"size-3\" />\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label=\"Remove queued message\"\n onClick={() => aui.composer.queueItem({ id: item.id }).remove()}\n className={cn(\n 'rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive',\n !showSendNow &&\n 'opacity-0 focus-visible:opacity-100 group-hover:opacity-100',\n )}\n >\n <Trash2Icon className=\"size-3\" />\n </button>\n </div>\n </li>\n );\n })}\n {failed.map((item, index) => (\n <li\n key={item.id}\n className=\"group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background\"\n >\n <AlertCircleIcon className=\"mt-0.5 size-3.5 shrink-0 text-destructive\" />\n {renderRowContent({\n text: queueEntryText(item.parts),\n index: rows.length + index,\n item,\n })}\n <div\n className=\"flex shrink-0 items-center gap-1\"\n data-testid=\"statewire-queue-row-actions\"\n >\n <span\n className=\"px-1 text-[10px] text-destructive\"\n title={describeQueueSendFailure(item.sendFailure)}\n >\n Failed to send\n </span>\n <button\n type=\"button\"\n aria-label=\"Retry failed message\"\n onClick={() =>\n runFailedSendAction({\n action: 'retry',\n messageId: item.id,\n run: (actions) => actions.retryFailed(item.id),\n })\n }\n className=\"inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5\"\n >\n <RotateCcwIcon className=\"size-2.5\" />\n Retry\n </button>\n <button\n type=\"button\"\n aria-label=\"Discard failed message\"\n onClick={() =>\n runFailedSendAction({\n action: 'discard',\n messageId: item.id,\n run: (actions) => actions.discardFailed(item.id),\n })\n }\n className=\"rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive\"\n >\n <Trash2Icon className=\"size-3\" />\n </button>\n </div>\n </li>\n ))}\n </ul>\n ) : null}\n </section>\n );\n};\n\n/** Promotes ordinary stranded queue heads once; infrastructure recovery stays server-owned. */\nconst QueueAutoContinue: FC<{\n delayMs: number;\n queueHeadId: string | null;\n retryableRefusal: boolean;\n isContinuable: boolean;\n status: DeepAgentThreadStatus;\n threadId: string | null;\n editing: boolean;\n continuedRef: MutableRefObject<Set<string>>;\n onEventRef: MutableRefObject<((event: StatewireQueueEvent) => void) | undefined>;\n}> = ({\n delayMs,\n queueHeadId,\n retryableRefusal,\n isContinuable,\n status,\n threadId,\n editing,\n continuedRef,\n onEventRef,\n}) => {\n const aui = useAui();\n // The settle that stranded the queue is described by the LAST message's run\n // marker (a marker deeper in history was superseded by a later send). The\n // selectors return primitives so the subscriptions stay shallow-stable.\n const lastMessageMarker = useAuiState((s) => {\n const last = s.thread.messages.at(-1);\n return last ? readRunMarkerFromSourceMessages(last)?.marker : undefined;\n });\n const lastMessageMarkerSource = useAuiState((s) => {\n const last = s.thread.messages.at(-1);\n return last ? readRunMarkerFromSourceMessages(last)?.source : undefined;\n });\n const userStopBlocks = userStopBlocksQueueAutoContinue({\n marker: lastMessageMarker,\n source: lastMessageMarkerSource,\n });\n\n useEffect(() => {\n if (\n !isContinuable ||\n userStopBlocks ||\n retryableRefusal ||\n isServerUpdateStopSource(lastMessageMarkerSource)\n ) return;\n // An open inline edit means the user is mid-revision on some row —\n // dispatching underneath them could send text they are about to change.\n if (editing) return;\n if (queueHeadId === null) return;\n const attemptKey = `${threadId ?? 'unknown'}:${queueHeadId}`;\n if (continuedRef.current.has(attemptKey)) return;\n const timeoutId = setTimeout(() => {\n continuedRef.current.add(attemptKey);\n onEventRef.current?.({ type: 'auto-continued', threadId, status, headEntryId: queueHeadId });\n aui.composer.queueItem({ id: queueHeadId }).move({ lane: 'steer' });\n }, delayMs);\n return () => clearTimeout(timeoutId);\n }, [\n continuedRef,\n aui,\n delayMs,\n editing,\n isContinuable,\n onEventRef,\n queueHeadId,\n retryableRefusal,\n lastMessageMarkerSource,\n status,\n threadId,\n userStopBlocks,\n ]);\n\n return null;\n};\n\n/**\n * The default row body: `[@name](…)` mentions render as chips, not raw\n * markdown links, and the body clamps to two lines. Show more / Show less\n * appears only when the rendered text overflows those two lines, so a short\n * message that wraps in a narrow tray is still caught and a short one gets no\n * dead control.\n */\nconst QueueRowText: FC<{ text: string }> = ({ text }) => {\n const bodyRef = useRef<HTMLParagraphElement>(null);\n const [expanded, setExpanded] = useState(false);\n const [overflows, setOverflows] = useState(false);\n\n useLayoutEffect(() => {\n const body = bodyRef.current;\n // Expanded text has no clamp to overflow; the toggle stays up to collapse it.\n if (!body || expanded) return;\n const measure = (): void => setOverflows(body.scrollHeight > body.clientHeight + 1);\n measure();\n if (typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(measure);\n observer.observe(body);\n return () => observer.disconnect();\n }, [text, expanded]);\n\n if (!text) {\n return <p className=\"min-w-0 flex-1 text-foreground text-xs\">Queued attachment</p>;\n }\n return (\n <div className=\"min-w-0 flex-1\">\n <p\n ref={bodyRef}\n className={cn(\n 'whitespace-pre-wrap break-words text-foreground text-xs leading-relaxed',\n !expanded && 'line-clamp-2',\n )}\n title={overflows && !expanded ? mentionsToPlainText(text) : undefined}\n >\n {parseMentionsInText(text)}\n </p>\n {overflows || expanded ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n onClick={() => setExpanded((value) => !value)}\n className=\"mt-0.5 font-medium text-[10px] text-muted-foreground hover:text-foreground\"\n >\n {expanded ? 'Show less' : 'Show more'}\n </button>\n ) : null}\n </div>\n );\n};\n\n/** Plain textarea editor: Enter saves, Shift+Enter breaks a line, Escape cancels. */\nconst DefaultQueueEditor: FC<StatewireQueueEditorContext> = ({\n value,\n onChange,\n onSave,\n onCancel,\n}) => {\n const canSave = value.trim().length > 0;\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>): void => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n if (canSave) onSave(value);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n onCancel();\n }\n };\n return (\n <div className=\"flex min-w-0 flex-1 items-start gap-1\">\n <textarea\n autoFocus\n aria-label=\"Edit message\"\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onKeyDown={handleKeyDown}\n rows={Math.min(6, Math.max(1, value.split('\\n').length))}\n className=\"min-w-0 flex-1 resize-none rounded-md border border-border bg-background px-2 py-1 text-foreground text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring/50\"\n />\n <button\n type=\"button\"\n aria-label=\"Save edit\"\n disabled={!canSave}\n onClick={() => onSave(value)}\n className={cn(\n 'rounded p-1 text-primary transition-colors hover:bg-primary/10',\n !canSave && 'cursor-not-allowed opacity-40',\n )}\n >\n <CheckIcon className=\"size-3.5\" />\n </button>\n <button\n type=\"button\"\n aria-label=\"Cancel edit\"\n onClick={onCancel}\n className=\"rounded p-1 text-muted-foreground transition-colors hover:bg-muted\"\n >\n <XIcon className=\"size-3.5\" />\n </button>\n </div>\n );\n};\n"],"names":["useAuiState","hasStatewireThreadExtras","jsx","useStatewireRuns","queue","useStatewireState","readDeepAgentStreamValues","useMemo","readPrioritizedQueueIds","useDeepAgentThreadStatus","queueLaneFlags","useAui","useStatewireSendCommand","useId","useState","useRef","buildStatewireQueueRows","readRetryableRunRefusal","buildQueueEditCommand","requireStatewireFailedActions","isFailedSendEntryRace","jsxs","cn","QUEUE_AUTO_CONTINUE_DELAY_MS","ChevronDownIcon","ChevronRightIcon","ContinuePill","queueEntryText","isQueueEntryUnsettled","showQueueRowSendNow","Loader2Icon","CircleIcon","SendIcon","ZapIcon","PencilIcon","Trash2Icon","AlertCircleIcon","describeQueueSendFailure","RotateCcwIcon","readRunMarkerFromSourceMessages","userStopBlocksQueueAutoContinue","useEffect","isServerUpdateStopSource","useLayoutEffect","mentionsToPlainText","CheckIcon","XIcon"],"mappings":"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"}
1
+ {"version":3,"file":"StatewireQueuedMessages.cjs","sources":["../../src/chat/StatewireQueuedMessages.tsx"],"sourcesContent":["import { useAui, useAuiState } from '@assistant-ui/react';\nimport type { StatewireThread } from '@assistant-ui/react-statewire';\nimport {\n useStatewireRuns,\n useStatewireSendCommand,\n useStatewireState,\n} from '@assistant-ui/react-statewire';\nimport {\n buildQueueEditCommand,\n buildStatewireQueueRows,\n type DeepAgentThreadStatus,\n describeQueueSendFailure,\n hasStatewireThreadExtras,\n isFailedSendEntryRace,\n isQueueEntryUnsettled,\n isServerUpdateStopSource,\n QUEUE_AUTO_CONTINUE_DELAY_MS,\n queueEntryText,\n queueLaneFlags,\n readDeepAgentStreamValues,\n readPrioritizedQueueIds,\n readRetryableRunRefusal,\n readRunMarkerFromSourceMessages,\n requireStatewireFailedActions,\n type StatewireFailedActions,\n showQueueRowSendNow,\n showQueueRowSteer,\n useDeepAgentThreadStatus,\n userStopBlocksQueueAutoContinue,\n} from '@athenaintel/agent-runtime';\nimport {\n AlertCircleIcon,\n CheckIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n CircleIcon,\n Loader2Icon,\n PencilIcon,\n RotateCcwIcon,\n SendIcon,\n ShipWheelIcon,\n Trash2Icon,\n XIcon,\n ZapIcon,\n} from 'lucide-react';\nimport {\n type FC,\n type KeyboardEvent,\n type MutableRefObject,\n type ReactNode,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { mentionsToPlainText, parseMentionsInText } from '../chat-ui/mentions/mention-chip';\nimport { ContinuePill } from '../chat-ui/messages/continue-pill';\nimport { cn } from '../lib/utils';\n\ndeclare module '@assistant-ui/core' {\n namespace Assistant {\n interface Commands {\n /**\n * The ⚡ on a queued row (`DeepAgentThread.run_prioritize`). With\n * `priority: true` the host moves the entry to the head of the queue\n * lane (behind entries prioritized before it), records it durably, and\n * the live run ends at its next model-call boundary — after the\n * in-flight tool chain, never mid-tool — so the settle delivers the\n * entry on top of the finished tool results instead of after the whole\n * turn. `priority: false` withdraws the request and leaves the entry\n * where it is.\n */\n runPrioritize: {\n type: 'run/prioritize';\n runId: string;\n messageId: string;\n priority: boolean;\n };\n /**\n * \"Steer\" on a queued row (`DeepAgentThread.run_steer_live`) — what\n * ChatGPT and Codex call Steer, versus Queue. The host moves the entry\n * to the steer lane and records it as a live steer, so the running\n * turn is NOT cancelled: at its next model call — after the in-flight\n * tool chain, never mid-tool — the run drains the entry into its own\n * context as a user turn and continues. Everything the run produces\n * from then on lands after the steered message. Mirrors `run/steer`'s\n * params (exactly one of `message` or `messageId`).\n */\n runSteerLive: {\n type: 'run/steer-live';\n runId: string;\n messageId: string;\n };\n }\n }\n}\n\n/**\n * The one queued-messages tray for the server-owned statewire queue and steer\n * lanes, mounted by the SDK's `AthenaChat`, the Chrome side panel, the Office\n * task pane, and Olympus.\n *\n * A message sent mid-run queues behind the active run. Rows offer \"Steer\"\n * (`run/steer-live` — the host parks the entry on the steer lane as a live\n * steer and the running turn drains it into its own context at its next model\n * call, so the run continues with it; ChatGPT's Steer versus Queue), \"Send now\"\n * (a steer-lane move — the host stops the run and dispatches it once the run\n * settles; on a stopped/errored thread the same move dispatches immediately),\n * \"Prioritize\" (`run/prioritize`, the ⚡ — the non-interrupting analog: the\n * live run ends at its next model-call boundary so the entry lands on top of\n * the finished tool results), inline edit (re-sent under the entry's own id\n * on its own lane, which the host folds as an in-place content update), and\n * remove (`run/dequeue`). While the thread rests stopped/errored, stranded\n * steer-lane entries list ahead of the queue (they dispatch first, as one\n * batch, so they carry Remove but no per-row Send now) and a Continue pill\n * steer-promotes the queue head — a steer entry moved onto its own lane is a\n * no-op, so a steer-only rest state gets no dead button.\n *\n * A row whose send has not settled yet (`isQueueEntryUnsettled` — this\n * client's optimistic fold, not a host-admitted lane entry) renders as\n * \"Sending…\" with no acting affordances: admission is server-side and can\n * still refuse the message. Failed run sends (`runs.failed`) list after the\n * lanes with Retry (`retryFailed`) and Discard (`discardFailed`).\n *\n * With `autoContinue`, an ordinary stranded settle promotes the queue head\n * once after `QUEUE_AUTO_CONTINUE_DELAY_MS`. User stops remain manual;\n * infrastructure pauses and retryable dispatch refusals recover on the server.\n *\n * Renders nothing on the legacy transport or when every lane is empty.\n */\n\nexport type StatewireQueueEvent =\n | {\n type: 'auto-continued';\n threadId: string | null;\n status: DeepAgentThreadStatus;\n headEntryId: string;\n }\n | {\n type: 'failed-send-action-raced';\n threadId: string | null;\n messageId: string;\n action: 'retry' | 'discard';\n error: string;\n };\n\nexport interface StatewireQueueRowContentContext {\n text: string;\n index: number;\n item: StatewireThread.RunsQueueEntry;\n}\n\nexport interface StatewireQueueRowMarkerContext {\n item: StatewireThread.RunsQueueEntry;\n lane: 'queue' | 'steer';\n index: number;\n /** This client's optimistic fold, not yet admitted by the host (renders \"Sending…\"). */\n isUnsettled: boolean;\n}\n\nexport interface StatewireQueueEditorContext {\n value: string;\n /** The entry being edited, for an editor that reads its metadata (e.g. the composer markdown it was sent from). */\n item: StatewireThread.RunsQueueEntry;\n onChange: (value: string) => void;\n /**\n * Save the edit; a blank or unchanged message sends nothing but closes the\n * editor. `metadata`, when given, replaces the entry's message metadata.\n */\n onSave: (text: string, options?: { metadata?: Record<string, unknown> }) => void;\n onCancel: () => void;\n}\n\nexport interface StatewireQueuedMessagesProps {\n /** Surface-styling overrides merged onto the default classes. */\n classNames?: {\n /** The tray container. */\n root?: string;\n /** The row list. */\n list?: string;\n };\n /**\n * Steer-promote a stranded queue head automatically after a settle (see the\n * component docs). Off by default: a host opts in to dispatching runs on the\n * user's behalf. Pass `{ delayMs }` to tune the grace before the promotion\n * (defaults to `QUEUE_AUTO_CONTINUE_DELAY_MS`).\n */\n autoContinue?: boolean | { delayMs?: number };\n /** Identifies the thread for once-per-entry auto-continue attempts and events. */\n threadId?: string | null;\n /** Telemetry sink for the tray's notable moments. */\n onEvent?: (event: StatewireQueueEvent) => void;\n /** Replace the plain-text row body (e.g. a mention-aware renderer). */\n renderContent?: (context: StatewireQueueRowContentContext) => ReactNode;\n /** Replace the plain textarea inline editor (e.g. the host's composer editor). */\n renderEditor?: (context: StatewireQueueEditorContext) => ReactNode;\n /**\n * Replace a lane row's leading marker (the bullet, or the spinner while the\n * send is unsettled) — e.g. the submitter's avatar on a shared thread.\n * Returning `null`/`undefined` keeps the default marker for that row.\n */\n renderRowMarker?: (context: StatewireQueueRowMarkerContext) => ReactNode;\n}\n\nexport const StatewireQueuedMessages: FC<StatewireQueuedMessagesProps> = (props) => {\n const extras = useAuiState((s) => s.thread.extras);\n if (!hasStatewireThreadExtras(extras)) return null;\n return <StatewireQueuedMessagesInner {...props} />;\n};\n\nconst StatewireQueuedMessagesInner: FC<StatewireQueuedMessagesProps> = ({\n classNames,\n autoContinue = false,\n threadId = null,\n onEvent,\n renderContent,\n renderEditor,\n renderRowMarker,\n}) => {\n // The QUEUE lane only: composer.queue prepends the steer lane, whose entries\n // already render in the message list. A non-empty queue implies a live run\n // entry (the host retires runId only once both lanes drain), so the row\n // controls can always send.\n const runs = useStatewireRuns();\n const { queue, steerQueue, runId } = runs;\n // `failed` joined the runs projection in react-statewire 0.24; a projection\n // without it (an older lib, a stubbed runs read) must not crash the tray.\n const failed = runs.failed ?? [];\n // The host's durable prioritized-id record: a raw path read (the selector\n // must return a stable reference), with the lookup set derived below.\n const rawPrioritizedQueueIds = useStatewireState(\n (state) => readDeepAgentStreamValues(state).prioritizedQueueIds,\n );\n const prioritizedQueueIds = useMemo(\n () => new Set(readPrioritizedQueueIds(rawPrioritizedQueueIds)),\n [rawPrioritizedQueueIds],\n );\n const status = useDeepAgentThreadStatus();\n const { isRunning, isContinuable } = queueLaneFlags(status);\n const aui = useAui();\n const sendCommand = useStatewireSendCommand();\n const listId = useId();\n const [expanded, setExpanded] = useState(true);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editingText, setEditingText] = useState('');\n // Head entries already auto-promoted once on this mount: an attempt whose\n // continue run dies and re-strands the SAME entry must not loop — the manual\n // Continue pill is the fallback for a repeatedly failing dispatch. Kept on\n // the tray (not the auto-continue child) so it survives the empty-lane\n // renders between a promotion and its outcome.\n const autoContinuedRef = useRef<Set<string>>(new Set());\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n\n const rows = buildStatewireQueueRows({ queue, steerQueue, isContinuable });\n // Continue promotes the QUEUE head only: a queue→steer move dispatches the\n // stranded steer lane plus this entry, while a steer entry moved onto its\n // own lane is a no-op.\n const queueHeadId = queue[0]?.id ?? null;\n const retryableRefusal = readRetryableRunRefusal(runs.error) !== null;\n const autoContinueOptions = autoContinue === true ? {} : autoContinue || null;\n\n /**\n * Re-send the entry under its own id on its own lane: the host replaces the\n * queued message's content in place, leaving its queue position and lane\n * untouched (a same-id send never dispatches).\n */\n const saveEdit = (\n item: StatewireThread.RunsQueueEntry,\n lane: 'queue' | 'steer',\n text: string,\n metadata?: Record<string, unknown>,\n ): void => {\n setEditingId(null);\n setEditingText('');\n const command = buildQueueEditCommand({ item, lane, runId, text, metadata });\n if (command !== null) sendCommand(command);\n };\n\n /**\n * Retry/Discard act on a rendered lane snapshot that can trail the session\n * record; acting on an entry statewire already dropped throws. Nothing is\n * lost in that race, so it is recorded instead of crashing the click.\n */\n const runFailedSendAction = ({\n action,\n messageId,\n run,\n }: {\n action: 'retry' | 'discard';\n messageId: string;\n run: (actions: StatewireFailedActions) => void;\n }): void => {\n try {\n run(requireStatewireFailedActions(aui.thread().getState().extras));\n } catch (error) {\n if (!(error instanceof Error) || !isFailedSendEntryRace(error)) throw error;\n onEvent?.({\n type: 'failed-send-action-raced',\n threadId,\n messageId,\n action,\n error: error.message,\n });\n }\n };\n\n if (rows.length === 0 && failed.length === 0) return null;\n\n const renderRowContent = (context: StatewireQueueRowContentContext): ReactNode =>\n renderContent ? renderContent(context) : <QueueRowText text={context.text} />;\n\n return (\n <section\n aria-label=\"Queued messages\"\n className={cn(\n 'aui-statewire-queue w-full rounded-xl border border-border/70 bg-muted/30 px-2 py-1.5',\n classNames?.root,\n )}\n >\n {autoContinueOptions ? (\n <QueueAutoContinue\n delayMs={autoContinueOptions.delayMs ?? QUEUE_AUTO_CONTINUE_DELAY_MS}\n queueHeadId={queueHeadId}\n retryableRefusal={retryableRefusal}\n isContinuable={isContinuable}\n status={status}\n threadId={threadId}\n editing={editingId !== null}\n continuedRef={autoContinuedRef}\n onEventRef={onEventRef}\n />\n ) : null}\n <div className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={() => setExpanded((value) => !value)}\n aria-expanded={expanded}\n aria-controls={listId}\n className=\"flex items-center gap-1 rounded px-1 py-1 font-medium text-muted-foreground text-xs hover:text-foreground\"\n >\n {expanded ? (\n <ChevronDownIcon className=\"size-3.5\" />\n ) : (\n <ChevronRightIcon className=\"size-3.5\" />\n )}\n {rows.length + failed.length} queued\n </button>\n {isContinuable && queueHeadId !== null ? (\n <ContinuePill\n ariaLabel=\"Continue with queued messages\"\n onClick={() => aui.composer.queueItem({ id: queueHeadId }).move({ lane: 'steer' })}\n />\n ) : null}\n </div>\n {expanded ? (\n <ul\n id={listId}\n className={cn('max-h-40 overflow-y-auto', classNames?.list)}\n data-testid=\"athena-statewire-queue\"\n >\n {rows.map(({ item, lane }, index) => {\n const text = queueEntryText(item.parts);\n const isUnsettled = isQueueEntryUnsettled(item);\n const isEditing = editingId === item.id;\n const showSendNow =\n !isUnsettled && showQueueRowSendNow({ lane, index, isRunning, isContinuable });\n const showPrioritize = !isUnsettled && lane === 'queue' && isRunning && runId !== null;\n const showSteer =\n !isUnsettled && runId !== null && showQueueRowSteer({ lane, isRunning });\n const isPrioritized = prioritizedQueueIds.has(item.id);\n const marker = renderRowMarker?.({ item, lane, index, isUnsettled });\n const editorContext: StatewireQueueEditorContext = {\n value: editingText,\n item,\n onChange: setEditingText,\n onSave: (next, options) => saveEdit(item, lane, next, options?.metadata),\n onCancel: () => {\n setEditingId(null);\n setEditingText('');\n },\n };\n return (\n <li\n key={item.id}\n className=\"group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background\"\n >\n {marker != null ? (\n marker\n ) : isUnsettled ? (\n <Loader2Icon className=\"mt-0.5 size-3.5 shrink-0 animate-spin text-muted-foreground/60\" />\n ) : (\n <CircleIcon className=\"mt-0.5 size-3.5 shrink-0 text-muted-foreground/40\" />\n )}\n {isEditing ? (\n renderEditor ? (\n renderEditor(editorContext)\n ) : (\n <DefaultQueueEditor {...editorContext} />\n )\n ) : (\n renderRowContent({ text, index, item })\n )}\n <div\n className={cn('flex shrink-0 items-center gap-1', isEditing && 'hidden')}\n data-testid=\"statewire-queue-row-actions\"\n >\n {isUnsettled ? (\n <span\n className=\"px-1 text-[10px] text-muted-foreground\"\n data-testid=\"statewire-queued-message-sending\"\n >\n Sending…\n </span>\n ) : null}\n {showSteer ? (\n <button\n type=\"button\"\n aria-label=\"Steer\"\n title=\"Steer the current response: folded into the running turn at its next step, without stopping it.\"\n onClick={() => {\n if (runId === null) return;\n sendCommand({ type: 'run/steer-live', runId, messageId: item.id });\n }}\n className=\"inline-flex items-center gap-1 rounded-full border border-border px-2 py-1 font-medium text-[10px] text-foreground/80 hover:bg-background hover:text-foreground\"\n >\n <ShipWheelIcon className=\"size-2.5\" />\n Steer\n </button>\n ) : null}\n {showSendNow ? (\n <button\n type=\"button\"\n aria-label=\"Send now\"\n onClick={() =>\n aui.composer.queueItem({ id: item.id }).move({ lane: 'steer' })\n }\n className=\"inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5\"\n >\n <SendIcon className=\"size-2.5\" />\n Send now\n </button>\n ) : null}\n {showPrioritize ? (\n <button\n type=\"button\"\n aria-label={isPrioritized ? 'Remove priority' : 'Prioritize'}\n aria-pressed={isPrioritized}\n title={\n isPrioritized\n ? 'Remove priority'\n : 'Prioritize this message. Delivered as soon as the current step ends.'\n }\n onClick={() => {\n if (runId === null) return;\n sendCommand({\n type: 'run/prioritize',\n runId,\n messageId: item.id,\n priority: !isPrioritized,\n });\n }}\n className={cn(\n 'rounded p-1 transition-colors',\n isPrioritized\n ? 'text-amber-500 hover:text-amber-600'\n : 'text-muted-foreground hover:text-amber-500',\n )}\n >\n <ZapIcon className=\"size-3\" />\n </button>\n ) : null}\n {!isUnsettled ? (\n <button\n type=\"button\"\n aria-label=\"Edit queued message\"\n onClick={() => {\n setEditingId(item.id);\n setEditingText(text);\n }}\n className=\"rounded p-1 text-muted-foreground transition-colors hover:text-primary\"\n >\n <PencilIcon className=\"size-3\" />\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label=\"Remove queued message\"\n onClick={() => aui.composer.queueItem({ id: item.id }).remove()}\n className={cn(\n 'rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive',\n !showSendNow &&\n 'opacity-0 focus-visible:opacity-100 group-hover:opacity-100',\n )}\n >\n <Trash2Icon className=\"size-3\" />\n </button>\n </div>\n </li>\n );\n })}\n {failed.map((item, index) => (\n <li\n key={item.id}\n className=\"group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background\"\n >\n <AlertCircleIcon className=\"mt-0.5 size-3.5 shrink-0 text-destructive\" />\n {renderRowContent({\n text: queueEntryText(item.parts),\n index: rows.length + index,\n item,\n })}\n <div\n className=\"flex shrink-0 items-center gap-1\"\n data-testid=\"statewire-queue-row-actions\"\n >\n <span\n className=\"px-1 text-[10px] text-destructive\"\n title={describeQueueSendFailure(item.sendFailure)}\n >\n Failed to send\n </span>\n <button\n type=\"button\"\n aria-label=\"Retry failed message\"\n onClick={() =>\n runFailedSendAction({\n action: 'retry',\n messageId: item.id,\n run: (actions) => actions.retryFailed(item.id),\n })\n }\n className=\"inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5\"\n >\n <RotateCcwIcon className=\"size-2.5\" />\n Retry\n </button>\n <button\n type=\"button\"\n aria-label=\"Discard failed message\"\n onClick={() =>\n runFailedSendAction({\n action: 'discard',\n messageId: item.id,\n run: (actions) => actions.discardFailed(item.id),\n })\n }\n className=\"rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive\"\n >\n <Trash2Icon className=\"size-3\" />\n </button>\n </div>\n </li>\n ))}\n </ul>\n ) : null}\n </section>\n );\n};\n\n/** Promotes ordinary stranded queue heads once; infrastructure recovery stays server-owned. */\nconst QueueAutoContinue: FC<{\n delayMs: number;\n queueHeadId: string | null;\n retryableRefusal: boolean;\n isContinuable: boolean;\n status: DeepAgentThreadStatus;\n threadId: string | null;\n editing: boolean;\n continuedRef: MutableRefObject<Set<string>>;\n onEventRef: MutableRefObject<((event: StatewireQueueEvent) => void) | undefined>;\n}> = ({\n delayMs,\n queueHeadId,\n retryableRefusal,\n isContinuable,\n status,\n threadId,\n editing,\n continuedRef,\n onEventRef,\n}) => {\n const aui = useAui();\n // The settle that stranded the queue is described by the LAST message's run\n // marker (a marker deeper in history was superseded by a later send). The\n // selectors return primitives so the subscriptions stay shallow-stable.\n const lastMessageMarker = useAuiState((s) => {\n const last = s.thread.messages.at(-1);\n return last ? readRunMarkerFromSourceMessages(last)?.marker : undefined;\n });\n const lastMessageMarkerSource = useAuiState((s) => {\n const last = s.thread.messages.at(-1);\n return last ? readRunMarkerFromSourceMessages(last)?.source : undefined;\n });\n const userStopBlocks = userStopBlocksQueueAutoContinue({\n marker: lastMessageMarker,\n source: lastMessageMarkerSource,\n });\n\n useEffect(() => {\n if (\n !isContinuable ||\n userStopBlocks ||\n retryableRefusal ||\n isServerUpdateStopSource(lastMessageMarkerSource)\n ) return;\n // An open inline edit means the user is mid-revision on some row —\n // dispatching underneath them could send text they are about to change.\n if (editing) return;\n if (queueHeadId === null) return;\n const attemptKey = `${threadId ?? 'unknown'}:${queueHeadId}`;\n if (continuedRef.current.has(attemptKey)) return;\n const timeoutId = setTimeout(() => {\n continuedRef.current.add(attemptKey);\n onEventRef.current?.({ type: 'auto-continued', threadId, status, headEntryId: queueHeadId });\n aui.composer.queueItem({ id: queueHeadId }).move({ lane: 'steer' });\n }, delayMs);\n return () => clearTimeout(timeoutId);\n }, [\n continuedRef,\n aui,\n delayMs,\n editing,\n isContinuable,\n onEventRef,\n queueHeadId,\n retryableRefusal,\n lastMessageMarkerSource,\n status,\n threadId,\n userStopBlocks,\n ]);\n\n return null;\n};\n\n/**\n * The default row body: `[@name](…)` mentions render as chips, not raw\n * markdown links, and the body clamps to two lines. Show more / Show less\n * appears only when the rendered text overflows those two lines, so a short\n * message that wraps in a narrow tray is still caught and a short one gets no\n * dead control.\n */\nconst QueueRowText: FC<{ text: string }> = ({ text }) => {\n const bodyRef = useRef<HTMLParagraphElement>(null);\n const [expanded, setExpanded] = useState(false);\n const [overflows, setOverflows] = useState(false);\n\n useLayoutEffect(() => {\n const body = bodyRef.current;\n // Expanded text has no clamp to overflow; the toggle stays up to collapse it.\n if (!body || expanded) return;\n const measure = (): void => setOverflows(body.scrollHeight > body.clientHeight + 1);\n measure();\n if (typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(measure);\n observer.observe(body);\n return () => observer.disconnect();\n }, [text, expanded]);\n\n if (!text) {\n return <p className=\"min-w-0 flex-1 text-foreground text-xs\">Queued attachment</p>;\n }\n return (\n <div className=\"min-w-0 flex-1\">\n <p\n ref={bodyRef}\n className={cn(\n 'whitespace-pre-wrap break-words text-foreground text-xs leading-relaxed',\n !expanded && 'line-clamp-2',\n )}\n title={overflows && !expanded ? mentionsToPlainText(text) : undefined}\n >\n {parseMentionsInText(text)}\n </p>\n {overflows || expanded ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n onClick={() => setExpanded((value) => !value)}\n className=\"mt-0.5 font-medium text-[10px] text-muted-foreground hover:text-foreground\"\n >\n {expanded ? 'Show less' : 'Show more'}\n </button>\n ) : null}\n </div>\n );\n};\n\n/** Plain textarea editor: Enter saves, Shift+Enter breaks a line, Escape cancels. */\nconst DefaultQueueEditor: FC<StatewireQueueEditorContext> = ({\n value,\n onChange,\n onSave,\n onCancel,\n}) => {\n const canSave = value.trim().length > 0;\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>): void => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n if (canSave) onSave(value);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n onCancel();\n }\n };\n return (\n <div className=\"flex min-w-0 flex-1 items-start gap-1\">\n <textarea\n autoFocus\n aria-label=\"Edit message\"\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onKeyDown={handleKeyDown}\n rows={Math.min(6, Math.max(1, value.split('\\n').length))}\n className=\"min-w-0 flex-1 resize-none rounded-md border border-border bg-background px-2 py-1 text-foreground text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring/50\"\n />\n <button\n type=\"button\"\n aria-label=\"Save edit\"\n disabled={!canSave}\n onClick={() => onSave(value)}\n className={cn(\n 'rounded p-1 text-primary transition-colors hover:bg-primary/10',\n !canSave && 'cursor-not-allowed opacity-40',\n )}\n >\n <CheckIcon className=\"size-3.5\" />\n </button>\n <button\n type=\"button\"\n aria-label=\"Cancel edit\"\n onClick={onCancel}\n className=\"rounded p-1 text-muted-foreground transition-colors hover:bg-muted\"\n >\n <XIcon className=\"size-3.5\" />\n </button>\n </div>\n );\n};\n"],"names":["useAuiState","hasStatewireThreadExtras","jsx","useStatewireRuns","queue","useStatewireState","readDeepAgentStreamValues","useMemo","readPrioritizedQueueIds","useDeepAgentThreadStatus","queueLaneFlags","useAui","useStatewireSendCommand","useId","useState","useRef","buildStatewireQueueRows","readRetryableRunRefusal","buildQueueEditCommand","requireStatewireFailedActions","isFailedSendEntryRace","jsxs","cn","QUEUE_AUTO_CONTINUE_DELAY_MS","ChevronDownIcon","ChevronRightIcon","ContinuePill","queueEntryText","isQueueEntryUnsettled","showQueueRowSendNow","showQueueRowSteer","Loader2Icon","CircleIcon","ShipWheelIcon","SendIcon","ZapIcon","PencilIcon","Trash2Icon","AlertCircleIcon","describeQueueSendFailure","RotateCcwIcon","readRunMarkerFromSourceMessages","userStopBlocksQueueAutoContinue","useEffect","isServerUpdateStopSource","useLayoutEffect","mentionsToPlainText","CheckIcon","XIcon"],"mappings":"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"}
@@ -20,6 +20,21 @@ declare module '@assistant-ui/core' {
20
20
  messageId: string;
21
21
  priority: boolean;
22
22
  };
23
+ /**
24
+ * "Steer" on a queued row (`DeepAgentThread.run_steer_live`) — what
25
+ * ChatGPT and Codex call Steer, versus Queue. The host moves the entry
26
+ * to the steer lane and records it as a live steer, so the running
27
+ * turn is NOT cancelled: at its next model call — after the in-flight
28
+ * tool chain, never mid-tool — the run drains the entry into its own
29
+ * context as a user turn and continues. Everything the run produces
30
+ * from then on lands after the steered message. Mirrors `run/steer`'s
31
+ * params (exactly one of `message` or `messageId`).
32
+ */
33
+ runSteerLive: {
34
+ type: 'run/steer-live';
35
+ runId: string;
36
+ messageId: string;
37
+ };
23
38
  }
24
39
  }
25
40
  }
@@ -28,7 +43,10 @@ declare module '@assistant-ui/core' {
28
43
  * lanes, mounted by the SDK's `AthenaChat`, the Chrome side panel, the Office
29
44
  * task pane, and Olympus.
30
45
  *
31
- * A message sent mid-run queues behind the active run. Rows offer "Send now"
46
+ * A message sent mid-run queues behind the active run. Rows offer "Steer"
47
+ * (`run/steer-live` — the host parks the entry on the steer lane as a live
48
+ * steer and the running turn drains it into its own context at its next model
49
+ * call, so the run continues with it; ChatGPT's Steer versus Queue), "Send now"
32
50
  * (a steer-lane move — the host stops the run and dispatches it once the run
33
51
  * settles; on a stopped/errored thread the same move dispatches immediately),
34
52
  * "Prioritize" (`run/prioritize`, the ⚡ — the non-interrupting analog: the
@@ -1,13 +1,13 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useAuiState, useAui } from "@assistant-ui/react";
3
3
  import { useStatewireRuns, useStatewireState, useStatewireSendCommand } from "@assistant-ui/react-statewire";
4
- import { ChevronDownIcon, ChevronRightIcon, Loader2Icon, CircleIcon, SendIcon, ZapIcon, PencilIcon, Trash2Icon, AlertCircleIcon, RotateCcwIcon, CheckIcon, XIcon } from "lucide-react";
4
+ import { ChevronDownIcon, ChevronRightIcon, Loader2Icon, CircleIcon, ShipWheelIcon, SendIcon, ZapIcon, PencilIcon, Trash2Icon, AlertCircleIcon, RotateCcwIcon, CheckIcon, XIcon } from "lucide-react";
5
5
  import { useMemo, useId, useState, useRef, useEffect, useLayoutEffect } from "react";
6
6
  import { parseMentionsInText, mentionsToPlainText } from "../chat-ui/mentions/mention-chip.js";
7
7
  import { ContinuePill } from "../chat-ui/messages/continue-pill.js";
8
8
  import { hasStatewireThreadExtras, requireStatewireFailedActions } from "../agent-runtime/src/thread-extras.js";
9
9
  import { readDeepAgentStreamValues } from "../agent-runtime/src/statewire-state.js";
10
- import { readPrioritizedQueueIds, buildStatewireQueueRows, QUEUE_AUTO_CONTINUE_DELAY_MS, queueEntryText, isQueueEntryUnsettled, describeQueueSendFailure, queueLaneFlags, showQueueRowSendNow, isFailedSendEntryRace, userStopBlocksQueueAutoContinue, buildQueueEditCommand } from "../agent-runtime/src/queue.js";
10
+ import { readPrioritizedQueueIds, buildStatewireQueueRows, QUEUE_AUTO_CONTINUE_DELAY_MS, queueEntryText, isQueueEntryUnsettled, describeQueueSendFailure, queueLaneFlags, showQueueRowSteer, showQueueRowSendNow, isFailedSendEntryRace, userStopBlocksQueueAutoContinue, buildQueueEditCommand } from "../agent-runtime/src/queue.js";
11
11
  import { useDeepAgentThreadStatus } from "../agent-runtime/src/thread-status.js";
12
12
  import { readRetryableRunRefusal } from "../agent-runtime/src/errors.js";
13
13
  import { readRunMarkerFromSourceMessages, isServerUpdateStopSource } from "../agent-runtime/src/messages.js";
@@ -138,6 +138,7 @@ const StatewireQueuedMessagesInner = ({
138
138
  const isEditing = editingId === item.id;
139
139
  const showSendNow = !isUnsettled && showQueueRowSendNow({ lane, index, isRunning, isContinuable });
140
140
  const showPrioritize = !isUnsettled && lane === "queue" && isRunning && runId !== null;
141
+ const showSteer = !isUnsettled && runId !== null && showQueueRowSteer({ lane, isRunning });
141
142
  const isPrioritized = prioritizedQueueIds.has(item.id);
142
143
  const marker = renderRowMarker == null ? void 0 : renderRowMarker({ item, lane, index, isUnsettled });
143
144
  const editorContext = {
@@ -171,6 +172,23 @@ const StatewireQueuedMessagesInner = ({
171
172
  children: "Sending…"
172
173
  }
173
174
  ) : null,
175
+ showSteer ? /* @__PURE__ */ jsxs(
176
+ "button",
177
+ {
178
+ type: "button",
179
+ "aria-label": "Steer",
180
+ title: "Steer the current response: folded into the running turn at its next step, without stopping it.",
181
+ onClick: () => {
182
+ if (runId === null) return;
183
+ sendCommand({ type: "run/steer-live", runId, messageId: item.id });
184
+ },
185
+ className: "inline-flex items-center gap-1 rounded-full border border-border px-2 py-1 font-medium text-[10px] text-foreground/80 hover:bg-background hover:text-foreground",
186
+ children: [
187
+ /* @__PURE__ */ jsx(ShipWheelIcon, { className: "size-2.5" }),
188
+ "Steer"
189
+ ]
190
+ }
191
+ ) : null,
174
192
  showSendNow ? /* @__PURE__ */ jsxs(
175
193
  "button",
176
194
  {
@@ -1 +1 @@
1
- {"version":3,"file":"StatewireQueuedMessages.js","sources":["../../src/chat/StatewireQueuedMessages.tsx"],"sourcesContent":["import { useAui, useAuiState } from '@assistant-ui/react';\nimport type { StatewireThread } from '@assistant-ui/react-statewire';\nimport {\n useStatewireRuns,\n useStatewireSendCommand,\n useStatewireState,\n} from '@assistant-ui/react-statewire';\nimport {\n buildQueueEditCommand,\n buildStatewireQueueRows,\n type DeepAgentThreadStatus,\n describeQueueSendFailure,\n hasStatewireThreadExtras,\n isFailedSendEntryRace,\n isQueueEntryUnsettled,\n isServerUpdateStopSource,\n QUEUE_AUTO_CONTINUE_DELAY_MS,\n queueEntryText,\n queueLaneFlags,\n readDeepAgentStreamValues,\n readPrioritizedQueueIds,\n readRetryableRunRefusal,\n readRunMarkerFromSourceMessages,\n requireStatewireFailedActions,\n type StatewireFailedActions,\n showQueueRowSendNow,\n useDeepAgentThreadStatus,\n userStopBlocksQueueAutoContinue,\n} from '@athenaintel/agent-runtime';\nimport {\n AlertCircleIcon,\n CheckIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n CircleIcon,\n Loader2Icon,\n PencilIcon,\n RotateCcwIcon,\n SendIcon,\n Trash2Icon,\n XIcon,\n ZapIcon,\n} from 'lucide-react';\nimport {\n type FC,\n type KeyboardEvent,\n type MutableRefObject,\n type ReactNode,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { mentionsToPlainText, parseMentionsInText } from '../chat-ui/mentions/mention-chip';\nimport { ContinuePill } from '../chat-ui/messages/continue-pill';\nimport { cn } from '../lib/utils';\n\ndeclare module '@assistant-ui/core' {\n namespace Assistant {\n interface Commands {\n /**\n * The ⚡ on a queued row (`DeepAgentThread.run_prioritize`). With\n * `priority: true` the host moves the entry to the head of the queue\n * lane (behind entries prioritized before it), records it durably, and\n * the live run ends at its next model-call boundary — after the\n * in-flight tool chain, never mid-tool — so the settle delivers the\n * entry on top of the finished tool results instead of after the whole\n * turn. `priority: false` withdraws the request and leaves the entry\n * where it is.\n */\n runPrioritize: {\n type: 'run/prioritize';\n runId: string;\n messageId: string;\n priority: boolean;\n };\n }\n }\n}\n\n/**\n * The one queued-messages tray for the server-owned statewire queue and steer\n * lanes, mounted by the SDK's `AthenaChat`, the Chrome side panel, the Office\n * task pane, and Olympus.\n *\n * A message sent mid-run queues behind the active run. Rows offer \"Send now\"\n * (a steer-lane move — the host stops the run and dispatches it once the run\n * settles; on a stopped/errored thread the same move dispatches immediately),\n * \"Prioritize\" (`run/prioritize`, the ⚡ — the non-interrupting analog: the\n * live run ends at its next model-call boundary so the entry lands on top of\n * the finished tool results), inline edit (re-sent under the entry's own id\n * on its own lane, which the host folds as an in-place content update), and\n * remove (`run/dequeue`). While the thread rests stopped/errored, stranded\n * steer-lane entries list ahead of the queue (they dispatch first, as one\n * batch, so they carry Remove but no per-row Send now) and a Continue pill\n * steer-promotes the queue head — a steer entry moved onto its own lane is a\n * no-op, so a steer-only rest state gets no dead button.\n *\n * A row whose send has not settled yet (`isQueueEntryUnsettled` — this\n * client's optimistic fold, not a host-admitted lane entry) renders as\n * \"Sending…\" with no acting affordances: admission is server-side and can\n * still refuse the message. Failed run sends (`runs.failed`) list after the\n * lanes with Retry (`retryFailed`) and Discard (`discardFailed`).\n *\n * With `autoContinue`, an ordinary stranded settle promotes the queue head\n * once after `QUEUE_AUTO_CONTINUE_DELAY_MS`. User stops remain manual;\n * infrastructure pauses and retryable dispatch refusals recover on the server.\n *\n * Renders nothing on the legacy transport or when every lane is empty.\n */\n\nexport type StatewireQueueEvent =\n | {\n type: 'auto-continued';\n threadId: string | null;\n status: DeepAgentThreadStatus;\n headEntryId: string;\n }\n | {\n type: 'failed-send-action-raced';\n threadId: string | null;\n messageId: string;\n action: 'retry' | 'discard';\n error: string;\n };\n\nexport interface StatewireQueueRowContentContext {\n text: string;\n index: number;\n item: StatewireThread.RunsQueueEntry;\n}\n\nexport interface StatewireQueueRowMarkerContext {\n item: StatewireThread.RunsQueueEntry;\n lane: 'queue' | 'steer';\n index: number;\n /** This client's optimistic fold, not yet admitted by the host (renders \"Sending…\"). */\n isUnsettled: boolean;\n}\n\nexport interface StatewireQueueEditorContext {\n value: string;\n /** The entry being edited, for an editor that reads its metadata (e.g. the composer markdown it was sent from). */\n item: StatewireThread.RunsQueueEntry;\n onChange: (value: string) => void;\n /**\n * Save the edit; a blank or unchanged message sends nothing but closes the\n * editor. `metadata`, when given, replaces the entry's message metadata.\n */\n onSave: (text: string, options?: { metadata?: Record<string, unknown> }) => void;\n onCancel: () => void;\n}\n\nexport interface StatewireQueuedMessagesProps {\n /** Surface-styling overrides merged onto the default classes. */\n classNames?: {\n /** The tray container. */\n root?: string;\n /** The row list. */\n list?: string;\n };\n /**\n * Steer-promote a stranded queue head automatically after a settle (see the\n * component docs). Off by default: a host opts in to dispatching runs on the\n * user's behalf. Pass `{ delayMs }` to tune the grace before the promotion\n * (defaults to `QUEUE_AUTO_CONTINUE_DELAY_MS`).\n */\n autoContinue?: boolean | { delayMs?: number };\n /** Identifies the thread for once-per-entry auto-continue attempts and events. */\n threadId?: string | null;\n /** Telemetry sink for the tray's notable moments. */\n onEvent?: (event: StatewireQueueEvent) => void;\n /** Replace the plain-text row body (e.g. a mention-aware renderer). */\n renderContent?: (context: StatewireQueueRowContentContext) => ReactNode;\n /** Replace the plain textarea inline editor (e.g. the host's composer editor). */\n renderEditor?: (context: StatewireQueueEditorContext) => ReactNode;\n /**\n * Replace a lane row's leading marker (the bullet, or the spinner while the\n * send is unsettled) — e.g. the submitter's avatar on a shared thread.\n * Returning `null`/`undefined` keeps the default marker for that row.\n */\n renderRowMarker?: (context: StatewireQueueRowMarkerContext) => ReactNode;\n}\n\nexport const StatewireQueuedMessages: FC<StatewireQueuedMessagesProps> = (props) => {\n const extras = useAuiState((s) => s.thread.extras);\n if (!hasStatewireThreadExtras(extras)) return null;\n return <StatewireQueuedMessagesInner {...props} />;\n};\n\nconst StatewireQueuedMessagesInner: FC<StatewireQueuedMessagesProps> = ({\n classNames,\n autoContinue = false,\n threadId = null,\n onEvent,\n renderContent,\n renderEditor,\n renderRowMarker,\n}) => {\n // The QUEUE lane only: composer.queue prepends the steer lane, whose entries\n // already render in the message list. A non-empty queue implies a live run\n // entry (the host retires runId only once both lanes drain), so the row\n // controls can always send.\n const runs = useStatewireRuns();\n const { queue, steerQueue, runId } = runs;\n // `failed` joined the runs projection in react-statewire 0.24; a projection\n // without it (an older lib, a stubbed runs read) must not crash the tray.\n const failed = runs.failed ?? [];\n // The host's durable prioritized-id record: a raw path read (the selector\n // must return a stable reference), with the lookup set derived below.\n const rawPrioritizedQueueIds = useStatewireState(\n (state) => readDeepAgentStreamValues(state).prioritizedQueueIds,\n );\n const prioritizedQueueIds = useMemo(\n () => new Set(readPrioritizedQueueIds(rawPrioritizedQueueIds)),\n [rawPrioritizedQueueIds],\n );\n const status = useDeepAgentThreadStatus();\n const { isRunning, isContinuable } = queueLaneFlags(status);\n const aui = useAui();\n const sendCommand = useStatewireSendCommand();\n const listId = useId();\n const [expanded, setExpanded] = useState(true);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editingText, setEditingText] = useState('');\n // Head entries already auto-promoted once on this mount: an attempt whose\n // continue run dies and re-strands the SAME entry must not loop — the manual\n // Continue pill is the fallback for a repeatedly failing dispatch. Kept on\n // the tray (not the auto-continue child) so it survives the empty-lane\n // renders between a promotion and its outcome.\n const autoContinuedRef = useRef<Set<string>>(new Set());\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n\n const rows = buildStatewireQueueRows({ queue, steerQueue, isContinuable });\n // Continue promotes the QUEUE head only: a queue→steer move dispatches the\n // stranded steer lane plus this entry, while a steer entry moved onto its\n // own lane is a no-op.\n const queueHeadId = queue[0]?.id ?? null;\n const retryableRefusal = readRetryableRunRefusal(runs.error) !== null;\n const autoContinueOptions = autoContinue === true ? {} : autoContinue || null;\n\n /**\n * Re-send the entry under its own id on its own lane: the host replaces the\n * queued message's content in place, leaving its queue position and lane\n * untouched (a same-id send never dispatches).\n */\n const saveEdit = (\n item: StatewireThread.RunsQueueEntry,\n lane: 'queue' | 'steer',\n text: string,\n metadata?: Record<string, unknown>,\n ): void => {\n setEditingId(null);\n setEditingText('');\n const command = buildQueueEditCommand({ item, lane, runId, text, metadata });\n if (command !== null) sendCommand(command);\n };\n\n /**\n * Retry/Discard act on a rendered lane snapshot that can trail the session\n * record; acting on an entry statewire already dropped throws. Nothing is\n * lost in that race, so it is recorded instead of crashing the click.\n */\n const runFailedSendAction = ({\n action,\n messageId,\n run,\n }: {\n action: 'retry' | 'discard';\n messageId: string;\n run: (actions: StatewireFailedActions) => void;\n }): void => {\n try {\n run(requireStatewireFailedActions(aui.thread().getState().extras));\n } catch (error) {\n if (!(error instanceof Error) || !isFailedSendEntryRace(error)) throw error;\n onEvent?.({\n type: 'failed-send-action-raced',\n threadId,\n messageId,\n action,\n error: error.message,\n });\n }\n };\n\n if (rows.length === 0 && failed.length === 0) return null;\n\n const renderRowContent = (context: StatewireQueueRowContentContext): ReactNode =>\n renderContent ? renderContent(context) : <QueueRowText text={context.text} />;\n\n return (\n <section\n aria-label=\"Queued messages\"\n className={cn(\n 'aui-statewire-queue w-full rounded-xl border border-border/70 bg-muted/30 px-2 py-1.5',\n classNames?.root,\n )}\n >\n {autoContinueOptions ? (\n <QueueAutoContinue\n delayMs={autoContinueOptions.delayMs ?? QUEUE_AUTO_CONTINUE_DELAY_MS}\n queueHeadId={queueHeadId}\n retryableRefusal={retryableRefusal}\n isContinuable={isContinuable}\n status={status}\n threadId={threadId}\n editing={editingId !== null}\n continuedRef={autoContinuedRef}\n onEventRef={onEventRef}\n />\n ) : null}\n <div className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={() => setExpanded((value) => !value)}\n aria-expanded={expanded}\n aria-controls={listId}\n className=\"flex items-center gap-1 rounded px-1 py-1 font-medium text-muted-foreground text-xs hover:text-foreground\"\n >\n {expanded ? (\n <ChevronDownIcon className=\"size-3.5\" />\n ) : (\n <ChevronRightIcon className=\"size-3.5\" />\n )}\n {rows.length + failed.length} queued\n </button>\n {isContinuable && queueHeadId !== null ? (\n <ContinuePill\n ariaLabel=\"Continue with queued messages\"\n onClick={() => aui.composer.queueItem({ id: queueHeadId }).move({ lane: 'steer' })}\n />\n ) : null}\n </div>\n {expanded ? (\n <ul\n id={listId}\n className={cn('max-h-40 overflow-y-auto', classNames?.list)}\n data-testid=\"athena-statewire-queue\"\n >\n {rows.map(({ item, lane }, index) => {\n const text = queueEntryText(item.parts);\n const isUnsettled = isQueueEntryUnsettled(item);\n const isEditing = editingId === item.id;\n const showSendNow =\n !isUnsettled && showQueueRowSendNow({ lane, index, isRunning, isContinuable });\n const showPrioritize = !isUnsettled && lane === 'queue' && isRunning && runId !== null;\n const isPrioritized = prioritizedQueueIds.has(item.id);\n const marker = renderRowMarker?.({ item, lane, index, isUnsettled });\n const editorContext: StatewireQueueEditorContext = {\n value: editingText,\n item,\n onChange: setEditingText,\n onSave: (next, options) => saveEdit(item, lane, next, options?.metadata),\n onCancel: () => {\n setEditingId(null);\n setEditingText('');\n },\n };\n return (\n <li\n key={item.id}\n className=\"group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background\"\n >\n {marker != null ? (\n marker\n ) : isUnsettled ? (\n <Loader2Icon className=\"mt-0.5 size-3.5 shrink-0 animate-spin text-muted-foreground/60\" />\n ) : (\n <CircleIcon className=\"mt-0.5 size-3.5 shrink-0 text-muted-foreground/40\" />\n )}\n {isEditing ? (\n renderEditor ? (\n renderEditor(editorContext)\n ) : (\n <DefaultQueueEditor {...editorContext} />\n )\n ) : (\n renderRowContent({ text, index, item })\n )}\n <div\n className={cn('flex shrink-0 items-center gap-1', isEditing && 'hidden')}\n data-testid=\"statewire-queue-row-actions\"\n >\n {isUnsettled ? (\n <span\n className=\"px-1 text-[10px] text-muted-foreground\"\n data-testid=\"statewire-queued-message-sending\"\n >\n Sending…\n </span>\n ) : null}\n {showSendNow ? (\n <button\n type=\"button\"\n aria-label=\"Send now\"\n onClick={() =>\n aui.composer.queueItem({ id: item.id }).move({ lane: 'steer' })\n }\n className=\"inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5\"\n >\n <SendIcon className=\"size-2.5\" />\n Send now\n </button>\n ) : null}\n {showPrioritize ? (\n <button\n type=\"button\"\n aria-label={isPrioritized ? 'Remove priority' : 'Prioritize'}\n aria-pressed={isPrioritized}\n title={\n isPrioritized\n ? 'Remove priority'\n : 'Prioritize this message. Delivered as soon as the current step ends.'\n }\n onClick={() => {\n if (runId === null) return;\n sendCommand({\n type: 'run/prioritize',\n runId,\n messageId: item.id,\n priority: !isPrioritized,\n });\n }}\n className={cn(\n 'rounded p-1 transition-colors',\n isPrioritized\n ? 'text-amber-500 hover:text-amber-600'\n : 'text-muted-foreground hover:text-amber-500',\n )}\n >\n <ZapIcon className=\"size-3\" />\n </button>\n ) : null}\n {!isUnsettled ? (\n <button\n type=\"button\"\n aria-label=\"Edit queued message\"\n onClick={() => {\n setEditingId(item.id);\n setEditingText(text);\n }}\n className=\"rounded p-1 text-muted-foreground transition-colors hover:text-primary\"\n >\n <PencilIcon className=\"size-3\" />\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label=\"Remove queued message\"\n onClick={() => aui.composer.queueItem({ id: item.id }).remove()}\n className={cn(\n 'rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive',\n !showSendNow &&\n 'opacity-0 focus-visible:opacity-100 group-hover:opacity-100',\n )}\n >\n <Trash2Icon className=\"size-3\" />\n </button>\n </div>\n </li>\n );\n })}\n {failed.map((item, index) => (\n <li\n key={item.id}\n className=\"group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background\"\n >\n <AlertCircleIcon className=\"mt-0.5 size-3.5 shrink-0 text-destructive\" />\n {renderRowContent({\n text: queueEntryText(item.parts),\n index: rows.length + index,\n item,\n })}\n <div\n className=\"flex shrink-0 items-center gap-1\"\n data-testid=\"statewire-queue-row-actions\"\n >\n <span\n className=\"px-1 text-[10px] text-destructive\"\n title={describeQueueSendFailure(item.sendFailure)}\n >\n Failed to send\n </span>\n <button\n type=\"button\"\n aria-label=\"Retry failed message\"\n onClick={() =>\n runFailedSendAction({\n action: 'retry',\n messageId: item.id,\n run: (actions) => actions.retryFailed(item.id),\n })\n }\n className=\"inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5\"\n >\n <RotateCcwIcon className=\"size-2.5\" />\n Retry\n </button>\n <button\n type=\"button\"\n aria-label=\"Discard failed message\"\n onClick={() =>\n runFailedSendAction({\n action: 'discard',\n messageId: item.id,\n run: (actions) => actions.discardFailed(item.id),\n })\n }\n className=\"rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive\"\n >\n <Trash2Icon className=\"size-3\" />\n </button>\n </div>\n </li>\n ))}\n </ul>\n ) : null}\n </section>\n );\n};\n\n/** Promotes ordinary stranded queue heads once; infrastructure recovery stays server-owned. */\nconst QueueAutoContinue: FC<{\n delayMs: number;\n queueHeadId: string | null;\n retryableRefusal: boolean;\n isContinuable: boolean;\n status: DeepAgentThreadStatus;\n threadId: string | null;\n editing: boolean;\n continuedRef: MutableRefObject<Set<string>>;\n onEventRef: MutableRefObject<((event: StatewireQueueEvent) => void) | undefined>;\n}> = ({\n delayMs,\n queueHeadId,\n retryableRefusal,\n isContinuable,\n status,\n threadId,\n editing,\n continuedRef,\n onEventRef,\n}) => {\n const aui = useAui();\n // The settle that stranded the queue is described by the LAST message's run\n // marker (a marker deeper in history was superseded by a later send). The\n // selectors return primitives so the subscriptions stay shallow-stable.\n const lastMessageMarker = useAuiState((s) => {\n const last = s.thread.messages.at(-1);\n return last ? readRunMarkerFromSourceMessages(last)?.marker : undefined;\n });\n const lastMessageMarkerSource = useAuiState((s) => {\n const last = s.thread.messages.at(-1);\n return last ? readRunMarkerFromSourceMessages(last)?.source : undefined;\n });\n const userStopBlocks = userStopBlocksQueueAutoContinue({\n marker: lastMessageMarker,\n source: lastMessageMarkerSource,\n });\n\n useEffect(() => {\n if (\n !isContinuable ||\n userStopBlocks ||\n retryableRefusal ||\n isServerUpdateStopSource(lastMessageMarkerSource)\n ) return;\n // An open inline edit means the user is mid-revision on some row —\n // dispatching underneath them could send text they are about to change.\n if (editing) return;\n if (queueHeadId === null) return;\n const attemptKey = `${threadId ?? 'unknown'}:${queueHeadId}`;\n if (continuedRef.current.has(attemptKey)) return;\n const timeoutId = setTimeout(() => {\n continuedRef.current.add(attemptKey);\n onEventRef.current?.({ type: 'auto-continued', threadId, status, headEntryId: queueHeadId });\n aui.composer.queueItem({ id: queueHeadId }).move({ lane: 'steer' });\n }, delayMs);\n return () => clearTimeout(timeoutId);\n }, [\n continuedRef,\n aui,\n delayMs,\n editing,\n isContinuable,\n onEventRef,\n queueHeadId,\n retryableRefusal,\n lastMessageMarkerSource,\n status,\n threadId,\n userStopBlocks,\n ]);\n\n return null;\n};\n\n/**\n * The default row body: `[@name](…)` mentions render as chips, not raw\n * markdown links, and the body clamps to two lines. Show more / Show less\n * appears only when the rendered text overflows those two lines, so a short\n * message that wraps in a narrow tray is still caught and a short one gets no\n * dead control.\n */\nconst QueueRowText: FC<{ text: string }> = ({ text }) => {\n const bodyRef = useRef<HTMLParagraphElement>(null);\n const [expanded, setExpanded] = useState(false);\n const [overflows, setOverflows] = useState(false);\n\n useLayoutEffect(() => {\n const body = bodyRef.current;\n // Expanded text has no clamp to overflow; the toggle stays up to collapse it.\n if (!body || expanded) return;\n const measure = (): void => setOverflows(body.scrollHeight > body.clientHeight + 1);\n measure();\n if (typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(measure);\n observer.observe(body);\n return () => observer.disconnect();\n }, [text, expanded]);\n\n if (!text) {\n return <p className=\"min-w-0 flex-1 text-foreground text-xs\">Queued attachment</p>;\n }\n return (\n <div className=\"min-w-0 flex-1\">\n <p\n ref={bodyRef}\n className={cn(\n 'whitespace-pre-wrap break-words text-foreground text-xs leading-relaxed',\n !expanded && 'line-clamp-2',\n )}\n title={overflows && !expanded ? mentionsToPlainText(text) : undefined}\n >\n {parseMentionsInText(text)}\n </p>\n {overflows || expanded ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n onClick={() => setExpanded((value) => !value)}\n className=\"mt-0.5 font-medium text-[10px] text-muted-foreground hover:text-foreground\"\n >\n {expanded ? 'Show less' : 'Show more'}\n </button>\n ) : null}\n </div>\n );\n};\n\n/** Plain textarea editor: Enter saves, Shift+Enter breaks a line, Escape cancels. */\nconst DefaultQueueEditor: FC<StatewireQueueEditorContext> = ({\n value,\n onChange,\n onSave,\n onCancel,\n}) => {\n const canSave = value.trim().length > 0;\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>): void => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n if (canSave) onSave(value);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n onCancel();\n }\n };\n return (\n <div className=\"flex min-w-0 flex-1 items-start gap-1\">\n <textarea\n autoFocus\n aria-label=\"Edit message\"\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onKeyDown={handleKeyDown}\n rows={Math.min(6, Math.max(1, value.split('\\n').length))}\n className=\"min-w-0 flex-1 resize-none rounded-md border border-border bg-background px-2 py-1 text-foreground text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring/50\"\n />\n <button\n type=\"button\"\n aria-label=\"Save edit\"\n disabled={!canSave}\n onClick={() => onSave(value)}\n className={cn(\n 'rounded p-1 text-primary transition-colors hover:bg-primary/10',\n !canSave && 'cursor-not-allowed opacity-40',\n )}\n >\n <CheckIcon className=\"size-3.5\" />\n </button>\n <button\n type=\"button\"\n aria-label=\"Cancel edit\"\n onClick={onCancel}\n className=\"rounded p-1 text-muted-foreground transition-colors hover:bg-muted\"\n >\n <XIcon className=\"size-3.5\" />\n </button>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StatewireQueuedMessages.js","sources":["../../src/chat/StatewireQueuedMessages.tsx"],"sourcesContent":["import { useAui, useAuiState } from '@assistant-ui/react';\nimport type { StatewireThread } from '@assistant-ui/react-statewire';\nimport {\n useStatewireRuns,\n useStatewireSendCommand,\n useStatewireState,\n} from '@assistant-ui/react-statewire';\nimport {\n buildQueueEditCommand,\n buildStatewireQueueRows,\n type DeepAgentThreadStatus,\n describeQueueSendFailure,\n hasStatewireThreadExtras,\n isFailedSendEntryRace,\n isQueueEntryUnsettled,\n isServerUpdateStopSource,\n QUEUE_AUTO_CONTINUE_DELAY_MS,\n queueEntryText,\n queueLaneFlags,\n readDeepAgentStreamValues,\n readPrioritizedQueueIds,\n readRetryableRunRefusal,\n readRunMarkerFromSourceMessages,\n requireStatewireFailedActions,\n type StatewireFailedActions,\n showQueueRowSendNow,\n showQueueRowSteer,\n useDeepAgentThreadStatus,\n userStopBlocksQueueAutoContinue,\n} from '@athenaintel/agent-runtime';\nimport {\n AlertCircleIcon,\n CheckIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n CircleIcon,\n Loader2Icon,\n PencilIcon,\n RotateCcwIcon,\n SendIcon,\n ShipWheelIcon,\n Trash2Icon,\n XIcon,\n ZapIcon,\n} from 'lucide-react';\nimport {\n type FC,\n type KeyboardEvent,\n type MutableRefObject,\n type ReactNode,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { mentionsToPlainText, parseMentionsInText } from '../chat-ui/mentions/mention-chip';\nimport { ContinuePill } from '../chat-ui/messages/continue-pill';\nimport { cn } from '../lib/utils';\n\ndeclare module '@assistant-ui/core' {\n namespace Assistant {\n interface Commands {\n /**\n * The ⚡ on a queued row (`DeepAgentThread.run_prioritize`). With\n * `priority: true` the host moves the entry to the head of the queue\n * lane (behind entries prioritized before it), records it durably, and\n * the live run ends at its next model-call boundary — after the\n * in-flight tool chain, never mid-tool — so the settle delivers the\n * entry on top of the finished tool results instead of after the whole\n * turn. `priority: false` withdraws the request and leaves the entry\n * where it is.\n */\n runPrioritize: {\n type: 'run/prioritize';\n runId: string;\n messageId: string;\n priority: boolean;\n };\n /**\n * \"Steer\" on a queued row (`DeepAgentThread.run_steer_live`) — what\n * ChatGPT and Codex call Steer, versus Queue. The host moves the entry\n * to the steer lane and records it as a live steer, so the running\n * turn is NOT cancelled: at its next model call — after the in-flight\n * tool chain, never mid-tool — the run drains the entry into its own\n * context as a user turn and continues. Everything the run produces\n * from then on lands after the steered message. Mirrors `run/steer`'s\n * params (exactly one of `message` or `messageId`).\n */\n runSteerLive: {\n type: 'run/steer-live';\n runId: string;\n messageId: string;\n };\n }\n }\n}\n\n/**\n * The one queued-messages tray for the server-owned statewire queue and steer\n * lanes, mounted by the SDK's `AthenaChat`, the Chrome side panel, the Office\n * task pane, and Olympus.\n *\n * A message sent mid-run queues behind the active run. Rows offer \"Steer\"\n * (`run/steer-live` — the host parks the entry on the steer lane as a live\n * steer and the running turn drains it into its own context at its next model\n * call, so the run continues with it; ChatGPT's Steer versus Queue), \"Send now\"\n * (a steer-lane move — the host stops the run and dispatches it once the run\n * settles; on a stopped/errored thread the same move dispatches immediately),\n * \"Prioritize\" (`run/prioritize`, the ⚡ — the non-interrupting analog: the\n * live run ends at its next model-call boundary so the entry lands on top of\n * the finished tool results), inline edit (re-sent under the entry's own id\n * on its own lane, which the host folds as an in-place content update), and\n * remove (`run/dequeue`). While the thread rests stopped/errored, stranded\n * steer-lane entries list ahead of the queue (they dispatch first, as one\n * batch, so they carry Remove but no per-row Send now) and a Continue pill\n * steer-promotes the queue head — a steer entry moved onto its own lane is a\n * no-op, so a steer-only rest state gets no dead button.\n *\n * A row whose send has not settled yet (`isQueueEntryUnsettled` — this\n * client's optimistic fold, not a host-admitted lane entry) renders as\n * \"Sending…\" with no acting affordances: admission is server-side and can\n * still refuse the message. Failed run sends (`runs.failed`) list after the\n * lanes with Retry (`retryFailed`) and Discard (`discardFailed`).\n *\n * With `autoContinue`, an ordinary stranded settle promotes the queue head\n * once after `QUEUE_AUTO_CONTINUE_DELAY_MS`. User stops remain manual;\n * infrastructure pauses and retryable dispatch refusals recover on the server.\n *\n * Renders nothing on the legacy transport or when every lane is empty.\n */\n\nexport type StatewireQueueEvent =\n | {\n type: 'auto-continued';\n threadId: string | null;\n status: DeepAgentThreadStatus;\n headEntryId: string;\n }\n | {\n type: 'failed-send-action-raced';\n threadId: string | null;\n messageId: string;\n action: 'retry' | 'discard';\n error: string;\n };\n\nexport interface StatewireQueueRowContentContext {\n text: string;\n index: number;\n item: StatewireThread.RunsQueueEntry;\n}\n\nexport interface StatewireQueueRowMarkerContext {\n item: StatewireThread.RunsQueueEntry;\n lane: 'queue' | 'steer';\n index: number;\n /** This client's optimistic fold, not yet admitted by the host (renders \"Sending…\"). */\n isUnsettled: boolean;\n}\n\nexport interface StatewireQueueEditorContext {\n value: string;\n /** The entry being edited, for an editor that reads its metadata (e.g. the composer markdown it was sent from). */\n item: StatewireThread.RunsQueueEntry;\n onChange: (value: string) => void;\n /**\n * Save the edit; a blank or unchanged message sends nothing but closes the\n * editor. `metadata`, when given, replaces the entry's message metadata.\n */\n onSave: (text: string, options?: { metadata?: Record<string, unknown> }) => void;\n onCancel: () => void;\n}\n\nexport interface StatewireQueuedMessagesProps {\n /** Surface-styling overrides merged onto the default classes. */\n classNames?: {\n /** The tray container. */\n root?: string;\n /** The row list. */\n list?: string;\n };\n /**\n * Steer-promote a stranded queue head automatically after a settle (see the\n * component docs). Off by default: a host opts in to dispatching runs on the\n * user's behalf. Pass `{ delayMs }` to tune the grace before the promotion\n * (defaults to `QUEUE_AUTO_CONTINUE_DELAY_MS`).\n */\n autoContinue?: boolean | { delayMs?: number };\n /** Identifies the thread for once-per-entry auto-continue attempts and events. */\n threadId?: string | null;\n /** Telemetry sink for the tray's notable moments. */\n onEvent?: (event: StatewireQueueEvent) => void;\n /** Replace the plain-text row body (e.g. a mention-aware renderer). */\n renderContent?: (context: StatewireQueueRowContentContext) => ReactNode;\n /** Replace the plain textarea inline editor (e.g. the host's composer editor). */\n renderEditor?: (context: StatewireQueueEditorContext) => ReactNode;\n /**\n * Replace a lane row's leading marker (the bullet, or the spinner while the\n * send is unsettled) — e.g. the submitter's avatar on a shared thread.\n * Returning `null`/`undefined` keeps the default marker for that row.\n */\n renderRowMarker?: (context: StatewireQueueRowMarkerContext) => ReactNode;\n}\n\nexport const StatewireQueuedMessages: FC<StatewireQueuedMessagesProps> = (props) => {\n const extras = useAuiState((s) => s.thread.extras);\n if (!hasStatewireThreadExtras(extras)) return null;\n return <StatewireQueuedMessagesInner {...props} />;\n};\n\nconst StatewireQueuedMessagesInner: FC<StatewireQueuedMessagesProps> = ({\n classNames,\n autoContinue = false,\n threadId = null,\n onEvent,\n renderContent,\n renderEditor,\n renderRowMarker,\n}) => {\n // The QUEUE lane only: composer.queue prepends the steer lane, whose entries\n // already render in the message list. A non-empty queue implies a live run\n // entry (the host retires runId only once both lanes drain), so the row\n // controls can always send.\n const runs = useStatewireRuns();\n const { queue, steerQueue, runId } = runs;\n // `failed` joined the runs projection in react-statewire 0.24; a projection\n // without it (an older lib, a stubbed runs read) must not crash the tray.\n const failed = runs.failed ?? [];\n // The host's durable prioritized-id record: a raw path read (the selector\n // must return a stable reference), with the lookup set derived below.\n const rawPrioritizedQueueIds = useStatewireState(\n (state) => readDeepAgentStreamValues(state).prioritizedQueueIds,\n );\n const prioritizedQueueIds = useMemo(\n () => new Set(readPrioritizedQueueIds(rawPrioritizedQueueIds)),\n [rawPrioritizedQueueIds],\n );\n const status = useDeepAgentThreadStatus();\n const { isRunning, isContinuable } = queueLaneFlags(status);\n const aui = useAui();\n const sendCommand = useStatewireSendCommand();\n const listId = useId();\n const [expanded, setExpanded] = useState(true);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editingText, setEditingText] = useState('');\n // Head entries already auto-promoted once on this mount: an attempt whose\n // continue run dies and re-strands the SAME entry must not loop — the manual\n // Continue pill is the fallback for a repeatedly failing dispatch. Kept on\n // the tray (not the auto-continue child) so it survives the empty-lane\n // renders between a promotion and its outcome.\n const autoContinuedRef = useRef<Set<string>>(new Set());\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n\n const rows = buildStatewireQueueRows({ queue, steerQueue, isContinuable });\n // Continue promotes the QUEUE head only: a queue→steer move dispatches the\n // stranded steer lane plus this entry, while a steer entry moved onto its\n // own lane is a no-op.\n const queueHeadId = queue[0]?.id ?? null;\n const retryableRefusal = readRetryableRunRefusal(runs.error) !== null;\n const autoContinueOptions = autoContinue === true ? {} : autoContinue || null;\n\n /**\n * Re-send the entry under its own id on its own lane: the host replaces the\n * queued message's content in place, leaving its queue position and lane\n * untouched (a same-id send never dispatches).\n */\n const saveEdit = (\n item: StatewireThread.RunsQueueEntry,\n lane: 'queue' | 'steer',\n text: string,\n metadata?: Record<string, unknown>,\n ): void => {\n setEditingId(null);\n setEditingText('');\n const command = buildQueueEditCommand({ item, lane, runId, text, metadata });\n if (command !== null) sendCommand(command);\n };\n\n /**\n * Retry/Discard act on a rendered lane snapshot that can trail the session\n * record; acting on an entry statewire already dropped throws. Nothing is\n * lost in that race, so it is recorded instead of crashing the click.\n */\n const runFailedSendAction = ({\n action,\n messageId,\n run,\n }: {\n action: 'retry' | 'discard';\n messageId: string;\n run: (actions: StatewireFailedActions) => void;\n }): void => {\n try {\n run(requireStatewireFailedActions(aui.thread().getState().extras));\n } catch (error) {\n if (!(error instanceof Error) || !isFailedSendEntryRace(error)) throw error;\n onEvent?.({\n type: 'failed-send-action-raced',\n threadId,\n messageId,\n action,\n error: error.message,\n });\n }\n };\n\n if (rows.length === 0 && failed.length === 0) return null;\n\n const renderRowContent = (context: StatewireQueueRowContentContext): ReactNode =>\n renderContent ? renderContent(context) : <QueueRowText text={context.text} />;\n\n return (\n <section\n aria-label=\"Queued messages\"\n className={cn(\n 'aui-statewire-queue w-full rounded-xl border border-border/70 bg-muted/30 px-2 py-1.5',\n classNames?.root,\n )}\n >\n {autoContinueOptions ? (\n <QueueAutoContinue\n delayMs={autoContinueOptions.delayMs ?? QUEUE_AUTO_CONTINUE_DELAY_MS}\n queueHeadId={queueHeadId}\n retryableRefusal={retryableRefusal}\n isContinuable={isContinuable}\n status={status}\n threadId={threadId}\n editing={editingId !== null}\n continuedRef={autoContinuedRef}\n onEventRef={onEventRef}\n />\n ) : null}\n <div className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={() => setExpanded((value) => !value)}\n aria-expanded={expanded}\n aria-controls={listId}\n className=\"flex items-center gap-1 rounded px-1 py-1 font-medium text-muted-foreground text-xs hover:text-foreground\"\n >\n {expanded ? (\n <ChevronDownIcon className=\"size-3.5\" />\n ) : (\n <ChevronRightIcon className=\"size-3.5\" />\n )}\n {rows.length + failed.length} queued\n </button>\n {isContinuable && queueHeadId !== null ? (\n <ContinuePill\n ariaLabel=\"Continue with queued messages\"\n onClick={() => aui.composer.queueItem({ id: queueHeadId }).move({ lane: 'steer' })}\n />\n ) : null}\n </div>\n {expanded ? (\n <ul\n id={listId}\n className={cn('max-h-40 overflow-y-auto', classNames?.list)}\n data-testid=\"athena-statewire-queue\"\n >\n {rows.map(({ item, lane }, index) => {\n const text = queueEntryText(item.parts);\n const isUnsettled = isQueueEntryUnsettled(item);\n const isEditing = editingId === item.id;\n const showSendNow =\n !isUnsettled && showQueueRowSendNow({ lane, index, isRunning, isContinuable });\n const showPrioritize = !isUnsettled && lane === 'queue' && isRunning && runId !== null;\n const showSteer =\n !isUnsettled && runId !== null && showQueueRowSteer({ lane, isRunning });\n const isPrioritized = prioritizedQueueIds.has(item.id);\n const marker = renderRowMarker?.({ item, lane, index, isUnsettled });\n const editorContext: StatewireQueueEditorContext = {\n value: editingText,\n item,\n onChange: setEditingText,\n onSave: (next, options) => saveEdit(item, lane, next, options?.metadata),\n onCancel: () => {\n setEditingId(null);\n setEditingText('');\n },\n };\n return (\n <li\n key={item.id}\n className=\"group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background\"\n >\n {marker != null ? (\n marker\n ) : isUnsettled ? (\n <Loader2Icon className=\"mt-0.5 size-3.5 shrink-0 animate-spin text-muted-foreground/60\" />\n ) : (\n <CircleIcon className=\"mt-0.5 size-3.5 shrink-0 text-muted-foreground/40\" />\n )}\n {isEditing ? (\n renderEditor ? (\n renderEditor(editorContext)\n ) : (\n <DefaultQueueEditor {...editorContext} />\n )\n ) : (\n renderRowContent({ text, index, item })\n )}\n <div\n className={cn('flex shrink-0 items-center gap-1', isEditing && 'hidden')}\n data-testid=\"statewire-queue-row-actions\"\n >\n {isUnsettled ? (\n <span\n className=\"px-1 text-[10px] text-muted-foreground\"\n data-testid=\"statewire-queued-message-sending\"\n >\n Sending…\n </span>\n ) : null}\n {showSteer ? (\n <button\n type=\"button\"\n aria-label=\"Steer\"\n title=\"Steer the current response: folded into the running turn at its next step, without stopping it.\"\n onClick={() => {\n if (runId === null) return;\n sendCommand({ type: 'run/steer-live', runId, messageId: item.id });\n }}\n className=\"inline-flex items-center gap-1 rounded-full border border-border px-2 py-1 font-medium text-[10px] text-foreground/80 hover:bg-background hover:text-foreground\"\n >\n <ShipWheelIcon className=\"size-2.5\" />\n Steer\n </button>\n ) : null}\n {showSendNow ? (\n <button\n type=\"button\"\n aria-label=\"Send now\"\n onClick={() =>\n aui.composer.queueItem({ id: item.id }).move({ lane: 'steer' })\n }\n className=\"inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5\"\n >\n <SendIcon className=\"size-2.5\" />\n Send now\n </button>\n ) : null}\n {showPrioritize ? (\n <button\n type=\"button\"\n aria-label={isPrioritized ? 'Remove priority' : 'Prioritize'}\n aria-pressed={isPrioritized}\n title={\n isPrioritized\n ? 'Remove priority'\n : 'Prioritize this message. Delivered as soon as the current step ends.'\n }\n onClick={() => {\n if (runId === null) return;\n sendCommand({\n type: 'run/prioritize',\n runId,\n messageId: item.id,\n priority: !isPrioritized,\n });\n }}\n className={cn(\n 'rounded p-1 transition-colors',\n isPrioritized\n ? 'text-amber-500 hover:text-amber-600'\n : 'text-muted-foreground hover:text-amber-500',\n )}\n >\n <ZapIcon className=\"size-3\" />\n </button>\n ) : null}\n {!isUnsettled ? (\n <button\n type=\"button\"\n aria-label=\"Edit queued message\"\n onClick={() => {\n setEditingId(item.id);\n setEditingText(text);\n }}\n className=\"rounded p-1 text-muted-foreground transition-colors hover:text-primary\"\n >\n <PencilIcon className=\"size-3\" />\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label=\"Remove queued message\"\n onClick={() => aui.composer.queueItem({ id: item.id }).remove()}\n className={cn(\n 'rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive',\n !showSendNow &&\n 'opacity-0 focus-visible:opacity-100 group-hover:opacity-100',\n )}\n >\n <Trash2Icon className=\"size-3\" />\n </button>\n </div>\n </li>\n );\n })}\n {failed.map((item, index) => (\n <li\n key={item.id}\n className=\"group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background\"\n >\n <AlertCircleIcon className=\"mt-0.5 size-3.5 shrink-0 text-destructive\" />\n {renderRowContent({\n text: queueEntryText(item.parts),\n index: rows.length + index,\n item,\n })}\n <div\n className=\"flex shrink-0 items-center gap-1\"\n data-testid=\"statewire-queue-row-actions\"\n >\n <span\n className=\"px-1 text-[10px] text-destructive\"\n title={describeQueueSendFailure(item.sendFailure)}\n >\n Failed to send\n </span>\n <button\n type=\"button\"\n aria-label=\"Retry failed message\"\n onClick={() =>\n runFailedSendAction({\n action: 'retry',\n messageId: item.id,\n run: (actions) => actions.retryFailed(item.id),\n })\n }\n className=\"inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5\"\n >\n <RotateCcwIcon className=\"size-2.5\" />\n Retry\n </button>\n <button\n type=\"button\"\n aria-label=\"Discard failed message\"\n onClick={() =>\n runFailedSendAction({\n action: 'discard',\n messageId: item.id,\n run: (actions) => actions.discardFailed(item.id),\n })\n }\n className=\"rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive\"\n >\n <Trash2Icon className=\"size-3\" />\n </button>\n </div>\n </li>\n ))}\n </ul>\n ) : null}\n </section>\n );\n};\n\n/** Promotes ordinary stranded queue heads once; infrastructure recovery stays server-owned. */\nconst QueueAutoContinue: FC<{\n delayMs: number;\n queueHeadId: string | null;\n retryableRefusal: boolean;\n isContinuable: boolean;\n status: DeepAgentThreadStatus;\n threadId: string | null;\n editing: boolean;\n continuedRef: MutableRefObject<Set<string>>;\n onEventRef: MutableRefObject<((event: StatewireQueueEvent) => void) | undefined>;\n}> = ({\n delayMs,\n queueHeadId,\n retryableRefusal,\n isContinuable,\n status,\n threadId,\n editing,\n continuedRef,\n onEventRef,\n}) => {\n const aui = useAui();\n // The settle that stranded the queue is described by the LAST message's run\n // marker (a marker deeper in history was superseded by a later send). The\n // selectors return primitives so the subscriptions stay shallow-stable.\n const lastMessageMarker = useAuiState((s) => {\n const last = s.thread.messages.at(-1);\n return last ? readRunMarkerFromSourceMessages(last)?.marker : undefined;\n });\n const lastMessageMarkerSource = useAuiState((s) => {\n const last = s.thread.messages.at(-1);\n return last ? readRunMarkerFromSourceMessages(last)?.source : undefined;\n });\n const userStopBlocks = userStopBlocksQueueAutoContinue({\n marker: lastMessageMarker,\n source: lastMessageMarkerSource,\n });\n\n useEffect(() => {\n if (\n !isContinuable ||\n userStopBlocks ||\n retryableRefusal ||\n isServerUpdateStopSource(lastMessageMarkerSource)\n ) return;\n // An open inline edit means the user is mid-revision on some row —\n // dispatching underneath them could send text they are about to change.\n if (editing) return;\n if (queueHeadId === null) return;\n const attemptKey = `${threadId ?? 'unknown'}:${queueHeadId}`;\n if (continuedRef.current.has(attemptKey)) return;\n const timeoutId = setTimeout(() => {\n continuedRef.current.add(attemptKey);\n onEventRef.current?.({ type: 'auto-continued', threadId, status, headEntryId: queueHeadId });\n aui.composer.queueItem({ id: queueHeadId }).move({ lane: 'steer' });\n }, delayMs);\n return () => clearTimeout(timeoutId);\n }, [\n continuedRef,\n aui,\n delayMs,\n editing,\n isContinuable,\n onEventRef,\n queueHeadId,\n retryableRefusal,\n lastMessageMarkerSource,\n status,\n threadId,\n userStopBlocks,\n ]);\n\n return null;\n};\n\n/**\n * The default row body: `[@name](…)` mentions render as chips, not raw\n * markdown links, and the body clamps to two lines. Show more / Show less\n * appears only when the rendered text overflows those two lines, so a short\n * message that wraps in a narrow tray is still caught and a short one gets no\n * dead control.\n */\nconst QueueRowText: FC<{ text: string }> = ({ text }) => {\n const bodyRef = useRef<HTMLParagraphElement>(null);\n const [expanded, setExpanded] = useState(false);\n const [overflows, setOverflows] = useState(false);\n\n useLayoutEffect(() => {\n const body = bodyRef.current;\n // Expanded text has no clamp to overflow; the toggle stays up to collapse it.\n if (!body || expanded) return;\n const measure = (): void => setOverflows(body.scrollHeight > body.clientHeight + 1);\n measure();\n if (typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(measure);\n observer.observe(body);\n return () => observer.disconnect();\n }, [text, expanded]);\n\n if (!text) {\n return <p className=\"min-w-0 flex-1 text-foreground text-xs\">Queued attachment</p>;\n }\n return (\n <div className=\"min-w-0 flex-1\">\n <p\n ref={bodyRef}\n className={cn(\n 'whitespace-pre-wrap break-words text-foreground text-xs leading-relaxed',\n !expanded && 'line-clamp-2',\n )}\n title={overflows && !expanded ? mentionsToPlainText(text) : undefined}\n >\n {parseMentionsInText(text)}\n </p>\n {overflows || expanded ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n onClick={() => setExpanded((value) => !value)}\n className=\"mt-0.5 font-medium text-[10px] text-muted-foreground hover:text-foreground\"\n >\n {expanded ? 'Show less' : 'Show more'}\n </button>\n ) : null}\n </div>\n );\n};\n\n/** Plain textarea editor: Enter saves, Shift+Enter breaks a line, Escape cancels. */\nconst DefaultQueueEditor: FC<StatewireQueueEditorContext> = ({\n value,\n onChange,\n onSave,\n onCancel,\n}) => {\n const canSave = value.trim().length > 0;\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>): void => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n if (canSave) onSave(value);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n onCancel();\n }\n };\n return (\n <div className=\"flex min-w-0 flex-1 items-start gap-1\">\n <textarea\n autoFocus\n aria-label=\"Edit message\"\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onKeyDown={handleKeyDown}\n rows={Math.min(6, Math.max(1, value.split('\\n').length))}\n className=\"min-w-0 flex-1 resize-none rounded-md border border-border bg-background px-2 py-1 text-foreground text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring/50\"\n />\n <button\n type=\"button\"\n aria-label=\"Save edit\"\n disabled={!canSave}\n onClick={() => onSave(value)}\n className={cn(\n 'rounded p-1 text-primary transition-colors hover:bg-primary/10',\n !canSave && 'cursor-not-allowed opacity-40',\n )}\n >\n <CheckIcon className=\"size-3.5\" />\n </button>\n <button\n type=\"button\"\n aria-label=\"Cancel edit\"\n onClick={onCancel}\n className=\"rounded p-1 text-muted-foreground transition-colors hover:bg-muted\"\n >\n <XIcon className=\"size-3.5\" />\n </button>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
- const version = "0.38.0";
3
+ const version = "0.38.1";
4
4
  const packageJson = {
5
5
  version
6
6
  };
@@ -1,4 +1,4 @@
1
- const version = "0.38.0";
1
+ const version = "0.38.1";
2
2
  const packageJson = {
3
3
  version
4
4
  };