@opengeni/react 7.1.0 → 7.1.2-canary.36199476632001

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 (78) hide show
  1. package/dist/artifacts-document.js +2 -2
  2. package/dist/artifacts-presentation.js +2 -2
  3. package/dist/artifacts-spreadsheet.js +2 -2
  4. package/dist/artifacts.js +4 -4
  5. package/dist/{browser-viewer-MN7MOYQT.js → browser-viewer-K2H3SLIW.js} +2 -2
  6. package/dist/{chunk-KCGXPP5V.js → chunk-6P7T4RPE.js} +7 -3
  7. package/dist/chunk-6P7T4RPE.js.map +1 -0
  8. package/dist/{chunk-SHRCATV6.js → chunk-7J4DUR3E.js} +12 -5
  9. package/dist/chunk-7J4DUR3E.js.map +1 -0
  10. package/dist/{chunk-UQS7BGNQ.js → chunk-ETA37UZ7.js} +82 -11
  11. package/dist/chunk-ETA37UZ7.js.map +1 -0
  12. package/dist/{chunk-VR4Z73EU.js → chunk-G2SCXNXW.js} +9 -2
  13. package/dist/chunk-G2SCXNXW.js.map +1 -0
  14. package/dist/{chunk-5UONOQ3Y.js → chunk-K3MQZO7R.js} +150 -67
  15. package/dist/chunk-K3MQZO7R.js.map +1 -0
  16. package/dist/{chunk-OWHPKAOV.js → chunk-L6MYP3QU.js} +4 -2
  17. package/dist/{chunk-OWHPKAOV.js.map → chunk-L6MYP3QU.js.map} +1 -1
  18. package/dist/{chunk-ZC2DK5SC.js → chunk-RSFCYKA7.js} +88 -7
  19. package/dist/chunk-RSFCYKA7.js.map +1 -0
  20. package/dist/{chunk-VI7HELBI.js → chunk-SJ5HE4ZA.js} +21 -2
  21. package/dist/chunk-SJ5HE4ZA.js.map +1 -0
  22. package/dist/{chunk-4ACTWOOW.js → chunk-VDSZ3AVO.js} +41 -18
  23. package/dist/chunk-VDSZ3AVO.js.map +1 -0
  24. package/dist/{chunk-XMXRI5JK.js → chunk-ZZ4744OZ.js} +128 -71
  25. package/dist/chunk-ZZ4744OZ.js.map +1 -0
  26. package/dist/components/artifacts/artifact-surface.d.ts +3 -1
  27. package/dist/components/artifacts/document-editor.d.ts +4 -2
  28. package/dist/components/artifacts/editable-document.d.ts +1 -1
  29. package/dist/components/artifacts/editable-presentation.d.ts +1 -1
  30. package/dist/components/artifacts/editable-spreadsheet.d.ts +2 -1
  31. package/dist/components/artifacts/presentation-editor.d.ts +4 -2
  32. package/dist/components/browser-viewer.d.ts +4 -1
  33. package/dist/components/markdown.d.ts +2 -0
  34. package/dist/components/session-capability-frame.d.ts +5 -1
  35. package/dist/composer.js +1 -1
  36. package/dist/connect.js +2 -2
  37. package/dist/hooks/use-browser-session.d.ts +3 -0
  38. package/dist/index.js +7 -6
  39. package/dist/index.js.map +1 -1
  40. package/dist/interaction.js +1 -1
  41. package/dist/session-ui.js +4 -4
  42. package/dist/session.js +1 -1
  43. package/dist/timeline/types.d.ts +2 -0
  44. package/package.json +5 -5
  45. package/src/components/artifacts/artifact-surface.tsx +39 -19
  46. package/src/components/artifacts/document-editor.tsx +77 -9
  47. package/src/components/artifacts/editable-document.tsx +3 -0
  48. package/src/components/artifacts/editable-presentation.tsx +3 -0
  49. package/src/components/artifacts/editable-spreadsheet.tsx +3 -0
  50. package/src/components/artifacts/presentation-editor.tsx +6 -0
  51. package/src/components/browser-viewer.tsx +11 -5
  52. package/src/components/composer-transcription-control.tsx +4 -2
  53. package/src/components/composer.tsx +45 -20
  54. package/src/components/markdown.tsx +9 -2
  55. package/src/components/sandbox-workspace.tsx +1 -0
  56. package/src/components/session-capability-frame.tsx +11 -3
  57. package/src/components/session-mcp-capability-card.tsx +174 -70
  58. package/src/hooks/use-browser-frame-stream.ts +3 -1
  59. package/src/hooks/use-browser-session.ts +107 -3
  60. package/src/hooks/use-voice-input.ts +12 -1
  61. package/src/timeline/compaction-copy.ts +2 -0
  62. package/src/timeline/parsers.ts +2 -2
  63. package/src/timeline/projection.ts +31 -5
  64. package/src/timeline/tool-renderers.tsx +105 -16
  65. package/src/timeline/turn-summary.tsx +10 -2
  66. package/src/timeline/types.ts +2 -0
  67. package/styles/compiled.css +6 -0
  68. package/styles/session-capability.css +2 -0
  69. package/dist/chunk-4ACTWOOW.js.map +0 -1
  70. package/dist/chunk-5UONOQ3Y.js.map +0 -1
  71. package/dist/chunk-KCGXPP5V.js.map +0 -1
  72. package/dist/chunk-SHRCATV6.js.map +0 -1
  73. package/dist/chunk-UQS7BGNQ.js.map +0 -1
  74. package/dist/chunk-VI7HELBI.js.map +0 -1
  75. package/dist/chunk-VR4Z73EU.js.map +0 -1
  76. package/dist/chunk-XMXRI5JK.js.map +0 -1
  77. package/dist/chunk-ZC2DK5SC.js.map +0 -1
  78. /package/dist/{browser-viewer-MN7MOYQT.js.map → browser-viewer-K2H3SLIW.js.map} +0 -0
