@opengeni/react 1.4.2 → 1.4.5-canary.37458084490001

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 (240) hide show
  1. package/README.md +17 -6
  2. package/dist/artifacts.d.ts +1 -0
  3. package/dist/artifacts.js +22 -15
  4. package/dist/artifacts.js.map +1 -1
  5. package/dist/{browser-viewer-WGJ43YGI.js → browser-viewer-CV23VIHB.js} +8 -6
  6. package/dist/chunk-3ZC6QPOM.js +174 -0
  7. package/dist/chunk-3ZC6QPOM.js.map +1 -0
  8. package/dist/{chunk-YVFRBXST.js → chunk-4BCVCJSU.js} +2 -2
  9. package/dist/{chunk-JHTIMBOL.js → chunk-5JSUNNQN.js} +26 -4
  10. package/dist/{chunk-JHTIMBOL.js.map → chunk-5JSUNNQN.js.map} +1 -1
  11. package/dist/{chunk-MDIXFKA3.js → chunk-6FOTSVWU.js} +303 -109
  12. package/dist/chunk-6FOTSVWU.js.map +1 -0
  13. package/dist/{chunk-IUHHPMAX.js → chunk-7RRBX5EM.js} +14 -85
  14. package/dist/chunk-7RRBX5EM.js.map +1 -0
  15. package/dist/{chunk-L2J3PU7A.js → chunk-7ZB7I3KP.js} +24 -98
  16. package/dist/chunk-7ZB7I3KP.js.map +1 -0
  17. package/dist/{chunk-LVS3MH5T.js → chunk-ATIRUHBZ.js} +128 -10
  18. package/dist/chunk-ATIRUHBZ.js.map +1 -0
  19. package/dist/chunk-BOFEQC6K.js +162 -0
  20. package/dist/chunk-BOFEQC6K.js.map +1 -0
  21. package/dist/{chunk-VCSERYXH.js → chunk-CESBPQP5.js} +309 -162
  22. package/dist/chunk-CESBPQP5.js.map +1 -0
  23. package/dist/{chunk-IYQCWGU5.js → chunk-GHJU7XG7.js} +35 -62
  24. package/dist/chunk-GHJU7XG7.js.map +1 -0
  25. package/dist/{chunk-G6YRCIYJ.js → chunk-HNVWMDNN.js} +55 -60
  26. package/dist/chunk-HNVWMDNN.js.map +1 -0
  27. package/dist/{chunk-PHBFJCEU.js → chunk-I5EGRXXG.js} +110 -7
  28. package/dist/chunk-I5EGRXXG.js.map +1 -0
  29. package/dist/{chunk-PBCZL4JP.js → chunk-INIZSNXT.js} +2 -2
  30. package/dist/{chunk-XS67YG5R.js → chunk-IX3K4THH.js} +24 -3
  31. package/dist/chunk-IX3K4THH.js.map +1 -0
  32. package/dist/chunk-IZV5FTJC.js +55 -0
  33. package/dist/chunk-IZV5FTJC.js.map +1 -0
  34. package/dist/chunk-JDJJMBB3.js +1883 -0
  35. package/dist/chunk-JDJJMBB3.js.map +1 -0
  36. package/dist/{chunk-C5BF4L26.js → chunk-KHF2VRXF.js} +7 -7
  37. package/dist/{chunk-QMMCJGFI.js → chunk-L5OKM2VX.js} +2 -2
  38. package/dist/chunk-LHF6BVM4.js +83 -0
  39. package/dist/chunk-LHF6BVM4.js.map +1 -0
  40. package/dist/chunk-N7S72EXK.js +25 -0
  41. package/dist/chunk-N7S72EXK.js.map +1 -0
  42. package/dist/{chunk-CVYCLFMH.js → chunk-PEHTX3V7.js} +19 -1
  43. package/dist/chunk-PEHTX3V7.js.map +1 -0
  44. package/dist/chunk-R5R5RQQD.js +51 -0
  45. package/dist/chunk-R5R5RQQD.js.map +1 -0
  46. package/dist/chunk-RI42H5IU.js +326 -0
  47. package/dist/chunk-RI42H5IU.js.map +1 -0
  48. package/dist/{chunk-JH7V627O.js → chunk-SHLZMAJN.js} +2 -11
  49. package/dist/chunk-SHLZMAJN.js.map +1 -0
  50. package/dist/{chunk-CREMJMVN.js → chunk-TZQSHCZN.js} +692 -1996
  51. package/dist/chunk-TZQSHCZN.js.map +1 -0
  52. package/dist/chunk-ZIB4H5LN.js +101 -0
  53. package/dist/chunk-ZIB4H5LN.js.map +1 -0
  54. package/dist/client.d.ts +9 -3
  55. package/dist/clipboard.js +1 -1
  56. package/dist/components/browser-viewer.d.ts +6 -0
  57. package/dist/components/composer.d.ts +3 -69
  58. package/dist/components/human-input-form.d.ts +3 -32
  59. package/dist/components/markdown.d.ts +8 -0
  60. package/dist/components/model-policy-picker.d.ts +4 -37
  61. package/dist/components/opper-mark.d.ts +7 -0
  62. package/dist/components/provider-recovery-notice.d.ts +15 -0
  63. package/dist/components/remark-soft-line-breaks.d.ts +38 -0
  64. package/dist/components/sandbox-workspace.d.ts +13 -0
  65. package/dist/components/session-chrome.d.ts +5 -3
  66. package/dist/components/session-conversation.d.ts +15 -3
  67. package/dist/composer-messages.d.ts +74 -0
  68. package/dist/composer-messages.js +9 -0
  69. package/dist/composer.js +15 -10
  70. package/dist/{computer-viewer-46UIN7F3.js → computer-viewer-K4CKYRX6.js} +4 -4
  71. package/dist/connect-setup.d.ts +2 -0
  72. package/dist/connect.d.ts +1 -1
  73. package/dist/connect.js +21 -6
  74. package/dist/connect.js.map +1 -1
  75. package/dist/{embedded-voice-NIL4RDX3.js → embedded-voice-3ZFWWJ6O.js} +6 -4
  76. package/dist/{embedded-voice-NIL4RDX3.js.map → embedded-voice-3ZFWWJ6O.js.map} +1 -1
  77. package/dist/hooks/shared-machines-list.d.ts +4 -0
  78. package/dist/hooks/use-client-config-flags.d.ts +6 -0
  79. package/dist/hooks/use-computer-session.d.ts +2 -0
  80. package/dist/hooks/use-goal.d.ts +2 -1
  81. package/dist/human-input-model.d.ts +40 -0
  82. package/dist/index.d.ts +4 -1
  83. package/dist/index.js +116 -73
  84. package/dist/index.js.map +1 -1
  85. package/dist/interaction.js +5 -5
  86. package/dist/{latest-question-2POFPYNB.js → latest-question-SWC6QEVN.js} +3 -3
  87. package/dist/lib/clipboard.d.ts +7 -0
  88. package/dist/lib/provider-recovery.d.ts +49 -0
  89. package/dist/machines.js +2 -2
  90. package/dist/model-mark-paths.d.ts +34 -0
  91. package/dist/model-mark-paths.js +16 -0
  92. package/dist/model-picker-model.d.ts +111 -0
  93. package/dist/model-picker-model.js +25 -0
  94. package/dist/model-picker-model.js.map +1 -0
  95. package/dist/{model-policy-picker-menu-WRNSRFQC.js → model-policy-picker-menu-NM4RPTY6.js} +6 -4
  96. package/dist/model-policy-picker-menu-NM4RPTY6.js.map +1 -0
  97. package/dist/model-policy.d.ts +10 -0
  98. package/dist/model-policy.js +5 -1
  99. package/dist/organization-model.d.ts +32 -0
  100. package/dist/organization-model.js +65 -0
  101. package/dist/organization-model.js.map +1 -0
  102. package/dist/{platform-activity-row-PJJVATTZ.js → platform-activity-row-NJ47YBXW.js} +7 -84
  103. package/dist/platform-activity-row-NJ47YBXW.js.map +1 -0
  104. package/dist/queue-presentation-model.d.ts +72 -0
  105. package/dist/queue-presentation-model.js +38 -0
  106. package/dist/queue-presentation-model.js.map +1 -0
  107. package/dist/{queue-surface-implementation-67FS7FUI.js → queue-surface-implementation-YPJFQ3O6.js} +24 -252
  108. package/dist/queue-surface-implementation-YPJFQ3O6.js.map +1 -0
  109. package/dist/realtime.js +5 -3
  110. package/dist/{sandbox-files-34CJJNOY.js → sandbox-files-RCVCMXG7.js} +5 -5
  111. package/dist/sandbox-files-RCVCMXG7.js.map +1 -0
  112. package/dist/sandbox-label-model.d.ts +23 -0
  113. package/dist/sandbox-label-model.js +28 -0
  114. package/dist/sandbox-label-model.js.map +1 -0
  115. package/dist/session-attention-model.d.ts +8 -0
  116. package/dist/session-attention-model.js +46 -0
  117. package/dist/session-attention-model.js.map +1 -0
  118. package/dist/session-feedback-model.d.ts +20 -0
  119. package/dist/session-feedback-model.js +56 -0
  120. package/dist/session-feedback-model.js.map +1 -0
  121. package/dist/session-list-model.d.ts +96 -0
  122. package/dist/session-list-model.js +219 -0
  123. package/dist/session-list-model.js.map +1 -0
  124. package/dist/session-status-model.d.ts +19 -0
  125. package/dist/session-ui.js +26 -17
  126. package/dist/session-ui.js.map +1 -1
  127. package/dist/session.js +8 -6
  128. package/dist/testing/session-scenarios.d.ts +10 -0
  129. package/dist/testing/session-scenarios.js +303 -0
  130. package/dist/testing/session-scenarios.js.map +1 -0
  131. package/dist/timeline/genie-copy.d.ts +3 -0
  132. package/dist/timeline/genie-loading.d.ts +11 -0
  133. package/dist/timeline/index.d.ts +1 -1
  134. package/dist/timeline/notice-presentation.d.ts +7 -0
  135. package/dist/timeline/patch-apply-command.d.ts +18 -0
  136. package/dist/timeline/platform-activity-presentation.d.ts +7 -0
  137. package/dist/timeline/presented-image.d.ts +6 -1
  138. package/dist/timeline/question-nav-model.d.ts +23 -0
  139. package/dist/timeline/registry.d.ts +10 -1
  140. package/dist/timeline/retained-loaders.d.ts +1 -1
  141. package/dist/timeline/tool-presentation.d.ts +172 -0
  142. package/dist/timeline/turn-summary-model.d.ts +90 -0
  143. package/dist/timeline/turn-summary.d.ts +4 -74
  144. package/dist/timeline/work-presentation.d.ts +42 -0
  145. package/dist/timeline-model.d.ts +24 -0
  146. package/dist/timeline-model.js +152 -0
  147. package/dist/timeline-model.js.map +1 -0
  148. package/package.json +47 -3
  149. package/src/artifacts.ts +1 -0
  150. package/src/client.ts +9 -3
  151. package/src/components/browser-viewer.tsx +23 -2
  152. package/src/components/claude-mark.tsx +2 -1
  153. package/src/components/composer.tsx +4 -144
  154. package/src/components/computer-viewer.tsx +139 -30
  155. package/src/components/grok-mark.tsx +2 -1
  156. package/src/components/human-input-form.tsx +13 -124
  157. package/src/components/markdown.tsx +19 -1
  158. package/src/components/message-timeline.tsx +45 -99
  159. package/src/components/model-mark.tsx +2 -1
  160. package/src/components/model-policy-picker-menu.tsx +30 -85
  161. package/src/components/model-policy-picker.tsx +15 -148
  162. package/src/components/opper-mark.tsx +18 -0
  163. package/src/components/provider-recovery-notice.tsx +41 -0
  164. package/src/components/queue-surface-implementation.tsx +20 -349
  165. package/src/components/remark-soft-line-breaks.ts +166 -0
  166. package/src/components/sandbox-workspace.tsx +17 -1
  167. package/src/components/session-chrome.tsx +114 -99
  168. package/src/components/session-conversation.tsx +55 -6
  169. package/src/components/session-list.tsx +1 -1
  170. package/src/components/session-status.tsx +17 -16
  171. package/src/composer-messages.ts +150 -0
  172. package/src/connect-setup.tsx +45 -11
  173. package/src/connect.ts +1 -1
  174. package/src/hooks/shared-machines-list.ts +34 -1
  175. package/src/hooks/use-browser-session.ts +445 -168
  176. package/src/hooks/use-client-config-flags.ts +8 -0
  177. package/src/hooks/use-computer-session.ts +334 -98
  178. package/src/hooks/use-goal.ts +66 -10
  179. package/src/human-input-model.ts +147 -0
  180. package/src/index.ts +16 -0
  181. package/src/lib/clipboard.ts +29 -0
  182. package/src/lib/format.ts +7 -0
  183. package/src/lib/provider-recovery.ts +202 -0
  184. package/src/model-mark-paths.ts +53 -0
  185. package/src/model-picker-model.ts +330 -0
  186. package/src/model-policy.ts +43 -2
  187. package/src/organization-model.ts +118 -0
  188. package/src/queue-presentation-model.ts +464 -0
  189. package/src/sandbox-label-model.ts +41 -0
  190. package/src/session-attention-model.ts +59 -0
  191. package/src/session-feedback-model.ts +95 -0
  192. package/src/session-list-model.ts +327 -0
  193. package/src/session-status-model.ts +62 -0
  194. package/src/testing/session-scenarios.ts +326 -0
  195. package/src/timeline/activity-rail.tsx +5 -17
  196. package/src/timeline/genie-copy.ts +19 -0
  197. package/src/timeline/genie-loading.tsx +13 -18
  198. package/src/timeline/index.ts +1 -0
  199. package/src/timeline/notice-presentation.ts +22 -0
  200. package/src/timeline/patch-apply-command.tsx +135 -0
  201. package/src/timeline/platform-activity-presentation.ts +122 -0
  202. package/src/timeline/platform-activity-row.tsx +6 -96
  203. package/src/timeline/presented-image.ts +16 -2
  204. package/src/timeline/question-nav-model.ts +28 -0
  205. package/src/timeline/registry.ts +11 -1
  206. package/src/timeline/retained-loaders.ts +9 -4
  207. package/src/timeline/rolling-activity.tsx +7 -19
  208. package/src/timeline/tool-presentation.ts +1316 -0
  209. package/src/timeline/tool-renderers.tsx +226 -1025
  210. package/src/timeline/turn-summary-model.ts +338 -0
  211. package/src/timeline/turn-summary.tsx +21 -326
  212. package/src/timeline/work-presentation.ts +139 -0
  213. package/src/timeline-model.ts +108 -0
  214. package/styles/compiled.css +8 -0
  215. package/styles/connect.css +4 -0
  216. package/dist/chunk-CREMJMVN.js.map +0 -1
  217. package/dist/chunk-CVYCLFMH.js.map +0 -1
  218. package/dist/chunk-G6YRCIYJ.js.map +0 -1
  219. package/dist/chunk-HXYOSSQO.js +0 -117
  220. package/dist/chunk-HXYOSSQO.js.map +0 -1
  221. package/dist/chunk-IUHHPMAX.js.map +0 -1
  222. package/dist/chunk-IYQCWGU5.js.map +0 -1
  223. package/dist/chunk-JH7V627O.js.map +0 -1
  224. package/dist/chunk-L2J3PU7A.js.map +0 -1
  225. package/dist/chunk-LVS3MH5T.js.map +0 -1
  226. package/dist/chunk-MDIXFKA3.js.map +0 -1
  227. package/dist/chunk-PHBFJCEU.js.map +0 -1
  228. package/dist/chunk-VCSERYXH.js.map +0 -1
  229. package/dist/chunk-XS67YG5R.js.map +0 -1
  230. package/dist/platform-activity-row-PJJVATTZ.js.map +0 -1
  231. package/dist/queue-surface-implementation-67FS7FUI.js.map +0 -1
  232. /package/dist/{browser-viewer-WGJ43YGI.js.map → browser-viewer-CV23VIHB.js.map} +0 -0
  233. /package/dist/{chunk-YVFRBXST.js.map → chunk-4BCVCJSU.js.map} +0 -0
  234. /package/dist/{chunk-PBCZL4JP.js.map → chunk-INIZSNXT.js.map} +0 -0
  235. /package/dist/{chunk-C5BF4L26.js.map → chunk-KHF2VRXF.js.map} +0 -0
  236. /package/dist/{chunk-QMMCJGFI.js.map → chunk-L5OKM2VX.js.map} +0 -0
  237. /package/dist/{computer-viewer-46UIN7F3.js.map → composer-messages.js.map} +0 -0
  238. /package/dist/{model-policy-picker-menu-WRNSRFQC.js.map → computer-viewer-K4CKYRX6.js.map} +0 -0
  239. /package/dist/{latest-question-2POFPYNB.js.map → latest-question-SWC6QEVN.js.map} +0 -0
  240. /package/dist/{sandbox-files-34CJJNOY.js.map → model-mark-paths.js.map} +0 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Queue presentation shared by the web queue surface and native docks: the
