@opengeni/react 0.46.1 → 0.48.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 (141) hide show
  1. package/README.md +68 -12
  2. package/dist/{chunk-U3CSCMWA.js → chunk-FK6VG4LL.js} +9 -13
  3. package/dist/chunk-FK6VG4LL.js.map +1 -0
  4. package/dist/{chunk-HFO4ERGQ.js → chunk-FWXGSNXT.js} +2 -2
  5. package/dist/{chunk-SRFUT2ZU.js → chunk-I4MPFDRP.js} +119 -63
  6. package/dist/chunk-I4MPFDRP.js.map +1 -0
  7. package/dist/{chunk-EB67J347.js → chunk-KZ73RL76.js} +111 -31
  8. package/dist/chunk-KZ73RL76.js.map +1 -0
  9. package/dist/{chunk-LWR4MXSS.js → chunk-LHLYWG5R.js} +10 -1
  10. package/dist/chunk-LHLYWG5R.js.map +1 -0
  11. package/dist/{chunk-3PB7MIT6.js → chunk-NJ7M2B6Z.js} +207 -67
  12. package/dist/chunk-NJ7M2B6Z.js.map +1 -0
  13. package/dist/{chunk-VCBFUSUZ.js → chunk-O4VXOBGF.js} +3 -3
  14. package/dist/{chunk-VCBFUSUZ.js.map → chunk-O4VXOBGF.js.map} +1 -1
  15. package/dist/{chunk-6EDV6YFE.js → chunk-OL6QVXGF.js} +121 -29
  16. package/dist/chunk-OL6QVXGF.js.map +1 -0
  17. package/dist/chunk-VZTQ73XT.js +86 -0
  18. package/dist/chunk-VZTQ73XT.js.map +1 -0
  19. package/dist/{chunk-FGZUCXZF.js → chunk-WYA65Y3F.js} +16 -16
  20. package/dist/chunk-WYA65Y3F.js.map +1 -0
  21. package/dist/{chunk-LGVMUIRV.js → chunk-XCNTXWBB.js} +264 -115
  22. package/dist/chunk-XCNTXWBB.js.map +1 -0
  23. package/dist/client.d.ts +1 -1
  24. package/dist/components/chat-composer.d.ts +7 -2
  25. package/dist/components/composer-transcription-control.d.ts +2 -0
  26. package/dist/components/composer.d.ts +14 -0
  27. package/dist/components/machines/machine-detail.d.ts +3 -1
  28. package/dist/components/machines-dashboard.d.ts +3 -3
  29. package/dist/components/message-timeline.d.ts +12 -2
  30. package/dist/components/sandbox-files.d.ts +2 -2
  31. package/dist/components/sandbox-terminal.d.ts +29 -0
  32. package/dist/components/sandbox-workspace.d.ts +5 -1
  33. package/dist/components/workspace-dock.d.ts +3 -1
  34. package/dist/composer.d.ts +2 -2
  35. package/dist/composer.js +6 -6
  36. package/dist/hooks/internal.d.ts +6 -0
  37. package/dist/hooks/use-codex-accounts.d.ts +1 -1
  38. package/dist/hooks/use-environments.d.ts +10 -4
  39. package/dist/hooks/use-machines.d.ts +7 -0
  40. package/dist/hooks/use-sandbox-files.d.ts +19 -0
  41. package/dist/hooks/use-sandbox-git.d.ts +7 -0
  42. package/dist/hooks/use-transcription.d.ts +2 -2
  43. package/dist/hooks/use-voice-input.d.ts +5 -3
  44. package/dist/index.d.ts +6 -5
  45. package/dist/index.js +904 -538
  46. package/dist/index.js.map +1 -1
  47. package/dist/lib/composer-responsive-context.d.ts +9 -0
  48. package/dist/lib/use-portal-token-style.d.ts +14 -3
  49. package/dist/machines.js +2 -2
  50. package/dist/{queue-surface-implementation-J4XJFKRW.js → queue-surface-implementation-U5JFG7HT.js} +19 -18
  51. package/dist/queue-surface-implementation-U5JFG7HT.js.map +1 -0
  52. package/dist/realtime/realtime-control.d.ts +9 -0
  53. package/dist/realtime.js +27 -30
  54. package/dist/realtime.js.map +1 -1
  55. package/dist/session-ui.js +5 -5
  56. package/dist/session.js +4 -4
  57. package/dist/timeline/activity-rail.d.ts +3 -2
  58. package/dist/timeline/index.d.ts +2 -2
  59. package/dist/timeline/parsers.d.ts +3 -3
  60. package/dist/timeline/registry.d.ts +3 -0
  61. package/dist/timeline/screenshot-lightbox.d.ts +1 -1
  62. package/dist/timeline/types.d.ts +4 -0
  63. package/dist/voice-recording-store.d.ts +8 -2
  64. package/package.json +20 -4
  65. package/src/client.ts +3 -0
  66. package/src/components/chat-composer.tsx +12 -2
  67. package/src/components/code-editor.tsx +1 -1
  68. package/src/components/command-palette.tsx +1 -1
  69. package/src/components/composer-transcription-control.tsx +41 -16
  70. package/src/components/composer.tsx +49 -23
  71. package/src/components/copy-button.tsx +1 -1
  72. package/src/components/desktop-viewer.tsx +2 -2
  73. package/src/components/file-browser.tsx +39 -17
  74. package/src/components/human-input-form.tsx +2 -2
  75. package/src/components/machine-card.tsx +1 -1
  76. package/src/components/machines/machine-detail.tsx +39 -15
  77. package/src/components/machines-dashboard.tsx +7 -6
  78. package/src/components/message-timeline.tsx +39 -6
  79. package/src/components/model-picker.tsx +2 -2
  80. package/src/components/model-policy-picker.tsx +16 -15
  81. package/src/components/queue-surface-implementation.tsx +20 -16
  82. package/src/components/queue-surface-state.tsx +2 -2
  83. package/src/components/sandbox-files.tsx +140 -60
  84. package/src/components/sandbox-terminal.tsx +24 -5
  85. package/src/components/sandbox-workspace.tsx +180 -142
  86. package/src/components/session-chrome.tsx +14 -14
  87. package/src/components/tooltip.tsx +13 -16
  88. package/src/components/user-message-body.tsx +1 -1
  89. package/src/components/workbench-changes.tsx +4 -4
  90. package/src/components/workspace-dock.tsx +13 -5
  91. package/src/composer.ts +3 -0
  92. package/src/hooks/internal.ts +132 -38
  93. package/src/hooks/use-codex-accounts.ts +4 -4
  94. package/src/hooks/use-environments.ts +24 -5
  95. package/src/hooks/use-file-attachments.ts +70 -32
  96. package/src/hooks/use-goal.ts +17 -5
  97. package/src/hooks/use-machines.ts +47 -1
  98. package/src/hooks/use-sandbox-files.ts +310 -59
  99. package/src/hooks/use-sandbox-git.ts +148 -41
  100. package/src/hooks/use-session-capabilities.ts +35 -24
  101. package/src/hooks/use-session-events.ts +18 -4
  102. package/src/hooks/use-transcription.ts +4 -14
  103. package/src/hooks/use-turn-queue.ts +17 -5
  104. package/src/hooks/use-voice-input.ts +163 -19
  105. package/src/hooks/use-windowed-sections.ts +9 -7
  106. package/src/index.ts +11 -6
  107. package/src/lib/composer-responsive-context.ts +15 -0
  108. package/src/lib/use-portal-token-style.ts +60 -15
  109. package/src/provider.tsx +52 -7
  110. package/src/realtime/dropdown-menu.tsx +15 -19
  111. package/src/realtime/realtime-control.tsx +16 -5
  112. package/src/timeline/activity-rail.tsx +14 -5
  113. package/src/timeline/index.ts +1 -1
  114. package/src/timeline/parsers.ts +33 -20
  115. package/src/timeline/projection.ts +23 -0
  116. package/src/timeline/registry.ts +7 -0
  117. package/src/timeline/screenshot-lightbox.tsx +15 -4
  118. package/src/timeline/shared.tsx +5 -5
  119. package/src/timeline/tool-renderers.tsx +166 -22
  120. package/src/timeline/turn-summary.tsx +2 -2
  121. package/src/timeline/types.ts +4 -0
  122. package/src/voice-recording-store.ts +15 -0
  123. package/styles/compiled.css +5065 -0
  124. package/styles/compiled.d.ts +2 -0
  125. package/styles/effective-tokens.css +27 -0
  126. package/styles/index.css +3 -0
  127. package/styles/responsive.css +196 -0
  128. package/styles/responsive.d.ts +2 -0
  129. package/styles/tokens.css +50 -17
  130. package/dist/chunk-3PB7MIT6.js.map +0 -1
  131. package/dist/chunk-6EDV6YFE.js.map +0 -1
  132. package/dist/chunk-EB67J347.js.map +0 -1
  133. package/dist/chunk-FGZUCXZF.js.map +0 -1
  134. package/dist/chunk-JB5725BI.js +0 -48
  135. package/dist/chunk-JB5725BI.js.map +0 -1
  136. package/dist/chunk-LGVMUIRV.js.map +0 -1
  137. package/dist/chunk-LWR4MXSS.js.map +0 -1
  138. package/dist/chunk-SRFUT2ZU.js.map +0 -1
  139. package/dist/chunk-U3CSCMWA.js.map +0 -1
  140. package/dist/queue-surface-implementation-J4XJFKRW.js.map +0 -1
  141. /package/dist/{chunk-HFO4ERGQ.js.map → chunk-FWXGSNXT.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import type { GitFileDiff } from "@opengeni/sdk";
1
+ import type { GitFileDiff, RetainedArtifactReference } from "@opengeni/sdk";
2
2
  import {
3
3
  BoxIcon,
4
4
  BrainCircuitIcon,
@@ -28,7 +28,7 @@ import {
28
28
  TerminalIcon,
29
29
  WrenchIcon,
30
30
  } from "lucide-react";
31
- import type { ReactNode } from "react";
31
+ import { useEffect, useState, type ReactNode } from "react";
32
32
  import { stringifyPayload, tryParseJson } from "../lib/format";
33
33
  import { useTimelineComputeLabel } from "./compute-label";
34
34
  import {
@@ -40,7 +40,7 @@ import {
40
40
  mediaPreviewFact,
41
41
  parseExecBannerSessionId,
42
42
  parseToolArgs,
43
- redactSecrets,
43
+ retainedScreenshotMetadata,
44
44
  sandboxCommandExitCode,
45
45
  stripExecBanner,
46
46
  tailPeek,
@@ -559,7 +559,7 @@ function asComputerArgs(args: unknown): Partial<ComputerAction> {
559
559
  };
560
560
  }
561
561
 
562
- function ComputerCallRenderer({ item }: ToolRendererProps) {
562
+ function ComputerCallRenderer({ item, loadRetainedScreenshot }: ToolRendererProps) {
563
563
  const raw = (item.raw ?? {}) as {
564
564
  action?: ComputerAction;
565
565
  actions?: ComputerAction[];
@@ -582,6 +582,7 @@ function ComputerCallRenderer({ item }: ToolRendererProps) {
582
582
  const rejected = raw.providerData?.approvalStatus === "rejected";
583
583
  const readOnly = typeof out === "string" && out.includes("read-only");
584
584
  const shotUrl = screenshotDataUrl(out);
585
+ const retained = retainedScreenshotMetadata(out);
585
586
  const omittedMedia = mediaPreviewFact(out);
586
587
  const empty = out === "" || out == null;
587
588
  const batched = actions.length > 1 ? actions.map((a) => computerVerb(a)).join(" · ") : null;
@@ -640,6 +641,41 @@ function ComputerCallRenderer({ item }: ToolRendererProps) {
640
641
  const isFailed = item.status === "failed";
641
642
  const isCancelled = item.status === "cancelled";
642
643
 
644
+ if (retained) {
645
+ if (!retained.available) {
646
+ const state =
647
+ retained.reason === "expired" || retained.reason === "deleted"
648
+ ? retained.reason
649
+ : "unavailable";
650
+ return (
651
+ <ActivityDisclosure
652
+ icon={<CameraOffIcon className={ICON_SIZE} />}
653
+ iconTone={isFailed ? "failed" : "muted"}
654
+ title={`${verb}${countSuffix} · ${state}`}
655
+ failed={isFailed}
656
+ cancelled={isCancelled}
657
+ preview={`screenshot ${state}`}
658
+ media={<MediaEmpty />}
659
+ >
660
+ <BodyNote tone={isFailed ? "error" : undefined}>
661
+ Screenshot {state}: {retained.reason.replaceAll("_", " ")}.
662
+ </BodyNote>
663
+ </ActivityDisclosure>
664
+ );
665
+ }
666
+ return (
667
+ <RetainedScreenshotDisclosure
668
+ artifact={retained}
669
+ load={loadRetainedScreenshot}
670
+ verb={verb}
671
+ countSuffix={countSuffix}
672
+ batched={batched}
673
+ failed={isFailed}
674
+ cancelled={isCancelled}
675
+ />
676
+ );
677
+ }
678
+
643
679
  if (shotUrl) {
644
680
  const caption = `${verb}${actions.length > 1 ? ` (+${actions.length - 1} more)` : ""}`;
645
681
  return (
@@ -720,6 +756,112 @@ function ComputerCallRenderer({ item }: ToolRendererProps) {
720
756
  );
721
757
  }
722
758
 
759
+ function RetainedScreenshotDisclosure({
760
+ artifact,
761
+ load,
762
+ verb,
763
+ countSuffix,
764
+ batched,
765
+ failed,
766
+ cancelled,
767
+ }: {
768
+ artifact: RetainedArtifactReference;
769
+ load: ToolRendererProps["loadRetainedScreenshot"];
770
+ verb: string;
771
+ countSuffix: string;
772
+ batched: string | null;
773
+ failed: boolean;
774
+ cancelled: boolean;
775
+ }) {
776
+ const [state, setState] = useState<
777
+ | { kind: "loading" }
778
+ | { kind: "ready"; url: string }
779
+ | { kind: "unavailable"; label: string }
780
+ | { kind: "error"; message: string }
781
+ >({ kind: "loading" });
782
+
783
+ useEffect(() => {
784
+ if (!load) {
785
+ setState({ kind: "unavailable", label: "retrieval is not configured" });
786
+ return;
787
+ }
788
+ const controller = new AbortController();
789
+ let objectUrl: string | null = null;
790
+ setState({ kind: "loading" });
791
+ void load(artifact, controller.signal)
792
+ .then((bytes) => {
793
+ if (controller.signal.aborted) return;
794
+ if (!bytes) {
795
+ setState({ kind: "unavailable", label: "bytes are unavailable" });
796
+ return;
797
+ }
798
+ objectUrl = URL.createObjectURL(new Blob([Uint8Array.from(bytes)], { type: "image/png" }));
799
+ setState({ kind: "ready", url: objectUrl });
800
+ })
801
+ .catch((error: unknown) => {
802
+ if (controller.signal.aborted) return;
803
+ const status =
804
+ error && typeof error === "object" && "status" in error
805
+ ? Number((error as { status?: unknown }).status)
806
+ : null;
807
+ setState(
808
+ status === 404
809
+ ? { kind: "unavailable", label: "deleted" }
810
+ : status === 410
811
+ ? { kind: "unavailable", label: "expired or unavailable" }
812
+ : {
813
+ kind: "error",
814
+ message: "retrieval failed",
815
+ },
816
+ );
817
+ });
818
+ return () => {
819
+ controller.abort();
820
+ if (objectUrl) URL.revokeObjectURL(objectUrl);
821
+ };
822
+ }, [artifact, load]);
823
+
824
+ const caption = `${verb}${countSuffix}`;
825
+ return (
826
+ <ActivityDisclosure
827
+ icon={<CameraIcon className={ICON_SIZE} />}
828
+ iconTone={failed ? "failed" : state.kind === "ready" ? "accent" : "muted"}
829
+ title={caption}
830
+ failed={failed}
831
+ cancelled={cancelled}
832
+ preview={
833
+ state.kind === "loading"
834
+ ? "loading retained screenshot…"
835
+ : state.kind === "error"
836
+ ? "screenshot retrieval failed"
837
+ : state.kind === "unavailable"
838
+ ? `screenshot ${state.label}`
839
+ : undefined
840
+ }
841
+ media={
842
+ state.kind === "ready" ? (
843
+ <Thumbnail src={state.url} caption={caption} />
844
+ ) : state.kind === "loading" ? (
845
+ <MediaSkeleton />
846
+ ) : (
847
+ <MediaEmpty />
848
+ )
849
+ }
850
+ >
851
+ {state.kind === "ready" ? (
852
+ <ScreenshotFigure src={state.url} caption={caption} />
853
+ ) : state.kind === "loading" ? (
854
+ <BodyNote>Loading the retained screenshot…</BodyNote>
855
+ ) : state.kind === "unavailable" ? (
856
+ <BodyNote>Screenshot {state.label}.</BodyNote>
857
+ ) : (
858
+ <BodyNote tone="error">Screenshot retrieval failed: {state.message}</BodyNote>
859
+ )}
860
+ {batched ? <BodyNote>batched: {batched}</BodyNote> : null}
861
+ </ActivityDisclosure>
862
+ );
863
+ }
864
+
723
865
  /* ---- web_search ------------------------------------------------------------ */
724
866
 
725
867
  type WebSearchResult = { title: string; domain: string; snippet: string };
@@ -995,7 +1137,7 @@ function SecretSetRenderer({ item }: ToolRendererProps) {
995
1137
  running
996
1138
  preview={<RunningPreview>setting…</RunningPreview>}
997
1139
  >
998
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1140
+ <PayloadBlock label="Arguments" value={args} />
999
1141
  </ActivityDisclosure>
1000
1142
  );
1001
1143
  }
@@ -1010,7 +1152,7 @@ function SecretSetRenderer({ item }: ToolRendererProps) {
1010
1152
  failed
1011
1153
  preview={errorText ?? "variable write failed"}
1012
1154
  >
1013
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1155
+ <PayloadBlock label="Arguments" value={args} />
1014
1156
  {errorText ? (
1015
1157
  <PayloadBlock label="Error" value={errorText} failed />
1016
1158
  ) : (
@@ -1026,10 +1168,12 @@ function SecretSetRenderer({ item }: ToolRendererProps) {
1026
1168
  iconTone="muted"
1027
1169
  title={`Set ${name}`}
1028
1170
  cancelled={item.status === "cancelled"}
1029
- preview="value write-only · never returned"
1171
+ preview="exact value preserved"
1030
1172
  >
1031
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1032
- <BodyNote>the value is a secret — redacted in every view; the API never returns it.</BodyNote>
1173
+ <PayloadBlock label="Arguments" value={args} />
1174
+ <BodyNote>
1175
+ The configured value is preserved exactly and available through authorized secret reads.
1176
+ </BodyNote>
1033
1177
  </ActivityDisclosure>
1034
1178
  );
1035
1179
  }
@@ -1175,7 +1319,7 @@ function ToolSearchRenderer({ item }: ToolRendererProps) {
1175
1319
  }
1176
1320
  >
1177
1321
  {query ? <BodyNote>capability query: {query}</BodyNote> : null}
1178
- <PayloadBlock label="Arguments" value={redactSecrets(parseToolArgs(item.arguments))} />
1322
+ <PayloadBlock label="Arguments" value={parseToolArgs(item.arguments)} />
1179
1323
  </ActivityDisclosure>
1180
1324
  );
1181
1325
  }
@@ -1191,7 +1335,7 @@ function ToolSearchRenderer({ item }: ToolRendererProps) {
1191
1335
  preview={truncatePreview(outText, 80) || queryPreview || "Lookup failed"}
1192
1336
  >
1193
1337
  {query ? <BodyNote>capability query: {query}</BodyNote> : null}
1194
- <PayloadBlock label="Arguments" value={redactSecrets(parseToolArgs(item.arguments))} />
1338
+ <PayloadBlock label="Arguments" value={parseToolArgs(item.arguments)} />
1195
1339
  <PayloadBlock label="Error" value={outText} failed />
1196
1340
  </ActivityDisclosure>
1197
1341
  );
@@ -1226,7 +1370,7 @@ function ToolSearchRenderer({ item }: ToolRendererProps) {
1226
1370
  ) : tools && tools.length === 0 ? (
1227
1371
  <BodyNote>no deferred tools matched this capability query.</BodyNote>
1228
1372
  ) : null}
1229
- <PayloadBlock label="Arguments" value={redactSecrets(parseToolArgs(item.arguments))} />
1373
+ <PayloadBlock label="Arguments" value={parseToolArgs(item.arguments)} />
1230
1374
  {tools == null && outText ? <PayloadBlock label="Result" value={outText} /> : null}
1231
1375
  </ActivityDisclosure>
1232
1376
  );
@@ -1249,7 +1393,7 @@ function DocsSearchRenderer({ item }: ToolRendererProps) {
1249
1393
  running
1250
1394
  preview={<RunningPreview>Searching…</RunningPreview>}
1251
1395
  >
1252
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1396
+ <PayloadBlock label="Arguments" value={args} />
1253
1397
  </ActivityDisclosure>
1254
1398
  );
1255
1399
  }
@@ -1264,7 +1408,7 @@ function DocsSearchRenderer({ item }: ToolRendererProps) {
1264
1408
  failed
1265
1409
  preview={truncatePreview(outText, 80) || "Search failed"}
1266
1410
  >
1267
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1411
+ <PayloadBlock label="Arguments" value={args} />
1268
1412
  <PayloadBlock label="Error" value={outText} failed />
1269
1413
  </ActivityDisclosure>
1270
1414
  );
@@ -1300,7 +1444,7 @@ function DocsSearchRenderer({ item }: ToolRendererProps) {
1300
1444
  ))}
1301
1445
  </ul>
1302
1446
  ) : null}
1303
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1447
+ <PayloadBlock label="Arguments" value={args} />
1304
1448
  <PayloadBlock label="Result" value={outText} />
1305
1449
  </ActivityDisclosure>
1306
1450
  );
