@opengeni/react 0.27.0 → 0.29.0

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.
Files changed (43) hide show
  1. package/README.md +32 -0
  2. package/dist/{chunk-4F2YLLHP.js → chunk-AVLMIWYO.js} +3 -12
  3. package/dist/chunk-AVLMIWYO.js.map +1 -0
  4. package/dist/{chunk-NBYNFI5T.js → chunk-CSJBF3QJ.js} +5 -3
  5. package/dist/chunk-CSJBF3QJ.js.map +1 -0
  6. package/dist/{chunk-XVVQP7A4.js → chunk-IPVOVOW6.js} +2 -2
  7. package/dist/{chunk-OZDLELJQ.js → chunk-OKXCECLG.js} +55 -10
  8. package/dist/chunk-OKXCECLG.js.map +1 -0
  9. package/dist/{chunk-GQN2QIR2.js → chunk-ZMNPFZWL.js} +238 -87
  10. package/dist/chunk-ZMNPFZWL.js.map +1 -0
  11. package/dist/composer.js +2 -2
  12. package/dist/index.d.ts +7 -34
  13. package/dist/index.js +7 -5
  14. package/dist/index.js.map +1 -1
  15. package/dist/{queue-surface-implementation-3UW3MIIR.js → queue-surface-implementation-UQ535OKQ.js} +44 -12
  16. package/dist/queue-surface-implementation-UQ535OKQ.js.map +1 -0
  17. package/dist/{session-LsampPc6.d.ts → session-DaONt-dY.d.ts} +1 -1
  18. package/dist/{session-ui-BPOV-tuY.d.ts → session-ui-B5_roA95.d.ts} +81 -5
  19. package/dist/session-ui.d.ts +2 -2
  20. package/dist/session-ui.js +4 -2
  21. package/dist/session.d.ts +2 -2
  22. package/dist/session.js +3 -3
  23. package/dist/{use-turn-queue-aDnQvzVz.d.ts → use-turn-queue-D_1a8W_l.d.ts} +26 -4
  24. package/package.json +2 -2
  25. package/src/components/message-timeline.tsx +88 -0
  26. package/src/components/queue-surface-implementation.tsx +79 -11
  27. package/src/components/queue-surface.tsx +5 -5
  28. package/src/hooks/use-composer.ts +1 -15
  29. package/src/hooks/use-turn-queue.ts +8 -0
  30. package/src/index.ts +9 -0
  31. package/src/session-ui.ts +9 -0
  32. package/src/session.ts +2 -0
  33. package/src/timeline/index.ts +13 -2
  34. package/src/timeline/parsers.ts +3 -31
  35. package/src/timeline/projection.ts +73 -9
  36. package/src/timeline/turn-summary.tsx +243 -56
  37. package/src/timeline/types.ts +27 -1
  38. package/dist/chunk-4F2YLLHP.js.map +0 -1
  39. package/dist/chunk-GQN2QIR2.js.map +0 -1
  40. package/dist/chunk-NBYNFI5T.js.map +0 -1
  41. package/dist/chunk-OZDLELJQ.js.map +0 -1
  42. package/dist/queue-surface-implementation-3UW3MIIR.js.map +0 -1
  43. /package/dist/{chunk-XVVQP7A4.js.map → chunk-IPVOVOW6.js.map} +0 -0
@@ -56,10 +56,20 @@ function QueueSurface({
56
56
  const surfaceRef = useRef(null);
57
57
  const [keyboardDrag, setKeyboardDrag] = useState(null);
58
58
  const count = queue.queue.length;
59
+ const pendingInputCount = queue.pendingInputs.length;
60
+ const totalCount = count + pendingInputCount;
61
+ const attachedInputIds = queue.pendingInputAttachment?.inputIds ?? [];
62
+ const attachedInputs = queue.pendingInputs.filter((input) => attachedInputIds.includes(input.id));
63
+ const standaloneInputs = queue.pendingInputs.filter(
64
+ (input) => !attachedInputIds.includes(input.id)
65
+ );
59
66
  const canEditInComposer = queueComposerCheckoutEnabled(composer, readOnly);
60
67
  const collapsedPreview = useMemo(
61
- () => queuePromptPreview(queue.queue[0]?.prompt ?? "", QUEUE_COLLAPSED_PREVIEW_CHARACTERS),
62
- [queue.queue]
68
+ () => queuePromptPreview(
69
+ queue.queue[0]?.prompt ?? queue.pendingInputs[0]?.summary ?? "",
70
+ QUEUE_COLLAPSED_PREVIEW_CHARACTERS
71
+ ),
72
+ [queue.pendingInputs, queue.queue]
63
73
  );
64
74
  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 6 } }));
