@opengeni/react 1.4.4 → 1.4.5-canary.37485542607001

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 (249) 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-5EEAS3IU.js → browser-viewer-CV23VIHB.js} +8 -6
  6. package/dist/{chunk-XS67YG5R.js → chunk-4O7OE7ON.js} +45 -4
  7. package/dist/chunk-4O7OE7ON.js.map +1 -0
  8. package/dist/{chunk-JHTIMBOL.js → chunk-5JSUNNQN.js} +26 -4
  9. package/dist/{chunk-JHTIMBOL.js.map → chunk-5JSUNNQN.js.map} +1 -1
  10. package/dist/{chunk-QMMCJGFI.js → chunk-6BAMPGBV.js} +6 -3
  11. package/dist/chunk-6BAMPGBV.js.map +1 -0
  12. package/dist/{chunk-I6OY3MWC.js → chunk-6FOTSVWU.js} +2 -2
  13. package/dist/{chunk-LVS3MH5T.js → chunk-ATIRUHBZ.js} +128 -10
  14. package/dist/chunk-ATIRUHBZ.js.map +1 -0
  15. package/dist/chunk-BOFEQC6K.js +162 -0
  16. package/dist/chunk-BOFEQC6K.js.map +1 -0
  17. package/dist/{chunk-2OQA3CPB.js → chunk-CESBPQP5.js} +19 -5
  18. package/dist/chunk-CESBPQP5.js.map +1 -0
  19. package/dist/{chunk-YVFRBXST.js → chunk-GMNGUPMX.js} +2 -2
  20. package/dist/{chunk-PHBFJCEU.js → chunk-I5EGRXXG.js} +110 -7
  21. package/dist/chunk-I5EGRXXG.js.map +1 -0
  22. package/dist/{chunk-PBCZL4JP.js → chunk-INIZSNXT.js} +2 -2
  23. package/dist/chunk-IZV5FTJC.js +55 -0
  24. package/dist/chunk-IZV5FTJC.js.map +1 -0
  25. package/dist/chunk-JDJJMBB3.js +1883 -0
  26. package/dist/chunk-JDJJMBB3.js.map +1 -0
  27. package/dist/chunk-LHF6BVM4.js +83 -0
  28. package/dist/chunk-LHF6BVM4.js.map +1 -0
  29. package/dist/{chunk-C5BF4L26.js → chunk-LSMWZSCJ.js} +7 -7
  30. package/dist/chunk-LTKGTXUQ.js +174 -0
  31. package/dist/chunk-LTKGTXUQ.js.map +1 -0
  32. package/dist/chunk-N7S72EXK.js +25 -0
  33. package/dist/chunk-N7S72EXK.js.map +1 -0
  34. package/dist/{chunk-CVYCLFMH.js → chunk-PEHTX3V7.js} +19 -1
  35. package/dist/chunk-PEHTX3V7.js.map +1 -0
  36. package/dist/chunk-R5R5RQQD.js +51 -0
  37. package/dist/chunk-R5R5RQQD.js.map +1 -0
  38. package/dist/{chunk-IYQCWGU5.js → chunk-RGTZ2VDR.js} +35 -62
  39. package/dist/chunk-RGTZ2VDR.js.map +1 -0
  40. package/dist/chunk-RI42H5IU.js +326 -0
  41. package/dist/chunk-RI42H5IU.js.map +1 -0
  42. package/dist/{chunk-EAOSEIXB.js → chunk-RRRS5D5T.js} +727 -1983
  43. package/dist/chunk-RRRS5D5T.js.map +1 -0
  44. package/dist/{chunk-JH7V627O.js → chunk-SHLZMAJN.js} +2 -11
  45. package/dist/chunk-SHLZMAJN.js.map +1 -0
  46. package/dist/{chunk-IUHHPMAX.js → chunk-SZOCY5VG.js} +18 -87
  47. package/dist/chunk-SZOCY5VG.js.map +1 -0
  48. package/dist/{chunk-L2J3PU7A.js → chunk-VYIPNDUZ.js} +29 -100
  49. package/dist/chunk-VYIPNDUZ.js.map +1 -0
  50. package/dist/{chunk-G6YRCIYJ.js → chunk-YK6QMGVL.js} +55 -60
  51. package/dist/chunk-YK6QMGVL.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-ELNLZGHI.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-K7SOZVVZ.js} +6 -4
  76. package/dist/{embedded-voice-NIL4RDX3.js.map → embedded-voice-K7SOZVVZ.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-goal.d.ts +2 -1
  80. package/dist/hooks/use-new-session-draft.d.ts +74 -0
  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-27HGRPVF.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/lib/transient-retry.d.ts +25 -0
  90. package/dist/machines.js +2 -2
  91. package/dist/model-mark-paths.d.ts +34 -0
  92. package/dist/model-mark-paths.js +16 -0
  93. package/dist/model-picker-model.d.ts +111 -0
  94. package/dist/model-picker-model.js +25 -0
  95. package/dist/model-picker-model.js.map +1 -0
  96. package/dist/{model-policy-picker-menu-WRNSRFQC.js → model-policy-picker-menu-I5KPC3D6.js} +6 -4
  97. package/dist/model-policy-picker-menu-I5KPC3D6.js.map +1 -0
  98. package/dist/model-policy.d.ts +10 -0
  99. package/dist/model-policy.js +5 -1
  100. package/dist/new-session-draft.d.ts +7 -0
  101. package/dist/new-session-draft.js +639 -0
  102. package/dist/new-session-draft.js.map +1 -0
  103. package/dist/organization-model.d.ts +32 -0
  104. package/dist/organization-model.js +65 -0
  105. package/dist/organization-model.js.map +1 -0
  106. package/dist/{platform-activity-row-PJJVATTZ.js → platform-activity-row-NJ47YBXW.js} +7 -84
  107. package/dist/platform-activity-row-NJ47YBXW.js.map +1 -0
  108. package/dist/queue-presentation-model.d.ts +72 -0
  109. package/dist/queue-presentation-model.js +38 -0
  110. package/dist/queue-presentation-model.js.map +1 -0
  111. package/dist/{queue-surface-implementation-67FS7FUI.js → queue-surface-implementation-YPJFQ3O6.js} +24 -252
  112. package/dist/queue-surface-implementation-YPJFQ3O6.js.map +1 -0
  113. package/dist/realtime.js +5 -3
  114. package/dist/{sandbox-files-34CJJNOY.js → sandbox-files-2DGDO6NI.js} +5 -5
  115. package/dist/sandbox-files-2DGDO6NI.js.map +1 -0
  116. package/dist/sandbox-label-model.d.ts +23 -0
  117. package/dist/sandbox-label-model.js +28 -0
  118. package/dist/sandbox-label-model.js.map +1 -0
  119. package/dist/session-agents-model.d.ts +10 -0
  120. package/dist/session-agents-model.js +25 -0
  121. package/dist/session-agents-model.js.map +1 -0
  122. package/dist/session-attention-model.d.ts +8 -0
  123. package/dist/session-attention-model.js +46 -0
  124. package/dist/session-attention-model.js.map +1 -0
  125. package/dist/session-feedback-model.d.ts +20 -0
  126. package/dist/session-feedback-model.js +56 -0
  127. package/dist/session-feedback-model.js.map +1 -0
  128. package/dist/session-list-model.d.ts +119 -0
  129. package/dist/session-list-model.js +244 -0
  130. package/dist/session-list-model.js.map +1 -0
  131. package/dist/session-status-model.d.ts +19 -0
  132. package/dist/session-ui.js +26 -17
  133. package/dist/session-ui.js.map +1 -1
  134. package/dist/session.js +8 -6
  135. package/dist/testing/session-scenarios.d.ts +10 -0
  136. package/dist/testing/session-scenarios.js +303 -0
  137. package/dist/testing/session-scenarios.js.map +1 -0
  138. package/dist/timeline/genie-copy.d.ts +3 -0
  139. package/dist/timeline/genie-loading.d.ts +11 -0
  140. package/dist/timeline/index.d.ts +1 -1
  141. package/dist/timeline/notice-presentation.d.ts +7 -0
  142. package/dist/timeline/patch-apply-command.d.ts +18 -0
  143. package/dist/timeline/platform-activity-presentation.d.ts +7 -0
  144. package/dist/timeline/presented-image.d.ts +6 -1
  145. package/dist/timeline/question-nav-model.d.ts +23 -0
  146. package/dist/timeline/registry.d.ts +10 -1
  147. package/dist/timeline/retained-loaders.d.ts +1 -1
  148. package/dist/timeline/tool-presentation.d.ts +172 -0
  149. package/dist/timeline/turn-summary-model.d.ts +90 -0
  150. package/dist/timeline/turn-summary.d.ts +4 -74
  151. package/dist/timeline/work-presentation.d.ts +42 -0
  152. package/dist/timeline-model.d.ts +24 -0
  153. package/dist/timeline-model.js +152 -0
  154. package/dist/timeline-model.js.map +1 -0
  155. package/package.json +55 -3
  156. package/src/artifacts.ts +1 -0
  157. package/src/client.ts +9 -3
  158. package/src/components/browser-viewer.tsx +23 -2
  159. package/src/components/claude-mark.tsx +2 -1
  160. package/src/components/composer.tsx +8 -146
  161. package/src/components/grok-mark.tsx +2 -1
  162. package/src/components/human-input-form.tsx +13 -124
  163. package/src/components/markdown.tsx +19 -1
  164. package/src/components/message-timeline.tsx +45 -99
  165. package/src/components/model-mark.tsx +2 -1
  166. package/src/components/model-policy-picker-menu.tsx +30 -85
  167. package/src/components/model-policy-picker.tsx +20 -150
  168. package/src/components/opper-mark.tsx +18 -0
  169. package/src/components/provider-recovery-notice.tsx +41 -0
  170. package/src/components/queue-surface-implementation.tsx +20 -349
  171. package/src/components/remark-soft-line-breaks.ts +166 -0
  172. package/src/components/sandbox-workspace.tsx +17 -1
  173. package/src/components/session-chrome.tsx +114 -99
  174. package/src/components/session-conversation.tsx +55 -6
  175. package/src/components/session-status.tsx +17 -16
  176. package/src/composer-messages.ts +150 -0
  177. package/src/connect-setup.tsx +45 -11
  178. package/src/connect.ts +1 -1
  179. package/src/hooks/shared-machines-list.ts +34 -1
  180. package/src/hooks/use-client-config-flags.ts +8 -0
  181. package/src/hooks/use-goal.ts +66 -10
  182. package/src/hooks/use-new-session-draft.ts +813 -0
  183. package/src/human-input-model.ts +147 -0
  184. package/src/index.ts +16 -0
  185. package/src/lib/clipboard.ts +29 -0
  186. package/src/lib/format.ts +7 -0
  187. package/src/lib/provider-recovery.ts +202 -0
  188. package/src/lib/transient-retry.ts +99 -0
  189. package/src/model-mark-paths.ts +53 -0
  190. package/src/model-picker-model.ts +330 -0
  191. package/src/model-policy.ts +75 -5
  192. package/src/new-session-draft.ts +22 -0
  193. package/src/organization-model.ts +118 -0
  194. package/src/queue-presentation-model.ts +464 -0
  195. package/src/sandbox-label-model.ts +41 -0
  196. package/src/session-agents-model.ts +33 -0
  197. package/src/session-attention-model.ts +59 -0
  198. package/src/session-feedback-model.ts +95 -0
  199. package/src/session-list-model.ts +377 -0
  200. package/src/session-status-model.ts +62 -0
  201. package/src/testing/session-scenarios.ts +326 -0
  202. package/src/timeline/activity-rail.tsx +54 -24
  203. package/src/timeline/genie-copy.ts +19 -0
  204. package/src/timeline/genie-loading.tsx +15 -19
  205. package/src/timeline/index.ts +1 -0
  206. package/src/timeline/notice-presentation.ts +22 -0
  207. package/src/timeline/patch-apply-command.tsx +135 -0
  208. package/src/timeline/platform-activity-presentation.ts +122 -0
  209. package/src/timeline/platform-activity-row.tsx +6 -96
  210. package/src/timeline/presented-image.ts +16 -2
  211. package/src/timeline/projection.ts +12 -1
  212. package/src/timeline/question-nav-model.ts +28 -0
  213. package/src/timeline/registry.ts +11 -1
  214. package/src/timeline/retained-loaders.ts +9 -4
  215. package/src/timeline/rolling-activity.tsx +7 -19
  216. package/src/timeline/tool-presentation.ts +1316 -0
  217. package/src/timeline/tool-renderers.tsx +254 -1024
  218. package/src/timeline/turn-summary-model.ts +338 -0
  219. package/src/timeline/turn-summary.tsx +21 -326
  220. package/src/timeline/work-presentation.ts +139 -0
  221. package/src/timeline-model.ts +108 -0
  222. package/styles/compiled.css +17 -4
  223. package/styles/connect.css +4 -0
  224. package/styles/responsive.css +11 -2
  225. package/dist/chunk-2OQA3CPB.js.map +0 -1
  226. package/dist/chunk-CVYCLFMH.js.map +0 -1
  227. package/dist/chunk-EAOSEIXB.js.map +0 -1
  228. package/dist/chunk-G6YRCIYJ.js.map +0 -1
  229. package/dist/chunk-HXYOSSQO.js +0 -117
  230. package/dist/chunk-HXYOSSQO.js.map +0 -1
  231. package/dist/chunk-IUHHPMAX.js.map +0 -1
  232. package/dist/chunk-IYQCWGU5.js.map +0 -1
  233. package/dist/chunk-JH7V627O.js.map +0 -1
  234. package/dist/chunk-L2J3PU7A.js.map +0 -1
  235. package/dist/chunk-LVS3MH5T.js.map +0 -1
  236. package/dist/chunk-PHBFJCEU.js.map +0 -1
  237. package/dist/chunk-QMMCJGFI.js.map +0 -1
  238. package/dist/chunk-XS67YG5R.js.map +0 -1
  239. package/dist/platform-activity-row-PJJVATTZ.js.map +0 -1
  240. package/dist/queue-surface-implementation-67FS7FUI.js.map +0 -1
  241. /package/dist/{browser-viewer-5EEAS3IU.js.map → browser-viewer-CV23VIHB.js.map} +0 -0
  242. /package/dist/{chunk-I6OY3MWC.js.map → chunk-6FOTSVWU.js.map} +0 -0
  243. /package/dist/{chunk-YVFRBXST.js.map → chunk-GMNGUPMX.js.map} +0 -0
  244. /package/dist/{chunk-PBCZL4JP.js.map → chunk-INIZSNXT.js.map} +0 -0
  245. /package/dist/{chunk-C5BF4L26.js.map → chunk-LSMWZSCJ.js.map} +0 -0
  246. /package/dist/{computer-viewer-ELNLZGHI.js.map → composer-messages.js.map} +0 -0
  247. /package/dist/{model-policy-picker-menu-WRNSRFQC.js.map → computer-viewer-K4CKYRX6.js.map} +0 -0
  248. /package/dist/{latest-question-2POFPYNB.js.map → latest-question-27HGRPVF.js.map} +0 -0
  249. /package/dist/{sandbox-files-34CJJNOY.js.map → model-mark-paths.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-new-session-draft.ts","../src/lib/transient-retry.ts"],"sourcesContent":["import type {\n FileAsset,\n NewSessionDraft,\n NewSessionSelectionHistory,\n OpenGeniClient,\n ResourceRef,\n SaveNewSessionDraftRequest,\n} from \"@opengeni/sdk\";\nimport { OpenGeniApiError } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n isTransientServiceFailure,\n retryTransient,\n TRANSIENT_RECONNECT_INTERVAL_MS,\n TRANSIENT_RETRY_DELAYS_MS,\n} from \"../lib/transient-retry\";\n\nexport type NewSessionDraftEditable = Omit<SaveNewSessionDraftRequest, \"expectedRevision\">;\n\nexport type UseNewSessionDraftOptions = {\n workspaceId: string;\n client: Pick<OpenGeniClient, \"getNewSessionDraft\" | \"saveNewSessionDraft\" | \"getFile\">;\n /** The complete browser-visible value. It must contain ready file refs only. */\n value: NewSessionDraftEditable;\n /** Apply a remote value to the controlled text/model/tool/options state. */\n onApplyRemote: (\n value: NewSessionDraftEditable,\n selectionHistory: NewSessionSelectionHistory,\n ) => void;\n /** Replace finalized attachments with freshly revalidated server assets. */\n restoreReadyFiles: (files: Iterable<FileAsset>) => void;\n /** Revalidate non-file resource identities against the current UI catalog. */\n hydrateResources?: (resources: ResourceRef[]) => ResourceRef[] | Promise<ResourceRef[]>;\n /** Keep the first read pending until catalogs needed for hydration are ready. */\n resourceHydrationReady?: boolean;\n /** A create in flight owns the exact clicked snapshot; resume autosave on settlement. */\n suspendAutosave?: boolean;\n /** Test seam for the quiet retry backoff and the background reconnect pace. */\n transientRetry?: { delaysMs?: readonly number[]; reconnectIntervalMs?: number };\n};\n\nexport type FlushedNewSessionDraft = {\n revision: number;\n /** Signature of the exact local snapshot acknowledged by this revision. */\n signature: string;\n};\n\nexport type AcknowledgeConsumedNewSessionDraftResult =\n | { kind: \"consumed\" }\n | { kind: \"preserved\"; flushed: FlushedNewSessionDraft };\n\nexport type UseNewSessionDraftResult = {\n draft: NewSessionDraft | null;\n revision: number;\n loading: boolean;\n saving: boolean;\n conflict: Error | null;\n error: Error | null;\n /**\n * `error` only says Opengeni was briefly unreachable (a deploy or database\n * restart). Show the calm updating notice instead of the error; the hook\n * keeps reconnecting in the background and clears this on success.\n */\n unavailable: boolean;\n /** The latest failure, readable right after an awaited call (state lags a render). */\n currentError: () => Error | null;\n /** Mark Opengeni unreachable after a transient failure elsewhere in the send path. */\n reportUnavailable: (cause: unknown) => boolean;\n flush: () => Promise<FlushedNewSessionDraft | null>;\n /** Send the visible snapshot, rebasing a stale draft revision without replacing the composer. */\n flushForSend: (snapshot?: NewSessionDraftEditable) => Promise<FlushedNewSessionDraft | null>;\n isCurrentSignature: (signature: string) => boolean;\n /**\n * Fence the exact acknowledged snapshot after session creation consumes it,\n * preserving a genuinely newer local value against the safe-seed row.\n */\n acknowledgeConsumed: (\n flushed: FlushedNewSessionDraft,\n visibleSignature?: string,\n ) => Promise<AcknowledgeConsumedNewSessionDraftResult | null>;\n reload: () => Promise<void>;\n /** Surface a create-time OCC rejection through the ordinary draft recovery UI. */\n captureConflict: (cause: unknown) => boolean;\n resolveConflict: (choice: \"keep_mine\" | \"use_remote\") => Promise<void>;\n clearError: () => void;\n};\n\ntype ValidatedRemoteDraft = {\n draft: NewSessionDraft;\n editable: NewSessionDraftEditable;\n files: FileAsset[];\n};\n\n/**\n * Actor-private, server-authoritative state for the composer shown before a\n * session exists. Reads and writes are fenced to one client/workspace target;\n * writes serialize and acquire the latest acknowledged revision at execution\n * time, so a stale closure can never invent its own OCC base.\n */\nexport function useNewSessionDraft(options: UseNewSessionDraftOptions): UseNewSessionDraftResult {\n const { client, workspaceId } = options;\n const resourceHydrationReady = options.resourceHydrationReady ?? true;\n const suspendAutosave = options.suspendAutosave ?? false;\n const hydrateResources = options.hydrateResources;\n const retryDelaysMs = options.transientRetry?.delaysMs ?? TRANSIENT_RETRY_DELAYS_MS;\n const reconnectIntervalMs =\n options.transientRetry?.reconnectIntervalMs ?? TRANSIENT_RECONNECT_INTERVAL_MS;\n const [draft, setDraft] = useState<NewSessionDraft | null>(null);\n const [loading, setLoading] = useState(true);\n const [saving, setSaving] = useState(false);\n const [conflict, setConflict] = useState<Error | null>(null);\n const [error, setErrorState] = useState<Error | null>(null);\n const errorRef = useRef<Error | null>(null);\n const setError = useCallback((next: Error | null) => {\n errorRef.current = next;\n setErrorState(next);\n }, []);\n /**\n * Composer value when a first load failed. A background reconnect may apply\n * the remote draft only while the person has not edited since then.\n */\n const unloadedValueSignature = useRef<string | null>(null);\n const valueRef = useRef(options.value);\n valueRef.current = options.value;\n const onApplyRemoteRef = useRef(options.onApplyRemote);\n onApplyRemoteRef.current = options.onApplyRemote;\n const restoreReadyFilesRef = useRef(options.restoreReadyFiles);\n restoreReadyFilesRef.current = options.restoreReadyFiles;\n const draftRef = useRef<NewSessionDraft | null>(null);\n const lastSavedSignature = useRef<string | null>(null);\n const passiveProjectionSignature = useRef<string | null>(null);\n const pendingHydratedBaselineGeneration = useRef<number | null>(null);\n const targetGeneration = useRef(0);\n const persistenceEpoch = useRef(0);\n const saveChain = useRef<Promise<void>>(Promise.resolve());\n const autosaveTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const conflictRef = useRef<Error | null>(null);\n const loadingRef = useRef(true);\n const activeRemoteReads = useRef(new Set<AbortController>());\n const targetKey = `${workspaceId}\\u0000${clientIdentity(client)}`;\n const targetKeyRef = useRef(targetKey);\n\n const setCurrentConflict = useCallback((next: Error | null) => {\n conflictRef.current = next;\n setConflict(next);\n }, []);\n\n const captureConflict = useCallback(\n (cause: unknown): boolean => {\n if (!isNewSessionDraftConflict(cause)) return false;\n const problem = asError(cause);\n setCurrentConflict(problem);\n setError(problem);\n return true;\n },\n [setCurrentConflict, setError],\n );\n\n const abortActiveRemoteReads = useCallback(() => {\n for (const controller of activeRemoteReads.current) controller.abort();\n activeRemoteReads.current.clear();\n }, []);\n\n const validateRemoteDraft = useCallback(\n async (\n remote: NewSessionDraft,\n generation: number,\n signal: AbortSignal,\n ): Promise<ValidatedRemoteDraft | null> => {\n if (!resourceHydrationReady || signal.aborted) return null;\n const hydratedResources = hydrateResources\n ? await hydrateResources(remote.resources)\n : remote.resources;\n if (generation !== targetGeneration.current || signal.aborted) return null;\n const seen = new Set<string>();\n const fileRefs = hydratedResources.flatMap((resource) => {\n if (resource.kind !== \"file\" || seen.has(resource.fileId)) return [];\n seen.add(resource.fileId);\n return [resource];\n });\n const settled = await Promise.allSettled(\n fileRefs.map((resource) =>\n retryTransient(() => client.getFile(workspaceId, resource.fileId, { signal }), {\n signal,\n delaysMs: retryDelaysMs,\n }),\n ),\n );\n if (generation !== targetGeneration.current || signal.aborted) return null;\n const files = settled.flatMap((result, index) => {\n if (result.status !== \"fulfilled\") return [];\n const file = result.value;\n const expected = fileRefs[index]?.fileId;\n return file.id === expected && file.workspaceId === workspaceId && file.status === \"ready\"\n ? [file]\n : [];\n });\n return {\n draft: remote,\n editable: {\n text: remote.text,\n resources: [\n ...hydratedResources.filter((resource) => resource.kind === \"repository\"),\n ...files.map(\n (file): ResourceRef => ({\n kind: \"file\",\n fileId: file.id,\n }),\n ),\n ],\n tools: remote.tools,\n toolsProvided: remote.toolsProvided,\n model: remote.model,\n reasoningEffort: remote.reasoningEffort,\n latencyMode: remote.latencyMode ?? \"standard\",\n ...(remote.modelProvided !== undefined ? { modelProvided: remote.modelProvided } : {}),\n ...(Object.hasOwn(remote, \"selectedProjectChannelId\")\n ? { selectedProjectChannelId: remote.selectedProjectChannelId }\n : {}),\n options: remote.options,\n },\n files,\n };\n },\n [client, hydrateResources, resourceHydrationReady, retryDelaysMs, workspaceId],\n );\n\n const readRemote = useCallback(\n async (quietRetries = true): Promise<ValidatedRemoteDraft | null> => {\n const controller = new AbortController();\n activeRemoteReads.current.add(controller);\n const generation = targetGeneration.current;\n try {\n // A deploy or database restart answers 502/503 for a few seconds; the\n // read is safe to repeat, so retry it quietly before reporting anything.\n const remote = normalizeLegacyNewSessionDraft(\n await retryTransient(\n () => client.getNewSessionDraft(workspaceId, { signal: controller.signal }),\n {\n signal: controller.signal,\n shouldContinue: () => generation === targetGeneration.current,\n delaysMs: quietRetries ? retryDelaysMs : [],\n },\n ),\n );\n if (generation !== targetGeneration.current || controller.signal.aborted) return null;\n return await validateRemoteDraft(remote, generation, controller.signal);\n } finally {\n activeRemoteReads.current.delete(controller);\n }\n },\n [client, retryDelaysMs, validateRemoteDraft, workspaceId],\n );\n\n const applyRemote = useCallback(\n (remote: ValidatedRemoteDraft): void => {\n draftRef.current = remote.draft;\n // A GET may project away revoked files, repositories, or tools without\n // changing the stored row. This signature suppresses passive autosave;\n // explicit Send always writes its exact snapshot before create.\n lastSavedSignature.current = draftSignature(remote.editable);\n passiveProjectionSignature.current = null;\n pendingHydratedBaselineGeneration.current = targetGeneration.current;\n unloadedValueSignature.current = null;\n setDraft(remote.draft);\n setCurrentConflict(null);\n setError(null);\n restoreReadyFilesRef.current(remote.files);\n onApplyRemoteRef.current(remote.editable, remote.draft.selectionHistory);\n },\n [setCurrentConflict, setError],\n );\n\n const reload = useCallback(async (): Promise<void> => {\n if (!resourceHydrationReady) return;\n const generation = targetGeneration.current;\n const valueAtStart = draftSignature(valueRef.current);\n loadingRef.current = true;\n setLoading(true);\n try {\n const remote = await readRemote();\n if (remote && generation === targetGeneration.current) applyRemote(remote);\n } catch (cause) {\n if (generation === targetGeneration.current) {\n if (!draftRef.current) unloadedValueSignature.current = valueAtStart;\n setError(asError(cause));\n }\n } finally {\n if (generation === targetGeneration.current) {\n loadingRef.current = false;\n setLoading(false);\n }\n }\n }, [applyRemote, readRemote, resourceHydrationReady, setError]);\n\n // `reload` intentionally follows resource hydration callbacks, but those\n // callbacks can change identity when a catalog refresh publishes a new\n // snapshot. Keep the effect below targeted to durable authority (the actor,\n // workspace/client, and readiness), not to an incidental callback identity.\n const reloadRef = useRef(reload);\n reloadRef.current = reload;\n\n // A client replacement represents a new authenticated actor. Reset all OCC\n // state before the first await, so no effect in this commit can persist the\n // prior actor/workspace value under the new target.\n useEffect(() => {\n if (targetKeyRef.current !== targetKey) {\n targetKeyRef.current = targetKey;\n }\n targetGeneration.current += 1;\n abortActiveRemoteReads();\n persistenceEpoch.current += 1;\n draftRef.current = null;\n lastSavedSignature.current = null;\n passiveProjectionSignature.current = null;\n pendingHydratedBaselineGeneration.current = null;\n unloadedValueSignature.current = null;\n saveChain.current = Promise.resolve();\n if (autosaveTimer.current) clearTimeout(autosaveTimer.current);\n autosaveTimer.current = null;\n setDraft(null);\n setCurrentConflict(null);\n setError(null);\n setSaving(false);\n loadingRef.current = true;\n setLoading(true);\n return () => {\n targetGeneration.current += 1;\n abortActiveRemoteReads();\n if (autosaveTimer.current) clearTimeout(autosaveTimer.current);\n autosaveTimer.current = null;\n };\n }, [abortActiveRemoteReads, setCurrentConflict, setError, targetKey]);\n\n // Initial/target reads wait for the catalogs required to validate resources.\n // A later catalog refresh keeps this boolean true and therefore does not\n // restart the read or fence a local/in-flight edit.\n useEffect(() => {\n if (resourceHydrationReady) void reloadRef.current();\n }, [resourceHydrationReady, targetKey]);\n\n const persistSnapshot = useCallback(\n (snapshot: NewSessionDraftEditable, force = false): Promise<FlushedNewSessionDraft | null> => {\n const generation = targetGeneration.current;\n const epoch = persistenceEpoch.current;\n const signature = draftSignature(snapshot);\n const run = async (): Promise<FlushedNewSessionDraft | null> => {\n if (generation !== targetGeneration.current || epoch !== persistenceEpoch.current) {\n return null;\n }\n const current = draftRef.current;\n if (!current) return null;\n if (!force && signature === lastSavedSignature.current) {\n return { revision: current.revision, signature };\n }\n setSaving(true);\n try {\n const save = () =>\n client.saveNewSessionDraft(workspaceId, {\n ...snapshot,\n expectedRevision: current.revision,\n });\n // Send's save is idempotent by construction: it writes one exact\n // snapshot against one expected revision. If an unconfirmed attempt\n // did commit, the repeat is a revision conflict that flushForSend\n // already reconciles by rereading, so it can never apply twice.\n const saved = force\n ? await retryTransient(save, {\n shouldContinue: () =>\n generation === targetGeneration.current && epoch === persistenceEpoch.current,\n delaysMs: retryDelaysMs,\n })\n : await save();\n if (generation !== targetGeneration.current || epoch !== persistenceEpoch.current) {\n return null;\n }\n draftRef.current = saved;\n lastSavedSignature.current = signature;\n passiveProjectionSignature.current = null;\n setDraft(saved);\n setCurrentConflict(null);\n setError(null);\n return { revision: saved.revision, signature };\n } catch (cause) {\n if (generation !== targetGeneration.current || epoch !== persistenceEpoch.current) {\n return null;\n }\n const problem = asError(cause);\n if (isNewSessionDraftConflict(cause)) setCurrentConflict(problem);\n setError(problem);\n return null;\n } finally {\n if (generation === targetGeneration.current && epoch === persistenceEpoch.current) {\n setSaving(false);\n }\n }\n };\n const operation = saveChain.current.then(run, run);\n saveChain.current = operation.then(\n () => undefined,\n () => undefined,\n );\n return operation;\n },\n [client, retryDelaysMs, setCurrentConflict, setError, workspaceId],\n );\n\n const valueSignature = draftSignature(options.value);\n useEffect(() => {\n if (\n !loading &&\n draftRef.current &&\n pendingHydratedBaselineGeneration.current === targetGeneration.current\n ) {\n // Route hydration may deliberately project the durable row through newer\n // route intent (Recents/Default/named project) and therefore change its\n // compute/provenance representation. The first complete controlled value\n // after onApplyRemote is a passive-autosave baseline only. It is not a\n // durable acknowledgement: an immediate create-time flush must persist\n // this projection against the remote revision before exact create.\n pendingHydratedBaselineGeneration.current = null;\n passiveProjectionSignature.current = valueSignature;\n return;\n }\n if (\n loading ||\n suspendAutosave ||\n !draftRef.current ||\n conflictRef.current ||\n valueSignature === lastSavedSignature.current ||\n valueSignature === passiveProjectionSignature.current\n ) {\n return;\n }\n passiveProjectionSignature.current = null;\n const snapshot = cloneEditable(valueRef.current);\n autosaveTimer.current = setTimeout(() => {\n autosaveTimer.current = null;\n void persistSnapshot(snapshot);\n }, 500);\n return () => {\n if (autosaveTimer.current) clearTimeout(autosaveTimer.current);\n autosaveTimer.current = null;\n };\n }, [loading, persistSnapshot, suspendAutosave, valueSignature]);\n\n const flush = useCallback(async (): Promise<FlushedNewSessionDraft | null> => {\n if (loadingRef.current || conflictRef.current || !draftRef.current) return null;\n if (autosaveTimer.current) clearTimeout(autosaveTimer.current);\n autosaveTimer.current = null;\n return await persistSnapshot(cloneEditable(valueRef.current));\n }, [persistSnapshot]);\n\n const flushForSend = useCallback(\n async (sendSnapshot?: NewSessionDraftEditable): Promise<FlushedNewSessionDraft | null> => {\n if (loadingRef.current) return null;\n if (autosaveTimer.current) clearTimeout(autosaveTimer.current);\n autosaveTimer.current = null;\n const snapshot = cloneEditable(sendSnapshot ?? valueRef.current);\n const generation = targetGeneration.current;\n if (!draftRef.current) {\n // A consumed draft can be followed by a newer local edit. Reacquire\n // the safe seed before preserving that edit.\n try {\n const remote = await readRemote();\n if (!remote || generation !== targetGeneration.current) return null;\n draftRef.current = remote.draft;\n lastSavedSignature.current = draftSignature(remote.editable);\n setDraft(remote.draft);\n } catch (cause) {\n if (generation === targetGeneration.current) setError(asError(cause));\n return null;\n }\n }\n // A sibling can save between our read and write. Retry a bounded number of\n // times; only the explicit Send may choose the visible snapshot over it.\n for (let attempt = 0; attempt < 3; attempt += 1) {\n if (generation !== targetGeneration.current) return null;\n if (conflictRef.current) {\n await saveChain.current;\n try {\n const remote = await readRemote();\n if (!remote || generation !== targetGeneration.current) return null;\n draftRef.current = remote.draft;\n lastSavedSignature.current = draftSignature(remote.editable);\n passiveProjectionSignature.current = null;\n setDraft(remote.draft);\n setCurrentConflict(null);\n setError(null);\n } catch (cause) {\n if (generation === targetGeneration.current) setError(asError(cause));\n return null;\n }\n }\n // GET can be a sanitized projection of a different stored row. An\n // explicit Send always writes its clicked snapshot, even when its\n // signature appears unchanged, before exact create consumes it.\n const flushed = await persistSnapshot(snapshot, true);\n if (flushed) return flushed;\n if (!conflictRef.current) return null;\n }\n return null;\n },\n [persistSnapshot, readRemote, setCurrentConflict, setError],\n );\n\n const isCurrentSignature = useCallback(\n (signature: string): boolean => draftSignature(valueRef.current) === signature,\n [],\n );\n\n const acknowledgeConsumed = useCallback(\n async (\n flushed: FlushedNewSessionDraft,\n visibleSignature = flushed.signature,\n ): Promise<AcknowledgeConsumedNewSessionDraftResult | null> => {\n const current = draftRef.current;\n if (\n !current ||\n current.revision !== flushed.revision ||\n lastSavedSignature.current !== flushed.signature\n ) {\n return null;\n }\n\n if (autosaveTimer.current) clearTimeout(autosaveTimer.current);\n autosaveTimer.current = null;\n\n const generation = targetGeneration.current;\n const epoch = persistenceEpoch.current + 1;\n persistenceEpoch.current = epoch;\n const priorSaves = saveChain.current;\n\n // Session creation accepted this exact server revision. Invalidate every\n // save that captured the old row as its OCC base, then wait for its\n // physical response before reading the safe seed. A late response must\n // not restore stale persistence authority or race the seed read.\n setCurrentConflict(null);\n setError(null);\n\n const run = async (): Promise<AcknowledgeConsumedNewSessionDraftResult | null> => {\n if (generation !== targetGeneration.current || epoch !== persistenceEpoch.current) {\n return null;\n }\n setSaving(true);\n try {\n await priorSaves;\n if (generation !== targetGeneration.current || epoch !== persistenceEpoch.current) {\n return null;\n }\n const remote = await readRemote();\n if (!remote || generation !== targetGeneration.current) return null;\n\n // A successful create turns the accepted revision into exactly one\n // newer safe seed. A larger revision proves that a sibling/in-flight\n // edit won after the create; never overwrite that newer authority.\n const expectedSeedRevision = flushed.revision + 1;\n if (remote.draft.revision > expectedSeedRevision) {\n const problem = new Error(\n \"New-session defaults changed in another client while the session was created\",\n );\n draftRef.current = remote.draft;\n lastSavedSignature.current = draftSignature(remote.editable);\n passiveProjectionSignature.current = null;\n setDraft(remote.draft);\n setCurrentConflict(problem);\n setError(problem);\n return null;\n }\n if (remote.draft.revision < expectedSeedRevision) {\n const problem = new Error(\"New-session defaults were not seeded yet\");\n setError(problem);\n return null;\n }\n\n draftRef.current = remote.draft;\n lastSavedSignature.current = draftSignature(remote.editable);\n passiveProjectionSignature.current = null;\n setDraft(remote.draft);\n // Typing may continue while the safe-seed fetch is pending.\n const snapshot = cloneEditable(valueRef.current);\n const signature = draftSignature(snapshot);\n if (signature === visibleSignature) {\n // The server now owns the safe seed. Keep the post-create composer\n // UI-only until the next page load instead of persisting the\n // route's deliberate clear as a new empty draft.\n draftRef.current = null;\n lastSavedSignature.current = null;\n passiveProjectionSignature.current = null;\n setDraft(null);\n return { kind: \"consumed\" };\n }\n\n // A newer local edit is the next draft. It may be saved only against\n // the exact safe-seed revision; OCC still fences a concurrent sibling\n // save that lands between this read and this write.\n const saved = await client.saveNewSessionDraft(workspaceId, {\n ...snapshot,\n expectedRevision: remote.draft.revision,\n });\n if (generation !== targetGeneration.current || epoch !== persistenceEpoch.current) {\n return null;\n }\n draftRef.current = saved;\n lastSavedSignature.current = signature;\n passiveProjectionSignature.current = null;\n setDraft(saved);\n setCurrentConflict(null);\n setError(null);\n return {\n kind: \"preserved\",\n flushed: { revision: saved.revision, signature },\n };\n } catch (cause) {\n if (generation !== targetGeneration.current || epoch !== persistenceEpoch.current) {\n return null;\n }\n const problem = asError(cause);\n if (isNewSessionDraftConflict(cause)) setCurrentConflict(problem);\n setError(problem);\n return null;\n } finally {\n if (generation === targetGeneration.current && epoch === persistenceEpoch.current) {\n setSaving(false);\n }\n }\n };\n\n const operation = saveChain.current.then(run, run);\n saveChain.current = operation.then(\n () => undefined,\n () => undefined,\n );\n return await operation;\n },\n [client, readRemote, setCurrentConflict, setError, workspaceId],\n );\n\n const resolveConflict = useCallback(\n async (choice: \"keep_mine\" | \"use_remote\"): Promise<void> => {\n if (choice === \"use_remote\") {\n await reload();\n return;\n }\n const mine = cloneEditable(valueRef.current);\n const generation = targetGeneration.current;\n loadingRef.current = true;\n setLoading(true);\n try {\n const remote = await readRemote();\n if (!remote || generation !== targetGeneration.current) return;\n draftRef.current = remote.draft;\n lastSavedSignature.current = draftSignature(remote.editable);\n passiveProjectionSignature.current = null;\n setDraft(remote.draft);\n setCurrentConflict(null);\n await persistSnapshot(mine);\n } catch (cause) {\n if (generation === targetGeneration.current) setError(asError(cause));\n } finally {\n if (generation === targetGeneration.current) {\n loadingRef.current = false;\n setLoading(false);\n }\n }\n },\n [persistSnapshot, readRemote, reload, setCurrentConflict, setError],\n );\n\n const unavailable = error !== null && conflict === null && isTransientServiceFailure(error);\n\n /**\n * Re-read after Opengeni was unreachable. The remote draft replaces the\n * composer only when the first load never succeeded and nothing was typed\n * since; otherwise it only becomes the save base, so local text survives and\n * an unconfirmed save is reconciled by what the server actually holds.\n */\n const reconnect = useCallback(async (): Promise<void> => {\n if (!resourceHydrationReady) return;\n const generation = targetGeneration.current;\n try {\n // One attempt per tick: the loop itself is the retry.\n const remote = await readRemote(false);\n if (!remote || generation !== targetGeneration.current) return;\n if (\n !draftRef.current &&\n unloadedValueSignature.current !== null &&\n unloadedValueSignature.current === draftSignature(valueRef.current)\n ) {\n applyRemote(remote);\n return;\n }\n unloadedValueSignature.current = null;\n draftRef.current = remote.draft;\n lastSavedSignature.current = draftSignature(remote.editable);\n passiveProjectionSignature.current = null;\n setDraft(remote.draft);\n setError(null);\n } catch (cause) {\n if (generation === targetGeneration.current) setError(asError(cause));\n }\n }, [applyRemote, readRemote, resourceHydrationReady, setError]);\n const reconnectRef = useRef(reconnect);\n reconnectRef.current = reconnect;\n\n useEffect(() => {\n if (!unavailable) return;\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const tick = () => {\n timer = setTimeout(() => {\n if (stopped) return;\n void reconnectRef.current().finally(() => {\n if (!stopped) tick();\n });\n }, reconnectIntervalMs);\n };\n tick();\n return () => {\n stopped = true;\n if (timer !== undefined) clearTimeout(timer);\n };\n }, [unavailable, reconnectIntervalMs, targetKey]);\n\n return {\n draft,\n revision: draft?.revision ?? 0,\n loading,\n saving,\n conflict,\n error,\n unavailable,\n currentError: useCallback(() => errorRef.current, []),\n reportUnavailable: useCallback(\n (cause: unknown): boolean => {\n if (!isTransientServiceFailure(cause)) return false;\n setError(asError(cause));\n return true;\n },\n [setError],\n ),\n flush,\n flushForSend,\n isCurrentSignature,\n acknowledgeConsumed,\n reload,\n captureConflict,\n resolveConflict,\n clearError: useCallback(() => {\n setError(null);\n setCurrentConflict(null);\n }, [setCurrentConflict, setError]),\n };\n}\n\nfunction cloneEditable(value: NewSessionDraftEditable): NewSessionDraftEditable {\n return structuredClone(value);\n}\n\nfunction normalizeLegacyNewSessionDraft(remote: NewSessionDraft): NewSessionDraft {\n // Old servers returned the tools array without the explicitness marker. The\n // old request contract made that array the user's complete selection, so an\n // absent marker must remain explicit (including an empty array) on a new\n // client rather than inheriting current workspace defaults.\n return {\n ...remote,\n toolsProvided: Object.hasOwn(remote, \"toolsProvided\") ? remote.toolsProvided : true,\n latencyMode: remote.latencyMode ?? \"standard\",\n selectionHistory: remote.selectionHistory ?? { projects: [] },\n };\n}\n\nfunction draftSignature(value: NewSessionDraftEditable): string {\n return JSON.stringify(sortedJson(value));\n}\n\n/** Key-sorted copy so equal drafts compare equal regardless of key order. */\nfunction sortedJson(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortedJson);\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, nested]) => [key, sortedJson(nested)]),\n );\n }\n return value;\n}\n\nfunction clientIdentity(client: object): number {\n let identity = clientIdentities.get(client);\n if (identity === undefined) {\n identity = nextClientIdentity;\n nextClientIdentity += 1;\n clientIdentities.set(client, identity);\n }\n return identity;\n}\n\nconst clientIdentities = new WeakMap<object, number>();\nlet nextClientIdentity = 1;\n\nexport function isNewSessionDraftConflict(cause: unknown): boolean {\n return (\n cause instanceof OpenGeniApiError &&\n cause.status === 409 &&\n cause.code === \"NEW_SESSION_DRAFT_CONFLICT\"\n );\n}\n\nfunction asError(cause: unknown): Error {\n return cause instanceof Error ? cause : new Error(String(cause));\n}\n","import { OpenGeniApiError } from \"@opengeni/sdk\";\n\n/*\n * A deploy, failover or database restart makes the API answer 502/503/504 (or a\n * retryable 500) for a few seconds, or drops the connection outright. Reads\n * behind the new-chat composer retry those quietly before anything is shown;\n * the person keeps typing and never sees a raw \"service unavailable\" line.\n */\n\n/** Backoff between attempts: about ten seconds in all before anything is shown. */\nexport const TRANSIENT_RETRY_DELAYS_MS: readonly number[] = [1_000, 2_000, 3_000, 4_000];\n\n/** After the quiet retries give up, try once at this pace until Opengeni answers. */\nexport const TRANSIENT_RECONNECT_INTERVAL_MS = 3_000;\n\n/** The one line shown while Opengeni is briefly unreachable. */\nexport const OPENGENI_UPDATING_NOTICE = \"Opengeni is updating. We'll reconnect automatically.\";\n\nconst NETWORK_FAILURE =\n /failed to fetch|fetch failed|networkerror|load failed|network request failed/iu;\n\n/**\n * True for a failure that says the service is briefly unreachable, not that\n * the request was wrong: a gateway or availability status, a 500 the API marks\n * retryable, or a request that never got a response.\n */\nexport function isTransientServiceFailure(error: unknown): boolean {\n if (isAbort(error)) return false;\n if (error instanceof OpenGeniApiError) {\n if (error.status === 502 || error.status === 503 || error.status === 504) return true;\n if (error.status === 500) return error.retryable;\n // The SDK reports a mutation whose response never arrived as status 0.\n return error.status === 0 && error.code === \"network_error\";\n }\n return error instanceof TypeError && NETWORK_FAILURE.test(error.message);\n}\n\nexport type RetryTransientOptions = {\n /** Stop waiting (and rethrow the last failure) once this returns false. */\n shouldContinue?: () => boolean;\n signal?: AbortSignal;\n delaysMs?: readonly number[];\n sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n};\n\n/**\n * Run a read, retrying only transient service failures with backoff. Never use\n * this for a request whose repeat could apply twice: it is for reads and for\n * writes that are idempotent by construction.\n */\nexport async function retryTransient<T>(\n operation: () => Promise<T>,\n options: RetryTransientOptions = {},\n): Promise<T> {\n const delays = options.delaysMs ?? TRANSIENT_RETRY_DELAYS_MS;\n const sleep = options.sleep ?? abortableSleep;\n for (let attempt = 0; ; attempt += 1) {\n try {\n return await operation();\n } catch (error) {\n const delay = delays[attempt];\n if (\n delay === undefined ||\n !isTransientServiceFailure(error) ||\n options.signal?.aborted ||\n options.shouldContinue?.() === false\n ) {\n throw error;\n }\n await sleep(delay, options.signal);\n if (options.signal?.aborted || options.shouldContinue?.() === false) throw error;\n }\n }\n}\n\nfunction abortableSleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n const done = () => {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", done);\n resolve();\n };\n const timer = setTimeout(done, ms);\n signal?.addEventListener(\"abort\", done, { once: true });\n });\n}\n\nfunction isAbort(error: unknown): boolean {\n return (\n (typeof DOMException !== \"undefined\" &&\n error instanceof DOMException &&\n error.name === \"AbortError\") ||\n (error instanceof Error && error.name === \"AbortError\")\n );\n}\n"],"mappings":"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","names":["OpenGeniApiError","OpenGeniApiError"]}
