@opengeni/react 1.0.1 → 2.2.0-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -10
- package/dist/artifacts-spreadsheet.js +1 -1
- package/dist/artifacts.js +1 -1
- package/dist/browser-viewer-GXUICIAG.js +14 -0
- package/dist/{chunk-R3AZOAB5.js → chunk-4MDLEHXL.js} +9 -115
- package/dist/chunk-4MDLEHXL.js.map +1 -0
- package/dist/{chunk-Y7OEDUJ5.js → chunk-5RZN3DD5.js} +1014 -420
- package/dist/chunk-5RZN3DD5.js.map +1 -0
- package/dist/chunk-5YK2ZDIG.js +116 -0
- package/dist/chunk-5YK2ZDIG.js.map +1 -0
- package/dist/chunk-H5YGYNXS.js +329 -0
- package/dist/chunk-H5YGYNXS.js.map +1 -0
- package/dist/{chunk-7WCLAEFV.js → chunk-ICA6R6TW.js} +2 -2
- package/dist/{chunk-7WCLAEFV.js.map → chunk-ICA6R6TW.js.map} +1 -1
- package/dist/{chunk-IGC6A2ZI.js → chunk-JOAVA2TW.js} +589 -217
- package/dist/chunk-JOAVA2TW.js.map +1 -0
- package/dist/{chunk-5UQPNLIO.js → chunk-LTCHJ4MS.js} +9 -9
- package/dist/chunk-LTCHJ4MS.js.map +1 -0
- package/dist/{chunk-C5ZPSSS5.js → chunk-NEXLLTP4.js} +2 -1
- package/dist/{chunk-C5ZPSSS5.js.map → chunk-NEXLLTP4.js.map} +1 -1
- package/dist/chunk-QGBJ6GHG.js +2300 -0
- package/dist/chunk-QGBJ6GHG.js.map +1 -0
- package/dist/{chunk-B6WPZSTT.js → chunk-UOLJWT5Y.js} +78 -16
- package/dist/chunk-UOLJWT5Y.js.map +1 -0
- package/dist/{chunk-MKPIAGVL.js → chunk-W6NFJXSA.js} +8 -19
- package/dist/chunk-W6NFJXSA.js.map +1 -0
- package/dist/{chunk-XBZWOM2K.js → chunk-X4A66EWZ.js} +8 -3
- package/dist/chunk-X4A66EWZ.js.map +1 -0
- package/dist/chunk-X4JAFD5R.js +3907 -0
- package/dist/chunk-X4JAFD5R.js.map +1 -0
- package/dist/{chunk-6KLX2RH5.js → chunk-XSA2QAKP.js} +334 -19
- package/dist/chunk-XSA2QAKP.js.map +1 -0
- package/dist/{chunk-HA46CYQK.js → chunk-XXWH2JLC.js} +792 -206
- package/dist/chunk-XXWH2JLC.js.map +1 -0
- package/dist/client.d.ts +2 -2
- package/dist/components/browser-viewer.d.ts +7 -1
- package/dist/components/computer-viewer.d.ts +4 -1
- package/dist/components/enrollment-consent.d.ts +6 -3
- package/dist/components/file-browser.d.ts +7 -1
- package/dist/components/human-input-form.d.ts +1 -1
- package/dist/components/human-input-surface.d.ts +1 -1
- package/dist/components/machine-card.d.ts +4 -1
- package/dist/components/machines/machine-detail.d.ts +4 -1
- package/dist/components/machines/machine-operation-policy.d.ts +11 -0
- package/dist/components/machines-dashboard.d.ts +3 -1
- package/dist/components/markdown.d.ts +20 -1
- package/dist/components/message-timeline.d.ts +1 -1
- package/dist/components/model-policy-picker.d.ts +2 -0
- package/dist/components/pierre-file.d.ts +1 -1
- package/dist/components/sandbox-files.d.ts +8 -2
- package/dist/components/sandbox-workspace.d.ts +33 -3
- package/dist/components/session-chrome.d.ts +15 -3
- package/dist/components/workspace-dock.d.ts +6 -2
- package/dist/composer.js +5 -5
- package/dist/computer-viewer-ZOP4Q7A7.js +16 -0
- package/dist/computer-viewer-ZOP4Q7A7.js.map +1 -0
- package/dist/hooks/channel-cache.d.ts +23 -0
- package/dist/hooks/shared-machines-list.d.ts +14 -0
- package/dist/hooks/use-attached-browsers.d.ts +2 -1
- package/dist/hooks/use-channels.d.ts +1 -0
- package/dist/hooks/use-composer.d.ts +37 -9
- package/dist/hooks/use-machine-chip.d.ts +3 -3
- package/dist/hooks/use-machines.d.ts +19 -1
- package/dist/hooks/use-sandbox-files.d.ts +1 -0
- package/dist/hooks/use-session-background-commands.d.ts +14 -0
- package/dist/hooks/use-turn-queue.d.ts +12 -0
- package/dist/hooks/use-workspace-sessions.d.ts +1 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +1096 -623
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +29 -181
- package/dist/interaction.js.map +1 -1
- package/dist/lib/interaction-errors.d.ts +3 -0
- package/dist/machines.d.ts +4 -2
- package/dist/machines.js +10 -2
- package/dist/model-policy.d.ts +1 -1
- package/dist/model-policy.js +1 -1
- package/dist/platform-activity-row-BJHUHXAT.js +169 -0
- package/dist/platform-activity-row-BJHUHXAT.js.map +1 -0
- package/dist/{queue-surface-implementation-2KVJTYXH.js → queue-surface-implementation-BSKUWHRI.js} +76 -16
- package/dist/queue-surface-implementation-BSKUWHRI.js.map +1 -0
- package/dist/realtime/realtime-control.d.ts +6 -3
- package/dist/realtime.js +36 -14
- package/dist/realtime.js.map +1 -1
- package/dist/session-ui.d.ts +1 -1
- package/dist/session-ui.js +6 -2
- package/dist/session.d.ts +2 -2
- package/dist/session.js +4 -4
- package/dist/timeline/index.d.ts +1 -1
- package/dist/timeline/platform-activity-row.d.ts +15 -0
- package/dist/timeline/screenshot-lightbox.d.ts +1 -1
- package/dist/timeline/shared.d.ts +4 -2
- package/dist/timeline/types.d.ts +48 -5
- package/dist/types/machines.d.ts +2 -2
- package/package.json +3 -3
- package/src/client.ts +12 -1
- package/src/components/artifacts/editable-spreadsheet.tsx +1 -1
- package/src/components/browser-viewer.tsx +361 -58
- package/src/components/chat-composer.tsx +1 -1
- package/src/components/composer.tsx +6 -6
- package/src/components/computer-viewer.tsx +368 -115
- package/src/components/enrollment-consent.tsx +64 -6
- package/src/components/file-browser.tsx +117 -2
- package/src/components/human-input-form.tsx +91 -55
- package/src/components/human-input-surface.tsx +1 -1
- package/src/components/machine-card.tsx +111 -0
- package/src/components/machine-input-display.ts +15 -0
- package/src/components/machines/machine-detail.tsx +47 -0
- package/src/components/machines/machine-operation-policy.tsx +179 -0
- package/src/components/machines-dashboard.tsx +6 -0
- package/src/components/markdown.tsx +174 -20
- package/src/components/message-timeline.tsx +162 -17
- package/src/components/model-policy-picker.tsx +9 -17
- package/src/components/pierre-file.tsx +1 -1
- package/src/components/queue-surface-implementation.tsx +82 -16
- package/src/components/sandbox-files.tsx +135 -19
- package/src/components/sandbox-workspace.tsx +204 -92
- package/src/components/session-chrome.tsx +415 -208
- package/src/components/session-status.tsx +1 -1
- package/src/components/user-message-body.tsx +168 -48
- package/src/components/workspace-dock.tsx +141 -175
- package/src/hooks/channel-cache.ts +104 -0
- package/src/hooks/shared-machines-list.ts +239 -0
- package/src/hooks/use-attached-browsers.ts +5 -1
- package/src/hooks/use-browser-frame-stream.ts +6 -1
- package/src/hooks/use-browser-session.ts +6 -4
- package/src/hooks/use-browser-sessions.ts +7 -1
- package/src/hooks/use-channels.ts +32 -10
- package/src/hooks/use-composer.ts +760 -291
- package/src/hooks/use-computer-frame-stream.ts +14 -9
- package/src/hooks/use-computer-session.ts +16 -14
- package/src/hooks/use-computer-sessions.ts +8 -1
- package/src/hooks/use-last-started-turn-policy.ts +1 -1
- package/src/hooks/use-machine-chip.ts +23 -6
- package/src/hooks/use-machines.ts +104 -6
- package/src/hooks/use-sandbox-files.ts +195 -140
- package/src/hooks/use-sandbox-git.ts +58 -29
- package/src/hooks/use-session-background-commands.ts +56 -0
- package/src/hooks/use-session-capabilities.ts +18 -0
- package/src/hooks/use-turn-queue.ts +111 -12
- package/src/hooks/use-workspace-sessions.ts +5 -1
- package/src/index.ts +26 -4
- package/src/lib/interaction-errors.ts +18 -0
- package/src/machines.ts +9 -1
- package/src/model-policy.ts +10 -2
- package/src/realtime/realtime-control.tsx +53 -17
- package/src/session-context.ts +1 -0
- package/src/session-ui.ts +6 -1
- package/src/session.ts +9 -1
- package/src/timeline/activity-rail.tsx +20 -75
- package/src/timeline/index.ts +4 -0
- package/src/timeline/platform-activity-row.tsx +201 -0
- package/src/timeline/projection.ts +476 -23
- package/src/timeline/screenshot-lightbox.tsx +48 -14
- package/src/timeline/shared.tsx +8 -2
- package/src/timeline/tool-renderers.tsx +104 -6
- package/src/timeline/turn-summary.tsx +6 -1
- package/src/timeline/types.ts +75 -2
- package/src/types/machines.ts +10 -0
- package/styles/compiled.css +115 -104
- package/dist/chunk-5UQPNLIO.js.map +0 -1
- package/dist/chunk-6KLX2RH5.js.map +0 -1
- package/dist/chunk-B6WPZSTT.js.map +0 -1
- package/dist/chunk-HA46CYQK.js.map +0 -1
- package/dist/chunk-IGC6A2ZI.js.map +0 -1
- package/dist/chunk-LLOLUHVG.js +0 -5937
- package/dist/chunk-LLOLUHVG.js.map +0 -1
- package/dist/chunk-MKPIAGVL.js.map +0 -1
- package/dist/chunk-R3AZOAB5.js.map +0 -1
- package/dist/chunk-XBZWOM2K.js.map +0 -1
- package/dist/chunk-Y7OEDUJ5.js.map +0 -1
- package/dist/interactive-workbench-viewers-TOHBXJEE.js +0 -15
- package/dist/queue-surface-implementation-2KVJTYXH.js.map +0 -1
- /package/dist/{interactive-workbench-viewers-TOHBXJEE.js.map → browser-viewer-GXUICIAG.js.map} +0 -0
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type SessionRealtimeController,
|
|
7
7
|
type SessionRealtimeControllerSnapshot,
|
|
8
8
|
type CreateSessionRealtimeControllerOptions,
|
|
9
|
+
type SessionRealtimeLifecycleProjection,
|
|
9
10
|
type SessionRealtimeModel,
|
|
10
11
|
type WorkspaceRealtimeModelCatalogItem,
|
|
11
12
|
} from "@opengeni/sdk/realtime";
|
|
@@ -280,7 +281,7 @@ export function useSessionRealtime(options: {
|
|
|
280
281
|
const eventsReadyRef = useRef(options.eventsReady);
|
|
281
282
|
lifecycleRef.current = lifecycle;
|
|
282
283
|
eventsReadyRef.current = options.eventsReady;
|
|
283
|
-
const lifecycleActive = lifecycle
|
|
284
|
+
const lifecycleActive = sessionRealtimeLifecycleIsActive(lifecycle);
|
|
284
285
|
|
|
285
286
|
useEffect(() => {
|
|
286
287
|
let disposed = false;
|
|
@@ -401,6 +402,14 @@ export function useSessionRealtime(options: {
|
|
|
401
402
|
};
|
|
402
403
|
}
|
|
403
404
|
|
|
405
|
+
function sessionRealtimeLifecycleIsActive(
|
|
406
|
+
lifecycle: SessionRealtimeLifecycleProjection | null,
|
|
407
|
+
): boolean {
|
|
408
|
+
if (lifecycle?.state !== "active") return false;
|
|
409
|
+
const leaseExpiresAt = Date.parse(lifecycle.leaseExpiresAt);
|
|
410
|
+
return !Number.isFinite(leaseExpiresAt) || leaseExpiresAt > Date.now();
|
|
411
|
+
}
|
|
412
|
+
|
|
404
413
|
export function SessionRealtimeControl(props: {
|
|
405
414
|
client?: RealtimeControllerClient | undefined;
|
|
406
415
|
workspaceId?: string | undefined;
|
|
@@ -423,15 +432,18 @@ export function SessionRealtimeControl(props: {
|
|
|
423
432
|
* `none` never attaches a model menu to the bar button.
|
|
424
433
|
*/
|
|
425
434
|
modelMenu?: "split" | "split-desktop" | "none" | undefined;
|
|
435
|
+
/** Explicitly expose low-level controller diagnostics; disabled by default. */
|
|
436
|
+
showDiagnostics?: boolean | undefined;
|
|
426
437
|
/** Deterministic browser-test/demo seam. Production hosts should use the SDK default. */
|
|
427
438
|
controllerFactory?: SessionRealtimeControllerFactory | undefined;
|
|
428
439
|
}) {
|
|
429
440
|
const lifecycle = useMemo(() => projectSessionRealtimeLifecycle(props.events), [props.events]);
|
|
441
|
+
const lifecycleActive = sessionRealtimeLifecycleIsActive(lifecycle);
|
|
430
442
|
const selection = useRealtimeModelSelection({
|
|
431
443
|
client: props.client,
|
|
432
444
|
workspaceId: props.workspaceId,
|
|
433
445
|
codexConnected: props.codexConnected,
|
|
434
|
-
activeModel: lifecycle?.state === "active" ? lifecycle.model : null,
|
|
446
|
+
activeModel: lifecycleActive && lifecycle?.state === "active" ? lifecycle.model : null,
|
|
435
447
|
});
|
|
436
448
|
const selectedModel = selection.selectedModel;
|
|
437
449
|
const realtime = useSessionRealtime({
|
|
@@ -455,7 +467,7 @@ export function SessionRealtimeControl(props: {
|
|
|
455
467
|
|
|
456
468
|
useEffect(() => {
|
|
457
469
|
const pending = autostartModelRef.current;
|
|
458
|
-
if (!pending || autostartStartedRef.current ||
|
|
470
|
+
if (!pending || autostartStartedRef.current || lifecycleActive) return;
|
|
459
471
|
const available = models.some((model) => model.id === pending && model.available);
|
|
460
472
|
if (!available) return;
|
|
461
473
|
if (selectedRealtimeModel.id !== pending) {
|
|
@@ -474,7 +486,7 @@ export function SessionRealtimeControl(props: {
|
|
|
474
486
|
});
|
|
475
487
|
}, [
|
|
476
488
|
canStart,
|
|
477
|
-
|
|
489
|
+
lifecycleActive,
|
|
478
490
|
models,
|
|
479
491
|
props.sessionId,
|
|
480
492
|
props.workspaceId,
|
|
@@ -492,6 +504,7 @@ export function SessionRealtimeControl(props: {
|
|
|
492
504
|
modelAvailable={selectedModel.available}
|
|
493
505
|
menuSide="top"
|
|
494
506
|
modelMenu={props.modelMenu ?? "split"}
|
|
507
|
+
showDiagnostics={props.showDiagnostics}
|
|
495
508
|
audioRef={realtime.audioRef}
|
|
496
509
|
selectedModel={selectedModel}
|
|
497
510
|
models={selection.models}
|
|
@@ -609,7 +622,7 @@ const IDLE_REALTIME_SNAPSHOT: SessionRealtimeControllerSnapshot = {
|
|
|
609
622
|
error: null,
|
|
610
623
|
};
|
|
611
624
|
|
|
612
|
-
|
|
625
|
+
type NewSessionRealtimeControlProps = {
|
|
613
626
|
client?: RealtimeControllerClient | undefined;
|
|
614
627
|
workspaceId?: string | undefined;
|
|
615
628
|
codexConnected: boolean;
|
|
@@ -627,20 +640,43 @@ export function NewSessionRealtimeControl(props: {
|
|
|
627
640
|
* `none` never attaches a model menu to the bar button.
|
|
628
641
|
*/
|
|
629
642
|
modelMenu?: "split" | "split-desktop" | "none" | undefined;
|
|
630
|
-
}
|
|
631
|
-
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
type NewSessionRealtimeSelection = {
|
|
646
|
+
models: readonly RealtimeModelOption[];
|
|
647
|
+
selectedModel: RealtimeModelOption;
|
|
648
|
+
selectModel: (modelId: string) => void;
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
export function NewSessionRealtimeControl(props: NewSessionRealtimeControlProps) {
|
|
652
|
+
if (props.models && props.selectedModel && props.onSelectModel) {
|
|
653
|
+
return (
|
|
654
|
+
<NewSessionRealtimeControlView
|
|
655
|
+
{...props}
|
|
656
|
+
selection={{
|
|
657
|
+
models: props.models,
|
|
658
|
+
selectedModel: props.selectedModel,
|
|
659
|
+
selectModel: props.onSelectModel,
|
|
660
|
+
}}
|
|
661
|
+
/>
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
return <NewSessionRealtimeControlWithInternalSelection {...props} />;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
function NewSessionRealtimeControlWithInternalSelection(props: NewSessionRealtimeControlProps) {
|
|
668
|
+
const selection = useRealtimeModelSelection({
|
|
632
669
|
client: props.client,
|
|
633
670
|
workspaceId: props.workspaceId,
|
|
634
671
|
codexConnected: props.codexConnected,
|
|
635
672
|
});
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
: internalSelection;
|
|
673
|
+
return <NewSessionRealtimeControlView {...props} selection={selection} />;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function NewSessionRealtimeControlView(
|
|
677
|
+
props: NewSessionRealtimeControlProps & { selection: NewSessionRealtimeSelection },
|
|
678
|
+
) {
|
|
679
|
+
const selection = props.selection;
|
|
644
680
|
const audioRef = useRef<HTMLAudioElement>(null);
|
|
645
681
|
const [starting, setStarting] = useState(false);
|
|
646
682
|
const [error, setError] = useState<string | null>(null);
|
|
@@ -709,7 +745,7 @@ export function RealtimeVoiceControl(props: {
|
|
|
709
745
|
* `none` = start button only.
|
|
710
746
|
*/
|
|
711
747
|
modelMenu?: "split" | "split-desktop" | "none" | undefined;
|
|
712
|
-
showDiagnostics?: boolean;
|
|
748
|
+
showDiagnostics?: boolean | undefined;
|
|
713
749
|
/** Extra classes on the in-bar mute cluster (e.g. `max-sm:hidden` when mutes live in “+”). */
|
|
714
750
|
muteControlsClassName?: string | undefined;
|
|
715
751
|
audioRef: RefObject<HTMLAudioElement | null>;
|
|
@@ -763,7 +799,7 @@ export function RealtimeVoiceControl(props: {
|
|
|
763
799
|
: modeOwned
|
|
764
800
|
? props.onStop
|
|
765
801
|
: props.onStart;
|
|
766
|
-
const diagnosticsVisible = props.showDiagnostics ??
|
|
802
|
+
const diagnosticsVisible = props.showDiagnostics ?? false;
|
|
767
803
|
const modelMenu = props.modelMenu ?? "split";
|
|
768
804
|
const showAttachedModelMenu = modelMenu === "split" || modelMenu === "split-desktop";
|
|
769
805
|
const desktopOnlyModelMenu = modelMenu === "split-desktop";
|
package/src/session-context.ts
CHANGED
package/src/session-ui.ts
CHANGED
|
@@ -24,7 +24,12 @@ export type {
|
|
|
24
24
|
} from "./timeline/turn-summary";
|
|
25
25
|
export { QueueSurface } from "./components/queue-surface";
|
|
26
26
|
export type { QueueSurfaceProps } from "./components/queue-surface";
|
|
27
|
-
export {
|
|
27
|
+
export {
|
|
28
|
+
SessionChrome,
|
|
29
|
+
sessionChromeGoalPillExplanation,
|
|
30
|
+
sessionChromeGoalPillLabel,
|
|
31
|
+
sessionChromeGoalPillState,
|
|
32
|
+
} from "./components/session-chrome";
|
|
28
33
|
export type {
|
|
29
34
|
SessionChromeAgentsSignal,
|
|
30
35
|
SessionChromeProps,
|
package/src/session.ts
CHANGED
|
@@ -38,7 +38,13 @@ export {
|
|
|
38
38
|
shouldSubmitOnKey,
|
|
39
39
|
FILE_ONLY_MESSAGE_TEXT,
|
|
40
40
|
} from "./hooks/use-composer";
|
|
41
|
-
export type {
|
|
41
|
+
export type {
|
|
42
|
+
ComposerControllerState,
|
|
43
|
+
ComposerPolicy,
|
|
44
|
+
ComposerSendExtras,
|
|
45
|
+
ComposerState,
|
|
46
|
+
UseComposerOptions,
|
|
47
|
+
} from "./hooks/use-composer";
|
|
42
48
|
export { useFileAttachments } from "./hooks/use-file-attachments";
|
|
43
49
|
export type {
|
|
44
50
|
FileAttachment,
|
|
@@ -96,6 +102,8 @@ export type {
|
|
|
96
102
|
AgentMessageItem,
|
|
97
103
|
AuthNeededItem,
|
|
98
104
|
GoalItem,
|
|
105
|
+
HumanInputAnswerSummary,
|
|
106
|
+
HumanInputItem,
|
|
99
107
|
MachineInputBatchItem,
|
|
100
108
|
MachineInputMember,
|
|
101
109
|
MemoryItem,
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ArrowRightIcon,
|
|
3
|
-
BotIcon,
|
|
4
|
-
BrainCircuitIcon,
|
|
5
|
-
BrainIcon,
|
|
6
|
-
SquareTerminalIcon,
|
|
7
|
-
} from "lucide-react";
|
|
1
|
+
import { ArrowRightIcon, BotIcon, BrainCircuitIcon } from "lucide-react";
|
|
8
2
|
import { lazy, Suspense, useLayoutEffect, useRef } from "react";
|
|
9
3
|
import { jsx as rowJsx, jsxs as rowJsxs } from "react/jsx-runtime";
|
|
10
4
|
import { Markdown } from "../components/markdown";
|
|
@@ -16,9 +10,10 @@ import type { RetainedArtifactLoader, RetainedScreenshotLoader, ToolRegistry } f
|
|
|
16
10
|
import { useSeenActivityIds } from "./seen-activity-ids";
|
|
17
11
|
import { BodyNote, PayloadBlock, ActivityDisclosure, ToolCallTruncationProvider } from "./shared";
|
|
18
12
|
import { toolDisplayName } from "./tool-display-name";
|
|
19
|
-
import type { ActivityItem, MemoryItem,
|
|
13
|
+
import type { ActivityItem, MemoryItem, WorkerItem } from "./types";
|
|
20
14
|
|
|
21
15
|
const LazyFleetDecisionRow = lazy(() => import("./fleet-decision-row"));
|
|
16
|
+
const LazyPlatformActivityRow = lazy(() => import("./platform-activity-row"));
|
|
22
17
|
|
|
23
18
|
/* ----------------------------------------------------------------------------
|
|
24
19
|
Activity rail
|
|
@@ -157,7 +152,23 @@ function renderActivity(
|
|
|
157
152
|
) {
|
|
158
153
|
switch (item.kind) {
|
|
159
154
|
case "reasoning":
|
|
160
|
-
|
|
155
|
+
case "sandbox":
|
|
156
|
+
case "startup-phase":
|
|
157
|
+
return (
|
|
158
|
+
<Suspense fallback={null}>
|
|
159
|
+
<LazyPlatformActivityRow
|
|
160
|
+
item={item}
|
|
161
|
+
d={ActivityDisclosure}
|
|
162
|
+
p={PayloadBlock}
|
|
163
|
+
t={toolDisplayName}
|
|
164
|
+
b={BotIcon}
|
|
165
|
+
m={Markdown}
|
|
166
|
+
r={truncate}
|
|
167
|
+
j={rowJsx}
|
|
168
|
+
s={rowJsxs}
|
|
169
|
+
/>
|
|
170
|
+
</Suspense>
|
|
171
|
+
);
|
|
161
172
|
case "tool-call": {
|
|
162
173
|
const Renderer = toolRegistry.resolve(item);
|
|
163
174
|
return (
|
|
@@ -172,8 +183,6 @@ function renderActivity(
|
|
|
172
183
|
}
|
|
173
184
|
case "worker":
|
|
174
185
|
return <WorkerRow item={item} onOpenSession={onOpenSession} />;
|
|
175
|
-
case "sandbox":
|
|
176
|
-
return <SandboxRow item={item} />;
|
|
177
186
|
case "memory":
|
|
178
187
|
return <MemoryRow item={item} onMemoryClick={onMemoryClick} />;
|
|
179
188
|
case "fleet-decision":
|
|
@@ -193,32 +202,6 @@ function renderActivity(
|
|
|
193
202
|
}
|
|
194
203
|
}
|
|
195
204
|
|
|
196
|
-
function ReasoningRow({ item }: { item: ReasoningItem }) {
|
|
197
|
-
// Reasoning recedes: a dimmer, lighter-weight title so action rows lead and
|
|
198
|
-
// thought rows sit a half-step back in the hierarchy. Body uses the same
|
|
199
|
-
// GFM markdown path as agent messages — Codex reasoning often carries
|
|
200
|
-
// headings/lists/bold that were previously shown as raw plaintext.
|
|
201
|
-
return (
|
|
202
|
-
<ActivityDisclosure
|
|
203
|
-
icon={<BrainIcon className="size-3.5" />}
|
|
204
|
-
iconTone="muted"
|
|
205
|
-
title={
|
|
206
|
-
item.streaming ? (
|
|
207
|
-
"Thinking"
|
|
208
|
-
) : (
|
|
209
|
-
<span className="font-normal italic text-og-fg-subtle">Thought</span>
|
|
210
|
-
)
|
|
211
|
-
}
|
|
212
|
-
running={item.streaming}
|
|
213
|
-
preview={truncate(item.text, 110)}
|
|
214
|
-
>
|
|
215
|
-
<div className="text-og-base leading-6 text-og-fg-muted [&_strong]:text-og-fg-muted">
|
|
216
|
-
<Markdown streaming={item.streaming}>{item.text}</Markdown>
|
|
217
|
-
</div>
|
|
218
|
-
</ActivityDisclosure>
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
205
|
/**
|
|
223
206
|
* Human labels for the memory kinds, translated at the SDK boundary so a raw
|
|
224
207
|
* enum slug never renders as UI. Kept local to the library (the app has its own
|
|
@@ -317,44 +300,6 @@ function MemoryRow({
|
|
|
317
300
|
);
|
|
318
301
|
}
|
|
319
302
|
|
|
320
|
-
/**
|
|
321
|
-
* A human title for a sandbox operation row. Named platform operations (the lazy
|
|
322
|
-
* `sandbox.provision` first-establish that now runs mid-turn) read as calm,
|
|
323
|
-
* status-aware English instead of a raw op id — the box coming up should look
|
|
324
|
-
* like "Starting sandbox", never an unexplained long-running command. Unnamed /
|
|
325
|
-
* unknown ops fall back to the generic id-to-words {@link toolDisplayName}.
|
|
326
|
-
*/
|
|
327
|
-
function sandboxRowTitle(item: SandboxItem): string {
|
|
328
|
-
if (item.name === "sandbox.provision") {
|
|
329
|
-
if (item.status === "failed") return "Sandbox didn’t start";
|
|
330
|
-
if (item.status === "running") return "Starting sandbox";
|
|
331
|
-
if (item.origin === "resumed") return "Sandbox reattached";
|
|
332
|
-
if (item.origin === "restored") return "Sandbox restored";
|
|
333
|
-
if (item.origin === "created") return "Sandbox created";
|
|
334
|
-
return "Sandbox ready";
|
|
335
|
-
}
|
|
336
|
-
return toolDisplayName(item.name);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
function SandboxRow({ item }: { item: SandboxItem }) {
|
|
340
|
-
return (
|
|
341
|
-
<ActivityDisclosure
|
|
342
|
-
icon={<SquareTerminalIcon className="size-3.5" />}
|
|
343
|
-
iconTone={
|
|
344
|
-
item.status === "failed" ? "failed" : item.status === "running" ? "running" : "muted"
|
|
345
|
-
}
|
|
346
|
-
title={sandboxRowTitle(item)}
|
|
347
|
-
running={item.status === "running"}
|
|
348
|
-
failed={item.status === "failed"}
|
|
349
|
-
cancelled={item.status === "cancelled"}
|
|
350
|
-
preview={item.command ?? undefined}
|
|
351
|
-
>
|
|
352
|
-
{item.command ? <PayloadBlock label="Command" value={item.command} /> : null}
|
|
353
|
-
{item.output ? <PayloadBlock label="Output" value={item.output} /> : null}
|
|
354
|
-
</ActivityDisclosure>
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
303
|
/** Spawned/messaged worker sessions get a first-class card, not a tool row. */
|
|
359
304
|
function WorkerRow({
|
|
360
305
|
item,
|
package/src/timeline/index.ts
CHANGED
|
@@ -36,12 +36,16 @@ export type {
|
|
|
36
36
|
FleetDecisionItem,
|
|
37
37
|
FleetDecisionScoreItem,
|
|
38
38
|
GoalItem,
|
|
39
|
+
HumanInputAnswerSummary,
|
|
40
|
+
HumanInputItem,
|
|
39
41
|
MachineInputBatchItem,
|
|
40
42
|
MachineInputMember,
|
|
41
43
|
MemoryItem,
|
|
42
44
|
NoticeItem,
|
|
43
45
|
ReasoningItem,
|
|
44
46
|
SandboxItem,
|
|
47
|
+
StartupPhase,
|
|
48
|
+
StartupPhaseItem,
|
|
45
49
|
SessionStatusItem,
|
|
46
50
|
TimelineGroup,
|
|
47
51
|
TimelineItem,
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import type { ReasoningItem, SandboxItem, StartupPhaseItem } from "./types";
|
|
2
|
+
|
|
3
|
+
type RowJsx = typeof import("react/jsx-runtime").jsx;
|
|
4
|
+
type RowJsxs = typeof import("react/jsx-runtime").jsxs;
|
|
5
|
+
|
|
6
|
+
export default function PlatformActivityRow({
|
|
7
|
+
item,
|
|
8
|
+
d: ActivityDisclosure,
|
|
9
|
+
p: PayloadBlock,
|
|
10
|
+
t: displayName,
|
|
11
|
+
b: BotIcon,
|
|
12
|
+
m: Markdown,
|
|
13
|
+
r: truncate,
|
|
14
|
+
j,
|
|
15
|
+
s,
|
|
16
|
+
}: {
|
|
17
|
+
item: ReasoningItem | SandboxItem | StartupPhaseItem;
|
|
18
|
+
d: typeof import("./shared").ActivityDisclosure;
|
|
19
|
+
p: typeof import("./shared").PayloadBlock;
|
|
20
|
+
t: (name: string) => string;
|
|
21
|
+
b: typeof import("lucide-react").BotIcon;
|
|
22
|
+
m: typeof import("../components/markdown").Markdown;
|
|
23
|
+
r: typeof import("../lib/format").truncate;
|
|
24
|
+
j: RowJsx;
|
|
25
|
+
s: RowJsxs;
|
|
26
|
+
}) {
|
|
27
|
+
if (item.kind === "reasoning") {
|
|
28
|
+
return j(ActivityDisclosure, {
|
|
29
|
+
icon: brainIcon(j, s),
|
|
30
|
+
iconTone: "muted",
|
|
31
|
+
title: item.streaming
|
|
32
|
+
? "Thinking"
|
|
33
|
+
: j("span", {
|
|
34
|
+
className: "font-normal italic text-og-fg-subtle",
|
|
35
|
+
children: "Thought",
|
|
36
|
+
}),
|
|
37
|
+
running: item.streaming,
|
|
38
|
+
preview: truncate(item.text, 110),
|
|
39
|
+
children: j("div", {
|
|
40
|
+
className: "text-og-base leading-6 text-og-fg-muted [&_strong]:text-og-fg-muted",
|
|
41
|
+
children: j(Markdown, { streaming: item.streaming, children: item.text }),
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (item.kind === "sandbox") {
|
|
46
|
+
return s(ActivityDisclosure, {
|
|
47
|
+
icon: terminalIcon(j, s),
|
|
48
|
+
iconTone:
|
|
49
|
+
item.status === "failed" ? "failed" : item.status === "running" ? "running" : "muted",
|
|
50
|
+
title: sandboxRowTitle(item, displayName),
|
|
51
|
+
running: item.status === "running",
|
|
52
|
+
failed: item.status === "failed",
|
|
53
|
+
cancelled: item.status === "cancelled",
|
|
54
|
+
preview: item.command ?? undefined,
|
|
55
|
+
children: [
|
|
56
|
+
item.command ? j(PayloadBlock, { label: "Command", value: item.command }, "command") : null,
|
|
57
|
+
item.output ? j(PayloadBlock, { label: "Output", value: item.output }, "output") : null,
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const failed = item.status === "failed";
|
|
63
|
+
const running = item.status === "running";
|
|
64
|
+
const duration = startupDuration(item.durationMs);
|
|
65
|
+
return j(ActivityDisclosure, {
|
|
66
|
+
icon: j(BotIcon, { className: "size-3.5" }),
|
|
67
|
+
iconTone: failed ? "failed" : running ? "running" : "muted",
|
|
68
|
+
title: startupPhaseTitle(item.phase, item.status, item.outcome),
|
|
69
|
+
preview:
|
|
70
|
+
item.phase === "model_preparation"
|
|
71
|
+
? "Includes overlapping sandbox, rig, repository, and runtime setup shown below."
|
|
72
|
+
: undefined,
|
|
73
|
+
running,
|
|
74
|
+
failed,
|
|
75
|
+
cancelled: item.status === "cancelled",
|
|
76
|
+
chip: duration ? { tone: failed ? "bad" : "muted", text: duration } : undefined,
|
|
77
|
+
expandable: false,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function brainIcon(j: RowJsx, s: RowJsxs) {
|
|
82
|
+
return lucideIcon(j, s, "brain", [
|
|
83
|
+
j("path", { d: "M 12 18V5" }, "spine"),
|
|
84
|
+
j("path", { d: "M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4" }, "center"),
|
|
85
|
+
j("path", { d: "M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5" }, "top"),
|
|
86
|
+
j("path", { d: "M17.997 5.125a4 4 0 0 1 2.526 5.77" }, "upper-right"),
|
|
87
|
+
j("path", { d: "M18 18a4 4 0 0 0 2-7.464" }, "right"),
|
|
88
|
+
j("path", { d: "M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517" }, "base"),
|
|
89
|
+
j("path", { d: "M6 18a4 4 0 0 1-2-7.464" }, "left"),
|
|
90
|
+
j("path", { d: "M6.003 5.125a4 4 0 0 0-2.526 5.77" }, "upper-left"),
|
|
91
|
+
]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function terminalIcon(j: RowJsx, s: RowJsxs) {
|
|
95
|
+
return lucideIcon(j, s, "square-terminal", [
|
|
96
|
+
j("path", { d: "m7 11 2-2-2-2" }, "prompt"),
|
|
97
|
+
j("path", { d: "M11 13h4" }, "cursor"),
|
|
98
|
+
j("rect", { width: 18, height: 18, x: 3, y: 3, rx: 2, ry: 2 }, "frame"),
|
|
99
|
+
]);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function lucideIcon(j: RowJsx, s: RowJsxs, name: string, children: ReturnType<RowJsx>[]) {
|
|
103
|
+
return s("svg", {
|
|
104
|
+
"aria-hidden": "true",
|
|
105
|
+
className: `lucide lucide-${name} size-3.5`,
|
|
106
|
+
fill: "none",
|
|
107
|
+
height: 24,
|
|
108
|
+
stroke: "currentColor",
|
|
109
|
+
strokeLinecap: "round",
|
|
110
|
+
strokeLinejoin: "round",
|
|
111
|
+
strokeWidth: 2,
|
|
112
|
+
viewBox: "0 0 24 24",
|
|
113
|
+
width: 24,
|
|
114
|
+
children,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function sandboxRowTitle(item: SandboxItem, displayName: (name: string) => string): string {
|
|
119
|
+
if (item.name === "sandbox.provision") {
|
|
120
|
+
return startupPhaseTitle(
|
|
121
|
+
"sandbox",
|
|
122
|
+
item.status === "cancelled" ? "complete" : item.status,
|
|
123
|
+
item.origin ?? null,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return displayName(item.name);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function startupPhaseTitle(
|
|
130
|
+
phase: StartupPhaseItem["phase"],
|
|
131
|
+
status: StartupPhaseItem["status"],
|
|
132
|
+
outcome: StartupPhaseItem["outcome"],
|
|
133
|
+
): string {
|
|
134
|
+
if (status === "complete" && phase === "sandbox" && outcome && outcome !== "skipped") {
|
|
135
|
+
return `Sandbox ${outcome === "resumed" ? "reattached" : outcome}`;
|
|
136
|
+
}
|
|
137
|
+
if (status === "complete" && phase === "rig" && outcome === "skipped") {
|
|
138
|
+
return "Rig already ready";
|
|
139
|
+
}
|
|
140
|
+
const statusIndex =
|
|
141
|
+
status === "running" ? 0 : status === "failed" ? 1 : status === "cancelled" ? 2 : 3;
|
|
142
|
+
return STARTUP_PHASE_TITLES[phase][statusIndex];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const STARTUP_PHASE_TITLES: Record<
|
|
146
|
+
StartupPhaseItem["phase"],
|
|
147
|
+
readonly [string, string, string, string]
|
|
148
|
+
> = {
|
|
149
|
+
queue: [
|
|
150
|
+
"Waiting for a worker",
|
|
151
|
+
"Worker startup failed",
|
|
152
|
+
"Worker wait interrupted",
|
|
153
|
+
"Worker started",
|
|
154
|
+
],
|
|
155
|
+
sandbox: [
|
|
156
|
+
"Starting sandbox",
|
|
157
|
+
"Sandbox didn’t start",
|
|
158
|
+
"Sandbox startup interrupted",
|
|
159
|
+
"Sandbox ready",
|
|
160
|
+
],
|
|
161
|
+
rig: ["Setting up rig", "Rig setup failed", "Rig setup interrupted", "Rig ready"],
|
|
162
|
+
repository: [
|
|
163
|
+
"Preparing repository",
|
|
164
|
+
"Repository preparation failed",
|
|
165
|
+
"Repository preparation interrupted",
|
|
166
|
+
"Repository ready",
|
|
167
|
+
],
|
|
168
|
+
files: [
|
|
169
|
+
"Preparing files",
|
|
170
|
+
"File preparation failed",
|
|
171
|
+
"File preparation interrupted",
|
|
172
|
+
"Files ready",
|
|
173
|
+
],
|
|
174
|
+
tools: [
|
|
175
|
+
"Connecting tools",
|
|
176
|
+
"Tool connection failed",
|
|
177
|
+
"Tool connection interrupted",
|
|
178
|
+
"Tools ready",
|
|
179
|
+
],
|
|
180
|
+
model_preparation: [
|
|
181
|
+
"Preparing runtime and model request",
|
|
182
|
+
"Runtime/model preparation failed",
|
|
183
|
+
"Runtime/model preparation interrupted",
|
|
184
|
+
"Model request dispatched",
|
|
185
|
+
],
|
|
186
|
+
provider_first_byte: [
|
|
187
|
+
"Waiting for model",
|
|
188
|
+
"Model didn’t respond",
|
|
189
|
+
"Model wait interrupted",
|
|
190
|
+
"Model started responding",
|
|
191
|
+
],
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
function startupDuration(durationMs: number | null): string | null {
|
|
195
|
+
if (durationMs === null || !Number.isFinite(durationMs) || durationMs < 0) return null;
|
|
196
|
+
if (durationMs < 1_000) return `${Math.round(durationMs)}ms`;
|
|
197
|
+
if (durationMs < 60_000) return `${(durationMs / 1_000).toFixed(1)}s`;
|
|
198
|
+
const minutes = Math.floor(durationMs / 60_000);
|
|
199
|
+
const seconds = Math.round((durationMs % 60_000) / 1_000);
|
|
200
|
+
return `${minutes}m ${String(seconds).padStart(2, "0")}s`;
|
|
201
|
+
}
|