@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
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
GitFileDiff,
|
|
3
|
+
SessionCapabilities,
|
|
3
4
|
SessionEvent,
|
|
4
5
|
WorkspaceCaptureManifest,
|
|
5
6
|
WorkspaceCaptureRepo,
|
|
6
7
|
} from "@opengeni/sdk";
|
|
7
8
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
8
|
-
import {
|
|
9
|
+
import { type ClientOverride, useOpenGeni } from "../provider";
|
|
10
|
+
import { sandboxAcceptsLiveIo } from "../lib/sandbox-liveness";
|
|
9
11
|
|
|
10
12
|
export type UseSandboxGitOptions = ClientOverride & {
|
|
11
13
|
/** Live event log (usually `useSessionEvents().events`) — drives auto-refresh
|
|
@@ -18,21 +20,32 @@ export type UseSandboxGitOptions = ClientOverride & {
|
|
|
18
20
|
repoPaths?: readonly string[] | undefined;
|
|
19
21
|
/** Diff the staged index vs HEAD (`--cached`) instead of the working tree. */
|
|
20
22
|
staged?: boolean | undefined;
|
|
23
|
+
/** Review scope. `branch` compares the current branch with the remote default
|
|
24
|
+
* branch, `working` shows uncommitted edits, and `staged` shows the index.
|
|
25
|
+
* `staged` above remains as a compatibility alias. */
|
|
26
|
+
comparison?: SandboxGitComparison | undefined;
|
|
21
27
|
/** Hold off the initial fetch. Default true. */
|
|
22
28
|
enabled?: boolean | undefined;
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
liveness
|
|
29
|
+
/** Pause live reads/invalidation while preserving the last rendered result. */
|
|
30
|
+
active?: boolean | undefined;
|
|
31
|
+
/** Lease liveness. `null` means capability negotiation is still pending and
|
|
32
|
+
* blocks live I/O. When not warm, the diff is served from the capture instead
|
|
33
|
+
* of a live `gitDiff` RPC. Omission preserves legacy direct-hook behavior. */
|
|
34
|
+
liveness?: SessionCapabilities["liveness"] | null | undefined;
|
|
26
35
|
/** The latest turn-end capture (from `useWorkspaceCapture`). Seeds the diff
|
|
27
36
|
* immediately; a warm box reconciles live and leaves this durable review
|
|
28
37
|
* surface in place if the live request is temporarily unavailable. */
|
|
29
38
|
capture?: WorkspaceCaptureManifest | null | undefined;
|
|
30
39
|
};
|
|
31
40
|
|
|
41
|
+
export type SandboxGitComparison = "branch" | "working" | "staged";
|
|
42
|
+
|
|
32
43
|
/** A Git diff qualified into workspace scope. `repoRoot` is present for the
|
|
33
44
|
* workspace-wide path and lets review UI group real repositories without
|
|
34
45
|
* guessing from the first path segment. */
|
|
35
|
-
export type SandboxGitFileDiff = GitFileDiff & {
|
|
46
|
+
export type SandboxGitFileDiff = GitFileDiff & {
|
|
47
|
+
repoRoot?: string | undefined;
|
|
48
|
+
};
|
|
36
49
|
|
|
37
50
|
export type UseSandboxGitResult = {
|
|
38
51
|
/** Working-tree (or staged) diff vs HEAD — the structured hunks the Pierre
|
|
@@ -83,6 +96,11 @@ function uniqueRoots(roots: readonly string[]): string[] {
|
|
|
83
96
|
return [...new Set(roots.map(normalizeRoot))].sort((a, b) => a.localeCompare(b));
|
|
84
97
|
}
|
|
85
98
|
|
|
99
|
+
// GitReadBatchRequest is contract-bounded to 32 items. Keep workspace-wide
|
|
100
|
+
// reads bounded without changing the wire limit; sequential chunks preserve
|
|
101
|
+
// deterministic root/result mapping and cap Channel-A lease concurrency at one.
|
|
102
|
+
const GIT_READ_BATCH_REQUEST_LIMIT = 32;
|
|
103
|
+
|
|
86
104
|
/** Find the capture repo matching `repoPath` (default workspace root). */
|
|
87
105
|
function repoForPath(
|
|
88
106
|
manifest: WorkspaceCaptureManifest,
|
|
@@ -175,6 +193,7 @@ export function useSandboxGit(
|
|
|
175
193
|
): UseSandboxGitResult {
|
|
176
194
|
const { client, workspaceId } = useOpenGeni(options);
|
|
177
195
|
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
196
|
+
const active = options.active ?? true;
|
|
178
197
|
const repoPath = options.repoPath ?? "";
|
|
179
198
|
const workspaceWide = options.repoPaths !== undefined;
|
|
180
199
|
// Serialize the caller's array so inline values do not retrigger effects. An
|
|
@@ -183,10 +202,21 @@ export function useSandboxGit(
|
|
|
183
202
|
options.repoPaths && options.repoPaths.length > 0 ? options.repoPaths : [repoPath],
|
|
184
203
|
).join("\u0000");
|
|
185
204
|
const repoPaths = useMemo(() => repoPathsKey.split("\u0000"), [repoPathsKey]);
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
205
|
+
const comparison: SandboxGitComparison =
|
|
206
|
+
options.comparison ?? (options.staged ? "staged" : "working");
|
|
207
|
+
const hasAdvertisedRepoPaths = (options.repoPaths?.length ?? 0) > 0;
|
|
208
|
+
// New captures retain both working-tree and branch comparisons. Staged state
|
|
209
|
+
// remains live-only; legacy captures simply lack branchDiff and fall back via
|
|
210
|
+
// the workspace controller without inventing an empty branch comparison.
|
|
211
|
+
const capture = comparison === "staged" ? null : (options.capture ?? null);
|
|
212
|
+
const isLive = sandboxAcceptsLiveIo(options.liveness);
|
|
213
|
+
// `liveness` is optional for compatibility with direct hook consumers. Explicit
|
|
214
|
+
// `null` (negotiating) and lifecycle values require authoritative warm.
|
|
215
|
+
const acceptsEventReads = options.liveness === undefined || isLive;
|
|
216
|
+
const acceptsEventReadsRef = useRef(acceptsEventReads);
|
|
217
|
+
acceptsEventReadsRef.current = acceptsEventReads;
|
|
218
|
+
const hasLiveIoFence = options.liveness !== undefined;
|
|
219
|
+
const identityKey = `${workspaceId}\u0000${sessionId ?? ""}\u0000${repoPathsKey}\u0000${workspaceWide}\u0000${comparison}`;
|
|
190
220
|
|
|
191
221
|
const [diff, setDiff] = useState<SandboxGitFileDiff[]>([]);
|
|
192
222
|
const [branch, setBranch] = useState<string | null>(null);
|
|
@@ -204,6 +234,7 @@ export function useSandboxGit(
|
|
|
204
234
|
const refreshGenerationRef = useRef(0);
|
|
205
235
|
const refreshAbortRef = useRef<AbortController | null>(null);
|
|
206
236
|
const lastChangeRef = useRef(0);
|
|
237
|
+
const commandRefreshTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
207
238
|
|
|
208
239
|
const refresh = useCallback(async () => {
|
|
209
240
|
if (!sessionId) return;
|
|
@@ -214,17 +245,88 @@ export function useSandboxGit(
|
|
|
214
245
|
setLoading(true);
|
|
215
246
|
setError(null);
|
|
216
247
|
try {
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
248
|
+
const diffRequest = (root: string) =>
|
|
249
|
+
client.gitDiff(
|
|
250
|
+
workspaceId,
|
|
251
|
+
sessionId,
|
|
252
|
+
{
|
|
253
|
+
path: root,
|
|
254
|
+
...(comparison === "branch"
|
|
255
|
+
? { fromRef: "origin/HEAD", includeUntracked: true }
|
|
256
|
+
: comparison === "working"
|
|
257
|
+
? { fromRef: "HEAD", includeUntracked: true }
|
|
258
|
+
: { staged: true, includeUntracked: false }),
|
|
259
|
+
},
|
|
260
|
+
{ signal: refreshAbort.signal },
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
// Capability-advertised roots are known repositories. Fetch status metadata
|
|
264
|
+
// and diff hunks together: both are independent Channel-A reads and each can
|
|
265
|
+
// take several seconds on a remote sandbox. The legacy root probe remains
|
|
266
|
+
// serial so a non-repository workspace never receives a failing git diff.
|
|
267
|
+
const prefetched = hasAdvertisedRepoPaths
|
|
268
|
+
? await (async () => {
|
|
269
|
+
const prefetchedRepos: Array<{
|
|
270
|
+
root: string;
|
|
271
|
+
status: Awaited<ReturnType<typeof client.gitStatus>>;
|
|
272
|
+
result: Awaited<ReturnType<typeof client.gitDiff>>;
|
|
273
|
+
}> = [];
|
|
274
|
+
for (
|
|
275
|
+
let offset = 0;
|
|
276
|
+
offset < repoPaths.length;
|
|
277
|
+
offset += GIT_READ_BATCH_REQUEST_LIMIT
|
|
278
|
+
) {
|
|
279
|
+
const roots = repoPaths.slice(offset, offset + GIT_READ_BATCH_REQUEST_LIMIT);
|
|
280
|
+
const batch = await client.gitReadBatch(
|
|
281
|
+
workspaceId,
|
|
282
|
+
sessionId,
|
|
283
|
+
{
|
|
284
|
+
requests: roots.map((root) => ({
|
|
285
|
+
status: { path: root },
|
|
286
|
+
diff: {
|
|
287
|
+
path: root,
|
|
288
|
+
...(comparison === "branch"
|
|
289
|
+
? { fromRef: "origin/HEAD", includeUntracked: true }
|
|
290
|
+
: comparison === "working"
|
|
291
|
+
? { fromRef: "HEAD", includeUntracked: true }
|
|
292
|
+
: { staged: true, includeUntracked: false }),
|
|
293
|
+
},
|
|
294
|
+
})),
|
|
295
|
+
},
|
|
296
|
+
{ signal: refreshAbort.signal },
|
|
297
|
+
);
|
|
298
|
+
if (batch.results.length !== roots.length) {
|
|
299
|
+
throw new Error(
|
|
300
|
+
`Workspace Git batch returned ${batch.results.length} results for ${roots.length} repositories.`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
batch.results.forEach((item, index) => {
|
|
304
|
+
prefetchedRepos.push({
|
|
305
|
+
root: roots[index]!,
|
|
306
|
+
status: item.status,
|
|
307
|
+
result: item.diff ?? {
|
|
308
|
+
files: [],
|
|
309
|
+
revision: item.status.revision,
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
return prefetchedRepos;
|
|
315
|
+
})()
|
|
316
|
+
: null;
|
|
317
|
+
const statuses =
|
|
318
|
+
prefetched ??
|
|
319
|
+
(await Promise.all(
|
|
320
|
+
repoPaths.map(async (root) => ({
|
|
321
|
+
root,
|
|
322
|
+
status: await client.gitStatus(
|
|
323
|
+
workspaceId,
|
|
324
|
+
sessionId,
|
|
325
|
+
{ path: root },
|
|
326
|
+
{ signal: refreshAbort.signal },
|
|
327
|
+
),
|
|
328
|
+
})),
|
|
329
|
+
));
|
|
228
330
|
if (refreshGenerationRef.current !== generation) return;
|
|
229
331
|
const repositories = statuses.filter(({ status }) => status.isRepo);
|
|
230
332
|
const roots = repositories.map(({ root }) => root);
|
|
@@ -239,19 +341,11 @@ export function useSandboxGit(
|
|
|
239
341
|
setSource("live");
|
|
240
342
|
return;
|
|
241
343
|
}
|
|
344
|
+
const prefetchedByRoot = new Map(prefetched?.map(({ root, result }) => [root, result]));
|
|
242
345
|
const results = await Promise.all(
|
|
243
346
|
repositories.map(async ({ root }) => ({
|
|
244
347
|
root,
|
|
245
|
-
result: await
|
|
246
|
-
workspaceId,
|
|
247
|
-
sessionId,
|
|
248
|
-
{
|
|
249
|
-
path: root,
|
|
250
|
-
staged,
|
|
251
|
-
includeUntracked: !staged,
|
|
252
|
-
},
|
|
253
|
-
{ signal: refreshAbort.signal },
|
|
254
|
-
),
|
|
348
|
+
result: prefetchedByRoot.get(root) ?? (await diffRequest(root)),
|
|
255
349
|
})),
|
|
256
350
|
);
|
|
257
351
|
if (refreshGenerationRef.current !== generation) return;
|
|
@@ -273,15 +367,25 @@ export function useSandboxGit(
|
|
|
273
367
|
if (refreshGenerationRef.current === generation) setLoading(false);
|
|
274
368
|
if (refreshAbortRef.current === refreshAbort) refreshAbortRef.current = null;
|
|
275
369
|
}
|
|
276
|
-
}, [
|
|
370
|
+
}, [
|
|
371
|
+
client,
|
|
372
|
+
workspaceId,
|
|
373
|
+
sessionId,
|
|
374
|
+
repoPaths,
|
|
375
|
+
hasAdvertisedRepoPaths,
|
|
376
|
+
workspaceWide,
|
|
377
|
+
comparison,
|
|
378
|
+
]);
|
|
277
379
|
|
|
278
|
-
// Serve the
|
|
279
|
-
// meaning here: the capture records the combined turn-end change surface vs HEAD.
|
|
380
|
+
// Serve the requested review scope from a capture when that scope exists.
|
|
280
381
|
const seedFromCapture = useCallback(
|
|
281
382
|
(manifest: WorkspaceCaptureManifest) => {
|
|
282
383
|
const repositories = workspaceWide
|
|
283
384
|
? manifest.repos
|
|
284
385
|
: ([repoForPath(manifest, repoPath)].filter(Boolean) as WorkspaceCaptureRepo[]);
|
|
386
|
+
if (comparison === "branch" && repositories.some((repo) => repo.branchDiff === undefined)) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
285
389
|
if (repositories.length === 0) {
|
|
286
390
|
setIsRepo(false);
|
|
287
391
|
setBranch(null);
|
|
@@ -301,16 +405,19 @@ export function useSandboxGit(
|
|
|
301
405
|
setDiff((prev) =>
|
|
302
406
|
mergeDiffs(
|
|
303
407
|
prev,
|
|
304
|
-
repositories.flatMap((repo) =>
|
|
305
|
-
|
|
306
|
-
|
|
408
|
+
repositories.flatMap((repo) => {
|
|
409
|
+
const capturedDiff = comparison === "branch" ? (repo.branchDiff ?? []) : repo.diff;
|
|
410
|
+
return workspaceWide
|
|
411
|
+
? capturedDiff.map((file) => qualifyDiff(repo.root, file))
|
|
412
|
+
: capturedDiff;
|
|
413
|
+
}),
|
|
307
414
|
),
|
|
308
415
|
);
|
|
309
416
|
sourceRef.current = "capture";
|
|
310
417
|
setSource("capture");
|
|
311
418
|
setError(null);
|
|
312
419
|
},
|
|
313
|
-
[repoPath, workspaceWide],
|
|
420
|
+
[comparison, repoPath, workspaceWide],
|
|
314
421
|
);
|
|
315
422
|
|
|
316
423
|
// Source selection on mount / liveness / capture-revision change. Key on the
|
|
@@ -349,7 +456,11 @@ export function useSandboxGit(
|
|
|
349
456
|
if (currentCapture && (identityChanged || !isLive || sourceRef.current !== "live")) {
|
|
350
457
|
seedFromCapture(currentCapture);
|
|
351
458
|
}
|
|
352
|
-
if (
|
|
459
|
+
if (!active) {
|
|
460
|
+
if (!active) setLoading(false);
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
if (isLive || (!hasLiveIoFence && !currentCapture)) {
|
|
353
464
|
void refresh();
|
|
354
465
|
}
|
|
355
466
|
return () => {
|
|
@@ -357,25 +468,76 @@ export function useSandboxGit(
|
|
|
357
468
|
refreshAbortRef.current = null;
|
|
358
469
|
refreshGenerationRef.current += 1;
|
|
359
470
|
};
|
|
360
|
-
}, [
|
|
471
|
+
}, [
|
|
472
|
+
enabled,
|
|
473
|
+
active,
|
|
474
|
+
isLive,
|
|
475
|
+
hasLiveIoFence,
|
|
476
|
+
captureRevision,
|
|
477
|
+
identityKey,
|
|
478
|
+
refresh,
|
|
479
|
+
seedFromCapture,
|
|
480
|
+
]);
|
|
361
481
|
|
|
362
|
-
// git.changed → re-fetch the LIVE diff.
|
|
363
|
-
//
|
|
364
|
-
//
|
|
482
|
+
// git.changed → re-fetch the LIVE diff. Agent tool completion is also an
|
|
483
|
+
// invalidation point because shell/apply-patch writes can bypass Channel-A and
|
|
484
|
+
// therefore emit no git.changed event. This is event-driven, never polling.
|
|
365
485
|
const events = options.events;
|
|
366
486
|
useEffect(() => {
|
|
367
|
-
if (!enabled || !events)
|
|
487
|
+
if (!enabled || !events) {
|
|
488
|
+
if (commandRefreshTimerRef.current) {
|
|
489
|
+
clearTimeout(commandRefreshTimerRef.current);
|
|
490
|
+
commandRefreshTimerRef.current = null;
|
|
491
|
+
}
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
// Historical events describe the capture we already loaded. Inactive tabs
|
|
495
|
+
// and holderless draining/cold leases advance the cursor without issuing
|
|
496
|
+
// provider I/O; becoming warm performs one authoritative reconcile above.
|
|
497
|
+
if (!active || !acceptsEventReads) {
|
|
498
|
+
for (const event of events) {
|
|
499
|
+
if (event.sequence > lastChangeRef.current) lastChangeRef.current = event.sequence;
|
|
500
|
+
}
|
|
501
|
+
if (commandRefreshTimerRef.current) {
|
|
502
|
+
clearTimeout(commandRefreshTimerRef.current);
|
|
503
|
+
commandRefreshTimerRef.current = null;
|
|
504
|
+
}
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
368
507
|
let latest = lastChangeRef.current;
|
|
508
|
+
let immediate = false;
|
|
509
|
+
let commandDelta = false;
|
|
369
510
|
for (const event of events) {
|
|
370
|
-
if (event.
|
|
511
|
+
if (event.sequence <= latest) continue;
|
|
512
|
+
if (event.type === "git.changed" || event.type === "agent.toolCall.output") {
|
|
513
|
+
latest = event.sequence;
|
|
514
|
+
immediate = true;
|
|
515
|
+
} else if (event.type === "sandbox.command.output.delta") {
|
|
371
516
|
latest = event.sequence;
|
|
517
|
+
commandDelta = true;
|
|
372
518
|
}
|
|
373
519
|
}
|
|
374
520
|
if (latest > lastChangeRef.current) {
|
|
375
521
|
lastChangeRef.current = latest;
|
|
376
|
-
|
|
522
|
+
if (immediate) {
|
|
523
|
+
if (commandRefreshTimerRef.current) clearTimeout(commandRefreshTimerRef.current);
|
|
524
|
+
commandRefreshTimerRef.current = null;
|
|
525
|
+
if (acceptsEventReadsRef.current) void refresh();
|
|
526
|
+
} else if (commandDelta && !commandRefreshTimerRef.current) {
|
|
527
|
+
commandRefreshTimerRef.current = setTimeout(() => {
|
|
528
|
+
commandRefreshTimerRef.current = null;
|
|
529
|
+
if (acceptsEventReadsRef.current) void refresh();
|
|
530
|
+
}, 1_000);
|
|
531
|
+
}
|
|
377
532
|
}
|
|
378
|
-
}, [enabled, events, refresh]);
|
|
533
|
+
}, [enabled, active, acceptsEventReads, events, refresh]);
|
|
534
|
+
|
|
535
|
+
useEffect(
|
|
536
|
+
() => () => {
|
|
537
|
+
if (commandRefreshTimerRef.current) clearTimeout(commandRefreshTimerRef.current);
|
|
538
|
+
},
|
|
539
|
+
[],
|
|
540
|
+
);
|
|
379
541
|
|
|
380
542
|
const identityMatches = enabled && stateIdentity === identityKey;
|
|
381
543
|
const visibleRepoRoots = identityMatches ? repoRoots : [];
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
import { OpenGeniApiError } from "@opengeni/sdk";
|
|
8
8
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
9
9
|
import { useOpenGeni, type ClientOverride } from "../provider";
|
|
10
|
+
import { sandboxAcceptsLiveIo } from "../lib/sandbox-liveness";
|
|
10
11
|
|
|
11
12
|
export type TerminalChunk = {
|
|
12
13
|
/** Stable key (the source event id) so the xterm writer tracks a written-cursor. */
|
|
@@ -107,9 +108,9 @@ export function useSandboxTerminal(
|
|
|
107
108
|
// projection is the single source of truth for what's written). The open is
|
|
108
109
|
// gated on a WARM box: opening on a cold/warming lease races the box (the PTY
|
|
109
110
|
// exec-session is created on a box that the next op may not resume), which is
|
|
110
|
-
// exactly the "session not found" terminal failure; we wait for warm
|
|
111
|
+
// exactly the "session not found" terminal failure; we wait for warm.
|
|
111
112
|
const openInFlight = useRef(false);
|
|
112
|
-
const boxWarm = liveness === undefined || liveness
|
|
113
|
+
const boxWarm = liveness === undefined || sandboxAcceptsLiveIo(liveness);
|
|
113
114
|
useEffect(() => {
|
|
114
115
|
if (!interactive || !sessionId || ptyFilter || !boxWarm) {
|
|
115
116
|
setOpenError(null);
|