@opengeni/react 0.46.1 → 0.52.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/README.md +158 -14
  2. package/dist/artifacts-document.d.ts +3 -0
  3. package/dist/artifacts-document.js +17 -0
  4. package/dist/artifacts-document.js.map +1 -0
  5. package/dist/artifacts-presentation.d.ts +3 -0
  6. package/dist/artifacts-presentation.js +17 -0
  7. package/dist/artifacts-presentation.js.map +1 -0
  8. package/dist/artifacts-spreadsheet.d.ts +3 -0
  9. package/dist/artifacts-spreadsheet.js +17 -0
  10. package/dist/artifacts-spreadsheet.js.map +1 -0
  11. package/dist/artifacts.d.ts +2 -0
  12. package/dist/artifacts.js +170 -0
  13. package/dist/artifacts.js.map +1 -0
  14. package/dist/chunk-6BBWWOOU.js +82 -0
  15. package/dist/chunk-6BBWWOOU.js.map +1 -0
  16. package/dist/{chunk-HFO4ERGQ.js → chunk-724BW4TW.js} +586 -35
  17. package/dist/chunk-724BW4TW.js.map +1 -0
  18. package/dist/chunk-7I2KB3OK.js +3895 -0
  19. package/dist/chunk-7I2KB3OK.js.map +1 -0
  20. package/dist/chunk-7WCLAEFV.js +2828 -0
  21. package/dist/chunk-7WCLAEFV.js.map +1 -0
  22. package/dist/{chunk-U3CSCMWA.js → chunk-FK6VG4LL.js} +9 -13
  23. package/dist/chunk-FK6VG4LL.js.map +1 -0
  24. package/dist/{chunk-SRFUT2ZU.js → chunk-FWS3KC3Z.js} +120 -64
  25. package/dist/chunk-FWS3KC3Z.js.map +1 -0
  26. package/dist/{chunk-EKZH6IDG.js → chunk-HDBG7XGO.js} +62 -1
  27. package/dist/chunk-HDBG7XGO.js.map +1 -0
  28. package/dist/chunk-HUIKIDM5.js +2148 -0
  29. package/dist/chunk-HUIKIDM5.js.map +1 -0
  30. package/dist/{chunk-LGVMUIRV.js → chunk-JAGDUCZQ.js} +1053 -390
  31. package/dist/chunk-JAGDUCZQ.js.map +1 -0
  32. package/dist/{chunk-LWR4MXSS.js → chunk-JR3QFY6B.js} +420 -35
  33. package/dist/chunk-JR3QFY6B.js.map +1 -0
  34. package/dist/chunk-JVYQRRC4.js +53 -0
  35. package/dist/chunk-JVYQRRC4.js.map +1 -0
  36. package/dist/chunk-KCGXPP5V.js +157 -0
  37. package/dist/chunk-KCGXPP5V.js.map +1 -0
  38. package/dist/{chunk-EB67J347.js → chunk-KZ73RL76.js} +111 -31
  39. package/dist/chunk-KZ73RL76.js.map +1 -0
  40. package/dist/chunk-PEI6RANI.js +3234 -0
  41. package/dist/chunk-PEI6RANI.js.map +1 -0
  42. package/dist/{chunk-3PB7MIT6.js → chunk-ROIRTM37.js} +220 -72
  43. package/dist/chunk-ROIRTM37.js.map +1 -0
  44. package/dist/chunk-VZTQ73XT.js +86 -0
  45. package/dist/chunk-VZTQ73XT.js.map +1 -0
  46. package/dist/{chunk-VCBFUSUZ.js → chunk-WSK7G5LE.js} +72 -4
  47. package/dist/chunk-WSK7G5LE.js.map +1 -0
  48. package/dist/{chunk-FGZUCXZF.js → chunk-WYA65Y3F.js} +16 -16
  49. package/dist/chunk-WYA65Y3F.js.map +1 -0
  50. package/dist/{chunk-6EDV6YFE.js → chunk-X4S56Y2H.js} +147 -35
  51. package/dist/chunk-X4S56Y2H.js.map +1 -0
  52. package/dist/client.d.ts +7 -1
  53. package/dist/clipboard.d.ts +1 -0
  54. package/dist/clipboard.js +7 -0
  55. package/dist/clipboard.js.map +1 -0
  56. package/dist/commands/index.d.ts +3 -3
  57. package/dist/commands/registry.d.ts +1 -1
  58. package/dist/commands/types.d.ts +1 -1
  59. package/dist/components/approval-surface.d.ts +2 -2
  60. package/dist/components/artifacts/artifact-surface.d.ts +18 -0
  61. package/dist/components/artifacts/document-editor.d.ts +172 -0
  62. package/dist/components/artifacts/editable-artifact-ui.d.ts +13 -0
  63. package/dist/components/artifacts/editable-artifact-workbench.d.ts +49 -0
  64. package/dist/components/artifacts/editable-document.d.ts +24 -0
  65. package/dist/components/artifacts/editable-presentation.d.ts +24 -0
  66. package/dist/components/artifacts/editable-spreadsheet.d.ts +32 -0
  67. package/dist/components/artifacts/index.d.ts +8 -0
  68. package/dist/components/artifacts/presentation-editor.d.ts +297 -0
  69. package/dist/components/artifacts/spreadsheet-canvas.d.ts +120 -0
  70. package/dist/components/artifacts/spreadsheet-grid.d.ts +113 -0
  71. package/dist/components/browser-viewer.d.ts +29 -0
  72. package/dist/components/chat-composer.d.ts +13 -8
  73. package/dist/components/code-editor.d.ts +25 -3
  74. package/dist/components/command-palette.d.ts +2 -2
  75. package/dist/components/composer-transcription-control.d.ts +4 -2
  76. package/dist/components/composer.d.ts +29 -15
  77. package/dist/components/computer-viewer.d.ts +23 -0
  78. package/dist/components/copy-button.d.ts +2 -2
  79. package/dist/components/desktop-viewer.d.ts +25 -21
  80. package/dist/components/diff-view.d.ts +1 -1
  81. package/dist/components/enrollment-consent.d.ts +1 -1
  82. package/dist/components/enrollment-device-flow.d.ts +1 -1
  83. package/dist/components/file-browser.d.ts +2 -2
  84. package/dist/components/fleet-tile.d.ts +1 -1
  85. package/dist/components/generated-video-player.d.ts +10 -0
  86. package/dist/components/human-input-form.d.ts +1 -1
  87. package/dist/components/human-input-surface.d.ts +2 -2
  88. package/dist/components/interactive-workbench-viewers.d.ts +2 -0
  89. package/dist/components/machine-card.d.ts +2 -2
  90. package/dist/components/machine-dock-bar.d.ts +3 -3
  91. package/dist/components/machine-health-pill.d.ts +2 -2
  92. package/dist/components/machine-input-display.d.ts +1 -1
  93. package/dist/components/machine-metrics.d.ts +2 -2
  94. package/dist/components/machine-status-pill.d.ts +4 -4
  95. package/dist/components/machines/health.d.ts +1 -1
  96. package/dist/components/machines/machine-detail.d.ts +5 -3
  97. package/dist/components/machines/metric-history-chart.d.ts +1 -1
  98. package/dist/components/machines/metric-sparkline.d.ts +2 -2
  99. package/dist/components/machines/series.d.ts +2 -2
  100. package/dist/components/machines-dashboard.d.ts +5 -5
  101. package/dist/components/markdown.d.ts +1 -1
  102. package/dist/components/message-timeline.d.ts +22 -5
  103. package/dist/components/model-picker.d.ts +2 -2
  104. package/dist/components/model-policy-picker.d.ts +7 -7
  105. package/dist/components/pierre-diff.d.ts +1 -1
  106. package/dist/components/pierre-file.d.ts +1 -1
  107. package/dist/components/queue-draft-policy.d.ts +1 -1
  108. package/dist/components/queue-surface-implementation.d.ts +3 -3
  109. package/dist/components/queue-surface-state.d.ts +4 -4
  110. package/dist/components/queue-surface.d.ts +5 -5
  111. package/dist/components/sandbox-files.d.ts +5 -5
  112. package/dist/components/sandbox-terminal.d.ts +50 -4
  113. package/dist/components/sandbox-workspace.d.ts +30 -10
  114. package/dist/components/session-chrome.d.ts +4 -4
  115. package/dist/components/session-status.d.ts +2 -2
  116. package/dist/components/timeline-annotation-selection.d.ts +9 -0
  117. package/dist/components/timeline-annotations-dialog.d.ts +16 -0
  118. package/dist/components/timeline-annotations.d.ts +13 -0
  119. package/dist/components/tooltip.d.ts +4 -4
  120. package/dist/components/user-message-body.d.ts +2 -2
  121. package/dist/components/workbench-changes.d.ts +2 -2
  122. package/dist/components/workspace-dock.d.ts +3 -1
  123. package/dist/composer.d.ts +11 -11
  124. package/dist/composer.js +7 -7
  125. package/dist/hooks/internal.d.ts +7 -1
  126. package/dist/hooks/use-attached-browsers.d.ts +21 -0
  127. package/dist/hooks/use-available-models.d.ts +2 -2
  128. package/dist/hooks/use-billing-usage.d.ts +1 -1
  129. package/dist/hooks/use-browser-frame-stream.d.ts +28 -0
  130. package/dist/hooks/use-browser-identities.d.ts +26 -0
  131. package/dist/hooks/use-browser-session.d.ts +28 -0
  132. package/dist/hooks/use-browser-sessions.d.ts +32 -0
  133. package/dist/hooks/use-codex-accounts.d.ts +3 -3
  134. package/dist/hooks/use-composer.d.ts +36 -9
  135. package/dist/hooks/use-computer-frame-stream.d.ts +24 -0
  136. package/dist/hooks/use-computer-session.d.ts +28 -0
  137. package/dist/hooks/use-computer-sessions.d.ts +28 -0
  138. package/dist/hooks/use-desktop-stream.d.ts +1 -1
  139. package/dist/hooks/use-environments.d.ts +11 -5
  140. package/dist/hooks/use-file-attachments.d.ts +1 -1
  141. package/dist/hooks/use-goal.d.ts +2 -2
  142. package/dist/hooks/use-human-input.d.ts +2 -2
  143. package/dist/hooks/use-last-started-turn-policy.d.ts +2 -2
  144. package/dist/hooks/use-machine-chip.d.ts +2 -2
  145. package/dist/hooks/use-machines.d.ts +10 -3
  146. package/dist/hooks/use-packs.d.ts +7 -2
  147. package/dist/hooks/use-rigs.d.ts +1 -1
  148. package/dist/hooks/use-sandbox-files.d.ts +25 -4
  149. package/dist/hooks/use-sandbox-git.d.ts +13 -5
  150. package/dist/hooks/use-sandbox-terminal.d.ts +1 -1
  151. package/dist/hooks/use-scheduled-tasks.d.ts +1 -1
  152. package/dist/hooks/use-session-capabilities.d.ts +5 -4
  153. package/dist/hooks/use-session-control.d.ts +1 -1
  154. package/dist/hooks/use-session-events.d.ts +2 -2
  155. package/dist/hooks/use-session-lineage.d.ts +1 -1
  156. package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
  157. package/dist/hooks/use-session.d.ts +2 -2
  158. package/dist/hooks/use-slash-commands.d.ts +1 -1
  159. package/dist/hooks/use-terminal-stream.d.ts +8 -2
  160. package/dist/hooks/use-transcription.d.ts +2 -2
  161. package/dist/hooks/use-turn-queue.d.ts +2 -2
  162. package/dist/hooks/use-video-artifact-playback.d.ts +9 -0
  163. package/dist/hooks/use-voice-input.d.ts +6 -4
  164. package/dist/hooks/use-workspace-capture.d.ts +1 -1
  165. package/dist/hooks/use-workspace-edit.d.ts +1 -1
  166. package/dist/hooks/use-workspace-sessions.d.ts +1 -1
  167. package/dist/hooks/use-workspaces.d.ts +1 -1
  168. package/dist/index.d.ts +158 -154
  169. package/dist/index.js +1718 -908
  170. package/dist/index.js.map +1 -1
  171. package/dist/interaction.d.ts +23 -0
  172. package/dist/interaction.js +36 -0
  173. package/dist/interaction.js.map +1 -0
  174. package/dist/interactive-workbench-viewers-KHNOHWQE.js +13 -0
  175. package/dist/interactive-workbench-viewers-KHNOHWQE.js.map +1 -0
  176. package/dist/lib/composer-responsive-context.d.ts +9 -0
  177. package/dist/lib/relay-wire.d.ts +4 -0
  178. package/dist/lib/sandbox-liveness.d.ts +9 -0
  179. package/dist/lib/terminal-capability.d.ts +5 -0
  180. package/dist/lib/use-portal-token-style.d.ts +14 -3
  181. package/dist/lib/xterm-theme.d.ts +1 -1
  182. package/dist/machines.d.ts +30 -30
  183. package/dist/machines.js +3 -3
  184. package/dist/provider.d.ts +4 -4
  185. package/dist/{queue-surface-implementation-J4XJFKRW.js → queue-surface-implementation-2KVJTYXH.js} +117 -64
  186. package/dist/queue-surface-implementation-2KVJTYXH.js.map +1 -0
  187. package/dist/realtime/dropdown-menu.d.ts +8 -8
  188. package/dist/realtime/realtime-control.d.ts +15 -6
  189. package/dist/realtime.d.ts +4 -4
  190. package/dist/realtime.js +30 -33
  191. package/dist/realtime.js.map +1 -1
  192. package/dist/session-context.d.ts +19 -1
  193. package/dist/session-ui.d.ts +14 -14
  194. package/dist/session-ui.js +6 -5
  195. package/dist/session.d.ts +28 -28
  196. package/dist/session.js +5 -5
  197. package/dist/timeline/activity-rail.d.ts +6 -3
  198. package/dist/timeline/disclosure-context.d.ts +1 -1
  199. package/dist/timeline/fleet-decision-projection.d.ts +1 -1
  200. package/dist/timeline/fleet-decision-row.d.ts +3 -3
  201. package/dist/timeline/index.d.ts +19 -19
  202. package/dist/timeline/parsers.d.ts +6 -3
  203. package/dist/timeline/projection.d.ts +3 -3
  204. package/dist/timeline/registry.d.ts +10 -1
  205. package/dist/timeline/screenshot-lightbox.d.ts +2 -2
  206. package/dist/timeline/shared.d.ts +21 -10
  207. package/dist/timeline/tool-diff.d.ts +2 -2
  208. package/dist/timeline/tool-renderers.d.ts +1 -1
  209. package/dist/timeline/turn-summary.d.ts +3 -3
  210. package/dist/timeline/types.d.ts +42 -2
  211. package/dist/timeline-annotation-selection-3L7LHGG2.js +187 -0
  212. package/dist/timeline-annotation-selection-3L7LHGG2.js.map +1 -0
  213. package/dist/timeline-annotations-dialog-U7EVLR75.js +196 -0
  214. package/dist/timeline-annotations-dialog-U7EVLR75.js.map +1 -0
  215. package/dist/voice-recording-store.d.ts +8 -2
  216. package/package.json +52 -7
  217. package/src/artifacts-document.ts +31 -0
  218. package/src/artifacts-presentation.ts +36 -0
  219. package/src/artifacts-spreadsheet.ts +21 -0
  220. package/src/artifacts.ts +86 -0
  221. package/src/client.ts +90 -1
  222. package/src/clipboard.ts +2 -0
  223. package/src/components/artifacts/artifact-surface.tsx +93 -0
  224. package/src/components/artifacts/document-editor.tsx +2255 -0
  225. package/src/components/artifacts/editable-artifact-ui.tsx +89 -0
  226. package/src/components/artifacts/editable-artifact-workbench.tsx +203 -0
  227. package/src/components/artifacts/editable-document.tsx +657 -0
  228. package/src/components/artifacts/editable-presentation.tsx +1020 -0
  229. package/src/components/artifacts/editable-spreadsheet.tsx +733 -0
  230. package/src/components/artifacts/index.ts +99 -0
  231. package/src/components/artifacts/presentation-editor.tsx +3148 -0
  232. package/src/components/artifacts/spreadsheet-canvas.ts +799 -0
  233. package/src/components/artifacts/spreadsheet-grid.tsx +2129 -0
  234. package/src/components/browser-viewer.tsx +1592 -0
  235. package/src/components/chat-composer.tsx +25 -2
  236. package/src/components/code-editor.tsx +90 -31
  237. package/src/components/command-palette.tsx +1 -1
  238. package/src/components/composer-transcription-control.tsx +51 -22
  239. package/src/components/composer.tsx +49 -23
  240. package/src/components/computer-viewer.tsx +1139 -0
  241. package/src/components/copy-button.tsx +1 -1
  242. package/src/components/desktop-viewer.tsx +103 -75
  243. package/src/components/file-browser.tsx +39 -17
  244. package/src/components/generated-video-player.tsx +89 -0
  245. package/src/components/human-input-form.tsx +2 -2
  246. package/src/components/interactive-workbench-viewers.ts +2 -0
  247. package/src/components/machine-card.tsx +1 -1
  248. package/src/components/machine-input-display.ts +3 -0
  249. package/src/components/machines/machine-detail.tsx +39 -15
  250. package/src/components/machines-dashboard.tsx +7 -6
  251. package/src/components/message-timeline.tsx +327 -37
  252. package/src/components/model-picker.tsx +2 -2
  253. package/src/components/model-policy-picker.tsx +16 -15
  254. package/src/components/queue-surface-implementation.tsx +135 -75
  255. package/src/components/queue-surface-state.tsx +2 -2
  256. package/src/components/sandbox-files.tsx +142 -62
  257. package/src/components/sandbox-terminal.tsx +119 -35
  258. package/src/components/sandbox-workspace.tsx +394 -228
  259. package/src/components/session-chrome.tsx +67 -27
  260. package/src/components/timeline-annotation-selection.tsx +221 -0
  261. package/src/components/timeline-annotations-dialog.tsx +213 -0
  262. package/src/components/timeline-annotations.tsx +84 -0
  263. package/src/components/tooltip.tsx +13 -16
  264. package/src/components/user-message-body.tsx +1 -1
  265. package/src/components/workbench-changes.tsx +192 -35
  266. package/src/components/workspace-dock.tsx +13 -5
  267. package/src/composer.ts +3 -0
  268. package/src/hooks/internal.ts +132 -38
  269. package/src/hooks/use-attached-browsers.ts +152 -0
  270. package/src/hooks/use-browser-frame-stream.ts +316 -0
  271. package/src/hooks/use-browser-identities.ts +225 -0
  272. package/src/hooks/use-browser-session.ts +476 -0
  273. package/src/hooks/use-browser-sessions.ts +281 -0
  274. package/src/hooks/use-codex-accounts.ts +4 -4
  275. package/src/hooks/use-composer.ts +769 -24
  276. package/src/hooks/use-computer-frame-stream.ts +311 -0
  277. package/src/hooks/use-computer-session.ts +442 -0
  278. package/src/hooks/use-computer-sessions.ts +245 -0
  279. package/src/hooks/use-environments.ts +24 -5
  280. package/src/hooks/use-file-attachments.ts +70 -32
  281. package/src/hooks/use-goal.ts +17 -5
  282. package/src/hooks/use-machine-chip.ts +5 -3
  283. package/src/hooks/use-machines.ts +79 -3
  284. package/src/hooks/use-packs.ts +51 -0
  285. package/src/hooks/use-sandbox-files.ts +382 -88
  286. package/src/hooks/use-sandbox-git.ts +208 -46
  287. package/src/hooks/use-sandbox-terminal.ts +3 -2
  288. package/src/hooks/use-session-capabilities.ts +94 -70
  289. package/src/hooks/use-session-events.ts +18 -4
  290. package/src/hooks/use-terminal-stream.ts +102 -23
  291. package/src/hooks/use-transcription.ts +4 -14
  292. package/src/hooks/use-turn-queue.ts +17 -5
  293. package/src/hooks/use-video-artifact-playback.ts +28 -0
  294. package/src/hooks/use-voice-input.ts +163 -19
  295. package/src/hooks/use-windowed-sections.ts +9 -7
  296. package/src/hooks/use-workspace-edit.ts +2 -1
  297. package/src/index.ts +21 -6
  298. package/src/interaction.ts +71 -0
  299. package/src/lib/composer-responsive-context.ts +15 -0
  300. package/src/lib/relay-wire.ts +4 -0
  301. package/src/lib/sandbox-liveness.ts +11 -0
  302. package/src/lib/terminal-capability.ts +10 -0
  303. package/src/lib/use-portal-token-style.ts +60 -15
  304. package/src/provider.tsx +52 -7
  305. package/src/realtime/dropdown-menu.tsx +15 -19
  306. package/src/realtime/realtime-control.tsx +16 -5
  307. package/src/session-context.ts +90 -0
  308. package/src/timeline/activity-rail.tsx +31 -6
  309. package/src/timeline/index.ts +4 -1
  310. package/src/timeline/parsers.ts +46 -20
  311. package/src/timeline/projection.ts +233 -13
  312. package/src/timeline/registry.ts +19 -0
  313. package/src/timeline/screenshot-lightbox.tsx +30 -9
  314. package/src/timeline/shared.tsx +59 -11
  315. package/src/timeline/tool-renderers.tsx +421 -24
  316. package/src/timeline/turn-summary.tsx +2 -2
  317. package/src/timeline/types.ts +58 -2
  318. package/src/voice-recording-store.ts +15 -0
  319. package/styles/compiled.css +5298 -0
  320. package/styles/compiled.d.ts +2 -0
  321. package/styles/effective-tokens.css +27 -0
  322. package/styles/index.css +18 -0
  323. package/styles/responsive.css +208 -0
  324. package/styles/responsive.d.ts +2 -0
  325. package/styles/tokens.css +50 -17
  326. package/dist/chunk-3PB7MIT6.js.map +0 -1
  327. package/dist/chunk-6EDV6YFE.js.map +0 -1
  328. package/dist/chunk-EB67J347.js.map +0 -1
  329. package/dist/chunk-EKZH6IDG.js.map +0 -1
  330. package/dist/chunk-FGZUCXZF.js.map +0 -1
  331. package/dist/chunk-HFO4ERGQ.js.map +0 -1
  332. package/dist/chunk-JB5725BI.js +0 -48
  333. package/dist/chunk-JB5725BI.js.map +0 -1
  334. package/dist/chunk-LGVMUIRV.js.map +0 -1
  335. package/dist/chunk-LWR4MXSS.js.map +0 -1
  336. package/dist/chunk-SRFUT2ZU.js.map +0 -1
  337. package/dist/chunk-U3CSCMWA.js.map +0 -1
  338. package/dist/chunk-VCBFUSUZ.js.map +0 -1
  339. package/dist/fleet-decision-projection-SLNZMS42.js +0 -241
  340. package/dist/fleet-decision-projection-SLNZMS42.js.map +0 -1
  341. package/dist/queue-surface-implementation-J4XJFKRW.js.map +0 -1