@@ -163,6 +163,7 @@ export function useVoiceInput({
163
163
  const automaticRetryAttemptRef = useRef(0);
164
164
  const ownerHeartbeatTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
165
165
  const controllerRef = useRef<AbortController | null>(null);
166
+ const disabledRef = useRef(disabled);
166
167
  const valueRef = useRef(value);
167
168
  const storeRef = useRef<VoiceRecordingStore | null>(null);
168
169
  const storePromiseRef = useRef<Promise<VoiceRecordingStore> | null>(null);
@@ -176,6 +177,7 @@ export function useVoiceInput({
176
177
  const statusRef = useRef(status);
177
178
  valueRef.current = value;
178
179
  statusRef.current = status;
180
+ disabledRef.current = disabled;
179
181
  workspaceIdRef.current = workspaceId;
180
182
 
181
183
  const ensureOwnerId = useCallback(async (): Promise<string> => {
@@ -468,6 +470,14 @@ export function useVoiceInput({
468
470
  return;
469
471
  }
470
472
 
473
+ // Session creation can disable the composer while a recording is
474
+ // transcribing. Keep the durable transcript for explicit insertion
475
+ // later; never append text after Send captured its visible snapshot.
476
+ if (disabledRef.current) {
477
+ setStatus("transcript-ready");
478
+ return;
479
+ }
480
+
471
481
  const next = appendFinalTranscript(valueRef.current, response.text);
472
482
  if (next !== valueRef.current) {
473
483
  valueRef.current = next;
@@ -944,6 +954,7 @@ export function useVoiceInput({
944
954
  const insertSavedTranscript = useCallback(async (): Promise<void> => {
945
955
  const manifest = manifestRef.current;
946
956
  if (
957
+ disabledRef.current ||
947
958
  !manifest ||
948
959
  manifest.workspaceId !== workspaceId ||
949
960
  manifest.finalizationState !== "transcript-ready" ||
@@ -955,7 +966,7 @@ export function useVoiceInput({
955
966
  controllerRef.current?.abort();
956
967
  controllerRef.current = null;
957
968
  const store = await ensureStore();
958
- if (generation !== generationRef.current) return;
969
+ if (generation !== generationRef.current || disabledRef.current) return;
959
970
  const next = appendFinalTranscript(valueRef.current, manifest.transcriptText);
960
971
  if (next !== valueRef.current) {
961
972
  valueRef.current = next;
@@ -15,6 +15,8 @@ export function compactionSkipSubtitle(
15
15
  return "No active history to compact";
16
16
  case "replacement_not_smaller":
17
17
  return "Checkpoint would not reduce memory size";
18
+ case "replacement_exceeds_model_budget":
19
+ return "Checkpoint exceeds this model's context budget. Chat history is unchanged.";
18
20
  case "replacement_unchanged":
19
21
  return "Checkpoint made no progress";
20
22
  case "summarization_failed":
@@ -566,8 +566,8 @@ export function retainedScreenshotMetadata(out: unknown): RetainedArtifactMetada
566
566
  if (!value.available) {
567
567
  return typeof value.reason === "string" ? (value as unknown as RetainedArtifactMetadata) : null;
568
568
  }
569
- return value.kind === "computer_screenshot" &&
570
- value.contentType === "image/png" &&
569
+ return (value.kind === "computer_screenshot" || value.kind === "browser_screenshot") &&
570
+ ["image/png", "image/jpeg", "image/webp"].includes(String(value.contentType)) &&
571
571
  typeof value.originalBytes === "number" &&
572
572
  typeof value.sha256 === "string" &&
573
573
  value.dimensions !== null &&
@@ -1016,6 +1016,7 @@ export function buildTimeline(
1016
1016
  case "tool.auth_needed":
1017
1017
  case "credential.auth_needed": {
1018
1018
  const capability = capabilityAuthorizationRequest(payload.capability);
1019
+ const setupRequest = customMcpSetupRequest(payload.setupRequest);
1019
1020
  if (
1020
1021
  event.type === "tool.auth_needed" &&
1021
1022
  !stringValue(payload.toolName) &&
@@ -1045,11 +1046,12 @@ export function buildTimeline(
1045
1046
  payload.connectionSubjectScope === "workspace"
1046
1047
  ? payload.connectionSubjectScope
1047
1048
  : null,
1048
- source: capability
1049
- ? "capability"
1050
- : event.type === "tool.auth_needed"
1051
- ? "tool"
1052
- : "credential",
1049
+ source:
1050
+ capability || setupRequest
1051
+ ? "capability"
1052
+ : event.type === "tool.auth_needed"
1053
+ ? "tool"
1054
+ : "credential",
1053
1055
  providerDomain: stringValue(payload.providerDomain),
1054
1056
  connectionId: typeof payload.connectionId === "string" ? payload.connectionId : null,
1055
1057
  authoritySource: payload.authoritySource === "host" ? "host" : null,
@@ -1064,6 +1066,7 @@ export function buildTimeline(
1064
1066
  authorizationUrl:
1065
1067
  typeof payload.authorizationUrl === "string" ? payload.authorizationUrl : null,
1066
1068
  capability,
1069
+ setupRequest,
1067
1070
  occurredAt: event.occurredAt,
1068
1071
  });
1069
1072
  break;
@@ -2623,6 +2626,29 @@ function capabilityAuthorizationRequest(
2623
2626
  };
2624
2627
  }
2625
2628
 
2629
+ function customMcpSetupRequest(value: unknown): NonNullable<AuthNeededItem["setupRequest"]> | null {
2630
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
2631
+ const input = value as Record<string, unknown>;
2632
+ if (
2633
+ input.kind !== "mcp" ||
2634
+ typeof input.name !== "string" ||
2635
+ typeof input.rationale !== "string" ||
2636
+ typeof input.endpointUrl !== "string"
2637
+ )
2638
+ return null;
2639
+ try {
2640
+ if (new URL(input.endpointUrl).protocol !== "https:") return null;
2641
+ } catch {
2642
+ return null;
2643
+ }
2644
+ return {
2645
+ kind: "mcp",
2646
+ name: input.name,
2647
+ endpointUrl: input.endpointUrl,
2648
+ rationale: input.rationale,
2649
+ };
2650
+ }
2651
+
2626
2652
  function stringList(value: unknown): string[] {
2627
2653
  return Array.isArray(value)
2628
2654
  ? value.filter((entry): entry is string => typeof entry === "string" && entry.trim().length > 0)
@@ -772,21 +772,73 @@ function ComputerCallRenderer({ item, loadRetainedScreenshot }: ToolRendererProp
772
772
  );
773
773
  }
774
774
 
775
- function RetainedSessionImageDisclosure({
776
- artifact,
777
- load,
778
- title,
779
- caption,
780
- noun,
781
- icon,
782
- lightboxLabel,
783
- batched,
784
- failed,
785
- cancelled,
786
- filename,
787
- defaultOpen,
788
- children,
789
- }: {
775
+ /** Browser tool images share authenticated screenshot loading, with their own media kind. */
776
+ function BrowserScreenshotRenderer(props: ToolRendererProps) {
777
+ const { item, loadRetainedScreenshot } = props;
778
+ const leaf = mcpToolLeaf(item.name);
779
+ const title =
780
+ leaf === "browser_observe"
781
+ ? "Observed browser"
782
+ : leaf === "browser_act"
783
+ ? "Used browser"
784
+ : "Browser screenshot";
785
+ const retained = retainedScreenshotMetadata(item.output);
786
+ const isFailed = item.status === "failed";
787
+ const isCancelled = item.status === "cancelled";
788
+
789
+ if (item.status === "running" && leaf === "browser_screenshot") {
790
+ return (
791
+ <ActivityDisclosure
792
+ icon={<CameraIcon className={ICON_SIZE} />}
793
+ iconTone="running"
794
+ title={title}
795
+ running
796
+ media={<MediaSkeleton />}
797
+ >
798
+ <BodyNote>capturing frame…</BodyNote>
799
+ </ActivityDisclosure>
800
+ );
801
+ }
802
+
803
+ if (!retained) return <GenericRenderer {...props} />;
804
+ if (!retained.available) {
805
+ const state =
806
+ retained.reason === "expired" || retained.reason === "deleted"
807
+ ? retained.reason
808
+ : "unavailable";
809
+ return (
810
+ <ActivityDisclosure
811
+ icon={<CameraOffIcon className={ICON_SIZE} />}
812
+ iconTone={isFailed ? "failed" : "muted"}
813
+ title={`${title} · ${state}`}
814
+ failed={isFailed}
815
+ cancelled={isCancelled}
816
+ preview={`screenshot ${state}`}
817
+ media={<MediaEmpty />}
818
+ >
819
+ <BodyNote tone={isFailed ? "error" : undefined}>
820
+ Screenshot {state}: {retained.reason.replaceAll("_", " ")}.
821
+ </BodyNote>
822
+ </ActivityDisclosure>
823
+ );
824
+ }
825
+ return (
826
+ <RetainedSessionImageDisclosure
827
+ artifact={retained}
828
+ load={loadRetainedScreenshot}
829
+ title={title}
830
+ caption={title}
831
+ noun="screenshot"
832
+ icon={<CameraIcon className={ICON_SIZE} />}
833
+ lightboxLabel="Browser screenshot"
834
+ batched={null}
835
+ failed={isFailed}
836
+ cancelled={isCancelled}
837
+ />
838
+ );
839
+ }
840
+
841
+ type RetainedSessionImageDisclosureProps = {
790
842
  artifact: RetainedArtifactReference;
791
843
  load: ToolRendererProps["loadRetainedArtifact"];
792
844
  title: string;
@@ -800,7 +852,41 @@ function RetainedSessionImageDisclosure({
800
852
  filename?: string;
801
853
  defaultOpen?: boolean;
802
854
  children?: ReactNode;
803
- }) {
855
+ };
856
+
857
+ function RetainedSessionImageDisclosure(props: RetainedSessionImageDisclosureProps) {
858
+ const compact = useContext(CompactActivityContext);
859
+ // The rolling progress label has no screenshot loader by design. Do not run
860
+ // the full image hook there: it would report the missing loader as an error.
861
+ if (compact) {
862
+ return (
863
+ <ActivityDisclosure
864
+ icon={props.icon}
865
+ title={props.title}
866
+ compactPreview={null}
867
+ failed={props.failed}
868
+ cancelled={props.cancelled}
869
+ />
870
+ );
871
+ }
872
+ return <LoadedRetainedSessionImageDisclosure {...props} />;
873
+ }
874
+
875
+ function LoadedRetainedSessionImageDisclosure({
876
+ artifact,
877
+ load,
878
+ title,
879
+ caption,
880
+ noun,
881
+ icon,
882
+ lightboxLabel,
883
+ batched,
884
+ failed,
885
+ cancelled,
886
+ filename,
887
+ defaultOpen,
888
+ children,
889
+ }: RetainedSessionImageDisclosureProps) {
804
890
  const state = useRetainedImageObjectUrl(artifact, load);
805
891
  const downloadFilename = filename ?? retainedImageFilename(artifact);
806
892
 
@@ -2401,6 +2487,9 @@ const BASE_ENTRIES: ToolRegistryEntry[] = [
2401
2487
  { match: "name", name: "apply_patch_call", render: ApplyPatchRenderer },
2402
2488
  { match: "name", name: "apply_patch", render: ApplyPatchRenderer },
2403
2489
  { match: "name", name: "computer_call", render: ComputerCallRenderer },
2490
+ { match: "name", name: "browser_screenshot", render: BrowserScreenshotRenderer },
2491
+ { match: "name", name: "browser_observe", render: BrowserScreenshotRenderer },
2492
+ { match: "name", name: "browser_act", render: BrowserScreenshotRenderer },
2404
2493
  // Function-mode computer tools (codex / chat-wire transports).
2405
2494
  { match: "name", name: "computer_screenshot", render: ComputerCallRenderer },
2406
2495
  { match: "name", name: "computer_click", render: ComputerCallRenderer },
@@ -21,9 +21,11 @@ import {
21
21
  applyPatchOpsFromToolItem,
22
22
  isApplyPatch,
23
23
  mediaPreviewFact,
24
+ retainedScreenshotMetadata,
24
25
  screenshotDataUrl,
25
26
  } from "./parsers";
26
27
  import { rawTypeOf } from "./registry";
28
+ import { mcpToolLeaf } from "./tool-display-name";
27
29
  import type { ActivityItem, ToolCallItem, TurnOutcome } from "./types";
28
30
  export type { TurnOutcome } from "./types";
29
31
 
@@ -626,11 +628,17 @@ const BUILT_IN_TURN_SUMMARY_FACETS: readonly TurnSummaryFacet[] = Object.freeze(
626
628
  summarize: ({ toolCalls }) => {
627
629
  let screenshots = 0;
628
630
  for (const item of toolCalls) {
631
+ const leaf = mcpToolLeaf(item.name);
629
632
  if (
630
633
  (rawTypeOf(item) === "computer_call" ||
631
634
  item.name === "computer_call" ||
632
- item.name === "computer_screenshot") &&
633
- (screenshotDataUrl(item.output) !== null || mediaPreviewFact(item.output) !== null)
635
+ item.name === "computer_screenshot" ||
636
+ leaf === "browser_screenshot" ||
637
+ leaf === "browser_observe" ||
638
+ leaf === "browser_act") &&
639
+ (retainedScreenshotMetadata(item.output) !== null ||
640
+ screenshotDataUrl(item.output) !== null ||
641
+ mediaPreviewFact(item.output) !== null)
634
642
  ) {
635
643
  screenshots += 1;
636
644
  }
@@ -475,6 +475,8 @@ export type AuthNeededItem = {
475
475
  authorizationUrl: string | null;
476
476
  /** Agent-selected catalog recommendation. The host still owns authorization. */
477
477
  capability?: NonNullable<ToolAuthNeededPayload["capability"]> | null | undefined;
478
+ /** Human-reviewed custom integration proposal. Never treated as catalog authority. */
479
+ setupRequest?: ToolAuthNeededPayload["setupRequest"] | null | undefined;
478
480
  occurredAt: string;
479
481
  };
480
482
 
@@ -809,6 +809,9 @@
809
809
  :where(.og-root).og-session-capability-setup [role=alert],:where(.og-root) .og-session-capability-setup [role=alert] {
810
810
  color: var(--og-color-danger,#b42318);
811
811
  }
812
+ :where(.og-root).og-session-capability-setup .og-session-capability-notice,:where(.og-root) .og-session-capability-setup .og-session-capability-notice {
813
+ color: var(--og-color-fg-muted);
814
+ }
812
815
  :where(.og-root).og-session-capability-shell[data-state="complete"],:where(.og-root) .og-session-capability-shell[data-state="complete"] {
813
816
  border-color: var(--og-color-status-success,#16804a);
814
817
  @supports (color: color-mix(in lab, red, red)) {
@@ -857,6 +860,9 @@
857
860
  color: var(--og-color-fg-muted);
858
861
  padding-block: 8px;
859
862
  }
863
+ :where(.og-root).og-session-capability-setup .og-session-capability-stop,:where(.og-root) .og-session-capability-setup .og-session-capability-stop {
864
+ justify-self: end;
865
+ }
860
866
  @media (pointer:coarse) {
861
867
  :where(.og-root).og-session-capability-actions button,:where(.og-root) .og-session-capability-actions button,:where(.og-root).og-session-capability-setup button,:where(.og-root) .og-session-capability-setup button {
862
868
  min-height: 44px;
@@ -28,6 +28,7 @@
28
28
  .og-session-capability-setup button { font:inherit; padding:9px 12px; border-radius:7px; border:1px solid var(--og-color-border); background:var(--og-color-surface-2); color:inherit; cursor:pointer; }
29
29
  .og-session-capability-setup button:disabled { opacity:.55; cursor:not-allowed; }
30
30
  .og-session-capability-setup [role=alert] { color:var(--og-color-danger,#b42318); }
31
+ .og-session-capability-setup .og-session-capability-notice { color:var(--og-color-fg-muted); }
31
32
  .og-session-capability-shell[data-state="complete"] { border-color:color-mix(in srgb,var(--og-color-status-success,#16804a) 35%,var(--og-color-border)); }
32
33
  .og-session-capability-shell[data-state="complete"] .og-session-capability-header > svg,
33
34
  .og-session-capability-shell[data-state="complete"] .og-session-capability-copy { color:var(--og-color-status-success,#16804a); }
@@ -39,4 +40,5 @@
39
40
  .og-session-capability-setup .og-session-capability-primary { justify-self:end; min-height:40px; padding:10px 16px; border:0; background:var(--og-color-accent-deep,#006cdb); color:var(--og-color-accent-fg,#fff); font-weight:500; }
40
41
  .og-session-capability-setup .og-session-capability-primary:hover:not(:disabled) { filter:brightness(.94); }
41
42
  .og-session-capability-progress { color:var(--og-color-fg-muted); padding-block:8px; }
43
+ .og-session-capability-setup .og-session-capability-stop { justify-self:end; }
42
44
  @media (pointer:coarse) { .og-session-capability-actions button,.og-session-capability-setup button { min-height:44px; } }