@@ -0,0 +1,32 @@
1
+ import type { AccessContext, AccountGrant, Workspace } from "@opengeni/sdk";
2
+ export type OrgOption = {
3
+ accountId: string;
4
+ label: string;
5
+ /** Whether the subject has the owner/admin authority required by organization settings. */
6
+ canManage: boolean;
7
+ };
8
+ /** Organizations the subject administers (owner or admin), sorted by id. */
9
+ export declare function organizationAdministrationAccountIds(accessContext: AccessContext): string[];
10
+ /** A short, stable id fragment for an account that has no human name. */
11
+ export declare function shortAccountId(accountId: string): string;
12
+ /** The organization's real name, or null when the API sent none. */
13
+ export declare function orgName(accountId: string, grants: AccountGrant[]): string | null;
14
+ /** Human label for an organization: the grant's subjectLabel, else a short id. */
15
+ export declare function orgLabel(accountId: string, grants: AccountGrant[]): string;
16
+ /**
17
+ * The organizations the subject belongs to, in a stable order (default org
18
+ * first, then by name). Derived from account grants, unioned with the accounts
19
+ * that own the accessible workspaces so an org always shows even without an
20
+ * explicit grant.
21
+ */
22
+ export declare function organizationsForSubject(context: AccessContext, workspaces: Workspace[]): OrgOption[];
23
+ /** Workspaces that belong to a given organization, ordered by name. */
24
+ export declare function workspacesInOrg(workspaces: Workspace[], accountId: string): Workspace[];
25
+ /** Organization settings remain anchored to an accessible workspace in that organization. */
26
+ export declare function organizationSettingsWorkspaceId(workspaces: Workspace[], accountId: string, activeWorkspaceId: string): string | null;
27
+ /**
28
+ * Where switching to an organization lands: the workspace last used there
29
+ * while it is still open to the person, else its first shared workspace, else
30
+ * their Personal workspace there. Null when nothing in it is open to them.
31
+ */
32
+ export declare function organizationLandingWorkspaceId(workspaces: Workspace[], accountId: string, rememberedWorkspaceId?: string | null): string | null;
@@ -0,0 +1,65 @@
1
+ "use client";
2
+
3
+ // src/organization-model.ts
4
+ function organizationAdministrationAccountIds(accessContext) {
5
+ return accessContext.accountGrants.filter(
6
+ (grant) => grant.subjectId === accessContext.subjectId && (grant.role === "owner" || grant.role === "admin")
7
+ ).map((grant) => grant.accountId).sort();
8
+ }
9
+ function shortAccountId(accountId) {
10
+ return accountId.length > 8 ? accountId.slice(0, 8) : accountId;
11
+ }
12
+ function orgName(accountId, grants) {
13
+ const grant = grants.find((candidate) => candidate.accountId === accountId);
14
+ const label = grant?.metadata && typeof grant.metadata.accountName === "string" ? grant.metadata.accountName : void 0;
15
+ return label?.trim() || null;
16
+ }
17
+ function orgLabel(accountId, grants) {
18
+ return orgName(accountId, grants) ?? `Org ${shortAccountId(accountId)}`;
19
+ }
20
+ function organizationsForSubject(context, workspaces) {
21
+ const administeredIds = new Set(organizationAdministrationAccountIds(context));
22
+ const ids = /* @__PURE__ */ new Set();
23
+ for (const grant of context.accountGrants) {
24
+ ids.add(grant.accountId);
25
+ }
26
+ for (const workspace of workspaces) {
27
+ ids.add(workspace.accountId);
28
+ }
29
+ const options = [...ids].map((accountId) => ({
30
+ accountId,
31
+ label: orgLabel(accountId, context.accountGrants),
32
+ canManage: administeredIds.has(accountId)
33
+ }));
34
+ return options.sort((a, b) => {
35
+ if (a.accountId === context.defaultAccountId) {
36
+ return -1;
37
+ }
38
+ if (b.accountId === context.defaultAccountId) {
39
+ return 1;
40
+ }
41
+ return a.label.localeCompare(b.label) || a.accountId.localeCompare(b.accountId);
42
+ });
43
+ }
44
+ function workspacesInOrg(workspaces, accountId) {
45
+ return workspaces.filter((workspace) => workspace.accountId === accountId).sort((a, b) => a.name.localeCompare(b.name));
46
+ }
47
+ function organizationSettingsWorkspaceId(workspaces, accountId, activeWorkspaceId) {
48
+ const candidates = workspacesInOrg(workspaces, accountId);
49
+ return candidates.find((workspace) => workspace.id === activeWorkspaceId)?.id ?? candidates[0]?.id ?? null;
50
+ }
51
+ function organizationLandingWorkspaceId(workspaces, accountId, rememberedWorkspaceId) {
52
+ const candidates = workspacesInOrg(workspaces, accountId);
53
+ return candidates.find((workspace) => workspace.id === rememberedWorkspaceId)?.id ?? candidates.find((workspace) => workspace.kind !== "personal")?.id ?? candidates[0]?.id ?? null;
54
+ }
55
+ export {
56
+ orgLabel,
57
+ orgName,
58
+ organizationAdministrationAccountIds,
59
+ organizationLandingWorkspaceId,
60
+ organizationSettingsWorkspaceId,
61
+ organizationsForSubject,
62
+ shortAccountId,
63
+ workspacesInOrg
64
+ };
65
+ //# sourceMappingURL=organization-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/organization-model.ts"],"sourcesContent":["// Pure organization and workspace selection rules shared by the web rail's\n// switcher and native renderers. The wire model has no account *name*, so a\n// display label is derived from the access grant — preferring the account\n// name, falling back to a short, stable id fragment. No DOM, no React.\nimport type { AccessContext, AccountGrant, Workspace } from \"@opengeni/sdk\";\n\nexport type OrgOption = {\n accountId: string;\n label: string;\n /** Whether the subject has the owner/admin authority required by organization settings. */\n canManage: boolean;\n};\n\n/** Organizations the subject administers (owner or admin), sorted by id. */\nexport function organizationAdministrationAccountIds(accessContext: AccessContext): string[] {\n return accessContext.accountGrants\n .filter(\n (grant) =>\n grant.subjectId === accessContext.subjectId &&\n (grant.role === \"owner\" || grant.role === \"admin\"),\n )\n .map((grant) => grant.accountId)\n .sort();\n}\n\n/** A short, stable id fragment for an account that has no human name. */\nexport function shortAccountId(accountId: string): string {\n return accountId.length > 8 ? accountId.slice(0, 8) : accountId;\n}\n\n/** The organization's real name, or null when the API sent none. */\nexport function orgName(accountId: string, grants: AccountGrant[]): string | null {\n const grant = grants.find((candidate) => candidate.accountId === accountId);\n const label =\n grant?.metadata && typeof grant.metadata.accountName === \"string\"\n ? grant.metadata.accountName\n : undefined;\n return label?.trim() || null;\n}\n\n/** Human label for an organization: the grant's subjectLabel, else a short id. */\nexport function orgLabel(accountId: string, grants: AccountGrant[]): string {\n return orgName(accountId, grants) ?? `Org ${shortAccountId(accountId)}`;\n}\n\n/**\n * The organizations the subject belongs to, in a stable order (default org\n * first, then by name). Derived from account grants, unioned with the accounts\n * that own the accessible workspaces so an org always shows even without an\n * explicit grant.\n */\nexport function organizationsForSubject(\n context: AccessContext,\n workspaces: Workspace[],\n): OrgOption[] {\n const administeredIds = new Set(organizationAdministrationAccountIds(context));\n const ids = new Set<string>();\n for (const grant of context.accountGrants) {\n ids.add(grant.accountId);\n }\n for (const workspace of workspaces) {\n ids.add(workspace.accountId);\n }\n const options = [...ids].map((accountId) => ({\n accountId,\n label: orgLabel(accountId, context.accountGrants),\n canManage: administeredIds.has(accountId),\n }));\n return options.sort((a, b) => {\n if (a.accountId === context.defaultAccountId) {\n return -1;\n }\n if (b.accountId === context.defaultAccountId) {\n return 1;\n }\n return a.label.localeCompare(b.label) || a.accountId.localeCompare(b.accountId);\n });\n}\n\n/** Workspaces that belong to a given organization, ordered by name. */\nexport function workspacesInOrg(workspaces: Workspace[], accountId: string): Workspace[] {\n return workspaces\n .filter((workspace) => workspace.accountId === accountId)\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/** Organization settings remain anchored to an accessible workspace in that organization. */\nexport function organizationSettingsWorkspaceId(\n workspaces: Workspace[],\n accountId: string,\n activeWorkspaceId: string,\n): string | null {\n const candidates = workspacesInOrg(workspaces, accountId);\n return (\n candidates.find((workspace) => workspace.id === activeWorkspaceId)?.id ??\n candidates[0]?.id ??\n null\n );\n}\n\n/**\n * Where switching to an organization lands: the workspace last used there\n * while it is still open to the person, else its first shared workspace, else\n * their Personal workspace there. Null when nothing in it is open to them.\n */\nexport function organizationLandingWorkspaceId(\n workspaces: Workspace[],\n accountId: string,\n rememberedWorkspaceId?: string | null,\n): string | null {\n const candidates = workspacesInOrg(workspaces, accountId);\n return (\n candidates.find((workspace) => workspace.id === rememberedWorkspaceId)?.id ??\n candidates.find((workspace) => workspace.kind !== \"personal\")?.id ??\n candidates[0]?.id ??\n null\n );\n}\n"],"mappings":";;;AAcO,SAAS,qCAAqC,eAAwC;AAC3F,SAAO,cAAc,cAClB;AAAA,IACC,CAAC,UACC,MAAM,cAAc,cAAc,cACjC,MAAM,SAAS,WAAW,MAAM,SAAS;AAAA,EAC9C,EACC,IAAI,CAAC,UAAU,MAAM,SAAS,EAC9B,KAAK;AACV;AAGO,SAAS,eAAe,WAA2B;AACxD,SAAO,UAAU,SAAS,IAAI,UAAU,MAAM,GAAG,CAAC,IAAI;AACxD;AAGO,SAAS,QAAQ,WAAmB,QAAuC;AAChF,QAAM,QAAQ,OAAO,KAAK,CAAC,cAAc,UAAU,cAAc,SAAS;AAC1E,QAAM,QACJ,OAAO,YAAY,OAAO,MAAM,SAAS,gBAAgB,WACrD,MAAM,SAAS,cACf;AACN,SAAO,OAAO,KAAK,KAAK;AAC1B;AAGO,SAAS,SAAS,WAAmB,QAAgC;AAC1E,SAAO,QAAQ,WAAW,MAAM,KAAK,OAAO,eAAe,SAAS,CAAC;AACvE;AAQO,SAAS,wBACd,SACA,YACa;AACb,QAAM,kBAAkB,IAAI,IAAI,qCAAqC,OAAO,CAAC;AAC7E,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,SAAS,QAAQ,eAAe;AACzC,QAAI,IAAI,MAAM,SAAS;AAAA,EACzB;AACA,aAAW,aAAa,YAAY;AAClC,QAAI,IAAI,UAAU,SAAS;AAAA,EAC7B;AACA,QAAM,UAAU,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,eAAe;AAAA,IAC3C;AAAA,IACA,OAAO,SAAS,WAAW,QAAQ,aAAa;AAAA,IAChD,WAAW,gBAAgB,IAAI,SAAS;AAAA,EAC1C,EAAE;AACF,SAAO,QAAQ,KAAK,CAAC,GAAG,MAAM;AAC5B,QAAI,EAAE,cAAc,QAAQ,kBAAkB;AAC5C,aAAO;AAAA,IACT;AACA,QAAI,EAAE,cAAc,QAAQ,kBAAkB;AAC5C,aAAO;AAAA,IACT;AACA,WAAO,EAAE,MAAM,cAAc,EAAE,KAAK,KAAK,EAAE,UAAU,cAAc,EAAE,SAAS;AAAA,EAChF,CAAC;AACH;AAGO,SAAS,gBAAgB,YAAyB,WAAgC;AACvF,SAAO,WACJ,OAAO,CAAC,cAAc,UAAU,cAAc,SAAS,EACvD,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAChD;AAGO,SAAS,gCACd,YACA,WACA,mBACe;AACf,QAAM,aAAa,gBAAgB,YAAY,SAAS;AACxD,SACE,WAAW,KAAK,CAAC,cAAc,UAAU,OAAO,iBAAiB,GAAG,MACpE,WAAW,CAAC,GAAG,MACf;AAEJ;AAOO,SAAS,+BACd,YACA,WACA,uBACe;AACf,QAAM,aAAa,gBAAgB,YAAY,SAAS;AACxD,SACE,WAAW,KAAK,CAAC,cAAc,UAAU,OAAO,qBAAqB,GAAG,MACxE,WAAW,KAAK,CAAC,cAAc,UAAU,SAAS,UAAU,GAAG,MAC/D,WAAW,CAAC,GAAG,MACf;AAEJ;","names":[]}
@@ -1,4 +1,10 @@
1
1
  "use client";