@@ -1,6 +1,14 @@
1
- import { normalizeMcpOutput, type GitFileDiff } from "@opengeni/sdk";
1
+ import {
2
+ normalizeMcpOutput,
3
+ parseGeneratedImageReceipt,
4
+ type GeneratedImageReceipt,
5
+ type GitFileDiff,
6
+ type RetainedArtifactMetadata,
7
+ } from "@opengeni/sdk";
2
8
  import { tryParseJson } from "../lib/format";
3
9
 
10
+ export type { GeneratedImageReceipt };
11
+
4
12
  /* ----------------------------------------------------------------------------
5
13
  Pure parsers for the provider-native tool shapes that the timeline renders.
6
14
 
@@ -437,25 +445,6 @@ export function isApplyPatch(item: { name: string; raw: unknown }): boolean {
437
445
  return name === "apply_patch_call" || name === "apply_patch" || name.endsWith("__apply_patch");
438
446
  }
439
447
 
440
- /* --- secret redaction ------------------------------------------------------- */
441
-
442
- const SECRET_KEY = /^(value|secret|token|password|api[_-]?key|signing[_-]?key)$/i;
443
-
444
- /** Deep-redact secret-looking values so arguments never leak a key into the UI. */
445
- export function redactSecrets(value: unknown): unknown {
446
- if (Array.isArray(value)) {
447
- return value.map(redactSecrets);
448
- }
449
- if (value && typeof value === "object") {
450
- const out: Record<string, unknown> = {};
451
- for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
452
- out[k] = SECRET_KEY.test(k) ? "••••" : redactSecrets(v);
453
- }
454
- return out;
455
- }
456
- return value;
457
- }
458
-
459
448
  /** Parse tool arguments that may arrive as a JSON string or an object. */
