@opengeni/react 1.0.1 → 2.2.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +33 -10
  2. package/dist/artifacts-spreadsheet.js +1 -1
  3. package/dist/artifacts.js +1 -1
  4. package/dist/browser-viewer-GXUICIAG.js +14 -0
  5. package/dist/{chunk-R3AZOAB5.js → chunk-4MDLEHXL.js} +9 -115
  6. package/dist/chunk-4MDLEHXL.js.map +1 -0
  7. package/dist/{chunk-Y7OEDUJ5.js → chunk-5RZN3DD5.js} +1014 -420
  8. package/dist/chunk-5RZN3DD5.js.map +1 -0
  9. package/dist/chunk-5YK2ZDIG.js +116 -0
  10. package/dist/chunk-5YK2ZDIG.js.map +1 -0
  11. package/dist/chunk-H5YGYNXS.js +329 -0
  12. package/dist/chunk-H5YGYNXS.js.map +1 -0
  13. package/dist/{chunk-7WCLAEFV.js → chunk-ICA6R6TW.js} +2 -2
  14. package/dist/{chunk-7WCLAEFV.js.map → chunk-ICA6R6TW.js.map} +1 -1
  15. package/dist/{chunk-IGC6A2ZI.js → chunk-JOAVA2TW.js} +589 -217
  16. package/dist/chunk-JOAVA2TW.js.map +1 -0
  17. package/dist/{chunk-5UQPNLIO.js → chunk-LTCHJ4MS.js} +9 -9
  18. package/dist/chunk-LTCHJ4MS.js.map +1 -0
  19. package/dist/{chunk-C5ZPSSS5.js → chunk-NEXLLTP4.js} +2 -1
  20. package/dist/{chunk-C5ZPSSS5.js.map → chunk-NEXLLTP4.js.map} +1 -1
  21. package/dist/chunk-QGBJ6GHG.js +2300 -0
  22. package/dist/chunk-QGBJ6GHG.js.map +1 -0
  23. package/dist/{chunk-B6WPZSTT.js → chunk-UOLJWT5Y.js} +78 -16
  24. package/dist/chunk-UOLJWT5Y.js.map +1 -0
  25. package/dist/{chunk-MKPIAGVL.js → chunk-W6NFJXSA.js} +8 -19
  26. package/dist/chunk-W6NFJXSA.js.map +1 -0
  27. package/dist/{chunk-XBZWOM2K.js → chunk-X4A66EWZ.js} +8 -3
  28. package/dist/chunk-X4A66EWZ.js.map +1 -0
  29. package/dist/chunk-X4JAFD5R.js +3907 -0
  30. package/dist/chunk-X4JAFD5R.js.map +1 -0
  31. package/dist/{chunk-6KLX2RH5.js → chunk-XSA2QAKP.js} +334 -19
  32. package/dist/chunk-XSA2QAKP.js.map +1 -0
  33. package/dist/{chunk-HA46CYQK.js → chunk-XXWH2JLC.js} +792 -206
  34. package/dist/chunk-XXWH2JLC.js.map +1 -0
  35. package/dist/client.d.ts +2 -2
  36. package/dist/components/browser-viewer.d.ts +7 -1
  37. package/dist/components/computer-viewer.d.ts +4 -1
  38. package/dist/components/enrollment-consent.d.ts +6 -3
  39. package/dist/components/file-browser.d.ts +7 -1
  40. package/dist/components/human-input-form.d.ts +1 -1
  41. package/dist/components/human-input-surface.d.ts +1 -1
  42. package/dist/components/machine-card.d.ts +4 -1
  43. package/dist/components/machines/machine-detail.d.ts +4 -1
  44. package/dist/components/machines/machine-operation-policy.d.ts +11 -0
  45. package/dist/components/machines-dashboard.d.ts +3 -1
  46. package/dist/components/markdown.d.ts +20 -1
  47. package/dist/components/message-timeline.d.ts +1 -1
  48. package/dist/components/model-policy-picker.d.ts +2 -0
  49. package/dist/components/pierre-file.d.ts +1 -1
  50. package/dist/components/sandbox-files.d.ts +8 -2
  51. package/dist/components/sandbox-workspace.d.ts +33 -3
  52. package/dist/components/session-chrome.d.ts +15 -3
  53. package/dist/components/workspace-dock.d.ts +6 -2
  54. package/dist/composer.js +5 -5
  55. package/dist/computer-viewer-ZOP4Q7A7.js +16 -0
  56. package/dist/computer-viewer-ZOP4Q7A7.js.map +1 -0
  57. package/dist/hooks/channel-cache.d.ts +23 -0
  58. package/dist/hooks/shared-machines-list.d.ts +14 -0
  59. package/dist/hooks/use-attached-browsers.d.ts +2 -1
  60. package/dist/hooks/use-channels.d.ts +1 -0
  61. package/dist/hooks/use-composer.d.ts +37 -9
  62. package/dist/hooks/use-machine-chip.d.ts +3 -3
  63. package/dist/hooks/use-machines.d.ts +19 -1
  64. package/dist/hooks/use-sandbox-files.d.ts +1 -0
  65. package/dist/hooks/use-session-background-commands.d.ts +14 -0
  66. package/dist/hooks/use-turn-queue.d.ts +12 -0
  67. package/dist/hooks/use-workspace-sessions.d.ts +1 -0
  68. package/dist/index.d.ts +7 -5
  69. package/dist/index.js +1096 -623
  70. package/dist/index.js.map +1 -1
  71. package/dist/interaction.js +29 -181
  72. package/dist/interaction.js.map +1 -1
  73. package/dist/lib/interaction-errors.d.ts +3 -0
  74. package/dist/machines.d.ts +4 -2
  75. package/dist/machines.js +10 -2
  76. package/dist/model-policy.d.ts +1 -1
  77. package/dist/model-policy.js +1 -1
  78. package/dist/platform-activity-row-BJHUHXAT.js +169 -0
  79. package/dist/platform-activity-row-BJHUHXAT.js.map +1 -0
  80. package/dist/{queue-surface-implementation-2KVJTYXH.js → queue-surface-implementation-BSKUWHRI.js} +76 -16
  81. package/dist/queue-surface-implementation-BSKUWHRI.js.map +1 -0
  82. package/dist/realtime/realtime-control.d.ts +6 -3
  83. package/dist/realtime.js +36 -14
  84. package/dist/realtime.js.map +1 -1
  85. package/dist/session-ui.d.ts +1 -1
  86. package/dist/session-ui.js +6 -2
  87. package/dist/session.d.ts +2 -2
  88. package/dist/session.js +4 -4
  89. package/dist/timeline/index.d.ts +1 -1
  90. package/dist/timeline/platform-activity-row.d.ts +15 -0
  91. package/dist/timeline/screenshot-lightbox.d.ts +1 -1
  92. package/dist/timeline/shared.d.ts +4 -2
  93. package/dist/timeline/types.d.ts +48 -5
  94. package/dist/types/machines.d.ts +2 -2
  95. package/package.json +3 -3
  96. package/src/client.ts +12 -1
  97. package/src/components/artifacts/editable-spreadsheet.tsx +1 -1
  98. package/src/components/browser-viewer.tsx +361 -58
  99. package/src/components/chat-composer.tsx +1 -1
  100. package/src/components/composer.tsx +6 -6
  101. package/src/components/computer-viewer.tsx +368 -115
  102. package/src/components/enrollment-consent.tsx +64 -6
  103. package/src/components/file-browser.tsx +117 -2
  104. package/src/components/human-input-form.tsx +91 -55
  105. package/src/components/human-input-surface.tsx +1 -1
  106. package/src/components/machine-card.tsx +111 -0
  107. package/src/components/machine-input-display.ts +15 -0
  108. package/src/components/machines/machine-detail.tsx +47 -0
  109. package/src/components/machines/machine-operation-policy.tsx +179 -0
  110. package/src/components/machines-dashboard.tsx +6 -0
  111. package/src/components/markdown.tsx +174 -20
  112. package/src/components/message-timeline.tsx +162 -17
  113. package/src/components/model-policy-picker.tsx +9 -17
  114. package/src/components/pierre-file.tsx +1 -1
  115. package/src/components/queue-surface-implementation.tsx +82 -16
  116. package/src/components/sandbox-files.tsx +135 -19
  117. package/src/components/sandbox-workspace.tsx +204 -92
  118. package/src/components/session-chrome.tsx +415 -208
  119. package/src/components/session-status.tsx +1 -1
  120. package/src/components/user-message-body.tsx +168 -48
  121. package/src/components/workspace-dock.tsx +141 -175
  122. package/src/hooks/channel-cache.ts +104 -0
  123. package/src/hooks/shared-machines-list.ts +239 -0
  124. package/src/hooks/use-attached-browsers.ts +5 -1
  125. package/src/hooks/use-browser-frame-stream.ts +6 -1
  126. package/src/hooks/use-browser-session.ts +6 -4
  127. package/src/hooks/use-browser-sessions.ts +7 -1
  128. package/src/hooks/use-channels.ts +32 -10
  129. package/src/hooks/use-composer.ts +760 -291
  130. package/src/hooks/use-computer-frame-stream.ts +14 -9
  131. package/src/hooks/use-computer-session.ts +16 -14
  132. package/src/hooks/use-computer-sessions.ts +8 -1
  133. package/src/hooks/use-last-started-turn-policy.ts +1 -1
  134. package/src/hooks/use-machine-chip.ts +23 -6
  135. package/src/hooks/use-machines.ts +104 -6
  136. package/src/hooks/use-sandbox-files.ts +195 -140
  137. package/src/hooks/use-sandbox-git.ts +58 -29
  138. package/src/hooks/use-session-background-commands.ts +56 -0
  139. package/src/hooks/use-session-capabilities.ts +18 -0
  140. package/src/hooks/use-turn-queue.ts +111 -12
  141. package/src/hooks/use-workspace-sessions.ts +5 -1
  142. package/src/index.ts +26 -4
  143. package/src/lib/interaction-errors.ts +18 -0
  144. package/src/machines.ts +9 -1
  145. package/src/model-policy.ts +10 -2
  146. package/src/realtime/realtime-control.tsx +53 -17
  147. package/src/session-context.ts +1 -0
  148. package/src/session-ui.ts +6 -1
  149. package/src/session.ts +9 -1
  150. package/src/timeline/activity-rail.tsx +20 -75
  151. package/src/timeline/index.ts +4 -0
  152. package/src/timeline/platform-activity-row.tsx +201 -0
  153. package/src/timeline/projection.ts +476 -23
  154. package/src/timeline/screenshot-lightbox.tsx +48 -14
  155. package/src/timeline/shared.tsx +8 -2
  156. package/src/timeline/tool-renderers.tsx +104 -6
  157. package/src/timeline/turn-summary.tsx +6 -1
  158. package/src/timeline/types.ts +75 -2
  159. package/src/types/machines.ts +10 -0
  160. package/styles/compiled.css +115 -104
  161. package/dist/chunk-5UQPNLIO.js.map +0 -1
  162. package/dist/chunk-6KLX2RH5.js.map +0 -1
  163. package/dist/chunk-B6WPZSTT.js.map +0 -1
  164. package/dist/chunk-HA46CYQK.js.map +0 -1
  165. package/dist/chunk-IGC6A2ZI.js.map +0 -1
  166. package/dist/chunk-LLOLUHVG.js +0 -5937
  167. package/dist/chunk-LLOLUHVG.js.map +0 -1
  168. package/dist/chunk-MKPIAGVL.js.map +0 -1
  169. package/dist/chunk-R3AZOAB5.js.map +0 -1
  170. package/dist/chunk-XBZWOM2K.js.map +0 -1
  171. package/dist/chunk-Y7OEDUJ5.js.map +0 -1
  172. package/dist/interactive-workbench-viewers-TOHBXJEE.js +0 -15
  173. package/dist/queue-surface-implementation-2KVJTYXH.js.map +0 -1
  174. /package/dist/{interactive-workbench-viewers-TOHBXJEE.js.map → browser-viewer-GXUICIAG.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import { XIcon } from "lucide-react";
1
+ import { DownloadIcon, XIcon } from "lucide-react";
2
2
  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";
@@ -19,7 +19,13 @@ import { usePortalTokenStyle } from "../lib/use-portal-token-style";
19
19
  -------------------------------------------------------------------------- */
20
20
 
21
21
  type LightboxController = {
22
- open: (src: string, caption?: string, source?: HTMLElement | null, label?: string) => void;
22
+ open: (
23
+ src: string,
24
+ caption?: string,
25
+ source?: HTMLElement | null,
26
+ label?: string,
27
+ downloadFilename?: string,
28
+ ) => void;
23
29
  };
24
30
 
25
31
  const LightboxContext = createContext<LightboxController | null>(null);
@@ -63,14 +69,26 @@ function LightboxRoot({ children }: { children: ReactNode }) {
63
69
  src: string;
64
70
  caption?: string;
65
71
  label: string;
72
+ downloadFilename?: string;
66
73
  } | null>(null);
67
74
  const [tokenSource, setTokenSource] = useState<HTMLElement | null>(null);
68
75
  const portalStyle = usePortalTokenStyle(tokenSource);
69
76
 
70
77
  const open = useCallback(
71
- (src: string, caption?: string, source?: HTMLElement | null, label = "Screenshot") => {
78
+ (
79
+ src: string,
80
+ caption?: string,
81
+ source?: HTMLElement | null,
82
+ label = "Screenshot",
83
+ downloadFilename?: string,
84
+ ) => {
72
85
  setTokenSource(source ?? null);
73
- setState(caption ? { src, caption, label } : { src, label });
86
+ setState({
87
+ src,
88
+ label,
89
+ ...(caption ? { caption } : {}),
90
+ ...(downloadFilename ? { downloadFilename } : {}),
91
+ });
74
92
  },
75
93
  [],
76
94
  );
@@ -141,16 +159,32 @@ function LightboxRoot({ children }: { children: ReactNode }) {
141
159
  alt={state.caption ?? state.label}
142
160
  className="min-h-0 max-h-[82vh] w-auto max-w-full rounded-og-md border border-white/10 object-contain shadow-og-lg"
143
161
  />
144
- <Dialog.Close
145
- className={cn(
146
- "absolute -right-3 -top-3 inline-flex size-9 items-center justify-center rounded-full",
147
- "border border-white/15 bg-black/60 text-white/70 backdrop-blur",
148
- "transition-colors hover:border-white/30 hover:text-white",
149
- )}
150
- aria-label="Close"
151
- >
152
- <XIcon className="size-4" />
153
- </Dialog.Close>
162
+ <div className="absolute -right-3 -top-3 flex items-center gap-2">
163
+ {state.downloadFilename ? (
164
+ <a
165
+ href={state.src}
166
+ download={state.downloadFilename}
167
+ className={cn(
168
+ "inline-flex size-9 items-center justify-center rounded-full",
169
+ "border border-white/15 bg-black/60 text-white/70 backdrop-blur",
170
+ "transition-colors hover:border-white/30 hover:text-white",
171
+ )}
172
+ aria-label={`Download ${state.downloadFilename}`}
173
+ >
174
+ <DownloadIcon className="size-4" />
175
+ </a>
176
+ ) : null}
177
+ <Dialog.Close
178
+ className={cn(
179
+ "inline-flex size-9 items-center justify-center rounded-full",
180
+ "border border-white/15 bg-black/60 text-white/70 backdrop-blur",
181
+ "transition-colors hover:border-white/30 hover:text-white",
182
+ )}
183
+ aria-label="Close"
184
+ >
185
+ <XIcon className="size-4" />
186
+ </Dialog.Close>
187
+ </div>
154
188
  </div>
155
189
  {state.caption ? (
156
190
  <figcaption className="max-w-2xl text-center font-og-mono text-og-xs text-white/55">
@@ -509,12 +509,14 @@ export function Thumbnail({
509
509
  alt = "screenshot",
510
510
  expandLabel = "Expand screenshot",
511
511
  lightboxLabel = "Screenshot",
512
+ downloadFilename,
512
513
  }: {
513
514
  src: string;
514
515
  caption?: string | undefined;
515
516
  alt?: string;
516
517
  expandLabel?: string | undefined;
517
518
  lightboxLabel?: string | undefined;
519
+ downloadFilename?: string | undefined;
518
520
  }) {
519
521
  const lightbox = useLightboxOptional();
520
522
  const [failed, setFailed] = useState(false);
@@ -542,7 +544,7 @@ export function Thumbnail({
542
544
  type="button"
543
545
  onClick={(event) => {
544
546
  event.stopPropagation();
545
- lightbox.open(src, caption, event.currentTarget, lightboxLabel);
547
+ lightbox.open(src, caption, event.currentTarget, lightboxLabel, downloadFilename);
546
548
  }}
547
549
  onKeyDown={(event) => {
548
550
  if (event.key === "Enter" || event.key === " ") {
@@ -573,12 +575,14 @@ export function ScreenshotFigure({
573
575
  alt = "screenshot",
574
576
  expandLabel = "Expand screenshot",
575
577
  lightboxLabel = "Screenshot",
578
+ downloadFilename,
576
579
  }: {
577
580
  src: string;
578
581
  caption?: string | undefined;
579
582
  alt?: string;
580
583
  expandLabel?: string | undefined;
581
584
  lightboxLabel?: string | undefined;
585
+ downloadFilename?: string | undefined;
582
586
  }) {
583
587
  const lightbox = useLightboxOptional();
584
588
  const [failed, setFailed] = useState(false);
@@ -602,7 +606,9 @@ export function ScreenshotFigure({
602
606
  ) : lightbox ? (
603
607
  <button
604
608
  type="button"
605
- onClick={(event) => lightbox.open(src, caption, event.currentTarget, lightboxLabel)}
609
+ onClick={(event) =>
610
+ lightbox.open(src, caption, event.currentTarget, lightboxLabel, downloadFilename)
611
+ }
606
612
  className={surface}
607
613
  aria-label={expandLabel}
608
614
  >
@@ -1,10 +1,15 @@
1
- import type { GitFileDiff, RetainedArtifactReference } from "@opengeni/sdk";
1
+ import {
2
+ parseSandboxFileArtifactReceipt,
3
+ type GitFileDiff,
4
+ type RetainedArtifactReference,
5
+ } from "@opengeni/sdk";
2
6
  import {
3
7
  BoxIcon,
4
8
  BrainCircuitIcon,
5
9
  CalendarClockIcon,
6
10
  CameraIcon,
7
11
  CameraOffIcon,
12
+ DownloadIcon,
8
13
  FileDiffIcon,
9
14
  FileSearchIcon,
10
15
  FolderGitIcon,
@@ -30,7 +35,7 @@ import {
30
35
  WrenchIcon,
31
36
  } from "lucide-react";
32
37
  import { useEffect, useRef, useState, type ReactNode } from "react";
33
- import { stringifyPayload, tryParseJson } from "../lib/format";
38
+ import { formatBytes, stringifyPayload, tryParseJson } from "../lib/format";
34
39
  import { useTimelineComputeLabel } from "./compute-label";
35
40
  import {
36
41
  applyPatchOpsFromToolItem,
@@ -874,6 +879,7 @@ function RetainedSessionImageDisclosure({
874
879
  cancelled: boolean;
875
880
  }) {
876
881
  const state = useRetainedImageObjectUrl(artifact, load);
882
+ const downloadFilename = retainedImageFilename(artifact);
877
883
 
878
884
  return (
879
885
  <ActivityDisclosure
@@ -899,6 +905,7 @@ function RetainedSessionImageDisclosure({
899
905
  alt={caption}
900
906
  expandLabel={`Expand ${noun}`}
901
907
  lightboxLabel={lightboxLabel}
908
+ downloadFilename={downloadFilename}
902
909
  />
903
910
  ) : state.kind === "loading" ? (
904
911
  <MediaSkeleton />
@@ -914,6 +921,7 @@ function RetainedSessionImageDisclosure({
914
921
  alt={caption}
915
922
  expandLabel={`Expand ${noun}`}
916
923
  lightboxLabel={lightboxLabel}
924
+ downloadFilename={downloadFilename}
917
925
  />
918
926
  ) : state.kind === "loading" ? (
919
927
  <BodyNote>Loading the retained {noun}…</BodyNote>
@@ -1001,6 +1009,82 @@ function GeneratedVideoRenderer({ item }: ToolRendererProps) {
1001
1009
  </ActivityDisclosure>
1002
1010
  );
1003
1011
  }
1012
+ function SandboxFilePublishRenderer({ item, loadRetainedArtifact }: ToolRendererProps) {
1013
+ const { text: output, isError } = unwrapMcpOutput(item.output);
1014
+ const receipt = parseSandboxFileArtifactReceipt(output);
1015
+ const [downloadState, setDownloadState] = useState<"idle" | "loading" | "error">("idle");
1016
+ if (item.status === "running") {
1017
+ return (
1018
+ <ActivityDisclosure
1019
+ icon={<DownloadIcon className={ICON_SIZE} />}
1020
+ iconTone="running"
1021
+ title="Publishing file"
1022
+ running
1023
+ preview={<RunningPreview>retaining workspace bytes…</RunningPreview>}
1024
+ />
1025
+ );
1026
+ }
1027
+ if (!receipt || isError || item.status === "failed") {
1028
+ return <GenericRenderer item={item} />;
1029
+ }
1030
+
1031
+ const download = async () => {
1032
+ if (!loadRetainedArtifact) {
1033
+ setDownloadState("error");
1034
+ return;
1035
+ }
1036
+ setDownloadState("loading");
1037
+ let objectUrl: string | null = null;
1038
+ try {
1039
+ const source = await loadRetainedArtifact(receipt.artifact, new AbortController().signal);
1040
+ if (!source) throw new Error("artifact unavailable");
1041
+ const url =
1042
+ source instanceof Uint8Array
1043
+ ? (objectUrl = URL.createObjectURL(
1044
+ new Blob([source as unknown as BlobPart], {
1045
+ type: receipt.artifact.contentType,
1046
+ }),
1047
+ ))
1048
+ : source.url;
1049
+ const anchor = document.createElement("a");
1050
+ anchor.href = url;
1051
+ anchor.download = receipt.filename;
1052
+ anchor.rel = "noopener";
1053
+ anchor.click();
1054
+ setDownloadState("idle");
1055
+ } catch {
1056
+ setDownloadState("error");
1057
+ } finally {
1058
+ const urlToRevoke = objectUrl;
1059
+ if (urlToRevoke) setTimeout(() => URL.revokeObjectURL(urlToRevoke), 0);
1060
+ }
1061
+ };
1062
+
1063
+ return (
1064
+ <ActivityDisclosure
1065
+ icon={<DownloadIcon className={ICON_SIZE} />}
1066
+ iconTone="accent"
1067
+ title={`Published ${receipt.filename}`}
1068
+ defaultOpen
1069
+ preview={formatBytes(receipt.artifact.originalBytes)}
1070
+ >
1071
+ <button
1072
+ type="button"
1073
+ onClick={() => void download()}
1074
+ disabled={downloadState === "loading"}
1075
+ className="inline-flex items-center gap-1.5 rounded-og-sm border border-og-border px-2.5 py-1.5 text-og-sm font-medium text-og-fg transition-colors hover:border-og-border-strong hover:bg-og-surface-2 disabled:cursor-wait disabled:opacity-60"
1076
+ >
1077
+ <DownloadIcon className="size-3.5" />
1078
+ {downloadState === "loading"
1079
+ ? "Preparing…"
1080
+ : downloadState === "error"
1081
+ ? "Retry download"
1082
+ : "Download"}
1083
+ </button>
1084
+ </ActivityDisclosure>
1085
+ );
1086
+ }
1087
+
1004
1088
  function GeneratedImageDisclosure({
1005
1089
  receipt,
1006
1090
  load,
@@ -1073,6 +1157,16 @@ function GeneratedImageDisclosure({
1073
1157
  );
1074
1158
  }
1075
1159
 
1160
+ function retainedImageFilename(artifact: RetainedArtifactReference): string {
1161
+ const extension =
1162
+ artifact.contentType === "image/jpeg"
1163
+ ? "jpg"
1164
+ : artifact.contentType === "image/webp"
1165
+ ? "webp"
1166
+ : "png";
1167
+ return `${artifact.kind}-${artifact.artifactId}.${extension}`;
1168
+ }
1169
+
1076
1170
  /* ---- web_search ------------------------------------------------------------ */
1077
1171
 
1078
1172
  type WebSearchResult = { title: string; domain: string; snippet: string };
@@ -2103,7 +2197,8 @@ function goalToolPreview(name: string, args: unknown): string | null {
2103
2197
  leaf !== "goal_set" &&
2104
2198
  leaf !== "goal_update" &&
2105
2199
  leaf !== "goal_complete" &&
2106
- leaf !== "goal_pause"
2200
+ leaf !== "goal_pause" &&
2201
+ leaf !== "goal_wait"
2107
2202
  ) {
2108
2203
  return null;
2109
2204
  }
@@ -2118,9 +2213,11 @@ function goalToolPreview(name: string, args: unknown): string | null {
2118
2213
  ? record.evidence
2119
2214
  : typeof record.rationale === "string"
2120
2215
  ? record.rationale
2121
- : typeof record.progressNote === "string"
2122
- ? record.progressNote
2123
- : null;
2216
+ : typeof record.reason === "string"
2217
+ ? record.reason
2218
+ : typeof record.progressNote === "string"
2219
+ ? record.progressNote
2220
+ : null;
2124
2221
  return text ? truncatePreview(text, 90) : null;
2125
2222
  }
2126
2223
 
@@ -2210,6 +2307,7 @@ const BASE_ENTRIES: ToolRegistryEntry[] = [
2210
2307
  { match: "name", name: "generate_video", render: GeneratedVideoRenderer },
2211
2308
  { match: "name", name: "tool_search", render: ToolSearchRenderer },
2212
2309
  { match: "name", name: "view_image", render: ViewImageRenderer },
2310
+ { match: "name", name: "sandbox_file_publish", render: SandboxFilePublishRenderer },
2213
2311
  { match: "name", name: "environment_set_variable", render: SecretSetRenderer },
2214
2312
  { match: "name", name: "variable_set_set_variable", render: SecretSetRenderer },
2215
2313
  { match: "name", name: "search_documents", render: DocsSearchRenderer },
@@ -547,7 +547,12 @@ function createTurnSummaryContext(
547
547
  if (item.kind === "reasoning") {
548
548
  return !item.streaming;
549
549
  }
550
- if (item.kind === "tool-call" || item.kind === "worker" || item.kind === "sandbox") {
550
+ if (
551
+ item.kind === "tool-call" ||
552
+ item.kind === "worker" ||
553
+ item.kind === "sandbox" ||
554
+ item.kind === "startup-phase"
555
+ ) {
551
556
  return item.status !== "running";
552
557
  }
553
558
  return true;
@@ -1,4 +1,6 @@
1
1
  import type {
2
+ HumanInputQuestion,
3
+ HumanInputResponse,
2
4
  MediaGenerationResult,
3
5
  ResourceRef,
4
6
  SessionStatus,
@@ -27,6 +29,13 @@ export type TimelineAnnotationSourceDescriptor = Omit<
27
29
  export type UserMessageItem = {
28
30
  kind: "user-message";
29
31
  id: string;
32
+ /**
33
+ * Renderer-only identity shared by a locally acknowledged message and the
34
+ * durable event that replaces it. The canonical event id remains `id`; this
35
+ * key only prevents the optimistic-to-durable handoff from remounting and
36
+ * replaying the row entrance animation.
37
+ */
38
+ reconciliationKey?: string | undefined;
30
39
  text: string;
31
40
  annotations?: TimelineAnnotation[] | undefined;
32
41
  annotationSource?: TimelineAnnotationSourceDescriptor | undefined;
@@ -51,6 +60,29 @@ export type UserMessageItem = {
51
60
  | undefined;
52
61
  };
53
62
 
63
+ export type HumanInputAnswerSummary = {
64
+ questionId: string;
65
+ label: string;
66
+ prompt: string;
67
+ values: string[];
68
+ };
69
+
70
+ /**
71
+ * One resolved structured question in the conversation. The live pending form
72
+ * is rendered at the timeline tip by the host; after settlement this item keeps
73
+ * both the agent's question and the human's answer visible as chat history.
74
+ */
75
+ export type HumanInputItem = {
76
+ kind: "human-input";
77
+ id: string;
78
+ turnId: string | null;
79
+ requestId: string;
80
+ questions: HumanInputQuestion[];
81
+ response: HumanInputResponse;
82
+ answers: HumanInputAnswerSummary[];
83
+ occurredAt: string;
84
+ };
85
+
54
86
  export type AgentMessageItem = {
55
87
  kind: "agent-message";
56
88
  id: string;
@@ -159,6 +191,31 @@ export type SandboxItem = {
159
191
  occurredAt: string;
160
192
  };
161
193
 
194
+ export type StartupPhase =
195
+ | "queue"
196
+ | "sandbox"
197
+ | "rig"
198
+ | "repository"
199
+ | "files"
200
+ | "tools"
201
+ | "model_preparation"
202
+ | "provider_first_byte";
203
+
204
+ /** A compact user-visible critical-path span reconstructed from durable events. */
205
+ export type StartupPhaseItem = {
206
+ kind: "startup-phase";
207
+ id: string;
208
+ turnId: string | null;
209
+ phase: StartupPhase;
210
+ status: "running" | "complete" | "failed" | "cancelled";
211
+ startedAt: string;
212
+ completedAt: string | null;
213
+ durationMs: number | null;
214
+ /** Sandbox origin and rig marker outcomes refine the settled label only. */
215
+ outcome: "created" | "restored" | "resumed" | "skipped" | null;
216
+ occurredAt: string;
217
+ };
218
+
162
219
  /**
163
220
  * A first-party workspace-memory write the agent made mid-turn — a `memory.saved`
164
221
  * (it committed a new preference / fact / procedure / decision / history) or a
@@ -265,7 +322,15 @@ export type SessionStatusItem = {
265
322
  export type GoalItem = {
266
323
  kind: "goal";
267
324
  id: string;
268
- action: "set" | "updated" | "completed" | "paused" | "resumed" | "cleared" | "continuation";
325
+ action:
326
+ | "set"
327
+ | "updated"
328
+ | "completed"
329
+ | "paused"
330
+ | "resumed"
331
+ | "cleared"
332
+ | "held"
333
+ | "continuation";
269
334
  text: string | null;
270
335
  occurredAt: string;
271
336
  };
@@ -307,7 +372,12 @@ export type MachineInputMember = {
307
372
  | "agent_message"
308
373
  | "agent_steer_instruction"
309
374
  | "child_terminal_result"
310
- | "media_generation_result";
375
+ | "media_generation_result"
376
+ | "child_requires_action"
377
+ | "child_requires_action_resolved"
378
+ | "child_paused"
379
+ | "child_waiting_capacity"
380
+ | "child_progress";
311
381
  classification: "success" | "failure" | "action_required" | "info";
312
382
  sourceId: string;
313
383
  summary: string;
@@ -375,12 +445,14 @@ export type TurnEndItem = {
375
445
 
376
446
  export type TimelineItem =
377
447
  | UserMessageItem
448
+ | HumanInputItem
378
449
  | AgentMessageItem
379
450
  | ReasoningItem
380
451
  | ToolCallItem
381
452
  | WorkerItem
382
453
  | WorkerCompletionItem
383
454
  | SandboxItem
455
+ | StartupPhaseItem
384
456
  | SessionStatusItem
385
457
  | GoalItem
386
458
  | NoticeItem
@@ -397,6 +469,7 @@ export type ActivityItem =
397
469
  | ToolCallItem
398
470
  | WorkerItem
399
471
  | SandboxItem
472
+ | StartupPhaseItem
400
473
  | MemoryItem
401
474
  | FleetDecisionItem;
402
475
 
@@ -23,6 +23,11 @@ import type {
23
23
  MachinesResponse,
24
24
  MachineState,
25
25
  MachineView,
26
+ MachineRuntime,
27
+ MachineRuntimeCapabilities,
28
+ MachineOperationPolicy,
29
+ MachineUpdateState,
30
+ MachineUpdateStatus,
26
31
  MetricSample,
27
32
  } from "@opengeni/sdk";
28
33
 
@@ -32,6 +37,11 @@ export type {
32
37
  MachinesResponse,
33
38
  MachineState,
34
39
  MachineView,
40
+ MachineRuntime,
41
+ MachineRuntimeCapabilities,
42
+ MachineOperationPolicy,
43
+ MachineUpdateState,
44
+ MachineUpdateStatus,
35
45
  MetricSample,
36
46
  };
37
47