2
+ import {
3
+ STARTUP_WAIT_TITLES,
4
+ sandboxRowTitle,
5
+ startupDuration,
6
+ startupPhaseTitle
7
+ } from "./chunk-ZIB4H5LN.js";
2
8
 
3
9
  // src/timeline/platform-activity-row.tsx
4
10
  function PlatformActivityRow({
@@ -95,90 +101,7 @@ function lucideIcon(j, s, name, children) {
95
101
  children
96
102
  });
97
103
  }
98
- function sandboxRowTitle(item, displayName) {
99
- if (item.name === "sandbox.provision") {
100
- return startupPhaseTitle(
101
- "sandbox",
102
- item.status === "cancelled" ? "complete" : item.status,
103
- item.origin ?? null
104
- );
105
- }
106
- return displayName(item.name);
107
- }
108
- function startupPhaseTitle(phase, status, outcome) {
109
- if (status === "complete" && phase === "sandbox" && outcome && outcome !== "skipped") {
110
- return `Sandbox ${outcome === "resumed" ? "reattached" : outcome}`;
111
- }
112
- if (status === "complete" && phase === "rig" && outcome === "skipped") {
113
- return "Sandbox Environment already ready";
114
- }
115
- const statusIndex = status === "running" ? 0 : status === "failed" ? 1 : status === "cancelled" ? 2 : 3;
116
- return STARTUP_PHASE_TITLES[phase][statusIndex];
117
- }
118
- var STARTUP_WAIT_TITLES = {
119
- capture_in_progress: "Waiting for sandbox checkpoint",
120
- rotation_in_progress: "Waiting for sandbox rotation",
121
- provider_recovery_in_progress: "Waiting for sandbox recovery"
122
- };
123
- var STARTUP_PHASE_TITLES = {
124
- queue: [
125
- "Waiting for a worker",
126
- "Worker startup failed",
127
- "Worker wait interrupted",
128
- "Worker started"
129
- ],
130
- sandbox: [
131
- "Starting sandbox",
132
- "Sandbox didn\u2019t start",
133
- "Sandbox startup interrupted",
134
- "Sandbox ready"
135
- ],
136
- rig: [
137
- "Setting up sandbox environment",
138
- "Sandbox Environment setup failed",
139
- "Sandbox Environment setup interrupted",
140
- "Sandbox Environment ready"
141
- ],
142
- repository: [
143
- "Preparing repository",
144
- "Repository preparation failed",
145
- "Repository preparation interrupted",
146
- "Repository ready"
147
- ],
148
- files: [
149
- "Preparing files",
150
- "File preparation failed",
151
- "File preparation interrupted",
152
- "Files ready"
153
- ],
154
- tools: [
155
- "Connecting tools",
156
- "Tool connection failed",
157
- "Tool connection interrupted",
158
- "Tools ready"
159
- ],
160
- model_preparation: [
161
- "Preparing runtime and model request",
162
- "Runtime/model preparation failed",
163
- "Runtime/model preparation interrupted",
164
- "Model request dispatched"
165
- ],
166
- provider_first_byte: [
167
- "Waiting for model",
168
- "Model didn\u2019t respond",
169
- "Model wait interrupted",
170
- "Model started responding"
171
- ]
172
- };
173
- function startupDuration(durationMs) {
174
- if (durationMs === null || !Number.isFinite(durationMs) || durationMs < 0) return null;
175
- if (durationMs < 1e3) return `${Math.round(durationMs)}ms`;
176
- if (durationMs < 6e4) return `${(durationMs / 1e3).toFixed(1)}s`;
177
- const minutes = Math.floor(durationMs / 6e4);
178
- const seconds = Math.round(durationMs % 6e4 / 1e3);
179
- return `${minutes}m ${String(seconds).padStart(2, "0")}s`;
180
- }
181
104
  export {
182
105
  PlatformActivityRow as default
183
106
  };