460
449
  export function parseToolArgs(args: unknown): Record<string, unknown> {
461
450
  if (args == null) {
@@ -558,6 +547,43 @@ export function screenshotDataUrl(out: unknown): string | null {
558
547
  return null;
559
548
  }
560
549
 
550
+ /** Parse the closed retained-screenshot receipt carried by new tool events. */
551
+ export function retainedScreenshotMetadata(out: unknown): RetainedArtifactMetadata | null {
552
+ if (typeof out === "string" && (out.startsWith("{") || out.startsWith("["))) {
553
+ const parsed = tryParseJson(out);
554
+ if (parsed !== undefined && parsed !== out) return retainedScreenshotMetadata(parsed);
555
+ }
556
+ if (Array.isArray(out)) {
557
+ for (const entry of out) {
558
+ const metadata = retainedScreenshotMetadata(entry);
559
+ if (metadata) return metadata;
560
+ }
561
+ return null;
562
+ }
563
+ if (!out || typeof out !== "object") return null;
564
+ const value = out as Record<string, unknown>;
565
+ if (typeof value.artifactId !== "string" || typeof value.available !== "boolean") return null;
566
+ if (!value.available) {
567
+ return typeof value.reason === "string" ? (value as unknown as RetainedArtifactMetadata) : null;
568
+ }
569
+ return value.kind === "computer_screenshot" &&
570
+ value.contentType === "image/png" &&
571
+ typeof value.originalBytes === "number" &&
572
+ typeof value.sha256 === "string" &&
573
+ value.dimensions !== null &&
574
+ typeof value.dimensions === "object" &&
575
+ value.retention !== null &&
576
+ typeof value.retention === "object" &&
577
+ (value.retention as Record<string, unknown>).policy === "session_screenshot"
578
+ ? (value as unknown as RetainedArtifactMetadata)
579
+ : null;
580
+ }
581
+
582
+ /** Parse the closed permanent generated-image receipt from native/function tools. */
583
+ export function generatedImageReceipt(out: unknown): GeneratedImageReceipt | null {
584
+ return parseGeneratedImageReceipt(out);
585
+ }
586
+
561
587
  export type TimelineMediaPreview = {
562
588
  type: "media_preview";
563
589
  mediaType: string;
@@ -1,5 +1,10 @@
1
- import type { SessionEvent, SessionStatus } from "@opengeni/sdk";
2
- const { default: fleetDecisionItem } = await import("./fleet-decision-projection");
1
+ import {
2
+ parseMediaGenerationResult,
3
+ type SessionEvent,
4
+ type SessionStatus,
5
+ type TimelineAnnotation,
6
+ } from "@opengeni/sdk";
7
+ import fleetDecisionItem from "./fleet-decision-projection";
3
8
  import {
4
9
  CREDIT_EXHAUSTION_MESSAGE,
5
10
  humanizeFailureReason,
@@ -21,6 +26,7 @@ import type {
21
26
  TimelineItem,
22
27
  TurnEndItem,
23
28
  ToolCallItem,
29
+ ToolCallTruncation,
24
30
  WorkerItem,
25
31
  } from "./types";
26
32
 
@@ -61,6 +67,56 @@ const WORKER_MESSAGE_TOOL = "session_send_message";
61
67
  * render as machine-input rows.
62
68
  */
63
69
  const LANDMARK_ONLY_TOOL_LEAVES = new Set(["memory_save", "memory_correct"]);
70
+ const TIMELINE_ANNOTATION_ANSI_SEQUENCE = new RegExp("\\u001B\\[[0-?]*[ -/]*[@-~]", "g");
71
+
72
+ function safeTimelineAnnotationJson(value: unknown): string {
73
+ try {
74
+ return JSON.stringify(value) ?? "";
75
+ } catch {
76
+ return String(value ?? "");
77
+ }
78
+ }
79
+
80
+ function timelineAnnotationToolOutputValue(value: unknown, depth = 0): string {
81
+ if (depth > 8 || value === null || value === undefined) {
82
+ return value == null ? "" : safeTimelineAnnotationJson(value);
83
+ }
84
+ if (typeof value === "string") return value;
85
+ if (typeof value !== "object" || Array.isArray(value)) {
86
+ return safeTimelineAnnotationJson(value);
87
+ }
88
+ const record = value as Record<string, unknown>;
89
+ if (record.type === "text" && typeof record.text === "string") return record.text;
90
+ if (Array.isArray(record.content)) {
91
+ const text = record.content.find(
92
+ (part) =>
93
+ part !== null &&
94
+ typeof part === "object" &&
95
+ (part as { type?: unknown }).type === "text" &&
96
+ typeof (part as { text?: unknown }).text === "string",
97
+ ) as { text: string } | undefined;
98
+ if (text) return text.text;
99
+ }
100
+ if ("structuredContent" in record) {
101
+ return timelineAnnotationToolOutputValue(record.structuredContent, depth + 1);
102
+ }
103
+ if ("result" in record) return timelineAnnotationToolOutputValue(record.result, depth + 1);
104
+ return safeTimelineAnnotationJson(value);
105
+ }
106
+
107
+ /** Browser mirror of the server's canonical annotation source projection. */
108
+ function timelineAnnotationToolOutputText(output: unknown): string | null {
109
+ const raw = timelineAnnotationToolOutputValue(output);
110
+ const marker = raw.indexOf("\nOutput:\n");
111
+ const text = (
112
+ marker >= 0
113
+ ? raw.slice(marker + "\nOutput:\n".length)
114
+ : raw.startsWith("Output:\n")
115
+ ? raw.slice("Output:\n".length)
116
+ : raw
117
+ ).replace(TIMELINE_ANNOTATION_ANSI_SEQUENCE, "");
118
+ return text.length > 0 ? text : null;
119
+ }
64
120
 
65
121
  export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
66
122
  const items: TimelineItem[] = [];
@@ -134,6 +190,15 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
134
190
  kind: "user-message",
135
191
  id: event.id,
136
192
  text: voiceMessage?.text ?? stringValue(payload.text),
193
+ annotations: timelineAnnotations(payload.annotations),
194
+ annotationSource: {
195
+ kind: "user_message",
196
+ eventId: event.id,
197
+ eventType: "user.message",
198
+ sequence: event.sequence,
199
+ turnId,
200
+ text: voiceMessage?.text ?? stringValue(payload.text),
201
+ },
137
202
  ...(voiceMessage ? { presentation: voiceMessage.presentation } : {}),
138
203
  resources: resourceRefs(payload.resources),
139
204
  tools: toolRefs(payload.tools),
@@ -212,6 +277,17 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
212
277
  // Completion time is what the footer shows ("finished at"); keep the
213
278
  // first-delta stamp only until this event arrives.
214
279
  open.occurredAt = event.occurredAt;
280
+ open.annotationSource =
281
+ text && open.text === text
282
+ ? {
283
+ kind: "assistant_message",
284
+ eventId: event.id,
285
+ eventType: "agent.message.completed",
286
+ sequence: event.sequence,
287
+ turnId,
288
+ text,
289
+ }
290
+ : undefined;
215
291
  // The SDK can emit a hosted-tool item only after its provider-native
216
292
  // operation has completed, even though answer deltas were already
217
293
  // streamed. The completed message event is the durable ordering
@@ -231,6 +307,14 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
231
307
  text,
232
308
  streaming: false,
233
309
  occurredAt: event.occurredAt,
310
+ annotationSource: {
311
+ kind: "assistant_message",
312
+ eventId: event.id,
313
+ eventType: "agent.message.completed",
314
+ sequence: event.sequence,
315
+ turnId,
316
+ text,
317
+ },
234
318
  });
235
319
  }
236
320
  break;
@@ -312,6 +396,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
312
396
  name,
313
397
  arguments: args,
314
398
  output: undefined,
399
+ truncation: null,
315
400
  // The provider-native item drives the per-tool renderers (apply_patch
316
401
  // operation, computer_call action, web_search providerData, …).
317
402
  raw: payload.raw,
@@ -336,8 +421,30 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
336
421
  }