3
+ * bounded head/tail previews of queued prompts, and the reorder plan and its
4
+ * optimistic projection. No DOM, no React.
5
+ */
6
+ import type { SessionQueueSnapshot, SessionTurn } from "@opengeni/sdk";
7
+ import { QUEUE_ITEM_CONTENT_UNAVAILABLE, queueItemContent } from "./components/queue-item-content.js";
8
+ export { QUEUE_ITEM_CONTENT_UNAVAILABLE, queueItemContent };
9
+ export declare const QUEUE_ROW_PREVIEW_CHARACTERS = 360;
10
+ export declare const QUEUE_COLLAPSED_PREVIEW_CHARACTERS = 180;
11
+ export type QueuePromptPreview = {
12
+ summary: string;
13
+ collapsedVisual: string;
14
+ visibleStart: string;
15
+ visibleIdentity: string | null;
16
+ visibleIdentityLabel: "End" | "Safe boundary" | null;
17
+ isFallback: boolean;
18
+ };
19
+ export declare function queueTurnPreview(turn: SessionTurn | undefined, maxCharacters: number): QueuePromptPreview;
20
+ export declare function queueContentPreview(prompt: string, annotationCount: number, maxCharacters: number): QueuePromptPreview;
21
+ /**
22
+ * Build a bounded head/tail summary of an arbitrary queued prompt. Sampling
23
+ * both ends distinguishes prompts with equal long prefixes. Each sampled edge
24
+ * has a small amount of grapheme context so ordinary emoji/combining sequences
25
+ * can be retained whole. A cluster that exceeds that context is omitted rather
26
+ * than fragmented, and malformed UTF-16 is replaced only in the summary. The
27
+ * durable prompt remains exact and no operation scans or copies it in full.
28
+ */
29
+ export declare function queuePromptPreview(prompt: string, maxCharacters: number): QueuePromptPreview;
30
+ /** Move one item, as dnd-kit's arrayMove does. */
31
+ export declare function moveQueueItem<T>(items: readonly T[], from: number, to: number): T[];
32
+ export type QueueMovePlan = {
33
+ /** The turn ids in their new order. */
34
+ turnIds: string[];
35
+ /** The server anchor: the turn the moved one now precedes, null for last. */
36
+ beforeTurnId: string | null;
37
+ /** The bounded destination index. */
38
+ index: number;
39
+ };
40
+ /** The reorder request for moving a queued turn to an index, or null for a no-op. */
41
+ export declare function queueMovePlan(queue: readonly SessionTurn[], turnId: string, nextIndex: number): QueueMovePlan | null;
42
+ export type PendingQueueMove = {
43
+ baseVersion: number | null;
44
+ turnIds: string[];
45
+ };
46
+ /**
47
+ * The queue as shown while a move is in flight: the optimistic order, unless
48
+ * any authoritative change arrived. A projection never omits or invents a row.
49
+ */
50
+ export declare function projectPendingQueueMove(queue: SessionTurn[], pendingMove: PendingQueueMove | null, snapshot: Pick<SessionQueueSnapshot, "version"> | null): SessionTurn[];
51
+ /** Copy for the "replace your draft with this queued prompt" confirmation. */
52
+ export declare const QUEUE_REPLACE_DRAFT_COPY: {
53
+ readonly title: "Your composer already has a draft. Replace it with this queued prompt?";
54
+ readonly detail: "The current draft will be permanently discarded; this queued prompt is preserved until you confirm.";
55
+ readonly keep: "Keep current draft";
56
+ readonly replace: "Replace and edit";
57
+ };
58
+ export type QueuedTurnPresentation = {
59
+ kind: "prompt" | "realtime_voice" | "realtime_voice_handoff";
60
+ text: string;
61
+ };
62
+ /** What a queued row shows: the prompt, or the transcript of a voice request. */
63
+ export declare function queuedTurnPresentation(turn: SessionTurn): QueuedTurnPresentation;
64
+ export declare function isSteeringTurn(turn: SessionTurn): boolean;
65
+ /** A queued turn that is really waiting: not already a steer in flight. */
66
+ export declare function isAuthoritativeQueuedTurn(turn: SessionTurn, mutationFor: (turnId: string) => string | null): boolean;
67
+ export declare function countAuthoritativeQueuedTurns(turns: readonly SessionTurn[], mutationFor: (turnId: string) => string | null): number;
68
+ /** The move anchors for one row's Move up / Move down. */
69
+ export declare function queueNeighborAnchors(turns: readonly SessionTurn[], index: number): {
70
+ beforeUp: string | null;
71
+ beforeDown: string | null;
72
+ };
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import {
3
+ QUEUE_COLLAPSED_PREVIEW_CHARACTERS,
4
+ QUEUE_ITEM_CONTENT_UNAVAILABLE,
5
+ QUEUE_REPLACE_DRAFT_COPY,
6
+ QUEUE_ROW_PREVIEW_CHARACTERS,
7
+ countAuthoritativeQueuedTurns,
8
+ isAuthoritativeQueuedTurn,
9
+ isSteeringTurn,
10
+ moveQueueItem,
11
+ projectPendingQueueMove,
12
+ queueContentPreview,
13
+ queueItemContent,
14
+ queueMovePlan,
15
+ queueNeighborAnchors,
16
+ queuePromptPreview,
17
+ queueTurnPreview,
18
+ queuedTurnPresentation
19
+ } from "./chunk-RI42H5IU.js";
20
+ export {
21
+ QUEUE_COLLAPSED_PREVIEW_CHARACTERS,
22
+ QUEUE_ITEM_CONTENT_UNAVAILABLE,
23
+ QUEUE_REPLACE_DRAFT_COPY,
24
+ QUEUE_ROW_PREVIEW_CHARACTERS,
25
+ countAuthoritativeQueuedTurns,
26
+ isAuthoritativeQueuedTurn,
27
+ isSteeringTurn,
28
+ moveQueueItem,
29
+ projectPendingQueueMove,
30
+ queueContentPreview,
31
+ queueItemContent,
32
+ queueMovePlan,
33
+ queueNeighborAnchors,
34
+ queuePromptPreview,
35
+ queueTurnPreview,
36
+ queuedTurnPresentation
37
+ };
38
+ //# sourceMappingURL=queue-presentation-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,14 +1,24 @@
1
1
  "use client";
