@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.
- package/README.md +158 -14
- package/dist/artifacts-document.d.ts +3 -0
- package/dist/artifacts-document.js +17 -0
- package/dist/artifacts-document.js.map +1 -0
- package/dist/artifacts-presentation.d.ts +3 -0
- package/dist/artifacts-presentation.js +17 -0
- package/dist/artifacts-presentation.js.map +1 -0
- package/dist/artifacts-spreadsheet.d.ts +3 -0
- package/dist/artifacts-spreadsheet.js +17 -0
- package/dist/artifacts-spreadsheet.js.map +1 -0
- package/dist/artifacts.d.ts +2 -0
- package/dist/artifacts.js +170 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/chunk-6BBWWOOU.js +82 -0
- package/dist/chunk-6BBWWOOU.js.map +1 -0
- package/dist/{chunk-HFO4ERGQ.js → chunk-724BW4TW.js} +586 -35
- package/dist/chunk-724BW4TW.js.map +1 -0
- package/dist/chunk-7I2KB3OK.js +3895 -0
- package/dist/chunk-7I2KB3OK.js.map +1 -0
- package/dist/chunk-7WCLAEFV.js +2828 -0
- package/dist/chunk-7WCLAEFV.js.map +1 -0
- package/dist/{chunk-U3CSCMWA.js → chunk-FK6VG4LL.js} +9 -13
- package/dist/chunk-FK6VG4LL.js.map +1 -0
- package/dist/{chunk-SRFUT2ZU.js → chunk-FWS3KC3Z.js} +120 -64
- package/dist/chunk-FWS3KC3Z.js.map +1 -0
- package/dist/{chunk-EKZH6IDG.js → chunk-HDBG7XGO.js} +62 -1
- package/dist/chunk-HDBG7XGO.js.map +1 -0
- package/dist/chunk-HUIKIDM5.js +2148 -0
- package/dist/chunk-HUIKIDM5.js.map +1 -0
- package/dist/{chunk-LGVMUIRV.js → chunk-JAGDUCZQ.js} +1053 -390
- package/dist/chunk-JAGDUCZQ.js.map +1 -0
- package/dist/{chunk-LWR4MXSS.js → chunk-JR3QFY6B.js} +420 -35
- package/dist/chunk-JR3QFY6B.js.map +1 -0
- package/dist/chunk-JVYQRRC4.js +53 -0
- package/dist/chunk-JVYQRRC4.js.map +1 -0
- package/dist/chunk-KCGXPP5V.js +157 -0
- package/dist/chunk-KCGXPP5V.js.map +1 -0
- package/dist/{chunk-EB67J347.js → chunk-KZ73RL76.js} +111 -31
- package/dist/chunk-KZ73RL76.js.map +1 -0
- package/dist/chunk-PEI6RANI.js +3234 -0
- package/dist/chunk-PEI6RANI.js.map +1 -0
- package/dist/{chunk-3PB7MIT6.js → chunk-ROIRTM37.js} +220 -72
- package/dist/chunk-ROIRTM37.js.map +1 -0
- package/dist/chunk-VZTQ73XT.js +86 -0
- package/dist/chunk-VZTQ73XT.js.map +1 -0
- package/dist/{chunk-VCBFUSUZ.js → chunk-WSK7G5LE.js} +72 -4
- package/dist/chunk-WSK7G5LE.js.map +1 -0
- package/dist/{chunk-FGZUCXZF.js → chunk-WYA65Y3F.js} +16 -16
- package/dist/chunk-WYA65Y3F.js.map +1 -0
- package/dist/{chunk-6EDV6YFE.js → chunk-X4S56Y2H.js} +147 -35
- package/dist/chunk-X4S56Y2H.js.map +1 -0
- package/dist/client.d.ts +7 -1
- package/dist/clipboard.d.ts +1 -0
- package/dist/clipboard.js +7 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/commands/index.d.ts +3 -3
- package/dist/commands/registry.d.ts +1 -1
- package/dist/commands/types.d.ts +1 -1
- package/dist/components/approval-surface.d.ts +2 -2
- package/dist/components/artifacts/artifact-surface.d.ts +18 -0
- package/dist/components/artifacts/document-editor.d.ts +172 -0
- package/dist/components/artifacts/editable-artifact-ui.d.ts +13 -0
- package/dist/components/artifacts/editable-artifact-workbench.d.ts +49 -0
- package/dist/components/artifacts/editable-document.d.ts +24 -0
- package/dist/components/artifacts/editable-presentation.d.ts +24 -0
- package/dist/components/artifacts/editable-spreadsheet.d.ts +32 -0
- package/dist/components/artifacts/index.d.ts +8 -0
- package/dist/components/artifacts/presentation-editor.d.ts +297 -0
- package/dist/components/artifacts/spreadsheet-canvas.d.ts +120 -0
- package/dist/components/artifacts/spreadsheet-grid.d.ts +113 -0
- package/dist/components/browser-viewer.d.ts +29 -0
- package/dist/components/chat-composer.d.ts +13 -8
- package/dist/components/code-editor.d.ts +25 -3
- package/dist/components/command-palette.d.ts +2 -2
- package/dist/components/composer-transcription-control.d.ts +4 -2
- package/dist/components/composer.d.ts +29 -15
- package/dist/components/computer-viewer.d.ts +23 -0
- package/dist/components/copy-button.d.ts +2 -2
- package/dist/components/desktop-viewer.d.ts +25 -21
- package/dist/components/diff-view.d.ts +1 -1
- package/dist/components/enrollment-consent.d.ts +1 -1
- package/dist/components/enrollment-device-flow.d.ts +1 -1
- package/dist/components/file-browser.d.ts +2 -2
- package/dist/components/fleet-tile.d.ts +1 -1
- package/dist/components/generated-video-player.d.ts +10 -0
- package/dist/components/human-input-form.d.ts +1 -1
- package/dist/components/human-input-surface.d.ts +2 -2
- package/dist/components/interactive-workbench-viewers.d.ts +2 -0
- package/dist/components/machine-card.d.ts +2 -2
- package/dist/components/machine-dock-bar.d.ts +3 -3
- package/dist/components/machine-health-pill.d.ts +2 -2
- package/dist/components/machine-input-display.d.ts +1 -1
- package/dist/components/machine-metrics.d.ts +2 -2
- package/dist/components/machine-status-pill.d.ts +4 -4
- package/dist/components/machines/health.d.ts +1 -1
- package/dist/components/machines/machine-detail.d.ts +5 -3
- package/dist/components/machines/metric-history-chart.d.ts +1 -1
- package/dist/components/machines/metric-sparkline.d.ts +2 -2
- package/dist/components/machines/series.d.ts +2 -2
- package/dist/components/machines-dashboard.d.ts +5 -5
- package/dist/components/markdown.d.ts +1 -1
- package/dist/components/message-timeline.d.ts +22 -5
- package/dist/components/model-picker.d.ts +2 -2
- package/dist/components/model-policy-picker.d.ts +7 -7
- package/dist/components/pierre-diff.d.ts +1 -1
- package/dist/components/pierre-file.d.ts +1 -1
- package/dist/components/queue-draft-policy.d.ts +1 -1
- package/dist/components/queue-surface-implementation.d.ts +3 -3
- package/dist/components/queue-surface-state.d.ts +4 -4
- package/dist/components/queue-surface.d.ts +5 -5
- package/dist/components/sandbox-files.d.ts +5 -5
- package/dist/components/sandbox-terminal.d.ts +50 -4
- package/dist/components/sandbox-workspace.d.ts +30 -10
- package/dist/components/session-chrome.d.ts +4 -4
- package/dist/components/session-status.d.ts +2 -2
- package/dist/components/timeline-annotation-selection.d.ts +9 -0
- package/dist/components/timeline-annotations-dialog.d.ts +16 -0
- package/dist/components/timeline-annotations.d.ts +13 -0
- package/dist/components/tooltip.d.ts +4 -4
- package/dist/components/user-message-body.d.ts +2 -2
- package/dist/components/workbench-changes.d.ts +2 -2
- package/dist/components/workspace-dock.d.ts +3 -1
- package/dist/composer.d.ts +11 -11
- package/dist/composer.js +7 -7
- package/dist/hooks/internal.d.ts +7 -1
- package/dist/hooks/use-attached-browsers.d.ts +21 -0
- package/dist/hooks/use-available-models.d.ts +2 -2
- package/dist/hooks/use-billing-usage.d.ts +1 -1
- package/dist/hooks/use-browser-frame-stream.d.ts +28 -0
- package/dist/hooks/use-browser-identities.d.ts +26 -0
- package/dist/hooks/use-browser-session.d.ts +28 -0
- package/dist/hooks/use-browser-sessions.d.ts +32 -0
- package/dist/hooks/use-codex-accounts.d.ts +3 -3
- package/dist/hooks/use-composer.d.ts +36 -9
- package/dist/hooks/use-computer-frame-stream.d.ts +24 -0
- package/dist/hooks/use-computer-session.d.ts +28 -0
- package/dist/hooks/use-computer-sessions.d.ts +28 -0
- package/dist/hooks/use-desktop-stream.d.ts +1 -1
- package/dist/hooks/use-environments.d.ts +11 -5
- package/dist/hooks/use-file-attachments.d.ts +1 -1
- package/dist/hooks/use-goal.d.ts +2 -2
- package/dist/hooks/use-human-input.d.ts +2 -2
- package/dist/hooks/use-last-started-turn-policy.d.ts +2 -2
- package/dist/hooks/use-machine-chip.d.ts +2 -2
- package/dist/hooks/use-machines.d.ts +10 -3
- package/dist/hooks/use-packs.d.ts +7 -2
- package/dist/hooks/use-rigs.d.ts +1 -1
- package/dist/hooks/use-sandbox-files.d.ts +25 -4
- package/dist/hooks/use-sandbox-git.d.ts +13 -5
- package/dist/hooks/use-sandbox-terminal.d.ts +1 -1
- package/dist/hooks/use-scheduled-tasks.d.ts +1 -1
- package/dist/hooks/use-session-capabilities.d.ts +5 -4
- package/dist/hooks/use-session-control.d.ts +1 -1
- package/dist/hooks/use-session-events.d.ts +2 -2
- package/dist/hooks/use-session-lineage.d.ts +1 -1
- package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
- package/dist/hooks/use-session.d.ts +2 -2
- package/dist/hooks/use-slash-commands.d.ts +1 -1
- package/dist/hooks/use-terminal-stream.d.ts +8 -2
- package/dist/hooks/use-transcription.d.ts +2 -2
- package/dist/hooks/use-turn-queue.d.ts +2 -2
- package/dist/hooks/use-video-artifact-playback.d.ts +9 -0
- package/dist/hooks/use-voice-input.d.ts +6 -4
- package/dist/hooks/use-workspace-capture.d.ts +1 -1
- package/dist/hooks/use-workspace-edit.d.ts +1 -1
- package/dist/hooks/use-workspace-sessions.d.ts +1 -1
- package/dist/hooks/use-workspaces.d.ts +1 -1
- package/dist/index.d.ts +158 -154
- package/dist/index.js +1718 -908
- package/dist/index.js.map +1 -1
- package/dist/interaction.d.ts +23 -0
- package/dist/interaction.js +36 -0
- package/dist/interaction.js.map +1 -0
- package/dist/interactive-workbench-viewers-KHNOHWQE.js +13 -0
- package/dist/interactive-workbench-viewers-KHNOHWQE.js.map +1 -0
- package/dist/lib/composer-responsive-context.d.ts +9 -0
- package/dist/lib/relay-wire.d.ts +4 -0
- package/dist/lib/sandbox-liveness.d.ts +9 -0
- package/dist/lib/terminal-capability.d.ts +5 -0
- package/dist/lib/use-portal-token-style.d.ts +14 -3
- package/dist/lib/xterm-theme.d.ts +1 -1
- package/dist/machines.d.ts +30 -30
- package/dist/machines.js +3 -3
- package/dist/provider.d.ts +4 -4
- package/dist/{queue-surface-implementation-J4XJFKRW.js → queue-surface-implementation-2KVJTYXH.js} +117 -64
- package/dist/queue-surface-implementation-2KVJTYXH.js.map +1 -0
- package/dist/realtime/dropdown-menu.d.ts +8 -8
- package/dist/realtime/realtime-control.d.ts +15 -6
- package/dist/realtime.d.ts +4 -4
- package/dist/realtime.js +30 -33
- package/dist/realtime.js.map +1 -1
- package/dist/session-context.d.ts +19 -1
- package/dist/session-ui.d.ts +14 -14
- package/dist/session-ui.js +6 -5
- package/dist/session.d.ts +28 -28
- package/dist/session.js +5 -5
- package/dist/timeline/activity-rail.d.ts +6 -3
- package/dist/timeline/disclosure-context.d.ts +1 -1
- package/dist/timeline/fleet-decision-projection.d.ts +1 -1
- package/dist/timeline/fleet-decision-row.d.ts +3 -3
- package/dist/timeline/index.d.ts +19 -19
- package/dist/timeline/parsers.d.ts +6 -3
- package/dist/timeline/projection.d.ts +3 -3
- package/dist/timeline/registry.d.ts +10 -1
- package/dist/timeline/screenshot-lightbox.d.ts +2 -2
- package/dist/timeline/shared.d.ts +21 -10
- package/dist/timeline/tool-diff.d.ts +2 -2
- package/dist/timeline/tool-renderers.d.ts +1 -1
- package/dist/timeline/turn-summary.d.ts +3 -3
- package/dist/timeline/types.d.ts +42 -2
- package/dist/timeline-annotation-selection-3L7LHGG2.js +187 -0
- package/dist/timeline-annotation-selection-3L7LHGG2.js.map +1 -0
- package/dist/timeline-annotations-dialog-U7EVLR75.js +196 -0
- package/dist/timeline-annotations-dialog-U7EVLR75.js.map +1 -0
- package/dist/voice-recording-store.d.ts +8 -2
- package/package.json +52 -7
- package/src/artifacts-document.ts +31 -0
- package/src/artifacts-presentation.ts +36 -0
- package/src/artifacts-spreadsheet.ts +21 -0
- package/src/artifacts.ts +86 -0
- package/src/client.ts +90 -1
- package/src/clipboard.ts +2 -0
- package/src/components/artifacts/artifact-surface.tsx +93 -0
- package/src/components/artifacts/document-editor.tsx +2255 -0
- package/src/components/artifacts/editable-artifact-ui.tsx +89 -0
- package/src/components/artifacts/editable-artifact-workbench.tsx +203 -0
- package/src/components/artifacts/editable-document.tsx +657 -0
- package/src/components/artifacts/editable-presentation.tsx +1020 -0
- package/src/components/artifacts/editable-spreadsheet.tsx +733 -0
- package/src/components/artifacts/index.ts +99 -0
- package/src/components/artifacts/presentation-editor.tsx +3148 -0
- package/src/components/artifacts/spreadsheet-canvas.ts +799 -0
- package/src/components/artifacts/spreadsheet-grid.tsx +2129 -0
- package/src/components/browser-viewer.tsx +1592 -0
- package/src/components/chat-composer.tsx +25 -2
- package/src/components/code-editor.tsx +90 -31
- package/src/components/command-palette.tsx +1 -1
- package/src/components/composer-transcription-control.tsx +51 -22
- package/src/components/composer.tsx +49 -23
- package/src/components/computer-viewer.tsx +1139 -0
- package/src/components/copy-button.tsx +1 -1
- package/src/components/desktop-viewer.tsx +103 -75
- package/src/components/file-browser.tsx +39 -17
- package/src/components/generated-video-player.tsx +89 -0
- package/src/components/human-input-form.tsx +2 -2
- package/src/components/interactive-workbench-viewers.ts +2 -0
- package/src/components/machine-card.tsx +1 -1
- package/src/components/machine-input-display.ts +3 -0
- package/src/components/machines/machine-detail.tsx +39 -15
- package/src/components/machines-dashboard.tsx +7 -6
- package/src/components/message-timeline.tsx +327 -37
- package/src/components/model-picker.tsx +2 -2
- package/src/components/model-policy-picker.tsx +16 -15
- package/src/components/queue-surface-implementation.tsx +135 -75
- package/src/components/queue-surface-state.tsx +2 -2
- package/src/components/sandbox-files.tsx +142 -62
- package/src/components/sandbox-terminal.tsx +119 -35
- package/src/components/sandbox-workspace.tsx +394 -228
- package/src/components/session-chrome.tsx +67 -27
- package/src/components/timeline-annotation-selection.tsx +221 -0
- package/src/components/timeline-annotations-dialog.tsx +213 -0
- package/src/components/timeline-annotations.tsx +84 -0
- package/src/components/tooltip.tsx +13 -16
- package/src/components/user-message-body.tsx +1 -1
- package/src/components/workbench-changes.tsx +192 -35
- package/src/components/workspace-dock.tsx +13 -5
- package/src/composer.ts +3 -0
- package/src/hooks/internal.ts +132 -38
- package/src/hooks/use-attached-browsers.ts +152 -0
- package/src/hooks/use-browser-frame-stream.ts +316 -0
- package/src/hooks/use-browser-identities.ts +225 -0
- package/src/hooks/use-browser-session.ts +476 -0
- package/src/hooks/use-browser-sessions.ts +281 -0
- package/src/hooks/use-codex-accounts.ts +4 -4
- package/src/hooks/use-composer.ts +769 -24
- package/src/hooks/use-computer-frame-stream.ts +311 -0
- package/src/hooks/use-computer-session.ts +442 -0
- package/src/hooks/use-computer-sessions.ts +245 -0
- package/src/hooks/use-environments.ts +24 -5
- package/src/hooks/use-file-attachments.ts +70 -32
- package/src/hooks/use-goal.ts +17 -5
- package/src/hooks/use-machine-chip.ts +5 -3
- package/src/hooks/use-machines.ts +79 -3
- package/src/hooks/use-packs.ts +51 -0
- package/src/hooks/use-sandbox-files.ts +382 -88
- package/src/hooks/use-sandbox-git.ts +208 -46
- package/src/hooks/use-sandbox-terminal.ts +3 -2
- package/src/hooks/use-session-capabilities.ts +94 -70
- package/src/hooks/use-session-events.ts +18 -4
- package/src/hooks/use-terminal-stream.ts +102 -23
- package/src/hooks/use-transcription.ts +4 -14
- package/src/hooks/use-turn-queue.ts +17 -5
- package/src/hooks/use-video-artifact-playback.ts +28 -0
- package/src/hooks/use-voice-input.ts +163 -19
- package/src/hooks/use-windowed-sections.ts +9 -7
- package/src/hooks/use-workspace-edit.ts +2 -1
- package/src/index.ts +21 -6
- package/src/interaction.ts +71 -0
- package/src/lib/composer-responsive-context.ts +15 -0
- package/src/lib/relay-wire.ts +4 -0
- package/src/lib/sandbox-liveness.ts +11 -0
- package/src/lib/terminal-capability.ts +10 -0
- package/src/lib/use-portal-token-style.ts +60 -15
- package/src/provider.tsx +52 -7
- package/src/realtime/dropdown-menu.tsx +15 -19
- package/src/realtime/realtime-control.tsx +16 -5
- package/src/session-context.ts +90 -0
- package/src/timeline/activity-rail.tsx +31 -6
- package/src/timeline/index.ts +4 -1
- package/src/timeline/parsers.ts +46 -20
- package/src/timeline/projection.ts +233 -13
- package/src/timeline/registry.ts +19 -0
- package/src/timeline/screenshot-lightbox.tsx +30 -9
- package/src/timeline/shared.tsx +59 -11
- package/src/timeline/tool-renderers.tsx +421 -24
- package/src/timeline/turn-summary.tsx +2 -2
- package/src/timeline/types.ts +58 -2
- package/src/voice-recording-store.ts +15 -0
- package/styles/compiled.css +5298 -0
- package/styles/compiled.d.ts +2 -0
- package/styles/effective-tokens.css +27 -0
- package/styles/index.css +18 -0
- package/styles/responsive.css +208 -0
- package/styles/responsive.d.ts +2 -0
- package/styles/tokens.css +50 -17
- package/dist/chunk-3PB7MIT6.js.map +0 -1
- package/dist/chunk-6EDV6YFE.js.map +0 -1
- package/dist/chunk-EB67J347.js.map +0 -1
- package/dist/chunk-EKZH6IDG.js.map +0 -1
- package/dist/chunk-FGZUCXZF.js.map +0 -1
- package/dist/chunk-HFO4ERGQ.js.map +0 -1
- package/dist/chunk-JB5725BI.js +0 -48
- package/dist/chunk-JB5725BI.js.map +0 -1
- package/dist/chunk-LGVMUIRV.js.map +0 -1
- package/dist/chunk-LWR4MXSS.js.map +0 -1
- package/dist/chunk-SRFUT2ZU.js.map +0 -1
- package/dist/chunk-U3CSCMWA.js.map +0 -1
- package/dist/chunk-VCBFUSUZ.js.map +0 -1
- package/dist/fleet-decision-projection-SLNZMS42.js +0 -241
- package/dist/fleet-decision-projection-SLNZMS42.js.map +0 -1
- package/dist/queue-surface-implementation-J4XJFKRW.js.map +0 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createContext, useContext, type RefObject } from "react";
|
|
2
|
+
|
|
3
|
+
/** The measurement surface used by responsive composer chrome. */
|
|
4
|
+
export type ResponsiveBasis = "viewport" | "container";
|
|
5
|
+
|
|
6
|
+
export type ComposerResponsiveContextValue = {
|
|
7
|
+
responsiveBasis: ResponsiveBasis;
|
|
8
|
+
rootRef: RefObject<HTMLDivElement | null>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const ComposerResponsiveContext = createContext<ComposerResponsiveContextValue | null>(null);
|
|
12
|
+
|
|
13
|
+
export function useComposerResponsiveContext(): ComposerResponsiveContextValue | null {
|
|
14
|
+
return useContext(ComposerResponsiveContext);
|
|
15
|
+
}
|
package/src/lib/relay-wire.ts
CHANGED
|
@@ -17,6 +17,10 @@ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
|
|
17
17
|
|
|
18
18
|
/** `StreamKind.STREAM_KIND_DESKTOP` (agent-proto enum value). */
|
|
19
19
|
export const STREAM_KIND_DESKTOP = 2;
|
|
20
|
+
/** `StreamKind.STREAM_KIND_BROWSER` (agent-proto enum value). */
|
|
21
|
+
export const STREAM_KIND_BROWSER = 3;
|
|
22
|
+
/** `StreamKind.STREAM_KIND_COMPUTER` (agent-proto enum value). */
|
|
23
|
+
export const STREAM_KIND_COMPUTER = 4;
|
|
20
24
|
/** `StreamRole.STREAM_ROLE_CLIENT` (agent-proto enum value). */
|
|
21
25
|
export const STREAM_ROLE_CLIENT = 2;
|
|
22
26
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sandbox is available for new I/O only after a holder has observed `warm`.
|
|
3
|
+
*
|
|
4
|
+
* `draining` means the holder count is zero and teardown owns the provider
|
|
5
|
+
* instance. The provider may disappear before the durable lease reaches `cold`,
|
|
6
|
+
* so treating `draining` as live races capture/termination. Explicit user intent
|
|
7
|
+
* reacquires a holder; only its subsequent `warm` state re-enables live I/O.
|
|
8
|
+
*/
|
|
9
|
+
export function sandboxAcceptsLiveIo(liveness: string | null | undefined): boolean {
|
|
10
|
+
return liveness === "warm";
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TerminalCapability } from "@opengeni/sdk";
|
|
2
|
+
|
|
3
|
+
/** Whether an explicit viewer grant can upgrade this cell to a real PTY.
|
|
4
|
+
* Keep acquisition feasibility separate from the current transport: a cold
|
|
5
|
+
* real-PTY backend reports sse-events until the just-in-time grant warms it. */
|
|
6
|
+
export function terminalCanAcquirePty(cell: TerminalCapability | null | undefined): boolean {
|
|
7
|
+
if (!cell?.ptyCapable) return false;
|
|
8
|
+
if (cell.transport === "pty-ws") return true;
|
|
9
|
+
return cell.reason === "lease_cold" || cell.reason === "not_provisioned";
|
|
10
|
+
}
|
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type CSSProperties,
|
|
3
|
+
type RefCallback,
|
|
4
|
+
type RefObject,
|
|
5
|
+
useCallback,
|
|
6
|
+
useEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from "react";
|
|
10
|
+
import { useComposerResponsiveContext } from "./composer-responsive-context";
|
|
2
11
|
|
|
3
|
-
export type PortalTokenStyle = CSSProperties &
|
|
12
|
+
export type PortalTokenStyle = Pick<CSSProperties, "colorScheme"> &
|
|
13
|
+
Partial<Record<`--${string}`, string>>;
|
|
14
|
+
|
|
15
|
+
export const PORTAL_SOURCE_INLINE_SIZE = "--og-portal-source-inline-size";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A callback ref that publishes the currently mounted source element through
|
|
19
|
+
* React state. Unlike a bare mutable ref, late mounts and replacements cause
|
|
20
|
+
* consumers to render and restart their observers without polling.
|
|
21
|
+
*/
|
|
22
|
+
export function usePortalTokenSource<T extends HTMLElement>(): {
|
|
23
|
+
source: T | null;
|
|
24
|
+
currentRef: RefObject<T | null>;
|
|
25
|
+
ref: RefCallback<T>;
|
|
26
|
+
} {
|
|
27
|
+
const currentRef = useRef<T | null>(null);
|
|
28
|
+
const [source, setSource] = useState<T | null>(null);
|
|
29
|
+
const ref = useCallback<RefCallback<T>>((node) => {
|
|
30
|
+
currentRef.current = node;
|
|
31
|
+
setSource((current) => (current === node ? current : node));
|
|
32
|
+
}, []);
|
|
33
|
+
return { source, currentRef, ref };
|
|
34
|
+
}
|
|
4
35
|
|
|
5
36
|
/**
|
|
6
37
|
* Copy the effective SDK tokens across a portal boundary. A locally themed or
|
|
@@ -8,11 +39,13 @@ export type PortalTokenStyle = CSSProperties & Record<`--${string}`, string>;
|
|
|
8
39
|
* `<body>`. Ancestor theme/class/style mutations and OS color-scheme changes
|
|
9
40
|
* keep the copied values live.
|
|
10
41
|
*/
|
|
11
|
-
export function usePortalTokenStyle(
|
|
42
|
+
export function usePortalTokenStyle(source: HTMLElement | null): PortalTokenStyle {
|
|
43
|
+
const responsiveContext = useComposerResponsiveContext();
|
|
12
44
|
const [style, setStyle] = useState<PortalTokenStyle>({});
|
|
13
45
|
useEffect(() => {
|
|
14
|
-
|
|
15
|
-
|
|
46
|
+
if (!source || typeof window === "undefined") return;
|
|
47
|
+
const layoutSource =
|
|
48
|
+
responsiveContext?.responsiveBasis === "container" ? responsiveContext.rootRef.current : null;
|
|
16
49
|
let signature = "";
|
|
17
50
|
const sync = () => {
|
|
18
51
|
const computed = getComputedStyle(source);
|
|
@@ -22,6 +55,12 @@ export function usePortalTokenStyle(sourceRef: RefObject<HTMLElement | null>): P
|
|
|
22
55
|
if (!property.startsWith("--og-")) continue;
|
|
23
56
|
next[property as `--${string}`] = computed.getPropertyValue(property);
|
|
24
57
|
}
|
|
58
|
+
if (layoutSource) {
|
|
59
|
+
const inlineSize = layoutSource.clientWidth || layoutSource.getBoundingClientRect().width;
|
|
60
|
+
if (inlineSize > 0) {
|
|
61
|
+
next[PORTAL_SOURCE_INLINE_SIZE] = `${Math.round(inlineSize * 1000) / 1000}px`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
25
64
|
const nextSignature = JSON.stringify(next);
|
|
26
65
|
if (nextSignature !== signature) {
|
|
27
66
|
signature = nextSignature;
|
|
@@ -29,23 +68,29 @@ export function usePortalTokenStyle(sourceRef: RefObject<HTMLElement | null>): P
|
|
|
29
68
|
}
|
|
30
69
|
};
|
|
31
70
|
const observers: MutationObserver[] = [];
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
71
|
+
if (typeof MutationObserver !== "undefined") {
|
|
72
|
+
let ancestor: HTMLElement | null = source;
|
|
73
|
+
while (ancestor) {
|
|
74
|
+
const observer = new MutationObserver(sync);
|
|
75
|
+
observer.observe(ancestor, {
|
|
76
|
+
attributes: true,
|
|
77
|
+
attributeFilter: ["class", "data-og-density", "data-og-theme", "style"],
|
|
78
|
+
});
|
|
79
|
+
observers.push(observer);
|
|
80
|
+
ancestor = ancestor.parentElement;
|
|
81
|
+
}
|
|
41
82
|
}
|
|
83
|
+
const resizeObserver =
|
|
84
|
+
layoutSource && typeof ResizeObserver !== "undefined" ? new ResizeObserver(sync) : null;
|
|
85
|
+
if (layoutSource) resizeObserver?.observe(layoutSource);
|
|
42
86
|
const colorScheme = window.matchMedia?.("(prefers-color-scheme: dark)");
|
|
43
87
|
colorScheme?.addEventListener?.("change", sync);
|
|
44
88
|
sync();
|
|
45
89
|
return () => {
|
|
46
90
|
for (const observer of observers) observer.disconnect();
|
|
91
|
+
resizeObserver?.disconnect();
|
|
47
92
|
colorScheme?.removeEventListener?.("change", sync);
|
|
48
93
|
};
|
|
49
|
-
}, [
|
|
94
|
+
}, [responsiveContext?.responsiveBasis, responsiveContext?.rootRef, source]);
|
|
50
95
|
return style;
|
|
51
96
|
}
|
package/src/provider.tsx
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "@opengeni/sdk";
|
|
7
7
|
import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
|
|
8
8
|
import type { SessionClientLike } from "./client";
|
|
9
|
+
import { usePageLiveActivity } from "./hooks/internal";
|
|
9
10
|
import { OpenGeniContext } from "./session-context";
|
|
10
11
|
|
|
11
12
|
export { useOpenGeni, useOpenGeniClient } from "./session-context";
|
|
@@ -40,6 +41,9 @@ export function OpenGeniProvider({
|
|
|
40
41
|
);
|
|
41
42
|
const callbackRef = useRef(onWorkspaceControlEvent);
|
|
42
43
|
const reconcilersRef = useRef(new Map<string, Map<string, () => Promise<void>>>());
|
|
44
|
+
const reconcileInFlightRef = useRef(new Map<string, Promise<void>>());
|
|
45
|
+
const workspaceControlSequencesRef = useRef(new Map<string, number>());
|
|
46
|
+
const pageLive = usePageLiveActivity();
|
|
43
47
|
callbackRef.current = onWorkspaceControlEvent;
|
|
44
48
|
|
|
45
49
|
const verifyApiContract = useCallback(async (): Promise<void> => {
|
|
@@ -76,31 +80,57 @@ export function OpenGeniProvider({
|
|
|
76
80
|
);
|
|
77
81
|
const reconcileSession = useMemo(
|
|
78
82
|
() =>
|
|
79
|
-
|
|
83
|
+
(sessionId: string): Promise<void> => {
|
|
84
|
+
const existing = reconcileInFlightRef.current.get(sessionId);
|
|
85
|
+
if (existing) return existing;
|
|
80
86
|
// This read also crosses the exact API-contract handshake before stale
|
|
81
87
|
// state can be presented as live after a deployment.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
const promise = (async () => {
|
|
89
|
+
await withTimeout(verifyApiContract(), 10_000, "API contract reconciliation");
|
|
90
|
+
const callbacks = [...(reconcilersRef.current.get(sessionId)?.values() ?? [])];
|
|
91
|
+
await withTimeout(
|
|
92
|
+
Promise.all(callbacks.map((reconcile) => reconcile())).then(() => undefined),
|
|
93
|
+
15_000,
|
|
94
|
+
"session reconciliation",
|
|
95
|
+
);
|
|
96
|
+
})().finally(() => {
|
|
97
|
+
if (reconcileInFlightRef.current.get(sessionId) === promise) {
|
|
98
|
+
reconcileInFlightRef.current.delete(sessionId);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
reconcileInFlightRef.current.set(sessionId, promise);
|
|
102
|
+
return promise;
|
|
85
103
|
},
|
|
86
104
|
[verifyApiContract],
|
|
87
105
|
);
|
|
88
106
|
|
|
89
107
|
useEffect(() => {
|
|
108
|
+
if (!pageLive) {
|
|
109
|
+
setWorkspaceControlConnectionState("idle");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
90
112
|
const controller = new AbortController();
|
|
91
|
-
setWorkspaceControlEvent(null);
|
|
92
113
|
setWorkspaceControlConnectionState("connecting");
|
|
93
114
|
void (async () => {
|
|
94
115
|
try {
|
|
95
116
|
await verifyApiContract();
|
|
96
117
|
const workspace = await client.getWorkspace(workspaceId);
|
|
118
|
+
const resumeAfter = Math.max(
|
|
119
|
+
workspaceControlSequencesRef.current.get(workspaceId) ?? 0,
|
|
120
|
+
workspace.inferenceControl.revision,
|
|
121
|
+
);
|
|
122
|
+
workspaceControlSequencesRef.current.set(workspaceId, resumeAfter);
|
|
97
123
|
const stream = client.streamWorkspaceControlEvents(workspaceId, {
|
|
98
|
-
after:
|
|
124
|
+
after: resumeAfter,
|
|
99
125
|
signal: controller.signal,
|
|
100
126
|
onStateChange: setWorkspaceControlConnectionState,
|
|
101
127
|
});
|
|
102
128
|
for await (const event of stream) {
|
|
103
129
|
if (controller.signal.aborted) return;
|
|
130
|
+
workspaceControlSequencesRef.current.set(
|
|
131
|
+
workspaceId,
|
|
132
|
+
Math.max(workspaceControlSequencesRef.current.get(workspaceId) ?? 0, event.sequence),
|
|
133
|
+
);
|
|
104
134
|
setWorkspaceControlEvent((current) =>
|
|
105
135
|
!current || event.sequence > current.sequence ? event : current,
|
|
106
136
|
);
|
|
@@ -115,7 +145,7 @@ export function OpenGeniProvider({
|
|
|
115
145
|
}
|
|
116
146
|
})();
|
|
117
147
|
return () => controller.abort();
|
|
118
|
-
}, [client, verifyApiContract, workspaceId]);
|
|
148
|
+
}, [client, pageLive, verifyApiContract, workspaceId]);
|
|
119
149
|
|
|
120
150
|
const value = useMemo(
|
|
121
151
|
() => ({
|
|
@@ -143,6 +173,21 @@ export function OpenGeniProvider({
|
|
|
143
173
|
);
|
|
144
174
|
}
|
|
145
175
|
|
|
176
|
+
function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {
|
|
177
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
178
|
+
return Promise.race([
|
|
179
|
+
promise,
|
|
180
|
+
new Promise<T>((_resolve, reject) => {
|
|
181
|
+
timer = setTimeout(
|
|
182
|
+
() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),
|
|
183
|
+
timeoutMs,
|
|
184
|
+
);
|
|
185
|
+
}),
|
|
186
|
+
]).finally(() => {
|
|
187
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
146
191
|
function ApiContractMismatchScreen({ mismatch }: { mismatch: OpenGeniApiContractMismatchError }) {
|
|
147
192
|
return (
|
|
148
193
|
<div
|
|
@@ -2,18 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import { ChevronRightIcon } from "lucide-react";
|
|
4
4
|
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
|
|
5
|
-
import {
|
|
6
|
-
createContext,
|
|
7
|
-
useContext,
|
|
8
|
-
useRef,
|
|
9
|
-
type ComponentProps,
|
|
10
|
-
type Ref,
|
|
11
|
-
type RefObject,
|
|
12
|
-
} from "react";
|
|
5
|
+
import { createContext, useContext, type ComponentProps, type Ref } from "react";
|
|
13
6
|
import { cn } from "../lib/cn";
|
|
14
|
-
import { usePortalTokenStyle } from "../lib/use-portal-token-style";
|
|
7
|
+
import { usePortalTokenSource, usePortalTokenStyle } from "../lib/use-portal-token-style";
|
|
15
8
|
|
|
16
|
-
|
|
9
|
+
type DropdownMenuSourceContextValue = {
|
|
10
|
+
source: HTMLElement | null;
|
|
11
|
+
ref: (node: HTMLElement | null) => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const DropdownMenuSourceContext = createContext<DropdownMenuSourceContextValue | null>(null);
|
|
17
15
|
|
|
18
16
|
function assignRef<T>(ref: Ref<T> | undefined, value: T | null) {
|
|
19
17
|
if (typeof ref === "function") ref(value);
|
|
@@ -21,9 +19,9 @@ function assignRef<T>(ref: Ref<T> | undefined, value: T | null) {
|
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
function DropdownMenu(props: ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
|
24
|
-
const
|
|
22
|
+
const source = usePortalTokenSource<HTMLElement>();
|
|
25
23
|
return (
|
|
26
|
-
<DropdownMenuSourceContext.Provider value={
|
|
24
|
+
<DropdownMenuSourceContext.Provider value={source}>
|
|
27
25
|
<DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
|
|
28
26
|
</DropdownMenuSourceContext.Provider>
|
|
29
27
|
);
|
|
@@ -38,7 +36,7 @@ function DropdownMenuTrigger({
|
|
|
38
36
|
<DropdownMenuPrimitive.Trigger
|
|
39
37
|
data-slot="dropdown-menu-trigger"
|
|
40
38
|
ref={(node) => {
|
|
41
|
-
|
|
39
|
+
sourceRef?.ref(node);
|
|
42
40
|
assignRef(ref, node);
|
|
43
41
|
}}
|
|
44
42
|
{...props}
|
|
@@ -52,9 +50,8 @@ function DropdownMenuContent({
|
|
|
52
50
|
style,
|
|
53
51
|
...props
|
|
54
52
|
}: ComponentProps<typeof DropdownMenuPrimitive.Content>) {
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const portalStyle = usePortalTokenStyle(sourceRef ?? fallbackRef);
|
|
53
|
+
const source = useContext(DropdownMenuSourceContext);
|
|
54
|
+
const portalStyle = usePortalTokenStyle(source?.source ?? null);
|
|
58
55
|
return (
|
|
59
56
|
<DropdownMenuPrimitive.Portal>
|
|
60
57
|
<DropdownMenuPrimitive.Content
|
|
@@ -138,9 +135,8 @@ function DropdownMenuSubContent({
|
|
|
138
135
|
style,
|
|
139
136
|
...props
|
|
140
137
|
}: ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
const portalStyle = usePortalTokenStyle(sourceRef ?? fallbackRef);
|
|
138
|
+
const source = useContext(DropdownMenuSourceContext);
|
|
139
|
+
const portalStyle = usePortalTokenStyle(source?.source ?? null);
|
|
144
140
|
return (
|
|
145
141
|
<DropdownMenuPrimitive.SubContent
|
|
146
142
|
data-slot="dropdown-menu-sub-content"
|
|
@@ -297,6 +297,13 @@ export function SessionRealtimeControl(props: {
|
|
|
297
297
|
onRealtimeAutostartConsumed?: (() => void) | undefined;
|
|
298
298
|
/** Host hides dictate (and can choreograph layout) while realtime voice is live. */
|
|
299
299
|
onVoiceActiveChange?: ((active: boolean) => void) | undefined;
|
|
300
|
+
/**
|
|
301
|
+
* `split` attaches the model chevron at every breakpoint (public default).
|
|
302
|
+
* `split-desktop` hides it below `sm` when the host owns mobile selection.
|
|
303
|
+
* Inside a container-responsive Composer.Root, `sm` follows that composer.
|
|
304
|
+
* `none` never attaches a model menu to the bar button.
|
|
305
|
+
*/
|
|
306
|
+
modelMenu?: "split" | "split-desktop" | "none" | undefined;
|
|
300
307
|
/** Deterministic browser-test/demo seam. Production hosts should use the SDK default. */
|
|
301
308
|
controllerFactory?: SessionRealtimeControllerFactory | undefined;
|
|
302
309
|
}) {
|
|
@@ -365,6 +372,7 @@ export function SessionRealtimeControl(props: {
|
|
|
365
372
|
admissionBlocker={realtime.admissionBlocker}
|
|
366
373
|
modelAvailable={selectedModel.available}
|
|
367
374
|
menuSide="top"
|
|
375
|
+
modelMenu={props.modelMenu ?? "split"}
|
|
368
376
|
audioRef={realtime.audioRef}
|
|
369
377
|
selectedModel={selectedModel}
|
|
370
378
|
models={selection.models}
|
|
@@ -475,6 +483,7 @@ export function NewSessionRealtimeControl(props: {
|
|
|
475
483
|
/**
|
|
476
484
|
* `split` attaches the model chevron at every breakpoint (public default).
|
|
477
485
|
* `split-desktop` hides it below `sm` when the host owns mobile selection (e.g. “+”).
|
|
486
|
+
* Inside a container-responsive Composer.Root, `sm` follows that composer.
|
|
478
487
|
* `none` never attaches a model menu to the bar button.
|
|
479
488
|
*/
|
|
480
489
|
modelMenu?: "split" | "split-desktop" | "none" | undefined;
|
|
@@ -556,6 +565,7 @@ export function RealtimeVoiceControl(props: {
|
|
|
556
565
|
/**
|
|
557
566
|
* `split` = start + model chevron at every breakpoint (public SDK default).
|
|
558
567
|
* `split-desktop` = chevron from `sm` up; below that the host owns selection.
|
|
568
|
+
* Inside a container-responsive Composer.Root, `sm` follows that composer.
|
|
559
569
|
* `none` = start button only.
|
|
560
570
|
*/
|
|
561
571
|
modelMenu?: "split" | "split-desktop" | "none" | undefined;
|
|
@@ -632,7 +642,8 @@ export function RealtimeVoiceControl(props: {
|
|
|
632
642
|
role="group"
|
|
633
643
|
aria-label="Realtime voice"
|
|
634
644
|
data-picker-side={props.menuSide ?? "top"}
|
|
635
|
-
|
|
645
|
+
data-model-menu={modelMenu}
|
|
646
|
+
className="og-realtime-control inline-flex shrink-0 items-center"
|
|
636
647
|
>
|
|
637
648
|
<audio ref={props.audioRef} autoPlay className="hidden" aria-hidden="true" />
|
|
638
649
|
<RealtimeComposerGlow phase={status.phase} reduceMotion={reduceMotion === true} />
|
|
@@ -719,7 +730,7 @@ export function RealtimeVoiceControl(props: {
|
|
|
719
730
|
// Match transcription mic: ghost icon when idle; filled only when live.
|
|
720
731
|
// Public contract: coarse pointers keep a 44px target; split menu uses
|
|
721
732
|
// left-only rounding at `sm+` where the chevron attaches.
|
|
722
|
-
"relative inline-flex size-8 items-center justify-center outline-
|
|
733
|
+
"og-realtime-primary relative inline-flex size-8 items-center justify-center outline-hidden",
|
|
723
734
|
"rounded-og-md transition-[background-color,border-color,color,box-shadow] duration-200 ease-og-out",
|
|
724
735
|
"focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-og-accent/45",
|
|
725
736
|
"disabled:cursor-not-allowed disabled:opacity-45 pointer-coarse:size-11",
|
|
@@ -748,7 +759,7 @@ export function RealtimeVoiceControl(props: {
|
|
|
748
759
|
className={cn(
|
|
749
760
|
// Keep the split trigger compact on desktop while preserving a
|
|
750
761
|
// full 44px mobile target independent of pointer-media support.
|
|
751
|
-
"inline-flex h-11 w-11 items-center justify-center rounded-r-og-md outline-
|
|
762
|
+
"og-realtime-model-trigger inline-flex h-11 w-11 items-center justify-center rounded-r-og-md outline-hidden sm:h-8 sm:w-6",
|
|
752
763
|
"transition-[background-color,border-color,color] duration-200 ease-og-out",
|
|
753
764
|
"focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-og-accent/45",
|
|
754
765
|
desktopOnlyModelMenu && "hidden sm:inline-flex",
|
|
@@ -763,7 +774,7 @@ export function RealtimeVoiceControl(props: {
|
|
|
763
774
|
align="end"
|
|
764
775
|
sideOffset={8}
|
|
765
776
|
collisionPadding={12}
|
|
766
|
-
className="flex w-72 max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height))] flex-col overflow-hidden rounded-xl border-border bg-surface p-1.5 shadow-xl"
|
|
777
|
+
className="og-realtime-menu flex w-72 max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height))] flex-col overflow-hidden rounded-xl border-border bg-surface p-1.5 shadow-xl"
|
|
767
778
|
onCloseAutoFocus={(event) => event.preventDefault()}
|
|
768
779
|
>
|
|
769
780
|
<div className="min-h-0 flex-1 overflow-y-auto overscroll-contain">
|
|
@@ -931,7 +942,7 @@ function RealtimeMuteButton(props: {
|
|
|
931
942
|
{...(props.reduceMotion ? {} : { whileTap: { scale: 0.92 } })}
|
|
932
943
|
onClick={props.onToggle}
|
|
933
944
|
className={cn(
|
|
934
|
-
"inline-flex size-8 shrink-0 items-center justify-center rounded-og-md outline-
|
|
945
|
+
"inline-flex size-8 shrink-0 items-center justify-center rounded-og-md outline-hidden",
|
|
935
946
|
"transition-[background-color,border-color,color] duration-150 ease-og-out",
|
|
936
947
|
"focus-visible:ring-2 focus-visible:ring-og-accent/45 pointer-coarse:size-11",
|
|
937
948
|
props.muted
|
package/src/session-context.ts
CHANGED
|
@@ -4,6 +4,9 @@ import type {
|
|
|
4
4
|
EmbeddedFileAttachmentClientLike,
|
|
5
5
|
EmbeddedGoalClientLike,
|
|
6
6
|
EmbeddedHumanInputSessionClientLike,
|
|
7
|
+
EmbeddedBrowserInteractionClientLike,
|
|
8
|
+
EmbeddedComputerInteractionClientLike,
|
|
9
|
+
EmbeddedInteractionClientLike,
|
|
7
10
|
EmbeddedRealtimeSessionClientLike,
|
|
8
11
|
EmbeddedSessionClientLike,
|
|
9
12
|
EmbeddedSessionLineageClientLike,
|
|
@@ -76,6 +79,21 @@ export type EmbeddedFileAttachmentClientOverride = {
|
|
|
76
79
|
workspaceId?: string | undefined;
|
|
77
80
|
};
|
|
78
81
|
|
|
82
|
+
export type EmbeddedInteractionClientOverride = {
|
|
83
|
+
client?: EmbeddedInteractionClientLike | undefined;
|
|
84
|
+
workspaceId?: string | undefined;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export type EmbeddedBrowserInteractionClientOverride = {
|
|
88
|
+
client?: EmbeddedBrowserInteractionClientLike | undefined;
|
|
89
|
+
workspaceId?: string | undefined;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export type EmbeddedComputerInteractionClientOverride = {
|
|
93
|
+
client?: EmbeddedComputerInteractionClientLike | undefined;
|
|
94
|
+
workspaceId?: string | undefined;
|
|
95
|
+
};
|
|
96
|
+
|
|
79
97
|
export type EmbeddedSessionContextValue = Omit<OpenGeniContextValue, "client"> & {
|
|
80
98
|
client: EmbeddedSessionClientLike;
|
|
81
99
|
};
|
|
@@ -145,6 +163,78 @@ export function useOpenGeni(override: ClientOverride = {}): OpenGeniContextValue
|
|
|
145
163
|
};
|
|
146
164
|
}
|
|
147
165
|
|
|
166
|
+
const BROWSER_INTERACTION_METHODS = [
|
|
167
|
+
"listAttachedBrowsers",
|
|
168
|
+
"getAttachedBrowser",
|
|
169
|
+
"listBrowserIdentities",
|
|
170
|
+
"getBrowserIdentity",
|
|
171
|
+
"createBrowserIdentity",
|
|
172
|
+
"listBrowserRevisions",
|
|
173
|
+
"listBrowserSessions",
|
|
174
|
+
"getBrowserSession",
|
|
175
|
+
"createBrowserSession",
|
|
176
|
+
"listBrowserTargets",
|
|
177
|
+
"openBrowserTarget",
|
|
178
|
+
"selectBrowserTarget",
|
|
179
|
+
"closeBrowserTarget",
|
|
180
|
+
"observeBrowserTarget",
|
|
181
|
+
"actInBrowser",
|
|
182
|
+
"getBrowserActionReceipt",
|
|
183
|
+
"listBrowserDiagnostics",
|
|
184
|
+
"attachBrowserSession",
|
|
185
|
+
"heartbeatBrowserSession",
|
|
186
|
+
"publishBrowserRevision",
|
|
187
|
+
"suspendBrowserSession",
|
|
188
|
+
"resumeBrowserSession",
|
|
189
|
+
"endBrowserSession",
|
|
190
|
+
] as const;
|
|
191
|
+
|
|
192
|
+
const COMPUTER_INTERACTION_METHODS = [
|
|
193
|
+
"listComputerSessions",
|
|
194
|
+
"getComputerSession",
|
|
195
|
+
"createComputerSession",
|
|
196
|
+
"listComputerTargets",
|
|
197
|
+
"observeComputerTarget",
|
|
198
|
+
"actInComputer",
|
|
199
|
+
"getComputerActionReceipt",
|
|
200
|
+
"attachComputerSession",
|
|
201
|
+
"heartbeatComputerSession",
|
|
202
|
+
"endComputerSession",
|
|
203
|
+
] as const;
|
|
204
|
+
|
|
205
|
+
/** Resolve only BrowserSession methods for a standalone Browser embed. */
|
|
206
|
+
export function useEmbeddedBrowserInteraction(
|
|
207
|
+
override: EmbeddedBrowserInteractionClientOverride = {},
|
|
208
|
+
): EmbeddedClientContextValue<EmbeddedBrowserInteractionClientLike> {
|
|
209
|
+
return useEmbeddedClientRefinement(
|
|
210
|
+
override,
|
|
211
|
+
BROWSER_INTERACTION_METHODS,
|
|
212
|
+
"browser interaction hooks",
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Resolve only ComputerSession methods for a standalone Computer embed. */
|
|
217
|
+
export function useEmbeddedComputerInteraction(
|
|
218
|
+
override: EmbeddedComputerInteractionClientOverride = {},
|
|
219
|
+
): EmbeddedClientContextValue<EmbeddedComputerInteractionClientLike> {
|
|
220
|
+
return useEmbeddedClientRefinement(
|
|
221
|
+
override,
|
|
222
|
+
COMPUTER_INTERACTION_METHODS,
|
|
223
|
+
"computer interaction hooks",
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Resolve the complete Browser + Computer client surface. */
|
|
228
|
+
export function useEmbeddedInteraction(
|
|
229
|
+
override: EmbeddedInteractionClientOverride = {},
|
|
230
|
+
): EmbeddedClientContextValue<EmbeddedInteractionClientLike> {
|
|
231
|
+
return useEmbeddedClientRefinement(
|
|
232
|
+
override,
|
|
233
|
+
[...BROWSER_INTERACTION_METHODS, ...COMPUTER_INTERACTION_METHODS],
|
|
234
|
+
"interaction hooks",
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
148
238
|
/**
|
|
149
239
|
* Resolve the narrow client required by the session-only hooks. The full
|
|
150
240
|
* provider client is structurally compatible, while an explicit host proxy
|
|
@@ -12,9 +12,9 @@ import { cn } from "../lib/cn";
|
|
|
12
12
|
import { truncate } from "../lib/format";
|
|
13
13
|
import { defaultToolRegistry } from "./tool-renderers";
|
|
14
14
|
import { useEntranceAnimation, useEntranceAnimationLive } from "./entrance";
|
|
15
|
-
import type { ToolRegistry } from "./registry";
|
|
15
|
+
import type { RetainedArtifactLoader, RetainedScreenshotLoader, ToolRegistry } from "./registry";
|
|
16
16
|
import { useSeenActivityIds } from "./seen-activity-ids";
|
|
17
|
-
import { BodyNote, PayloadBlock, ActivityDisclosure } from "./shared";
|
|
17
|
+
import { BodyNote, PayloadBlock, ActivityDisclosure, ToolCallTruncationProvider } from "./shared";
|
|
18
18
|
import { toolDisplayName } from "./tool-display-name";
|
|
19
19
|
import type { ActivityItem, MemoryItem, ReasoningItem, SandboxItem, WorkerItem } from "./types";
|
|
20
20
|
|
|
@@ -43,6 +43,9 @@ export type ActivityRailProps = {
|
|
|
43
43
|
* row is then non-interactive rich content). See {@link MessageTimelineProps}.
|
|
44
44
|
*/
|
|
45
45
|
onMemoryClick?: ((memoryId: string) => void) | undefined;
|
|
46
|
+
loadRetainedScreenshot?: RetainedScreenshotLoader | undefined;
|
|
47
|
+
/** Resolve permanent generated-image receipts through the authenticated host SDK. */
|
|
48
|
+
loadRetainedArtifact?: RetainedArtifactLoader | undefined;
|
|
46
49
|
/** Drop the left rule + indent (used inside a folded turn summary). */
|
|
47
50
|
bare?: boolean | undefined;
|
|
48
51
|
className?: string | undefined;
|
|
@@ -65,6 +68,8 @@ export function ActivityRail({
|
|
|
65
68
|
toolRegistry = defaultToolRegistry,
|
|
66
69
|
onOpenSession,
|
|
67
70
|
onMemoryClick,
|
|
71
|
+
loadRetainedScreenshot,
|
|
72
|
+
loadRetainedArtifact,
|
|
68
73
|
bare,
|
|
69
74
|
className,
|
|
70
75
|
}: ActivityRailProps) {
|
|
@@ -112,11 +117,21 @@ export function ActivityRail({
|
|
|
112
117
|
>
|
|
113
118
|
{items.map((item, index) => {
|
|
114
119
|
const newFamily = index > 0 && familyOf(item) !== familyOf(items[index - 1]!);
|
|
115
|
-
const row = renderActivity(
|
|
120
|
+
const row = renderActivity(
|
|
121
|
+
item,
|
|
122
|
+
toolRegistry,
|
|
123
|
+
onOpenSession,
|
|
124
|
+
onMemoryClick,
|
|
125
|
+
loadRetainedScreenshot,
|
|
126
|
+
loadRetainedArtifact,
|
|
127
|
+
);
|
|
116
128
|
return (
|
|
117
129
|
<div
|
|
118
130
|
key={item.id}
|
|
119
131
|
data-og-timeline-row-anchor=""
|
|
132
|
+
data-og-annotation-source-key={
|
|
133
|
+
item.kind === "tool-call" ? item.annotationSource?.eventId : undefined
|
|
134
|
+
}
|
|
120
135
|
className={cn(newFamily && "mt-3", enteringIds.has(item.id) && "animate-og-row-enter")}
|
|
121
136
|
>
|
|
122
137
|
{row}
|
|
@@ -137,13 +152,23 @@ function renderActivity(
|
|
|
137
152
|
toolRegistry: ToolRegistry,
|
|
138
153
|
onOpenSession: ((sessionId: string) => void) | undefined,
|
|
139
154
|
onMemoryClick: ((memoryId: string) => void) | undefined,
|
|
155
|
+
loadRetainedScreenshot: RetainedScreenshotLoader | undefined,
|
|
156
|
+
loadRetainedArtifact: RetainedArtifactLoader | undefined,
|
|
140
157
|
) {
|
|
141
158
|
switch (item.kind) {
|
|
142
159
|
case "reasoning":
|
|
143
160
|
return <ReasoningRow item={item} />;
|
|
144
161
|
case "tool-call": {
|
|
145
162
|
const Renderer = toolRegistry.resolve(item);
|
|
146
|
-
return
|
|
163
|
+
return (
|
|
164
|
+
<ToolCallTruncationProvider value={item.truncation ?? null}>
|
|
165
|
+
<Renderer
|
|
166
|
+
item={item}
|
|
167
|
+
loadRetainedScreenshot={loadRetainedScreenshot}
|
|
168
|
+
loadRetainedArtifact={loadRetainedArtifact}
|
|
169
|
+
/>
|
|
170
|
+
</ToolCallTruncationProvider>
|
|
171
|
+
);
|
|
147
172
|
}
|
|
148
173
|
case "worker":
|
|
149
174
|
return <WorkerRow item={item} onOpenSession={onOpenSession} />;
|
|
@@ -281,7 +306,7 @@ function MemoryRow({
|
|
|
281
306
|
onClick={() => onMemoryClick?.(targetId)}
|
|
282
307
|
className={cn(
|
|
283
308
|
"group/memlink -mx-1 inline-flex w-fit items-center gap-1 rounded-og-sm px-1 py-0.5 text-left text-og-sm text-og-fg-subtle",
|
|
284
|
-
"outline-
|
|
309
|
+
"outline-hidden transition-colors duration-150 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent",
|
|
285
310
|
)}
|
|
286
311
|
>
|
|
287
312
|
View in memory
|
|
@@ -418,7 +443,7 @@ function WorkerRow({
|
|
|
418
443
|
onClick={() => onOpenSession(sessionId)}
|
|
419
444
|
className={cn(
|
|
420
445
|
"group/worker -mx-1.5 flex w-full items-start gap-2 rounded-og-sm px-1.5 py-1.5 text-left",
|
|
421
|
-
"outline-
|
|
446
|
+
"outline-hidden transition-colors duration-150 hover:bg-og-surface-1 focus-visible:ring-2 focus-visible:ring-og-accent",
|
|
422
447
|
"pointer-coarse:min-h-11 pointer-coarse:py-2.5",
|
|
423
448
|
)}
|
|
424
449
|
>
|
package/src/timeline/index.ts
CHANGED
|
@@ -45,6 +45,7 @@ export type {
|
|
|
45
45
|
SessionStatusItem,
|
|
46
46
|
TimelineGroup,
|
|
47
47
|
TimelineItem,
|
|
48
|
+
TimelineAnnotationSourceDescriptor,
|
|
48
49
|
TurnEndItem,
|
|
49
50
|
ToolCallItem,
|
|
50
51
|
UserMessageItem,
|
|
@@ -56,6 +57,9 @@ export type {
|
|
|
56
57
|
export { createToolRegistry, rawTypeOf } from "./registry";
|
|
57
58
|
export type {
|
|
58
59
|
CreateToolRegistryOptions,
|
|
60
|
+
RetainedArtifactLoader,
|
|
61
|
+
RetainedScreenshotLoader,
|
|
62
|
+
VideoArtifactPlaybackLoader,
|
|
59
63
|
ToolRegistry,
|
|
60
64
|
ToolRegistryEntry,
|
|
61
65
|
ToolRenderer,
|
|
@@ -123,7 +127,6 @@ export {
|
|
|
123
127
|
looksBinary,
|
|
124
128
|
parseExecBannerSessionId,
|
|
125
129
|
parseToolArgs,
|
|
126
|
-
redactSecrets,
|
|
127
130
|
sandboxCommandExitCode,
|
|
128
131
|
stripExecBanner,
|
|
129
132
|
tailPeek,
|