337
422
  // An output carrying an explicit error flag (or an MCP isError result)
338
423
  // settles the tool to "failed" so the renderer can surface it loudly.
424
+ const truncation = toolCallTruncation(payload);
339
425
  target.status = isErrorOutput(payload) ? "failed" : "complete";
340
- target.output = payload.output;
426
+ target.output = Object.prototype.hasOwnProperty.call(payload, "output")
427
+ ? payload.output
428
+ : truncation && typeof payload.preview === "string"
429
+ ? payload.preview
430
+ : payload.output;
431
+ target.truncation = truncation;
432
+ const sourceText = timelineAnnotationToolOutputText(
433
+ Object.prototype.hasOwnProperty.call(payload, "output")
434
+ ? payload.output
435
+ : payload.preview,
436
+ );
437
+ if (sourceText !== null) {
438
+ target.annotationSource = {
439
+ kind: "tool_output",
440
+ eventId: event.id,
441
+ eventType: "agent.toolCall.output",
442
+ sequence: event.sequence,
443
+ turnId,
444
+ text: sourceText,
445
+ label: target.name,
446
+ };
447
+ }
341
448
  break;
342
449
  }
343
450
 
@@ -540,6 +647,19 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
540
647
 
541
648
  case "tool.auth_needed":
542
649
  case "credential.auth_needed": {
650
+ const capability = capabilityAuthorizationRequest(payload.capability);
651
+ if (
652
+ event.type === "tool.auth_needed" &&
653
+ !stringValue(payload.toolName) &&
654
+ stringValue(payload.serverId) !== "codex_apps"
655
+ ) {
656
+ // Historical optional-MCP initialize/tools-list credential misses are
657
+ // setup availability, not evidence of a concrete conversational tool
658
+ // call. Keep the raw event in Debug/audit but do not manufacture an
659
+ // actionable reconnect card in the transcript. Actual tools/call auth
660
+ // failures carry a concrete toolName and remain visible.
661
+ break;
662
+ }
543
663
  // Keep the whole structured payload — the renderer turns it into a clean
544
664
  // inline reconnect card, and the app starts the recovery flow off the
545
665
  // connectionId/resource. Losing it to a plain-text notice was the ugly
@@ -549,6 +669,12 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
549
669
  kind: "auth-needed",
550
670
  id: event.id,
551
671
  turnId,
672
+ serverId: typeof payload.serverId === "string" ? payload.serverId : null,
673
+ source: capability
674
+ ? "capability"
675
+ : event.type === "tool.auth_needed"
676
+ ? "tool"
677
+ : "credential",
552
678
  providerDomain: stringValue(payload.providerDomain),
553
679
  connectionId: typeof payload.connectionId === "string" ? payload.connectionId : null,
554
680
  reason: authNeededReason(payload.reason),
@@ -557,6 +683,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
557
683
  toolName: typeof payload.toolName === "string" ? payload.toolName : null,
558
684
  authorizationUrl:
559
685
  typeof payload.authorizationUrl === "string" ? payload.authorizationUrl : null,
686
+ capability,
560
687
  occurredAt: event.occurredAt,
561
688
  });