2
2
  import {
3
- QUEUE_ITEM_CONTENT_UNAVAILABLE,
4
3
  QueueErrorAlert,
5
4
  QueueStoppingStatus,
6
5
  TimelineAnnotationsChip,
7
- queueItemContent,
8
6
  requestQueueDraftEdit
9
- } from "./chunk-JH7V627O.js";
7
+ } from "./chunk-SHLZMAJN.js";
10
8
  import "./chunk-2HVLQ26H.js";
11
9
  import "./chunk-LJUMYUBO.js";
10
+ import {
11
+ QUEUE_COLLAPSED_PREVIEW_CHARACTERS,
12
+ QUEUE_ITEM_CONTENT_UNAVAILABLE,
13
+ QUEUE_REPLACE_DRAFT_COPY,
14
+ QUEUE_ROW_PREVIEW_CHARACTERS,
15
+ projectPendingQueueMove,
16
+ queueContentPreview,
17
+ queueItemContent,
18
+ queueMovePlan,
19
+ queuePromptPreview,
20
+ queueTurnPreview
21
+ } from "./chunk-RI42H5IU.js";
12
22
  import "./chunk-S2QH6EZ5.js";
13
23
  import {
14
24
  MENU_ITEM_CLASS,
@@ -100,29 +110,18 @@ function QueueSurface({
100
110
  if (oldIndex < 0) return queue.queue;
101
111
  return arrayMove(queue.queue, oldIndex, keyboardDrag.projectedIndex);
102
112
  }
103
- if (!pendingMove || pendingMove.baseVersion === null || queue.snapshot?.version !== pendingMove.baseVersion) {
104
- return queue.queue;
105
- }
106
- const byId = new Map(queue.queue.map((turn) => [turn.id, turn]));
107
- const projected = pendingMove.turnIds.map((turnId) => byId.get(turnId));
108
- if (projected.some((turn) => !turn) || projected.length !== queue.queue.length) {
109
- return queue.queue;
110
- }
111
- return projected;
112
- }, [keyboardDrag, pendingMove, queue.queue, queue.snapshot?.version]);
113
+ return projectPendingQueueMove(queue.queue, pendingMove, queue.snapshot);
114
+ }, [keyboardDrag, pendingMove, queue.queue, queue.snapshot]);
113
115
  const ids = useMemo(() => displayedQueue.map((turn) => turn.id), [displayedQueue]);