65
75
  const displayedQueue = useMemo(() => {
@@ -185,7 +195,7 @@ function QueueSurface({
185
195
  },
186
196
  [canEditInComposer, composer, edit]
187
197
  );
188
- if (count === 0 && !queue.stoppingPreviousAttempt && !queue.error && !queue.mutationError)
198
+ if (totalCount === 0 && !queue.stoppingPreviousAttempt && !queue.error && !queue.mutationError)
189
199
  return null;
190
200
  return /* @__PURE__ */ jsxs(
191
201
  "div",
@@ -202,9 +212,9 @@ function QueueSurface({
202
212
  type: "button",
203
213
  className: "flex w-full min-w-0 flex-wrap items-center gap-2 px-3 py-2 text-left outline-none transition-colors hover:bg-surface-2/60 focus-visible:bg-surface-2/60 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/40 pointer-coarse:min-h-[44px]",
204
214
  onClick: () => setOpen((value) => !value),
205
- "aria-description": !open && count > 0 ? collapsedPreview.summary : void 0,
215
+ "aria-description": !open && totalCount > 0 ? collapsedPreview.summary : void 0,
206
216
  "aria-expanded": open,
207
- "aria-label": `${count} queued prompt${count === 1 ? "" : "s"}${readOnly ? " Read-only" : ""}`,
217
+ "aria-label": `${count} queued prompt${count === 1 ? "" : "s"}${pendingInputCount > 0 ? ` and ${pendingInputCount} pending machine input${pendingInputCount === 1 ? "" : "s"}` : ""}${readOnly ? " Read-only" : ""}`,
208
218
  children: [
209
219
  /* @__PURE__ */ jsx(
210
220
  ChevronDownIcon,
@@ -214,12 +224,12 @@ function QueueSurface({
214
224
  }
215
225
  ),
216
226
  /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-fg", children: [
217
- count,
218
- " queued prompt",
219
- count === 1 ? "" : "s"
227
+ count > 0 ? `${count} queued prompt${count === 1 ? "" : "s"}` : null,
228
+ count > 0 && pendingInputCount > 0 ? " \xB7 " : null,
229
+ pendingInputCount > 0 ? `${pendingInputCount} incoming update${pendingInputCount === 1 ? "" : "s"}` : null
220
230
  ] }),
221
231
  readOnly ? /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded border border-border px-1.5 py-0.5 text-2xs text-fg-subtle", children: "Read-only" }) : null,
222
- !open && count > 0 ? /* @__PURE__ */ jsx(
232
+ !open && totalCount > 0 ? /* @__PURE__ */ jsx(
223
233
  "span",
224
234
  {
225
235
  "aria-hidden": "true",
@@ -233,6 +243,7 @@ function QueueSurface({
233
243
  ]
234
244
  }
235
245
  ),
246
+ open && standaloneInputs.length > 0 ? /* @__PURE__ */ jsx(PendingMachineInputs, { inputs: standaloneInputs }) : null,
236
247
  open && count > 0 && readOnly ? /* @__PURE__ */ jsx(
237
248
  "ol",
238
249
  {
@@ -244,6 +255,7 @@ function QueueSurface({
244
255
  {
245
256
  turn,
246
257
  index,
258
+ attachedInputs: turn.id === queue.pendingInputAttachment?.turnId ? attachedInputs : [],
247
259
  onDisclosureChange: (expanded) => setAnnouncement(
248
260
  `Full content for queued prompt ${index + 1} ${expanded ? "shown" : "hidden"}.`
249
261
  )
@@ -277,6 +289,7 @@ function QueueSurface({
277
289
  turn,
278
290
  index,
279
291
  count,
292
+ attachedInputs: turn.id === queue.pendingInputAttachment?.turnId ? attachedInputs : [],
280
293
  pending: queue.mutationFor(turn.id),
281
294
  confirmingReplace: replaceDraftFor === turn.id,
282
295
  keyboardDragging: keyboardDrag?.turnId === turn.id,
@@ -342,6 +355,21 @@ function QueueSurface({
342
355
  }
343
356
  );
344
357
  }
358
+ function PendingMachineInputs({
359
+ inputs,
360
+ attached = false
361
+ }) {
362
+ return /* @__PURE__ */ jsxs("section", { className: "border-t border-border px-3 py-2", children: [
363
+ /* @__PURE__ */ jsx("p", { className: "text-2xs font-medium text-fg-subtle", children: attached ? `${inputs.length} update${inputs.length === 1 ? "" : "s"} will join this prompt` : "Incoming updates waiting to run" }),
364
+ /* @__PURE__ */ jsx("ol", { className: "mt-1 space-y-1", children: inputs.map((input) => /* @__PURE__ */ jsxs("li", { className: "line-clamp-3 break-words text-xs text-fg", dir: "auto", children: [
365
+ /* @__PURE__ */ jsx("strong", { className: "capitalize text-fg-muted", children: input.kind.replace("_terminal", "").replaceAll("_", " ") }),
366
+ " ",
367
+ "\xB7 ",
368
+ input.sourceId,
369
+ input.summary ? ` \u2014 ${input.summary}` : ""
370
+ ] }, input.id)) })
371
+ ] });
372
+ }
345
373
  var QUEUE_ROW_PREVIEW_CHARACTERS = 360;
346
374
  var QUEUE_COLLAPSED_PREVIEW_CHARACTERS = 180;
347
375
  var QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS = 32;
@@ -599,7 +627,7 @@ function QueuePrompt({
599
627
  "aria-controls": fullContentId,
600
628
  "aria-expanded": expanded,
601
629
  "aria-label": `${expanded ? "Hide" : "Show"} full content for queued prompt ${index + 1}`,
602
- className: "mt-1 inline-flex min-h-7 min-w-0 max-w-full items-center gap-1 whitespace-normal rounded-md text-left text-2xs font-medium text-fg-muted outline-none transition-colors hover:text-fg focus-visible:ring-2 focus-visible:ring-ring/40 pointer-coarse:min-h-[44px]",
630
+ className: "mt-1 inline-flex min-h-7 min-w-0 max-w-full items-center gap-1 whitespace-normal rounded-md text-left text-2xs font-medium text-fg outline-none focus-visible:ring-2 focus-visible:ring-ring/40 pointer-coarse:min-h-[44px]",
603
631
  "data-testid": `queue-prompt-disclosure-${index + 1}`,
604
632
  onClick: () => {
605
633
  const next = !expanded;
@@ -636,12 +664,14 @@ function QueuePrompt({
636
664
  function ReadOnlyQueueRow({
637
665
  turn,
638
666
  index,
667
+ attachedInputs,
639
668
  onDisclosureChange
640
669
  }) {
641
670
  return /* @__PURE__ */ jsxs("li", { className: "flex min-w-0 items-start gap-2 bg-surface px-3 py-2", children: [
642
671
  /* @__PURE__ */ jsx("span", { className: "mt-1 shrink-0 font-mono text-2xs text-fg-subtle", children: index + 1 }),
643
672
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
644
673
  /* @__PURE__ */ jsx(QueuePrompt, { prompt: turn.prompt, index, onDisclosureChange }),
674
+ attachedInputs.length > 0 ? /* @__PURE__ */ jsx(PendingMachineInputs, { inputs: attachedInputs, attached: true }) : null,
645
675
  /* @__PURE__ */ jsxs("div", { className: "mt-1 flex min-w-0 items-center gap-2 overflow-hidden whitespace-nowrap text-2xs text-fg-subtle", children: [
646
676
  turn.resources.length > 0 ? /* @__PURE__ */ jsxs("span", { className: "shrink-0", children: [
647
677
  turn.resources.length,
@@ -663,6 +693,7 @@ function SortableQueueRow({
663
693
  turn,
664
694
  index,
665
695
  count,
696
+ attachedInputs,
666
697
  pending,
667
698
  confirmingReplace,
668
699
  keyboardDragging,
@@ -710,6 +741,7 @@ function SortableQueueRow({
710
741
  /* @__PURE__ */ jsx("span", { className: "col-start-2 row-start-1 mt-1 shrink-0 font-mono text-2xs text-fg-subtle", children: index + 1 }),
711
742
  /* @__PURE__ */ jsxs("div", { className: "col-span-full row-start-2 min-w-0 sm:col-span-1 sm:col-start-3 sm:row-start-1", children: [
712
743
  /* @__PURE__ */ jsx(QueuePrompt, { prompt: turn.prompt, index, onDisclosureChange }),
744
+ attachedInputs.length > 0 ? /* @__PURE__ */ jsx(PendingMachineInputs, { inputs: attachedInputs, attached: true }) : null,
713
745
  /* @__PURE__ */ jsxs("div", { className: "mt-1 flex min-w-0 items-center gap-2 overflow-hidden whitespace-nowrap text-2xs text-fg-subtle", children: [
714
746
  turn.resources.length > 0 ? /* @__PURE__ */ jsxs("span", { className: "shrink-0", children: [
715
747
  turn.resources.length,
@@ -734,7 +766,7 @@ function SortableQueueRow({
734
766
  onClick: onSteer,
735
767
  "aria-label": `Steer queued prompt ${index + 1}`,
736
768
  title: "Make this the next direction",
737
- className: "inline-flex h-7 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-xs font-medium outline-none transition-colors hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50 pointer-coarse:min-h-[44px] pointer-coarse:min-w-[44px]",
769
+ className: "inline-flex h-7 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-xs font-medium text-fg outline-none transition-[background-color] hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50 pointer-coarse:min-h-[44px] pointer-coarse:min-w-[44px]",
738
770
  children: [
739
771
  pending === "steer" ? /* @__PURE__ */ jsx(Loader2Icon, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsx(ZapIcon, { className: "size-3.5" }),
740
772
  /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Steer" })
@@ -887,4 +919,4 @@ export {
887
919
  QueueSurface,
888
920
  queueComposerCheckoutEnabled
889
921
  };
890
- //# sourceMappingURL=queue-surface-implementation-3UW3MIIR.js.map
922
+ //# sourceMappingURL=queue-surface-implementation-UQ535OKQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/queue-surface-implementation.tsx"],"sourcesContent":["import {\n DndContext,\n DragOverlay,\n PointerSensor,\n closestCenter,\n useSensor,\n useSensors,\n type DragEndEvent,\n type DragStartEvent,\n type Modifier,\n} from \"@dnd-kit/core\";\nimport {\n SortableContext,\n arrayMove,\n useSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport type { SessionPendingInputPreview, SessionTurn } from \"@opengeni/sdk\";\nimport {\n ArrowDownToLineIcon,\n ArrowUpToLineIcon,\n ChevronDownIcon,\n EllipsisIcon,\n GripVerticalIcon,\n Loader2Icon,\n PencilIcon,\n Trash2Icon,\n ZapIcon,\n} from \"lucide-react\";\nimport {\n useCallback,\n useId,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent as ReactKeyboardEvent,\n} from \"react\";\n\nimport { DropdownMenu } from \"radix-ui\";\nimport type { ComposerState } from \"../hooks/use-composer\";\nimport type { QueueMutationKind, UseTurnQueueResult } from \"../hooks/use-turn-queue\";\nimport { requestQueueDraftEdit } from \"./queue-draft-policy\";\nimport { QueueErrorAlert, QueueStoppingStatus } from \"./queue-surface-state\";\n\n/** The sole pending-input surface: compact above Goal, Agents, and composer. */\ntype QueueSurfaceCommonProps = {\n /** Focus the composer owned by this queue after checkout/removal. */\n onRequestComposerFocus?: (() => void) | undefined;\n};\n\nexport type QueueSurfaceProps =\n | (QueueSurfaceCommonProps & {\n queue: UseTurnQueueResult;\n composer: ComposerState;\n readOnly?: false | undefined;\n })\n | (QueueSurfaceCommonProps & {\n queue: UseTurnQueueResult;\n composer?: undefined;\n readOnly: true;\n });\n\n/** @internal Pure policy seam for queue/composer embedding tests. */\nexport function queueComposerCheckoutEnabled(\n composer: ComposerState | undefined,\n readOnly: boolean,\n): boolean {\n return !readOnly && composer !== undefined && composer.draftPersistence !== \"disabled\";\n}\n\nexport function QueueSurface({\n queue,\n composer,\n readOnly = false,\n onRequestComposerFocus,\n}: QueueSurfaceProps) {\n const [open, setOpen] = useState(false);\n const [replaceDraftFor, setReplaceDraftFor] = useState<string | null>(null);\n const [announcement, setAnnouncement] = useState(\"\");\n const [draggedTurnId, setDraggedTurnId] = useState<string | null>(null);\n const surfaceRef = useRef<HTMLDivElement | null>(null);\n const [keyboardDrag, setKeyboardDrag] = useState<{\n turnId: string;\n projectedIndex: number;\n } | null>(null);\n const count = queue.queue.length;\n const pendingInputCount = queue.pendingInputs.length;\n const totalCount = count + pendingInputCount;\n const attachedInputIds = queue.pendingInputAttachment?.inputIds ?? [];\n const attachedInputs = queue.pendingInputs.filter((input) => attachedInputIds.includes(input.id));\n const standaloneInputs = queue.pendingInputs.filter(\n (input) => !attachedInputIds.includes(input.id),\n );\n const canEditInComposer = queueComposerCheckoutEnabled(composer, readOnly);\n const collapsedPreview = useMemo(\n () =>\n queuePromptPreview(\n queue.queue[0]?.prompt ?? queue.pendingInputs[0]?.summary ?? \"\",\n QUEUE_COLLAPSED_PREVIEW_CHARACTERS,\n ),\n [queue.pendingInputs, queue.queue],\n );\n const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 6 } }));\n\n const displayedQueue = useMemo(() => {\n if (!keyboardDrag) return queue.queue;\n const oldIndex = queue.queue.findIndex((turn) => turn.id === keyboardDrag.turnId);\n if (oldIndex < 0) return queue.queue;\n return arrayMove(queue.queue, oldIndex, keyboardDrag.projectedIndex);\n }, [keyboardDrag, queue.queue]);\n\n const ids = useMemo(() => displayedQueue.map((turn) => turn.id), [displayedQueue]);\n const moveToIndex = useCallback(\n async (turnId: string, nextIndex: number): Promise<void> => {\n const oldIndex = queue.queue.findIndex((turn) => turn.id === turnId);\n if (oldIndex < 0) return;\n const boundedIndex = Math.max(0, Math.min(nextIndex, queue.queue.length - 1));\n if (oldIndex === boundedIndex) return;\n const ordered = arrayMove(queue.queue, oldIndex, boundedIndex);\n const beforeTurnId = ordered[boundedIndex + 1]?.id ?? null;\n const moved = await queue.moveTurn(turnId, beforeTurnId);\n setAnnouncement(\n moved\n ? `Queued prompt moved to position ${boundedIndex + 1}.`\n : \"The queue changed before that prompt could be moved. Refreshed server order.\",\n );\n if (moved) focusQueueTurn(surfaceRef.current, turnId);\n },\n [queue],\n );\n\n const onDragEnd = useCallback(\n (event: DragEndEvent) => {\n setDraggedTurnId(null);\n const activeId = String(event.active.id);\n const overId = event.over ? String(event.over.id) : null;\n if (!overId || activeId === overId) {\n setAnnouncement(\"Queued prompt returned to its original position.\");\n return;\n }\n const nextIndex = queue.queue.findIndex((turn) => turn.id === overId);\n if (nextIndex >= 0) void moveToIndex(activeId, nextIndex);\n },\n [moveToIndex, queue.queue],\n );\n\n const onDragStart = useCallback(\n (event: DragStartEvent) => {\n setKeyboardDrag(null);\n const turnId = String(event.active.id);\n const position = queue.queue.findIndex((turn) => turn.id === turnId) + 1;\n setDraggedTurnId(turnId);\n setAnnouncement(`Dragging queued prompt ${position} of ${queue.queue.length}.`);\n },\n [queue.queue],\n );\n\n const onHandleKeyDown = useCallback(\n (event: ReactKeyboardEvent<HTMLButtonElement>, turnId: string) => {\n const canonicalIndex = queue.queue.findIndex((turn) => turn.id === turnId);\n if (canonicalIndex < 0) return;\n\n if (!keyboardDrag) {\n if (event.key !== \" \") return;\n event.preventDefault();\n setKeyboardDrag({ turnId, projectedIndex: canonicalIndex });\n setAnnouncement(\n `Lifted queued prompt ${canonicalIndex + 1} of ${count}. Use arrow keys to move it, then press Space to drop.`,\n );\n return;\n }\n if (keyboardDrag.turnId !== turnId) return;\n\n if (event.key === \"Escape\") {\n event.preventDefault();\n setKeyboardDrag(null);\n setAnnouncement(\"Queue reorder cancelled.\");\n return;\n }\n if (event.key === \" \") {\n event.preventDefault();\n const targetIndex = keyboardDrag.projectedIndex;\n setAnnouncement(`Moving queued prompt to position ${targetIndex + 1}.`);\n void moveToIndex(turnId, targetIndex).finally(() => setKeyboardDrag(null));\n return;\n }\n\n const direction = event.key === \"ArrowUp\" ? -1 : event.key === \"ArrowDown\" ? 1 : 0;\n const edge = event.key === \"Home\" ? 0 : event.key === \"End\" ? count - 1 : null;\n if (direction === 0 && edge === null) return;\n event.preventDefault();\n const projectedIndex = Math.max(\n 0,\n Math.min(edge ?? keyboardDrag.projectedIndex + direction, count - 1),\n );\n setKeyboardDrag({ turnId, projectedIndex });\n setAnnouncement(`Queued prompt projected to position ${projectedIndex + 1} of ${count}.`);\n },\n [count, keyboardDrag, moveToIndex, queue.queue],\n );\n\n const edit = useCallback(\n async (turn: SessionTurn, replaceDraft: boolean) => {\n if (!composer || !canEditInComposer) return;\n const restored = await queue.editTurn(turn.id, {\n expectedDraftRevision: composer.draftRevision,\n replaceDraft,\n });\n if (!restored) return;\n composer.applyDraft(restored);\n setReplaceDraftFor(null);\n setAnnouncement(\"Queued prompt moved back to the composer for editing.\");\n window.requestAnimationFrame(() => {\n if (onRequestComposerFocus) {\n onRequestComposerFocus();\n return;\n }\n const input = document.querySelector<HTMLTextAreaElement>(\n 'textarea[aria-label=\"Message the agent\"]',\n );\n input?.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n input?.focus();\n });\n },\n [canEditInComposer, composer, onRequestComposerFocus, queue],\n );\n\n const requestEdit = useCallback(\n (turn: SessionTurn) => {\n if (!composer || !canEditInComposer) return;\n requestQueueDraftEdit(\n composer,\n () => setReplaceDraftFor(turn.id),\n () => void edit(turn, false),\n );\n },\n [canEditInComposer, composer, edit],\n );\n\n if (totalCount === 0 && !queue.stoppingPreviousAttempt && !queue.error && !queue.mutationError)\n return null;\n\n return (\n <div\n ref={surfaceRef}\n className=\"mx-auto mb-2 w-full max-w-3xl shrink-0 px-4 sm:px-6\"\n data-testid=\"queue-surface\"\n >\n <div className=\"overflow-hidden rounded-lg border border-border bg-surface/80 shadow-sm\">\n {queue.stoppingPreviousAttempt ? <QueueStoppingStatus queue={queue} dividerAfter /> : null}\n <button\n type=\"button\"\n className=\"flex w-full min-w-0 flex-wrap items-center gap-2 px-3 py-2 text-left outline-none transition-colors hover:bg-surface-2/60 focus-visible:bg-surface-2/60 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/40 pointer-coarse:min-h-[44px]\"\n onClick={() => setOpen((value) => !value)}\n aria-description={!open && totalCount > 0 ? collapsedPreview.summary : undefined}\n aria-expanded={open}\n aria-label={`${count} queued prompt${count === 1 ? \"\" : \"s\"}${\n pendingInputCount > 0\n ? ` and ${pendingInputCount} pending machine input${pendingInputCount === 1 ? \"\" : \"s\"}`\n : \"\"\n }${readOnly ? \" Read-only\" : \"\"}`}\n >\n <ChevronDownIcon\n aria-hidden=\"true\"\n className={`size-3.5 shrink-0 text-fg-subtle transition-transform ${open ? \"rotate-180\" : \"\"}`}\n />\n <span className=\"text-xs font-medium text-fg\">\n {count > 0 ? `${count} queued prompt${count === 1 ? \"\" : \"s\"}` : null}\n {count > 0 && pendingInputCount > 0 ? \" · \" : null}\n {pendingInputCount > 0\n ? `${pendingInputCount} incoming update${pendingInputCount === 1 ? \"\" : \"s\"}`\n : null}\n </span>\n {readOnly ? (\n <span className=\"shrink-0 rounded border border-border px-1.5 py-0.5 text-2xs text-fg-subtle\">\n Read-only\n </span>\n ) : null}\n {!open && totalCount > 0 ? (\n <span\n aria-hidden=\"true\"\n className={`max-w-full truncate text-fg-muted ${\n collapsedPreview.collapsedVisual === collapsedPreview.summary\n ? \"min-w-0 flex-1 text-xs\"\n : \"shrink-0 text-[10px]\"\n }`}\n data-testid=\"queue-collapsed-preview\"\n dir=\"auto\"\n >\n {collapsedPreview.collapsedVisual}\n </span>\n ) : null}\n {queue.loading ? <Loader2Icon className=\"ml-auto size-3.5 animate-spin\" /> : null}\n </button>\n\n {open && standaloneInputs.length > 0 ? (\n <PendingMachineInputs inputs={standaloneInputs} />\n ) : null}\n\n {open && count > 0 && readOnly ? (\n <ol\n className=\"max-h-[min(30rem,60dvh)] divide-y divide-border overflow-y-auto overscroll-contain border-t border-border\"\n aria-label=\"Queued prompts\"\n data-testid=\"queue-list\"\n >\n {queue.queue.map((turn, index) => (\n <ReadOnlyQueueRow\n key={turn.id}\n turn={turn}\n index={index}\n attachedInputs={\n turn.id === queue.pendingInputAttachment?.turnId ? attachedInputs : []\n }\n onDisclosureChange={(expanded) =>\n setAnnouncement(\n `Full content for queued prompt ${index + 1} ${expanded ? \"shown\" : \"hidden\"}.`,\n )\n }\n />\n ))}\n </ol>\n ) : null}\n\n {open && count > 0 && !readOnly ? (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n modifiers={[verticalOnly]}\n onDragStart={onDragStart}\n onDragCancel={() => {\n setDraggedTurnId(null);\n setAnnouncement(\"Queue reorder cancelled.\");\n }}\n onDragEnd={onDragEnd}\n >\n <SortableContext items={ids} strategy={verticalListSortingStrategy}>\n <ol\n className=\"max-h-[min(30rem,60dvh)] divide-y divide-border overflow-y-auto overscroll-contain border-t border-border\"\n aria-label=\"Queued prompts\"\n data-testid=\"queue-list\"\n >\n {displayedQueue.map((turn, index) => (\n <SortableQueueRow\n key={turn.id}\n turn={turn}\n index={index}\n count={count}\n attachedInputs={\n turn.id === queue.pendingInputAttachment?.turnId ? attachedInputs : []\n }\n pending={queue.mutationFor(turn.id)}\n confirmingReplace={replaceDraftFor === turn.id}\n keyboardDragging={keyboardDrag?.turnId === turn.id}\n onHandleKeyDown={(event) => onHandleKeyDown(event, turn.id)}\n onMove={(nextIndex) => void moveToIndex(turn.id, nextIndex)}\n onEdit={canEditInComposer ? () => requestEdit(turn) : undefined}\n onConfirmReplace={() => void edit(turn, true)}\n onCancelReplace={() => setReplaceDraftFor(null)}\n onSteer={() => {\n void queue.steerTurn(turn.id).then((steered) => {\n setAnnouncement(\n steered\n ? \"Queued prompt is now the next direction.\"\n : \"That prompt changed before it could be steered.\",\n );\n if (steered) {\n focusAfterQueueRemoval(surfaceRef.current, index, onRequestComposerFocus);\n }\n });\n }}\n onDelete={() => {\n void queue.removeTurn(turn.id).then((removed) => {\n setAnnouncement(\n removed\n ? \"Queued prompt deleted.\"\n : \"That prompt changed before it could be deleted.\",\n );\n if (removed) {\n focusAfterQueueRemoval(surfaceRef.current, index, onRequestComposerFocus);\n }\n });\n }}\n onDisclosureChange={(expanded) =>\n setAnnouncement(\n `Full content for queued prompt ${index + 1} ${expanded ? \"shown\" : \"hidden\"}.`,\n )\n }\n />\n ))}\n </ol>\n </SortableContext>\n <DragOverlay modifiers={[verticalOnly]}>\n {draggedTurnId ? (\n <div\n className=\"max-h-20 w-[min(36rem,calc(100vw-2rem))] max-w-[calc(100vw-2rem)] overflow-hidden rounded-md border border-brand/40 bg-surface px-3 py-2 text-xs text-fg shadow-lg\"\n data-testid=\"queue-drag-overlay\"\n >\n <p\n aria-hidden=\"true\"\n className=\"line-clamp-3 break-all whitespace-pre-wrap [unicode-bidi:plaintext]\"\n dir=\"auto\"\n >\n {\n queuePromptPreview(\n queue.queue.find((turn) => turn.id === draggedTurnId)?.prompt ?? \"\",\n QUEUE_ROW_PREVIEW_CHARACTERS,\n ).summary\n }\n </p>\n </div>\n ) : null}\n </DragOverlay>\n </DndContext>\n ) : null}\n\n {queue.error || queue.mutationError ? (\n <QueueErrorAlert queue={queue} dividerBefore />\n ) : null}\n </div>\n <p className=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n {announcement}\n </p>\n </div>\n );\n}\n\nfunction PendingMachineInputs({\n inputs,\n attached = false,\n}: {\n inputs: SessionPendingInputPreview[];\n attached?: boolean;\n}) {\n return (\n <section className=\"border-t border-border px-3 py-2\">\n <p className=\"text-2xs font-medium text-fg-subtle\">\n {attached\n ? `${inputs.length} update${inputs.length === 1 ? \"\" : \"s\"} will join this prompt`\n : \"Incoming updates waiting to run\"}\n </p>\n <ol className=\"mt-1 space-y-1\">\n {inputs.map((input) => (\n <li key={input.id} className=\"line-clamp-3 break-words text-xs text-fg\" dir=\"auto\">\n <strong className=\"capitalize text-fg-muted\">\n {input.kind.replace(\"_terminal\", \"\").replaceAll(\"_\", \" \")}\n </strong>{\" \"}\n · {input.sourceId}\n {input.summary ? ` — ${input.summary}` : \"\"}\n </li>\n ))}\n </ol>\n </section>\n );\n}\n\nconst QUEUE_ROW_PREVIEW_CHARACTERS = 360;\nconst QUEUE_COLLAPSED_PREVIEW_CHARACTERS = 180;\nconst QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS = 32;\nconst QUEUE_PREVIEW_REFERENCE_SAMPLE_CHARACTERS = 32;\nconst QUEUE_VISIBLE_END_IDENTITY_CHARACTERS = 18;\nconst QUEUE_PREVIEW_SEPARATOR = \" … \";\nconst queuePreviewSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\nconst queuePromptNonRenderingCodePoint =\n /[\\p{White_Space}\\p{Control}\\p{Default_Ignorable_Code_Point}]/u;\n\ntype BoundedPromptSample = {\n value: string;\n characters: number;\n truncated: boolean;\n};\n\ntype QueuePromptPreview = {\n summary: string;\n collapsedVisual: string;\n visibleStart: string;\n visibleIdentity: string | null;\n visibleIdentityLabel: \"End\" | \"Safe boundary\" | null;\n isFallback: boolean;\n};\n\n/**\n * Build a bounded head/tail summary of an arbitrary queued prompt. Sampling\n * both ends distinguishes prompts with equal long prefixes. Each sampled edge\n * has a small amount of grapheme context so ordinary emoji/combining sequences\n * can be retained whole. A cluster that exceeds that context is omitted rather\n * than fragmented, and malformed UTF-16 is replaced only in the summary. The\n * durable prompt remains exact and no operation scans or copies it in full.\n */\nfunction queuePromptPreview(prompt: string, maxCharacters: number): QueuePromptPreview {\n const wholePromptProbe = samplePromptStart(prompt, maxCharacters + 1);\n if (!wholePromptProbe.truncated && wholePromptProbe.characters <= maxCharacters) {\n const summary = replaceLoneSurrogates(wholePromptProbe.value);\n return hasVisiblePromptContent(summary)\n ? {\n summary,\n collapsedVisual: summary,\n visibleStart: summary,\n visibleIdentity: null,\n visibleIdentityLabel: null,\n isFallback: false,\n }\n : fallbackPromptPreview(prompt.length, wholePromptProbe.value, wholePromptProbe.value);\n }\n\n const suffixCharacters = Math.min(Math.floor(maxCharacters / 3), 120);\n const prefixCharacters =\n maxCharacters - codePointLength(QUEUE_PREVIEW_SEPARATOR) - suffixCharacters;\n const prefixSample = samplePromptStart(\n prompt,\n prefixCharacters + QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS,\n );\n const suffixSample = samplePromptEnd(\n prompt,\n suffixCharacters + QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS,\n );\n const prefixSegments = segmentPromptSample(prefixSample.value);\n const suffixSegments = segmentPromptSample(suffixSample.value);\n\n // A cluster at a truncated sampling edge may continue outside the sample.\n // Prefix sampling starts at the true source start, so only its last segment\n // is ambiguous. Suffix sampling ends at the true source end, so its first is.\n if (prefixSample.truncated) prefixSegments.pop();\n if (suffixSample.truncated) {\n let ambiguousSegment = suffixSegments.shift();\n // A locally segmented leading fragment ending in ZWJ can join the next\n // pictographic segment when omitted left context supplies its base. Keep\n // backing off until that uncertainty no longer propagates to the right.\n while (ambiguousSegment?.endsWith(\"\\u200d\") && suffixSegments.length > 0) {\n ambiguousSegment = suffixSegments.shift();\n }\n // Regional Indicator pairing depends on the parity of the preceding run.\n // If that run reaches the unknown sample boundary, omit all of its visible\n // leading segments rather than potentially recombining halves of flags.\n while (suffixSegments[0] && startsWithRegionalIndicator(suffixSegments[0])) {\n suffixSegments.shift();\n }\n }\n\n const prefix = takeWholeGraphemesFromStart(prefixSegments, prefixCharacters);\n const suffix = takeWholeGraphemesFromEnd(suffixSegments, suffixCharacters);\n const reference = boundedPromptSampleReference(\n prompt.length,\n prefixSample.value,\n suffixSample.value,\n );\n\n if (!hasVisiblePromptContent(prefix) && !hasVisiblePromptContent(suffix)) {\n return fallbackPromptPreview(prompt.length, prefixSample.value, suffixSample.value);\n }\n\n const safeSuffix = hasVisiblePromptContent(suffix)\n ? suffix\n : promptPreviewFallbackLabel(reference);\n const summary = `${prefix}${QUEUE_PREVIEW_SEPARATOR}${safeSuffix}`;\n if (!hasVisiblePromptContent(prefix)) {\n return {\n summary,\n collapsedVisual: summary,\n visibleStart: safeSuffix,\n visibleIdentity: null,\n visibleIdentityLabel: null,\n isFallback: false,\n };\n }\n\n const endIdentity = takeWholeGraphemesFromEnd(\n suffixSegments,\n QUEUE_VISIBLE_END_IDENTITY_CHARACTERS,\n );\n return {\n summary,\n collapsedVisual: summary,\n visibleStart: prefix,\n visibleIdentity: hasVisiblePromptContent(endIdentity) ? endIdentity : `ref ${reference}`,\n visibleIdentityLabel: hasVisiblePromptContent(endIdentity) ? \"End\" : \"Safe boundary\",\n isFallback: false,\n };\n}\n\nfunction fallbackPromptPreview(\n promptLength: number,\n startSample: string,\n endSample: string,\n): QueuePromptPreview {\n const reference = boundedPromptSampleReference(promptLength, startSample, endSample);\n const summary = promptPreviewFallbackLabel(reference);\n return {\n summary,\n collapsedVisual: `Omitted · ${reference}`,\n // The complete fallback remains the canonical accessible summary. Narrow\n // collapsed/row layouts paint the bounded reference in a compact truthful\n // form so ellipsis cannot hide the only identifying portion.\n visibleStart: `Omitted · ${reference}`,\n visibleIdentity: null,\n visibleIdentityLabel: null,\n isFallback: true,\n };\n}\n\nfunction promptPreviewFallbackLabel(reference: string): string {\n return `Content omitted at safe boundary · ref ${reference}`;\n}\n\nfunction boundedPromptSampleReference(\n promptLength: number,\n startSample: string,\n endSample: string,\n): string {\n const head = samplePromptStart(startSample, QUEUE_PREVIEW_REFERENCE_SAMPLE_CHARACTERS).value;\n const tail = samplePromptEnd(endSample, QUEUE_PREVIEW_REFERENCE_SAMPLE_CHARACTERS).value;\n let hash = 0x811c9dc5;\n for (const value of [String(promptLength), head, tail]) {\n for (let index = 0; index < value.length; index += 1) {\n hash ^= value.charCodeAt(index);\n hash = Math.imul(hash, 0x01000193);\n }\n hash ^= 0xffff;\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\").toUpperCase();\n}\n\nfunction hasVisiblePromptContent(value: string): boolean {\n // Callers pass only the already-bounded whole/head/tail preview samples.\n // Default-ignorables and controls can survive trim() while painting no row\n // identity at all (for example ZWJ, VS16, bidi controls, and tag characters).\n for (const character of value) {\n if (!queuePromptNonRenderingCodePoint.test(character)) return true;\n }\n return false;\n}\n\nfunction samplePromptStart(prompt: string, maxCharacters: number): BoundedPromptSample {\n let end = 0;\n let characters = 0;\n while (end < prompt.length && characters < maxCharacters) {\n const first = prompt.charCodeAt(end);\n end +=\n isHighSurrogate(first) &&\n end + 1 < prompt.length &&\n isLowSurrogate(prompt.charCodeAt(end + 1))\n ? 2\n : 1;\n characters += 1;\n }\n return { value: prompt.slice(0, end), characters, truncated: end < prompt.length };\n}\n\nfunction samplePromptEnd(prompt: string, maxCharacters: number): BoundedPromptSample {\n let start = prompt.length;\n let characters = 0;\n while (start > 0 && characters < maxCharacters) {\n start -= 1;\n if (\n isLowSurrogate(prompt.charCodeAt(start)) &&\n start > 0 &&\n isHighSurrogate(prompt.charCodeAt(start - 1))\n ) {\n start -= 1;\n }\n characters += 1;\n }\n return { value: prompt.slice(start), characters, truncated: start > 0 };\n}\n\nfunction segmentPromptSample(sample: string): string[] {\n return Array.from(\n queuePreviewSegmenter.segment(replaceLoneSurrogates(sample)),\n ({ segment }) => segment,\n );\n}\n\nfunction replaceLoneSurrogates(value: string): string {\n let sanitized = \"\";\n for (let index = 0; index < value.length; index += 1) {\n const current = value.charCodeAt(index);\n if (\n isHighSurrogate(current) &&\n index + 1 < value.length &&\n isLowSurrogate(value.charCodeAt(index + 1))\n ) {\n sanitized += value.slice(index, index + 2);\n index += 1;\n } else if (isHighSurrogate(current) || isLowSurrogate(current)) {\n sanitized += \"�\";\n } else {\n sanitized += value[index];\n }\n }\n return sanitized;\n}\n\nfunction takeWholeGraphemesFromStart(segments: string[], maxCharacters: number): string {\n const selected: string[] = [];\n let characters = 0;\n for (const segment of segments) {\n const segmentCharacters = codePointLength(segment);\n if (characters + segmentCharacters > maxCharacters) break;\n selected.push(segment);\n characters += segmentCharacters;\n }\n while (selected.at(-1)?.trim().length === 0) selected.pop();\n return selected.join(\"\");\n}\n\nfunction takeWholeGraphemesFromEnd(segments: string[], maxCharacters: number): string {\n const selected: string[] = [];\n let characters = 0;\n for (let index = segments.length - 1; index >= 0; index -= 1) {\n const segment = segments[index];\n if (!segment) continue;\n const segmentCharacters = codePointLength(segment);\n if (characters + segmentCharacters > maxCharacters) break;\n selected.unshift(segment);\n characters += segmentCharacters;\n }\n while (selected[0]?.trim().length === 0) selected.shift();\n while (selected.at(-1)?.trim().length === 0) selected.pop();\n return selected.join(\"\");\n}\n\nfunction codePointLength(value: string): number {\n let characters = 0;\n for (const _character of value) characters += 1;\n return characters;\n}\n\nfunction startsWithRegionalIndicator(value: string): boolean {\n const codePoint = value.codePointAt(0);\n return codePoint !== undefined && codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff;\n}\n\nfunction isHighSurrogate(codeUnit: number): boolean {\n return codeUnit >= 0xd800 && codeUnit <= 0xdbff;\n}\n\nfunction isLowSurrogate(codeUnit: number): boolean {\n return codeUnit >= 0xdc00 && codeUnit <= 0xdfff;\n}\n\nfunction QueuePrompt({\n prompt,\n index,\n onDisclosureChange,\n}: {\n prompt: string;\n index: number;\n onDisclosureChange: (expanded: boolean) => void;\n}) {\n const [expanded, setExpanded] = useState(false);\n const fullContentId = useId();\n const preview = useMemo(() => queuePromptPreview(prompt, QUEUE_ROW_PREVIEW_CHARACTERS), [prompt]);\n\n return (\n <div className=\"w-full min-w-0 max-w-full\">\n <div\n aria-label={`Queued prompt ${index + 1} summary: ${preview.summary}`}\n className=\"max-w-full overflow-hidden text-xs leading-5 text-fg\"\n data-testid={`queue-prompt-preview-${index + 1}`}\n dir=\"auto\"\n role=\"note\"\n >\n <span aria-hidden=\"true\" className=\"flex min-w-0 max-w-full items-baseline gap-2 sm:block\">\n <span\n className={`${preview.isFallback ? \"\" : \"line-clamp-1 sm:line-clamp-2\"} min-w-0 flex-1 whitespace-pre-wrap break-all [unicode-bidi:plaintext]`}\n data-testid={`queue-prompt-start-${index + 1}`}\n dir=\"auto\"\n >\n {preview.visibleStart}\n </span>\n {preview.visibleIdentity && preview.visibleIdentityLabel ? (\n <span\n className=\"flex min-w-0 max-w-[70%] shrink-0 items-center gap-1 text-2xs leading-4 text-fg-muted sm:mt-0.5 sm:max-w-full\"\n data-testid={`queue-prompt-identity-row-${index + 1}`}\n >\n <span className=\"shrink-0 font-medium text-fg-subtle\">\n {preview.visibleIdentityLabel}\n </span>\n <span\n className=\"min-w-0 overflow-hidden text-ellipsis whitespace-nowrap font-mono [unicode-bidi:plaintext]\"\n data-testid={`queue-prompt-identity-${index + 1}`}\n dir=\"auto\"\n >\n {preview.visibleIdentity}\n </span>\n </span>\n ) : null}\n </span>\n </div>\n <button\n type=\"button\"\n aria-controls={fullContentId}\n aria-expanded={expanded}\n aria-label={`${expanded ? \"Hide\" : \"Show\"} full content for queued prompt ${index + 1}`}\n className=\"mt-1 inline-flex min-h-7 min-w-0 max-w-full items-center gap-1 whitespace-normal rounded-md text-left text-2xs font-medium text-fg outline-none focus-visible:ring-2 focus-visible:ring-ring/40 pointer-coarse:min-h-[44px]\"\n data-testid={`queue-prompt-disclosure-${index + 1}`}\n onClick={() => {\n const next = !expanded;\n setExpanded(next);\n onDisclosureChange(next);\n }}\n >\n <ChevronDownIcon\n aria-hidden=\"true\"\n className={`size-3 shrink-0 transition-transform ${expanded ? \"rotate-180\" : \"\"}`}\n />\n {expanded ? \"Hide full prompt\" : \"View full prompt\"}\n </button>\n {expanded ? (\n <pre\n id={fullContentId}\n role=\"region\"\n aria-label={`Full content for queued prompt ${index + 1}`}\n className=\"mt-1.5 max-h-64 w-full min-w-0 max-w-full overflow-auto overscroll-contain rounded-md border border-border bg-surface-2/60 p-2 whitespace-pre-wrap break-all font-mono text-xs leading-5 text-fg [unicode-bidi:plaintext]\"\n data-testid={`queue-prompt-full-${index + 1}`}\n dir=\"auto\"\n tabIndex={0}\n >\n {prompt}\n </pre>\n ) : null}\n </div>\n );\n}\n\nfunction ReadOnlyQueueRow({\n turn,\n index,\n attachedInputs,\n onDisclosureChange,\n}: {\n turn: SessionTurn;\n index: number;\n attachedInputs: SessionPendingInputPreview[];\n onDisclosureChange: (expanded: boolean) => void;\n}) {\n return (\n <li className=\"flex min-w-0 items-start gap-2 bg-surface px-3 py-2\">\n <span className=\"mt-1 shrink-0 font-mono text-2xs text-fg-subtle\">{index + 1}</span>\n <div className=\"min-w-0 flex-1\">\n <QueuePrompt prompt={turn.prompt} index={index} onDisclosureChange={onDisclosureChange} />\n {attachedInputs.length > 0 ? (\n <PendingMachineInputs inputs={attachedInputs} attached />\n ) : null}\n <div className=\"mt-1 flex min-w-0 items-center gap-2 overflow-hidden whitespace-nowrap text-2xs text-fg-subtle\">\n {turn.resources.length > 0 ? (\n <span className=\"shrink-0\">\n {turn.resources.length} resource{turn.resources.length === 1 ? \"\" : \"s\"}\n </span>\n ) : null}\n {turn.tools.length > 0 ? (\n <span className=\"shrink-0\">\n {turn.tools.length} tool{turn.tools.length === 1 ? \"\" : \"s\"}\n </span>\n ) : null}\n <span className=\"min-w-0 truncate\">{turn.model}</span>\n <span className=\"shrink-0\">{turn.reasoningEffort}</span>\n </div>\n </div>\n </li>\n );\n}\n\nfunction SortableQueueRow({\n turn,\n index,\n count,\n attachedInputs,\n pending,\n confirmingReplace,\n keyboardDragging,\n onHandleKeyDown,\n onMove,\n onEdit,\n onConfirmReplace,\n onCancelReplace,\n onSteer,\n onDelete,\n onDisclosureChange,\n}: {\n turn: SessionTurn;\n index: number;\n count: number;\n attachedInputs: SessionPendingInputPreview[];\n pending: QueueMutationKind | null;\n confirmingReplace: boolean;\n keyboardDragging: boolean;\n onHandleKeyDown: (event: ReactKeyboardEvent<HTMLButtonElement>) => void;\n onMove: (index: number) => void;\n onEdit?: (() => void) | undefined;\n onConfirmReplace: () => void;\n onCancelReplace: () => void;\n onSteer: () => void;\n onDelete: () => void;\n onDisclosureChange: (expanded: boolean) => void;\n}) {\n const sortable = useSortable({\n id: turn.id,\n disabled: pending !== null || keyboardDragging,\n });\n return (\n <li\n data-queue-turn-id={turn.id}\n ref={sortable.setNodeRef}\n style={{\n transform: CSS.Transform.toString(sortable.transform),\n transition: sortable.transition,\n }}\n className={`bg-surface ${sortable.isDragging || keyboardDragging ? \"relative z-10 shadow-lg ring-1 ring-brand/40\" : \"\"}`}\n >\n <div className=\"grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-start gap-x-1.5 px-2 py-1.5 sm:grid-cols-[auto_auto_minmax(0,1fr)_auto] sm:gap-x-2 sm:px-3 sm:py-2\">\n <button\n data-queue-handle\n ref={sortable.setActivatorNodeRef}\n type=\"button\"\n {...sortable.attributes}\n {...sortable.listeners}\n onKeyDown={onHandleKeyDown}\n disabled={pending !== null}\n className=\"col-start-1 row-start-1 mt-0.5 inline-flex size-7 shrink-0 touch-none items-center justify-center rounded-md text-fg-subtle hover:bg-surface-2 hover:text-fg focus-visible:ring-2 focus-visible:ring-ring/40 pointer-coarse:size-[44px]\"\n aria-label={`Reorder queued prompt ${index + 1}`}\n title=\"Drag to reorder. Press Space, arrows, then Space to drop.\"\n >\n <GripVerticalIcon className=\"size-3.5\" />\n </button>\n <span className=\"col-start-2 row-start-1 mt-1 shrink-0 font-mono text-2xs text-fg-subtle\">\n {index + 1}\n </span>\n <div className=\"col-span-full row-start-2 min-w-0 sm:col-span-1 sm:col-start-3 sm:row-start-1\">\n <QueuePrompt prompt={turn.prompt} index={index} onDisclosureChange={onDisclosureChange} />\n {attachedInputs.length > 0 ? (\n <PendingMachineInputs inputs={attachedInputs} attached />\n ) : null}\n <div className=\"mt-1 flex min-w-0 items-center gap-2 overflow-hidden whitespace-nowrap text-2xs text-fg-subtle\">\n {turn.resources.length > 0 ? (\n <span className=\"shrink-0\">\n {turn.resources.length} resource{turn.resources.length === 1 ? \"\" : \"s\"}\n </span>\n ) : null}\n {turn.tools.length > 0 ? (\n <span className=\"shrink-0\">\n {turn.tools.length} tool{turn.tools.length === 1 ? \"\" : \"s\"}\n </span>\n ) : null}\n <span className=\"min-w-0 truncate\">{turn.model}</span>\n <span className=\"shrink-0\">{turn.reasoningEffort}</span>\n </div>\n </div>\n <div className=\"col-span-full row-start-3 flex min-w-0 items-start justify-end gap-1.5 sm:col-span-1 sm:col-start-4 sm:row-start-1 sm:gap-2\">\n <button\n type=\"button\"\n disabled={pending !== null}\n onClick={onSteer}\n aria-label={`Steer queued prompt ${index + 1}`}\n title=\"Make this the next direction\"\n className=\"inline-flex h-7 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-xs font-medium text-fg outline-none transition-[background-color] hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50 pointer-coarse:min-h-[44px] pointer-coarse:min-w-[44px]\"\n >\n {pending === \"steer\" ? (\n <Loader2Icon className=\"size-3.5 animate-spin\" />\n ) : (\n <ZapIcon className=\"size-3.5\" />\n )}\n <span className=\"hidden sm:inline\">Steer</span>\n </button>\n <button\n type=\"button\"\n disabled={pending !== null}\n onClick={onDelete}\n aria-label={`Delete queued prompt ${index + 1}`}\n title=\"Delete this queued prompt\"\n className=\"inline-flex size-7 shrink-0 items-center justify-center rounded-md outline-none transition-colors hover:bg-surface-2 hover:text-status-failed focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50 pointer-coarse:size-[44px]\"\n >\n {pending === \"delete\" ? (\n <Loader2Icon className=\"size-3.5 animate-spin\" />\n ) : (\n <Trash2Icon className=\"size-3.5\" />\n )}\n </button>\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n disabled={pending !== null}\n aria-label={`More actions for queued prompt ${index + 1}`}\n className=\"inline-flex size-7 shrink-0 items-center justify-center rounded-md outline-none transition-colors hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50 pointer-coarse:size-[44px]\"\n >\n {pending && pending !== \"steer\" && pending !== \"delete\" ? (\n <Loader2Icon className=\"size-3.5 animate-spin\" />\n ) : (\n <EllipsisIcon className=\"size-3.5\" />\n )}\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n align=\"end\"\n sideOffset={4}\n className=\"z-50 w-48 max-w-[calc(100vw-16px)] rounded-md border border-border bg-surface p-1 text-xs text-fg shadow-lg\"\n data-testid={`queue-actions-menu-${index + 1}`}\n >\n {onEdit ? (\n <>\n <DropdownMenu.Item\n className=\"flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 pointer-coarse:min-h-[44px]\"\n onSelect={onEdit}\n >\n <PencilIcon className=\"size-3.5\" /> Edit in composer\n </DropdownMenu.Item>\n <DropdownMenu.Separator className=\"my-1 h-px bg-border\" />\n </>\n ) : null}\n <DropdownMenu.Item\n className=\"flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]\"\n disabled={index === 0}\n onSelect={() => onMove(0)}\n >\n <ArrowUpToLineIcon className=\"size-3.5\" /> Move to top\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className=\"flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]\"\n disabled={index === 0}\n onSelect={() => onMove(index - 1)}\n >\n Move up\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className=\"flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]\"\n disabled={index === count - 1}\n onSelect={() => onMove(index + 1)}\n >\n Move down\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className=\"flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]\"\n disabled={index === count - 1}\n onSelect={() => onMove(count - 1)}\n >\n <ArrowDownToLineIcon className=\"size-3.5\" /> Move to bottom\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n </div>\n </div>\n {confirmingReplace ? (\n <div className=\"mx-3 mb-2 rounded-md border border-status-waiting/30 bg-status-waiting/10 p-2 text-xs text-fg\">\n <p>Your composer already has a draft. Replace it with this queued prompt?</p>\n <p className=\"mt-0.5 text-fg-muted\">\n The current draft will be permanently discarded; this queued prompt is preserved until\n you confirm.\n </p>\n <div className=\"mt-2 flex justify-end gap-1.5\">\n <button\n type=\"button\"\n className=\"rounded-md px-2 py-1 font-medium hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring/40\"\n onClick={onCancelReplace}\n >\n Keep current draft\n </button>\n <button\n type=\"button\"\n className=\"rounded-md bg-brand px-2 py-1 font-medium text-white hover:bg-brand/90 focus-visible:ring-2 focus-visible:ring-ring/40\"\n onClick={onConfirmReplace}\n >\n Replace and edit\n </button>\n </div>\n </div>\n ) : null}\n </li>\n );\n}\n\nconst verticalOnly: Modifier = ({ transform }) => ({ ...transform, x: 0 });\n\nfunction focusQueueTurn(surface: HTMLElement | null, turnId: string): void {\n window.requestAnimationFrame(() => {\n surface\n ?.querySelector<HTMLElement>(`[data-queue-turn-id=\"${turnId}\"] [data-queue-handle]`)\n ?.focus();\n });\n}\n\nfunction focusAfterQueueRemoval(\n surface: HTMLElement | null,\n previousIndex: number,\n onRequestComposerFocus?: (() => void) | undefined,\n): void {\n window.requestAnimationFrame(() => {\n const handles = surface?.querySelectorAll<HTMLElement>(\"[data-queue-handle]\") ?? [];\n const nearest = handles[Math.min(previousIndex, Math.max(0, handles.length - 1))];\n if (nearest) {\n nearest.focus();\n return;\n }\n if (onRequestComposerFocus) {\n onRequestComposerFocus();\n return;\n }\n document\n .querySelector<HTMLTextAreaElement>('textarea[aria-label=\"Message the agent\"]')\n ?.focus();\n });\n}\n"],"mappings":";;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW;AAEpB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAEP,SAAS,oBAAoB;AAmNY,SAgvBvB,UAhvBuB,KAiB/B,YAjB+B;AA1LlC,SAAS,6BACd,UACA,UACS;AACT,SAAO,CAAC,YAAY,aAAa,UAAa,SAAS,qBAAqB;AAC9E;AAEO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AACF,GAAsB;AACpB,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAwB,IAAI;AAC1E,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,EAAE;AACnD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAwB,IAAI;AACtE,QAAM,aAAa,OAA8B,IAAI;AACrD,QAAM,CAAC,cAAc,eAAe,IAAI,SAG9B,IAAI;AACd,QAAM,QAAQ,MAAM,MAAM;AAC1B,QAAM,oBAAoB,MAAM,cAAc;AAC9C,QAAM,aAAa,QAAQ;AAC3B,QAAM,mBAAmB,MAAM,wBAAwB,YAAY,CAAC;AACpE,QAAM,iBAAiB,MAAM,cAAc,OAAO,CAAC,UAAU,iBAAiB,SAAS,MAAM,EAAE,CAAC;AAChG,QAAM,mBAAmB,MAAM,cAAc;AAAA,IAC3C,CAAC,UAAU,CAAC,iBAAiB,SAAS,MAAM,EAAE;AAAA,EAChD;AACA,QAAM,oBAAoB,6BAA6B,UAAU,QAAQ;AACzE,QAAM,mBAAmB;AAAA,IACvB,MACE;AAAA,MACE,MAAM,MAAM,CAAC,GAAG,UAAU,MAAM,cAAc,CAAC,GAAG,WAAW;AAAA,MAC7D;AAAA,IACF;AAAA,IACF,CAAC,MAAM,eAAe,MAAM,KAAK;AAAA,EACnC;AACA,QAAM,UAAU,WAAW,UAAU,eAAe,EAAE,sBAAsB,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;AAE9F,QAAM,iBAAiB,QAAQ,MAAM;AACnC,QAAI,CAAC,aAAc,QAAO,MAAM;AAChC,UAAM,WAAW,MAAM,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,aAAa,MAAM;AAChF,QAAI,WAAW,EAAG,QAAO,MAAM;AAC/B,WAAO,UAAU,MAAM,OAAO,UAAU,aAAa,cAAc;AAAA,EACrE,GAAG,CAAC,cAAc,MAAM,KAAK,CAAC;AAE9B,QAAM,MAAM,QAAQ,MAAM,eAAe,IAAI,CAAC,SAAS,KAAK,EAAE,GAAG,CAAC,cAAc,CAAC;AACjF,QAAM,cAAc;AAAA,IAClB,OAAO,QAAgB,cAAqC;AAC1D,YAAM,WAAW,MAAM,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,MAAM;AACnE,UAAI,WAAW,EAAG;AAClB,YAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,MAAM,MAAM,SAAS,CAAC,CAAC;AAC5E,UAAI,aAAa,aAAc;AAC/B,YAAM,UAAU,UAAU,MAAM,OAAO,UAAU,YAAY;AAC7D,YAAM,eAAe,QAAQ,eAAe,CAAC,GAAG,MAAM;AACtD,YAAM,QAAQ,MAAM,MAAM,SAAS,QAAQ,YAAY;AACvD;AAAA,QACE,QACI,mCAAmC,eAAe,CAAC,MACnD;AAAA,MACN;AACA,UAAI,MAAO,gBAAe,WAAW,SAAS,MAAM;AAAA,IACtD;AAAA,IACA,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,YAAY;AAAA,IAChB,CAAC,UAAwB;AACvB,uBAAiB,IAAI;AACrB,YAAM,WAAW,OAAO,MAAM,OAAO,EAAE;AACvC,YAAM,SAAS,MAAM,OAAO,OAAO,MAAM,KAAK,EAAE,IAAI;AACpD,UAAI,CAAC,UAAU,aAAa,QAAQ;AAClC,wBAAgB,kDAAkD;AAClE;AAAA,MACF;AACA,YAAM,YAAY,MAAM,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,MAAM;AACpE,UAAI,aAAa,EAAG,MAAK,YAAY,UAAU,SAAS;AAAA,IAC1D;AAAA,IACA,CAAC,aAAa,MAAM,KAAK;AAAA,EAC3B;AAEA,QAAM,cAAc;AAAA,IAClB,CAAC,UAA0B;AACzB,sBAAgB,IAAI;AACpB,YAAM,SAAS,OAAO,MAAM,OAAO,EAAE;AACrC,YAAM,WAAW,MAAM,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,MAAM,IAAI;AACvE,uBAAiB,MAAM;AACvB,sBAAgB,0BAA0B,QAAQ,OAAO,MAAM,MAAM,MAAM,GAAG;AAAA,IAChF;AAAA,IACA,CAAC,MAAM,KAAK;AAAA,EACd;AAEA,QAAM,kBAAkB;AAAA,IACtB,CAAC,OAA8C,WAAmB;AAChE,YAAM,iBAAiB,MAAM,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,MAAM;AACzE,UAAI,iBAAiB,EAAG;AAExB,UAAI,CAAC,cAAc;AACjB,YAAI,MAAM,QAAQ,IAAK;AACvB,cAAM,eAAe;AACrB,wBAAgB,EAAE,QAAQ,gBAAgB,eAAe,CAAC;AAC1D;AAAA,UACE,wBAAwB,iBAAiB,CAAC,OAAO,KAAK;AAAA,QACxD;AACA;AAAA,MACF;AACA,UAAI,aAAa,WAAW,OAAQ;AAEpC,UAAI,MAAM,QAAQ,UAAU;AAC1B,cAAM,eAAe;AACrB,wBAAgB,IAAI;AACpB,wBAAgB,0BAA0B;AAC1C;AAAA,MACF;AACA,UAAI,MAAM,QAAQ,KAAK;AACrB,cAAM,eAAe;AACrB,cAAM,cAAc,aAAa;AACjC,wBAAgB,oCAAoC,cAAc,CAAC,GAAG;AACtE,aAAK,YAAY,QAAQ,WAAW,EAAE,QAAQ,MAAM,gBAAgB,IAAI,CAAC;AACzE;AAAA,MACF;AAEA,YAAM,YAAY,MAAM,QAAQ,YAAY,KAAK,MAAM,QAAQ,cAAc,IAAI;AACjF,YAAM,OAAO,MAAM,QAAQ,SAAS,IAAI,MAAM,QAAQ,QAAQ,QAAQ,IAAI;AAC1E,UAAI,cAAc,KAAK,SAAS,KAAM;AACtC,YAAM,eAAe;AACrB,YAAM,iBAAiB,KAAK;AAAA,QAC1B;AAAA,QACA,KAAK,IAAI,QAAQ,aAAa,iBAAiB,WAAW,QAAQ,CAAC;AAAA,MACrE;AACA,sBAAgB,EAAE,QAAQ,eAAe,CAAC;AAC1C,sBAAgB,uCAAuC,iBAAiB,CAAC,OAAO,KAAK,GAAG;AAAA,IAC1F;AAAA,IACA,CAAC,OAAO,cAAc,aAAa,MAAM,KAAK;AAAA,EAChD;AAEA,QAAM,OAAO;AAAA,IACX,OAAO,MAAmB,iBAA0B;AAClD,UAAI,CAAC,YAAY,CAAC,kBAAmB;AACrC,YAAM,WAAW,MAAM,MAAM,SAAS,KAAK,IAAI;AAAA,QAC7C,uBAAuB,SAAS;AAAA,QAChC;AAAA,MACF,CAAC;AACD,UAAI,CAAC,SAAU;AACf,eAAS,WAAW,QAAQ;AAC5B,yBAAmB,IAAI;AACvB,sBAAgB,uDAAuD;AACvE,aAAO,sBAAsB,MAAM;AACjC,YAAI,wBAAwB;AAC1B,iCAAuB;AACvB;AAAA,QACF;AACA,cAAM,QAAQ,SAAS;AAAA,UACrB;AAAA,QACF;AACA,eAAO,eAAe,EAAE,OAAO,WAAW,UAAU,SAAS,CAAC;AAC9D,eAAO,MAAM;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,CAAC,mBAAmB,UAAU,wBAAwB,KAAK;AAAA,EAC7D;AAEA,QAAM,cAAc;AAAA,IAClB,CAAC,SAAsB;AACrB,UAAI,CAAC,YAAY,CAAC,kBAAmB;AACrC;AAAA,QACE;AAAA,QACA,MAAM,mBAAmB,KAAK,EAAE;AAAA,QAChC,MAAM,KAAK,KAAK,MAAM,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,CAAC,mBAAmB,UAAU,IAAI;AAAA,EACpC;AAEA,MAAI,eAAe,KAAK,CAAC,MAAM,2BAA2B,CAAC,MAAM,SAAS,CAAC,MAAM;AAC/E,WAAO;AAET,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAU;AAAA,MACV,eAAY;AAAA,MAEZ;AAAA,6BAAC,SAAI,WAAU,2EACZ;AAAA,gBAAM,0BAA0B,oBAAC,uBAAoB,OAAc,cAAY,MAAC,IAAK;AAAA,UACtF;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,MAAM,QAAQ,CAAC,UAAU,CAAC,KAAK;AAAA,cACxC,oBAAkB,CAAC,QAAQ,aAAa,IAAI,iBAAiB,UAAU;AAAA,cACvE,iBAAe;AAAA,cACf,cAAY,GAAG,KAAK,iBAAiB,UAAU,IAAI,KAAK,GAAG,GACzD,oBAAoB,IAChB,QAAQ,iBAAiB,yBAAyB,sBAAsB,IAAI,KAAK,GAAG,KACpF,EACN,GAAG,WAAW,eAAe,EAAE;AAAA,cAE/B;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,eAAY;AAAA,oBACZ,WAAW,yDAAyD,OAAO,eAAe,EAAE;AAAA;AAAA,gBAC9F;AAAA,gBACA,qBAAC,UAAK,WAAU,+BACb;AAAA,0BAAQ,IAAI,GAAG,KAAK,iBAAiB,UAAU,IAAI,KAAK,GAAG,KAAK;AAAA,kBAChE,QAAQ,KAAK,oBAAoB,IAAI,WAAQ;AAAA,kBAC7C,oBAAoB,IACjB,GAAG,iBAAiB,mBAAmB,sBAAsB,IAAI,KAAK,GAAG,KACzE;AAAA,mBACN;AAAA,gBACC,WACC,oBAAC,UAAK,WAAU,+EAA8E,uBAE9F,IACE;AAAA,gBACH,CAAC,QAAQ,aAAa,IACrB;AAAA,kBAAC;AAAA;AAAA,oBACC,eAAY;AAAA,oBACZ,WAAW,qCACT,iBAAiB,oBAAoB,iBAAiB,UAClD,2BACA,sBACN;AAAA,oBACA,eAAY;AAAA,oBACZ,KAAI;AAAA,oBAEH,2BAAiB;AAAA;AAAA,gBACpB,IACE;AAAA,gBACH,MAAM,UAAU,oBAAC,eAAY,WAAU,iCAAgC,IAAK;AAAA;AAAA;AAAA,UAC/E;AAAA,UAEC,QAAQ,iBAAiB,SAAS,IACjC,oBAAC,wBAAqB,QAAQ,kBAAkB,IAC9C;AAAA,UAEH,QAAQ,QAAQ,KAAK,WACpB;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,cAAW;AAAA,cACX,eAAY;AAAA,cAEX,gBAAM,MAAM,IAAI,CAAC,MAAM,UACtB;AAAA,gBAAC;AAAA;AAAA,kBAEC;AAAA,kBACA;AAAA,kBACA,gBACE,KAAK,OAAO,MAAM,wBAAwB,SAAS,iBAAiB,CAAC;AAAA,kBAEvE,oBAAoB,CAAC,aACnB;AAAA,oBACE,kCAAkC,QAAQ,CAAC,IAAI,WAAW,UAAU,QAAQ;AAAA,kBAC9E;AAAA;AAAA,gBATG,KAAK;AAAA,cAWZ,CACD;AAAA;AAAA,UACH,IACE;AAAA,UAEH,QAAQ,QAAQ,KAAK,CAAC,WACrB;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,oBAAoB;AAAA,cACpB,WAAW,CAAC,YAAY;AAAA,cACxB;AAAA,cACA,cAAc,MAAM;AAClB,iCAAiB,IAAI;AACrB,gCAAgB,0BAA0B;AAAA,cAC5C;AAAA,cACA;AAAA,cAEA;AAAA,oCAAC,mBAAgB,OAAO,KAAK,UAAU,6BACrC;AAAA,kBAAC;AAAA;AAAA,oBACC,WAAU;AAAA,oBACV,cAAW;AAAA,oBACX,eAAY;AAAA,oBAEX,yBAAe,IAAI,CAAC,MAAM,UACzB;AAAA,sBAAC;AAAA;AAAA,wBAEC;AAAA,wBACA;AAAA,wBACA;AAAA,wBACA,gBACE,KAAK,OAAO,MAAM,wBAAwB,SAAS,iBAAiB,CAAC;AAAA,wBAEvE,SAAS,MAAM,YAAY,KAAK,EAAE;AAAA,wBAClC,mBAAmB,oBAAoB,KAAK;AAAA,wBAC5C,kBAAkB,cAAc,WAAW,KAAK;AAAA,wBAChD,iBAAiB,CAAC,UAAU,gBAAgB,OAAO,KAAK,EAAE;AAAA,wBAC1D,QAAQ,CAAC,cAAc,KAAK,YAAY,KAAK,IAAI,SAAS;AAAA,wBAC1D,QAAQ,oBAAoB,MAAM,YAAY,IAAI,IAAI;AAAA,wBACtD,kBAAkB,MAAM,KAAK,KAAK,MAAM,IAAI;AAAA,wBAC5C,iBAAiB,MAAM,mBAAmB,IAAI;AAAA,wBAC9C,SAAS,MAAM;AACb,+BAAK,MAAM,UAAU,KAAK,EAAE,EAAE,KAAK,CAAC,YAAY;AAC9C;AAAA,8BACE,UACI,6CACA;AAAA,4BACN;AACA,gCAAI,SAAS;AACX,qDAAuB,WAAW,SAAS,OAAO,sBAAsB;AAAA,4BAC1E;AAAA,0BACF,CAAC;AAAA,wBACH;AAAA,wBACA,UAAU,MAAM;AACd,+BAAK,MAAM,WAAW,KAAK,EAAE,EAAE,KAAK,CAAC,YAAY;AAC/C;AAAA,8BACE,UACI,2BACA;AAAA,4BACN;AACA,gCAAI,SAAS;AACX,qDAAuB,WAAW,SAAS,OAAO,sBAAsB;AAAA,4BAC1E;AAAA,0BACF,CAAC;AAAA,wBACH;AAAA,wBACA,oBAAoB,CAAC,aACnB;AAAA,0BACE,kCAAkC,QAAQ,CAAC,IAAI,WAAW,UAAU,QAAQ;AAAA,wBAC9E;AAAA;AAAA,sBA1CG,KAAK;AAAA,oBA4CZ,CACD;AAAA;AAAA,gBACH,GACF;AAAA,gBACA,oBAAC,eAAY,WAAW,CAAC,YAAY,GAClC,0BACC;AAAA,kBAAC;AAAA;AAAA,oBACC,WAAU;AAAA,oBACV,eAAY;AAAA,oBAEZ;AAAA,sBAAC;AAAA;AAAA,wBACC,eAAY;AAAA,wBACZ,WAAU;AAAA,wBACV,KAAI;AAAA,wBAGF;AAAA,0BACE,MAAM,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,aAAa,GAAG,UAAU;AAAA,0BACjE;AAAA,wBACF,EAAE;AAAA;AAAA,oBAEN;AAAA;AAAA,gBACF,IACE,MACN;AAAA;AAAA;AAAA,UACF,IACE;AAAA,UAEH,MAAM,SAAS,MAAM,gBACpB,oBAAC,mBAAgB,OAAc,eAAa,MAAC,IAC3C;AAAA,WACN;AAAA,QACA,oBAAC,OAAE,WAAU,WAAU,aAAU,UAAS,eAAY,QACnD,wBACH;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,qBAAqB;AAAA,EAC5B;AAAA,EACA,WAAW;AACb,GAGG;AACD,SACE,qBAAC,aAAQ,WAAU,oCACjB;AAAA,wBAAC,OAAE,WAAU,uCACV,qBACG,GAAG,OAAO,MAAM,UAAU,OAAO,WAAW,IAAI,KAAK,GAAG,2BACxD,mCACN;AAAA,IACA,oBAAC,QAAG,WAAU,kBACX,iBAAO,IAAI,CAAC,UACX,qBAAC,QAAkB,WAAU,4CAA2C,KAAI,QAC1E;AAAA,0BAAC,YAAO,WAAU,4BACf,gBAAM,KAAK,QAAQ,aAAa,EAAE,EAAE,WAAW,KAAK,GAAG,GAC1D;AAAA,MAAU;AAAA,MAAI;AAAA,MACX,MAAM;AAAA,MACR,MAAM,UAAU,WAAM,MAAM,OAAO,KAAK;AAAA,SALlC,MAAM,EAMf,CACD,GACH;AAAA,KACF;AAEJ;AAEA,IAAM,+BAA+B;AACrC,IAAM,qCAAqC;AAC3C,IAAM,4CAA4C;AAClD,IAAM,4CAA4C;AAClD,IAAM,wCAAwC;AAC9C,IAAM,0BAA0B;AAChC,IAAM,wBAAwB,IAAI,KAAK,UAAU,QAAW,EAAE,aAAa,WAAW,CAAC;AACvF,IAAM,mCACJ;AAyBF,SAAS,mBAAmB,QAAgB,eAA2C;AACrF,QAAM,mBAAmB,kBAAkB,QAAQ,gBAAgB,CAAC;AACpE,MAAI,CAAC,iBAAiB,aAAa,iBAAiB,cAAc,eAAe;AAC/E,UAAMA,WAAU,sBAAsB,iBAAiB,KAAK;AAC5D,WAAO,wBAAwBA,QAAO,IAClC;AAAA,MACE,SAAAA;AAAA,MACA,iBAAiBA;AAAA,MACjB,cAAcA;AAAA,MACd,iBAAiB;AAAA,MACjB,sBAAsB;AAAA,MACtB,YAAY;AAAA,IACd,IACA,sBAAsB,OAAO,QAAQ,iBAAiB,OAAO,iBAAiB,KAAK;AAAA,EACzF;AAEA,QAAM,mBAAmB,KAAK,IAAI,KAAK,MAAM,gBAAgB,CAAC,GAAG,GAAG;AACpE,QAAM,mBACJ,gBAAgB,gBAAgB,uBAAuB,IAAI;AAC7D,QAAM,eAAe;AAAA,IACnB;AAAA,IACA,mBAAmB;AAAA,EACrB;AACA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA,mBAAmB;AAAA,EACrB;AACA,QAAM,iBAAiB,oBAAoB,aAAa,KAAK;AAC7D,QAAM,iBAAiB,oBAAoB,aAAa,KAAK;AAK7D,MAAI,aAAa,UAAW,gBAAe,IAAI;AAC/C,MAAI,aAAa,WAAW;AAC1B,QAAI,mBAAmB,eAAe,MAAM;AAI5C,WAAO,kBAAkB,SAAS,QAAQ,KAAK,eAAe,SAAS,GAAG;AACxE,yBAAmB,eAAe,MAAM;AAAA,IAC1C;AAIA,WAAO,eAAe,CAAC,KAAK,4BAA4B,eAAe,CAAC,CAAC,GAAG;AAC1E,qBAAe,MAAM;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,SAAS,4BAA4B,gBAAgB,gBAAgB;AAC3E,QAAM,SAAS,0BAA0B,gBAAgB,gBAAgB;AACzE,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,EACf;AAEA,MAAI,CAAC,wBAAwB,MAAM,KAAK,CAAC,wBAAwB,MAAM,GAAG;AACxE,WAAO,sBAAsB,OAAO,QAAQ,aAAa,OAAO,aAAa,KAAK;AAAA,EACpF;AAEA,QAAM,aAAa,wBAAwB,MAAM,IAC7C,SACA,2BAA2B,SAAS;AACxC,QAAM,UAAU,GAAG,MAAM,GAAG,uBAAuB,GAAG,UAAU;AAChE,MAAI,CAAC,wBAAwB,MAAM,GAAG;AACpC,WAAO;AAAA,MACL;AAAA,MACA,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,sBAAsB;AAAA,MACtB,YAAY;AAAA,IACd;AAAA,EACF;AAEA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,iBAAiB,wBAAwB,WAAW,IAAI,cAAc,OAAO,SAAS;AAAA,IACtF,sBAAsB,wBAAwB,WAAW,IAAI,QAAQ;AAAA,IACrE,YAAY;AAAA,EACd;AACF;AAEA,SAAS,sBACP,cACA,aACA,WACoB;AACpB,QAAM,YAAY,6BAA6B,cAAc,aAAa,SAAS;AACnF,QAAM,UAAU,2BAA2B,SAAS;AACpD,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB,gBAAa,SAAS;AAAA;AAAA;AAAA;AAAA,IAIvC,cAAc,gBAAa,SAAS;AAAA,IACpC,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,IACtB,YAAY;AAAA,EACd;AACF;AAEA,SAAS,2BAA2B,WAA2B;AAC7D,SAAO,6CAA0C,SAAS;AAC5D;AAEA,SAAS,6BACP,cACA,aACA,WACQ;AACR,QAAM,OAAO,kBAAkB,aAAa,yCAAyC,EAAE;AACvF,QAAM,OAAO,gBAAgB,WAAW,yCAAyC,EAAE;AACnF,MAAI,OAAO;AACX,aAAW,SAAS,CAAC,OAAO,YAAY,GAAG,MAAM,IAAI,GAAG;AACtD,aAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,cAAQ,MAAM,WAAW,KAAK;AAC9B,aAAO,KAAK,KAAK,MAAM,QAAU;AAAA,IACnC;AACA,YAAQ;AACR,WAAO,KAAK,KAAK,MAAM,QAAU;AAAA,EACnC;AACA,UAAQ,SAAS,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,EAAE,YAAY;AAChE;AAEA,SAAS,wBAAwB,OAAwB;AAIvD,aAAW,aAAa,OAAO;AAC7B,QAAI,CAAC,iCAAiC,KAAK,SAAS,EAAG,QAAO;AAAA,EAChE;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,QAAgB,eAA4C;AACrF,MAAI,MAAM;AACV,MAAI,aAAa;AACjB,SAAO,MAAM,OAAO,UAAU,aAAa,eAAe;AACxD,UAAM,QAAQ,OAAO,WAAW,GAAG;AACnC,WACE,gBAAgB,KAAK,KACrB,MAAM,IAAI,OAAO,UACjB,eAAe,OAAO,WAAW,MAAM,CAAC,CAAC,IACrC,IACA;AACN,kBAAc;AAAA,EAChB;AACA,SAAO,EAAE,OAAO,OAAO,MAAM,GAAG,GAAG,GAAG,YAAY,WAAW,MAAM,OAAO,OAAO;AACnF;AAEA,SAAS,gBAAgB,QAAgB,eAA4C;AACnF,MAAI,QAAQ,OAAO;AACnB,MAAI,aAAa;AACjB,SAAO,QAAQ,KAAK,aAAa,eAAe;AAC9C,aAAS;AACT,QACE,eAAe,OAAO,WAAW,KAAK,CAAC,KACvC,QAAQ,KACR,gBAAgB,OAAO,WAAW,QAAQ,CAAC,CAAC,GAC5C;AACA,eAAS;AAAA,IACX;AACA,kBAAc;AAAA,EAChB;AACA,SAAO,EAAE,OAAO,OAAO,MAAM,KAAK,GAAG,YAAY,WAAW,QAAQ,EAAE;AACxE;AAEA,SAAS,oBAAoB,QAA0B;AACrD,SAAO,MAAM;AAAA,IACX,sBAAsB,QAAQ,sBAAsB,MAAM,CAAC;AAAA,IAC3D,CAAC,EAAE,QAAQ,MAAM;AAAA,EACnB;AACF;AAEA,SAAS,sBAAsB,OAAuB;AACpD,MAAI,YAAY;AAChB,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,UAAU,MAAM,WAAW,KAAK;AACtC,QACE,gBAAgB,OAAO,KACvB,QAAQ,IAAI,MAAM,UAClB,eAAe,MAAM,WAAW,QAAQ,CAAC,CAAC,GAC1C;AACA,mBAAa,MAAM,MAAM,OAAO,QAAQ,CAAC;AACzC,eAAS;AAAA,IACX,WAAW,gBAAgB,OAAO,KAAK,eAAe,OAAO,GAAG;AAC9D,mBAAa;AAAA,IACf,OAAO;AACL,mBAAa,MAAM,KAAK;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,4BAA4B,UAAoB,eAA+B;AACtF,QAAM,WAAqB,CAAC;AAC5B,MAAI,aAAa;AACjB,aAAW,WAAW,UAAU;AAC9B,UAAM,oBAAoB,gBAAgB,OAAO;AACjD,QAAI,aAAa,oBAAoB,cAAe;AACpD,aAAS,KAAK,OAAO;AACrB,kBAAc;AAAA,EAChB;AACA,SAAO,SAAS,GAAG,EAAE,GAAG,KAAK,EAAE,WAAW,EAAG,UAAS,IAAI;AAC1D,SAAO,SAAS,KAAK,EAAE;AACzB;AAEA,SAAS,0BAA0B,UAAoB,eAA+B;AACpF,QAAM,WAAqB,CAAC;AAC5B,MAAI,aAAa;AACjB,WAAS,QAAQ,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AAC5D,UAAM,UAAU,SAAS,KAAK;AAC9B,QAAI,CAAC,QAAS;AACd,UAAM,oBAAoB,gBAAgB,OAAO;AACjD,QAAI,aAAa,oBAAoB,cAAe;AACpD,aAAS,QAAQ,OAAO;AACxB,kBAAc;AAAA,EAChB;AACA,SAAO,SAAS,CAAC,GAAG,KAAK,EAAE,WAAW,EAAG,UAAS,MAAM;AACxD,SAAO,SAAS,GAAG,EAAE,GAAG,KAAK,EAAE,WAAW,EAAG,UAAS,IAAI;AAC1D,SAAO,SAAS,KAAK,EAAE;AACzB;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,MAAI,aAAa;AACjB,aAAW,cAAc,MAAO,eAAc;AAC9C,SAAO;AACT;AAEA,SAAS,4BAA4B,OAAwB;AAC3D,QAAM,YAAY,MAAM,YAAY,CAAC;AACrC,SAAO,cAAc,UAAa,aAAa,UAAW,aAAa;AACzE;AAEA,SAAS,gBAAgB,UAA2B;AAClD,SAAO,YAAY,SAAU,YAAY;AAC3C;AAEA,SAAS,eAAe,UAA2B;AACjD,SAAO,YAAY,SAAU,YAAY;AAC3C;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,gBAAgB,MAAM;AAC5B,QAAM,UAAU,QAAQ,MAAM,mBAAmB,QAAQ,4BAA4B,GAAG,CAAC,MAAM,CAAC;AAEhG,SACE,qBAAC,SAAI,WAAU,6BACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,cAAY,iBAAiB,QAAQ,CAAC,aAAa,QAAQ,OAAO;AAAA,QAClE,WAAU;AAAA,QACV,eAAa,wBAAwB,QAAQ,CAAC;AAAA,QAC9C,KAAI;AAAA,QACJ,MAAK;AAAA,QAEL,+BAAC,UAAK,eAAY,QAAO,WAAU,yDACjC;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,WAAW,GAAG,QAAQ,aAAa,KAAK,8BAA8B;AAAA,cACtE,eAAa,sBAAsB,QAAQ,CAAC;AAAA,cAC5C,KAAI;AAAA,cAEH,kBAAQ;AAAA;AAAA,UACX;AAAA,UACC,QAAQ,mBAAmB,QAAQ,uBAClC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,eAAa,6BAA6B,QAAQ,CAAC;AAAA,cAEnD;AAAA,oCAAC,UAAK,WAAU,uCACb,kBAAQ,sBACX;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,WAAU;AAAA,oBACV,eAAa,yBAAyB,QAAQ,CAAC;AAAA,oBAC/C,KAAI;AAAA,oBAEH,kBAAQ;AAAA;AAAA,gBACX;AAAA;AAAA;AAAA,UACF,IACE;AAAA,WACN;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,iBAAe;AAAA,QACf,iBAAe;AAAA,QACf,cAAY,GAAG,WAAW,SAAS,MAAM,mCAAmC,QAAQ,CAAC;AAAA,QACrF,WAAU;AAAA,QACV,eAAa,2BAA2B,QAAQ,CAAC;AAAA,QACjD,SAAS,MAAM;AACb,gBAAM,OAAO,CAAC;AACd,sBAAY,IAAI;AAChB,6BAAmB,IAAI;AAAA,QACzB;AAAA,QAEA;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,eAAY;AAAA,cACZ,WAAW,wCAAwC,WAAW,eAAe,EAAE;AAAA;AAAA,UACjF;AAAA,UACC,WAAW,qBAAqB;AAAA;AAAA;AAAA,IACnC;AAAA,IACC,WACC;AAAA,MAAC;AAAA;AAAA,QACC,IAAI;AAAA,QACJ,MAAK;AAAA,QACL,cAAY,kCAAkC,QAAQ,CAAC;AAAA,QACvD,WAAU;AAAA,QACV,eAAa,qBAAqB,QAAQ,CAAC;AAAA,QAC3C,KAAI;AAAA,QACJ,UAAU;AAAA,QAET;AAAA;AAAA,IACH,IACE;AAAA,KACN;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,SACE,qBAAC,QAAG,WAAU,uDACZ;AAAA,wBAAC,UAAK,WAAU,mDAAmD,kBAAQ,GAAE;AAAA,IAC7E,qBAAC,SAAI,WAAU,kBACb;AAAA,0BAAC,eAAY,QAAQ,KAAK,QAAQ,OAAc,oBAAwC;AAAA,MACvF,eAAe,SAAS,IACvB,oBAAC,wBAAqB,QAAQ,gBAAgB,UAAQ,MAAC,IACrD;AAAA,MACJ,qBAAC,SAAI,WAAU,kGACZ;AAAA,aAAK,UAAU,SAAS,IACvB,qBAAC,UAAK,WAAU,YACb;AAAA,eAAK,UAAU;AAAA,UAAO;AAAA,UAAU,KAAK,UAAU,WAAW,IAAI,KAAK;AAAA,WACtE,IACE;AAAA,QACH,KAAK,MAAM,SAAS,IACnB,qBAAC,UAAK,WAAU,YACb;AAAA,eAAK,MAAM;AAAA,UAAO;AAAA,UAAM,KAAK,MAAM,WAAW,IAAI,KAAK;AAAA,WAC1D,IACE;AAAA,QACJ,oBAAC,UAAK,WAAU,oBAAoB,eAAK,OAAM;AAAA,QAC/C,oBAAC,UAAK,WAAU,YAAY,eAAK,iBAAgB;AAAA,SACnD;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAgBG;AACD,QAAM,WAAW,YAAY;AAAA,IAC3B,IAAI,KAAK;AAAA,IACT,UAAU,YAAY,QAAQ;AAAA,EAChC,CAAC;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,sBAAoB,KAAK;AAAA,MACzB,KAAK,SAAS;AAAA,MACd,OAAO;AAAA,QACL,WAAW,IAAI,UAAU,SAAS,SAAS,SAAS;AAAA,QACpD,YAAY,SAAS;AAAA,MACvB;AAAA,MACA,WAAW,cAAc,SAAS,cAAc,mBAAmB,iDAAiD,EAAE;AAAA,MAEtH;AAAA,6BAAC,SAAI,WAAU,wJACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,qBAAiB;AAAA,cACjB,KAAK,SAAS;AAAA,cACd,MAAK;AAAA,cACJ,GAAG,SAAS;AAAA,cACZ,GAAG,SAAS;AAAA,cACb,WAAW;AAAA,cACX,UAAU,YAAY;AAAA,cACtB,WAAU;AAAA,cACV,cAAY,yBAAyB,QAAQ,CAAC;AAAA,cAC9C,OAAM;AAAA,cAEN,8BAAC,oBAAiB,WAAU,YAAW;AAAA;AAAA,UACzC;AAAA,UACA,oBAAC,UAAK,WAAU,2EACb,kBAAQ,GACX;AAAA,UACA,qBAAC,SAAI,WAAU,iFACb;AAAA,gCAAC,eAAY,QAAQ,KAAK,QAAQ,OAAc,oBAAwC;AAAA,YACvF,eAAe,SAAS,IACvB,oBAAC,wBAAqB,QAAQ,gBAAgB,UAAQ,MAAC,IACrD;AAAA,YACJ,qBAAC,SAAI,WAAU,kGACZ;AAAA,mBAAK,UAAU,SAAS,IACvB,qBAAC,UAAK,WAAU,YACb;AAAA,qBAAK,UAAU;AAAA,gBAAO;AAAA,gBAAU,KAAK,UAAU,WAAW,IAAI,KAAK;AAAA,iBACtE,IACE;AAAA,cACH,KAAK,MAAM,SAAS,IACnB,qBAAC,UAAK,WAAU,YACb;AAAA,qBAAK,MAAM;AAAA,gBAAO;AAAA,gBAAM,KAAK,MAAM,WAAW,IAAI,KAAK;AAAA,iBAC1D,IACE;AAAA,cACJ,oBAAC,UAAK,WAAU,oBAAoB,eAAK,OAAM;AAAA,cAC/C,oBAAC,UAAK,WAAU,YAAY,eAAK,iBAAgB;AAAA,eACnD;AAAA,aACF;AAAA,UACA,qBAAC,SAAI,WAAU,+HACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,UAAU,YAAY;AAAA,gBACtB,SAAS;AAAA,gBACT,cAAY,uBAAuB,QAAQ,CAAC;AAAA,gBAC5C,OAAM;AAAA,gBACN,WAAU;AAAA,gBAET;AAAA,8BAAY,UACX,oBAAC,eAAY,WAAU,yBAAwB,IAE/C,oBAAC,WAAQ,WAAU,YAAW;AAAA,kBAEhC,oBAAC,UAAK,WAAU,oBAAmB,mBAAK;AAAA;AAAA;AAAA,YAC1C;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,UAAU,YAAY;AAAA,gBACtB,SAAS;AAAA,gBACT,cAAY,wBAAwB,QAAQ,CAAC;AAAA,gBAC7C,OAAM;AAAA,gBACN,WAAU;AAAA,gBAET,sBAAY,WACX,oBAAC,eAAY,WAAU,yBAAwB,IAE/C,oBAAC,cAAW,WAAU,YAAW;AAAA;AAAA,YAErC;AAAA,YACA,qBAAC,aAAa,MAAb,EACC;AAAA,kCAAC,aAAa,SAAb,EAAqB,SAAO,MAC3B;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,UAAU,YAAY;AAAA,kBACtB,cAAY,kCAAkC,QAAQ,CAAC;AAAA,kBACvD,WAAU;AAAA,kBAET,qBAAW,YAAY,WAAW,YAAY,WAC7C,oBAAC,eAAY,WAAU,yBAAwB,IAE/C,oBAAC,gBAAa,WAAU,YAAW;AAAA;AAAA,cAEvC,GACF;AAAA,cACA,oBAAC,aAAa,QAAb,EACC;AAAA,gBAAC,aAAa;AAAA,gBAAb;AAAA,kBACC,OAAM;AAAA,kBACN,YAAY;AAAA,kBACZ,WAAU;AAAA,kBACV,eAAa,sBAAsB,QAAQ,CAAC;AAAA,kBAE3C;AAAA,6BACC,iCACE;AAAA;AAAA,wBAAC,aAAa;AAAA,wBAAb;AAAA,0BACC,WAAU;AAAA,0BACV,UAAU;AAAA,0BAEV;AAAA,gDAAC,cAAW,WAAU,YAAW;AAAA,4BAAE;AAAA;AAAA;AAAA,sBACrC;AAAA,sBACA,oBAAC,aAAa,WAAb,EAAuB,WAAU,uBAAsB;AAAA,uBAC1D,IACE;AAAA,oBACJ;AAAA,sBAAC,aAAa;AAAA,sBAAb;AAAA,wBACC,WAAU;AAAA,wBACV,UAAU,UAAU;AAAA,wBACpB,UAAU,MAAM,OAAO,CAAC;AAAA,wBAExB;AAAA,8CAAC,qBAAkB,WAAU,YAAW;AAAA,0BAAE;AAAA;AAAA;AAAA,oBAC5C;AAAA,oBACA;AAAA,sBAAC,aAAa;AAAA,sBAAb;AAAA,wBACC,WAAU;AAAA,wBACV,UAAU,UAAU;AAAA,wBACpB,UAAU,MAAM,OAAO,QAAQ,CAAC;AAAA,wBACjC;AAAA;AAAA,oBAED;AAAA,oBACA;AAAA,sBAAC,aAAa;AAAA,sBAAb;AAAA,wBACC,WAAU;AAAA,wBACV,UAAU,UAAU,QAAQ;AAAA,wBAC5B,UAAU,MAAM,OAAO,QAAQ,CAAC;AAAA,wBACjC;AAAA;AAAA,oBAED;AAAA,oBACA;AAAA,sBAAC,aAAa;AAAA,sBAAb;AAAA,wBACC,WAAU;AAAA,wBACV,UAAU,UAAU,QAAQ;AAAA,wBAC5B,UAAU,MAAM,OAAO,QAAQ,CAAC;AAAA,wBAEhC;AAAA,8CAAC,uBAAoB,WAAU,YAAW;AAAA,0BAAE;AAAA;AAAA;AAAA,oBAC9C;AAAA;AAAA;AAAA,cACF,GACF;AAAA,eACF;AAAA,aACF;AAAA,WACF;AAAA,QACC,oBACC,qBAAC,SAAI,WAAU,iGACb;AAAA,8BAAC,OAAE,oFAAsE;AAAA,UACzE,oBAAC,OAAE,WAAU,wBAAuB,iHAGpC;AAAA,UACA,qBAAC,SAAI,WAAU,iCACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS;AAAA,gBACV;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS;AAAA,gBACV;AAAA;AAAA,YAED;AAAA,aACF;AAAA,WACF,IACE;AAAA;AAAA;AAAA,EACN;AAEJ;AAEA,IAAM,eAAyB,CAAC,EAAE,UAAU,OAAO,EAAE,GAAG,WAAW,GAAG,EAAE;AAExE,SAAS,eAAe,SAA6B,QAAsB;AACzE,SAAO,sBAAsB,MAAM;AACjC,aACI,cAA2B,wBAAwB,MAAM,wBAAwB,GACjF,MAAM;AAAA,EACZ,CAAC;AACH;AAEA,SAAS,uBACP,SACA,eACA,wBACM;AACN,SAAO,sBAAsB,MAAM;AACjC,UAAM,UAAU,SAAS,iBAA8B,qBAAqB,KAAK,CAAC;AAClF,UAAM,UAAU,QAAQ,KAAK,IAAI,eAAe,KAAK,IAAI,GAAG,QAAQ,SAAS,CAAC,CAAC,CAAC;AAChF,QAAI,SAAS;AACX,cAAQ,MAAM;AACd;AAAA,IACF;AACA,QAAI,wBAAwB;AAC1B,6BAAuB;AACvB;AAAA,IACF;AACA,aACG,cAAmC,0CAA0C,GAC5E,MAAM;AAAA,EACZ,CAAC;AACH;","names":["summary"]}
@@ -1,7 +1,7 @@
1
1
  import { k as EmbeddedSessionReadClientOverride, a as EmbeddedSessionClientOverride, l as EmbeddedGoalClientOverride, m as EmbeddedSessionMcpApprovalPolicyClientOverride, n as EmbeddedSessionLineageClientOverride, o as EmbeddedHumanInputClientOverride } from './session-context-CAjlaeZb.js';
2
2
  import { Session, SessionEvent, StreamConnectionState, SessionStatus, SessionGoal, SessionControlResponse, SessionMcpServerMetadata, SessionMcpApprovalPolicy, UpdateSessionMcpApprovalPolicyResponse, SessionLineageResponse, HumanInputQuestion, SessionHumanInputRequest, SubmitHumanInputResponseRequest } from '@opengeni/sdk';
3
3
  import { S as SessionEventFeedOptions } from './use-composer-ClHy1rkL.js';
4
- import { e as TimelineItem, d as TimelineGroup } from './use-turn-queue-aDnQvzVz.js';
4
+ import { e as TimelineItem, T as TimelineGroup } from './use-turn-queue-D_1a8W_l.js';
5
5
  import './use-file-attachments-BmT8WtqO.js';
6
6
 
7
7
  type UseSessionOptions = EmbeddedSessionReadClientOverride & SessionEventFeedOptions & {
@@ -1,10 +1,10 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { SessionHumanInputRequest, SubmitHumanInputResponseRequest, HumanInputQuestion, HumanInputAnswer, SessionEvent, SessionStatus } from '@opengeni/sdk';
3
3
  import { ReactNode, ComponentType } from 'react';
4
- import { h as UseTurnQueueResult, f as ToolCallItem, e as TimelineItem, a as AgentMessageItem, i as UserMessageItem, b as AuthNeededItem } from './use-turn-queue-aDnQvzVz.js';
4
+ import { i as UseTurnQueueResult, f as ToolCallItem, A as ActivityItem, h as TurnOutcome, e as TimelineItem, a as AgentMessageItem, j as UserMessageItem, b as AuthNeededItem } from './use-turn-queue-D_1a8W_l.js';
5
5
  import { C as ComposerState } from './use-composer-ClHy1rkL.js';
6
6
 
7
- /** The sole human prompt queue: compact above Goal, Agents, and composer. */
7
+ /** The sole pending-input surface: compact above Goal, Agents, and composer. */
8
8
  type QueueSurfaceCommonProps = {
9
9
  /** Focus the composer owned by this queue after checkout/removal. */
10
10
  onRequestComposerFocus?: (() => void) | undefined;
@@ -19,7 +19,7 @@ type QueueSurfaceProps = (QueueSurfaceCommonProps & {
19
19
  readOnly: true;
20
20
  });
21
21
 
22
- /** The sole human prompt queue: compact above Goal, Agents, and composer. */
22
+ /** The sole pending-input surface: compact above Goal, Agents, and composer. */
23
23
  declare const QueueSurface: (props: QueueSurfaceProps) => react_jsx_runtime.JSX.Element | null;
24
24
 
25
25
  type HumanInputAnswerDraft = {
@@ -107,6 +107,80 @@ declare function rawTypeOf(item: ToolCallItem): string | null;
107
107
  */
108
108
  declare function createToolRegistry(baseEntries: ToolRegistryEntry[], baseFallback: ToolRenderer, options?: CreateToolRegistryOptions): ToolRegistry;
109
109
 
110
+ declare const BUILT_IN_TURN_SUMMARY_FACET_IDS: readonly ["steps", "files", "commands", "screenshots", "memories", "duration"];
111
+ type BuiltInTurnSummaryFacetId = (typeof BUILT_IN_TURN_SUMMARY_FACET_IDS)[number];
112
+ type TurnSummaryContext = Readonly<{
113
+ /** Every normalized activity item folded into this summary. */
114
+ items: readonly ActivityItem[];
115
+ /** Tool calls from `items`, retained in timeline order for convenient aggregation. */
116
+ toolCalls: readonly ToolCallItem[];
117
+ /** The settled turn verdict, or absent for a neutral/incomplete cluster. */
118
+ outcome: TurnOutcome | undefined;
119
+ /** The bounded failure reason rendered by the enclosing summary, when present. */
120
+ failureText: string | undefined;
121
+ /** Total turn duration when the enclosing group has both valid timestamps. */
122
+ durationMs: number | undefined;
123
+ /** False when any projected activity is still running or streaming. */
124
+ settled: boolean;
125
+ }>;
126
+ type TurnSummaryFacetResult = Readonly<{
127
+ icon?: ReactNode;
128
+ content: ReactNode;
129
+ ariaLabel?: string;
130
+ title?: string;
131
+ }>;
132
+ type TurnSummaryFacet = Readonly<{
133
+ /** Stable identity used for removal and deterministic de-duplication. */
134
+ id: string;
135
+ /** Return null when this facet has nothing useful to show. */
136
+ summarize(context: TurnSummaryContext): TurnSummaryFacetResult | null;
137
+ }>;
138
+ type ModifyTurnSummaryFacets = Readonly<{
139
+ /** Appended after the remaining built-ins, in supplied order. */
140
+ add?: readonly TurnSummaryFacet[];
141
+ /** Built-ins to omit before custom facets are appended. */
142
+ remove?: readonly BuiltInTurnSummaryFacetId[];
143
+ replace?: never;
144
+ }>;
145
+ type ReplaceTurnSummaryFacets = Readonly<{
146
+ /** The complete ordered facet list. Mutually exclusive with add/remove. */
147
+ replace: readonly TurnSummaryFacet[];
148
+ add?: never;
149
+ remove?: never;
150
+ }>;
151
+ type TurnSummaryFacetConfiguration = ModifyTurnSummaryFacets | ReplaceTurnSummaryFacets;
152
+ type TurnSummaryOptions = Readonly<{
153
+ facets?: TurnSummaryFacetConfiguration;
154
+ }>;
155
+ type TurnSummaryProps = {
156
+ /** The activity items in the turn (used only to compute the facet counts). */
157
+ items: ActivityItem[];
158
+ /**
159
+ * The settled verdict — or absent for a completed CLUSTER of a still-running
160
+ * turn, which folds neutrally: no verdict glyph (the turn has none yet), a
161
+ * quiet pulse dot in its place so alignment and the running feel both hold.
162
+ */
163
+ outcome?: TurnOutcome | undefined;
164
+ /** A short failure reason shown inline on a failed chip (never hidden). */
165
+ failureText?: string | undefined;
166
+ /** Elapsed turn duration; shown as a trailing facet when at least 1s. */
167
+ durationMs?: number | undefined;
168
+ /** Start expanded. */
169
+ defaultOpen?: boolean | undefined;
170
+ /**
171
+ * A nested fold — a cluster or sub-turn INSIDE an already-expanded turn. It
172
+ * drops the bordered/filled chip and renders as a plain disclosure node on the
173
+ * parent's rail (chevron + glyph + facets), so expanding a turn reveals a thread
174
+ * of nodes, never a stack of boxes-in-boxes. The top-level fold stays a chip.
175
+ */
176
+ bare?: boolean | undefined;
177
+ /** Per-instance facet customization. Omit to preserve the built-in summary exactly. */
178
+ facets?: TurnSummaryFacetConfiguration | undefined;
179
+ /** The rendered activity rail revealed on expand. */
180
+ children: ReactNode;
181
+ };
182
+ declare function TurnSummary({ items, outcome, failureText, durationMs, defaultOpen, bare, facets: facetConfiguration, children, }: TurnSummaryProps): react_jsx_runtime.JSX.Element;
183
+
110
184
  type MessageTimelineProps = {
111
185
  /** Raw session events (projected internally) … */
112
186
  events?: SessionEvent[] | undefined;
@@ -149,6 +223,8 @@ type MessageTimelineProps = {
149
223
  * `createDefaultToolRegistry({ entries })` to add custom tool renderers.
150
224
  */
151
225
  toolRegistry?: ToolRegistry | undefined;
226
+ /** Customize collapsed turn facets for this timeline instance. */
227
+ turnSummary?: TurnSummaryOptions | undefined;
152
228
  /** Follow new events when pinned to the bottom. Defaults to true. */
153
229
  autoFollow?: boolean | undefined;
154
230
  /** Older durable history exists above the current window (see useSessionEvents). */
@@ -166,7 +242,7 @@ type MessageTimelineProps = {
166
242
  * cards, goal markers, and status transitions. Owns stick-to-bottom scrolling
167
243
  * with a "jump to latest" affordance when the reader scrolls back.
168
244
  */
169
- declare function MessageTimeline({ events, items, status, renderMessageText, onOpenSession, onMemoryClick, onReconnect, resolveProviderLogo, toolRegistry, autoFollow, hasOlder, loadingOlder, onLoadOlder, emptyState, className, }: MessageTimelineProps): react_jsx_runtime.JSX.Element;
245
+ declare function MessageTimeline({ events, items, status, renderMessageText, onOpenSession, onMemoryClick, onReconnect, resolveProviderLogo, toolRegistry, turnSummary, autoFollow, hasOlder, loadingOlder, onLoadOlder, emptyState, className, }: MessageTimelineProps): react_jsx_runtime.JSX.Element;
170
246
  /**
171
247
  * Render one non-activity timeline item (chat message, status divider, goal
172
248
  * landmark, notice). Exported so the component demo draws the EXACT same rows as
@@ -180,4 +256,4 @@ declare function TimelineRow({ item, renderMessageText, onReconnect, resolveProv
180
256
  onOpenSession?: ((sessionId: string) => void) | undefined;
181
257
  }): react_jsx_runtime.JSX.Element | null;
182
258
 
183
- export { type CreateToolRegistryOptions as C, type HumanInputAnswerDraft as H, MessageTimeline as M, QueueSurface as Q, type ToolRegistry as T, HumanInputForm as a, type HumanInputFormMessages as b, createToolRegistry as c, type HumanInputFormProps as d, type MessageTimelineProps as e, type QueueSurfaceProps as f, TimelineRow as g, type ToolRegistryEntry as h, type ToolRenderer as i, type ToolRendererProps as j, answersFromDrafts as k, defaultHumanInputFormMessages as l, rawTypeOf as r };
259
+ export { BUILT_IN_TURN_SUMMARY_FACET_IDS as B, type CreateToolRegistryOptions as C, type HumanInputAnswerDraft as H, MessageTimeline as M, QueueSurface as Q, type ToolRegistry as T, type BuiltInTurnSummaryFacetId as a, HumanInputForm as b, createToolRegistry as c, type HumanInputFormMessages as d, type HumanInputFormProps as e, type MessageTimelineProps as f, type QueueSurfaceProps as g, TimelineRow as h, type ToolRegistryEntry as i, type ToolRenderer as j, type ToolRendererProps as k, TurnSummary as l, type TurnSummaryContext as m, type TurnSummaryFacet as n, type TurnSummaryFacetConfiguration as o, type TurnSummaryFacetResult as p, type TurnSummaryOptions as q, type TurnSummaryProps as r, answersFromDrafts as s, defaultHumanInputFormMessages as t, rawTypeOf as u };
@@ -1,7 +1,7 @@
1
- export { H as HumanInputAnswerDraft, a as HumanInputForm, b as HumanInputFormMessages, d as HumanInputFormProps, M as MessageTimeline, e as MessageTimelineProps, Q as QueueSurface, f as QueueSurfaceProps, g as TimelineRow } from './session-ui-BPOV-tuY.js';
1
+ export { B as BUILT_IN_TURN_SUMMARY_FACET_IDS, a as BuiltInTurnSummaryFacetId, H as HumanInputAnswerDraft, b as HumanInputForm, d as HumanInputFormMessages, e as HumanInputFormProps, M as MessageTimeline, f as MessageTimelineProps, Q as QueueSurface, g as QueueSurfaceProps, h as TimelineRow, m as TurnSummaryContext, n as TurnSummaryFacet, o as TurnSummaryFacetConfiguration, p as TurnSummaryFacetResult, q as TurnSummaryOptions } from './session-ui-B5_roA95.js';
2
2
  import 'react/jsx-runtime';
3
3
  import '@opengeni/sdk';
4
4
  import 'react';
5
- import './use-turn-queue-aDnQvzVz.js';
5
+ import './use-turn-queue-D_1a8W_l.js';
6
6
  import './session-context-CAjlaeZb.js';
7
7
  import './use-composer-ClHy1rkL.js';
@@ -1,14 +1,16 @@
1
1
  import {
2
+ BUILT_IN_TURN_SUMMARY_FACET_IDS,
2
3
  HumanInputForm,
3
4
  MessageTimeline,
4
5
  QueueSurface,
5
6
  TimelineRow
6
- } from "./chunk-GQN2QIR2.js";
7
+ } from "./chunk-ZMNPFZWL.js";
7
8
  import "./chunk-TK7G6XLT.js";
8
- import "./chunk-OZDLELJQ.js";
9
+ import "./chunk-OKXCECLG.js";
9
10
  import "./chunk-M7X4JZOD.js";
10
11
  import "./chunk-YDNWMKXO.js";
11
12
  export {
13
+ BUILT_IN_TURN_SUMMARY_FACET_IDS,
12
14
  HumanInputForm,
13
15
  MessageTimeline,
14
16
  QueueSurface,
package/dist/session.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { a as ClientOverride, b as FileAttachmentClientLike, E as FileAttachmentClientOverride, c as GoalClientLike, l as GoalClientOverride, o as HumanInputClientOverride, d as HumanInputSessionClientLike, e as SessionClientLike, g as SessionLineageClientLike, n as SessionLineageClientOverride, h as SessionMcpApprovalPolicyClientLike, m as SessionMcpApprovalPolicyClientOverride, i as SessionReadClientLike, k as SessionReadClientOverride } from './session-context-CAjlaeZb.js';
2
- export { P as PendingApproval, a as PendingHumanInputRequest, f as SessionEventsConnectionState, U as UseGoalOptions, g as UseGoalResult, h as UseHumanInputRequestsOptions, i as UseHumanInputRequestsResult, j as UseSessionControlOptions, k as UseSessionControlResult, l as UseSessionEventsOptions, m as UseSessionEventsResult, n as UseSessionLineageOptions, o as UseSessionLineageResult, p as UseSessionMcpApprovalPolicyOptions, q as UseSessionMcpApprovalPolicyResult, r as UseSessionOptions, s as UseSessionResult, t as approvalsFromRequiresAction, v as buildTimeline, w as creditExhaustedFromEvents, x as extractSessionRef, y as groupTimeline, z as humanInputRequestFromEvent, A as isGoalEvent, C as isHumanInputEvent, D as isLineageRefreshEvent, E as isSessionMcpApprovalPolicyEvent, F as isTitleEvent, G as projectPendingApprovals, H as projectPendingHumanInputRequests, I as sessionStatusFromEvents, J as toolDisplayName, K as useGoal, L as useHumanInputRequests, M as useSession, N as useSessionControl, O as useSessionEvents, Q as useSessionLineage, R as useSessionMcpApprovalPolicy } from './session-LsampPc6.js';
2
+ export { P as PendingApproval, a as PendingHumanInputRequest, f as SessionEventsConnectionState, U as UseGoalOptions, g as UseGoalResult, h as UseHumanInputRequestsOptions, i as UseHumanInputRequestsResult, j as UseSessionControlOptions, k as UseSessionControlResult, l as UseSessionEventsOptions, m as UseSessionEventsResult, n as UseSessionLineageOptions, o as UseSessionLineageResult, p as UseSessionMcpApprovalPolicyOptions, q as UseSessionMcpApprovalPolicyResult, r as UseSessionOptions, s as UseSessionResult, t as approvalsFromRequiresAction, v as buildTimeline, w as creditExhaustedFromEvents, x as extractSessionRef, y as groupTimeline, z as humanInputRequestFromEvent, A as isGoalEvent, C as isHumanInputEvent, D as isLineageRefreshEvent, E as isSessionMcpApprovalPolicyEvent, F as isTitleEvent, G as projectPendingApprovals, H as projectPendingHumanInputRequests, I as sessionStatusFromEvents, J as toolDisplayName, K as useGoal, L as useHumanInputRequests, M as useSession, N as useSessionControl, O as useSessionEvents, Q as useSessionLineage, R as useSessionMcpApprovalPolicy } from './session-DaONt-dY.js';
3
3
  export { a as ComposerSendExtras, C as ComposerState, F as FILE_ONLY_MESSAGE_TEXT, U as UseComposerOptions, c as composeSendInput, s as shouldSteerOnKey, b as shouldSubmitOnKey, u as useComposer } from './use-composer-ClHy1rkL.js';
4
4
  export { F as FileAttachment, a as UseFileAttachmentsOptions, U as UseFileAttachmentsResult, u as useFileAttachments } from './use-file-attachments-BmT8WtqO.js';
5
- export { A as ActivityItem, a as AgentMessageItem, b as AuthNeededItem, G as GoalItem, M as MemoryItem, N as NoticeItem, Q as QueueMutationKind, R as ReasoningItem, S as SandboxItem, c as SessionStatusItem, d as TimelineGroup, e as TimelineItem, f as ToolCallItem, g as TurnEndItem, T as TurnOutcome, U as UseTurnQueueOptions, h as UseTurnQueueResult, i as UserMessageItem, k as WorkerCompletionItem, W as WorkerItem, j as isTurnQueueEvent, u as useTurnQueue } from './use-turn-queue-aDnQvzVz.js';
5
+ export { A as ActivityItem, a as AgentMessageItem, b as AuthNeededItem, G as GoalItem, M as MachineInputBatchItem, c as MachineInputMember, l as MemoryItem, N as NoticeItem, Q as QueueMutationKind, R as ReasoningItem, S as SandboxItem, d as SessionStatusItem, T as TimelineGroup, e as TimelineItem, f as ToolCallItem, g as TurnEndItem, h as TurnOutcome, U as UseTurnQueueOptions, i as UseTurnQueueResult, j as UserMessageItem, m as WorkerCompletionItem, W as WorkerItem, k as isTurnQueueEvent, u as useTurnQueue } from './use-turn-queue-D_1a8W_l.js';
6
6
  import '@opengeni/sdk';
package/dist/session.js CHANGED
@@ -18,14 +18,14 @@ import {
18
18
  useSessionLineage,
19
19
  useSessionMcpApprovalPolicy,
20
20
  useTurnQueue
21
- } from "./chunk-NBYNFI5T.js";
21
+ } from "./chunk-CSJBF3QJ.js";
22
22
  import {
23
23
  FILE_ONLY_MESSAGE_TEXT,
24
24
  composeSendInput,
25
25
  shouldSteerOnKey,
26
26
  shouldSubmitOnKey,
27
27
  useComposer
28
- } from "./chunk-4F2YLLHP.js";
28
+ } from "./chunk-AVLMIWYO.js";
29
29
  import "./chunk-HQFPO7VX.js";
30
30
  import {
31
31
  buildTimeline,
@@ -34,7 +34,7 @@ import {
34
34
  groupTimeline,
35
35
  sessionStatusFromEvents,
36
36
  toolDisplayName
37
- } from "./chunk-OZDLELJQ.js";
37
+ } from "./chunk-OKXCECLG.js";
38
38
  import "./chunk-M7X4JZOD.js";
39
39
  export {
40
40
  FILE_ONLY_MESSAGE_TEXT,
@@ -1,4 +1,4 @@
1
- import { ToolAuthNeededPayload, ResourceRef, ToolRef, SessionStatus, SessionQueueSnapshot, SessionTurn, EffectiveSessionControl, ComposerDraft, SessionEvent } from '@opengeni/sdk';
1
+ import { ToolAuthNeededPayload, ResourceRef, ToolRef, SessionStatus, SessionQueueSnapshot, SessionTurn, SessionPendingInputPreview, EffectiveSessionControl, ComposerDraft, SessionEvent } from '@opengeni/sdk';
2
2
  import { a as EmbeddedSessionClientOverride } from './session-context-CAjlaeZb.js';
3
3
  import { S as SessionEventFeedOptions } from './use-composer-ClHy1rkL.js';
4
4
 
@@ -176,7 +176,7 @@ type GoalItem = {
176
176
  type NoticeItem = {
177
177
  kind: "notice";
178
178
  id: string;
179
- tone: "waiting" | "cancelled" | "failed";
179
+ tone: "waiting" | "cancelled" | "failed" | "input";
180
180
  text: string;
181
181
  /** Optional evidence kept inspectable without overwhelming the main rail. */
182
182
  details?: {
@@ -189,6 +189,24 @@ type NoticeItem = {
189
189
  };
190
190
  occurredAt: string;
191
191
  };
192
+ type MachineInputMember = {
193
+ id: string;
194
+ kind: "scheduled_occurrence" | "goal_continuation" | "agent_message" | "agent_steer_instruction" | "child_terminal_result";
195
+ classification: "success" | "failure" | "action_required" | "info";
196
+ sourceId: string;
197
+ summary: string;
198
+ };
199
+ /**
200
+ * One or more durable non-human inputs that joined the following agent turn.
201
+ * This is communication, not a warning or a protocol-debug payload.
202
+ */
203
+ type MachineInputBatchItem = {
204
+ kind: "machine-input-batch";
205
+ id: string;
206
+ turnId: string | null;
207
+ members: MachineInputMember[];
208
+ occurredAt: string;
209
+ };
192
210
  /**
193
211
  * A tool call hit a missing or lapsed connection. The broker reports that
194
212
  * condition as a tool error and the turn continues; reconnecting never resumes
@@ -227,7 +245,7 @@ type TurnEndItem = {
227
245
  failureText: string | null;
228
246
  occurredAt: string;
229
247
  };
230
- type TimelineItem = UserMessageItem | AgentMessageItem | ReasoningItem | ToolCallItem | WorkerItem | WorkerCompletionItem | SandboxItem | SessionStatusItem | GoalItem | NoticeItem | AuthNeededItem | MemoryItem | FleetDecisionItem | TurnEndItem;
248
+ type TimelineItem = UserMessageItem | AgentMessageItem | ReasoningItem | ToolCallItem | WorkerItem | WorkerCompletionItem | SandboxItem | SessionStatusItem | GoalItem | NoticeItem | MachineInputBatchItem | AuthNeededItem | MemoryItem | FleetDecisionItem | TurnEndItem;
231
249
  /** Activity items cluster between chat messages (reasoning, tools, workers, sandbox, memory). */
232
250
  type ActivityItem = ReasoningItem | ToolCallItem | WorkerItem | SandboxItem | MemoryItem | FleetDecisionItem;
233
251
  type TimelineGroup = {
@@ -259,6 +277,10 @@ type UseTurnQueueResult = {
259
277
  snapshot: SessionQueueSnapshot | null;
260
278
  /** Human/API prompts exactly in server execution order. Never client-sorted. */
261
279
  queue: SessionTurn[];
280
+ /** Canonical pending machine inputs. Events only trigger an authoritative refresh. */
281
+ pendingInputs: SessionPendingInputPreview[];
282
+ /** Exact pending members projected to join an already-waiting prompt. */
283
+ pendingInputAttachment: SessionQueueSnapshot["pendingInputAttachment"];
262
284
  effectiveControl: EffectiveSessionControl | null;
263
285
  /** The latest interrupted attempt has not yet durably proved physical quiescence. */
264
286
  stoppingPreviousAttempt: boolean;
@@ -287,4 +309,4 @@ type UseTurnQueueResult = {
287
309
  */
288
310
  declare function useTurnQueue(sessionId: string | null | undefined, options?: UseTurnQueueOptions): UseTurnQueueResult;
289
311
 
290
- export { type ActivityItem as A, type GoalItem as G, type MemoryItem as M, type NoticeItem as N, type QueueMutationKind as Q, type ReasoningItem as R, type SandboxItem as S, type TurnOutcome as T, type UseTurnQueueOptions as U, type WorkerItem as W, type AgentMessageItem as a, type AuthNeededItem as b, type SessionStatusItem as c, type TimelineGroup as d, type TimelineItem as e, type ToolCallItem as f, type TurnEndItem as g, type UseTurnQueueResult as h, type UserMessageItem as i, isTurnQueueEvent as j, type WorkerCompletionItem as k, useTurnQueue as u };
312
+ export { type ActivityItem as A, type GoalItem as G, type MachineInputBatchItem as M, type NoticeItem as N, type QueueMutationKind as Q, type ReasoningItem as R, type SandboxItem as S, type TimelineGroup as T, type UseTurnQueueOptions as U, type WorkerItem as W, type AgentMessageItem as a, type AuthNeededItem as b, type MachineInputMember as c, type SessionStatusItem as d, type TimelineItem as e, type ToolCallItem as f, type TurnEndItem as g, type TurnOutcome as h, type UseTurnQueueResult as i, type UserMessageItem as j, isTurnQueueEvent as k, type MemoryItem as l, type WorkerCompletionItem as m, useTurnQueue as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/react",
3
- "version": "0.27.0",
3
+ "version": "0.29.0",
4
4
  "description": "React hooks and styled components for OpenGeni: live session streaming, chat composer, message timeline, session status, and fleet views — token-themed (CSS variables), dark-first, built on Tailwind v4 + Radix + Motion.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -66,7 +66,7 @@
66
66
  "@dnd-kit/utilities": "3.2.2",
67
67
  "@fontsource-variable/noto-sans-arabic": "5.2.10",
68
68
  "@fontsource-variable/noto-sans-jp": "5.2.10",
69
- "@opengeni/sdk": "^0.27.0",
69
+ "@opengeni/sdk": "^0.29.0",
70
70
  "clsx": "^2.1.1",
71
71
  "lucide-react": "^1.8.0",
72
72
  "motion": "^12.0.0",