@@ -1330,7 +1474,7 @@ function SetSessionTitleRenderer({ item }: ToolRendererProps) {
1330
1474
  )
1331
1475
  }
1332
1476
  >
1333
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1477
+ <PayloadBlock label="Arguments" value={args} />
1334
1478
  </ActivityDisclosure>
1335
1479
  );
1336
1480
  }
@@ -1345,7 +1489,7 @@ function SetSessionTitleRenderer({ item }: ToolRendererProps) {
1345
1489
  failed
1346
1490
  preview={truncatePreview(outText, 80) || "Rename failed"}
1347
1491
  >
1348
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1492
+ <PayloadBlock label="Arguments" value={args} />
1349
1493
  <PayloadBlock label="Error" value={outText} failed />
1350
1494
  </ActivityDisclosure>
1351
1495
  );
@@ -1371,7 +1515,7 @@ function SetSessionTitleRenderer({ item }: ToolRendererProps) {
1371
1515
  cancelled={item.status === "cancelled"}
1372
1516
  preview={item.status === "cancelled" ? undefined : settledTitle || undefined}
1373
1517
  >
1374
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1518
+ <PayloadBlock label="Arguments" value={args} />
1375
1519
  {outText ? <PayloadBlock label="Result" value={outText} /> : null}
1376
1520
  </ActivityDisclosure>
1377
1521
  );