114
116
  const moveToIndex = useCallback(
115
117
  async (turnId, nextIndex) => {
116
118
  if (queue.mutating || pendingMove) return;
117
- const oldIndex = queue.queue.findIndex((turn) => turn.id === turnId);
118
- if (oldIndex < 0) return;
119
- const boundedIndex = Math.max(0, Math.min(nextIndex, queue.queue.length - 1));
120
- if (oldIndex === boundedIndex) return;
121
- const ordered = arrayMove(queue.queue, oldIndex, boundedIndex);
122
- const beforeTurnId = ordered[boundedIndex + 1]?.id ?? null;
119
+ const plan = queueMovePlan(queue.queue, turnId, nextIndex);
120
+ if (!plan) return;
121
+ const { beforeTurnId, index: boundedIndex } = plan;
123
122
  setPendingMove({
124
123
  baseVersion: queue.snapshot?.version ?? null,
125
- turnIds: ordered.map((turn) => turn.id)
124
+ turnIds: plan.turnIds
126
125
  });
127
126
  setAnnouncement(`Saving queued prompt at position ${boundedIndex + 1}.`);
128
127
  try {
@@ -428,233 +427,6 @@ function PendingMachineInputs({
428
427
  )) })
429
428
  ] });
430
429
  }
431
- var QUEUE_ROW_PREVIEW_CHARACTERS = 360;
432
- var QUEUE_COLLAPSED_PREVIEW_CHARACTERS = 180;
433
- var QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS = 32;
434
- var QUEUE_PREVIEW_REFERENCE_SAMPLE_CHARACTERS = 32;
435
- var QUEUE_VISIBLE_END_IDENTITY_CHARACTERS = 18;
436
- var QUEUE_PREVIEW_SEPARATOR = " \u2026 ";
437
- var queuePreviewSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
438
- var queuePromptNonRenderingCodePoint = /[\p{White_Space}\p{Control}\p{Default_Ignorable_Code_Point}]/u;
439
- function labelQueuePreview(summary) {
440
- return {
441
- summary,
442
- collapsedVisual: summary,
443
- visibleStart: summary,
444
- visibleIdentity: null,
445
- visibleIdentityLabel: null,
446
- isFallback: false
447
- };
448
- }
449
- function queueTurnPreview(turn, maxCharacters) {
450
- if (!turn) return queuePromptPreview("", maxCharacters);
451
- return queueContentPreview(turn.prompt, turn.annotations?.length ?? 0, maxCharacters);
452
- }
453
- function queueContentPreview(prompt, annotationCount, maxCharacters) {
454
- switch (queueItemContent(prompt, annotationCount)) {
455
- case "text":
456
- return queuePromptPreview(prompt, maxCharacters);
457
- case "annotations":
458
- return labelQueuePreview(
459
- `${annotationCount} timeline ${annotationCount === 1 ? "annotation" : "annotations"}`
460
- );
461
- case "unavailable":
462
- return labelQueuePreview(QUEUE_ITEM_CONTENT_UNAVAILABLE);
463
- }
464
- }
465
- function queuePromptPreview(prompt, maxCharacters) {
466
- const wholePromptProbe = samplePromptStart(prompt, maxCharacters + 1);
467
- if (!wholePromptProbe.truncated && wholePromptProbe.characters <= maxCharacters) {
468
- const summary2 = replaceLoneSurrogates(wholePromptProbe.value);
469
- return hasVisiblePromptContent(summary2) ? {
470
- summary: summary2,
471
- collapsedVisual: summary2,
472
- visibleStart: summary2,
473
- visibleIdentity: null,
474
- visibleIdentityLabel: null,
475
- isFallback: false
476
- } : fallbackPromptPreview(prompt.length, wholePromptProbe.value, wholePromptProbe.value);
477
- }
478
- const suffixCharacters = Math.min(Math.floor(maxCharacters / 3), 120);
479
- const prefixCharacters = maxCharacters - codePointLength(QUEUE_PREVIEW_SEPARATOR) - suffixCharacters;
480
- const prefixSample = samplePromptStart(
481
- prompt,
482
- prefixCharacters + QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS
483
- );
484
- const suffixSample = samplePromptEnd(
485
- prompt,
486
- suffixCharacters + QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS
487
- );
488
- const prefixSegments = segmentPromptSample(prefixSample.value);
489
- const suffixSegments = segmentPromptSample(suffixSample.value);
490
- if (prefixSample.truncated) prefixSegments.pop();
491
- if (suffixSample.truncated) {
492
- let ambiguousSegment = suffixSegments.shift();
493
- while (ambiguousSegment?.endsWith("\u200D") && suffixSegments.length > 0) {
494
- ambiguousSegment = suffixSegments.shift();
495
- }
496
- while (suffixSegments[0] && startsWithRegionalIndicator(suffixSegments[0])) {
497
- suffixSegments.shift();
498
- }
499
- }
500
- const prefix = takeWholeGraphemesFromStart(prefixSegments, prefixCharacters);
501
- const suffix = takeWholeGraphemesFromEnd(suffixSegments, suffixCharacters);
502
- const reference = boundedPromptSampleReference(
503
- prompt.length,
504
- prefixSample.value,
505
- suffixSample.value
506
- );
507
- if (!hasVisiblePromptContent(prefix) && !hasVisiblePromptContent(suffix)) {
508
- return fallbackPromptPreview(prompt.length, prefixSample.value, suffixSample.value);
509
- }
510
- const safeSuffix = hasVisiblePromptContent(suffix) ? suffix : promptPreviewFallbackLabel(reference);
511
- const summary = `${prefix}${QUEUE_PREVIEW_SEPARATOR}${safeSuffix}`;
512
- if (!hasVisiblePromptContent(prefix)) {
513
- return {
514
- summary,
515
- collapsedVisual: summary,
516
- visibleStart: safeSuffix,
517
- visibleIdentity: null,
518
- visibleIdentityLabel: null,
519
- isFallback: false
520
- };
521
- }
522
- const endIdentity = takeWholeGraphemesFromEnd(
523
- suffixSegments,
524
- QUEUE_VISIBLE_END_IDENTITY_CHARACTERS
525
- );
526
- return {
527
- summary,
528
- collapsedVisual: summary,
529
- visibleStart: prefix,
530
- visibleIdentity: hasVisiblePromptContent(endIdentity) ? endIdentity : `ref ${reference}`,
531
- visibleIdentityLabel: hasVisiblePromptContent(endIdentity) ? "End" : "Safe boundary",
532
- isFallback: false
533
- };
534
- }
535
- function fallbackPromptPreview(promptLength, startSample, endSample) {
536
- const reference = boundedPromptSampleReference(promptLength, startSample, endSample);
537
- const summary = promptPreviewFallbackLabel(reference);
538
- return {
539
- summary,
540
- collapsedVisual: `Omitted \xB7 ${reference}`,
541
- // The complete fallback remains the canonical accessible summary. Narrow
542
- // collapsed/row layouts paint the bounded reference in a compact truthful
543
- // form so ellipsis cannot hide the only identifying portion.
544
- visibleStart: `Omitted \xB7 ${reference}`,
545
- visibleIdentity: null,
546
- visibleIdentityLabel: null,
547
- isFallback: true
548
- };
549
- }
550
- function promptPreviewFallbackLabel(reference) {
551
- return `Content omitted at safe boundary \xB7 ref ${reference}`;
552
- }
553
- function boundedPromptSampleReference(promptLength, startSample, endSample) {
554
- const head = samplePromptStart(startSample, QUEUE_PREVIEW_REFERENCE_SAMPLE_CHARACTERS).value;
555
- const tail = samplePromptEnd(endSample, QUEUE_PREVIEW_REFERENCE_SAMPLE_CHARACTERS).value;
556
- let hash = 2166136261;
557
- for (const value of [String(promptLength), head, tail]) {
558
- for (let index = 0; index < value.length; index += 1) {
559
- hash ^= value.charCodeAt(index);
560
- hash = Math.imul(hash, 16777619);
561
- }
562
- hash ^= 65535;
563
- hash = Math.imul(hash, 16777619);
564
- }
565
- return (hash >>> 0).toString(16).padStart(8, "0").toUpperCase();
566
- }
567
- function hasVisiblePromptContent(value) {
568
- for (const character of value) {
569
- if (!queuePromptNonRenderingCodePoint.test(character)) return true;
570
- }
571
- return false;
572
- }
573
- function samplePromptStart(prompt, maxCharacters) {
574
- let end = 0;
575
- let characters = 0;
576
- while (end < prompt.length && characters < maxCharacters) {
577
- const first = prompt.charCodeAt(end);
578
- end += isHighSurrogate(first) && end + 1 < prompt.length && isLowSurrogate(prompt.charCodeAt(end + 1)) ? 2 : 1;
579
- characters += 1;
580
- }
581
- return { value: prompt.slice(0, end), characters, truncated: end < prompt.length };
582
- }
583
- function samplePromptEnd(prompt, maxCharacters) {
584
- let start = prompt.length;
585
- let characters = 0;
586
- while (start > 0 && characters < maxCharacters) {
587
- start -= 1;
588
- if (isLowSurrogate(prompt.charCodeAt(start)) && start > 0 && isHighSurrogate(prompt.charCodeAt(start - 1))) {
589
- start -= 1;
590
- }
591
- characters += 1;
592
- }
593
- return { value: prompt.slice(start), characters, truncated: start > 0 };
594
- }
595
- function segmentPromptSample(sample) {
596
- return Array.from(
597
- queuePreviewSegmenter.segment(replaceLoneSurrogates(sample)),
598
- ({ segment }) => segment
599
- );
600
- }
601
- function replaceLoneSurrogates(value) {
602
- let sanitized = "";
603
- for (let index = 0; index < value.length; index += 1) {
604
- const current = value.charCodeAt(index);
605
- if (isHighSurrogate(current) && index + 1 < value.length && isLowSurrogate(value.charCodeAt(index + 1))) {
606
- sanitized += value.slice(index, index + 2);
607
- index += 1;
608
- } else if (isHighSurrogate(current) || isLowSurrogate(current)) {
609
- sanitized += "\uFFFD";
610
- } else {
611
- sanitized += value[index];
612
- }
613
- }
614
- return sanitized;
615
- }
616
- function takeWholeGraphemesFromStart(segments, maxCharacters) {
617
- const selected = [];
618
- let characters = 0;
619
- for (const segment of segments) {
620
- const segmentCharacters = codePointLength(segment);
621
- if (characters + segmentCharacters > maxCharacters) break;
622
- selected.push(segment);
623
- characters += segmentCharacters;
624
- }
625
- while (selected.at(-1)?.trim().length === 0) selected.pop();
626
- return selected.join("");
627
- }
628
- function takeWholeGraphemesFromEnd(segments, maxCharacters) {
629
- const selected = [];
630
- let characters = 0;
631
- for (let index = segments.length - 1; index >= 0; index -= 1) {
632
- const segment = segments[index];
633
- if (!segment) continue;
634
- const segmentCharacters = codePointLength(segment);
635
- if (characters + segmentCharacters > maxCharacters) break;
636
- selected.unshift(segment);
637
- characters += segmentCharacters;
638
- }
639
- while (selected[0]?.trim().length === 0) selected.shift();
640
- while (selected.at(-1)?.trim().length === 0) selected.pop();
641
- return selected.join("");
642
- }
643
- function codePointLength(value) {
644
- let characters = 0;
645
- for (const _character of value) characters += 1;
646
- return characters;
647
- }
648
- function startsWithRegionalIndicator(value) {
649
- const codePoint = value.codePointAt(0);
650
- return codePoint !== void 0 && codePoint >= 127462 && codePoint <= 127487;
651
- }
652
- function isHighSurrogate(codeUnit) {
653
- return codeUnit >= 55296 && codeUnit <= 56319;
654
- }
655
- function isLowSurrogate(codeUnit) {
656
- return codeUnit >= 56320 && codeUnit <= 57343;
657
- }
658
430
  function QueuePrompt({
659
431
  prompt,
660
432
  annotations,
@@ -1011,8 +783,8 @@ function SortableQueueRow({
1011
783
  ] })
1012
784
  ] }),