184
- //# sourceMappingURL=platform-activity-row-PJJVATTZ.js.map
107
+ //# sourceMappingURL=platform-activity-row-NJ47YBXW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/timeline/platform-activity-row.tsx"],"sourcesContent":["import {\n sandboxRowTitle,\n startupDuration,\n startupPhaseTitle,\n STARTUP_WAIT_TITLES,\n} from \"./platform-activity-presentation\";\nimport type { ReasoningItem, SandboxItem, StartupPhaseItem } from \"./types\";\n\ntype RowJsx = typeof import(\"react/jsx-runtime\").jsx;\ntype RowJsxs = typeof import(\"react/jsx-runtime\").jsxs;\n\nexport default function PlatformActivityRow({\n item,\n d: ActivityDisclosure,\n p: PayloadBlock,\n t: displayName,\n b: BotIcon,\n m: Markdown,\n j,\n s,\n}: {\n item: ReasoningItem | SandboxItem | StartupPhaseItem;\n d: typeof import(\"./shared\").ActivityDisclosure;\n p: typeof import(\"./shared\").PayloadBlock;\n t: (name: string) => string;\n b: typeof import(\"lucide-react\").BotIcon;\n m: typeof import(\"../components/markdown\").Markdown;\n j: RowJsx;\n s: RowJsxs;\n}) {\n if (item.kind === \"reasoning\") {\n return j(ActivityDisclosure, {\n icon: brainIcon(j, s),\n iconTone: \"muted\",\n title: item.streaming\n ? \"Thinking\"\n : j(\"span\", {\n className: \"font-normal italic text-og-fg-subtle\",\n children: \"Thought\",\n }),\n running: item.streaming,\n compactPreview: item.text.replace(/\\*\\*|__|`/g, \"\").replace(/\\s+/g, \" \"),\n preview: j(\"span\", {\n className: \"og-reasoning-preview\",\n children: j(Markdown, { streaming: item.streaming, children: item.text }),\n }),\n children: j(\"div\", {\n className: \"text-og-base leading-6 text-og-fg-muted [&_strong]:text-og-fg-muted\",\n children: j(Markdown, { streaming: item.streaming, children: item.text }),\n }),\n });\n }\n if (item.kind === \"sandbox\") {\n return s(ActivityDisclosure, {\n icon: terminalIcon(j, s),\n iconTone:\n item.status === \"failed\" ? \"failed\" : item.status === \"running\" ? \"running\" : \"muted\",\n title: sandboxRowTitle(item, displayName),\n running: item.status === \"running\",\n failed: item.status === \"failed\",\n cancelled: item.status === \"cancelled\",\n preview: item.command ?? undefined,\n children: [\n item.command ? j(PayloadBlock, { label: \"Command\", value: item.command }, \"command\") : null,\n item.output ? j(PayloadBlock, { label: \"Output\", value: item.output }, \"output\") : null,\n ],\n });\n }\n\n const failed = item.status === \"failed\";\n const running = item.status === \"running\";\n const duration = startupDuration(item.durationMs);\n return j(ActivityDisclosure, {\n icon: j(BotIcon, { className: \"size-3.5\" }),\n iconTone: failed ? \"failed\" : running ? \"running\" : \"muted\",\n title: item.blockedReason\n ? STARTUP_WAIT_TITLES[item.blockedReason]\n : startupPhaseTitle(item.phase, item.status, item.outcome),\n preview:\n item.phase === \"model_preparation\"\n ? \"Includes overlapping sandbox startup, custom environment setup, repository preparation, and runtime setup shown below.\"\n : undefined,\n running,\n failed,\n cancelled: item.status === \"cancelled\",\n chip: duration ? { tone: failed ? \"bad\" : \"muted\", text: duration } : undefined,\n expandable: false,\n });\n}\n\nfunction brainIcon(j: RowJsx, s: RowJsxs) {\n return lucideIcon(j, s, \"brain\", [\n j(\"path\", { d: \"M 12 18V5\" }, \"spine\"),\n j(\"path\", { d: \"M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4\" }, \"center\"),\n j(\"path\", { d: \"M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5\" }, \"top\"),\n j(\"path\", { d: \"M17.997 5.125a4 4 0 0 1 2.526 5.77\" }, \"upper-right\"),\n j(\"path\", { d: \"M18 18a4 4 0 0 0 2-7.464\" }, \"right\"),\n j(\"path\", { d: \"M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517\" }, \"base\"),\n j(\"path\", { d: \"M6 18a4 4 0 0 1-2-7.464\" }, \"left\"),\n j(\"path\", { d: \"M6.003 5.125a4 4 0 0 0-2.526 5.77\" }, \"upper-left\"),\n ]);\n}\n\nfunction terminalIcon(j: RowJsx, s: RowJsxs) {\n return lucideIcon(j, s, \"square-terminal\", [\n j(\"path\", { d: \"m7 11 2-2-2-2\" }, \"prompt\"),\n j(\"path\", { d: \"M11 13h4\" }, \"cursor\"),\n j(\"rect\", { width: 18, height: 18, x: 3, y: 3, rx: 2, ry: 2 }, \"frame\"),\n ]);\n}\n\nfunction lucideIcon(j: RowJsx, s: RowJsxs, name: string, children: ReturnType<RowJsx>[]) {\n return s(\"svg\", {\n \"aria-hidden\": \"true\",\n className: `lucide lucide-${name} size-3.5`,\n fill: \"none\",\n height: 24,\n stroke: \"currentColor\",\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\n viewBox: \"0 0 24 24\",\n width: 24,\n children,\n });\n}\n"],"mappings":"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","names":[]}
@@ -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":[]}