562
689
  break;
@@ -1301,6 +1428,7 @@ function machineInputMembers(value: unknown): MachineInputBatchItem["members"] {
1301
1428
  "agent_message",
1302
1429
  "agent_steer_instruction",
1303
1430
  "child_terminal_result",
1431
+ "media_generation_result",
1304
1432
  ]);
1305
1433
  const classifications = new Set<MachineInputBatchItem["members"][number]["classification"]>([
1306
1434
  "success",
@@ -1319,16 +1447,24 @@ function machineInputMembers(value: unknown): MachineInputBatchItem["members"] {
1319
1447
  member.classification as MachineInputBatchItem["members"][number]["classification"],
1320
1448
  ) &&
1321
1449
  typeof member.sourceId === "string"
1322
- ? [
1323
- {
1324
- id: member.id,
1325
- kind: member.kind as MachineInputBatchItem["members"][number]["kind"],
1326
- classification:
1327
- member.classification as MachineInputBatchItem["members"][number]["classification"],
1328
- sourceId: member.sourceId,
1329
- summary: stringValue(member.summary),
1330
- },
1331
- ]
1450
+ ? (() => {
1451
+ const kind = member.kind as MachineInputBatchItem["members"][number]["kind"];
1452
+ const result =
1453
+ kind === "media_generation_result"
1454
+ ? parseMediaGenerationResult(member.result)
1455
+ : null;
1456
+ return [
1457
+ {
1458
+ id: member.id,
1459
+ kind,
1460
+ classification:
1461
+ member.classification as MachineInputBatchItem["members"][number]["classification"],
1462
+ sourceId: member.sourceId,
1463
+ summary: stringValue(member.summary),
1464
+ ...(result ? { result } : {}),
1465
+ },
1466
+ ];
1467
+ })()
1332
1468
  : [];
1333
1469
  })