1013
785
  confirmingReplace ? /* @__PURE__ */ jsxs("div", { className: "mx-3 mb-2 rounded-md border border-status-waiting/30 bg-status-waiting/10 p-2 text-og-control text-fg", children: [
1014
- /* @__PURE__ */ jsx("p", { children: "Your composer already has a draft. Replace it with this queued prompt?" }),
1015
- /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-fg-muted", children: "The current draft will be permanently discarded; this queued prompt is preserved until you confirm." }),
786
+ /* @__PURE__ */ jsx("p", { children: QUEUE_REPLACE_DRAFT_COPY.title }),
787
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-fg-muted", children: QUEUE_REPLACE_DRAFT_COPY.detail }),
1016
788
  /* @__PURE__ */ jsxs("div", { className: "mt-2 flex justify-end gap-1.5", children: [
1017
789
  /* @__PURE__ */ jsx(
1018
790
  "button",
@@ -1020,7 +792,7 @@ function SortableQueueRow({
1020
792
  type: "button",
1021
793
  className: "rounded-md px-2 py-1 font-medium hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring/40",
1022
794
  onClick: onCancelReplace,
1023
- children: "Keep current draft"
795
+ children: QUEUE_REPLACE_DRAFT_COPY.keep
1024
796
  }
1025
797
  ),
1026
798
  /* @__PURE__ */ jsx(
@@ -1029,7 +801,7 @@ function SortableQueueRow({
1029
801
  type: "button",
1030
802
  className: "rounded-md border border-og-primary-border bg-og-primary text-og-primary-fg px-2 py-1 font-medium hover:bg-og-primary-hover focus-visible:ring-2 focus-visible:ring-ring/40",
1031
803
  onClick: onConfirmReplace,
1032
- children: "Replace and edit"
804
+ children: QUEUE_REPLACE_DRAFT_COPY.replace
1033
805
  }
1034
806
  )
1035
807
  ] })
@@ -1075,4 +847,4 @@ export {
1075
847
  QueueSurface,
1076
848
  queueComposerCheckoutEnabled
1077
849
  };
1078
- //# sourceMappingURL=queue-surface-implementation-67FS7FUI.js.map
850
+ //# sourceMappingURL=queue-surface-implementation-YPJFQ3O6.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, TimelineAnnotation } from \"@opengeni/sdk\";\nimport { modelDisplayName } from \"@opengeni/sdk/model-display\";\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 useState,\n type KeyboardEvent as ReactKeyboardEvent,\n} from \"react\";\n\nimport { DropdownMenu } from \"radix-ui\";\nimport { MENU_ITEM_CLASS, MENU_SEPARATOR_CLASS, MENU_SURFACE_CLASS } from \"../lib/menu-styles\";\nimport type { ComposerState } from \"../hooks/use-composer\";\nimport type { QueueMutationKind, UseTurnQueueResult } from \"../hooks/use-turn-queue\";\nimport {\n type PortalTokenStyle,\n usePortalTokenSource,\n usePortalTokenStyle,\n} from \"../lib/use-portal-token-style\";\nimport { requestQueueDraftEdit } from \"./queue-draft-policy\";\nimport {\n projectPendingQueueMove,\n QUEUE_COLLAPSED_PREVIEW_CHARACTERS,\n QUEUE_REPLACE_DRAFT_COPY,\n QUEUE_ROW_PREVIEW_CHARACTERS,\n queueContentPreview,\n queueMovePlan,\n queuePromptPreview,\n queueTurnPreview,\n} from \"../queue-presentation-model\";\nimport { QUEUE_ITEM_CONTENT_UNAVAILABLE, queueItemContent } from \"./queue-item-content\";\nimport { QueueErrorAlert, QueueStoppingStatus } from \"./queue-surface-state\";\nimport { TimelineAnnotationsChip } from \"./timeline-annotations\";\n\n// Queued prompts can be long; menu rows wrap instead of truncating.\nconst QUEUE_MENU_ITEM_CLASS = `${MENU_ITEM_CLASS} whitespace-normal break-words`;\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 [pendingMove, setPendingMove] = useState<{\n baseVersion: number | null;\n turnIds: string[];\n } | null>(null);\n const surface = usePortalTokenSource<HTMLDivElement>();\n const surfaceRef = surface.currentRef;\n const portalTokenStyle = usePortalTokenStyle(surface.source);\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 const firstTurn = queue.queue[0];\n return firstTurn\n ? queueTurnPreview(firstTurn, QUEUE_COLLAPSED_PREVIEW_CHARACTERS)\n : queuePromptPreview(\n queue.pendingInputs[0]?.summary ?? \"\",\n QUEUE_COLLAPSED_PREVIEW_CHARACTERS,\n );\n }, [queue.pendingInputs, queue.queue]);\n const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 6 } }));\n\n const displayedQueue = useMemo(() => {\n if (keyboardDrag) {\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 }\n // Never let an optimistic ordering projection omit or invent a row. Any\n // concurrent authoritative membership change wins immediately.\n return projectPendingQueueMove(queue.queue, pendingMove, queue.snapshot);\n }, [keyboardDrag, pendingMove, queue.queue, queue.snapshot]);\n\n const ids = useMemo(() => displayedQueue.map((turn) => turn.id), [displayedQueue]);\n const moveToIndex = useCallback(\n async (turnId: string, nextIndex: number): Promise<void> => {\n if (queue.mutating || pendingMove) return;\n const plan = queueMovePlan(queue.queue, turnId, nextIndex);\n if (!plan) return;\n const { beforeTurnId, index: boundedIndex } = plan;\n setPendingMove({\n baseVersion: queue.snapshot?.version ?? null,\n turnIds: plan.turnIds,\n });\n setAnnouncement(`Saving queued prompt at position ${boundedIndex + 1}.`);\n try {\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 } finally {\n setPendingMove(null);\n }\n },\n [pendingMove, queue, surfaceRef],\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 setAnnouncement(\"Moving queued prompt to the composer…\");\n const restored = await queue.editTurn(turn.id, {\n expectedDraftRevision: composer.draftRevision,\n replaceDraft,\n });\n if (!restored) {\n setAnnouncement(\"That prompt changed before it could be moved to the composer.\");\n return;\n }\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={surface.ref}\n className=\"og-root 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-hidden 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-og-control 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-og-xs 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-og-control\"\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 reorderDisabled={queue.mutating || pendingMove !== null}\n confirmingReplace={replaceDraftFor === turn.id}\n keyboardDragging={keyboardDrag?.turnId === turn.id}\n portalTokenStyle={portalTokenStyle}\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 setAnnouncement(\"Requesting this queued prompt as the next direction…\");\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 setAnnouncement(\"Deleting queued prompt…\");\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-og-control 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 queueTurnPreview(\n queue.queue.find((turn) => turn.id === draggedTurnId),\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-og-xs 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\n key={input.id}\n className=\"line-clamp-3 break-words text-og-control text-fg\"\n dir=\"auto\"\n >\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\nfunction QueuePrompt({\n prompt,\n annotations,\n index,\n onDisclosureChange,\n}: {\n prompt: string;\n annotations: readonly TimelineAnnotation[];\n index: number;\n onDisclosureChange: (expanded: boolean) => void;\n}) {\n const [expanded, setExpanded] = useState(false);\n const fullContentId = useId();\n const content = queueItemContent(prompt, annotations.length);\n const preview = useMemo(\n () => queueContentPreview(prompt, annotations.length, QUEUE_ROW_PREVIEW_CHARACTERS),\n [annotations.length, prompt],\n );\n\n return (\n <div className=\"w-full min-w-0 max-w-full\">\n {prompt ? (\n <div\n aria-label={`Queued prompt ${index + 1} summary: ${preview.summary}`}\n className=\"max-w-full overflow-hidden text-og-control leading-5 text-fg\"\n data-testid={`queue-prompt-preview-${index + 1}`}\n dir=\"auto\"\n role=\"note\"\n >\n <span\n aria-hidden=\"true\"\n className=\"flex min-w-0 max-w-full items-baseline gap-2 sm:block\"\n >\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-og-xs 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 ) : null}\n {annotations.length > 0 ? (\n <TimelineAnnotationsChip\n annotations={annotations}\n className={prompt ? \"mt-1\" : undefined}\n />\n ) : null}\n {content === \"unavailable\" ? (\n <p\n className=\"text-og-control leading-5 text-fg-muted italic\"\n data-testid={`queue-prompt-unavailable-${index + 1}`}\n >\n {QUEUE_ITEM_CONTENT_UNAVAILABLE}\n </p>\n ) : null}\n {prompt ? (\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-og-xs font-medium text-fg outline-hidden 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 ) : null}\n {expanded && prompt ? (\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-og-control 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-og-xs text-fg-subtle\">{index + 1}</span>\n <div className=\"min-w-0 flex-1\">\n <QueuePrompt\n prompt={turn.prompt}\n annotations={turn.annotations ?? []}\n index={index}\n onDisclosureChange={onDisclosureChange}\n />\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-og-xs 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\">{modelDisplayName(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 reorderDisabled,\n confirmingReplace,\n keyboardDragging,\n portalTokenStyle,\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 reorderDisabled: boolean;\n confirmingReplace: boolean;\n keyboardDragging: boolean;\n portalTokenStyle: PortalTokenStyle;\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: reorderDisabled || 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={reorderDisabled}\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-og-xs 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\n prompt={turn.prompt}\n annotations={turn.annotations ?? []}\n index={index}\n onDisclosureChange={onDisclosureChange}\n />\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-og-xs 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\">{modelDisplayName(turn.model)}</span>\n <span className=\"shrink-0\">{turn.reasoningEffort}</span>\n </div>\n {pending ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"mt-1 flex items-center gap-1.5 text-og-xs font-medium text-status-waiting\"\n data-testid={`queue-mutation-${pending}`}\n >\n <Loader2Icon\n aria-hidden=\"true\"\n className=\"size-3 shrink-0 animate-spin motion-reduce:animate-none\"\n />\n {queueMutationPendingLabel(pending)}\n </div>\n ) : null}\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 data-analytics-action=\"steer\"\n title=\"Steer — interrupt the current turn and send this message now\"\n className=\"inline-flex h-7 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-og-control font-medium text-fg outline-hidden 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-hidden 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-hidden 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 collisionPadding={8}\n className={`${MENU_SURFACE_CLASS} og-root z-50 max-h-(--radix-dropdown-menu-content-available-height) w-52 max-w-[calc(100vw-16px)] overflow-x-hidden overflow-y-auto`}\n style={portalTokenStyle}\n data-testid={`queue-actions-menu-${index + 1}`}\n >\n {onEdit ? (\n <>\n <DropdownMenu.Item className={QUEUE_MENU_ITEM_CLASS} onSelect={onEdit}>\n <PencilIcon /> Edit in composer\n </DropdownMenu.Item>\n <DropdownMenu.Separator className={MENU_SEPARATOR_CLASS} />\n </>\n ) : null}\n <DropdownMenu.Item\n className={QUEUE_MENU_ITEM_CLASS}\n disabled={index === 0}\n onSelect={() => onMove(0)}\n >\n <ArrowUpToLineIcon /> Move to top\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className={QUEUE_MENU_ITEM_CLASS}\n disabled={index === 0}\n onSelect={() => onMove(index - 1)}\n >\n Move up\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className={QUEUE_MENU_ITEM_CLASS}\n disabled={index === count - 1}\n onSelect={() => onMove(index + 1)}\n >\n Move down\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className={QUEUE_MENU_ITEM_CLASS}\n disabled={index === count - 1}\n onSelect={() => onMove(count - 1)}\n >\n <ArrowDownToLineIcon /> 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-og-control text-fg\">\n <p>{QUEUE_REPLACE_DRAFT_COPY.title}</p>\n <p className=\"mt-0.5 text-fg-muted\">{QUEUE_REPLACE_DRAFT_COPY.detail}</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 {QUEUE_REPLACE_DRAFT_COPY.keep}\n </button>\n <button\n type=\"button\"\n className=\"rounded-md border border-og-primary-border bg-og-primary text-og-primary-fg px-2 py-1 font-medium hover:bg-og-primary-hover focus-visible:ring-2 focus-visible:ring-ring/40\"\n onClick={onConfirmReplace}\n >\n {QUEUE_REPLACE_DRAFT_COPY.replace}\n </button>\n </div>\n </div>\n ) : null}\n </li>\n );\n}\n\nfunction queueMutationPendingLabel(kind: QueueMutationKind): string {\n switch (kind) {\n case \"move\":\n return \"Saving new position…\";\n case \"edit\":\n return \"Moving to composer…\";\n case \"steer\":\n return \"Changing direction…\";\n case \"delete\":\n return \"Deleting…\";\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":"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","names":[]}
package/dist/realtime.js CHANGED
@@ -13,12 +13,14 @@ import {
13
13
  useSessionCodexRealtime,
14
14
  useSessionRealtime,
15
15
  useWorkspaceRealtimeModelSelection
16
- } from "./chunk-YVFRBXST.js";
16
+ } from "./chunk-4BCVCJSU.js";
17
17
  import "./chunk-NX4ADH73.js";
18
- import "./chunk-L2J3PU7A.js";
18
+ import "./chunk-7ZB7I3KP.js";
19
19
  import "./chunk-PMV53IMM.js";
20
- import "./chunk-XS67YG5R.js";
20
+ import "./chunk-N7S72EXK.js";
21
+ import "./chunk-3ZC6QPOM.js";
21
22
  import "./chunk-XEA5BCMA.js";
23
+ import "./chunk-IX3K4THH.js";
22
24
  import "./chunk-XTD7TZHW.js";
23
25
  import "./chunk-TXS65BB2.js";
24
26
  export {
@@ -1,21 +1,21 @@
1
1
  "use client";
2
2
  import {
3
3
  SandboxFiles
4
- } from "./chunk-C5BF4L26.js";
4
+ } from "./chunk-KHF2VRXF.js";
5
+ import "./chunk-LSW2OJVV.js";
5
6
  import "./chunk-B27E3V37.js";
7
+ import "./chunk-YSRBFJMQ.js";
6
8
  import "./chunk-PKCAYHDC.js";
7
9
  import "./chunk-OYQQJL3J.js";
8
- import "./chunk-YSRBFJMQ.js";
9
10
  import "./chunk-PMV53IMM.js";
10
11
  import "./chunk-XEA5BCMA.js";
11
12
  import "./chunk-QV3DJVRZ.js";
13
+ import "./chunk-5I4VRWBB.js";
12
14
  import "./chunk-QHUE7E4N.js";
13
15
  import "./chunk-CM7LVUKC.js";
14
16
  import "./chunk-XTD7TZHW.js";
15
- import "./chunk-LSW2OJVV.js";
16
- import "./chunk-5I4VRWBB.js";
17
17
  import "./chunk-TXS65BB2.js";
18
18
  export {
19
19
  SandboxFiles
20
20
  };
21
- //# sourceMappingURL=sandbox-files-34CJJNOY.js.map
21
+ //# sourceMappingURL=sandbox-files-RCVCMXG7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * User-facing names for where a session's commands run, shared by the web
3
+ * sandbox switcher and every timeline that labels command rows ("on Cloud
4
+ * sandbox · …"). No DOM, no React.
5
+ */
6
+ import type { SandboxBackend } from "@opengeni/sdk";
7
+ import type { MachineView } from "./types/machines.js";
8
+ export declare const CLOUD_SANDBOX_LABEL = "Cloud sandbox";
9
+ export declare const NO_SANDBOX_LABEL = "No sandbox";
10
+ export declare const LOCAL_SANDBOX_LABEL = "Local sandbox";
11
+ /**
12
+ * User-facing name for a session's own managed box. Hosting vendors (Modal,
13
+ * Daytona, ...) are deployment detail, not something a user chose, so hosted
14
+ * providers read as the neutral "Cloud sandbox" and the local-dev Docker box as
15
+ * "Local sandbox". The local backend runs directly on the host, so it keeps the
16
+ * honest "this computer" instead of implying isolation. Connected Machines keep
17
+ * their own names.
18
+ */
19
+ export declare function sessionSandboxLabel(backend: SandboxBackend | string): string;
20
+ /** Display name for a fleet row: the session's own box never shows its vendor. */
21
+ export declare function machineDisplayName(machine: Pick<MachineView, "isSessionGroup" | "kind" | "name">): string;
22
+ /** The compute label a session timeline shows: the active machine, else the cloud box. */
23
+ export declare function sessionComputeLabel(machines: readonly Pick<MachineView, "active" | "isSessionGroup" | "kind" | "name">[]): string;