@@ -1431,7 +1575,7 @@ function MemoryProposeRenderer({ item }: ToolRendererProps) {
1431
1575
  running
1432
1576
  preview={<RunningPreview>Proposing…</RunningPreview>}
1433
1577
  >
1434
- <PayloadBlock label="Arguments" value={redactSecrets(args)} />
1578
+ <PayloadBlock label="Arguments" value={args} />
1435
1579
  </ActivityDisclosure>
1436
1580
  );
1437
1581
  }
@@ -1493,7 +1637,7 @@ function askToolPreview(args: unknown): string | null {
1493
1637
  }
1494
1638
 
1495
1639
  function AskRenderer({ item }: ToolRendererProps) {
1496
- const args = redactSecrets(parseToolArgs(item.arguments));
1640
+ const args = parseToolArgs(item.arguments);
1497
1641
  const preview = askToolPreview(args);
1498
1642
  const icon = <MessageCircleQuestionIcon className={ICON_SIZE} />;
1499
1643
  const title = "Ask";
@@ -1583,7 +1727,7 @@ function runOnOpPreview(args: Record<string, unknown>): string | null {
1583
1727
 
1584
1728
  function RunOnRenderer({ item }: ToolRendererProps) {
1585
1729
  const parsedArgs = parseToolArgs(item.arguments);
1586
- const args = redactSecrets(parsedArgs);
1730
+ const args = parsedArgs;
1587
1731
  const targetName = runOnTargetName(item.output);
1588
1732
  const title = targetName ? `Run on ${targetName}` : "Run on";
1589
1733
  const opPreview = runOnOpPreview(parsedArgs);
@@ -1648,7 +1792,7 @@ function RunOnRenderer({ item }: ToolRendererProps) {
1648
1792
  */
1649
1793
  function GenericRenderer({ item }: ToolRendererProps) {
1650
1794
  const running = item.status === "running";
1651
- const args = redactSecrets(parseToolArgs(item.arguments));
1795
+ const args = parseToolArgs(item.arguments);
1652
1796
  const display = toolDisplayName(item.name);
1653
1797
  const icon = <GenericToolIcon name={item.name} />;
1654
1798
  // Goal tools: surface the objective text on the collapsed row so the in-cluster
@@ -437,8 +437,8 @@ export function TurnSummary({
437
437
  className={cn(
438
438
  "size-3.5 shrink-0 text-og-fg-subtle transition-transform ease-og-in-out group-data-[state=open]:rotate-90",
439
439
  settlePhase
440
- ? "duration-[var(--og-duration-disclose-settle)]"
441
- : "duration-[var(--og-duration-disclose)]",
440
+ ? "duration-[var(--_og-duration-disclose-settle)]"
441
+ : "duration-[var(--_og-duration-disclose)]",
442
442
  )}
443
443
  />
444
444
  {/* Completion is the quiet default and needs no repeated glyph. Failed,
@@ -288,6 +288,10 @@ export type AuthNeededItem = {
288
288
  kind: "auth-needed";
289
289
  id: string;
290
290
  turnId: string | null;
291
+ /** The runtime surface that requested recovery, when the event is an MCP auth signal. */
292
+ serverId: string | null;
293
+ /** Durable event family that produced this notice. */
294
+ source?: "tool" | "credential" | undefined;
291
295
  /** The connection's registrable domain, e.g. "linear.app". */
292
296
  providerDomain: string;
293
297
  /** The lapsed connection to reconnect, when the row survived. */
@@ -9,6 +9,8 @@ export type VoiceRecordingUploadState = "pending" | "syncing" | "retrying" | "co
9
9
  export type VoiceRecordingTranscriptionState = "pending" | "transcribing" | "retrying" | "complete";
10
10
  export type VoiceRecordingFinalizationState = "pending" | "transcript-ready" | "handed-off";
11
11
  export type VoiceRecordingChunkUploadState = "pending" | "syncing" | "complete";
12
+ export type VoiceRecordingRecoveryMode = "automatic" | "manual";
13
+ export type VoiceRecordingHandoffMode = "append" | "explicit";
12
14
 
13
15
  export type VoiceRecordingManifest = {
14
16
  version: 1;
@@ -22,6 +24,10 @@ export type VoiceRecordingManifest = {
22
24
  uploadState: VoiceRecordingUploadState;
23
25
  transcriptionState: VoiceRecordingTranscriptionState;
24
26
  finalizationState: VoiceRecordingFinalizationState;
27
+ /** Whether safe server reconciliation should continue without another user action. */
28
+ recoveryMode: VoiceRecordingRecoveryMode;
29
+ /** Delayed/recovered results require explicit insertion instead of mutating an uncertain draft. */
30
+ handoffMode: VoiceRecordingHandoffMode;
25
31
  /** Tab/process lease. A different owner may take over only after this heartbeat is stale. */
26
32
  ownerId: string | null;
27
33
  ownerHeartbeatAt: string | null;
@@ -91,6 +97,8 @@ export interface VoiceRecordingStore {
91
97
  | "ownerId"
92
98
  | "ownerHeartbeatAt"
93
99
  | "transcriptText"
100
+ | "recoveryMode"
101
+ | "handoffMode"
94
102
  >
95
103
  >,
96
104
  updatedAt: string,
@@ -155,6 +163,8 @@ export function createVoiceRecordingManifest(input: {
155
163
  uploadState: "pending",
156
164
  transcriptionState: "pending",
157
165
  finalizationState: "pending",
166
+ recoveryMode: "automatic",
167
+ handoffMode: "append",
158
168
  ownerId: input.ownerId ?? null,
159
169
  ownerHeartbeatAt: input.ownerId ? input.createdAt : null,
160
170
  transcriptText: null,
@@ -306,6 +316,7 @@ export class IndexedDbVoiceRecordingStore implements VoiceRecordingStore {
306
316
  const updated: VoiceRecordingManifest = {
307
317
  ...manifest,
308
318
  captureState: manifest.captureState === "capturing" ? "stopped" : manifest.captureState,
319
+ handoffMode: "explicit",
309
320
  ownerId,
310
321
  ownerHeartbeatAt: claimedAt,
311
322
  updatedAt: claimedAt,
@@ -370,6 +381,8 @@ export class IndexedDbVoiceRecordingStore implements VoiceRecordingStore {
370
381
  | "ownerId"
371
382
  | "ownerHeartbeatAt"
372
383
  | "transcriptText"
384
+ | "recoveryMode"
385
+ | "handoffMode"
373
386
  >
374
387
  >,
375
388
  updatedAt: string,
@@ -455,6 +468,8 @@ function normalizeManifest(manifest: VoiceRecordingManifest): VoiceRecordingMani
455
468
  ownerId: manifest.ownerId ?? null,
456
469
  ownerHeartbeatAt: manifest.ownerHeartbeatAt ?? null,
457
470
  transcriptText: manifest.transcriptText ?? null,
471
+ recoveryMode: manifest.recoveryMode ?? "manual",
472
+ handoffMode: manifest.handoffMode ?? "explicit",
458
473
  };
459
474
  }
460
475