@opengeni/react 0.48.0 → 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 +90 -2
- 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-FWXGSNXT.js → chunk-724BW4TW.js} +585 -34
- 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-I4MPFDRP.js → chunk-FWS3KC3Z.js} +3 -3
- 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-XCNTXWBB.js → chunk-JAGDUCZQ.js} +854 -340
- package/dist/chunk-JAGDUCZQ.js.map +1 -0
- package/dist/{chunk-LHLYWG5R.js → chunk-JR3QFY6B.js} +413 -37
- 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-PEI6RANI.js +3234 -0
- package/dist/chunk-PEI6RANI.js.map +1 -0
- package/dist/{chunk-NJ7M2B6Z.js → chunk-ROIRTM37.js} +18 -10
- package/dist/{chunk-NJ7M2B6Z.js.map → chunk-ROIRTM37.js.map} +1 -1
- package/dist/{chunk-O4VXOBGF.js → chunk-WSK7G5LE.js} +70 -2
- package/dist/chunk-WSK7G5LE.js.map +1 -0
- package/dist/{chunk-OL6QVXGF.js → chunk-X4S56Y2H.js} +27 -7
- package/dist/{chunk-OL6QVXGF.js.map → chunk-X4S56Y2H.js.map} +1 -1
- 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 +8 -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 +2 -2
- package/dist/components/composer.d.ts +17 -17
- 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 +3 -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 +2 -2
- package/dist/components/markdown.d.ts +1 -1
- package/dist/components/message-timeline.d.ts +12 -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 +3 -3
- package/dist/components/sandbox-terminal.d.ts +21 -4
- package/dist/components/sandbox-workspace.d.ts +25 -9
- 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 +1 -1
- package/dist/composer.d.ts +11 -11
- package/dist/composer.js +5 -5
- package/dist/hooks/internal.d.ts +1 -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 +2 -2
- 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 +1 -1
- 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 +4 -4
- 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 +6 -4
- package/dist/hooks/use-sandbox-git.d.ts +6 -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-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 +1 -1
- 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 -155
- package/dist/index.js +906 -462
- 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/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/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-U5JFG7HT.js → queue-surface-implementation-2KVJTYXH.js} +100 -48
- 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 +6 -6
- package/dist/realtime.d.ts +4 -4
- package/dist/realtime.js +3 -3
- package/dist/session-context.d.ts +19 -1
- package/dist/session-ui.d.ts +14 -14
- package/dist/session-ui.js +5 -4
- package/dist/session.d.ts +28 -28
- package/dist/session.js +5 -5
- package/dist/timeline/activity-rail.d.ts +5 -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 +4 -1
- package/dist/timeline/projection.d.ts +3 -3
- package/dist/timeline/registry.d.ts +8 -2
- 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 +39 -3
- 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/package.json +36 -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 +87 -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 +13 -0
- package/src/components/code-editor.tsx +89 -30
- package/src/components/composer-transcription-control.tsx +10 -6
- package/src/components/computer-viewer.tsx +1139 -0
- package/src/components/desktop-viewer.tsx +101 -73
- package/src/components/generated-video-player.tsx +89 -0
- package/src/components/interactive-workbench-viewers.ts +2 -0
- package/src/components/machine-input-display.ts +3 -0
- package/src/components/message-timeline.tsx +289 -32
- package/src/components/queue-surface-implementation.tsx +116 -60
- package/src/components/sandbox-files.tsx +2 -2
- package/src/components/sandbox-terminal.tsx +106 -41
- package/src/components/sandbox-workspace.tsx +215 -87
- package/src/components/session-chrome.tsx +53 -13
- 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/workbench-changes.tsx +188 -31
- 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-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-machine-chip.ts +5 -3
- package/src/hooks/use-machines.ts +33 -3
- package/src/hooks/use-packs.ts +51 -0
- package/src/hooks/use-sandbox-files.ts +98 -55
- package/src/hooks/use-sandbox-git.ts +93 -38
- package/src/hooks/use-sandbox-terminal.ts +3 -2
- package/src/hooks/use-session-capabilities.ts +59 -46
- package/src/hooks/use-terminal-stream.ts +102 -23
- package/src/hooks/use-video-artifact-playback.ts +28 -0
- package/src/hooks/use-workspace-edit.ts +2 -1
- package/src/index.ts +10 -0
- package/src/interaction.ts +71 -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/session-context.ts +90 -0
- package/src/timeline/activity-rail.tsx +19 -3
- package/src/timeline/index.ts +3 -0
- package/src/timeline/parsers.ts +14 -1
- package/src/timeline/projection.ts +211 -14
- package/src/timeline/registry.ts +13 -1
- package/src/timeline/screenshot-lightbox.tsx +19 -9
- package/src/timeline/shared.tsx +56 -8
- package/src/timeline/tool-renderers.tsx +303 -50
- package/src/timeline/types.ts +55 -3
- package/styles/compiled.css +248 -15
- package/styles/index.css +15 -0
- package/styles/responsive.css +13 -1
- package/dist/chunk-EKZH6IDG.js.map +0 -1
- package/dist/chunk-FWXGSNXT.js.map +0 -1
- package/dist/chunk-LHLYWG5R.js.map +0 -1
- package/dist/chunk-O4VXOBGF.js.map +0 -1
- package/dist/chunk-XCNTXWBB.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-U5JFG7HT.js.map +0 -1
- /package/dist/{chunk-I4MPFDRP.js.map → chunk-FWS3KC3Z.js.map} +0 -0
package/src/timeline/shared.tsx
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CameraIcon, CameraOffIcon, ChevronRightIcon } from "lucide-react";
|
|
2
|
-
import { useState, type ReactNode } from "react";
|
|
2
|
+
import { createContext, useContext, useState, type ReactNode } from "react";
|
|
3
3
|
import { cn } from "../lib/cn";
|
|
4
4
|
import { stringifyPayload } from "../lib/format";
|
|
5
5
|
import { useForcedDefaultOpen } from "./disclosure-context";
|
|
6
6
|
import { useLightboxOptional } from "./screenshot-lightbox";
|
|
7
|
+
import type { ToolCallTruncation } from "./types";
|
|
7
8
|
|
|
8
9
|
/* ----------------------------------------------------------------------------
|
|
9
10
|
Shared timeline primitives
|
|
@@ -37,6 +38,22 @@ export type DisclosureChip = {
|
|
|
37
38
|
text: string;
|
|
38
39
|
};
|
|
39
40
|
|
|
41
|
+
const ToolCallTruncationContext = createContext<ToolCallTruncation | null>(null);
|
|
42
|
+
|
|
43
|
+
export function ToolCallTruncationProvider({
|
|
44
|
+
value,
|
|
45
|
+
children,
|
|
46
|
+
}: {
|
|
47
|
+
value: ToolCallTruncation | null;
|
|
48
|
+
children: ReactNode;
|
|
49
|
+
}) {
|
|
50
|
+
return (
|
|
51
|
+
<ToolCallTruncationContext.Provider value={value}>
|
|
52
|
+
{children}
|
|
53
|
+
</ToolCallTruncationContext.Provider>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
40
57
|
export type ActivityDisclosureProps = {
|
|
41
58
|
icon: ReactNode;
|
|
42
59
|
/** Icon tint. Defaults to the muted foreground; renderers pass accent/failed. */
|
|
@@ -81,6 +98,8 @@ export type ActivityDisclosureProps = {
|
|
|
81
98
|
cancelled?: boolean | undefined;
|
|
82
99
|
/** When false the row is a static line (no expand affordance). */
|
|
83
100
|
expandable?: boolean | undefined;
|
|
101
|
+
/** Seed this individual disclosure open; user interaction still owns it afterwards. */
|
|
102
|
+
defaultOpen?: boolean | undefined;
|
|
84
103
|
children?: ReactNode | undefined;
|
|
85
104
|
};
|
|
86
105
|
|
|
@@ -109,6 +128,7 @@ export function ActivityDisclosure({
|
|
|
109
128
|
failed,
|
|
110
129
|
cancelled,
|
|
111
130
|
expandable = true,
|
|
131
|
+
defaultOpen,
|
|
112
132
|
children,
|
|
113
133
|
}: ActivityDisclosureProps) {
|
|
114
134
|
// `failed` takes precedence over `cancelled` when both are set (shouldn't happen, but be safe).
|
|
@@ -128,8 +148,9 @@ export function ActivityDisclosure({
|
|
|
128
148
|
// An ancestor may seed the initial open state (screenshot instrumentation);
|
|
129
149
|
// absent in normal app usage, where the row starts collapsed.
|
|
130
150
|
const forcedDefaultOpen = useForcedDefaultOpen();
|
|
131
|
-
const [open, setOpen] = useState(forcedDefaultOpen ?? false);
|
|
132
|
-
const
|
|
151
|
+
const [open, setOpen] = useState(defaultOpen ?? forcedDefaultOpen ?? false);
|
|
152
|
+
const truncation = useContext(ToolCallTruncationContext);
|
|
153
|
+
const hasBody = expandable && (children != null || truncation != null);
|
|
133
154
|
|
|
134
155
|
// The preview is detail-on-demand: it is suppressed once the row is open so a
|
|
135
156
|
// path/stat shown in the body never also sits in the collapsed row.
|
|
@@ -184,7 +205,7 @@ export function ActivityDisclosure({
|
|
|
184
205
|
)}
|
|
185
206
|
{/* The right gutter carries at most ONE signal: the media thumbnail, else a
|
|
186
207
|
terse settle chip (hidden once expanded — the body owns the detail). */}
|
|
187
|
-
{media ? (
|
|
208
|
+
{media && !open ? (
|
|
188
209
|
<span className="ml-auto flex shrink-0 items-center gap-2 pl-2">{media}</span>
|
|
189
210
|
) : chip && !open ? (
|
|
190
211
|
<span className="ml-auto shrink-0 pl-2">
|
|
@@ -235,12 +256,31 @@ export function ActivityDisclosure({
|
|
|
235
256
|
{open ? (
|
|
236
257
|
<div className="mb-2 ml-7 mt-1.5 flex flex-col gap-2 overflow-hidden animate-og-expand">
|
|
237
258
|
{children}
|
|
259
|
+
{truncation ? <ToolCallTruncationNotice truncation={truncation} /> : null}
|
|
238
260
|
</div>
|
|
239
261
|
) : null}
|
|
240
262
|
</div>
|
|
241
263
|
);
|
|
242
264
|
}
|
|
243
265
|
|
|
266
|
+
function ToolCallTruncationNotice({ truncation }: { truncation: ToolCallTruncation }) {
|
|
267
|
+
const fullEvidence = truncation.fullEvidence.available
|
|
268
|
+
? "retained"
|
|
269
|
+
: (truncation.fullEvidence.reason ?? "unavailable");
|
|
270
|
+
return (
|
|
271
|
+
<div data-og-tool-output-truncation="" className="text-og-sm leading-5 text-og-fg-subtle">
|
|
272
|
+
Output bounded at <code className="font-og-mono">{truncation.surface}</code>
|
|
273
|
+
{truncation.omittedBytes != null && truncation.omittedBytes > 0
|
|
274
|
+
? ` · ${truncation.omittedBytes.toLocaleString()} bytes omitted`
|
|
275
|
+
: null}
|
|
276
|
+
{" · reason "}
|
|
277
|
+
<code className="font-og-mono">{truncation.reason}</code>
|
|
278
|
+
{" · full evidence "}
|
|
279
|
+
<code className="font-og-mono">{fullEvidence}</code>
|
|
280
|
+
</div>
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
244
284
|
/**
|
|
245
285
|
* The right-gutter settle chip. Color is spent only on the exception: a failure
|
|
246
286
|
* is a red dot + red text (the one colored token in a healthy run); success and
|
|
@@ -467,10 +507,14 @@ export function Thumbnail({
|
|
|
467
507
|
src,
|
|
468
508
|
caption,
|
|
469
509
|
alt = "screenshot",
|
|
510
|
+
expandLabel = "Expand screenshot",
|
|
511
|
+
lightboxLabel = "Screenshot",
|
|
470
512
|
}: {
|
|
471
513
|
src: string;
|
|
472
514
|
caption?: string | undefined;
|
|
473
515
|
alt?: string;
|
|
516
|
+
expandLabel?: string | undefined;
|
|
517
|
+
lightboxLabel?: string | undefined;
|
|
474
518
|
}) {
|
|
475
519
|
const lightbox = useLightboxOptional();
|
|
476
520
|
const [failed, setFailed] = useState(false);
|
|
@@ -498,7 +542,7 @@ export function Thumbnail({
|
|
|
498
542
|
type="button"
|
|
499
543
|
onClick={(event) => {
|
|
500
544
|
event.stopPropagation();
|
|
501
|
-
lightbox.open(src, caption, event.currentTarget);
|
|
545
|
+
lightbox.open(src, caption, event.currentTarget, lightboxLabel);
|
|
502
546
|
}}
|
|
503
547
|
onKeyDown={(event) => {
|
|
504
548
|
if (event.key === "Enter" || event.key === " ") {
|
|
@@ -510,7 +554,7 @@ export function Thumbnail({
|
|
|
510
554
|
"group/thumb relative inline-flex overflow-hidden bg-og-bg outline-hidden",
|
|
511
555
|
"focus-visible:ring-2 focus-visible:ring-og-accent",
|
|
512
556
|
)}
|
|
513
|
-
aria-label=
|
|
557
|
+
aria-label={expandLabel}
|
|
514
558
|
>
|
|
515
559
|
{img}
|
|
516
560
|
</button>
|
|
@@ -527,10 +571,14 @@ export function ScreenshotFigure({
|
|
|
527
571
|
src,
|
|
528
572
|
caption,
|
|
529
573
|
alt = "screenshot",
|
|
574
|
+
expandLabel = "Expand screenshot",
|
|
575
|
+
lightboxLabel = "Screenshot",
|
|
530
576
|
}: {
|
|
531
577
|
src: string;
|
|
532
578
|
caption?: string | undefined;
|
|
533
579
|
alt?: string;
|
|
580
|
+
expandLabel?: string | undefined;
|
|
581
|
+
lightboxLabel?: string | undefined;
|
|
534
582
|
}) {
|
|
535
583
|
const lightbox = useLightboxOptional();
|
|
536
584
|
const [failed, setFailed] = useState(false);
|
|
@@ -554,9 +602,9 @@ export function ScreenshotFigure({
|
|
|
554
602
|
) : lightbox ? (
|
|
555
603
|
<button
|
|
556
604
|
type="button"
|
|
557
|
-
onClick={(event) => lightbox.open(src, caption, event.currentTarget)}
|
|
605
|
+
onClick={(event) => lightbox.open(src, caption, event.currentTarget, lightboxLabel)}
|
|
558
606
|
className={surface}
|
|
559
|
-
aria-label=
|
|
607
|
+
aria-label={expandLabel}
|
|
560
608
|
>
|
|
561
609
|
{img}
|
|
562
610
|
</button>
|
|
@@ -26,15 +26,17 @@ import {
|
|
|
26
26
|
Share2Icon,
|
|
27
27
|
TargetIcon,
|
|
28
28
|
TerminalIcon,
|
|
29
|
+
VideoIcon,
|
|
29
30
|
WrenchIcon,
|
|
30
31
|
} from "lucide-react";
|
|
31
|
-
import { useEffect, useState, type ReactNode } from "react";
|
|
32
|
+
import { useEffect, useRef, useState, type ReactNode } from "react";
|
|
32
33
|
import { stringifyPayload, tryParseJson } from "../lib/format";
|
|
33
34
|
import { useTimelineComputeLabel } from "./compute-label";
|
|
34
35
|
import {
|
|
35
36
|
applyPatchOpsFromToolItem,
|
|
36
37
|
controlCaret,
|
|
37
38
|
execTruncated,
|
|
39
|
+
generatedImageReceipt,
|
|
38
40
|
isExecSessionLostBanner,
|
|
39
41
|
looksBinary,
|
|
40
42
|
mediaPreviewFact,
|
|
@@ -664,11 +666,14 @@ function ComputerCallRenderer({ item, loadRetainedScreenshot }: ToolRendererProp
|
|
|
664
666
|
);
|
|
665
667
|
}
|
|
666
668
|
return (
|
|
667
|
-
<
|
|
669
|
+
<RetainedSessionImageDisclosure
|
|
668
670
|
artifact={retained}
|
|
669
671
|
load={loadRetainedScreenshot}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
+
title={`${verb}${countSuffix}`}
|
|
673
|
+
caption={`${verb}${countSuffix}`}
|
|
674
|
+
noun="screenshot"
|
|
675
|
+
icon={<CameraIcon className={ICON_SIZE} />}
|
|
676
|
+
lightboxLabel="Screenshot"
|
|
672
677
|
batched={batched}
|
|
673
678
|
failed={isFailed}
|
|
674
679
|
cancelled={isCancelled}
|
|
@@ -756,30 +761,26 @@ function ComputerCallRenderer({ item, loadRetainedScreenshot }: ToolRendererProp
|
|
|
756
761
|
);
|
|
757
762
|
}
|
|
758
763
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
| { kind: "unavailable"; label: string }
|
|
780
|
-
| { kind: "error"; message: string }
|
|
781
|
-
>({ kind: "loading" });
|
|
782
|
-
|
|
764
|
+
type RetainedImageState =
|
|
765
|
+
| { kind: "loading" }
|
|
766
|
+
| { kind: "ready"; url: string }
|
|
767
|
+
| { kind: "unavailable"; label: string }
|
|
768
|
+
| { kind: "error"; message: string };
|
|
769
|
+
|
|
770
|
+
function useRetainedImageObjectUrl(
|
|
771
|
+
artifact: RetainedArtifactReference,
|
|
772
|
+
load: ToolRendererProps["loadRetainedArtifact"],
|
|
773
|
+
): RetainedImageState {
|
|
774
|
+
const [state, setState] = useState<RetainedImageState>({ kind: "loading" });
|
|
775
|
+
// Function outputs are commonly serialized JSON. Parsing them creates a new
|
|
776
|
+
// object on every render, so depend on the immutable wire value rather than
|
|
777
|
+
// object identity; otherwise the loader can refetch after its own setState.
|
|
778
|
+
const artifactValue = retainedArtifactValue(artifact);
|
|
779
|
+
const stableArtifactRef = useRef({ value: artifactValue, artifact });
|
|
780
|
+
if (stableArtifactRef.current.value !== artifactValue) {
|
|
781
|
+
stableArtifactRef.current = { value: artifactValue, artifact };
|
|
782
|
+
}
|
|
783
|
+
const stableArtifact = stableArtifactRef.current.artifact;
|
|
783
784
|
useEffect(() => {
|
|
784
785
|
if (!load) {
|
|
785
786
|
setState({ kind: "unavailable", label: "retrieval is not configured" });
|
|
@@ -788,14 +789,24 @@ function RetainedScreenshotDisclosure({
|
|
|
788
789
|
const controller = new AbortController();
|
|
789
790
|
let objectUrl: string | null = null;
|
|
790
791
|
setState({ kind: "loading" });
|
|
791
|
-
void load(
|
|
792
|
-
.then((
|
|
792
|
+
void load(stableArtifact, controller.signal)
|
|
793
|
+
.then((source) => {
|
|
793
794
|
if (controller.signal.aborted) return;
|
|
794
|
-
if (!
|
|
795
|
+
if (!source) {
|
|
795
796
|
setState({ kind: "unavailable", label: "bytes are unavailable" });
|
|
796
797
|
return;
|
|
797
798
|
}
|
|
798
|
-
|
|
799
|
+
if (!(source instanceof Uint8Array)) {
|
|
800
|
+
if (!source.url.trim()) {
|
|
801
|
+
setState({ kind: "unavailable", label: "URL is unavailable" });
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
setState({ kind: "ready", url: source.url });
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
objectUrl = URL.createObjectURL(
|
|
808
|
+
new Blob([source as unknown as BlobPart], { type: stableArtifact.contentType }),
|
|
809
|
+
);
|
|
799
810
|
setState({ kind: "ready", url: objectUrl });
|
|
800
811
|
})
|
|
801
812
|
.catch((error: unknown) => {
|
|
@@ -809,38 +820,86 @@ function RetainedScreenshotDisclosure({
|
|
|
809
820
|
? { kind: "unavailable", label: "deleted" }
|
|
810
821
|
: status === 410
|
|
811
822
|
? { kind: "unavailable", label: "expired or unavailable" }
|
|
812
|
-
: {
|
|
813
|
-
kind: "error",
|
|
814
|
-
message: "retrieval failed",
|
|
815
|
-
},
|
|
823
|
+
: { kind: "error", message: "retrieval failed" },
|
|
816
824
|
);
|
|
817
825
|
});
|
|
818
826
|
return () => {
|
|
819
827
|
controller.abort();
|
|
820
828
|
if (objectUrl) URL.revokeObjectURL(objectUrl);
|
|
821
829
|
};
|
|
822
|
-
}, [
|
|
830
|
+
}, [stableArtifact, load]);
|
|
831
|
+
return state;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
function retainedArtifactValue(artifact: RetainedArtifactReference): string {
|
|
835
|
+
return [
|
|
836
|
+
artifact.artifactId,
|
|
837
|
+
artifact.kind,
|
|
838
|
+
artifact.contentType,
|
|
839
|
+
artifact.originalBytes,
|
|
840
|
+
artifact.sha256,
|
|
841
|
+
artifact.retainedAt,
|
|
842
|
+
artifact.dimensions?.width ?? "",
|
|
843
|
+
artifact.dimensions?.height ?? "",
|
|
844
|
+
artifact.retention.policy,
|
|
845
|
+
artifact.retention.expiresAt ?? "",
|
|
846
|
+
artifact.retrieval.method,
|
|
847
|
+
artifact.retrieval.path,
|
|
848
|
+
artifact.retrieval.acceptRanges,
|
|
849
|
+
artifact.retrieval.maxRangeBytes,
|
|
850
|
+
].join("\0");
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
function RetainedSessionImageDisclosure({
|
|
854
|
+
artifact,
|
|
855
|
+
load,
|
|
856
|
+
title,
|
|
857
|
+
caption,
|
|
858
|
+
noun,
|
|
859
|
+
icon,
|
|
860
|
+
lightboxLabel,
|
|
861
|
+
batched,
|
|
862
|
+
failed,
|
|
863
|
+
cancelled,
|
|
864
|
+
}: {
|
|
865
|
+
artifact: RetainedArtifactReference;
|
|
866
|
+
load: ToolRendererProps["loadRetainedScreenshot"];
|
|
867
|
+
title: string;
|
|
868
|
+
caption: string;
|
|
869
|
+
noun: "image" | "screenshot";
|
|
870
|
+
icon: ReactNode;
|
|
871
|
+
lightboxLabel: string;
|
|
872
|
+
batched: string | null;
|
|
873
|
+
failed: boolean;
|
|
874
|
+
cancelled: boolean;
|
|
875
|
+
}) {
|
|
876
|
+
const state = useRetainedImageObjectUrl(artifact, load);
|
|
823
877
|
|
|
824
|
-
const caption = `${verb}${countSuffix}`;
|
|
825
878
|
return (
|
|
826
879
|
<ActivityDisclosure
|
|
827
|
-
icon={
|
|
880
|
+
icon={icon}
|
|
828
881
|
iconTone={failed ? "failed" : state.kind === "ready" ? "accent" : "muted"}
|
|
829
|
-
title={
|
|
882
|
+
title={title}
|
|
830
883
|
failed={failed}
|
|
831
884
|
cancelled={cancelled}
|
|
832
885
|
preview={
|
|
833
886
|
state.kind === "loading"
|
|
834
|
-
?
|
|
887
|
+
? `loading retained ${noun}…`
|
|
835
888
|
: state.kind === "error"
|
|
836
|
-
?
|
|
889
|
+
? `${noun} retrieval failed`
|
|
837
890
|
: state.kind === "unavailable"
|
|
838
|
-
?
|
|
891
|
+
? `${noun} ${state.label}`
|
|
839
892
|
: undefined
|
|
840
893
|
}
|
|
841
894
|
media={
|
|
842
895
|
state.kind === "ready" ? (
|
|
843
|
-
<Thumbnail
|
|
896
|
+
<Thumbnail
|
|
897
|
+
src={state.url}
|
|
898
|
+
caption={caption}
|
|
899
|
+
alt={caption}
|
|
900
|
+
expandLabel={`Expand ${noun}`}
|
|
901
|
+
lightboxLabel={lightboxLabel}
|
|
902
|
+
/>
|
|
844
903
|
) : state.kind === "loading" ? (
|
|
845
904
|
<MediaSkeleton />
|
|
846
905
|
) : (
|
|
@@ -849,19 +908,171 @@ function RetainedScreenshotDisclosure({
|
|
|
849
908
|
}
|
|
850
909
|
>
|
|
851
910
|
{state.kind === "ready" ? (
|
|
852
|
-
<ScreenshotFigure
|
|
911
|
+
<ScreenshotFigure
|
|
912
|
+
src={state.url}
|
|
913
|
+
caption={caption}
|
|
914
|
+
alt={caption}
|
|
915
|
+
expandLabel={`Expand ${noun}`}
|
|
916
|
+
lightboxLabel={lightboxLabel}
|
|
917
|
+
/>
|
|
853
918
|
) : state.kind === "loading" ? (
|
|
854
|
-
<BodyNote>Loading the retained
|
|
919
|
+
<BodyNote>Loading the retained {noun}…</BodyNote>
|
|
855
920
|
) : state.kind === "unavailable" ? (
|
|
856
|
-
<BodyNote>
|
|
921
|
+
<BodyNote>
|
|
922
|
+
{noun === "screenshot" ? "Screenshot" : "Image"} {state.label}.
|
|
923
|
+
</BodyNote>
|
|
857
924
|
) : (
|
|
858
|
-
<BodyNote tone="error">
|
|
925
|
+
<BodyNote tone="error">
|
|
926
|
+
{noun === "screenshot" ? "Screenshot" : "Image"} retrieval failed: {state.message}
|
|
927
|
+
</BodyNote>
|
|
859
928
|
)}
|
|
860
929
|
{batched ? <BodyNote>batched: {batched}</BodyNote> : null}
|
|
861
930
|
</ActivityDisclosure>
|
|
862
931
|
);
|
|
863
932
|
}
|
|
864
933
|
|
|
934
|
+
function GeneratedImageRenderer({ item, loadRetainedArtifact }: ToolRendererProps) {
|
|
935
|
+
const args = parseToolArgs(item.arguments);
|
|
936
|
+
const prompt = typeof args.prompt === "string" ? args.prompt : "";
|
|
937
|
+
const raw =
|
|
938
|
+
item.raw && typeof item.raw === "object" && !Array.isArray(item.raw)
|
|
939
|
+
? (item.raw as Record<string, unknown>)
|
|
940
|
+
: null;
|
|
941
|
+
// Function tools settle through agent.toolCall.output; OpenAI's hosted image
|
|
942
|
+
// call is already complete on agent.toolCall.created and carries the compact
|
|
943
|
+
// receipt in raw.output. Both paths deliberately converge on one renderer.
|
|
944
|
+
const receipt = generatedImageReceipt(item.output) ?? generatedImageReceipt(raw?.output);
|
|
945
|
+
if (item.status === "running") {
|
|
946
|
+
return (
|
|
947
|
+
<ActivityDisclosure
|
|
948
|
+
icon={<ImageIcon className={ICON_SIZE} />}
|
|
949
|
+
iconTone="running"
|
|
950
|
+
title="Generating image"
|
|
951
|
+
running
|
|
952
|
+
preview={<RunningPreview>{truncatePreview(prompt, 72) || "creating…"}</RunningPreview>}
|
|
953
|
+
media={<MediaSkeleton />}
|
|
954
|
+
>
|
|
955
|
+
{prompt ? <BodyNote>{prompt}</BodyNote> : null}
|
|
956
|
+
</ActivityDisclosure>
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
if (!receipt) return <GenericRenderer item={item} />;
|
|
960
|
+
return (
|
|
961
|
+
<GeneratedImageDisclosure
|
|
962
|
+
receipt={receipt}
|
|
963
|
+
load={loadRetainedArtifact}
|
|
964
|
+
prompt={prompt}
|
|
965
|
+
failed={item.status === "failed"}
|
|
966
|
+
cancelled={item.status === "cancelled"}
|
|
967
|
+
/>
|
|
968
|
+
);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
function GeneratedVideoRenderer({ item }: ToolRendererProps) {
|
|
972
|
+
const args = parseToolArgs(item.arguments);
|
|
973
|
+
const prompt = typeof args.prompt === "string" ? args.prompt : "";
|
|
974
|
+
const parsedOutput = typeof item.output === "string" ? tryParseJson(item.output) : item.output;
|
|
975
|
+
const accepted =
|
|
976
|
+
parsedOutput &&
|
|
977
|
+
typeof parsedOutput === "object" &&
|
|
978
|
+
!Array.isArray(parsedOutput) &&
|
|
979
|
+
(parsedOutput as Record<string, unknown>).status === "accepted";
|
|
980
|
+
const failed = item.status === "failed";
|
|
981
|
+
const cancelled = item.status === "cancelled";
|
|
982
|
+
const running = item.status === "running";
|
|
983
|
+
return (
|
|
984
|
+
<ActivityDisclosure
|
|
985
|
+
icon={<VideoIcon className={ICON_SIZE} />}
|
|
986
|
+
iconTone={failed ? "failed" : running ? "running" : accepted ? "accent" : "muted"}
|
|
987
|
+
title={
|
|
988
|
+
running ? "Starting video generation" : accepted ? "Generating video" : "Generate video"
|
|
989
|
+
}
|
|
990
|
+
running={running}
|
|
991
|
+
failed={failed}
|
|
992
|
+
cancelled={cancelled}
|
|
993
|
+
preview={truncatePreview(prompt, 88) || (accepted ? "request accepted" : undefined)}
|
|
994
|
+
>
|
|
995
|
+
{prompt ? <BodyNote>{prompt}</BodyNote> : null}
|
|
996
|
+
{accepted ? (
|
|
997
|
+
<BodyNote>The video will appear here when it is ready.</BodyNote>
|
|
998
|
+
) : item.output !== undefined ? (
|
|
999
|
+
<PayloadBlock label="Output" value={item.output} />
|
|
1000
|
+
) : null}
|
|
1001
|
+
</ActivityDisclosure>
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
function GeneratedImageDisclosure({
|
|
1005
|
+
receipt,
|
|
1006
|
+
load,
|
|
1007
|
+
prompt,
|
|
1008
|
+
failed,
|
|
1009
|
+
cancelled,
|
|
1010
|
+
}: {
|
|
1011
|
+
receipt: NonNullable<ReturnType<typeof generatedImageReceipt>>;
|
|
1012
|
+
load: ToolRendererProps["loadRetainedArtifact"];
|
|
1013
|
+
prompt: string;
|
|
1014
|
+
failed: boolean;
|
|
1015
|
+
cancelled: boolean;
|
|
1016
|
+
}) {
|
|
1017
|
+
const state = useRetainedImageObjectUrl(receipt.artifact, load);
|
|
1018
|
+
const dimensions = receipt.artifact.dimensions!;
|
|
1019
|
+
const title = failed ? "Image generation failed" : "Generated image";
|
|
1020
|
+
const caption = prompt || `Generated image · ${dimensions.width}×${dimensions.height}`;
|
|
1021
|
+
return (
|
|
1022
|
+
<ActivityDisclosure
|
|
1023
|
+
icon={<ImageIcon className={ICON_SIZE} />}
|
|
1024
|
+
iconTone={failed ? "failed" : state.kind === "ready" ? "accent" : "muted"}
|
|
1025
|
+
title={title}
|
|
1026
|
+
defaultOpen={!failed && !cancelled}
|
|
1027
|
+
failed={failed}
|
|
1028
|
+
cancelled={cancelled}
|
|
1029
|
+
preview={
|
|
1030
|
+
state.kind === "loading"
|
|
1031
|
+
? "loading image…"
|
|
1032
|
+
: state.kind === "error"
|
|
1033
|
+
? "image retrieval failed"
|
|
1034
|
+
: state.kind === "unavailable"
|
|
1035
|
+
? `image ${state.label}`
|
|
1036
|
+
: truncatePreview(prompt, 88) || `${dimensions.width}×${dimensions.height}`
|
|
1037
|
+
}
|
|
1038
|
+
media={
|
|
1039
|
+
state.kind === "ready" ? (
|
|
1040
|
+
<Thumbnail
|
|
1041
|
+
src={state.url}
|
|
1042
|
+
caption={caption}
|
|
1043
|
+
alt={caption}
|
|
1044
|
+
expandLabel="Expand generated image"
|
|
1045
|
+
lightboxLabel="Generated image"
|
|
1046
|
+
/>
|
|
1047
|
+
) : state.kind === "loading" ? (
|
|
1048
|
+
<MediaSkeleton />
|
|
1049
|
+
) : (
|
|
1050
|
+
<MediaEmpty />
|
|
1051
|
+
)
|
|
1052
|
+
}
|
|
1053
|
+
>
|
|
1054
|
+
{state.kind === "ready" ? (
|
|
1055
|
+
<ScreenshotFigure
|
|
1056
|
+
src={state.url}
|
|
1057
|
+
caption={caption}
|
|
1058
|
+
alt={caption}
|
|
1059
|
+
expandLabel="Expand generated image"
|
|
1060
|
+
lightboxLabel="Generated image"
|
|
1061
|
+
/>
|
|
1062
|
+
) : state.kind === "loading" ? (
|
|
1063
|
+
<BodyNote>Loading the generated image…</BodyNote>
|
|
1064
|
+
) : state.kind === "unavailable" ? (
|
|
1065
|
+
<BodyNote>Image {state.label}.</BodyNote>
|
|
1066
|
+
) : (
|
|
1067
|
+
<BodyNote tone="error">Image retrieval failed.</BodyNote>
|
|
1068
|
+
)}
|
|
1069
|
+
<BodyNote>
|
|
1070
|
+
{dimensions.width}×{dimensions.height} · {receipt.sandboxPath}
|
|
1071
|
+
</BodyNote>
|
|
1072
|
+
</ActivityDisclosure>
|
|
1073
|
+
);
|
|
1074
|
+
}
|
|
1075
|
+
|
|
865
1076
|
/* ---- web_search ------------------------------------------------------------ */
|
|
866
1077
|
|
|
867
1078
|
type WebSearchResult = { title: string; domain: string; snippet: string };
|
|
@@ -1013,11 +1224,12 @@ const VIEW_IMAGE_ERRORS = [
|
|
|
1013
1224
|
"unable to read image",
|
|
1014
1225
|
];
|
|
1015
1226
|
|
|
1016
|
-
function ViewImageRenderer({ item }: ToolRendererProps) {
|
|
1227
|
+
function ViewImageRenderer({ item, loadRetainedScreenshot }: ToolRendererProps) {
|
|
1017
1228
|
const args = parseToolArgs(item.arguments);
|
|
1018
1229
|
const path = typeof args.path === "string" ? args.path : "";
|
|
1019
1230
|
const out = item.output;
|
|
1020
1231
|
const text = typeof out === "string" ? out : "";
|
|
1232
|
+
const retained = retainedScreenshotMetadata(out);
|
|
1021
1233
|
const omittedMedia = mediaPreviewFact(out);
|
|
1022
1234
|
|
|
1023
1235
|
if (item.status === "running") {
|
|
@@ -1038,6 +1250,45 @@ function ViewImageRenderer({ item }: ToolRendererProps) {
|
|
|
1038
1250
|
const viewFailed = item.status === "failed";
|
|
1039
1251
|
const viewCancelled = item.status === "cancelled";
|
|
1040
1252
|
|
|
1253
|
+
if (retained) {
|
|
1254
|
+
const title = `Viewed ${basename(path)}`;
|
|
1255
|
+
if (!retained.available) {
|
|
1256
|
+
const state =
|
|
1257
|
+
retained.reason === "expired" || retained.reason === "deleted"
|
|
1258
|
+
? retained.reason
|
|
1259
|
+
: "unavailable";
|
|
1260
|
+
return (
|
|
1261
|
+
<ActivityDisclosure
|
|
1262
|
+
icon={<ImageIcon className={ICON_SIZE} />}
|
|
1263
|
+
iconTone={viewFailed ? "failed" : "muted"}
|
|
1264
|
+
title={`${title} · ${state}`}
|
|
1265
|
+
failed={viewFailed}
|
|
1266
|
+
cancelled={viewCancelled}
|
|
1267
|
+
preview={`image ${state}`}
|
|
1268
|
+
media={<MediaEmpty />}
|
|
1269
|
+
>
|
|
1270
|
+
<BodyNote tone={viewFailed ? "error" : undefined}>
|
|
1271
|
+
Image {state}: {retained.reason.replaceAll("_", " ")}.
|
|
1272
|
+
</BodyNote>
|
|
1273
|
+
</ActivityDisclosure>
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
return (
|
|
1277
|
+
<RetainedSessionImageDisclosure
|
|
1278
|
+
artifact={retained}
|
|
1279
|
+
load={loadRetainedScreenshot}
|
|
1280
|
+
title={title}
|
|
1281
|
+
caption={path || title}
|
|
1282
|
+
noun="image"
|
|
1283
|
+
icon={<ImageIcon className={ICON_SIZE} />}
|
|
1284
|
+
lightboxLabel="Image"
|
|
1285
|
+
batched={null}
|
|
1286
|
+
failed={viewFailed}
|
|
1287
|
+
cancelled={viewCancelled}
|
|
1288
|
+
/>
|
|
1289
|
+
);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1041
1292
|
const errMatch = VIEW_IMAGE_ERRORS.find((p) => text.includes(p));
|
|
1042
1293
|
if (errMatch) {
|
|
1043
1294
|
const tooBig = text.includes("exceeded the allowed size");
|
|
@@ -1935,7 +2186,6 @@ const BASE_ENTRIES: ToolRegistryEntry[] = [
|
|
|
1935
2186
|
// truth and is consulted first by the registry.
|
|
1936
2187
|
{ match: "rawType", type: "apply_patch_call", render: ApplyPatchRenderer },
|
|
1937
2188
|
{ match: "rawType", type: "computer_call", render: ComputerCallRenderer },
|
|
1938
|
-
{ match: "rawType", type: "hosted_tool_call", render: WebSearchRenderer },
|
|
1939
2189
|
{ match: "rawType", type: "tool_search_call", render: ToolSearchRenderer },
|
|
1940
2190
|
// First-party sandbox + MCP tools resolve by name (exact or MCP leaf).
|
|
1941
2191
|
{ match: "name", name: "exec_command", render: ExecRenderer },
|
|
@@ -1955,6 +2205,9 @@ const BASE_ENTRIES: ToolRegistryEntry[] = [
|
|
|
1955
2205
|
{ match: "name", name: "computer_keypress", render: ComputerCallRenderer },
|
|
1956
2206
|
{ match: "name", name: "computer_drag", render: ComputerCallRenderer },
|
|
1957
2207
|
{ match: "name", name: "web_search_call", render: WebSearchRenderer },
|
|
2208
|
+
{ match: "name", name: "image_generation_call", render: GeneratedImageRenderer },
|
|
2209
|
+
{ match: "name", name: "generate_image", render: GeneratedImageRenderer },
|
|
2210
|
+
{ match: "name", name: "generate_video", render: GeneratedVideoRenderer },
|
|
1958
2211
|
{ match: "name", name: "tool_search", render: ToolSearchRenderer },
|
|
1959
2212
|
{ match: "name", name: "view_image", render: ViewImageRenderer },
|
|
1960
2213
|
{ match: "name", name: "environment_set_variable", render: SecretSetRenderer },
|