1334
1470
  : [];
@@ -1364,6 +1500,25 @@ function resourceRefs(value: unknown): import("@opengeni/sdk").ResourceRef[] {
1364
1500
  });
1365
1501
  }
1366
1502
 
1503
+ function timelineAnnotations(value: unknown): TimelineAnnotation[] {
1504
+ if (!Array.isArray(value)) return [];
1505
+ return value.filter((candidate): candidate is TimelineAnnotation => {
1506
+ const annotation = asRecord(candidate);
1507
+ const source = asRecord(annotation.source);
1508
+ return (
1509
+ typeof annotation.id === "string" &&
1510
+ typeof annotation.ordinal === "number" &&
1511
+ typeof annotation.quote === "string" &&
1512
+ typeof annotation.note === "string" &&
1513
+ typeof source.eventId === "string" &&
1514
+ typeof source.eventType === "string" &&
1515
+ typeof source.sequence === "number" &&
1516
+ typeof source.startOffset === "number" &&
1517
+ typeof source.endOffset === "number"
1518
+ );
1519
+ });
1520
+ }
1521
+
1367
1522
  function toolRefs(value: unknown): import("@opengeni/sdk").ToolRef[] {
1368
1523
  if (!Array.isArray(value)) {
1369
1524
  return [];
@@ -1426,6 +1581,31 @@ function isErrorOutput(payload: Record<string, unknown>): boolean {
1426
1581
  );
1427
1582
  }
1428
1583
 
1584
+ function toolCallTruncation(payload: Record<string, unknown>): ToolCallTruncation | null {
1585
+ const truncation = asRecord(payload.truncation);
1586
+ const fullEvidence = asRecord(truncation.fullEvidence);
1587
+ const surface = stringValue(truncation.surface);
1588
+ const reason = stringValue(truncation.reason);
1589
+ if (
1590
+ truncation.truncated !== true ||
1591
+ !surface ||
1592
+ !reason ||
1593
+ typeof fullEvidence.available !== "boolean"
1594
+ ) {
1595
+ return null;
1596
+ }
1597
+ return {
1598
+ truncated: true,
1599
+ surface,
1600
+ reason,
1601
+ omittedBytes: numberOrNull(truncation.omittedBytes),
1602
+ fullEvidence: {
1603
+ available: fullEvidence.available,
1604
+ reason: stringValue(fullEvidence.reason) || null,
1605
+ },
1606
+ };
1607
+ }
1608
+
1429
1609
  function findOpenCall(
1430
1610
  items: TimelineItem[],
1431
1611
  callId: string | null,
@@ -1549,6 +1729,37 @@ function authNeededReason(value: unknown): AuthNeededItem["reason"] {
1549
1729
  : null;
1550
1730
  }
1551
1731
 
1732
+ function capabilityAuthorizationRequest(
1733
+ value: unknown,
1734
+ ): NonNullable<AuthNeededItem["capability"]> | null {
1735
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
1736
+ const record = value as Record<string, unknown>;
1737
+ const kind = record.kind;
1738
+ const source = record.source;
1739
+ const action = record.action;
1740
+ if (
1741
+ typeof record.id !== "string" ||
1742
+ typeof record.name !== "string" ||
1743
+ !["pack", "mcp", "api", "skill", "plugin"].includes(String(kind)) ||
1744
+ !["built_in", "library", "configured", "public_registry", "registry", "manual"].includes(
1745
+ String(source),
1746
+ ) ||
1747
+ !["connect", "add_credentials", "enable"].includes(String(action)) ||
1748
+ typeof record.rationale !== "string"
1749
+ ) {
1750
+ return null;
1751
+ }
1752
+ return {
1753
+ id: record.id,
1754
+ name: record.name,
1755
+ kind: kind as NonNullable<AuthNeededItem["capability"]>["kind"],
1756
+ source: source as NonNullable<AuthNeededItem["capability"]>["source"],
1757
+ action: action as NonNullable<AuthNeededItem["capability"]>["action"],
1758
+ rationale: record.rationale,
1759
+ requiredVariables: stringList(record.requiredVariables),
1760
+ };
1761
+ }
1762
+
1552
1763
  function stringList(value: unknown): string[] {
1553
1764
  return Array.isArray(value)
1554
1765
  ? value.filter((entry): entry is string => typeof entry === "string" && entry.trim().length > 0)
@@ -1609,6 +1820,15 @@ export function extractSessionRef(value: unknown, depth = 0): string | null {
1609
1820
  return null;
1610
1821
  }
1611
1822
  const record = value as Record<string, unknown>;
1823
+ const receiptResource = asRecord(record.resource);
1824
+ if (
1825
+ record.receiptVersion === "mcp-mutation-receipt.v1" &&
1826
+ receiptResource.type === "session" &&
1827
+ typeof receiptResource.id === "string" &&
1828
+ looksLikeId(receiptResource.id)
1829
+ ) {
1830
+ return receiptResource.id;
1831
+ }
1612
1832
  if (typeof record.sessionId === "string" && looksLikeId(record.sessionId)) {
1613
1833
  return record.sessionId;
1614
1834
  }
@@ -1,3 +1,4 @@
1
+ import type { RetainedArtifactReference, VideoArtifactPlaybackSource } from "@opengeni/sdk";
1
2
  import type { ComponentType } from "react";
2
3
  import { mcpToolLeaf } from "./tool-display-name";
3
4
  import type { ToolCallItem } from "./types";
@@ -22,8 +23,26 @@ import type { ToolCallItem } from "./types";
22
23
 
23
24
  export type ToolRendererProps = {
24
25
  item: ToolCallItem;
26
+ loadRetainedScreenshot?: RetainedScreenshotLoader | undefined;
27
+ loadRetainedArtifact?: RetainedArtifactLoader | undefined;
25
28
  };
26
29
 
30
+ export type RetainedScreenshotLoader = (
31
+ artifact: RetainedArtifactReference,
32
+ signal: AbortSignal,
33
+ ) => Promise<Uint8Array | null>;
34
+
35
+ export type RetainedArtifactLoader = (
36
+ artifact: RetainedArtifactReference,
37
+ signal: AbortSignal,
38
+ ) => Promise<Uint8Array | { url: string } | null>;
39
+
40
+ /** Mint an expiring source for native browser playback without loading video bytes in JS. */
41
+ export type VideoArtifactPlaybackLoader = (
42
+ artifactId: string,
43
+ signal: AbortSignal,
44
+ ) => Promise<VideoArtifactPlaybackSource>;
45
+
27
46
  export type ToolRenderer = ComponentType<ToolRendererProps>;
28
47
 
29
48
  /** A registry entry: which key it matches and the component that renders it. */
@@ -3,6 +3,7 @@ import { AnimatePresence, motion } from "motion/react";
3
3
  import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from "react";
4
4
  import { Dialog } from "radix-ui";
5
5
  import { cn } from "../lib/cn";
6
+ import { usePortalTokenStyle } from "../lib/use-portal-token-style";
6
7
 
7
8
  /* ----------------------------------------------------------------------------
8
9
  Screenshot lightbox
@@ -18,7 +19,7 @@ import { cn } from "../lib/cn";
18
19
  -------------------------------------------------------------------------- */
19
20
 
20
21
  type LightboxController = {
21
- open: (src: string, caption?: string) => void;
22
+ open: (src: string, caption?: string, source?: HTMLElement | null, label?: string) => void;
22
23
  };
23
24
 
24
25
  const LightboxContext = createContext<LightboxController | null>(null);
@@ -58,10 +59,25 @@ export function LightboxProvider({ children }: { children: ReactNode }) {
58
59
  }
59
60
 
60
61
  function LightboxRoot({ children }: { children: ReactNode }) {
61
- const [state, setState] = useState<{ src: string; caption?: string } | null>(null);
62
+ const [state, setState] = useState<{
63
+ src: string;
64
+ caption?: string;
65
+ label: string;
66
+ } | null>(null);
67
+ const [tokenSource, setTokenSource] = useState<HTMLElement | null>(null);
68
+ const portalStyle = usePortalTokenStyle(tokenSource);
62
69
 
63
- const open = useCallback((src: string, caption?: string) => {
64
- setState(caption ? { src, caption } : { src });
70
+ const open = useCallback(
71
+ (src: string, caption?: string, source?: HTMLElement | null, label = "Screenshot") => {
72
+ setTokenSource(source ?? null);
73
+ setState(caption ? { src, caption, label } : { src, label });
74
+ },
75
+ [],
76
+ );
77
+
78
+ const close = useCallback(() => {
79
+ setState(null);
80
+ setTokenSource(null);
65
81
  }, []);
66
82
 
67
83
  const controller = useMemo<LightboxController>(() => ({ open }), [open]);
@@ -69,7 +85,7 @@ function LightboxRoot({ children }: { children: ReactNode }) {
69
85
  return (
70
86
  <LightboxContext.Provider value={controller}>
71
87
  {children}
72
- <Dialog.Root open={state !== null} onOpenChange={(next) => !next && setState(null)}>
88
+ <Dialog.Root open={state !== null} onOpenChange={(next) => !next && close()}>
73
89
  <AnimatePresence>
74
90
  {state !== null ? (
75
91
  <Dialog.Portal forceMount>
@@ -80,12 +96,13 @@ function LightboxRoot({ children }: { children: ReactNode }) {
80
96
  exit={{ opacity: 0 }}
81
97
  transition={{ duration: 0.15 }}
82
98
  className="og-root fixed inset-0 z-50 bg-black/90 backdrop-blur-md"
99
+ style={portalStyle}
83
100
  />
84
101
  </Dialog.Overlay>
85
102
  <Dialog.Content
86
103
  asChild
87
104
  forceMount
88
- aria-label="Screenshot"
105
+ aria-label={state.label}
89
106
  onOpenAutoFocus={(event) => event.preventDefault()}
90
107
  >
91
108
  <motion.div
@@ -101,12 +118,16 @@ function LightboxRoot({ children }: { children: ReactNode }) {
101
118
  // figcaption's "click outside to close" affordance is real.
102
119
  onClick={(event) => {
103
120
  if (event.target === event.currentTarget) {
104
- setState(null);
121
+ close();
105
122
  }
106
123
  }}
107
124
  className="og-root fixed inset-0 z-50 flex items-center justify-center p-6 sm:p-12"
125
+ style={portalStyle}
108
126
  >
109
- <Dialog.Title className="sr-only">Screenshot</Dialog.Title>
127
+ <Dialog.Title className="sr-only">{state.label}</Dialog.Title>
128
+ <Dialog.Description className="sr-only">
129
+ {state.caption ?? `Expanded ${state.label.toLowerCase()}`}
130
+ </Dialog.Description>
110
131
  {/* The figure is one self-contained object: image, caption, and
111
132
  its own close control. The close button anchors to a wrapper
112
133
  sized to the IMAGE (w-fit), so it hugs the real top-right
@@ -117,7 +138,7 @@ function LightboxRoot({ children }: { children: ReactNode }) {
117
138
  {/* A plain <img>: this SDK is framework-agnostic, with no host Image component. */}
118
139
  <img
119
140
  src={state.src}
120
- alt={state.caption ?? "Screenshot"}
141
+ alt={state.caption ?? state.label}
121
142
  className="min-h-0 max-h-[82vh] w-auto max-w-full rounded-og-md border border-white/10 object-contain shadow-og-lg"
122
143
  />
123
144
  <Dialog.Close