@opengeni/react 0.15.0 → 0.23.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 +110 -10
- package/dist/{chunk-TOJR776I.js → chunk-6XUS5VFM.js} +45 -369
- package/dist/chunk-6XUS5VFM.js.map +1 -0
- package/dist/chunk-CATATY77.js +2393 -0
- package/dist/chunk-CATATY77.js.map +1 -0
- package/dist/chunk-I3BJZIG5.js +439 -0
- package/dist/chunk-I3BJZIG5.js.map +1 -0
- package/dist/chunk-TK7G6XLT.js +18 -0
- package/dist/chunk-TK7G6XLT.js.map +1 -0
- package/dist/chunk-UAHPKLB6.js +2237 -0
- package/dist/chunk-UAHPKLB6.js.map +1 -0
- package/dist/chunk-UQS7OQDE.js +591 -0
- package/dist/chunk-UQS7OQDE.js.map +1 -0
- package/dist/chunk-YDNWMKXO.js +102 -0
- package/dist/chunk-YDNWMKXO.js.map +1 -0
- package/dist/composer-CVm5uoUI.d.ts +585 -0
- package/dist/composer.d.ts +6 -0
- package/dist/composer.js +56 -0
- package/dist/composer.js.map +1 -0
- package/dist/index.d.ts +1288 -1785
- package/dist/index.js +7140 -8817
- package/dist/index.js.map +1 -1
- package/dist/machines.d.ts +412 -3
- package/dist/machines.js +3 -1
- package/dist/noto-sans-arabic-loader-IA2T4X2A.js +21 -0
- package/dist/noto-sans-arabic-loader-IA2T4X2A.js.map +1 -0
- package/dist/noto-sans-jp-loader.generated-HFGLYBR3.js +292 -0
- package/dist/noto-sans-jp-loader.generated-HFGLYBR3.js.map +1 -0
- package/dist/queue-surface-implementation-3UW3MIIR.js +890 -0
- package/dist/queue-surface-implementation-3UW3MIIR.js.map +1 -0
- package/dist/session-Db00TRwl.d.ts +446 -0
- package/dist/session-context-rgrfElMl.d.ts +58 -0
- package/dist/session.d.ts +4 -0
- package/dist/session.js +54 -0
- package/dist/session.js.map +1 -0
- package/dist/use-composer-By1wn3MM.d.ts +99 -0
- package/package.json +20 -4
- package/src/approvals.ts +5 -3
- package/src/client.ts +44 -0
- package/src/components/approval-surface.tsx +198 -0
- package/src/components/chat-composer.tsx +94 -993
- package/src/components/code-editor.tsx +104 -26
- package/src/components/command-palette.tsx +8 -2
- package/src/components/composer-transcription-control.tsx +211 -0
- package/src/components/composer.tsx +1536 -0
- package/src/components/desktop-viewer.tsx +3 -3
- package/src/components/enrollment-consent.tsx +2 -2
- package/src/components/file-browser.tsx +367 -29
- package/src/components/human-input-form.tsx +417 -0
- package/src/components/machine-card.tsx +1 -1
- package/src/components/machines-dashboard.tsx +3 -3
- package/src/components/message-timeline.tsx +205 -25
- package/src/components/model-picker.tsx +12 -3
- package/src/components/pierre-diff.tsx +32 -6
- package/src/components/queue-draft-policy.ts +18 -0
- package/src/components/queue-surface-implementation.tsx +1037 -0
- package/src/components/queue-surface-state.tsx +94 -0
- package/src/components/queue-surface.tsx +42 -559
- package/src/components/sandbox-files.tsx +138 -14
- package/src/components/sandbox-terminal.tsx +8 -2
- package/src/components/sandbox-workspace.tsx +339 -119
- package/src/components/workbench-changes.tsx +84 -33
- package/src/components/workspace-dock.tsx +188 -18
- package/src/composer.ts +60 -0
- package/src/hooks/internal.ts +115 -34
- package/src/hooks/use-composer.ts +385 -104
- package/src/hooks/use-human-input.ts +131 -0
- package/src/hooks/use-machine-chip.ts +2 -2
- package/src/hooks/use-machines.ts +27 -11
- package/src/hooks/use-sandbox-files.ts +310 -62
- package/src/hooks/use-sandbox-git.ts +154 -40
- package/src/hooks/use-sandbox-terminal.ts +28 -6
- package/src/hooks/use-session-capabilities.ts +38 -9
- package/src/hooks/use-session-control.ts +37 -8
- package/src/hooks/use-session-events.ts +522 -48
- package/src/hooks/use-session-mcp-approval-policy.ts +161 -0
- package/src/hooks/use-slash-commands.ts +38 -38
- package/src/hooks/use-transcription.ts +757 -0
- package/src/hooks/use-turn-queue.ts +134 -66
- package/src/hooks/use-windowed-sections.ts +2 -2
- package/src/hooks/use-workspace-capture.ts +146 -40
- package/src/hooks/use-workspace-edit.ts +50 -14
- package/src/hooks/use-workspace-sessions.ts +3 -0
- package/src/human-input.ts +72 -0
- package/src/index.ts +85 -6
- package/src/lib/noto-sans-arabic-loader.ts +21 -0
- package/src/lib/noto-sans-jp-loader.generated.ts +295 -0
- package/src/lib/use-portal-token-style.ts +51 -0
- package/src/lib/use-unicode-fonts.ts +57 -0
- package/src/provider.tsx +4 -69
- package/src/session-context.ts +160 -0
- package/src/session.ts +89 -0
- package/src/timeline/parsers.ts +35 -0
- package/src/timeline/projection.ts +12 -4
- package/src/timeline/tool-renderers.tsx +41 -0
- package/src/timeline/turn-summary.tsx +2 -2
- package/src/timeline/types.ts +10 -9
- package/styles/index.css +56 -0
- package/styles/index.d.ts +2 -0
- package/styles/tokens.css +11 -6
- package/styles/tokens.d.ts +2 -0
- package/dist/chunk-TOJR776I.js.map +0 -1
- package/dist/machines-BpdwuQcD.d.ts +0 -449
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { a as
|
|
3
|
-
import { SessionEvent, Session, ResourceRef, ToolRef, SessionStatus as SessionStatus$1, GitFileDiff, StreamConnectionState, EffectiveControlResumeOption, ComposerDraft, SendMessageInput, EffectiveSessionControl, FileAsset, FileResourceRef, SessionQueueSnapshot, SessionTurn, Permission, ClientModel, SessionGoal, SessionControlResponse, ScheduledTask, SessionLineageResponse, VariableSet, CreateVariableSetRequest, UpdateVariableSetRequest, VariableSetVariableMetadata, RigChange, Rig, UpdateRigRequest, RigVersion, ProposeRigChangeRequest, CreateRigRequest, CapabilityPack, PackInstallation, RegisterCapabilityPackRequest, WorkspaceRegisteredPack, EnablePackRequest, Workspace, CreateWorkspaceRequest, UpdateWorkspaceRequest, BillingBalance, UsageEvent, SessionCapabilities, DesktopStreamCapability, DesktopConnectionState, DesktopRfbFactory, TerminalCapability, FsReadResponse, FsWriteResponse, WorkspaceCaptureManifest, WorkspaceCaptureDegradedReason, MachineState, CapabilityUnavailableReason, MachineView, CodexAccountsResponse, CodexAccount, CodexRotationSettings } from '@opengeni/sdk';
|
|
4
|
-
export { MachineKind, MachineMetricsSeriesResponse, MachineState, MachineView, MachinesResponse, MetricSample } from '@opengeni/sdk';
|
|
1
|
+
import { S as SessionClientLike, C as ClientOverride } from './session-context-rgrfElMl.js';
|
|
2
|
+
export { a as EmbeddedHumanInputSessionClientLike, b as EmbeddedSessionClientLike, c as EmbeddedSessionMcpApprovalPolicyClientLike, O as OpenGeniContextValue, u as useOpenGeni, d as useOpenGeniClient } from './session-context-rgrfElMl.js';
|
|
5
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import { WorkspaceControlEvent, Session, SessionEvent, EffectiveSessionControl, ClientModel, SessionGoal, ScheduledTask, SessionLineageResponse, VariableSet, CreateVariableSetRequest, UpdateVariableSetRequest, VariableSetVariableMetadata, RigChange, Rig, UpdateRigRequest, RigVersion, ProposeRigChangeRequest, CreateRigRequest, CapabilityPack, PackInstallation, RegisterCapabilityPackRequest, WorkspaceRegisteredPack, EnablePackRequest, Workspace, CreateWorkspaceRequest, UpdateWorkspaceRequest, BillingBalance, UsageEvent, SessionCapabilities, DesktopStreamCapability, DesktopConnectionState, DesktopRfbFactory, TerminalCapability, OpenGeniRequestOptions, FsReadResponse, FsWriteResponse, WorkspaceCaptureManifest, GitFileDiff, WorkspaceCaptureDegradedReason, MachineState, SessionHumanInputRequest, SubmitHumanInputResponseRequest, HumanInputQuestion, HumanInputAnswer, Permission, SessionStatus as SessionStatus$1, CapabilityUnavailableReason, MachineView, CodexAccountsResponse, CodexAccount, CodexRotationSettings } from '@opengeni/sdk';
|
|
5
|
+
export { MachineKind, MachineMetricsSeriesResponse, MachineState, MachineView, MachinesResponse, MetricSample } from '@opengeni/sdk';
|
|
6
6
|
import * as react from 'react';
|
|
7
|
-
import {
|
|
7
|
+
import { ReactNode, ClipboardEvent, RefObject, ComponentType } from 'react';
|
|
8
|
+
import { S as SessionEventFeedOptions, C as ComposerState } from './use-composer-By1wn3MM.js';
|
|
9
|
+
export { a as ComposerSendExtras, F as FILE_ONLY_MESSAGE_TEXT, U as UseComposerOptions, c as composeSendInput, s as shouldSteerOnKey, b as shouldSubmitOnKey, u as useComposer } from './use-composer-By1wn3MM.js';
|
|
10
|
+
import { U as UseTurnQueueResult, P as PendingApproval, T as ToolCallItem, A as ActivityItem, a as TurnOutcome, b as TimelineItem, c as AgentMessageItem, d as UserMessageItem, e as AuthNeededItem } from './session-Db00TRwl.js';
|
|
11
|
+
export { B as BrowserSessionEventWindow, G as GoalItem, N as NoticeItem, f as PendingHumanInputRequest, Q as QueueMutationKind, R as ReasoningItem, S as SESSION_EVENT_BROWSER_MAX_BYTES, g as SESSION_EVENT_BROWSER_MAX_COUNT, h as SESSION_EVENT_BROWSER_PENDING_MAX_BYTES, i as SESSION_EVENT_BROWSER_PENDING_MAX_COUNT, j as SESSION_EVENT_BROWSER_SINGLE_EVENT_MAX_BYTES, k as SandboxItem, l as SessionEventsConnectionState, m as SessionStatusItem, n as TimelineGroup, o as TurnEndItem, p as UseHumanInputRequestsOptions, q as UseHumanInputRequestsResult, r as UseSessionControlOptions, s as UseSessionControlResult, t as UseSessionEventsOptions, u as UseSessionEventsResult, v as UseSessionMcpApprovalPolicyOptions, w as UseSessionMcpApprovalPolicyResult, x as UseTurnQueueOptions, W as WorkerItem, y as approvalsFromRequiresAction, z as boundBrowserSessionEventWindow, C as buildTimeline, D as creditExhaustedFromEvents, E as extractSessionRef, F as groupTimeline, H as humanInputRequestFromEvent, I as isHumanInputEvent, J as isSessionMcpApprovalPolicyEvent, K as isTurnQueueEvent, L as projectPendingApprovals, M as projectPendingHumanInputRequests, O as sessionStatusFromEvents, V as toolDisplayName, X as useHumanInputRequests, Y as useSessionControl, Z as useSessionEvents, _ as useSessionMcpApprovalPolicy, $ as useTurnQueue } from './session-Db00TRwl.js';
|
|
12
|
+
import { C as ComposerControlLinks, a as ComposerTranscriptionControlProps, U as UseFileAttachmentsResult, S as SlashCommand, b as SlashCommandContext, c as ChatComposerMessages, d as SlashArg, e as CommandContext } from './composer-CVm5uoUI.js';
|
|
13
|
+
export { f as CommandResult, g as ComposerTranscriptionControl, h as ComposerTranscriptionMessages, i as ConfirmState, F as FileAttachment, I as INITIAL_TRANSCRIPTION_CONTROL_STATE, N as Notice, O as OPEN_WORKSTREAM_CONTROL_EVENT, j as SlashCommandHandlers, T as TranscriptionControlAction, k as TranscriptionControlState, l as TranscriptionControlTransition, m as UseFileAttachmentsOptions, n as UseSlashCommandsOptions, o as UseSlashCommandsResult, p as UseTranscriptionOptions, q as UseTranscriptionResult, r as appendFinalTranscript, s as defaultChatComposerMessages, t as transitionTranscriptionControl, u as useFileAttachments, v as useSlashCommands, w as useTranscription } from './composer-CVm5uoUI.js';
|
|
14
|
+
export { CONNECTION_STATUS_META, ConnectionDot, ConnectionDotProps, ConnectionStatus, ConnectionStatusMeta, ConnectionStatusPill, ConnectionStatusPillProps, DeviceFlowPhase, EnrollmentConsent, EnrollmentConsentMachine, EnrollmentConsentPhase, EnrollmentConsentProps, EnrollmentDeviceFlow, EnrollmentDeviceFlowProps, HEALTH_TOKEN, HealthLevel, HealthVerdict, MACHINE_STATE_BADGE_META, METRICS, METRIC_WINDOWS, MachineCard, MachineCardProps, MachineDetail, MachineDetailProps, MachineDockBar, MachineDockBarProps, MachineHealthPill, MachineHealthPillProps, MachineMetrics, MachineMetricsProps, MachineStateBadgeMeta, MachineStatusPill, MachineStatusPillProps, MachinesClientLike, MachinesDashboard, MachinesDashboardProps, MetricDef, MetricHistoryChart, MetricHistoryChartProps, MetricKey, MetricSparkline, MetricSparklineProps, MetricWindow, SeriesPoint, SharedMachineDisclosure, SharedMachineDisclosureProps, UseMachinesOptions, UseMachinesResult, WINDOW_LABEL, connectionStatusForState, deriveHealth, healthPulses, pointsFor, useMachines } from './machines.js';
|
|
8
15
|
import { ClassValue } from 'clsx';
|
|
9
16
|
|
|
10
|
-
type
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*/
|
|
16
|
-
events?: SessionEvent[] | undefined;
|
|
17
|
-
enabled?: boolean | undefined;
|
|
17
|
+
type OpenGeniProviderProps = {
|
|
18
|
+
client: SessionClientLike;
|
|
19
|
+
workspaceId: string;
|
|
20
|
+
onWorkspaceControlEvent?: ((event: WorkspaceControlEvent) => void) | undefined;
|
|
21
|
+
children?: ReactNode;
|
|
18
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* Supplies the OpenGeni client + workspace to all hooks below it. Hooks also
|
|
25
|
+
* accept `{ client, workspaceId }` overrides per call for multi-workspace UIs.
|
|
26
|
+
*/
|
|
27
|
+
declare function OpenGeniProvider({ client, workspaceId, onWorkspaceControlEvent, children, }: OpenGeniProviderProps): react_jsx_runtime.JSX.Element;
|
|
19
28
|
|
|
20
29
|
type UseSessionOptions = ClientOverride & SessionEventFeedOptions & {
|
|
21
30
|
/** Re-fetch on an interval (ms). Off by default — pair with `useSessionEvents` for live status. */
|
|
@@ -38,1939 +47,1390 @@ declare function isTitleEvent(event: Pick<SessionEvent, "type">): boolean;
|
|
|
38
47
|
/** Fetch one session (with optional polling), live-patching its title on `session.title_set`. */
|
|
39
48
|
declare function useSession(sessionId: string | null | undefined, options?: UseSessionOptions): UseSessionResult;
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
/** Resources attached to this message (file uploads, repositories). */
|
|
46
|
-
resources: ResourceRef[];
|
|
47
|
-
/** Tools requested for the turn this message starts. */
|
|
48
|
-
tools: ToolRef[];
|
|
49
|
-
occurredAt: string;
|
|
50
|
-
};
|
|
51
|
-
type AgentMessageItem = {
|
|
52
|
-
kind: "agent-message";
|
|
53
|
-
id: string;
|
|
54
|
-
turnId: string | null;
|
|
55
|
-
text: string;
|
|
56
|
-
/** Still receiving deltas (no completed/turn-end seen yet). */
|
|
57
|
-
streaming: boolean;
|
|
58
|
-
occurredAt: string;
|
|
59
|
-
};
|
|
60
|
-
type ReasoningItem = {
|
|
61
|
-
kind: "reasoning";
|
|
62
|
-
id: string;
|
|
63
|
-
turnId: string | null;
|
|
64
|
-
text: string;
|
|
65
|
-
streaming: boolean;
|
|
66
|
-
occurredAt: string;
|
|
67
|
-
};
|
|
68
|
-
type ToolCallItem = {
|
|
69
|
-
kind: "tool-call";
|
|
70
|
-
id: string;
|
|
71
|
-
turnId: string | null;
|
|
72
|
-
callId: string | null;
|
|
73
|
-
name: string;
|
|
74
|
-
arguments: unknown;
|
|
75
|
-
output: unknown;
|
|
76
|
-
/**
|
|
77
|
-
* The provider-native tool item (`agent.toolCall.created.payload.raw`). Carries
|
|
78
|
-
* `type` (e.g. `apply_patch_call`, `computer_call`, `hosted_tool_call`) and the
|
|
79
|
-
* tool-specific fields the per-tool renderers read (`operation`, `action`,
|
|
80
|
-
* `providerData`, …). `undefined` for first-party MCP tools, which carry their
|
|
81
|
-
* payload in `arguments`/`output` instead.
|
|
82
|
-
*/
|
|
83
|
-
raw: unknown;
|
|
84
|
-
status: "running" | "complete" | "failed" | "cancelled";
|
|
85
|
-
occurredAt: string;
|
|
86
|
-
};
|
|
87
|
-
/**
|
|
88
|
-
* An orchestration call against another session — the manager spawning or
|
|
89
|
-
* messaging a worker. Rendered as a first-class "worker" row, not a generic
|
|
90
|
-
* tool call.
|
|
91
|
-
*/
|
|
92
|
-
type WorkerItem = {
|
|
93
|
-
kind: "worker";
|
|
94
|
-
id: string;
|
|
95
|
-
turnId: string | null;
|
|
96
|
-
callId: string | null;
|
|
97
|
-
action: "spawn" | "message";
|
|
98
|
-
/** The worker's initial message / the message sent to it, when parseable. */
|
|
99
|
-
prompt: string | null;
|
|
100
|
-
/** The target/spawned worker session id, when parseable from args/output. */
|
|
101
|
-
workerSessionId: string | null;
|
|
102
|
-
status: "running" | "complete" | "failed" | "cancelled";
|
|
103
|
-
occurredAt: string;
|
|
104
|
-
};
|
|
105
|
-
type WorkerCompletionItem = {
|
|
106
|
-
kind: "worker-completion";
|
|
107
|
-
id: string;
|
|
108
|
-
turnId: string | null;
|
|
109
|
-
occurredAt: string;
|
|
110
|
-
childSessionId: string;
|
|
111
|
-
childStatus: string;
|
|
112
|
-
goalStatus: string | null;
|
|
113
|
-
goalText: string | null;
|
|
114
|
-
evidence: string | null;
|
|
115
|
-
pausedReason: string | null;
|
|
116
|
-
text: string;
|
|
50
|
+
/** The sole human prompt queue: compact above Goal, Agents, and composer. */
|
|
51
|
+
type QueueSurfaceCommonProps = {
|
|
52
|
+
/** Focus the composer owned by this queue after checkout/removal. */
|
|
53
|
+
onRequestComposerFocus?: (() => void) | undefined;
|
|
117
54
|
};
|
|
118
|
-
type
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
55
|
+
type QueueSurfaceProps = (QueueSurfaceCommonProps & {
|
|
56
|
+
queue: UseTurnQueueResult;
|
|
57
|
+
composer: ComposerState;
|
|
58
|
+
readOnly?: false | undefined;
|
|
59
|
+
}) | (QueueSurfaceCommonProps & {
|
|
60
|
+
queue: UseTurnQueueResult;
|
|
61
|
+
composer?: undefined;
|
|
62
|
+
readOnly: true;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
/** The sole human prompt queue: compact above Goal, Agents, and composer. */
|
|
66
|
+
declare const QueueSurface: (props: QueueSurfaceProps) => react_jsx_runtime.JSX.Element | null;
|
|
67
|
+
|
|
68
|
+
type ChatComposerProps = {
|
|
69
|
+
composer: ComposerState;
|
|
70
|
+
/** Canonical workstream control, separate from lifecycle status. */
|
|
71
|
+
effectiveControl?: EffectiveSessionControl | null | undefined;
|
|
72
|
+
/** Waiting prompts already ahead of a normal Send. */
|
|
73
|
+
queuedAheadCount?: number | undefined;
|
|
74
|
+
/** Whether broader Workspace Resume is authorized for this viewer. */
|
|
75
|
+
canControlWorkspace?: boolean | undefined;
|
|
76
|
+
/** Optional host routes used to navigate from effective Pause blockers. */
|
|
77
|
+
controlLinks?: ComposerControlLinks | undefined;
|
|
78
|
+
placeholder?: string | undefined;
|
|
79
|
+
disabled?: boolean | undefined;
|
|
80
|
+
autoFocus?: boolean | undefined;
|
|
81
|
+
/** Replaces the default keyboard hint under the field. */
|
|
82
|
+
hint?: string | undefined;
|
|
83
|
+
/** App controls in the footer row, replacing the hint. */
|
|
84
|
+
controlsStart?: ReactNode | undefined;
|
|
85
|
+
/** Provider-neutral speech capability. Provider configuration stays in workspace settings. */
|
|
86
|
+
transcription?: ComposerTranscriptionControlProps | undefined;
|
|
87
|
+
/** Content rendered above the textarea, inside the field chrome. */
|
|
88
|
+
header?: ReactNode | undefined;
|
|
89
|
+
/** Paste hook composed with the attachment paste path. */
|
|
90
|
+
onPaste?: ((event: ClipboardEvent<HTMLTextAreaElement>) => void) | undefined;
|
|
91
|
+
/** Opt-in file attachment state, typically from `useFileAttachments`. */
|
|
92
|
+
attachments?: UseFileAttachmentsResult | undefined;
|
|
93
|
+
/** Opt-in model picker choices. */
|
|
94
|
+
models?: ClientModel[] | undefined;
|
|
95
|
+
selectedModel?: string | undefined;
|
|
96
|
+
onSelectModel?: ((modelId: string) => void) | undefined;
|
|
97
|
+
className?: string | undefined;
|
|
98
|
+
commands?: readonly SlashCommand[] | undefined;
|
|
99
|
+
commandContext?: SlashCommandContext | undefined;
|
|
100
|
+
onClearView?: (() => void) | undefined;
|
|
101
|
+
/** Partial overrides for all composer-owned visible and accessible copy. */
|
|
102
|
+
messages?: Partial<ChatComposerMessages> | undefined;
|
|
128
103
|
};
|
|
129
104
|
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* ordinary progress, not an exceptional state, so it renders as a calm NEUTRAL
|
|
134
|
-
* step on the rail (never accent/color). When the host app supplies an
|
|
135
|
-
* `onMemoryClick` handler the row also deep-links to the record in its memory
|
|
136
|
-
* pane; without one it is non-interactive rich content.
|
|
105
|
+
* Batteries-included chat composer. This preset is assembled exclusively from
|
|
106
|
+
* the public controller and compound primitives exported by the composer
|
|
107
|
+
* subpath, so custom and default layouts share one behavioral implementation.
|
|
137
108
|
*/
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
|
|
145
|
-
/** The memory text, ellipsized to ≤120 chars server-side. For a supersede this is the OLD text. */
|
|
146
|
-
preview: string;
|
|
147
|
-
/** The save collapsed into an existing memory (no new row was written). Saved variant only. */
|
|
148
|
-
deduped?: boolean;
|
|
149
|
-
/** The NEW text when a correction superseded the memory with a replacement; absent = updated-in-place or archived. */
|
|
150
|
-
replacementPreview?: string;
|
|
151
|
-
/**
|
|
152
|
-
* What a `memory.corrected` did: `"superseded"` (replaced by a new record, see
|
|
153
|
-
* `replacementPreview`), `"updated"` (edited in place — the record lives on), or
|
|
154
|
-
* `"archived"` (retired). Distinguishes updated-in-place from archived when there
|
|
155
|
-
* is no replacement. Corrected variant only; read defensively (may be absent).
|
|
156
|
-
*/
|
|
157
|
-
action?: string;
|
|
158
|
-
/** The saved / corrected memory's id — the deep-link target for a save. */
|
|
159
|
-
memoryId: string;
|
|
160
|
-
/** The replacement memory's id when a correction produced one — the LIVE record the deep-link targets. */
|
|
161
|
-
replacementMemoryId?: string;
|
|
162
|
-
occurredAt: string;
|
|
163
|
-
};
|
|
164
|
-
type SessionStatusItem = {
|
|
165
|
-
kind: "session-status";
|
|
166
|
-
id: string;
|
|
167
|
-
status: SessionStatus$1;
|
|
168
|
-
occurredAt: string;
|
|
169
|
-
};
|
|
170
|
-
type GoalItem = {
|
|
171
|
-
kind: "goal";
|
|
172
|
-
id: string;
|
|
173
|
-
action: "set" | "updated" | "completed" | "paused" | "resumed" | "cleared" | "continuation";
|
|
174
|
-
text: string | null;
|
|
175
|
-
occurredAt: string;
|
|
109
|
+
declare function ChatComposer({ composer, effectiveControl, queuedAheadCount, canControlWorkspace, controlLinks, placeholder, disabled, autoFocus, hint, controlsStart, transcription, header, onPaste, attachments, models, selectedModel, onSelectModel, className, commands, commandContext, onClearView, messages, }: ChatComposerProps): react_jsx_runtime.JSX.Element;
|
|
110
|
+
|
|
111
|
+
/** Event types that change the session goal (set/updated/completed/paused/...). */
|
|
112
|
+
declare function isGoalEvent(event: Pick<SessionEvent, "type">): boolean;
|
|
113
|
+
type UseGoalOptions = ClientOverride & SessionEventFeedOptions & {
|
|
114
|
+
/** Optional safety-net polling (ms). Off by default — goal.* events drive updates. */
|
|
115
|
+
pollIntervalMs?: number | undefined;
|
|
176
116
|
};
|
|
177
|
-
type
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
* surviving connection, or credential re-entry for an api-key one). The `reason`
|
|
200
|
-
* shapes the human copy but is never shown raw.
|
|
201
|
-
*/
|
|
202
|
-
type AuthNeededItem = {
|
|
203
|
-
kind: "auth-needed";
|
|
204
|
-
id: string;
|
|
205
|
-
turnId: string | null;
|
|
206
|
-
/** The connection's registrable domain, e.g. "linear.app". */
|
|
207
|
-
providerDomain: string;
|
|
208
|
-
/** The lapsed connection to reconnect, when the row survived. */
|
|
209
|
-
connectionId: string | null;
|
|
210
|
-
reason: "missing_connection" | "expired" | "insufficient_scope" | "refresh_failed" | null;
|
|
211
|
-
/** Scopes the provider now needs; may inform the copy, never shown as a raw label. */
|
|
212
|
-
scopes: string[];
|
|
213
|
-
/** The OAuth `resource` (RFC 8707) the reconnect should target, when supplied. */
|
|
214
|
-
resource: string | null;
|
|
215
|
-
/** The tool whose call triggered the reauth, for context. */
|
|
216
|
-
toolName: string | null;
|
|
217
|
-
/** A pre-minted authorization URL, when the broker already produced one. */
|
|
218
|
-
authorizationUrl: string | null;
|
|
219
|
-
occurredAt: string;
|
|
220
|
-
};
|
|
221
|
-
type TurnOutcome = "complete" | "failed" | "cancelled";
|
|
222
|
-
type TurnEndItem = {
|
|
223
|
-
kind: "turn-end";
|
|
224
|
-
id: string;
|
|
225
|
-
turnId: string | null;
|
|
226
|
-
outcome: TurnOutcome;
|
|
227
|
-
failureText: string | null;
|
|
228
|
-
occurredAt: string;
|
|
229
|
-
};
|
|
230
|
-
type TimelineItem = UserMessageItem | AgentMessageItem | ReasoningItem | ToolCallItem | WorkerItem | WorkerCompletionItem | SandboxItem | SessionStatusItem | GoalItem | NoticeItem | AuthNeededItem | MemoryItem | TurnEndItem;
|
|
231
|
-
/** Activity items cluster between chat messages (reasoning, tools, workers, sandbox, memory). */
|
|
232
|
-
type ActivityItem = ReasoningItem | ToolCallItem | WorkerItem | SandboxItem | MemoryItem;
|
|
233
|
-
type TimelineGroup = {
|
|
234
|
-
kind: "item";
|
|
235
|
-
item: TimelineItem;
|
|
236
|
-
} | {
|
|
237
|
-
kind: "activity";
|
|
238
|
-
id: string;
|
|
239
|
-
items: ActivityItem[];
|
|
240
|
-
outcome?: TurnOutcome;
|
|
241
|
-
failureText?: string;
|
|
242
|
-
} | {
|
|
243
|
-
kind: "turn";
|
|
244
|
-
id: string;
|
|
245
|
-
outcome: TurnOutcome;
|
|
246
|
-
failureText?: string;
|
|
247
|
-
startedAt: string;
|
|
248
|
-
endedAt: string;
|
|
249
|
-
groups: TimelineGroup[];
|
|
117
|
+
type UseGoalResult = {
|
|
118
|
+
/** The session goal, or null when the session has none. */
|
|
119
|
+
goal: SessionGoal | null;
|
|
120
|
+
/** Convenience flags over `goal.status`. */
|
|
121
|
+
isActive: boolean;
|
|
122
|
+
isPaused: boolean;
|
|
123
|
+
isCompleted: boolean;
|
|
124
|
+
loading: boolean;
|
|
125
|
+
error: Error | null;
|
|
126
|
+
refresh: () => Promise<void>;
|
|
127
|
+
/** Pause the goal loop (PATCH status=paused). */
|
|
128
|
+
pause: (rationale?: string) => Promise<SessionGoal | null>;
|
|
129
|
+
/** Resume a paused goal: resets counters and re-arms continuations. */
|
|
130
|
+
resume: () => Promise<SessionGoal | null>;
|
|
131
|
+
/** Clear the session goal; goal-less sessions remain a successful no-op. */
|
|
132
|
+
clearGoal: () => Promise<void>;
|
|
133
|
+
/** Alias for `clearGoal`. */
|
|
134
|
+
deleteGoal: () => Promise<void>;
|
|
135
|
+
/** True while a pause/resume/clear is in flight. */
|
|
136
|
+
updating: boolean;
|
|
137
|
+
mutationError: Error | null;
|
|
138
|
+
clearMutationError: () => void;
|
|
250
139
|
};
|
|
251
|
-
|
|
252
|
-
declare function buildTimeline(events: SessionEvent[]): TimelineItem[];
|
|
253
|
-
/**
|
|
254
|
-
* Whether the session's most recent turn ended in credit exhaustion — the
|
|
255
|
-
* terminal credit state apps key their "add credits" affordances on. Derived
|
|
256
|
-
* from the LAST turn-end event (completed/failed/cancelled): a later turn that
|
|
257
|
-
* settles any other way (someone topped up and kept working) clears it.
|
|
258
|
-
*/
|
|
259
|
-
declare function creditExhaustedFromEvents(events: SessionEvent[]): boolean;
|
|
260
|
-
/** The latest session status carried in the event log, if any. */
|
|
261
|
-
declare function sessionStatusFromEvents(events: SessionEvent[]): SessionStatus$1 | null;
|
|
262
|
-
declare function groupTimeline(items: TimelineItem[]): TimelineGroup[];
|
|
263
140
|
/**
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
141
|
+
* The session's goal: state, the autonomy counters (`autoContinuations`,
|
|
142
|
+
* `noProgressStreak`), and pause/resume control. A goal-less session yields
|
|
143
|
+
* `goal: null` (the 404 is absorbed). Live-updates on `goal.*` events —
|
|
144
|
+
* pass `options.events` from `useSessionEvents` to reuse its stream.
|
|
267
145
|
*/
|
|
268
|
-
declare function
|
|
269
|
-
/**
|
|
270
|
-
* Readable label for a tool call ("session_create" -> "session create").
|
|
271
|
-
*
|
|
272
|
-
* MCP tools are namespaced `<serverId>__<toolName>` (see prefixedMcpToolName),
|
|
273
|
-
* and for catalog-imported servers that serverId is an opaque slug+hash
|
|
274
|
-
* ("mcp-integrations-sh-supabase-com-34ed9dcf1390-0i6tcf8"). De-slugging the
|
|
275
|
-
* whole thing leaked that id into the timeline; strip the server prefix and show
|
|
276
|
-
* just the tool ("list organizations"). Names without the `__` boundary (plain
|
|
277
|
-
* built-ins like "session_create") are unaffected.
|
|
278
|
-
*/
|
|
279
|
-
declare function toolDisplayName(name: string): string;
|
|
146
|
+
declare function useGoal(sessionId: string | null | undefined, options?: UseGoalOptions): UseGoalResult;
|
|
280
147
|
|
|
281
|
-
type
|
|
282
|
-
|
|
148
|
+
type UseScheduledTasksOptions = ClientOverride & {
|
|
149
|
+
limit?: number | undefined;
|
|
150
|
+
pollIntervalMs?: number | undefined;
|
|
151
|
+
enabled?: boolean | undefined;
|
|
283
152
|
};
|
|
284
|
-
type
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
render: ToolRenderer;
|
|
290
|
-
} | {
|
|
291
|
-
match: "name";
|
|
292
|
-
name: string;
|
|
293
|
-
render: ToolRenderer;
|
|
153
|
+
type UseScheduledTasksResult = {
|
|
154
|
+
tasks: ScheduledTask[];
|
|
155
|
+
loading: boolean;
|
|
156
|
+
error: Error | null;
|
|
157
|
+
refresh: () => Promise<void>;
|
|
294
158
|
};
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
159
|
+
/** List the workspace's scheduled tasks (drift checks, sentinels, reapers, ...). */
|
|
160
|
+
declare function useScheduledTasks(options?: UseScheduledTasksOptions): UseScheduledTasksResult;
|
|
161
|
+
|
|
162
|
+
type UseWorkspaceSessionsOptions = ClientOverride & {
|
|
163
|
+
limit?: number | undefined;
|
|
164
|
+
parentSessionId?: string | null | undefined;
|
|
165
|
+
cursor?: string | undefined;
|
|
166
|
+
search?: string | undefined;
|
|
167
|
+
/** Refresh interval (ms) for fleet/manager views. Off by default. */
|
|
168
|
+
pollIntervalMs?: number | undefined;
|
|
169
|
+
enabled?: boolean | undefined;
|
|
300
170
|
};
|
|
301
|
-
type
|
|
171
|
+
type UseWorkspaceSessionsResult = {
|
|
302
172
|
/**
|
|
303
|
-
*
|
|
304
|
-
*
|
|
173
|
+
* All visible rows, with pins first. This preserves the pre-pinning hook
|
|
174
|
+
* contract for consumers that only read `sessions`.
|
|
305
175
|
*/
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
|
|
176
|
+
sessions: Session[];
|
|
177
|
+
/** The complete personal pinned section, also present in `sessions`. */
|
|
178
|
+
pinned: Session[];
|
|
179
|
+
/** True when the server omitted older pins from its bounded pinned section. */
|
|
180
|
+
pinnedTruncated: boolean;
|
|
181
|
+
nextCursor: string | null;
|
|
182
|
+
loading: boolean;
|
|
183
|
+
error: Error | null;
|
|
184
|
+
refresh: () => Promise<void>;
|
|
309
185
|
};
|
|
310
|
-
/**
|
|
311
|
-
declare function
|
|
312
|
-
/**
|
|
313
|
-
* Build a tool registry from a set of entries and a fallback. The returned
|
|
314
|
-
* registry resolves in priority order: `raw.type` entries first, then `name`
|
|
315
|
-
* entries, then the fallback. Consumer `entries` are consulted before the
|
|
316
|
-
* built-in `baseEntries`, so they shadow defaults cleanly.
|
|
317
|
-
*/
|
|
318
|
-
declare function createToolRegistry(baseEntries: ToolRegistryEntry[], baseFallback: ToolRenderer, options?: CreateToolRegistryOptions): ToolRegistry;
|
|
319
|
-
|
|
320
|
-
/** The built-in tool renderer registry: every first-party tool plus a fallback. */
|
|
321
|
-
declare const defaultToolRegistry: ToolRegistry;
|
|
322
|
-
/** Build a registry that extends the built-ins with consumer entries/fallback. */
|
|
323
|
-
declare function createDefaultToolRegistry(options?: Parameters<typeof createToolRegistry>[2]): ToolRegistry;
|
|
186
|
+
/** List the workspace's sessions — the data behind fleet and manager views. */
|
|
187
|
+
declare function useWorkspaceSessions(options?: UseWorkspaceSessionsOptions): UseWorkspaceSessionsResult;
|
|
324
188
|
|
|
325
|
-
type
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
onOpenSession?: ((sessionId: string) => void) | undefined;
|
|
331
|
-
/**
|
|
332
|
-
* Deep-link a memory row to its record in the host's memory pane. Opt-in: the
|
|
333
|
-
* library draws no "View in memory" affordance without a handler (the memory
|
|
334
|
-
* row is then non-interactive rich content). See {@link MessageTimelineProps}.
|
|
335
|
-
*/
|
|
336
|
-
onMemoryClick?: ((memoryId: string) => void) | undefined;
|
|
337
|
-
/** Drop the left rule + indent (used inside a folded turn summary). */
|
|
338
|
-
bare?: boolean | undefined;
|
|
339
|
-
className?: string | undefined;
|
|
189
|
+
type UseSessionLineageOptions = ClientOverride & {
|
|
190
|
+
events?: SessionEvent[] | undefined;
|
|
191
|
+
/** Refresh interval (ms). Off by default. */
|
|
192
|
+
pollIntervalMs?: number | undefined;
|
|
193
|
+
enabled?: boolean | undefined;
|
|
340
194
|
};
|
|
341
|
-
|
|
195
|
+
type UseSessionLineageResult = {
|
|
196
|
+
lineage: SessionLineageResponse | null;
|
|
197
|
+
loading: boolean;
|
|
198
|
+
error: Error | null;
|
|
199
|
+
refresh: () => Promise<void>;
|
|
200
|
+
};
|
|
201
|
+
declare function isLineageRefreshEvent(event: SessionEvent): boolean;
|
|
202
|
+
/** Read the ancestors + descendant tree for one session. Data-only; no UI state. */
|
|
203
|
+
declare function useSessionLineage(sessionId: string | null | undefined, options?: UseSessionLineageOptions): UseSessionLineageResult;
|
|
342
204
|
|
|
205
|
+
type UseVariableSetsOptions = ClientOverride & {
|
|
206
|
+
pollIntervalMs?: number | undefined;
|
|
207
|
+
enabled?: boolean | undefined;
|
|
208
|
+
};
|
|
209
|
+
type UseVariableSetsResult = {
|
|
210
|
+
variableSets: VariableSet[];
|
|
211
|
+
loading: boolean;
|
|
212
|
+
error: Error | null;
|
|
213
|
+
refresh: () => Promise<void>;
|
|
214
|
+
create: (request: CreateVariableSetRequest) => Promise<VariableSet | null>;
|
|
215
|
+
update: (variableSetId: string, request: UpdateVariableSetRequest) => Promise<VariableSet | null>;
|
|
216
|
+
remove: (variableSetId: string) => Promise<boolean>;
|
|
217
|
+
/** Set/rotate a variable. Values are write-only — reads expose metadata only. */
|
|
218
|
+
setVariable: (variableSetId: string, name: string, value: string) => Promise<VariableSetVariableMetadata | null>;
|
|
219
|
+
deleteVariable: (variableSetId: string, name: string) => Promise<boolean>;
|
|
220
|
+
mutating: boolean;
|
|
221
|
+
mutationError: Error | null;
|
|
222
|
+
clearMutationError: () => void;
|
|
223
|
+
};
|
|
343
224
|
/**
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
225
|
+
* Variable sets (named, encrypted variable sets attached to sessions
|
|
226
|
+
* and scheduled tasks). Variable values are write-only end to end: this hook
|
|
227
|
+
* never sees a value after it is sent.
|
|
347
228
|
*/
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
229
|
+
declare function useVariableSets(options?: UseVariableSetsOptions): UseVariableSetsResult;
|
|
230
|
+
/** @deprecated use UseVariableSetsOptions */
|
|
231
|
+
type UseEnvironmentsOptions = UseVariableSetsOptions;
|
|
232
|
+
/** @deprecated use UseVariableSetsResult */
|
|
233
|
+
type UseEnvironmentsResult = UseVariableSetsResult & {
|
|
234
|
+
environments: VariableSet[];
|
|
351
235
|
};
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
* `chip` is already supplied — the caller's chip wins). Output is still visible
|
|
375
|
-
* on expand; this is a quiet status signal, not a blocking banner.
|
|
376
|
-
*
|
|
377
|
-
* Renderers should pass `failed={item.status === "failed"}` on their settled
|
|
378
|
-
* (non-running) paths so any tool with a failed status shows a consistent
|
|
379
|
-
* affordance without each renderer having to duplicate the logic.
|
|
380
|
-
*/
|
|
381
|
-
failed?: boolean | undefined;
|
|
382
|
-
/**
|
|
383
|
-
* When true the row carries a calm "interrupted" affordance: the icon stays
|
|
384
|
-
* muted (no red) and a quiet "interrupted" chip appears in the right gutter
|
|
385
|
-
* (unless an explicit `chip` is already supplied — the caller's chip wins).
|
|
386
|
-
* This is the cancelled-status analogue of `failed`, but deliberately calm
|
|
387
|
-
* and neutral — it is NOT an error; the user chose to stop.
|
|
388
|
-
*
|
|
389
|
-
* Renderers should pass `cancelled={item.status === "cancelled"}` so any
|
|
390
|
-
* in-flight item that was interrupted on turn.cancelled reads consistently.
|
|
391
|
-
* `cancelled` is ignored when `failed` is also true (failure takes precedence).
|
|
392
|
-
*/
|
|
393
|
-
cancelled?: boolean | undefined;
|
|
394
|
-
/** When false the row is a static line (no expand affordance). */
|
|
395
|
-
expandable?: boolean | undefined;
|
|
396
|
-
children?: ReactNode | undefined;
|
|
236
|
+
/** @deprecated use useVariableSets */
|
|
237
|
+
declare function useEnvironments(options?: UseEnvironmentsOptions): UseEnvironmentsResult;
|
|
238
|
+
|
|
239
|
+
type UseRigsOptions = ClientOverride & {
|
|
240
|
+
pollIntervalMs?: number | undefined;
|
|
241
|
+
enabled?: boolean | undefined;
|
|
242
|
+
};
|
|
243
|
+
type UseRigsResult = {
|
|
244
|
+
rigs: Rig[];
|
|
245
|
+
loading: boolean;
|
|
246
|
+
error: Error | null;
|
|
247
|
+
refresh: () => Promise<void>;
|
|
248
|
+
create: (request: CreateRigRequest) => Promise<Rig | null>;
|
|
249
|
+
update: (rigId: string, request: UpdateRigRequest) => Promise<Rig | null>;
|
|
250
|
+
remove: (rigId: string) => Promise<boolean>;
|
|
251
|
+
listVersions: (rigId: string) => Promise<RigVersion[] | null>;
|
|
252
|
+
activateVersion: (rigId: string, versionId: string) => Promise<RigVersion | null>;
|
|
253
|
+
listChanges: (rigId: string) => Promise<RigChange[] | null>;
|
|
254
|
+
proposeChange: (rigId: string, request: ProposeRigChangeRequest) => Promise<RigChange | null>;
|
|
255
|
+
mutating: boolean;
|
|
256
|
+
mutationError: Error | null;
|
|
257
|
+
clearMutationError: () => void;
|
|
397
258
|
};
|
|
398
259
|
/**
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
* the body mounts only when expanded.
|
|
403
|
-
*/
|
|
404
|
-
declare function ActivityDisclosure({ icon, iconTone: iconToneProp, title, titleMono, running, preview, media, chip: chipProp, failed, cancelled, expandable, children, }: ActivityDisclosureProps): react_jsx_runtime.JSX.Element;
|
|
405
|
-
declare function TermBlock({ command, workdir, output, live, tailLines, failed, }: {
|
|
406
|
-
/**
|
|
407
|
-
* The command shown in the prompt header. Pass `null` when the row title
|
|
408
|
-
* already carries it (e.g. an exec row titled `$ cmd`): the header then drops
|
|
409
|
-
* the command — and the whole prompt line if there is no workdir either — so
|
|
410
|
-
* the command never reads twice, stacked, above the output.
|
|
411
|
-
*/
|
|
412
|
-
command: string | null;
|
|
413
|
-
workdir?: string | null | undefined;
|
|
414
|
-
/** The FULL output. TermBlock owns the tail/full slicing internally. */
|
|
415
|
-
output: string;
|
|
416
|
-
live?: boolean | undefined;
|
|
417
|
-
/** A non-zero exit / failed call — tints the left accent red (the one hue). */
|
|
418
|
-
failed?: boolean | undefined;
|
|
419
|
-
/**
|
|
420
|
-
* When the output exceeds the tail window, only the last `tailLines` are shown
|
|
421
|
-
* with a "show full output" toggle. The component holds the full text, so the
|
|
422
|
-
* toggle reveals the rest (never a dead affordance). Defaults to 12.
|
|
423
|
-
*/
|
|
424
|
-
tailLines?: number | undefined;
|
|
425
|
-
}): react_jsx_runtime.JSX.Element;
|
|
426
|
-
declare function PayloadBlock({ label, value, failed, }: {
|
|
427
|
-
label: string;
|
|
428
|
-
value: unknown;
|
|
429
|
-
failed?: boolean | undefined;
|
|
430
|
-
}): react_jsx_runtime.JSX.Element | null;
|
|
431
|
-
/** A quiet inline note inside an expanded body (lost output, empty frame, …). */
|
|
432
|
-
declare function BodyNote({ children, tone, }: {
|
|
433
|
-
children: ReactNode;
|
|
434
|
-
tone?: "error" | "muted" | undefined;
|
|
435
|
-
}): react_jsx_runtime.JSX.Element;
|
|
436
|
-
/**
|
|
437
|
-
* A loading screenshot placeholder. A faint camera glyph over a shimmering box,
|
|
438
|
-
* so a still frame of the running state reads unambiguously as "capturing" — not
|
|
439
|
-
* a broken thumbnail.
|
|
260
|
+
* Rigs (workspace-scoped, versioned sandbox machine definitions). The list
|
|
261
|
+
* polls; version/change reads are on-demand (they are per-rig detail, not part
|
|
262
|
+
* of the list surface).
|
|
440
263
|
*/
|
|
441
|
-
declare function
|
|
442
|
-
|
|
443
|
-
|
|
264
|
+
declare function useRigs(options?: UseRigsOptions): UseRigsResult;
|
|
265
|
+
type UseRigOptions = ClientOverride & {
|
|
266
|
+
pollIntervalMs?: number | undefined;
|
|
267
|
+
enabled?: boolean | undefined;
|
|
268
|
+
};
|
|
269
|
+
type UseRigResult = {
|
|
270
|
+
rig: Rig | null;
|
|
271
|
+
loading: boolean;
|
|
272
|
+
error: Error | null;
|
|
273
|
+
refresh: () => Promise<void>;
|
|
274
|
+
update: (request: UpdateRigRequest) => Promise<Rig | null>;
|
|
275
|
+
remove: () => Promise<boolean>;
|
|
276
|
+
activateVersion: (versionId: string) => Promise<RigVersion | null>;
|
|
277
|
+
proposeChange: (request: ProposeRigChangeRequest) => Promise<RigChange | null>;
|
|
278
|
+
/** Re-run verification for a change (asynchronous — poll for the outcome). */
|
|
279
|
+
verifyChange: (changeId: string) => Promise<RigChange | null>;
|
|
280
|
+
/** Promote a verified definition_edit into a new active version (rigs:manage). */
|
|
281
|
+
promoteChange: (changeId: string) => Promise<RigVersion | null>;
|
|
282
|
+
/** Re-verify the active version's checks in a clean throwaway sandbox. */
|
|
283
|
+
verify: () => Promise<{
|
|
284
|
+
ok: boolean;
|
|
285
|
+
versionId: string;
|
|
286
|
+
} | null>;
|
|
287
|
+
mutating: boolean;
|
|
288
|
+
mutationError: Error | null;
|
|
289
|
+
clearMutationError: () => void;
|
|
290
|
+
};
|
|
444
291
|
/**
|
|
445
|
-
* A
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
* Outside one it degrades to a plain, non-interactive image — never a dead
|
|
449
|
-
* "Expand" button that announces an action it cannot perform.
|
|
292
|
+
* A single rig (its active version + counts), polled so verification and
|
|
293
|
+
* promotion state stay live. Owns the rig's write actions; the versions and
|
|
294
|
+
* changes lists are separate polled reads (`useRigVersions`/`useRigChanges`).
|
|
450
295
|
*/
|
|
451
|
-
declare function
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
296
|
+
declare function useRig(rigId: string, options?: UseRigOptions): UseRigResult;
|
|
297
|
+
type UseRigVersionsOptions = ClientOverride & {
|
|
298
|
+
pollIntervalMs?: number | undefined;
|
|
299
|
+
enabled?: boolean | undefined;
|
|
300
|
+
};
|
|
301
|
+
type UseRigVersionsResult = {
|
|
302
|
+
versions: RigVersion[];
|
|
303
|
+
loading: boolean;
|
|
304
|
+
error: Error | null;
|
|
305
|
+
refresh: () => Promise<void>;
|
|
306
|
+
};
|
|
307
|
+
/** A rig's append-only version history, newest-first (polled). */
|
|
308
|
+
declare function useRigVersions(rigId: string, options?: UseRigVersionsOptions): UseRigVersionsResult;
|
|
309
|
+
type UseRigChangesOptions = ClientOverride & {
|
|
310
|
+
pollIntervalMs?: number | undefined;
|
|
311
|
+
enabled?: boolean | undefined;
|
|
312
|
+
};
|
|
313
|
+
type UseRigChangesResult = {
|
|
314
|
+
changes: RigChange[];
|
|
315
|
+
loading: boolean;
|
|
316
|
+
error: Error | null;
|
|
317
|
+
refresh: () => Promise<void>;
|
|
318
|
+
};
|
|
456
319
|
/**
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
* so it never breaks the row layout. Like {@link Thumbnail}, it degrades to a
|
|
460
|
-
* plain image outside a `LightboxProvider`.
|
|
320
|
+
* A rig's change queue (polled). The default poll cadence lets a change move
|
|
321
|
+
* through verifying → merged/rejected without a manual refresh.
|
|
461
322
|
*/
|
|
462
|
-
declare function
|
|
463
|
-
src: string;
|
|
464
|
-
caption?: string | undefined;
|
|
465
|
-
alt?: string;
|
|
466
|
-
}): react_jsx_runtime.JSX.Element;
|
|
323
|
+
declare function useRigChanges(rigId: string, options?: UseRigChangesOptions): UseRigChangesResult;
|
|
467
324
|
|
|
468
|
-
type
|
|
469
|
-
|
|
325
|
+
type UsePacksOptions = ClientOverride & {
|
|
326
|
+
pollIntervalMs?: number | undefined;
|
|
327
|
+
enabled?: boolean | undefined;
|
|
470
328
|
};
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
329
|
+
type UsePacksResult = {
|
|
330
|
+
/** Built-in + registered packs available to the workspace. */
|
|
331
|
+
packs: CapabilityPack[];
|
|
332
|
+
/** Enable/disable state per pack. */
|
|
333
|
+
installations: PackInstallation[];
|
|
334
|
+
/** The installation for a pack id, if any. */
|
|
335
|
+
installationFor: (packId: string) => PackInstallation | null;
|
|
336
|
+
loading: boolean;
|
|
337
|
+
error: Error | null;
|
|
338
|
+
refresh: () => Promise<void>;
|
|
339
|
+
/** Register (or replace) a workspace-scoped pack manifest. */
|
|
340
|
+
register: (manifest: RegisterCapabilityPackRequest) => Promise<WorkspaceRegisteredPack | null>;
|
|
341
|
+
enable: (packId: string, request?: EnablePackRequest) => Promise<PackInstallation | null>;
|
|
342
|
+
/** Unregister a workspace-scoped pack (built-ins cannot be removed). */
|
|
343
|
+
remove: (packId: string) => Promise<boolean>;
|
|
344
|
+
mutating: boolean;
|
|
345
|
+
mutationError: Error | null;
|
|
346
|
+
clearMutationError: () => void;
|
|
347
|
+
};
|
|
348
|
+
/** Capability packs: catalog + installations + register/enable/unregister. */
|
|
349
|
+
declare function usePacks(options?: UsePacksOptions): UsePacksResult;
|
|
492
350
|
|
|
351
|
+
type UseWorkspacesOptions = Pick<ClientOverride, "client"> & {
|
|
352
|
+
pollIntervalMs?: number | undefined;
|
|
353
|
+
enabled?: boolean | undefined;
|
|
354
|
+
};
|
|
355
|
+
type UseWorkspacesResult = {
|
|
356
|
+
workspaces: Workspace[];
|
|
357
|
+
loading: boolean;
|
|
358
|
+
error: Error | null;
|
|
359
|
+
refresh: () => Promise<void>;
|
|
360
|
+
create: (request: CreateWorkspaceRequest) => Promise<Workspace | null>;
|
|
361
|
+
update: (workspaceId: string, request: UpdateWorkspaceRequest) => Promise<Workspace | null>;
|
|
362
|
+
mutating: boolean;
|
|
363
|
+
mutationError: Error | null;
|
|
364
|
+
clearMutationError: () => void;
|
|
365
|
+
};
|
|
493
366
|
/**
|
|
494
|
-
*
|
|
495
|
-
*
|
|
367
|
+
* The caller's workspaces (workspace switchers, onboarding). Not scoped to
|
|
368
|
+
* the provider's workspace, so it only needs the client.
|
|
496
369
|
*/
|
|
497
|
-
declare function
|
|
498
|
-
defaultOpen: boolean;
|
|
499
|
-
children: ReactNode;
|
|
500
|
-
}): react_jsx_runtime.JSX.Element;
|
|
501
|
-
|
|
502
|
-
type TurnSummaryProps = {
|
|
503
|
-
/** The activity items in the turn (used only to compute the facet counts). */
|
|
504
|
-
items: ActivityItem[];
|
|
505
|
-
/**
|
|
506
|
-
* The settled verdict — or absent for a completed CLUSTER of a still-running
|
|
507
|
-
* turn, which folds neutrally: no verdict glyph (the turn has none yet), a
|
|
508
|
-
* quiet pulse dot in its place so alignment and the running feel both hold.
|
|
509
|
-
*/
|
|
510
|
-
outcome?: TurnOutcome | undefined;
|
|
511
|
-
/** A short failure reason shown inline on a failed chip (never hidden). */
|
|
512
|
-
failureText?: string | undefined;
|
|
513
|
-
/** Elapsed turn duration; shown as a trailing facet when at least 1s. */
|
|
514
|
-
durationMs?: number | undefined;
|
|
515
|
-
/** Start expanded. */
|
|
516
|
-
defaultOpen?: boolean | undefined;
|
|
517
|
-
/**
|
|
518
|
-
* A nested fold — a cluster or sub-turn INSIDE an already-expanded turn. It
|
|
519
|
-
* drops the bordered/filled chip and renders as a plain disclosure node on the
|
|
520
|
-
* parent's rail (chevron + glyph + facets), so expanding a turn reveals a thread
|
|
521
|
-
* of nodes, never a stack of boxes-in-boxes. The top-level fold stays a chip.
|
|
522
|
-
*/
|
|
523
|
-
bare?: boolean | undefined;
|
|
524
|
-
/** The rendered activity rail revealed on expand. */
|
|
525
|
-
children: React.ReactNode;
|
|
526
|
-
};
|
|
527
|
-
declare function TurnSummary({ items, outcome, failureText, durationMs, defaultOpen, bare, children, }: TurnSummaryProps): react_jsx_runtime.JSX.Element;
|
|
528
|
-
|
|
529
|
-
/** Recover the exit code from a sandbox exec banner (`Process exited with code N`). */
|
|
530
|
-
declare function sandboxCommandExitCode(out: unknown): number | null;
|
|
531
|
-
/**
|
|
532
|
-
* Recover the numeric exec-session id the sandbox embeds for a STILL-RUNNING
|
|
533
|
-
* (backgrounded) process (`Process running with session ID N`). A finished
|
|
534
|
-
* command emits `Process exited with code N` instead, which yields `null`.
|
|
535
|
-
*/
|
|
536
|
-
declare function parseExecBannerSessionId(out: unknown): number | null;
|
|
537
|
-
/** Strip the exec banner (`Chunk ID ...\n...\nOutput:\n`) down to the command's stdout. */
|
|
538
|
-
declare function stripExecBanner(out: unknown): string;
|
|
539
|
-
/** The sandbox clamped the output (token/line truncation markers in the banner). */
|
|
540
|
-
declare function execTruncated(out: unknown): boolean;
|
|
541
|
-
/** A `write_stdin` whose target PTY vanished (`write_stdin failed: session not found: N`). */
|
|
542
|
-
declare function isExecSessionLostBanner(out: unknown): boolean;
|
|
543
|
-
/** True when the exec stdout looks binary/garbled (a NUL byte or ELF magic). */
|
|
544
|
-
declare function looksBinary(text: string): boolean;
|
|
545
|
-
/**
|
|
546
|
-
* Render unprintable control characters as caret notation (0x03 -> `^C`) so a
|
|
547
|
-
* `write_stdin` keystroke payload reads cleanly in the row title.
|
|
548
|
-
*/
|
|
549
|
-
declare function controlCaret(printable: string): string;
|
|
550
|
-
/** One operation inside an `apply_patch_call` (a V4A file edit). */
|
|
551
|
-
type ApplyPatchOperation = {
|
|
552
|
-
/**
|
|
553
|
-
* The V4A op kind. The three canonical values are `create_file`,
|
|
554
|
-
* `update_file`, and `delete_file`; the open `string` tail tolerates a
|
|
555
|
-
* forward-compatible/unknown op kind from the provider without a type error
|
|
556
|
-
* (it falls through to the "Edited" treatment).
|
|
557
|
-
*/
|
|
558
|
-
type: "create_file" | "update_file" | "delete_file" | (string & {});
|
|
559
|
-
path: string;
|
|
560
|
-
/** Rename target -- when present the op is a move/rename. */
|
|
561
|
-
moveTo?: string | null | undefined;
|
|
562
|
-
/** The V4A hunk string (`@@ ...` lines with `+`/`-`/context prefixes). */
|
|
563
|
-
diff?: string | undefined;
|
|
564
|
-
};
|
|
565
|
-
/**
|
|
566
|
-
* Parse a single V4A `apply_patch` operation into the SDK's `GitFileDiff` shape
|
|
567
|
-
* so it can flow into the SAME `DiffView` / `PierreDiff` the Files tab uses.
|
|
568
|
-
* Throws on a hunk string it cannot structure (no `@@` anchor on an update); the
|
|
569
|
-
* renderer catches and falls back to a raw-patch view.
|
|
570
|
-
*/
|
|
571
|
-
declare function v4aToGitFileDiff(op: ApplyPatchOperation): GitFileDiff;
|
|
572
|
-
/**
|
|
573
|
-
* Extract the `apply_patch` operations from a provider-native tool item's `raw`
|
|
574
|
-
* payload, normalizing the two wire shapes (`raw.operations[]` for a multi-file
|
|
575
|
-
* patch, `raw.operation` for a single op). The single owner of this shape so the
|
|
576
|
-
* renderer and the turn-summary facet counter never drift.
|
|
577
|
-
*/
|
|
578
|
-
declare function applyPatchOps(raw: unknown): ApplyPatchOperation[];
|
|
579
|
-
/**
|
|
580
|
-
* True when a tool item is an `apply_patch_call` — by its provider-native
|
|
581
|
-
* `raw.type` (the live-wire source of truth) or by tool `name` (first-party
|
|
582
|
-
* replays that omit `raw`). Centralizes the rawType-or-name check.
|
|
583
|
-
*/
|
|
584
|
-
declare function isApplyPatch(item: {
|
|
585
|
-
name: string;
|
|
586
|
-
raw: unknown;
|
|
587
|
-
}): boolean;
|
|
588
|
-
/** Deep-redact secret-looking values so arguments never leak a key into the UI. */
|
|
589
|
-
declare function redactSecrets(value: unknown): unknown;
|
|
590
|
-
/** Parse tool arguments that may arrive as a JSON string or an object. */
|
|
591
|
-
declare function parseToolArgs(args: unknown): Record<string, unknown>;
|
|
592
|
-
/** The last non-empty line of a string -- the compact "what happened" peek. */
|
|
593
|
-
declare function tailPeek(text: string): string;
|
|
594
|
-
/**
|
|
595
|
-
* Unwrap an MCP tool result (`{ content: [{ type: "text", text }], isError? }`)
|
|
596
|
-
* into a flat `{ text, isError }`. Non-MCP outputs pass through as their string
|
|
597
|
-
* form.
|
|
598
|
-
*/
|
|
599
|
-
declare function unwrapMcpOutput(output: unknown): {
|
|
600
|
-
text: string;
|
|
601
|
-
isError: boolean;
|
|
602
|
-
};
|
|
370
|
+
declare function useWorkspaces(options?: UseWorkspacesOptions): UseWorkspacesResult;
|
|
603
371
|
|
|
604
|
-
type
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
372
|
+
type UseBillingUsageOptions = Pick<ClientOverride, "client"> & {
|
|
373
|
+
/** Account to read. Defaults to the caller's default account server-side. */
|
|
374
|
+
accountId?: string | undefined;
|
|
375
|
+
/** Filter usage to one workspace. */
|
|
376
|
+
workspaceId?: string | undefined;
|
|
377
|
+
/** Refresh interval (ms) for live billing meters. Off by default. */
|
|
378
|
+
pollIntervalMs?: number | undefined;
|
|
611
379
|
enabled?: boolean | undefined;
|
|
612
380
|
};
|
|
613
|
-
type
|
|
614
|
-
/**
|
|
615
|
-
|
|
616
|
-
/**
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
sessionStatus: SessionStatus$1 | null;
|
|
620
|
-
connectionState: SessionEventsConnectionState;
|
|
621
|
-
/** Highest sequence seen so far (0 before the first event). */
|
|
622
|
-
lastSequence: number;
|
|
623
|
-
/** True until the initial tail window has been applied (windowed mode). */
|
|
624
|
-
initialLoading: boolean;
|
|
625
|
-
/** Whether older durable events are available before the current window. */
|
|
626
|
-
hasOlder: boolean;
|
|
627
|
-
/** True while an older window is being fetched. */
|
|
628
|
-
loadingOlder: boolean;
|
|
629
|
-
/** Prepend an older density-bounded window; resolves true when more remain. */
|
|
630
|
-
loadOlder: () => Promise<boolean>;
|
|
631
|
-
error: Error | null;
|
|
632
|
-
};
|
|
633
|
-
/**
|
|
634
|
-
* Live-stream a session's event log with replay-by-sequence, reconnect, and
|
|
635
|
-
* batched React updates. Fresh loads default to a bounded tail window; pass
|
|
636
|
-
* `replay: "full"` or a nonzero `after` for the previous full replay path.
|
|
637
|
-
*/
|
|
638
|
-
declare function useSessionEvents(sessionId: string | null | undefined, options?: UseSessionEventsOptions): UseSessionEventsResult;
|
|
639
|
-
|
|
640
|
-
type ComposerSendExtras = Omit<SendMessageInput, "text" | "clientEventId">;
|
|
641
|
-
type UseComposerOptions = ClientOverride & SessionEventFeedOptions & {
|
|
642
|
-
/** Called with the accepted text after a successful send. */
|
|
643
|
-
onSent?: ((text: string) => void) | undefined;
|
|
644
|
-
/**
|
|
645
|
-
* Extra message fields (resources, tools, model, reasoningEffort) merged
|
|
646
|
-
* into every send. A function is evaluated at send time so it can read the
|
|
647
|
-
* surrounding UI state (attachment pickers, model selectors, ...).
|
|
648
|
-
*/
|
|
649
|
-
sendExtras?: ComposerSendExtras | (() => ComposerSendExtras) | undefined;
|
|
650
|
-
/** Latest server-derived workstream control; bound into Send/Steer OCC. */
|
|
651
|
-
effectiveControl?: EffectiveSessionControl | null | undefined;
|
|
652
|
-
/** Apply durable model/tool/reasoning settings in the host's controlled UI. */
|
|
653
|
-
onDraftApplied?: ((draft: ComposerDraft) => void) | undefined;
|
|
654
|
-
};
|
|
655
|
-
type ComposerState = {
|
|
656
|
-
value: string;
|
|
657
|
-
setValue: (value: string) => void;
|
|
658
|
-
/** Append the draft behind prompts already visible in the queue. */
|
|
659
|
-
send: (text?: string) => Promise<boolean>;
|
|
660
|
-
/** Supersede current direction with the draft. */
|
|
661
|
-
steer: (text?: string) => Promise<boolean>;
|
|
662
|
-
sending: boolean;
|
|
663
|
-
canSend: boolean;
|
|
664
|
-
/** Pause the session without deleting its prompt queue. */
|
|
665
|
-
pause: (reason?: string) => Promise<void>;
|
|
666
|
-
pausing: boolean;
|
|
667
|
-
resume: (reason?: string) => Promise<void>;
|
|
668
|
-
resumeScope: (option: EffectiveControlResumeOption) => Promise<void>;
|
|
669
|
-
resuming: boolean;
|
|
670
|
-
draft: ComposerDraft | null;
|
|
671
|
-
draftRevision: number;
|
|
672
|
-
draftLoading: boolean;
|
|
673
|
-
draftSaving: boolean;
|
|
674
|
-
draftConflict: Error | null;
|
|
675
|
-
/** Apply an atomic queue Edit checkout without a second read. */
|
|
676
|
-
applyDraft: (draft: ComposerDraft) => void;
|
|
677
|
-
reloadDraft: () => Promise<void>;
|
|
678
|
-
resolveDraftConflict: (choice: "keep_mine" | "use_remote") => Promise<void>;
|
|
679
|
-
restoredResources: ResourceRef[];
|
|
680
|
-
removeRestoredResource: (index: number) => void;
|
|
381
|
+
type UseBillingUsageResult = {
|
|
382
|
+
/** Prepaid credit balance (micro-USD), null until loaded. */
|
|
383
|
+
balance: BillingBalance | null;
|
|
384
|
+
/** Recent usage events (runs, tokens, cost, uploads, ...). */
|
|
385
|
+
usage: UsageEvent[];
|
|
386
|
+
loading: boolean;
|
|
681
387
|
error: Error | null;
|
|
682
|
-
|
|
388
|
+
refresh: () => Promise<void>;
|
|
683
389
|
};
|
|
684
390
|
/**
|
|
685
|
-
*
|
|
686
|
-
*
|
|
687
|
-
*
|
|
688
|
-
* `clientEventId` so retries stay idempotent server-side.
|
|
689
|
-
*/
|
|
690
|
-
declare function useComposer(sessionId: string | null | undefined, options?: UseComposerOptions): ComposerState;
|
|
691
|
-
/**
|
|
692
|
-
* Default text for a file-only message (attachment(s) present, no typed draft).
|
|
693
|
-
* Kept non-empty so the wire contract (`text: z.string().min(1)`) and the
|
|
694
|
-
* worker's non-whitespace guard accept it; the attached files still ride in
|
|
695
|
-
* `resources`. Exported for tests.
|
|
696
|
-
*/
|
|
697
|
-
declare const FILE_ONLY_MESSAGE_TEXT = "(see attached files)";
|
|
698
|
-
/**
|
|
699
|
-
* Merge the draft text + idempotency key with caller-provided extras. The
|
|
700
|
-
* text and clientEventId always win over extras. Exported for tests.
|
|
391
|
+
* Account billing usage: credit balance + recent usage events — the data
|
|
392
|
+
* behind per-call billing meters. Account-scoped, so it only needs the
|
|
393
|
+
* client; pass `workspaceId` to narrow usage to one workspace.
|
|
701
394
|
*/
|
|
702
|
-
declare function
|
|
703
|
-
/** Submit on plain Enter; Shift+Enter inserts a newline. Exported for tests. */
|
|
704
|
-
declare function shouldSubmitOnKey(event: {
|
|
705
|
-
key: string;
|
|
706
|
-
shiftKey: boolean;
|
|
707
|
-
metaKey?: boolean;
|
|
708
|
-
ctrlKey?: boolean;
|
|
709
|
-
nativeEvent?: {
|
|
710
|
-
isComposing?: boolean;
|
|
711
|
-
};
|
|
712
|
-
}): boolean;
|
|
713
|
-
/** Cmd/Ctrl+Enter steers; ordinary Enter appends to the queue. */
|
|
714
|
-
declare function shouldSteerOnKey(event: {
|
|
715
|
-
metaKey?: boolean;
|
|
716
|
-
ctrlKey?: boolean;
|
|
717
|
-
}): boolean;
|
|
718
|
-
|
|
719
|
-
type UseFileAttachmentsOptions = ClientOverride & {
|
|
720
|
-
/**
|
|
721
|
-
* Only files matching this predicate are accepted by {@link
|
|
722
|
-
* UseFileAttachmentsResult.addFromPaste} (the clipboard path). Defaults to
|
|
723
|
-
* `image/*` — the console's historical paste filter. {@link
|
|
724
|
-
* UseFileAttachmentsResult.addFiles} (the explicit picker / drop path)
|
|
725
|
-
* bypasses it.
|
|
726
|
-
*/
|
|
727
|
-
pasteFilter?: ((file: File) => boolean) | undefined;
|
|
728
|
-
};
|
|
729
|
-
type FileAttachment = {
|
|
730
|
-
id: string;
|
|
731
|
-
name: string;
|
|
732
|
-
contentType: string;
|
|
733
|
-
sizeBytes: number;
|
|
734
|
-
status: "uploading" | "ready" | "failed";
|
|
735
|
-
/** The SDK `FileAsset` once the upload finishes. */
|
|
736
|
-
file?: FileAsset | undefined;
|
|
737
|
-
/** Object-URL for an inline preview; minted for `image/*` files only. */
|
|
738
|
-
previewUrl?: string | undefined;
|
|
739
|
-
error?: string | undefined;
|
|
740
|
-
};
|
|
741
|
-
type UseFileAttachmentsResult = {
|
|
742
|
-
attachments: FileAttachment[];
|
|
743
|
-
/**
|
|
744
|
-
* `FileResourceRef[]` for every attachment that finished uploading — feed
|
|
745
|
-
* straight into `useComposer`'s `sendExtras.resources`.
|
|
746
|
-
*/
|
|
747
|
-
readyResources: FileResourceRef[];
|
|
748
|
-
/** True while any attachment is still uploading (drives the send-gate). */
|
|
749
|
-
uploading: boolean;
|
|
750
|
-
/** Explicit picker / drop path — uploads every file, no filter. */
|
|
751
|
-
addFiles: (files: Iterable<File>) => void;
|
|
752
|
-
/** Clipboard path — applies `pasteFilter` (default `image/*`) then uploads. */
|
|
753
|
-
addFromPaste: (event: {
|
|
754
|
-
clipboardData: DataTransfer | null;
|
|
755
|
-
}) => void;
|
|
756
|
-
/**
|
|
757
|
-
* Re-run the upload for a `failed` attachment, in place (same id, same
|
|
758
|
-
* source file). No-op for an id that isn't a known failed upload.
|
|
759
|
-
*/
|
|
760
|
-
retry: (id: string) => void;
|
|
761
|
-
/** Remove one attachment; revokes its object-URL. */
|
|
762
|
-
remove: (id: string) => void;
|
|
763
|
-
/** Remove all; revokes every object-URL. Call from `useComposer`'s `onSent`. */
|
|
764
|
-
clear: () => void;
|
|
765
|
-
};
|
|
766
|
-
/**
|
|
767
|
-
* Upload-and-track state for files attached to the next message. Owns the
|
|
768
|
-
* full client-side upload layer: a per-file `uploading | ready | failed`
|
|
769
|
-
* status machine driven by the SDK's `client.uploadFile`, object-URL image
|
|
770
|
-
* previews with create/revoke lifecycle, the `image/*` clipboard paste filter,
|
|
771
|
-
* and a `FileResourceRef[]` projection that drops straight into a message's
|
|
772
|
-
* `resources`. Workspace-scoped, so it resolves both client and workspace from
|
|
773
|
-
* the {@link OpenGeniProvider} (or a per-call `{ client, workspaceId }`).
|
|
774
|
-
*/
|
|
775
|
-
declare function useFileAttachments(options?: UseFileAttachmentsOptions): UseFileAttachmentsResult;
|
|
395
|
+
declare function useBillingUsage(options?: UseBillingUsageOptions): UseBillingUsageResult;
|
|
776
396
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
type QueueMutationKind = "move" | "edit" | "steer" | "delete";
|
|
780
|
-
type UseTurnQueueOptions = ClientOverride & SessionEventFeedOptions & {
|
|
397
|
+
type UseAvailableModelsOptions = Pick<ClientOverride, "client"> & {
|
|
398
|
+
/** Refresh interval (ms). Off by default — the host model list rarely moves. */
|
|
781
399
|
pollIntervalMs?: number | undefined;
|
|
400
|
+
enabled?: boolean | undefined;
|
|
782
401
|
};
|
|
783
|
-
type
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
402
|
+
type UseAvailableModelsResult = {
|
|
403
|
+
/** The provider-grouped models the host exposes (empty until loaded). */
|
|
404
|
+
models: ClientModel[];
|
|
405
|
+
/** The deployment's default model id, null until loaded. */
|
|
406
|
+
defaultModel: string | null;
|
|
788
407
|
loading: boolean;
|
|
789
408
|
error: Error | null;
|
|
790
409
|
refresh: () => Promise<void>;
|
|
791
|
-
moveTurn: (turnId: string, beforeTurnId: string | null) => Promise<boolean>;
|
|
792
|
-
/** Atomically withdraw a waiting prompt into the private durable composer draft. */
|
|
793
|
-
editTurn: (turnId: string, options: {
|
|
794
|
-
expectedDraftRevision: number;
|
|
795
|
-
replaceDraft: boolean;
|
|
796
|
-
}) => Promise<ComposerDraft | null>;
|
|
797
|
-
/** Advance the same durable waiting prompt; no duplicate prompt is created. */
|
|
798
|
-
steerTurn: (turnId: string) => Promise<boolean>;
|
|
799
|
-
removeTurn: (turnId: string) => Promise<boolean>;
|
|
800
|
-
pendingByTurn: Readonly<Record<string, QueueMutationKind>>;
|
|
801
|
-
mutationFor: (turnId: string) => QueueMutationKind | null;
|
|
802
|
-
mutating: boolean;
|
|
803
|
-
mutationError: Error | null;
|
|
804
|
-
clearMutationError: () => void;
|
|
805
410
|
};
|
|
806
411
|
/**
|
|
807
|
-
* The
|
|
808
|
-
*
|
|
809
|
-
*
|
|
412
|
+
* The host-exposed model list for a <ModelPicker>: fetches the deployment's
|
|
413
|
+
* public client config (`GET /v1/config/client`) and surfaces the richer
|
|
414
|
+
* provider-grouped `models` plus the `defaultModel` the picker should preselect.
|
|
415
|
+
* Deployment-scoped, so it only needs the client (no workspace).
|
|
810
416
|
*/
|
|
811
|
-
declare function
|
|
812
|
-
|
|
813
|
-
/** The sole human prompt queue: compact above Goal, Agents, and composer. */
|
|
814
|
-
type QueueSurfaceProps = {
|
|
815
|
-
queue: UseTurnQueueResult;
|
|
816
|
-
composer: ComposerState;
|
|
817
|
-
readOnly?: false | undefined;
|
|
818
|
-
} | {
|
|
819
|
-
queue: UseTurnQueueResult;
|
|
820
|
-
composer?: undefined;
|
|
821
|
-
readOnly: true;
|
|
822
|
-
};
|
|
823
|
-
declare function QueueSurface({ queue, composer, readOnly }: QueueSurfaceProps): react_jsx_runtime.JSX.Element | null;
|
|
417
|
+
declare function useAvailableModels(options?: UseAvailableModelsOptions): UseAvailableModelsResult;
|
|
824
418
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
* action on the session or the UI (clear, compact, pause the goal, show help) —
|
|
828
|
-
* NOT a structured way to talk to the agent. The human↔agent channel stays
|
|
829
|
-
* plain chat; the palette only recognizes a leading "/" and never sends a
|
|
830
|
-
* command to the model.
|
|
831
|
-
*
|
|
832
|
-
* Two kinds, modeled by where the handler does its work:
|
|
833
|
-
* - CLIENT commands touch only the local UI (e.g. /help, /clear-view).
|
|
834
|
-
* - SERVER commands call the API through the SDK (e.g. /clear, /compact,
|
|
835
|
-
* /goal).
|
|
836
|
-
* Both are just `run(args, ctx)`; `ctx` exposes the client for server commands
|
|
837
|
-
* and the UI affordances (notice, openHelp, clearView, confirm) for both.
|
|
838
|
-
*/
|
|
839
|
-
/** A positional argument a command accepts after its name. */
|
|
840
|
-
type SlashArg = {
|
|
841
|
-
name: string;
|
|
842
|
-
/** Enter runs only once every required arg is present; otherwise autocompletes. */
|
|
843
|
-
required?: boolean;
|
|
844
|
-
/** Closed value set (rendered as a hint; validated by the command itself). */
|
|
845
|
-
oneOf?: readonly string[];
|
|
846
|
-
description?: string;
|
|
847
|
-
};
|
|
848
|
-
/** Transient feedback surfaced in the composer (generalized error line). */
|
|
849
|
-
type Notice = {
|
|
850
|
-
tone: "ok" | "error";
|
|
851
|
-
message: string;
|
|
852
|
-
};
|
|
853
|
-
/** Everything a command handler can reach. Assembled by the composer. */
|
|
854
|
-
type CommandContext = {
|
|
855
|
-
/** SDK-shaped client for server commands. */
|
|
856
|
-
client: SessionClientLike;
|
|
857
|
-
workspaceId: string;
|
|
858
|
-
/** Null before a session exists (server commands should guard on this). */
|
|
859
|
-
sessionId: string | null;
|
|
860
|
-
status: SessionStatus$1 | null;
|
|
861
|
-
/** The operator's permissions on this workspace (gates command visibility). */
|
|
862
|
-
permissions: Permission[];
|
|
863
|
-
/** Surface a transient ok/error notice in the composer. */
|
|
864
|
-
notice: (notice: Notice) => void;
|
|
865
|
-
/** Open the in-composer /help panel (rendered from the registry). */
|
|
866
|
-
openHelp: () => void;
|
|
419
|
+
type SessionCapabilitiesState = "idle" | "negotiating" | "ready" | "cold" | "on-demand" | "error";
|
|
420
|
+
type UseSessionCapabilitiesOptions = ClientOverride & {
|
|
867
421
|
/**
|
|
868
|
-
*
|
|
869
|
-
*
|
|
870
|
-
*
|
|
871
|
-
* that don't (no resettable local timeline) get `false`. The /clear-view
|
|
872
|
-
* command uses this to avoid reporting a false "cleared" success on a no-op.
|
|
422
|
+
* Live event log to fold `stream.url.rotated` from (usually
|
|
423
|
+
* `useSessionEvents().events`). When present the desktop socket stays fresh on
|
|
424
|
+
* a box rollover without a round-trip; stale-epoch rotations are dropped.
|
|
873
425
|
*/
|
|
874
|
-
|
|
875
|
-
/** Show the danger confirm bar; resolves true once the operator confirms. */
|
|
876
|
-
confirm: () => Promise<boolean>;
|
|
877
|
-
};
|
|
878
|
-
type CommandResult = {
|
|
879
|
-
status: "ok" | "error";
|
|
880
|
-
message?: string;
|
|
426
|
+
events?: SessionEvent[] | undefined;
|
|
881
427
|
/**
|
|
882
|
-
*
|
|
883
|
-
*
|
|
884
|
-
* the
|
|
885
|
-
*
|
|
428
|
+
* Whether to acquire a viewer holder for the desktop pixel plane. Requires the
|
|
429
|
+
* un-redacted acknowledgment to have been recorded (else the attach 409s and
|
|
430
|
+
* the hook surfaces the consent requirement). Default false: read-only
|
|
431
|
+
* negotiation (no holder, no warm) — terminal/files/git work without it.
|
|
886
432
|
*/
|
|
887
|
-
|
|
888
|
-
};
|
|
889
|
-
type SlashCommand = {
|
|
890
|
-
/** Primary token after the slash (no leading "/"). */
|
|
891
|
-
name: string;
|
|
892
|
-
/** Alternate tokens that resolve to this command. */
|
|
893
|
-
aliases?: readonly string[];
|
|
894
|
-
description: string;
|
|
895
|
-
args?: readonly SlashArg[];
|
|
896
|
-
/** Required permission; the command is hidden from the palette without it. */
|
|
897
|
-
permission?: Permission;
|
|
898
|
-
/** Destructive — the palette shows a confirm bar before running. */
|
|
899
|
-
danger?: boolean;
|
|
433
|
+
attachDesktop?: boolean | undefined;
|
|
900
434
|
/**
|
|
901
|
-
*
|
|
902
|
-
*
|
|
435
|
+
* Whether to acquire a viewer holder to warm the box for the REAL interactive
|
|
436
|
+
* terminal (the ttyd pty-ws plane). Symmetric with `attachDesktop` and shares
|
|
437
|
+
* the SAME viewer attach (one warm box serves both planes), but needs NO
|
|
438
|
+
* un-redacted acknowledgment — a shell is interactive by nature, and the gate
|
|
439
|
+
* is the scoped tunnel URL + stream token. Default false: the terminal stays on
|
|
440
|
+
* the read-only Channel-A firehose until the user opens/focuses it. The attach
|
|
441
|
+
* folds the minted `pty-ws` url+token into the `Terminal` cell.
|
|
903
442
|
*/
|
|
904
|
-
|
|
905
|
-
/** Execute the command. Throwing is caught and surfaced as an error notice. */
|
|
906
|
-
run: (args: string[], ctx: CommandContext) => Promise<CommandResult> | CommandResult;
|
|
907
|
-
};
|
|
908
|
-
|
|
909
|
-
/**
|
|
910
|
-
* Context the composer supplies for command execution and visibility. The
|
|
911
|
-
* composer owns the UI affordances (notice/openHelp/clearView/confirm), so they
|
|
912
|
-
* are NOT part of this slice — the hook closes over them via `handlers`.
|
|
913
|
-
*/
|
|
914
|
-
type SlashCommandContext = Pick<CommandContext, "client" | "workspaceId" | "sessionId" | "status" | "permissions">;
|
|
915
|
-
/**
|
|
916
|
-
* UI affordances the composer supplies. `confirm` differs from the registry-
|
|
917
|
-
* facing {@link CommandContext.confirm} (which takes no args): the composer's
|
|
918
|
-
* confirm receives the command being run so the confirm bar renders from that
|
|
919
|
-
* exact command's identity. The hook bridges the two in {@link buildContext}.
|
|
920
|
-
*/
|
|
921
|
-
type SlashCommandHandlers = Pick<CommandContext, "notice" | "openHelp" | "clearView"> & {
|
|
922
|
-
confirm: (command: SlashCommand) => Promise<boolean>;
|
|
923
|
-
};
|
|
924
|
-
type ConfirmState = {
|
|
925
|
-
command: SlashCommand;
|
|
926
|
-
/** Resolve the pending confirm() promise. */
|
|
927
|
-
resolve: (confirmed: boolean) => void;
|
|
928
|
-
} | null;
|
|
929
|
-
type UseSlashCommandsOptions = {
|
|
930
|
-
commands: readonly SlashCommand[];
|
|
931
|
-
context: SlashCommandContext | undefined;
|
|
932
|
-
handlers: SlashCommandHandlers;
|
|
933
|
-
/** The current composer draft. */
|
|
934
|
-
value: string;
|
|
935
|
-
/** Replace the composer draft (autocomplete writes through this). */
|
|
936
|
-
setValue: (value: string) => void;
|
|
937
|
-
};
|
|
938
|
-
type UseSlashCommandsResult = {
|
|
939
|
-
/** Whether the palette is open (a command token is being typed). */
|
|
940
|
-
open: boolean;
|
|
443
|
+
attachTerminal?: boolean | undefined;
|
|
941
444
|
/**
|
|
942
|
-
* Whether
|
|
943
|
-
*
|
|
944
|
-
*
|
|
445
|
+
* Whether to acquire a viewer holder to warm the box for a FILE WRITE — the
|
|
446
|
+
* wake-on-edit INTENT (a first keystroke in the editor), NOT passive browsing.
|
|
447
|
+
* Shares the SAME viewer attach as the desktop/terminal (one warm box, one
|
|
448
|
+
* holder) and — like the terminal — needs NO un-redacted acknowledgment:
|
|
449
|
+
* reading/writing files is the ordinary Channel-A control plane, not the pixel
|
|
450
|
+
* plane. It folds NO live URL (files ride the stateless HTTP plane) — it only
|
|
451
|
+
* refcounts liveness. Unlike desktop/terminal it warms even a COLD box: an edit
|
|
452
|
+
* legitimately cold-creates (that IS the wake), so the write lands ~100ms warm
|
|
453
|
+
* instead of paying the ~5s cold resume. Default false. IMPORTANT: merely
|
|
454
|
+
* opening/reading the Files tab must NOT set this — browsing capture-served
|
|
455
|
+
* trees/diffs needs no box, and warming one on a cold glance burns box-hours to
|
|
456
|
+
* serve reads the capture already answers for free.
|
|
945
457
|
*/
|
|
946
|
-
|
|
947
|
-
/**
|
|
948
|
-
|
|
949
|
-
/**
|
|
950
|
-
|
|
951
|
-
setHighlight: (index: number) => void;
|
|
952
|
-
/** The matched command once the name is closed by a space (arg-hint mode). */
|
|
953
|
-
activeCommand: SlashCommand | null;
|
|
954
|
-
/** The arg hint string for the active command (footer), or "". */
|
|
955
|
-
activeArgHint: string;
|
|
458
|
+
attachFiles?: boolean | undefined;
|
|
459
|
+
/** Hold off negotiating (e.g. the workbench panel is collapsed). Default true. */
|
|
460
|
+
enabled?: boolean | undefined;
|
|
461
|
+
/** Poll cadence (ms) while the lease is cold/warming. Default 1500. */
|
|
462
|
+
warmingPollMs?: number | undefined;
|
|
956
463
|
/**
|
|
957
|
-
*
|
|
958
|
-
*
|
|
464
|
+
* Give up waiting for `warm` after this long while polling (ms) and surface a
|
|
465
|
+
* stalled error with a manual `renegotiate`. Default 30000. This is a UI
|
|
466
|
+
* patience deadline, independent from the worker's sandbox warming timeout.
|
|
467
|
+
* 0 disables the deadline.
|
|
959
468
|
*/
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
469
|
+
warmingDeadlineMs?: number | undefined;
|
|
470
|
+
};
|
|
471
|
+
type UseSessionCapabilitiesResult = {
|
|
472
|
+
/** The negotiated capability doc — the single source of UI truth. */
|
|
473
|
+
capabilities: SessionCapabilities | null;
|
|
474
|
+
state: SessionCapabilitiesState;
|
|
475
|
+
error: Error | null;
|
|
963
476
|
/**
|
|
964
|
-
*
|
|
965
|
-
*
|
|
966
|
-
* keyboard Enter, so an explicit click always runs the clicked command.
|
|
477
|
+
* 409 from the desktop attach: the un-redacted (or shared) plane needs explicit
|
|
478
|
+
* acknowledgment before a viewer holder is granted. Drives the consent prompt.
|
|
967
479
|
*/
|
|
968
|
-
|
|
969
|
-
/**
|
|
970
|
-
|
|
480
|
+
acknowledgmentRequired: "unredacted" | "shared" | null;
|
|
481
|
+
/** 429 from the desktop attach: the per-session viewer cap is reached. */
|
|
482
|
+
viewerCapReached: boolean;
|
|
483
|
+
/** The viewer holder id minted on a desktop attach (for detach/heartbeat). */
|
|
484
|
+
viewerId: string | null;
|
|
485
|
+
/** Force a re-negotiation (after acknowledging, a resolution change, etc.). */
|
|
486
|
+
renegotiate: () => void;
|
|
971
487
|
};
|
|
972
|
-
declare function useSlashCommands(options: UseSlashCommandsOptions): UseSlashCommandsResult;
|
|
973
|
-
|
|
974
|
-
type ChatComposerProps = {
|
|
975
|
-
composer: ComposerState;
|
|
976
|
-
/** Canonical workstream control, separate from lifecycle status. */
|
|
977
|
-
effectiveControl?: EffectiveSessionControl | null | undefined;
|
|
978
|
-
/** Waiting prompts already ahead of a normal Send. */
|
|
979
|
-
queuedAheadCount?: number | undefined;
|
|
980
|
-
/** Whether broader Workspace Resume is authorized for this viewer. */
|
|
981
|
-
canControlWorkspace?: boolean | undefined;
|
|
982
|
-
/** Optional host routes used to navigate from effective Pause blockers. */
|
|
983
|
-
controlLinks?: {
|
|
984
|
-
workspaceHref?: string | undefined;
|
|
985
|
-
sessionHref?: ((sessionId: string) => string) | undefined;
|
|
986
|
-
} | undefined;
|
|
987
|
-
placeholder?: string | undefined;
|
|
988
|
-
disabled?: boolean | undefined;
|
|
989
|
-
autoFocus?: boolean | undefined;
|
|
990
|
-
/** Replaces the default keyboard hint under the field. */
|
|
991
|
-
hint?: string | undefined;
|
|
992
|
-
/** App controls (model picker, attach button, ...) in the footer row, replacing the hint. */
|
|
993
|
-
controlsStart?: ReactNode | undefined;
|
|
994
|
-
/** Content rendered above the textarea, inside the field chrome (e.g. attachment chips). */
|
|
995
|
-
header?: ReactNode | undefined;
|
|
996
|
-
/** Paste hook on the textarea (e.g. paste-image-to-attach). */
|
|
997
|
-
onPaste?: ((event: ClipboardEvent<HTMLTextAreaElement>) => void) | undefined;
|
|
998
|
-
/**
|
|
999
|
-
* Opt-in file attachments. When supplied (e.g. from {@link useFileAttachments}),
|
|
1000
|
-
* the composer renders a built-in attach button (prepended to `controlsStart`),
|
|
1001
|
-
* an attachment-chips strip (above the textarea, before any host `header`),
|
|
1002
|
-
* routes paste through `addFromPaste` (image/* filter lives in the hook), and
|
|
1003
|
-
* gates send while `uploading` so a message never departs without its files.
|
|
1004
|
-
* Absent → no attachment UI renders and the composer behaves exactly as before.
|
|
1005
|
-
*/
|
|
1006
|
-
attachments?: UseFileAttachmentsResult | undefined;
|
|
1007
|
-
/**
|
|
1008
|
-
* Opt-in model picker. When supplied (e.g. from {@link useAvailableModels}),
|
|
1009
|
-
* the composer renders a {@link ModelPicker} at the start of `controlsStart`
|
|
1010
|
-
* so the operator can choose which host-exposed model serves the next message.
|
|
1011
|
-
* The host owns the selection (`selectedModel`/`onSelectModel`) and is
|
|
1012
|
-
* responsible for threading it into the composer's `sendExtras` (typically
|
|
1013
|
-
* `useComposer({ sendExtras: () => ({ model }) })`) so `composeSendInput`
|
|
1014
|
-
* carries it. Absent → no picker renders and the composer behaves as before.
|
|
1015
|
-
*/
|
|
1016
|
-
models?: ClientModel[] | undefined;
|
|
1017
|
-
/** The currently selected model id (the picker's controlled value). */
|
|
1018
|
-
selectedModel?: string | undefined;
|
|
1019
|
-
/** Called with the chosen model id when the operator picks one. */
|
|
1020
|
-
onSelectModel?: ((modelId: string) => void) | undefined;
|
|
1021
|
-
className?: string | undefined;
|
|
1022
|
-
/**
|
|
1023
|
-
* Slash-command palette. Defaults to the built-in {@link defaultCommands};
|
|
1024
|
-
* apps concat their own. Backward-compatible: when `commandContext` is absent
|
|
1025
|
-
* the palette is inert and behavior is identical to before.
|
|
1026
|
-
*/
|
|
1027
|
-
commands?: readonly SlashCommand[] | undefined;
|
|
1028
|
-
/**
|
|
1029
|
-
* Wiring the palette needs to run server commands and gate visibility. The
|
|
1030
|
-
* composer supplies notice/openHelp/clearView/confirm internally.
|
|
1031
|
-
*/
|
|
1032
|
-
commandContext?: SlashCommandContext | undefined;
|
|
1033
|
-
/** Reset the local timeline view (the /clear-view command target). */
|
|
1034
|
-
onClearView?: (() => void) | undefined;
|
|
1035
|
-
};
|
|
1036
|
-
declare const OPEN_WORKSTREAM_CONTROL_EVENT = "opengeni:open-workstream-control";
|
|
1037
488
|
/**
|
|
1038
|
-
* The
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
489
|
+
* The capability-negotiation hook. Discovers what THIS session+backend+OS
|
|
490
|
+
* supports (FileSystem/Terminal/Git always-ish; DesktopStream/Recording
|
|
491
|
+
* sometimes), drives capability-gated rendering, and — when `attachDesktop` —
|
|
492
|
+
* holds a viewer lease + heartbeats it so the box stays warm while watched.
|
|
1042
493
|
*
|
|
1043
|
-
*
|
|
1044
|
-
*
|
|
1045
|
-
*
|
|
1046
|
-
*
|
|
494
|
+
* Degradation is a value, never a crash: an unsupported surface comes back
|
|
495
|
+
* `available:false`/`transport:null` + a `reason`; the components render the
|
|
496
|
+
* reason-aware empty state. 409 (consent) and 429 (viewer cap) are surfaced as
|
|
497
|
+
* typed signals, not thrown.
|
|
1047
498
|
*/
|
|
1048
|
-
declare function
|
|
499
|
+
declare function useSessionCapabilities(sessionId: string | null | undefined, options?: UseSessionCapabilitiesOptions): UseSessionCapabilitiesResult;
|
|
1049
500
|
|
|
1050
|
-
/**
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
501
|
+
/**
|
|
502
|
+
* The minimal WebSocket surface the frame renderer drives. Lets tests (and a
|
|
503
|
+
* future transport swap) inject a fake without a live socket — the exact
|
|
504
|
+
* analogue of `DesktopRfbFactory` for the noVNC path. Structurally a subset of
|
|
505
|
+
* the browser `WebSocket`.
|
|
506
|
+
*/
|
|
507
|
+
interface DesktopWebSocketLike {
|
|
508
|
+
binaryType: string;
|
|
509
|
+
send(data: ArrayBuffer): void;
|
|
510
|
+
close(): void;
|
|
511
|
+
addEventListener(type: "open" | "message" | "error" | "close", listener: (ev: {
|
|
512
|
+
data?: unknown;
|
|
513
|
+
} & Record<string, unknown>) => void): void;
|
|
514
|
+
removeEventListener(type: "open" | "message" | "error" | "close", listener: (ev: {
|
|
515
|
+
data?: unknown;
|
|
516
|
+
} & Record<string, unknown>) => void): void;
|
|
517
|
+
}
|
|
518
|
+
type DesktopWebSocketFactory = (url: string) => DesktopWebSocketLike;
|
|
519
|
+
type UseRelayFrameStreamOptions = {
|
|
520
|
+
/** The desktop cell of the negotiated capabilities (`capabilities.DesktopStream`). */
|
|
521
|
+
capability: DesktopStreamCapability | null;
|
|
522
|
+
/** The mount target. A `<canvas>` is appended here on connect. */
|
|
523
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
524
|
+
/** Custom socket factory (tests / a transport swap). Defaults to `new WebSocket(url)`. */
|
|
525
|
+
webSocketFactory?: DesktopWebSocketFactory | undefined;
|
|
1055
526
|
};
|
|
1056
|
-
type
|
|
1057
|
-
|
|
1058
|
-
goal: SessionGoal | null;
|
|
1059
|
-
/** Convenience flags over `goal.status`. */
|
|
1060
|
-
isActive: boolean;
|
|
1061
|
-
isPaused: boolean;
|
|
1062
|
-
isCompleted: boolean;
|
|
1063
|
-
loading: boolean;
|
|
527
|
+
type UseRelayFrameStreamResult = {
|
|
528
|
+
state: DesktopConnectionState;
|
|
1064
529
|
error: Error | null;
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
pause: (rationale?: string) => Promise<SessionGoal | null>;
|
|
1068
|
-
/** Resume a paused goal: resets counters and re-arms continuations. */
|
|
1069
|
-
resume: () => Promise<SessionGoal | null>;
|
|
1070
|
-
/** Clear the session goal; goal-less sessions remain a successful no-op. */
|
|
1071
|
-
clearGoal: () => Promise<void>;
|
|
1072
|
-
/** Alias for `clearGoal`. */
|
|
1073
|
-
deleteGoal: () => Promise<void>;
|
|
1074
|
-
/** True while a pause/resume/clear is in flight. */
|
|
1075
|
-
updating: boolean;
|
|
1076
|
-
mutationError: Error | null;
|
|
1077
|
-
clearMutationError: () => void;
|
|
530
|
+
/** Tear down + reopen the socket (e.g. after a drop, once a fresh url arrives). */
|
|
531
|
+
reconnect: () => void;
|
|
1078
532
|
};
|
|
1079
533
|
/**
|
|
1080
|
-
*
|
|
1081
|
-
* `
|
|
1082
|
-
*
|
|
1083
|
-
*
|
|
534
|
+
* VIEW-ONLY PNG-frame renderer for a SELF-HOSTED desktop stream — the relay
|
|
535
|
+
* transport (`transport: "relay-frames"`, `client: "frames"`). The self-hosted
|
|
536
|
+
* agent produces one PNG per frame as a protobuf datagram over the relay; there
|
|
537
|
+
* is no RFB/noVNC here. This hook opens the relay DESKTOP channel as a CLIENT
|
|
538
|
+
* (mirroring the proven diagnostic wire protocol), decodes each PNG onto a
|
|
539
|
+
* `<canvas>` mounted into `containerRef`, and drives the connection state
|
|
540
|
+
* machine: idle → connecting (ws opening) → connected (first painted frame) →
|
|
541
|
+
* error (ws error/close/ack rejection).
|
|
542
|
+
*
|
|
543
|
+
* It is DORMANT for any other transport (or no url): it stays idle and touches
|
|
544
|
+
* nothing, so the noVNC path owns the surface. SSR-safe: the socket + DOM attach
|
|
545
|
+
* live inside `useEffect`.
|
|
546
|
+
*
|
|
547
|
+
* Backpressure (critical — frames are ~1.8MB at ~10fps): at most one frame is
|
|
548
|
+
* decoded at a time; a frame arriving mid-decode replaces the pending one
|
|
549
|
+
* (latest-wins), so a slow decode can never build an unbounded queue.
|
|
1084
550
|
*/
|
|
1085
|
-
declare function
|
|
551
|
+
declare function useRelayFrameStream(options: UseRelayFrameStreamOptions): UseRelayFrameStreamResult;
|
|
1086
552
|
|
|
1087
|
-
type
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
/**
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
553
|
+
type UseDesktopStreamOptions = {
|
|
554
|
+
/** The desktop cell of the negotiated capabilities (`capabilities.DesktopStream`). */
|
|
555
|
+
capability: DesktopStreamCapability | null;
|
|
556
|
+
/** The mount target. RFB (or the frame canvas) attaches here on connect. */
|
|
557
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
558
|
+
/** Read-only by default (v1 ruling H). interactive only when cap.mode allows. */
|
|
559
|
+
interactive?: boolean | undefined;
|
|
560
|
+
scaleViewport?: boolean | undefined;
|
|
561
|
+
/** Custom RFB factory (tests / a WebRTC swap). Defaults to a lazy @novnc/novnc. */
|
|
562
|
+
rfbFactory?: DesktopRfbFactory | undefined;
|
|
563
|
+
/** Custom socket factory for the `relay-frames` transport (tests). Defaults to
|
|
564
|
+
* `new WebSocket(url)`. Mirrors `rfbFactory` for the frame renderer. */
|
|
565
|
+
webSocketFactory?: DesktopWebSocketFactory | undefined;
|
|
566
|
+
};
|
|
567
|
+
type UseDesktopStreamResult = {
|
|
568
|
+
state: DesktopConnectionState;
|
|
1098
569
|
error: Error | null;
|
|
1099
|
-
|
|
570
|
+
/** Manual reconnect (e.g. after a securityfailure once a fresh URL arrives). */
|
|
571
|
+
reconnect: () => void;
|
|
1100
572
|
};
|
|
1101
573
|
/**
|
|
1102
|
-
*
|
|
1103
|
-
* `
|
|
1104
|
-
* `
|
|
574
|
+
* Drive the noVNC RFB lifecycle from a `DesktopStreamCapability`, using the
|
|
575
|
+
* SDK's `desktop.ts` reducer + `desktopSocketUrl`. SSR-safe: the RFB import and
|
|
576
|
+
* the DOM attach happen inside `useEffect`, so a server render is a no-op and
|
|
577
|
+
* the component shows its placeholder until hydration.
|
|
578
|
+
*
|
|
579
|
+
* Read-only is enforced at three layers: `capability.mode` (server) →
|
|
580
|
+
* `interactive` prop → `RFB.viewOnly`. v1 always resolves to read-only. On a
|
|
581
|
+
* capability `url` change (a rotation), the old RFB disconnects and a fresh one
|
|
582
|
+
* connects to the new URL — a brief "desktop blink", acceptable on rollover.
|
|
583
|
+
*
|
|
584
|
+
* Transport dispatch: a Modal box negotiates `transport: "vnc-ws"` and drives the
|
|
585
|
+
* noVNC RFB below. A SELF-HOSTED machine negotiates `transport: "relay-frames"`
|
|
586
|
+
* (PNG-per-frame over the relay, view-only) — that path is delegated to
|
|
587
|
+
* `useRelayFrameStream`, which paints a `<canvas>`. Both hooks are ALWAYS called
|
|
588
|
+
* (rules of hooks); each is dormant for the other's transport, and we return the
|
|
589
|
+
* result of whichever owns the surface. The public interface is identical either
|
|
590
|
+
* way, so `DesktopViewer` is transport-agnostic.
|
|
1105
591
|
*/
|
|
1106
|
-
declare function
|
|
592
|
+
declare function useDesktopStream(options: UseDesktopStreamOptions): UseDesktopStreamResult;
|
|
1107
593
|
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
594
|
+
/** The ttyd connection lifecycle as surfaced to the component. */
|
|
595
|
+
type TerminalStreamStatus = "connecting" | "open" | "closed" | "error";
|
|
596
|
+
type UseTerminalStreamOptions = {
|
|
597
|
+
/** The Terminal cell of the negotiated capabilities (`capabilities.Terminal`).
|
|
598
|
+
* The stream connects ONLY when `transport === "pty-ws"` and `url` is set; on a
|
|
599
|
+
* cold box (`transport === "sse-events"` / no url) it stays idle and the caller
|
|
600
|
+
* falls back to the Channel-A read-only firehose. */
|
|
601
|
+
capability: Pick<TerminalCapability, "transport" | "url" | "token"> | null;
|
|
602
|
+
/** Called for each OUTPUT payload from ttyd (write verbatim into xterm). */
|
|
603
|
+
onOutput?: ((data: string) => void) | undefined;
|
|
604
|
+
/** Called when ttyd sends a SET_WINDOW_TITLE frame. */
|
|
605
|
+
onTitle?: ((title: string) => void) | undefined;
|
|
606
|
+
/** Initial PTY size to seed the ttyd auth frame + first resize. */
|
|
607
|
+
initialCols?: number | undefined;
|
|
608
|
+
initialRows?: number | undefined;
|
|
1112
609
|
};
|
|
1113
|
-
type
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
610
|
+
type UseTerminalStreamResult = {
|
|
611
|
+
/** True once the ttyd socket is open (and the auth frame has been sent). */
|
|
612
|
+
connected: boolean;
|
|
613
|
+
status: TerminalStreamStatus;
|
|
614
|
+
/** Pipe a keystroke/paste to the PTY stdin. No-op until the socket is open. */
|
|
615
|
+
write: (data: string) => void;
|
|
616
|
+
/** Tell ttyd the PTY window changed size (on xterm fit/resize). */
|
|
617
|
+
resize: (cols: number, rows: number) => void;
|
|
618
|
+
/** Tear the socket down (the effect also tears down on unmount / url change). */
|
|
619
|
+
disconnect: () => void;
|
|
1118
620
|
};
|
|
1119
|
-
/**
|
|
1120
|
-
|
|
621
|
+
/**
|
|
622
|
+
* Drive a ttyd PTY-over-websocket connection from a `pty-ws` Terminal capability,
|
|
623
|
+
* symmetric with `use-desktop-stream` (the noVNC-over-tunnel hook). The scoped
|
|
624
|
+
* stream token is already embedded in the minted tunnel `url`; the WebSocket is
|
|
625
|
+
* opened with the REQUIRED ttyd subprotocol "tty".
|
|
626
|
+
*
|
|
627
|
+
* ttyd wire protocol (see `@opengeni/sdk/terminal`):
|
|
628
|
+
* - first frame: `JSON.stringify({ AuthToken: "" })` (+ optional columns/rows).
|
|
629
|
+
* - client→server: INPUT = "0"+data ; RESIZE = "1"+JSON({columns,rows}).
|
|
630
|
+
* - server→client: "0" = OUTPUT (→ xterm) ; "1" = SET_WINDOW_TITLE ;
|
|
631
|
+
* "2" = SET_PREFERENCES (ignored). Binary frames are decoded the same way.
|
|
632
|
+
*
|
|
633
|
+
* On a `url`/`token` rotation (a box rollover folds a fresh address into the cell)
|
|
634
|
+
* the effect re-runs: the old socket closes and a fresh one connects — a brief
|
|
635
|
+
* terminal blink, acceptable on rollover (mirrors the desktop's RFB hot-swap).
|
|
636
|
+
* SSR-safe: the socket open lives in `useEffect`, so a server render is a no-op.
|
|
637
|
+
*/
|
|
638
|
+
declare function useTerminalStream(options: UseTerminalStreamOptions): UseTerminalStreamResult;
|
|
1121
639
|
|
|
1122
|
-
type
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
/**
|
|
1128
|
-
|
|
1129
|
-
|
|
640
|
+
type TerminalChunk = {
|
|
641
|
+
/** Stable key (the source event id) so the xterm writer tracks a written-cursor. */
|
|
642
|
+
id: string;
|
|
643
|
+
/** Raw output bytes (utf-8 lossy) — written verbatim into xterm. */
|
|
644
|
+
text: string;
|
|
645
|
+
/** stdout vs stderr (drives optional tinting). */
|
|
646
|
+
stream: "stdout" | "stderr";
|
|
647
|
+
/** Global ordering: the source event sequence. */
|
|
648
|
+
seq: number;
|
|
1130
649
|
};
|
|
1131
|
-
type
|
|
650
|
+
type UseSandboxTerminalOptions = ClientOverride & {
|
|
651
|
+
/** The live session event log (usually `useSessionEvents().events`). */
|
|
652
|
+
events: SessionEvent[];
|
|
653
|
+
/** Restrict to one PTY (by ptyId). Omit to interleave the agent firehose +
|
|
654
|
+
* every PTY. */
|
|
655
|
+
ptyId?: string | undefined;
|
|
656
|
+
/** Include the agent's command-output firehose (sandbox.command.output.delta).
|
|
657
|
+
* Default true — the read-only "terminal-as-events" the data path settled on. */
|
|
658
|
+
includeAgentFirehose?: boolean | undefined;
|
|
1132
659
|
/**
|
|
1133
|
-
*
|
|
1134
|
-
*
|
|
660
|
+
* OPEN an interactive PTY against the box so the user can type, not just watch.
|
|
661
|
+
* When true (and the session is live) the hook calls `terminalPtyOpen` once,
|
|
662
|
+
* tracks the returned ptyId, exposes `write` immediately (bound to that ptyId),
|
|
663
|
+
* and closes the PTY on unmount. The PTY's banner + every output delta ride the
|
|
664
|
+
* SSE spine (`terminal.pty.*`) back into `events`, so xterm fills in. Default
|
|
665
|
+
* false — a caller that only wants the read-only firehose stays projection-only.
|
|
1135
666
|
*/
|
|
1136
|
-
|
|
1137
|
-
/**
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
error: Error | null;
|
|
1142
|
-
refresh: () => Promise<void>;
|
|
667
|
+
interactive?: boolean | undefined;
|
|
668
|
+
/** Lease liveness ("cold" | "warm" | "draining"). The interactive PTY is only
|
|
669
|
+
* opened once the box is warm — opening on a cold box (ptyCapable is advertised
|
|
670
|
+
* cold too) races the box and leaves a dead read-only terminal. */
|
|
671
|
+
liveness?: string | undefined;
|
|
1143
672
|
};
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
/**
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
673
|
+
type UseSandboxTerminalResult = {
|
|
674
|
+
/** Ordered, deduped output chunks to write() into xterm.js. */
|
|
675
|
+
chunks: TerminalChunk[];
|
|
676
|
+
/** Whether a PTY is currently open (drives the prompt/cursor affordance). */
|
|
677
|
+
running: boolean;
|
|
678
|
+
/**
|
|
679
|
+
* Interactive write fn when a PTY is open and the backend supports stdin
|
|
680
|
+
* (`terminal.transport === "pty-ws"` / `PtyOpenResponse.supportsInput`). Null
|
|
681
|
+
* in the read-only event-projection case (v1 default).
|
|
682
|
+
*/
|
|
683
|
+
write: ((data: string) => void) | null;
|
|
684
|
+
/** The active PTY id, if one is open. */
|
|
685
|
+
activePtyId: string | null;
|
|
686
|
+
/** Close the active PTY (no-op when none is open). */
|
|
687
|
+
close: () => void;
|
|
688
|
+
/** A PTY-open failure (interactive mode), if any. */
|
|
1156
689
|
error: Error | null;
|
|
1157
|
-
refresh: () => Promise<void>;
|
|
1158
690
|
};
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
691
|
+
/**
|
|
692
|
+
* Project the Channel-A event log into an xterm-writable byte stream. The
|
|
693
|
+
* terminal is "terminal-as-events": there is NO new socket in v1 — the agent's
|
|
694
|
+
* command output (`sandbox.command.output.delta`) and any interactive PTY
|
|
695
|
+
* (`terminal.pty.output.delta`) ride the existing SSE spine. When a PTY is open
|
|
696
|
+
* and the backend accepts stdin, `write` pipes keystrokes via the SDK
|
|
697
|
+
* `terminalPtyWrite` (the synchronous Channel-A control path).
|
|
698
|
+
*/
|
|
699
|
+
declare function useSandboxTerminal(sessionId: string | null | undefined, options: UseSandboxTerminalOptions): UseSandboxTerminalResult;
|
|
1162
700
|
|
|
1163
|
-
|
|
1164
|
-
|
|
701
|
+
/** The git-status overlay a file row may carry (tints modified files in the tree). */
|
|
702
|
+
type FileTreeStatus = "added" | "modified" | "deleted" | "renamed" | "untracked";
|
|
703
|
+
type CapturedFileUnavailableReason = "not-captured" | "too-large" | "content-missing";
|
|
704
|
+
/** A cold capture can index a path without retaining its contents. Components
|
|
705
|
+
* use this typed result to offer an explicit wake action instead of silently
|
|
706
|
+
* turning passive review into a live sandbox read. */
|
|
707
|
+
declare class CapturedFileUnavailableError extends Error {
|
|
708
|
+
readonly path: string;
|
|
709
|
+
readonly reason: CapturedFileUnavailableReason;
|
|
710
|
+
readonly code = "captured_file_unavailable";
|
|
711
|
+
constructor(path: string, reason: CapturedFileUnavailableReason);
|
|
712
|
+
}
|
|
713
|
+
declare class FileWriteConflictError extends Error {
|
|
714
|
+
readonly path: string;
|
|
715
|
+
readonly expectedContent: string;
|
|
716
|
+
readonly liveContent: string;
|
|
717
|
+
readonly code = "file_write_conflict";
|
|
718
|
+
constructor(path: string, expectedContent: string, liveContent: string);
|
|
719
|
+
}
|
|
720
|
+
type SandboxWriteFileOptions = {
|
|
721
|
+
/** Exact text loaded into the editor. The live file is re-read before write;
|
|
722
|
+
* divergence fails closed with FileWriteConflictError. */
|
|
723
|
+
expectedContent?: string | undefined;
|
|
724
|
+
/** Deliberately bypass the expected-content guard after a visible conflict. */
|
|
725
|
+
force?: boolean | undefined;
|
|
726
|
+
};
|
|
727
|
+
/** A node in the Pierre file tree. `children === undefined` ⇒ an unexpanded dir
|
|
728
|
+
* (lazy treeMode); `children: []` ⇒ an expanded-but-empty dir. */
|
|
729
|
+
type FileTreeNode = {
|
|
730
|
+
path: string;
|
|
731
|
+
name: string;
|
|
732
|
+
kind: "file" | "dir";
|
|
733
|
+
children?: FileTreeNode[] | undefined;
|
|
734
|
+
size?: number | null | undefined;
|
|
735
|
+
status?: FileTreeStatus | undefined;
|
|
736
|
+
/** A residue dir the capture COLLAPSED (node_modules, .git, dist, …): its
|
|
737
|
+
* contents were never indexed. Cold, expanding it can't list children — the
|
|
738
|
+
* UI shows an inline "contents on machine" row until the box is warm. */
|
|
739
|
+
truncated?: boolean | undefined;
|
|
740
|
+
};
|
|
741
|
+
type UseSandboxFilesOptions = ClientOverride & {
|
|
742
|
+
/** Live event log (usually `useSessionEvents().events`) — drives auto-refresh
|
|
743
|
+
* on `fs.changed` / `git.changed`. */
|
|
744
|
+
events?: SessionEvent[] | undefined;
|
|
745
|
+
/** Initial path to list (workspace root by default). */
|
|
746
|
+
rootPath?: string | undefined;
|
|
747
|
+
/** Hold off the initial list (e.g. panel collapsed). Default true. */
|
|
1165
748
|
enabled?: boolean | undefined;
|
|
749
|
+
/** The lease liveness ("cold" | "warm" | "draining"). The structured FileSystem
|
|
750
|
+
* capability is advertised even on a COLD box, so the mount-time list can race
|
|
751
|
+
* the box: it lists before the box is warm, gets an empty/errored result, and
|
|
752
|
+
* (with no `fs.changed` event) never re-lists. Passing liveness re-lists when
|
|
753
|
+
* the box first becomes warm, so the tree populates as soon as the box is up. */
|
|
754
|
+
liveness?: string | undefined;
|
|
755
|
+
/** The latest turn-end workspace capture (from `useWorkspaceCapture`). The tree
|
|
756
|
+
* paints immediately from this durable index, then a warm box reconciles live
|
|
757
|
+
* in place. If that live read fails, the capture remains a truthful read-only
|
|
758
|
+
* fallback instead of turning into an empty error surface. */
|
|
759
|
+
capture?: WorkspaceCaptureManifest | null | undefined;
|
|
760
|
+
/** Called when an OPTIMISTIC mutation is reverted because its background
|
|
761
|
+
* Channel-A op failed (e.g. a 409 rename collision). The host wires this to a
|
|
762
|
+
* toast — the tree silently rolls the node back, the user sees why. */
|
|
763
|
+
onMutationError?: ((error: Error, op: string) => void) | undefined;
|
|
1166
764
|
};
|
|
1167
|
-
type
|
|
1168
|
-
|
|
765
|
+
type UseSandboxFilesResult = {
|
|
766
|
+
/** The tree roots (the listed root's children). */
|
|
767
|
+
tree: FileTreeNode[];
|
|
768
|
+
/** Lazy-expand a directory node in place (lists its immediate children). */
|
|
769
|
+
expand: (path: string) => Promise<void>;
|
|
770
|
+
/** Paths whose lazy `fs.list` is currently in flight — the FileBrowser shows a
|
|
771
|
+
* spinner on these nodes so a 2-3s Channel-A list never looks frozen. */
|
|
772
|
+
expandingPaths: Set<string>;
|
|
773
|
+
/** Read a file for the preview pane (text or base64-for-binary, size-capped). */
|
|
774
|
+
readFile: (path: string, options?: OpenGeniRequestOptions) => Promise<FsReadResponse>;
|
|
775
|
+
/** Write a file (overwrite, last-writer-wins) — the editor save path.
|
|
776
|
+
* Optimistic: a brand-new file is spliced into the tree immediately and the
|
|
777
|
+
* Channel-A write runs in the background; on failure the splice is reverted. */
|
|
778
|
+
writeFile: (path: string, content: string, options?: SandboxWriteFileOptions) => Promise<FsWriteResponse>;
|
|
779
|
+
/** Create a new empty file (refuses to clobber an existing path: overwrite=false). */
|
|
780
|
+
createFile: (path: string) => Promise<void>;
|
|
781
|
+
/** Create a directory (recursive by default). */
|
|
782
|
+
createDir: (path: string) => Promise<void>;
|
|
783
|
+
/** Delete a path (pass recursive=true for a non-empty directory). */
|
|
784
|
+
deleteEntry: (path: string, recursive?: boolean) => Promise<void>;
|
|
785
|
+
/** Move / rename a path (rename == move). Refuses to clobber unless overwrite=true. */
|
|
786
|
+
moveEntry: (path: string, newPath: string, opts?: {
|
|
787
|
+
overwrite?: boolean;
|
|
788
|
+
}) => Promise<void>;
|
|
789
|
+
/** Re-list the whole tree from the root. */
|
|
790
|
+
refresh: () => Promise<void>;
|
|
791
|
+
/** Which source the tree is currently served from: the live box, the turn-end
|
|
792
|
+
* capture (cold/offline), or neither yet. M5's source badge reads this. */
|
|
793
|
+
source: "live" | "capture" | null;
|
|
794
|
+
/** When the served capture was taken (ISO), when `source === "capture"`. */
|
|
795
|
+
capturedAt: string | null;
|
|
1169
796
|
loading: boolean;
|
|
1170
797
|
error: Error | null;
|
|
1171
|
-
refresh: () => Promise<void>;
|
|
1172
|
-
create: (request: CreateVariableSetRequest) => Promise<VariableSet | null>;
|
|
1173
|
-
update: (variableSetId: string, request: UpdateVariableSetRequest) => Promise<VariableSet | null>;
|
|
1174
|
-
remove: (variableSetId: string) => Promise<boolean>;
|
|
1175
|
-
/** Set/rotate a variable. Values are write-only — reads expose metadata only. */
|
|
1176
|
-
setVariable: (variableSetId: string, name: string, value: string) => Promise<VariableSetVariableMetadata | null>;
|
|
1177
|
-
deleteVariable: (variableSetId: string, name: string) => Promise<boolean>;
|
|
1178
|
-
mutating: boolean;
|
|
1179
|
-
mutationError: Error | null;
|
|
1180
|
-
clearMutationError: () => void;
|
|
1181
798
|
};
|
|
1182
799
|
/**
|
|
1183
|
-
*
|
|
1184
|
-
*
|
|
1185
|
-
*
|
|
800
|
+
* Project the FileSystem service into a lazy-loaded Pierre tree. The initial
|
|
801
|
+
* list pulls one level (depth 1); `expand(path)` lists a directory's immediate
|
|
802
|
+
* children on demand (the fast lazy-tree UX). A git-status overlay tints
|
|
803
|
+
* modified files. Auto-refreshes when an `fs.changed` / `git.changed` event
|
|
804
|
+
* arrives on the live log.
|
|
1186
805
|
*/
|
|
1187
|
-
declare function
|
|
1188
|
-
/** @deprecated use UseVariableSetsOptions */
|
|
1189
|
-
type UseEnvironmentsOptions = UseVariableSetsOptions;
|
|
1190
|
-
/** @deprecated use UseVariableSetsResult */
|
|
1191
|
-
type UseEnvironmentsResult = UseVariableSetsResult & {
|
|
1192
|
-
environments: VariableSet[];
|
|
1193
|
-
};
|
|
1194
|
-
/** @deprecated use useVariableSets */
|
|
1195
|
-
declare function useEnvironments(options?: UseEnvironmentsOptions): UseEnvironmentsResult;
|
|
806
|
+
declare function useSandboxFiles(sessionId: string | null | undefined, options?: UseSandboxFilesOptions): UseSandboxFilesResult;
|
|
1196
807
|
|
|
1197
|
-
type
|
|
1198
|
-
|
|
808
|
+
type UseSandboxGitOptions = ClientOverride & {
|
|
809
|
+
/** Live event log (usually `useSessionEvents().events`) — drives auto-refresh
|
|
810
|
+
* on `git.changed`. */
|
|
811
|
+
events?: SessionEvent[] | undefined;
|
|
812
|
+
/** Repo root within the workspace (multi-repo). Default: workspace root. */
|
|
813
|
+
repoPath?: string | undefined;
|
|
814
|
+
/** All repository roots in the workspace. When supplied, status and diff are
|
|
815
|
+
* aggregated into one workspace-wide result and paths are workspace-relative. */
|
|
816
|
+
repoPaths?: readonly string[] | undefined;
|
|
817
|
+
/** Diff the staged index vs HEAD (`--cached`) instead of the working tree. */
|
|
818
|
+
staged?: boolean | undefined;
|
|
819
|
+
/** Hold off the initial fetch. Default true. */
|
|
1199
820
|
enabled?: boolean | undefined;
|
|
821
|
+
/** Lease liveness ("warm" | "draining" | "cold"). When NOT warm, the diff is
|
|
822
|
+
* served from the capture (cold/offline) instead of a live `gitDiff` RPC. */
|
|
823
|
+
liveness?: string | undefined;
|
|
824
|
+
/** The latest turn-end capture (from `useWorkspaceCapture`). Seeds the diff
|
|
825
|
+
* immediately; a warm box reconciles live and leaves this durable review
|
|
826
|
+
* surface in place if the live request is temporarily unavailable. */
|
|
827
|
+
capture?: WorkspaceCaptureManifest | null | undefined;
|
|
1200
828
|
};
|
|
1201
|
-
|
|
1202
|
-
|
|
829
|
+
/** A Git diff qualified into workspace scope. `repoRoot` is present for the
|
|
830
|
+
* workspace-wide path and lets review UI group real repositories without
|
|
831
|
+
* guessing from the first path segment. */
|
|
832
|
+
type SandboxGitFileDiff = GitFileDiff & {
|
|
833
|
+
repoRoot?: string | undefined;
|
|
834
|
+
};
|
|
835
|
+
type UseSandboxGitResult = {
|
|
836
|
+
/** Working-tree (or staged) diff vs HEAD — the structured hunks the Pierre
|
|
837
|
+
* diff view renders. */
|
|
838
|
+
diff: SandboxGitFileDiff[];
|
|
839
|
+
branch: string | null;
|
|
840
|
+
/** Whether a repo is actually mounted (drives "no repository" vs "no changes"). */
|
|
841
|
+
isRepo: boolean;
|
|
842
|
+
ahead: number;
|
|
843
|
+
behind: number;
|
|
844
|
+
/** Number and workspace-relative roots of repositories represented here. */
|
|
845
|
+
repoCount: number;
|
|
846
|
+
repoRoots: string[];
|
|
847
|
+
refresh: () => Promise<void>;
|
|
848
|
+
/** Which source the diff is served from: the live box or the turn-end capture. */
|
|
849
|
+
source: "live" | "capture" | null;
|
|
850
|
+
/** When the served capture was taken (ISO), when `source === "capture"`. */
|
|
851
|
+
capturedAt: string | null;
|
|
1203
852
|
loading: boolean;
|
|
1204
853
|
error: Error | null;
|
|
1205
|
-
refresh: () => Promise<void>;
|
|
1206
|
-
create: (request: CreateRigRequest) => Promise<Rig | null>;
|
|
1207
|
-
update: (rigId: string, request: UpdateRigRequest) => Promise<Rig | null>;
|
|
1208
|
-
remove: (rigId: string) => Promise<boolean>;
|
|
1209
|
-
listVersions: (rigId: string) => Promise<RigVersion[] | null>;
|
|
1210
|
-
activateVersion: (rigId: string, versionId: string) => Promise<RigVersion | null>;
|
|
1211
|
-
listChanges: (rigId: string) => Promise<RigChange[] | null>;
|
|
1212
|
-
proposeChange: (rigId: string, request: ProposeRigChangeRequest) => Promise<RigChange | null>;
|
|
1213
|
-
mutating: boolean;
|
|
1214
|
-
mutationError: Error | null;
|
|
1215
|
-
clearMutationError: () => void;
|
|
1216
854
|
};
|
|
1217
855
|
/**
|
|
1218
|
-
*
|
|
1219
|
-
*
|
|
1220
|
-
*
|
|
856
|
+
* Project the Git service into the Pierre diff data contract: structured
|
|
857
|
+
* `GitFileDiff[]` (per-file hunks with per-line old/new numbers, rename
|
|
858
|
+
* detection, binary flag, add/del counts) plus branch + ahead/behind. When the
|
|
859
|
+
* box is warm the `git diff` runs in-box (API-direct); when it is cold/offline the
|
|
860
|
+
* diff is served from the turn-end capture instead. Refreshes on
|
|
861
|
+
* `git.changed`; reconciles live in place on the cold→warm transition.
|
|
1221
862
|
*/
|
|
1222
|
-
declare function
|
|
1223
|
-
|
|
1224
|
-
|
|
863
|
+
declare function useSandboxGit(sessionId: string | null | undefined, options?: UseSandboxGitOptions): UseSandboxGitResult;
|
|
864
|
+
|
|
865
|
+
type UseWorkspaceCaptureOptions = ClientOverride & {
|
|
866
|
+
/** Live event log (usually `useSessionEvents().events`) — a
|
|
867
|
+
* `workspace.revision.captured` for a NEWER revision refreshes the manifest. */
|
|
868
|
+
events?: SessionEvent[] | undefined;
|
|
869
|
+
/** Hold off the mount fetch (e.g. the workbench panel is collapsed). Default true. */
|
|
1225
870
|
enabled?: boolean | undefined;
|
|
1226
871
|
};
|
|
1227
|
-
type
|
|
1228
|
-
|
|
872
|
+
type UseWorkspaceCaptureResult = {
|
|
873
|
+
/** The resolved manifest (tree index + per-repo diffs + file refs), or null when
|
|
874
|
+
* no capture exists (falls back to the live/wake path — status quo). */
|
|
875
|
+
capture: WorkspaceCaptureManifest | null;
|
|
876
|
+
/** The loaded capture's monotonic revision, or null when unavailable. */
|
|
877
|
+
revision: number | null;
|
|
878
|
+
/** When the loaded capture was taken (ISO), for the "as of <time>" source badge. */
|
|
879
|
+
capturedAt: string | null;
|
|
880
|
+
/** Whether a capture is available at all (the `{available:false}` discriminator). */
|
|
881
|
+
available: boolean;
|
|
882
|
+
/** Why the newest durable revision is unavailable. null means no capture has
|
|
883
|
+
* been attempted yet; a value means capture explicitly failed closed and
|
|
884
|
+
* consumers must use the live box rather than trust an incomplete snapshot. */
|
|
885
|
+
degradedReason: WorkspaceCaptureDegradedReason | null;
|
|
886
|
+
/** The changed-file count from the capture's stats, resolved on the FIRST GET
|
|
887
|
+
* (from the response's top-level `stats`, before any manifest-URL hop). null
|
|
888
|
+
* until that first resolve; 0 when no capture exists. This is the pre-paint
|
|
889
|
+
* "changes exist?" signal the dock uses to pick its default tab with no
|
|
890
|
+
* embedder events-at-mount contract. */
|
|
891
|
+
fileCount: number | null;
|
|
892
|
+
/** A newer revision has been ANNOUNCED than the one currently loaded (a refresh
|
|
893
|
+
* is in flight or pending). M5's source badge can show a subtle "updating…". */
|
|
894
|
+
isStale: boolean;
|
|
1229
895
|
loading: boolean;
|
|
1230
896
|
error: Error | null;
|
|
897
|
+
/** Force a re-fetch of the latest capture. */
|
|
1231
898
|
refresh: () => Promise<void>;
|
|
1232
|
-
update: (request: UpdateRigRequest) => Promise<Rig | null>;
|
|
1233
|
-
remove: () => Promise<boolean>;
|
|
1234
|
-
activateVersion: (versionId: string) => Promise<RigVersion | null>;
|
|
1235
|
-
proposeChange: (request: ProposeRigChangeRequest) => Promise<RigChange | null>;
|
|
1236
|
-
/** Re-run verification for a change (asynchronous — poll for the outcome). */
|
|
1237
|
-
verifyChange: (changeId: string) => Promise<RigChange | null>;
|
|
1238
|
-
/** Promote a verified definition_edit into a new active version (rigs:manage). */
|
|
1239
|
-
promoteChange: (changeId: string) => Promise<RigVersion | null>;
|
|
1240
|
-
/** Re-verify the active version's checks in a clean throwaway sandbox. */
|
|
1241
|
-
verify: () => Promise<{
|
|
1242
|
-
ok: boolean;
|
|
1243
|
-
versionId: string;
|
|
1244
|
-
} | null>;
|
|
1245
|
-
mutating: boolean;
|
|
1246
|
-
mutationError: Error | null;
|
|
1247
|
-
clearMutationError: () => void;
|
|
1248
899
|
};
|
|
1249
900
|
/**
|
|
1250
|
-
*
|
|
1251
|
-
*
|
|
1252
|
-
*
|
|
901
|
+
* The cold-paint data source: fetch the latest turn-end workspace capture with a
|
|
902
|
+
* SINGLE api round-trip on mount (no machine, no Channel-A — this is the <200ms
|
|
903
|
+
* first paint). The manifest is served inline in the common
|
|
904
|
+
* case; a rare >2MB manifest comes back as a short-TTL signed URL we follow.
|
|
905
|
+
*
|
|
906
|
+
* Subscribes to the live event log: a `workspace.revision.captured` for a revision
|
|
907
|
+
* newer than the one loaded triggers a background refresh (stale-while-revalidate).
|
|
908
|
+
* `{available:false}` is a value, never a crash — consumers fall back to the
|
|
909
|
+
* live/wake path exactly as before the capture feature existed.
|
|
1253
910
|
*/
|
|
1254
|
-
declare function
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
911
|
+
declare function useWorkspaceCapture(sessionId: string | null | undefined, options?: UseWorkspaceCaptureOptions): UseWorkspaceCaptureResult;
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* The wake-on-edit state machine. This hook owns the logic and the UI renders
|
|
915
|
+
* its result. States are explicit and exhaustive:
|
|
916
|
+
*
|
|
917
|
+
* viewing-cold — cold snapshot open, no local edits (editable, cloud).
|
|
918
|
+
* buffering — local edits buffered; the box is not warm and no warm is
|
|
919
|
+
* yet in flight (the host has not attached).
|
|
920
|
+
* warming — edits buffered; the box is actively coming up (the host
|
|
921
|
+
* attached a viewer in response to `wantsWarm`).
|
|
922
|
+
* flushing — the box is warm; the guarded write is in flight.
|
|
923
|
+
* flushed — the buffer was written to the live box.
|
|
924
|
+
* conflict — the live file diverged from the captured base between
|
|
925
|
+
* capture and flush; NO write was issued (C2).
|
|
926
|
+
* readonly-offline — a self-hosted machine that is offline; read-only, no wake.
|
|
927
|
+
*/
|
|
928
|
+
type WorkspaceEditState = "viewing-cold" | "buffering" | "warming" | "flushing" | "flushed" | "conflict" | "readonly-offline";
|
|
929
|
+
type WorkspaceEditConflict = {
|
|
930
|
+
path: string;
|
|
931
|
+
/** The capture-served content the edit was based on. */
|
|
932
|
+
base: string;
|
|
933
|
+
/** The live content found on the box at flush time (what would be overwritten). */
|
|
934
|
+
live: string;
|
|
1264
935
|
};
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
936
|
+
type UseWorkspaceEditOptions = ClientOverride & {
|
|
937
|
+
/** The file being edited (workspace-relative). null disables the machine. */
|
|
938
|
+
path?: string | null | undefined;
|
|
939
|
+
/** The capture-served content loaded into the editor — the flush base (C2). */
|
|
940
|
+
baseContent?: string | null | undefined;
|
|
941
|
+
/** `capabilities.liveness` — "warm" | "draining" | "cold". Drives the flush. */
|
|
942
|
+
liveness?: string | undefined;
|
|
943
|
+
/** True while the host is actively warming the box (attach in flight, not warm
|
|
944
|
+
* yet) — lifts `buffering` → `warming`. The host sets this after acting on
|
|
945
|
+
* `wantsWarm` (e.g. flipping `attachFiles` on `useSessionCapabilities`). */
|
|
946
|
+
warming?: boolean | undefined;
|
|
947
|
+
/** A self-hosted machine that is OFFLINE: read-only, no remote wake possible. */
|
|
948
|
+
offline?: boolean | undefined;
|
|
949
|
+
/** Called once when the first cold edit needs the box warmed — the host wires
|
|
950
|
+
* this to its liveness primitive (flip `attachFiles`/`attachViewer`). */
|
|
951
|
+
onWarmRequested?: (() => void) | undefined;
|
|
1270
952
|
};
|
|
1271
|
-
type
|
|
1272
|
-
|
|
1273
|
-
|
|
953
|
+
type UseWorkspaceEditResult = {
|
|
954
|
+
state: WorkspaceEditState;
|
|
955
|
+
/** The editor should be read-only (self-hosted offline). */
|
|
956
|
+
readOnly: boolean;
|
|
957
|
+
/** The current buffered content (null = no local edit yet). */
|
|
958
|
+
buffer: string | null;
|
|
959
|
+
/** The host should warm the box (flip its attach primitive). Latches true from
|
|
960
|
+
* the first cold edit until the buffer flushes or is discarded. */
|
|
961
|
+
wantsWarm: boolean;
|
|
962
|
+
/** Record an edit from the editor (idempotent per identical content). */
|
|
963
|
+
edit: (content: string) => void;
|
|
964
|
+
/** The conflict detail when `state === "conflict"`. */
|
|
965
|
+
conflict: WorkspaceEditConflict | null;
|
|
966
|
+
/** Flush the buffer regardless of the base guard (the user chose "overwrite"
|
|
967
|
+
* from the conflict bar). Writes last-writer-wins. */
|
|
968
|
+
overwrite: () => Promise<void>;
|
|
969
|
+
/** Drop the local buffer and return to viewing the snapshot. */
|
|
970
|
+
discard: () => void;
|
|
1274
971
|
error: Error | null;
|
|
1275
|
-
refresh: () => Promise<void>;
|
|
1276
972
|
};
|
|
1277
973
|
/**
|
|
1278
|
-
*
|
|
1279
|
-
*
|
|
974
|
+
* Cold-editing without a spinner: the editor opens instantly from the capture,
|
|
975
|
+
* the first keystroke buffers locally AND signals the host to warm the box, and on
|
|
976
|
+
* warm the buffer flushes IF the live file still matches the captured base — else a
|
|
977
|
+
* non-blocking conflict is surfaced and nothing is overwritten.
|
|
978
|
+
*
|
|
979
|
+
* The base guard compares the live content at flush time against `baseContent`
|
|
980
|
+
* (the exact bytes the editor loaded). This is equivalent to the sha256 compare
|
|
981
|
+
* the design specifies — M1 leaves `baseHash` null, so the loaded content IS the
|
|
982
|
+
* authoritative base — and avoids async Web Crypto in the render path.
|
|
1280
983
|
*/
|
|
1281
|
-
declare function
|
|
984
|
+
declare function useWorkspaceEdit(sessionId: string | null | undefined, options?: UseWorkspaceEditOptions): UseWorkspaceEditResult;
|
|
1282
985
|
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
986
|
+
/** The one truthful machine indicator. Honest staleness beats
|
|
987
|
+
* fake liveness: a cold/asleep box reads "offline — as of <time>", never "live". */
|
|
988
|
+
type MachineChipState = "live" | "waking" | "offline";
|
|
989
|
+
type MachineChip = {
|
|
990
|
+
state: MachineChipState;
|
|
991
|
+
/** A ready-to-render label ("Live" / "Waking…" / "Offline — as of 3m ago"). */
|
|
992
|
+
label: string;
|
|
993
|
+
/** The capture time backing an offline/stale label (ISO), or null. M4 may
|
|
994
|
+
* reformat this; `label` already embeds a relative form. */
|
|
995
|
+
asOf: string | null;
|
|
1286
996
|
};
|
|
1287
|
-
type
|
|
1288
|
-
/**
|
|
1289
|
-
|
|
1290
|
-
/**
|
|
1291
|
-
|
|
1292
|
-
/** The
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
/**
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
mutationError: Error | null;
|
|
1304
|
-
clearMutationError: () => void;
|
|
997
|
+
type DeriveMachineChipInput = {
|
|
998
|
+
/** `capabilities.liveness` — "warm" | "draining" | "cold" (or null pre-negotiation). */
|
|
999
|
+
liveness?: string | null | undefined;
|
|
1000
|
+
/** `useSessionCapabilities().state` — drives the "waking" (negotiating) read. */
|
|
1001
|
+
capabilitiesState?: SessionCapabilitiesState | null | undefined;
|
|
1002
|
+
/** The ACTIVE machine's connection state (from `useMachines`), when known. A
|
|
1003
|
+
* self-hosted machine that is `offline` cannot be remotely woken. */
|
|
1004
|
+
activeMachineState?: MachineState | null | undefined;
|
|
1005
|
+
/** Whether the active sandbox is a user-owned self-hosted machine (no remote wake). */
|
|
1006
|
+
activeIsSelfhosted?: boolean | undefined;
|
|
1007
|
+
/** An interaction (wake-on-edit, terminal focus) is actively warming the box. */
|
|
1008
|
+
wantsWarm?: boolean | undefined;
|
|
1009
|
+
/** The latest capture's `capturedAt` (ISO) — the "as of <time>" backing. */
|
|
1010
|
+
capturedAt?: string | null | undefined;
|
|
1011
|
+
/** Injectable clock for deterministic relative labels (defaults to Date.now). */
|
|
1012
|
+
now?: number | undefined;
|
|
1305
1013
|
};
|
|
1306
|
-
/**
|
|
1307
|
-
declare function
|
|
1014
|
+
/** Compact relative-time for the "as of" label. Pure, no Intl dependency. */
|
|
1015
|
+
declare function formatAsOf(capturedAt: string, now: number): string;
|
|
1016
|
+
/**
|
|
1017
|
+
* Derive the machine-state chip from the live capability/liveness surface, the
|
|
1018
|
+
* active machine's connection state, and the latest capture time. PURE (M4 renders
|
|
1019
|
+
* it; the whole point is a deterministic, testable projection).
|
|
1020
|
+
*
|
|
1021
|
+
* Precedence:
|
|
1022
|
+
* 1. warm/draining lease → **live** (a warm box always wins).
|
|
1023
|
+
* 2. actively warming (negotiating, wake-on-edit, or a reconnecting/enrolling
|
|
1024
|
+
* machine) → **waking**.
|
|
1025
|
+
* 3. everything else (a cold/asleep box, a self-hosted machine that's offline,
|
|
1026
|
+
* an error) → **offline**, labelled "as of <capture time>".
|
|
1027
|
+
*/
|
|
1028
|
+
declare function deriveMachineChip(input: DeriveMachineChipInput): MachineChip;
|
|
1029
|
+
type UseMachineChipOptions = DeriveMachineChipInput;
|
|
1030
|
+
/**
|
|
1031
|
+
* Thin memoized wrapper over `deriveMachineChip` for the dock header (M4). The
|
|
1032
|
+
* dock already runs `useSessionCapabilities` + `useMachines` + `useWorkspace
|
|
1033
|
+
* capture`; it feeds their `liveness` / `state` / active-machine state /
|
|
1034
|
+
* `capturedAt` here. Pass a periodically-updated `now` if you want the relative
|
|
1035
|
+
* "as of" label to tick.
|
|
1036
|
+
*/
|
|
1037
|
+
declare function useMachineChip(input: UseMachineChipOptions): MachineChip;
|
|
1308
1038
|
|
|
1309
|
-
type
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1039
|
+
type ApprovalSurfaceMessages = {
|
|
1040
|
+
title: string;
|
|
1041
|
+
description: string;
|
|
1042
|
+
approve: string;
|
|
1043
|
+
reject: string;
|
|
1044
|
+
approving: string;
|
|
1045
|
+
rejecting: string;
|
|
1046
|
+
formatToolName: (name: string) => string;
|
|
1047
|
+
};
|
|
1048
|
+
declare const defaultApprovalSurfaceMessages: ApprovalSurfaceMessages;
|
|
1049
|
+
type ApprovalSurfaceProps = {
|
|
1050
|
+
approvals: PendingApproval[];
|
|
1051
|
+
onApprove: (approval: PendingApproval) => void | Promise<void>;
|
|
1052
|
+
onReject: (approval: PendingApproval) => void | Promise<void>;
|
|
1053
|
+
responding?: boolean | undefined;
|
|
1054
|
+
error?: string | Error | null | undefined;
|
|
1055
|
+
messages?: Partial<ApprovalSurfaceMessages> | undefined;
|
|
1056
|
+
renderApproval?: ((approval: PendingApproval) => ReactNode) | undefined;
|
|
1057
|
+
className?: string | undefined;
|
|
1323
1058
|
};
|
|
1324
1059
|
/**
|
|
1325
|
-
*
|
|
1326
|
-
*
|
|
1060
|
+
* Host-neutral approval presentation backed by the native pending-approval
|
|
1061
|
+
* projection and control callbacks. It owns only presentation and duplicate
|
|
1062
|
+
* click fencing; OpenGeni remains the authority for approval state.
|
|
1327
1063
|
*/
|
|
1328
|
-
declare function
|
|
1064
|
+
declare function ApprovalSurface({ approvals, onApprove, onReject, responding, error, messages: overrides, renderApproval, className, }: ApprovalSurfaceProps): react_jsx_runtime.JSX.Element | null;
|
|
1329
1065
|
|
|
1330
|
-
type
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
workspaceId?: string | undefined;
|
|
1335
|
-
/** Refresh interval (ms) for live billing meters. Off by default. */
|
|
1336
|
-
pollIntervalMs?: number | undefined;
|
|
1337
|
-
enabled?: boolean | undefined;
|
|
1066
|
+
type HumanInputAnswerDraft = {
|
|
1067
|
+
values: string[];
|
|
1068
|
+
other: string;
|
|
1069
|
+
otherSelected: boolean;
|
|
1338
1070
|
};
|
|
1339
|
-
type
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1071
|
+
type HumanInputFormMessages = {
|
|
1072
|
+
title: string;
|
|
1073
|
+
description: string;
|
|
1074
|
+
submit: string;
|
|
1075
|
+
skip: string;
|
|
1076
|
+
submitting: string;
|
|
1077
|
+
other: string;
|
|
1078
|
+
deadlineLabel: string;
|
|
1079
|
+
formatDeadline: (value: string) => string;
|
|
1080
|
+
required: string;
|
|
1081
|
+
minLength: (count: number) => string;
|
|
1082
|
+
maxLength: (count: number) => string;
|
|
1083
|
+
otherRequired: string;
|
|
1084
|
+
minSelections: (count: number) => string;
|
|
1085
|
+
maxSelections: (count: number) => string;
|
|
1086
|
+
};
|
|
1087
|
+
declare const defaultHumanInputFormMessages: HumanInputFormMessages;
|
|
1088
|
+
type HumanInputFormProps = {
|
|
1089
|
+
request: Pick<SessionHumanInputRequest, "id" | "questions" | "allowSkip" | "expiresAt">;
|
|
1090
|
+
onSubmit: (response: SubmitHumanInputResponseRequest) => void | Promise<void>;
|
|
1091
|
+
submitting?: boolean | undefined;
|
|
1092
|
+
error?: string | null | undefined;
|
|
1093
|
+
title?: ReactNode;
|
|
1094
|
+
description?: ReactNode;
|
|
1095
|
+
submitLabel?: string | undefined;
|
|
1096
|
+
skipLabel?: string | undefined;
|
|
1097
|
+
messages?: Partial<HumanInputFormMessages> | undefined;
|
|
1098
|
+
autoFocus?: boolean | undefined;
|
|
1099
|
+
className?: string | undefined;
|
|
1347
1100
|
};
|
|
1348
1101
|
/**
|
|
1349
|
-
*
|
|
1350
|
-
*
|
|
1351
|
-
*
|
|
1102
|
+
* Styled but host-neutral renderer for one structured request. Hosts can use
|
|
1103
|
+
* the headless `useHumanInputRequests` hook instead, or replace the title and
|
|
1104
|
+
* description while retaining accessible field semantics and validation.
|
|
1352
1105
|
*/
|
|
1353
|
-
declare function
|
|
1106
|
+
declare function HumanInputForm({ request, onSubmit, submitting, error, title, description, submitLabel, skipLabel, messages: messageOverrides, autoFocus, className, }: HumanInputFormProps): react_jsx_runtime.JSX.Element;
|
|
1107
|
+
declare function answersFromDrafts(questions: HumanInputQuestion[], drafts: Record<string, HumanInputAnswerDraft>, messageOverrides?: Partial<HumanInputFormMessages>): {
|
|
1108
|
+
answers: HumanInputAnswer[];
|
|
1109
|
+
errors: Record<string, string>;
|
|
1110
|
+
};
|
|
1354
1111
|
|
|
1355
|
-
type
|
|
1356
|
-
|
|
1357
|
-
pollIntervalMs?: number | undefined;
|
|
1358
|
-
enabled?: boolean | undefined;
|
|
1112
|
+
type ToolRendererProps = {
|
|
1113
|
+
item: ToolCallItem;
|
|
1359
1114
|
};
|
|
1360
|
-
type
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1115
|
+
type ToolRenderer = ComponentType<ToolRendererProps>;
|
|
1116
|
+
/** A registry entry: which key it matches and the component that renders it. */
|
|
1117
|
+
type ToolRegistryEntry = {
|
|
1118
|
+
match: "rawType";
|
|
1119
|
+
type: string;
|
|
1120
|
+
render: ToolRenderer;
|
|
1121
|
+
} | {
|
|
1122
|
+
match: "name";
|
|
1123
|
+
name: string;
|
|
1124
|
+
render: ToolRenderer;
|
|
1125
|
+
};
|
|
1126
|
+
type ToolRegistry = {
|
|
1127
|
+
/** Resolve the renderer for a call (never null — falls back to generic). */
|
|
1128
|
+
resolve: (item: ToolCallItem) => ToolRenderer;
|
|
1129
|
+
/** The generic fallback renderer. */
|
|
1130
|
+
fallback: ToolRenderer;
|
|
1131
|
+
};
|
|
1132
|
+
type CreateToolRegistryOptions = {
|
|
1133
|
+
/**
|
|
1134
|
+
* Entries that take precedence over the built-ins. Earlier entries win, so a
|
|
1135
|
+
* consumer can shadow a default renderer for the same key.
|
|
1136
|
+
*/
|
|
1137
|
+
entries?: ToolRegistryEntry[] | undefined;
|
|
1138
|
+
/** Replace the generic fallback used for unmatched tools. */
|
|
1139
|
+
fallback?: ToolRenderer | undefined;
|
|
1368
1140
|
};
|
|
1141
|
+
/** The `raw.type` of a projected tool call, when the provider item carries one. */
|
|
1142
|
+
declare function rawTypeOf(item: ToolCallItem): string | null;
|
|
1369
1143
|
/**
|
|
1370
|
-
*
|
|
1371
|
-
*
|
|
1372
|
-
*
|
|
1373
|
-
*
|
|
1144
|
+
* Build a tool registry from a set of entries and a fallback. The returned
|
|
1145
|
+
* registry resolves in priority order: `raw.type` entries first, then `name`
|
|
1146
|
+
* entries, then the fallback. Consumer `entries` are consulted before the
|
|
1147
|
+
* built-in `baseEntries`, so they shadow defaults cleanly.
|
|
1374
1148
|
*/
|
|
1375
|
-
declare function
|
|
1149
|
+
declare function createToolRegistry(baseEntries: ToolRegistryEntry[], baseFallback: ToolRenderer, options?: CreateToolRegistryOptions): ToolRegistry;
|
|
1376
1150
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1151
|
+
/** The built-in tool renderer registry: every first-party tool plus a fallback. */
|
|
1152
|
+
declare const defaultToolRegistry: ToolRegistry;
|
|
1153
|
+
/** Build a registry that extends the built-ins with consumer entries/fallback. */
|
|
1154
|
+
declare function createDefaultToolRegistry(options?: Parameters<typeof createToolRegistry>[2]): ToolRegistry;
|
|
1155
|
+
|
|
1156
|
+
type ActivityRailProps = {
|
|
1157
|
+
items: ActivityItem[];
|
|
1158
|
+
/** Renderer registry for tool calls. Defaults to {@link defaultToolRegistry}. */
|
|
1159
|
+
toolRegistry?: ToolRegistry | undefined;
|
|
1160
|
+
/** Drill into a spawned worker session. */
|
|
1161
|
+
onOpenSession?: ((sessionId: string) => void) | undefined;
|
|
1379
1162
|
/**
|
|
1380
|
-
*
|
|
1381
|
-
*
|
|
1382
|
-
*
|
|
1163
|
+
* Deep-link a memory row to its record in the host's memory pane. Opt-in: the
|
|
1164
|
+
* library draws no "View in memory" affordance without a handler (the memory
|
|
1165
|
+
* row is then non-interactive rich content). See {@link MessageTimelineProps}.
|
|
1383
1166
|
*/
|
|
1384
|
-
|
|
1167
|
+
onMemoryClick?: ((memoryId: string) => void) | undefined;
|
|
1168
|
+
/** Drop the left rule + indent (used inside a folded turn summary). */
|
|
1169
|
+
bare?: boolean | undefined;
|
|
1170
|
+
className?: string | undefined;
|
|
1171
|
+
};
|
|
1172
|
+
declare function ActivityRail({ items, toolRegistry, onOpenSession, onMemoryClick, bare, className, }: ActivityRailProps): react_jsx_runtime.JSX.Element;
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* A subtle settle signal — see the CHIP DOCTRINE above. The closed tone set.
|
|
1176
|
+
* `"interrupted"` is a calm neutral tone for cancelled items — no dot, same
|
|
1177
|
+
* quiet weight as `"muted"`, but semantically distinct from metadata.
|
|
1178
|
+
*/
|
|
1179
|
+
type DisclosureChip = {
|
|
1180
|
+
tone: "ok" | "bad" | "muted" | "interrupted";
|
|
1181
|
+
text: string;
|
|
1182
|
+
};
|
|
1183
|
+
type ActivityDisclosureProps = {
|
|
1184
|
+
icon: ReactNode;
|
|
1185
|
+
/** Icon tint. Defaults to the muted foreground; renderers pass accent/failed. */
|
|
1186
|
+
iconTone?: "accent" | "failed" | "running" | "muted" | undefined;
|
|
1187
|
+
title: ReactNode;
|
|
1188
|
+
/** Render the title in the mono face (commands, paths). */
|
|
1189
|
+
titleMono?: boolean | undefined;
|
|
1190
|
+
/** Shimmer the title while the tool is in-flight. */
|
|
1191
|
+
running?: boolean | undefined;
|
|
1385
1192
|
/**
|
|
1386
|
-
*
|
|
1387
|
-
*
|
|
1388
|
-
* the
|
|
1389
|
-
* negotiation (no holder, no warm) — terminal/files/git work without it.
|
|
1193
|
+
* Quiet single-line secondary text (truncated). It is detail-on-demand: hidden
|
|
1194
|
+
* when a media preview is set, AND hidden once the row is expanded (the body
|
|
1195
|
+
* then owns the detail), so a stat/path never appears twice at once.
|
|
1390
1196
|
*/
|
|
1391
|
-
|
|
1197
|
+
preview?: ReactNode | undefined;
|
|
1198
|
+
/** A small inline media preview (a screenshot thumbnail) shown in place of `preview`. */
|
|
1199
|
+
media?: ReactNode | undefined;
|
|
1200
|
+
/** At most one quiet settle chip, right-aligned to the gutter. */
|
|
1201
|
+
chip?: DisclosureChip | undefined;
|
|
1392
1202
|
/**
|
|
1393
|
-
*
|
|
1394
|
-
*
|
|
1395
|
-
*
|
|
1396
|
-
*
|
|
1397
|
-
*
|
|
1398
|
-
*
|
|
1399
|
-
*
|
|
1203
|
+
* When true the row carries the standard failure affordance: the icon is tinted
|
|
1204
|
+
* red and a "failed" bad-chip appears in the right gutter (unless an explicit
|
|
1205
|
+
* `chip` is already supplied — the caller's chip wins). Output is still visible
|
|
1206
|
+
* on expand; this is a quiet status signal, not a blocking banner.
|
|
1207
|
+
*
|
|
1208
|
+
* Renderers should pass `failed={item.status === "failed"}` on their settled
|
|
1209
|
+
* (non-running) paths so any tool with a failed status shows a consistent
|
|
1210
|
+
* affordance without each renderer having to duplicate the logic.
|
|
1400
1211
|
*/
|
|
1401
|
-
|
|
1212
|
+
failed?: boolean | undefined;
|
|
1402
1213
|
/**
|
|
1403
|
-
*
|
|
1404
|
-
*
|
|
1405
|
-
*
|
|
1406
|
-
*
|
|
1407
|
-
*
|
|
1408
|
-
*
|
|
1409
|
-
*
|
|
1410
|
-
*
|
|
1411
|
-
*
|
|
1412
|
-
* opening/reading the Files tab must NOT set this — browsing capture-served
|
|
1413
|
-
* trees/diffs needs no box, and warming one on a cold glance burns box-hours to
|
|
1414
|
-
* serve reads the capture already answers for free.
|
|
1214
|
+
* When true the row carries a calm "interrupted" affordance: the icon stays
|
|
1215
|
+
* muted (no red) and a quiet "interrupted" chip appears in the right gutter
|
|
1216
|
+
* (unless an explicit `chip` is already supplied — the caller's chip wins).
|
|
1217
|
+
* This is the cancelled-status analogue of `failed`, but deliberately calm
|
|
1218
|
+
* and neutral — it is NOT an error; the user chose to stop.
|
|
1219
|
+
*
|
|
1220
|
+
* Renderers should pass `cancelled={item.status === "cancelled"}` so any
|
|
1221
|
+
* in-flight item that was interrupted on turn.cancelled reads consistently.
|
|
1222
|
+
* `cancelled` is ignored when `failed` is also true (failure takes precedence).
|
|
1415
1223
|
*/
|
|
1416
|
-
|
|
1417
|
-
/**
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1224
|
+
cancelled?: boolean | undefined;
|
|
1225
|
+
/** When false the row is a static line (no expand affordance). */
|
|
1226
|
+
expandable?: boolean | undefined;
|
|
1227
|
+
children?: ReactNode | undefined;
|
|
1228
|
+
};
|
|
1229
|
+
/**
|
|
1230
|
+
* The one disclosure row shape every activity row reuses (tool calls, reasoning,
|
|
1231
|
+
* sandbox ops): a chevron, a tinted icon, a title, an optional muted preview or
|
|
1232
|
+
* inline media, and at most one right-gutter settle chip. Compact by default;
|
|
1233
|
+
* the body mounts only when expanded.
|
|
1234
|
+
*/
|
|
1235
|
+
declare function ActivityDisclosure({ icon, iconTone: iconToneProp, title, titleMono, running, preview, media, chip: chipProp, failed, cancelled, expandable, children, }: ActivityDisclosureProps): react_jsx_runtime.JSX.Element;
|
|
1236
|
+
declare function TermBlock({ command, workdir, output, live, tailLines, failed, }: {
|
|
1421
1237
|
/**
|
|
1422
|
-
*
|
|
1423
|
-
*
|
|
1424
|
-
*
|
|
1425
|
-
*
|
|
1238
|
+
* The command shown in the prompt header. Pass `null` when the row title
|
|
1239
|
+
* already carries it (e.g. an exec row titled `$ cmd`): the header then drops
|
|
1240
|
+
* the command — and the whole prompt line if there is no workdir either — so
|
|
1241
|
+
* the command never reads twice, stacked, above the output.
|
|
1426
1242
|
*/
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1243
|
+
command: string | null;
|
|
1244
|
+
workdir?: string | null | undefined;
|
|
1245
|
+
/** The FULL output. TermBlock owns the tail/full slicing internally. */
|
|
1246
|
+
output: string;
|
|
1247
|
+
live?: boolean | undefined;
|
|
1248
|
+
/** A non-zero exit / failed call — tints the left accent red (the one hue). */
|
|
1249
|
+
failed?: boolean | undefined;
|
|
1434
1250
|
/**
|
|
1435
|
-
*
|
|
1436
|
-
*
|
|
1251
|
+
* When the output exceeds the tail window, only the last `tailLines` are shown
|
|
1252
|
+
* with a "show full output" toggle. The component holds the full text, so the
|
|
1253
|
+
* toggle reveals the rest (never a dead affordance). Defaults to 12.
|
|
1437
1254
|
*/
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
* holds a viewer lease + heartbeats it so the box stays warm while watched.
|
|
1451
|
-
*
|
|
1452
|
-
* Degradation is a value, never a crash: an unsupported surface comes back
|
|
1453
|
-
* `available:false`/`transport:null` + a `reason`; the components render the
|
|
1454
|
-
* reason-aware empty state. 409 (consent) and 429 (viewer cap) are surfaced as
|
|
1455
|
-
* typed signals, not thrown.
|
|
1456
|
-
*/
|
|
1457
|
-
declare function useSessionCapabilities(sessionId: string | null | undefined, options?: UseSessionCapabilitiesOptions): UseSessionCapabilitiesResult;
|
|
1458
|
-
|
|
1255
|
+
tailLines?: number | undefined;
|
|
1256
|
+
}): react_jsx_runtime.JSX.Element;
|
|
1257
|
+
declare function PayloadBlock({ label, value, failed, }: {
|
|
1258
|
+
label: string;
|
|
1259
|
+
value: unknown;
|
|
1260
|
+
failed?: boolean | undefined;
|
|
1261
|
+
}): react_jsx_runtime.JSX.Element | null;
|
|
1262
|
+
/** A quiet inline note inside an expanded body (lost output, empty frame, …). */
|
|
1263
|
+
declare function BodyNote({ children, tone, }: {
|
|
1264
|
+
children: ReactNode;
|
|
1265
|
+
tone?: "error" | "muted" | undefined;
|
|
1266
|
+
}): react_jsx_runtime.JSX.Element;
|
|
1459
1267
|
/**
|
|
1460
|
-
*
|
|
1461
|
-
*
|
|
1462
|
-
*
|
|
1463
|
-
* the browser `WebSocket`.
|
|
1268
|
+
* A loading screenshot placeholder. A faint camera glyph over a shimmering box,
|
|
1269
|
+
* so a still frame of the running state reads unambiguously as "capturing" — not
|
|
1270
|
+
* a broken thumbnail.
|
|
1464
1271
|
*/
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
close(): void;
|
|
1469
|
-
addEventListener(type: "open" | "message" | "error" | "close", listener: (ev: {
|
|
1470
|
-
data?: unknown;
|
|
1471
|
-
} & Record<string, unknown>) => void): void;
|
|
1472
|
-
removeEventListener(type: "open" | "message" | "error" | "close", listener: (ev: {
|
|
1473
|
-
data?: unknown;
|
|
1474
|
-
} & Record<string, unknown>) => void): void;
|
|
1475
|
-
}
|
|
1476
|
-
type DesktopWebSocketFactory = (url: string) => DesktopWebSocketLike;
|
|
1477
|
-
type UseRelayFrameStreamOptions = {
|
|
1478
|
-
/** The desktop cell of the negotiated capabilities (`capabilities.DesktopStream`). */
|
|
1479
|
-
capability: DesktopStreamCapability | null;
|
|
1480
|
-
/** The mount target. A `<canvas>` is appended here on connect. */
|
|
1481
|
-
containerRef: RefObject<HTMLDivElement | null>;
|
|
1482
|
-
/** Custom socket factory (tests / a transport swap). Defaults to `new WebSocket(url)`. */
|
|
1483
|
-
webSocketFactory?: DesktopWebSocketFactory | undefined;
|
|
1484
|
-
};
|
|
1485
|
-
type UseRelayFrameStreamResult = {
|
|
1486
|
-
state: DesktopConnectionState;
|
|
1487
|
-
error: Error | null;
|
|
1488
|
-
/** Tear down + reopen the socket (e.g. after a drop, once a fresh url arrives). */
|
|
1489
|
-
reconnect: () => void;
|
|
1490
|
-
};
|
|
1272
|
+
declare function MediaSkeleton(): react_jsx_runtime.JSX.Element;
|
|
1273
|
+
/** A standardized "tool ran, produced no image" placeholder in the media slot. */
|
|
1274
|
+
declare function MediaEmpty(): react_jsx_runtime.JSX.Element;
|
|
1491
1275
|
/**
|
|
1492
|
-
*
|
|
1493
|
-
* transport (`transport: "relay-frames"`, `client: "frames"`). The self-hosted
|
|
1494
|
-
* agent produces one PNG per frame as a protobuf datagram over the relay; there
|
|
1495
|
-
* is no RFB/noVNC here. This hook opens the relay DESKTOP channel as a CLIENT
|
|
1496
|
-
* (mirroring the proven diagnostic wire protocol), decodes each PNG onto a
|
|
1497
|
-
* `<canvas>` mounted into `containerRef`, and drives the connection state
|
|
1498
|
-
* machine: idle → connecting (ws opening) → connected (first painted frame) →
|
|
1499
|
-
* error (ws error/close/ack rejection).
|
|
1500
|
-
*
|
|
1501
|
-
* It is DORMANT for any other transport (or no url): it stays idle and touches
|
|
1502
|
-
* nothing, so the noVNC path owns the surface. SSR-safe: the socket + DOM attach
|
|
1503
|
-
* live inside `useEffect`.
|
|
1276
|
+
* A small inline screenshot thumbnail that opens the app lightbox on click.
|
|
1504
1277
|
*
|
|
1505
|
-
*
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
1278
|
+
* Requires a `LightboxProvider` ancestor for the click-to-expand affordance.
|
|
1279
|
+
* Outside one it degrades to a plain, non-interactive image — never a dead
|
|
1280
|
+
* "Expand" button that announces an action it cannot perform.
|
|
1508
1281
|
*/
|
|
1509
|
-
declare function
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
/** The mount target. RFB (or the frame canvas) attaches here on connect. */
|
|
1515
|
-
containerRef: RefObject<HTMLDivElement | null>;
|
|
1516
|
-
/** Read-only by default (v1 ruling H). interactive only when cap.mode allows. */
|
|
1517
|
-
interactive?: boolean | undefined;
|
|
1518
|
-
scaleViewport?: boolean | undefined;
|
|
1519
|
-
/** Custom RFB factory (tests / a WebRTC swap). Defaults to a lazy @novnc/novnc. */
|
|
1520
|
-
rfbFactory?: DesktopRfbFactory | undefined;
|
|
1521
|
-
/** Custom socket factory for the `relay-frames` transport (tests). Defaults to
|
|
1522
|
-
* `new WebSocket(url)`. Mirrors `rfbFactory` for the frame renderer. */
|
|
1523
|
-
webSocketFactory?: DesktopWebSocketFactory | undefined;
|
|
1524
|
-
};
|
|
1525
|
-
type UseDesktopStreamResult = {
|
|
1526
|
-
state: DesktopConnectionState;
|
|
1527
|
-
error: Error | null;
|
|
1528
|
-
/** Manual reconnect (e.g. after a securityfailure once a fresh URL arrives). */
|
|
1529
|
-
reconnect: () => void;
|
|
1530
|
-
};
|
|
1282
|
+
declare function Thumbnail({ src, caption, alt, }: {
|
|
1283
|
+
src: string;
|
|
1284
|
+
caption?: string | undefined;
|
|
1285
|
+
alt?: string;
|
|
1286
|
+
}): react_jsx_runtime.JSX.Element;
|
|
1531
1287
|
/**
|
|
1532
|
-
*
|
|
1533
|
-
*
|
|
1534
|
-
*
|
|
1535
|
-
*
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
* `useRelayFrameStream`, which paints a `<canvas>`. Both hooks are ALWAYS called
|
|
1546
|
-
* (rules of hooks); each is dormant for the other's transport, and we return the
|
|
1547
|
-
* result of whichever owns the surface. The public interface is identical either
|
|
1548
|
-
* way, so `DesktopViewer` is transport-agnostic.
|
|
1549
|
-
*/
|
|
1550
|
-
declare function useDesktopStream(options: UseDesktopStreamOptions): UseDesktopStreamResult;
|
|
1551
|
-
|
|
1552
|
-
/** The ttyd connection lifecycle as surfaced to the component. */
|
|
1553
|
-
type TerminalStreamStatus = "connecting" | "open" | "closed" | "error";
|
|
1554
|
-
type UseTerminalStreamOptions = {
|
|
1555
|
-
/** The Terminal cell of the negotiated capabilities (`capabilities.Terminal`).
|
|
1556
|
-
* The stream connects ONLY when `transport === "pty-ws"` and `url` is set; on a
|
|
1557
|
-
* cold box (`transport === "sse-events"` / no url) it stays idle and the caller
|
|
1558
|
-
* falls back to the Channel-A read-only firehose. */
|
|
1559
|
-
capability: Pick<TerminalCapability, "transport" | "url" | "token"> | null;
|
|
1560
|
-
/** Called for each OUTPUT payload from ttyd (write verbatim into xterm). */
|
|
1561
|
-
onOutput?: ((data: string) => void) | undefined;
|
|
1562
|
-
/** Called when ttyd sends a SET_WINDOW_TITLE frame. */
|
|
1563
|
-
onTitle?: ((title: string) => void) | undefined;
|
|
1564
|
-
/** Initial PTY size to seed the ttyd auth frame + first resize. */
|
|
1565
|
-
initialCols?: number | undefined;
|
|
1566
|
-
initialRows?: number | undefined;
|
|
1567
|
-
};
|
|
1568
|
-
type UseTerminalStreamResult = {
|
|
1569
|
-
/** True once the ttyd socket is open (and the auth frame has been sent). */
|
|
1570
|
-
connected: boolean;
|
|
1571
|
-
status: TerminalStreamStatus;
|
|
1572
|
-
/** Pipe a keystroke/paste to the PTY stdin. No-op until the socket is open. */
|
|
1573
|
-
write: (data: string) => void;
|
|
1574
|
-
/** Tell ttyd the PTY window changed size (on xterm fit/resize). */
|
|
1575
|
-
resize: (cols: number, rows: number) => void;
|
|
1576
|
-
/** Tear the socket down (the effect also tears down on unmount / url change). */
|
|
1577
|
-
disconnect: () => void;
|
|
1578
|
-
};
|
|
1579
|
-
/**
|
|
1580
|
-
* Drive a ttyd PTY-over-websocket connection from a `pty-ws` Terminal capability,
|
|
1581
|
-
* symmetric with `use-desktop-stream` (the noVNC-over-tunnel hook). The scoped
|
|
1582
|
-
* stream token is already embedded in the minted tunnel `url`; the WebSocket is
|
|
1583
|
-
* opened with the REQUIRED ttyd subprotocol "tty".
|
|
1584
|
-
*
|
|
1585
|
-
* ttyd wire protocol (see `@opengeni/sdk/terminal`):
|
|
1586
|
-
* - first frame: `JSON.stringify({ AuthToken: "" })` (+ optional columns/rows).
|
|
1587
|
-
* - client→server: INPUT = "0"+data ; RESIZE = "1"+JSON({columns,rows}).
|
|
1588
|
-
* - server→client: "0" = OUTPUT (→ xterm) ; "1" = SET_WINDOW_TITLE ;
|
|
1589
|
-
* "2" = SET_PREFERENCES (ignored). Binary frames are decoded the same way.
|
|
1590
|
-
*
|
|
1591
|
-
* On a `url`/`token` rotation (a box rollover folds a fresh address into the cell)
|
|
1592
|
-
* the effect re-runs: the old socket closes and a fresh one connects — a brief
|
|
1593
|
-
* terminal blink, acceptable on rollover (mirrors the desktop's RFB hot-swap).
|
|
1594
|
-
* SSR-safe: the socket open lives in `useEffect`, so a server render is a no-op.
|
|
1595
|
-
*/
|
|
1596
|
-
declare function useTerminalStream(options: UseTerminalStreamOptions): UseTerminalStreamResult;
|
|
1597
|
-
|
|
1598
|
-
type TerminalChunk = {
|
|
1599
|
-
/** Stable key (the source event id) so the xterm writer tracks a written-cursor. */
|
|
1600
|
-
id: string;
|
|
1601
|
-
/** Raw output bytes (utf-8 lossy) — written verbatim into xterm. */
|
|
1602
|
-
text: string;
|
|
1603
|
-
/** stdout vs stderr (drives optional tinting). */
|
|
1604
|
-
stream: "stdout" | "stderr";
|
|
1605
|
-
/** Global ordering: the source event sequence. */
|
|
1606
|
-
seq: number;
|
|
1607
|
-
};
|
|
1608
|
-
type UseSandboxTerminalOptions = ClientOverride & {
|
|
1609
|
-
/** The live session event log (usually `useSessionEvents().events`). */
|
|
1610
|
-
events: SessionEvent[];
|
|
1611
|
-
/** Restrict to one PTY (by ptyId). Omit to interleave the agent firehose +
|
|
1612
|
-
* every PTY. */
|
|
1613
|
-
ptyId?: string | undefined;
|
|
1614
|
-
/** Include the agent's command-output firehose (sandbox.command.output.delta).
|
|
1615
|
-
* Default true — the read-only "terminal-as-events" the data path settled on. */
|
|
1616
|
-
includeAgentFirehose?: boolean | undefined;
|
|
1617
|
-
/**
|
|
1618
|
-
* OPEN an interactive PTY against the box so the user can type, not just watch.
|
|
1619
|
-
* When true (and the session is live) the hook calls `terminalPtyOpen` once,
|
|
1620
|
-
* tracks the returned ptyId, exposes `write` immediately (bound to that ptyId),
|
|
1621
|
-
* and closes the PTY on unmount. The PTY's banner + every output delta ride the
|
|
1622
|
-
* SSE spine (`terminal.pty.*`) back into `events`, so xterm fills in. Default
|
|
1623
|
-
* false — a caller that only wants the read-only firehose stays projection-only.
|
|
1624
|
-
*/
|
|
1625
|
-
interactive?: boolean | undefined;
|
|
1626
|
-
/** Lease liveness ("cold" | "warm" | "draining"). The interactive PTY is only
|
|
1627
|
-
* opened once the box is warm — opening on a cold box (ptyCapable is advertised
|
|
1628
|
-
* cold too) races the box and leaves a dead read-only terminal. */
|
|
1629
|
-
liveness?: string | undefined;
|
|
1630
|
-
};
|
|
1631
|
-
type UseSandboxTerminalResult = {
|
|
1632
|
-
/** Ordered, deduped output chunks to write() into xterm.js. */
|
|
1633
|
-
chunks: TerminalChunk[];
|
|
1634
|
-
/** Whether a PTY is currently open (drives the prompt/cursor affordance). */
|
|
1635
|
-
running: boolean;
|
|
1636
|
-
/**
|
|
1637
|
-
* Interactive write fn when a PTY is open and the backend supports stdin
|
|
1638
|
-
* (`terminal.transport === "pty-ws"` / `PtyOpenResponse.supportsInput`). Null
|
|
1639
|
-
* in the read-only event-projection case (v1 default).
|
|
1640
|
-
*/
|
|
1641
|
-
write: ((data: string) => void) | null;
|
|
1642
|
-
/** The active PTY id, if one is open. */
|
|
1643
|
-
activePtyId: string | null;
|
|
1644
|
-
/** Close the active PTY (no-op when none is open). */
|
|
1645
|
-
close: () => void;
|
|
1646
|
-
/** A PTY-open failure (interactive mode), if any. */
|
|
1647
|
-
error: Error | null;
|
|
1648
|
-
};
|
|
1649
|
-
/**
|
|
1650
|
-
* Project the Channel-A event log into an xterm-writable byte stream. The
|
|
1651
|
-
* terminal is "terminal-as-events": there is NO new socket in v1 — the agent's
|
|
1652
|
-
* command output (`sandbox.command.output.delta`) and any interactive PTY
|
|
1653
|
-
* (`terminal.pty.output.delta`) ride the existing SSE spine. When a PTY is open
|
|
1654
|
-
* and the backend accepts stdin, `write` pipes keystrokes via the SDK
|
|
1655
|
-
* `terminalPtyWrite` (the synchronous Channel-A control path).
|
|
1656
|
-
*/
|
|
1657
|
-
declare function useSandboxTerminal(sessionId: string | null | undefined, options: UseSandboxTerminalOptions): UseSandboxTerminalResult;
|
|
1658
|
-
|
|
1659
|
-
/** The git-status overlay a file row may carry (tints modified files in the tree). */
|
|
1660
|
-
type FileTreeStatus = "added" | "modified" | "deleted" | "renamed" | "untracked";
|
|
1661
|
-
/** A node in the Pierre file tree. `children === undefined` ⇒ an unexpanded dir
|
|
1662
|
-
* (lazy treeMode); `children: []` ⇒ an expanded-but-empty dir. */
|
|
1663
|
-
type FileTreeNode = {
|
|
1664
|
-
path: string;
|
|
1665
|
-
name: string;
|
|
1666
|
-
kind: "file" | "dir";
|
|
1667
|
-
children?: FileTreeNode[] | undefined;
|
|
1668
|
-
size?: number | null | undefined;
|
|
1669
|
-
status?: FileTreeStatus | undefined;
|
|
1670
|
-
/** A residue dir the capture COLLAPSED (node_modules, .git, dist, …): its
|
|
1671
|
-
* contents were never indexed. Cold, expanding it can't list children — the
|
|
1672
|
-
* UI shows an inline "contents on machine" row until the box is warm. */
|
|
1673
|
-
truncated?: boolean | undefined;
|
|
1674
|
-
};
|
|
1675
|
-
type UseSandboxFilesOptions = ClientOverride & {
|
|
1676
|
-
/** Live event log (usually `useSessionEvents().events`) — drives auto-refresh
|
|
1677
|
-
* on `fs.changed` / `git.changed`. */
|
|
1678
|
-
events?: SessionEvent[] | undefined;
|
|
1679
|
-
/** Initial path to list (workspace root by default). */
|
|
1680
|
-
rootPath?: string | undefined;
|
|
1681
|
-
/** Hold off the initial list (e.g. panel collapsed). Default true. */
|
|
1682
|
-
enabled?: boolean | undefined;
|
|
1683
|
-
/** The lease liveness ("cold" | "warm" | "draining"). The structured FileSystem
|
|
1684
|
-
* capability is advertised even on a COLD box, so the mount-time list can race
|
|
1685
|
-
* the box: it lists before the box is warm, gets an empty/errored result, and
|
|
1686
|
-
* (with no `fs.changed` event) never re-lists. Passing liveness re-lists when
|
|
1687
|
-
* the box first becomes warm, so the tree populates as soon as the box is up. */
|
|
1688
|
-
liveness?: string | undefined;
|
|
1689
|
-
/** The latest turn-end workspace capture (from `useWorkspaceCapture`). When the
|
|
1690
|
-
* box is NOT warm, the tree paints INSTANTLY from this capture's tree index (the
|
|
1691
|
-
* <200ms cold first paint) instead of blocking on a Channel-A list. A warm box
|
|
1692
|
-
* always wins (live path unchanged). On the cold→warm transition the live list
|
|
1693
|
-
* is merged in place — no remount, no flash (dossier §10.4 / §12-A1/D1). */
|
|
1694
|
-
capture?: WorkspaceCaptureManifest | null | undefined;
|
|
1695
|
-
/** Called when an OPTIMISTIC mutation is reverted because its background
|
|
1696
|
-
* Channel-A op failed (e.g. a 409 rename collision). The host wires this to a
|
|
1697
|
-
* toast — the tree silently rolls the node back, the user sees why. */
|
|
1698
|
-
onMutationError?: ((error: Error, op: string) => void) | undefined;
|
|
1699
|
-
};
|
|
1700
|
-
type UseSandboxFilesResult = {
|
|
1701
|
-
/** The tree roots (the listed root's children). */
|
|
1702
|
-
tree: FileTreeNode[];
|
|
1703
|
-
/** Lazy-expand a directory node in place (lists its immediate children). */
|
|
1704
|
-
expand: (path: string) => Promise<void>;
|
|
1705
|
-
/** Paths whose lazy `fs.list` is currently in flight — the FileBrowser shows a
|
|
1706
|
-
* spinner on these nodes so a 2-3s Channel-A list never looks frozen. */
|
|
1707
|
-
expandingPaths: Set<string>;
|
|
1708
|
-
/** Read a file for the preview pane (text or base64-for-binary, size-capped). */
|
|
1709
|
-
readFile: (path: string) => Promise<FsReadResponse>;
|
|
1710
|
-
/** Write a file (overwrite, last-writer-wins) — the editor save path.
|
|
1711
|
-
* Optimistic: a brand-new file is spliced into the tree immediately and the
|
|
1712
|
-
* Channel-A write runs in the background; on failure the splice is reverted. */
|
|
1713
|
-
writeFile: (path: string, content: string) => Promise<FsWriteResponse>;
|
|
1714
|
-
/** Create a new empty file (refuses to clobber an existing path: overwrite=false). */
|
|
1715
|
-
createFile: (path: string) => Promise<void>;
|
|
1716
|
-
/** Create a directory (recursive by default). */
|
|
1717
|
-
createDir: (path: string) => Promise<void>;
|
|
1718
|
-
/** Delete a path (pass recursive=true for a non-empty directory). */
|
|
1719
|
-
deleteEntry: (path: string, recursive?: boolean) => Promise<void>;
|
|
1720
|
-
/** Move / rename a path (rename == move). Refuses to clobber unless overwrite=true. */
|
|
1721
|
-
moveEntry: (path: string, newPath: string, opts?: {
|
|
1722
|
-
overwrite?: boolean;
|
|
1723
|
-
}) => Promise<void>;
|
|
1724
|
-
/** Re-list the whole tree from the root. */
|
|
1725
|
-
refresh: () => Promise<void>;
|
|
1726
|
-
/** Which source the tree is currently served from: the live box, the turn-end
|
|
1727
|
-
* capture (cold/offline), or neither yet. M5's source badge reads this. */
|
|
1728
|
-
source: "live" | "capture" | null;
|
|
1729
|
-
/** When the served capture was taken (ISO), when `source === "capture"`. */
|
|
1730
|
-
capturedAt: string | null;
|
|
1731
|
-
loading: boolean;
|
|
1732
|
-
error: Error | null;
|
|
1733
|
-
};
|
|
1734
|
-
/**
|
|
1735
|
-
* Project the FileSystem service into a lazy-loaded Pierre tree. The initial
|
|
1736
|
-
* list pulls one level (depth 1); `expand(path)` lists a directory's immediate
|
|
1737
|
-
* children on demand (the fast lazy-tree UX). A git-status overlay tints
|
|
1738
|
-
* modified files. Auto-refreshes when an `fs.changed` / `git.changed` event
|
|
1739
|
-
* arrives on the live log.
|
|
1740
|
-
*/
|
|
1741
|
-
declare function useSandboxFiles(sessionId: string | null | undefined, options?: UseSandboxFilesOptions): UseSandboxFilesResult;
|
|
1742
|
-
|
|
1743
|
-
type UseSandboxGitOptions = ClientOverride & {
|
|
1744
|
-
/** Live event log (usually `useSessionEvents().events`) — drives auto-refresh
|
|
1745
|
-
* on `git.changed`. */
|
|
1746
|
-
events?: SessionEvent[] | undefined;
|
|
1747
|
-
/** Repo root within the workspace (multi-repo). Default: workspace root. */
|
|
1748
|
-
repoPath?: string | undefined;
|
|
1749
|
-
/** Diff the staged index vs HEAD (`--cached`) instead of the working tree. */
|
|
1750
|
-
staged?: boolean | undefined;
|
|
1751
|
-
/** Hold off the initial fetch. Default true. */
|
|
1752
|
-
enabled?: boolean | undefined;
|
|
1753
|
-
/** Lease liveness ("warm" | "draining" | "cold"). When NOT warm, the diff is
|
|
1754
|
-
* served from the capture (cold/offline) instead of a live `gitDiff` RPC. */
|
|
1755
|
-
liveness?: string | undefined;
|
|
1756
|
-
/** The latest turn-end capture (from `useWorkspaceCapture`). Supplies the cold
|
|
1757
|
-
* diff for this repo. A warm box always wins (live `gitDiff` unchanged). */
|
|
1758
|
-
capture?: WorkspaceCaptureManifest | null | undefined;
|
|
1759
|
-
};
|
|
1760
|
-
type UseSandboxGitResult = {
|
|
1761
|
-
/** Working-tree (or staged) diff vs HEAD — the structured hunks the Pierre
|
|
1762
|
-
* diff view renders. */
|
|
1763
|
-
diff: GitFileDiff[];
|
|
1764
|
-
branch: string | null;
|
|
1765
|
-
/** Whether a repo is actually mounted (drives "no repository" vs "no changes"). */
|
|
1766
|
-
isRepo: boolean;
|
|
1767
|
-
ahead: number;
|
|
1768
|
-
behind: number;
|
|
1769
|
-
refresh: () => Promise<void>;
|
|
1770
|
-
/** Which source the diff is served from: the live box or the turn-end capture. */
|
|
1771
|
-
source: "live" | "capture" | null;
|
|
1772
|
-
/** When the served capture was taken (ISO), when `source === "capture"`. */
|
|
1773
|
-
capturedAt: string | null;
|
|
1774
|
-
loading: boolean;
|
|
1775
|
-
error: Error | null;
|
|
1776
|
-
};
|
|
1777
|
-
/**
|
|
1778
|
-
* Project the Git service into the Pierre diff data contract: structured
|
|
1779
|
-
* `GitFileDiff[]` (per-file hunks with per-line old/new numbers, rename
|
|
1780
|
-
* detection, binary flag, add/del counts) plus branch + ahead/behind. When the
|
|
1781
|
-
* box is warm the `git diff` runs in-box (API-direct); when it is cold/offline the
|
|
1782
|
-
* diff is served from the turn-end capture instead (dossier §10.4). Refreshes on
|
|
1783
|
-
* `git.changed`; reconciles live in place on the cold→warm transition.
|
|
1784
|
-
*/
|
|
1785
|
-
declare function useSandboxGit(sessionId: string | null | undefined, options?: UseSandboxGitOptions): UseSandboxGitResult;
|
|
1786
|
-
|
|
1787
|
-
type UseWorkspaceCaptureOptions = ClientOverride & {
|
|
1788
|
-
/** Live event log (usually `useSessionEvents().events`) — a
|
|
1789
|
-
* `workspace.revision.captured` for a NEWER revision refreshes the manifest. */
|
|
1790
|
-
events?: SessionEvent[] | undefined;
|
|
1791
|
-
/** Hold off the mount fetch (e.g. the workbench panel is collapsed). Default true. */
|
|
1792
|
-
enabled?: boolean | undefined;
|
|
1793
|
-
};
|
|
1794
|
-
type UseWorkspaceCaptureResult = {
|
|
1795
|
-
/** The resolved manifest (tree index + per-repo diffs + file refs), or null when
|
|
1796
|
-
* no capture exists (falls back to the live/wake path — status quo). */
|
|
1797
|
-
capture: WorkspaceCaptureManifest | null;
|
|
1798
|
-
/** The loaded capture's monotonic revision, or null when unavailable. */
|
|
1799
|
-
revision: number | null;
|
|
1800
|
-
/** When the loaded capture was taken (ISO), for the "as of <time>" source badge. */
|
|
1801
|
-
capturedAt: string | null;
|
|
1802
|
-
/** Whether a capture is available at all (the `{available:false}` discriminator). */
|
|
1803
|
-
available: boolean;
|
|
1804
|
-
/** Why the newest durable revision is unavailable. null means no capture has
|
|
1805
|
-
* been attempted yet; a value means capture explicitly failed closed and
|
|
1806
|
-
* consumers must use the live box rather than trust an incomplete snapshot. */
|
|
1807
|
-
degradedReason: WorkspaceCaptureDegradedReason | null;
|
|
1808
|
-
/** The changed-file count from the capture's stats, resolved on the FIRST GET
|
|
1809
|
-
* (from the response's top-level `stats`, before any manifest-URL hop). null
|
|
1810
|
-
* until that first resolve; 0 when no capture exists. This is the pre-paint
|
|
1811
|
-
* "changes exist?" signal the dock uses to pick its default tab with no
|
|
1812
|
-
* embedder events-at-mount contract. */
|
|
1813
|
-
fileCount: number | null;
|
|
1814
|
-
/** A newer revision has been ANNOUNCED than the one currently loaded (a refresh
|
|
1815
|
-
* is in flight or pending). M5's source badge can show a subtle "updating…". */
|
|
1816
|
-
isStale: boolean;
|
|
1817
|
-
loading: boolean;
|
|
1818
|
-
error: Error | null;
|
|
1819
|
-
/** Force a re-fetch of the latest capture. */
|
|
1820
|
-
refresh: () => Promise<void>;
|
|
1288
|
+
* The expanded screenshot inside a tool body: a contained, clickable preview
|
|
1289
|
+
* (opens the lightbox) with a quiet caption. Constrained height + object-contain
|
|
1290
|
+
* so it never breaks the row layout. Like {@link Thumbnail}, it degrades to a
|
|
1291
|
+
* plain image outside a `LightboxProvider`.
|
|
1292
|
+
*/
|
|
1293
|
+
declare function ScreenshotFigure({ src, caption, alt, }: {
|
|
1294
|
+
src: string;
|
|
1295
|
+
caption?: string | undefined;
|
|
1296
|
+
alt?: string;
|
|
1297
|
+
}): react_jsx_runtime.JSX.Element;
|
|
1298
|
+
|
|
1299
|
+
type LightboxController = {
|
|
1300
|
+
open: (src: string, caption?: string) => void;
|
|
1821
1301
|
};
|
|
1302
|
+
/** Open the app-level screenshot lightbox. No-op outside a `LightboxProvider`. */
|
|
1303
|
+
declare function useLightbox(): LightboxController;
|
|
1822
1304
|
/**
|
|
1823
|
-
* The
|
|
1824
|
-
*
|
|
1825
|
-
*
|
|
1826
|
-
* case; a rare >2MB manifest comes back as a short-TTL signed URL we follow.
|
|
1827
|
-
*
|
|
1828
|
-
* Subscribes to the live event log: a `workspace.revision.captured` for a revision
|
|
1829
|
-
* newer than the one loaded triggers a background refresh (stale-while-revalidate).
|
|
1830
|
-
* `{available:false}` is a value, never a crash — consumers fall back to the
|
|
1831
|
-
* live/wake path exactly as before the capture feature existed.
|
|
1305
|
+
* The lightbox controller when one is mounted, or `null` outside a
|
|
1306
|
+
* `LightboxProvider`. Lets a media primitive degrade to a non-interactive image
|
|
1307
|
+
* (rather than a dead "Expand" button that announces an action it cannot do).
|
|
1832
1308
|
*/
|
|
1833
|
-
declare function
|
|
1834
|
-
|
|
1309
|
+
declare function useLightboxOptional(): LightboxController | null;
|
|
1835
1310
|
/**
|
|
1836
|
-
* The
|
|
1837
|
-
*
|
|
1311
|
+
* The app-level screenshot lightbox. Render once near the timeline; renderers
|
|
1312
|
+
* call `useLightbox().open(src)`.
|
|
1838
1313
|
*
|
|
1839
|
-
*
|
|
1840
|
-
*
|
|
1841
|
-
*
|
|
1842
|
-
*
|
|
1843
|
-
*
|
|
1844
|
-
* flushing — the box is warm; the guarded write is in flight.
|
|
1845
|
-
* flushed — the buffer was written to the live box.
|
|
1846
|
-
* conflict — the live file diverged from the captured base between
|
|
1847
|
-
* capture and flush; NO write was issued (C2).
|
|
1848
|
-
* readonly-offline — a self-hosted machine that is offline; read-only, no wake.
|
|
1314
|
+
* Idempotent by design: when an ancestor `LightboxProvider` already exists (e.g.
|
|
1315
|
+
* a `MessageTimeline` mounted inside an app that already wraps its shell), this
|
|
1316
|
+
* one becomes a pass-through and does NOT mount a second focus-trapping Dialog.
|
|
1317
|
+
* That keeps `MessageTimeline` self-sufficient (it owns its own provider) while
|
|
1318
|
+
* composing cleanly when nested.
|
|
1849
1319
|
*/
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
base: string;
|
|
1855
|
-
/** The live content found on the box at flush time (what would be overwritten). */
|
|
1856
|
-
live: string;
|
|
1857
|
-
};
|
|
1858
|
-
type UseWorkspaceEditOptions = ClientOverride & {
|
|
1859
|
-
/** The file being edited (workspace-relative). null disables the machine. */
|
|
1860
|
-
path?: string | null | undefined;
|
|
1861
|
-
/** The capture-served content loaded into the editor — the flush base (C2). */
|
|
1862
|
-
baseContent?: string | null | undefined;
|
|
1863
|
-
/** `capabilities.liveness` — "warm" | "draining" | "cold". Drives the flush. */
|
|
1864
|
-
liveness?: string | undefined;
|
|
1865
|
-
/** True while the host is actively warming the box (attach in flight, not warm
|
|
1866
|
-
* yet) — lifts `buffering` → `warming`. The host sets this after acting on
|
|
1867
|
-
* `wantsWarm` (e.g. flipping `attachFiles` on `useSessionCapabilities`). */
|
|
1868
|
-
warming?: boolean | undefined;
|
|
1869
|
-
/** A self-hosted machine that is OFFLINE: read-only, no remote wake possible. */
|
|
1870
|
-
offline?: boolean | undefined;
|
|
1871
|
-
/** Called once when the first cold edit needs the box warmed — the host wires
|
|
1872
|
-
* this to its liveness primitive (flip `attachFiles`/`attachViewer`). */
|
|
1873
|
-
onWarmRequested?: (() => void) | undefined;
|
|
1874
|
-
};
|
|
1875
|
-
type UseWorkspaceEditResult = {
|
|
1876
|
-
state: WorkspaceEditState;
|
|
1877
|
-
/** The editor should be read-only (self-hosted offline). */
|
|
1878
|
-
readOnly: boolean;
|
|
1879
|
-
/** The current buffered content (null = no local edit yet). */
|
|
1880
|
-
buffer: string | null;
|
|
1881
|
-
/** The host should warm the box (flip its attach primitive). Latches true from
|
|
1882
|
-
* the first cold edit until the buffer flushes or is discarded. */
|
|
1883
|
-
wantsWarm: boolean;
|
|
1884
|
-
/** Record an edit from the editor (idempotent per identical content). */
|
|
1885
|
-
edit: (content: string) => void;
|
|
1886
|
-
/** The conflict detail when `state === "conflict"`. */
|
|
1887
|
-
conflict: WorkspaceEditConflict | null;
|
|
1888
|
-
/** Flush the buffer regardless of the base guard (the user chose "overwrite"
|
|
1889
|
-
* from the conflict bar). Writes last-writer-wins. */
|
|
1890
|
-
overwrite: () => Promise<void>;
|
|
1891
|
-
/** Drop the local buffer and return to viewing the snapshot. */
|
|
1892
|
-
discard: () => void;
|
|
1893
|
-
error: Error | null;
|
|
1894
|
-
};
|
|
1320
|
+
declare function LightboxProvider({ children }: {
|
|
1321
|
+
children: ReactNode;
|
|
1322
|
+
}): react_jsx_runtime.JSX.Element;
|
|
1323
|
+
|
|
1895
1324
|
/**
|
|
1896
|
-
*
|
|
1897
|
-
*
|
|
1898
|
-
* warm the buffer flushes IF the live file still matches the captured base — else a
|
|
1899
|
-
* non-blocking conflict is surfaced and nothing is overwritten (dossier §12-C2).
|
|
1900
|
-
*
|
|
1901
|
-
* The base guard compares the live content at flush time against `baseContent`
|
|
1902
|
-
* (the exact bytes the editor loaded). This is equivalent to the sha256 compare
|
|
1903
|
-
* the dossier describes — M1 leaves `baseHash` null, so the loaded content IS the
|
|
1904
|
-
* authoritative base — and avoids async Web Crypto in the render path.
|
|
1325
|
+
* Seed the initial open state of every timeline collapsible below this node.
|
|
1326
|
+
* Intended for screenshot/test instrumentation only; absent by default.
|
|
1905
1327
|
*/
|
|
1906
|
-
declare function
|
|
1328
|
+
declare function DisclosureDefaultsProvider({ defaultOpen, children, }: {
|
|
1329
|
+
defaultOpen: boolean;
|
|
1330
|
+
children: ReactNode;
|
|
1331
|
+
}): react_jsx_runtime.JSX.Element;
|
|
1907
1332
|
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1333
|
+
type TurnSummaryProps = {
|
|
1334
|
+
/** The activity items in the turn (used only to compute the facet counts). */
|
|
1335
|
+
items: ActivityItem[];
|
|
1336
|
+
/**
|
|
1337
|
+
* The settled verdict — or absent for a completed CLUSTER of a still-running
|
|
1338
|
+
* turn, which folds neutrally: no verdict glyph (the turn has none yet), a
|
|
1339
|
+
* quiet pulse dot in its place so alignment and the running feel both hold.
|
|
1340
|
+
*/
|
|
1341
|
+
outcome?: TurnOutcome | undefined;
|
|
1342
|
+
/** A short failure reason shown inline on a failed chip (never hidden). */
|
|
1343
|
+
failureText?: string | undefined;
|
|
1344
|
+
/** Elapsed turn duration; shown as a trailing facet when at least 1s. */
|
|
1345
|
+
durationMs?: number | undefined;
|
|
1346
|
+
/** Start expanded. */
|
|
1347
|
+
defaultOpen?: boolean | undefined;
|
|
1348
|
+
/**
|
|
1349
|
+
* A nested fold — a cluster or sub-turn INSIDE an already-expanded turn. It
|
|
1350
|
+
* drops the bordered/filled chip and renders as a plain disclosure node on the
|
|
1351
|
+
* parent's rail (chevron + glyph + facets), so expanding a turn reveals a thread
|
|
1352
|
+
* of nodes, never a stack of boxes-in-boxes. The top-level fold stays a chip.
|
|
1353
|
+
*/
|
|
1354
|
+
bare?: boolean | undefined;
|
|
1355
|
+
/** The rendered activity rail revealed on expand. */
|
|
1356
|
+
children: React.ReactNode;
|
|
1918
1357
|
};
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1358
|
+
declare function TurnSummary({ items, outcome, failureText, durationMs, defaultOpen, bare, children, }: TurnSummaryProps): react_jsx_runtime.JSX.Element;
|
|
1359
|
+
|
|
1360
|
+
/** Recover the exit code from a sandbox exec banner (`Process exited with code N`). */
|
|
1361
|
+
declare function sandboxCommandExitCode(out: unknown): number | null;
|
|
1362
|
+
/**
|
|
1363
|
+
* Recover the numeric exec-session id the sandbox embeds for a STILL-RUNNING
|
|
1364
|
+
* (backgrounded) process (`Process running with session ID N`). A finished
|
|
1365
|
+
* command emits `Process exited with code N` instead, which yields `null`.
|
|
1366
|
+
*/
|
|
1367
|
+
declare function parseExecBannerSessionId(out: unknown): number | null;
|
|
1368
|
+
/** Strip the exec banner (`Chunk ID ...\n...\nOutput:\n`) down to the command's stdout. */
|
|
1369
|
+
declare function stripExecBanner(out: unknown): string;
|
|
1370
|
+
/** The sandbox clamped the output (token/line truncation markers in the banner). */
|
|
1371
|
+
declare function execTruncated(out: unknown): boolean;
|
|
1372
|
+
/** A `write_stdin` whose target PTY vanished (`write_stdin failed: session not found: N`). */
|
|
1373
|
+
declare function isExecSessionLostBanner(out: unknown): boolean;
|
|
1374
|
+
/** True when the exec stdout looks binary/garbled (a NUL byte or ELF magic). */
|
|
1375
|
+
declare function looksBinary(text: string): boolean;
|
|
1376
|
+
/**
|
|
1377
|
+
* Render unprintable control characters as caret notation (0x03 -> `^C`) so a
|
|
1378
|
+
* `write_stdin` keystroke payload reads cleanly in the row title.
|
|
1379
|
+
*/
|
|
1380
|
+
declare function controlCaret(printable: string): string;
|
|
1381
|
+
/** One operation inside an `apply_patch_call` (a V4A file edit). */
|
|
1382
|
+
type ApplyPatchOperation = {
|
|
1383
|
+
/**
|
|
1384
|
+
* The V4A op kind. The three canonical values are `create_file`,
|
|
1385
|
+
* `update_file`, and `delete_file`; the open `string` tail tolerates a
|
|
1386
|
+
* forward-compatible/unknown op kind from the provider without a type error
|
|
1387
|
+
* (it falls through to the "Edited" treatment).
|
|
1388
|
+
*/
|
|
1389
|
+
type: "create_file" | "update_file" | "delete_file" | (string & {});
|
|
1390
|
+
path: string;
|
|
1391
|
+
/** Rename target -- when present the op is a move/rename. */
|
|
1392
|
+
moveTo?: string | null | undefined;
|
|
1393
|
+
/** The V4A hunk string (`@@ ...` lines with `+`/`-`/context prefixes). */
|
|
1394
|
+
diff?: string | undefined;
|
|
1935
1395
|
};
|
|
1936
|
-
/** Compact relative-time for the "as of" label. Pure, no Intl dependency. */
|
|
1937
|
-
declare function formatAsOf(capturedAt: string, now: number): string;
|
|
1938
1396
|
/**
|
|
1939
|
-
*
|
|
1940
|
-
*
|
|
1941
|
-
* it
|
|
1942
|
-
*
|
|
1943
|
-
* Precedence:
|
|
1944
|
-
* 1. warm/draining lease → **live** (a warm box always wins).
|
|
1945
|
-
* 2. actively warming (negotiating, wake-on-edit, or a reconnecting/enrolling
|
|
1946
|
-
* machine) → **waking**.
|
|
1947
|
-
* 3. everything else (a cold/asleep box, a self-hosted machine that's offline,
|
|
1948
|
-
* an error) → **offline**, labelled "as of <capture time>".
|
|
1397
|
+
* Parse a single V4A `apply_patch` operation into the SDK's `GitFileDiff` shape
|
|
1398
|
+
* so it can flow into the SAME `DiffView` / `PierreDiff` the Files tab uses.
|
|
1399
|
+
* Throws on a hunk string it cannot structure (no `@@` anchor on an update); the
|
|
1400
|
+
* renderer catches and falls back to a raw-patch view.
|
|
1949
1401
|
*/
|
|
1950
|
-
declare function
|
|
1951
|
-
type UseMachineChipOptions = DeriveMachineChipInput;
|
|
1402
|
+
declare function v4aToGitFileDiff(op: ApplyPatchOperation): GitFileDiff;
|
|
1952
1403
|
/**
|
|
1953
|
-
*
|
|
1954
|
-
*
|
|
1955
|
-
*
|
|
1956
|
-
*
|
|
1957
|
-
* "as of" label to tick.
|
|
1404
|
+
* Extract the `apply_patch` operations from a provider-native tool item's `raw`
|
|
1405
|
+
* payload, normalizing the two wire shapes (`raw.operations[]` for a multi-file
|
|
1406
|
+
* patch, `raw.operation` for a single op). The single owner of this shape so the
|
|
1407
|
+
* renderer and the turn-summary facet counter never drift.
|
|
1958
1408
|
*/
|
|
1959
|
-
declare function
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1409
|
+
declare function applyPatchOps(raw: unknown): ApplyPatchOperation[];
|
|
1410
|
+
/**
|
|
1411
|
+
* True when a tool item is an `apply_patch_call` — by its provider-native
|
|
1412
|
+
* `raw.type` (the live-wire source of truth) or by tool `name` (first-party
|
|
1413
|
+
* replays that omit `raw`). Centralizes the rawType-or-name check.
|
|
1414
|
+
*/
|
|
1415
|
+
declare function isApplyPatch(item: {
|
|
1965
1416
|
name: string;
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
/**
|
|
1971
|
-
declare function
|
|
1972
|
-
/** The
|
|
1973
|
-
declare function
|
|
1417
|
+
raw: unknown;
|
|
1418
|
+
}): boolean;
|
|
1419
|
+
/** Deep-redact secret-looking values so arguments never leak a key into the UI. */
|
|
1420
|
+
declare function redactSecrets(value: unknown): unknown;
|
|
1421
|
+
/** Parse tool arguments that may arrive as a JSON string or an object. */
|
|
1422
|
+
declare function parseToolArgs(args: unknown): Record<string, unknown>;
|
|
1423
|
+
/** The last non-empty line of a string -- the compact "what happened" peek. */
|
|
1424
|
+
declare function tailPeek(text: string): string;
|
|
1425
|
+
/**
|
|
1426
|
+
* Unwrap an MCP tool result (`{ content: [{ type: "text", text }], isError? }`)
|
|
1427
|
+
* into a flat `{ text, isError }`. Non-MCP outputs pass through as their string
|
|
1428
|
+
* form.
|
|
1429
|
+
*/
|
|
1430
|
+
declare function unwrapMcpOutput(output: unknown): {
|
|
1431
|
+
text: string;
|
|
1432
|
+
isError: boolean;
|
|
1433
|
+
};
|
|
1974
1434
|
|
|
1975
1435
|
/**
|
|
1976
1436
|
* Parse a composer value into a command name + the rest. A command is
|
|
@@ -2023,6 +1483,10 @@ type CommandPaletteProps = {
|
|
|
2023
1483
|
argHintText: string;
|
|
2024
1484
|
/** id used for aria-activedescendant wiring from the textarea. */
|
|
2025
1485
|
listboxId: string;
|
|
1486
|
+
/** Accessible list label. Defaults to "Slash commands". */
|
|
1487
|
+
label?: string | undefined;
|
|
1488
|
+
/** Badge shown for destructive commands. Defaults to "danger". */
|
|
1489
|
+
dangerLabel?: string | undefined;
|
|
2026
1490
|
};
|
|
2027
1491
|
/**
|
|
2028
1492
|
* The slash-command palette: a popover anchored above the textarea, rendered
|
|
@@ -2030,7 +1494,7 @@ type CommandPaletteProps = {
|
|
|
2030
1494
|
* the opengeni#46 design tokens. Full keyboard nav lives in useSlashCommands;
|
|
2031
1495
|
* this component is presentational + aria.
|
|
2032
1496
|
*/
|
|
2033
|
-
declare function CommandPalette({ open, items, highlight, onHighlight, onRun, argHintText, listboxId, }: CommandPaletteProps): react_jsx_runtime.JSX.Element;
|
|
1497
|
+
declare function CommandPalette({ open, items, highlight, onHighlight, onRun, argHintText, listboxId, label, dangerLabel, }: CommandPaletteProps): react_jsx_runtime.JSX.Element;
|
|
2034
1498
|
|
|
2035
1499
|
type ModelPickerProps = {
|
|
2036
1500
|
/** The host-exposed models to choose from (typically {@link useAvailableModels}). */
|
|
@@ -2041,6 +1505,8 @@ type ModelPickerProps = {
|
|
|
2041
1505
|
onChange: (modelId: string) => void;
|
|
2042
1506
|
disabled?: boolean | undefined;
|
|
2043
1507
|
className?: string | undefined;
|
|
1508
|
+
/** Visible-to-assistive-technology label. Defaults to "Model". */
|
|
1509
|
+
label?: string | undefined;
|
|
2044
1510
|
};
|
|
2045
1511
|
/**
|
|
2046
1512
|
* The model picker — a compact dropdown for the composer footer, grouping the
|
|
@@ -2053,7 +1519,7 @@ type ModelPickerProps = {
|
|
|
2053
1519
|
* the send path. Renders nothing when no models are exposed, so a single-model
|
|
2054
1520
|
* deployment shows no chrome.
|
|
2055
1521
|
*/
|
|
2056
|
-
declare function ModelPicker({ models, value, onChange, disabled, className }: ModelPickerProps): react_jsx_runtime.JSX.Element | null;
|
|
1522
|
+
declare function ModelPicker({ models, value, onChange, disabled, className, label, }: ModelPickerProps): react_jsx_runtime.JSX.Element | null;
|
|
2057
1523
|
|
|
2058
1524
|
type MessageTimelineProps = {
|
|
2059
1525
|
/** Raw session events (projected internally) … */
|
|
@@ -2337,7 +1803,8 @@ type FileBrowserProps = {
|
|
|
2337
1803
|
editable?: boolean | undefined;
|
|
2338
1804
|
/**
|
|
2339
1805
|
* Confirm a (recursive) delete before it runs. Return `false` to cancel.
|
|
2340
|
-
*
|
|
1806
|
+
* The default is an accessible, non-blocking confirmation dialog. Supply this
|
|
1807
|
+
* callback to delegate confirmation to a host-owned dialog.
|
|
2341
1808
|
*/
|
|
2342
1809
|
confirmDelete?: ((node: FileTreeNode) => boolean | Promise<boolean>) | undefined;
|
|
2343
1810
|
className?: string | undefined;
|
|
@@ -2467,6 +1934,10 @@ type CodeEditorProps = {
|
|
|
2467
1934
|
initialContents: string;
|
|
2468
1935
|
/** Persist the current buffer. Resolves when the write lands; rejects to surface an error. */
|
|
2469
1936
|
onSave: (contents: string) => Promise<unknown>;
|
|
1937
|
+
/** Explicitly overwrite after a visible expected-content conflict. */
|
|
1938
|
+
onOverwrite?: ((contents: string) => Promise<unknown>) | undefined;
|
|
1939
|
+
/** Re-read the selected file after a visible save conflict. */
|
|
1940
|
+
onReload?: (() => void) | undefined;
|
|
2470
1941
|
/** Fired once when the buffer FIRST diverges from its baseline (the first real
|
|
2471
1942
|
* keystroke) — the wake-on-edit intent. The host warms the box on this so the
|
|
2472
1943
|
* eventual save lands fast; merely opening the file for reading never fires it. */
|
|
@@ -2492,7 +1963,7 @@ type CodeEditorProps = {
|
|
|
2492
1963
|
* `readOnly` suppresses every mutation path so a truncated/binary file can never
|
|
2493
1964
|
* be saved back (which would corrupt it by writing the truncated prefix).
|
|
2494
1965
|
*/
|
|
2495
|
-
declare function CodeEditor({ path, initialContents, onSave, onEditIntent, readOnly, themeType, loading, fallback, className, }: CodeEditorProps): react_jsx_runtime.JSX.Element;
|
|
1966
|
+
declare function CodeEditor({ path, initialContents, onSave, onOverwrite, onReload, onEditIntent, readOnly, themeType, loading, fallback, className, }: CodeEditorProps): react_jsx_runtime.JSX.Element;
|
|
2496
1967
|
|
|
2497
1968
|
type SandboxFilesProps = {
|
|
2498
1969
|
/** From `useSandboxFiles(...)`. */
|
|
@@ -2521,6 +1992,15 @@ type SandboxFilesProps = {
|
|
|
2521
1992
|
requestedPathRequestId?: string | number | undefined;
|
|
2522
1993
|
/** False while the parent is waking a cold sandbox for `requestedPath`. */
|
|
2523
1994
|
requestedPathReady?: boolean | undefined;
|
|
1995
|
+
/** The machine is cold and no durable capture exists yet. Render an explicit
|
|
1996
|
+
* wake gate instead of an empty-tree lie or an implicit Channel-A read. */
|
|
1997
|
+
workspaceResting?: boolean | undefined;
|
|
1998
|
+
/** A deliberate wake has started but the live file surface is not ready yet. */
|
|
1999
|
+
workspaceWaking?: boolean | undefined;
|
|
2000
|
+
/** Whether live reads are currently authoritative. */
|
|
2001
|
+
liveWorkspaceReady?: boolean | undefined;
|
|
2002
|
+
/** Deliberately wake the machine to read content absent from the capture. */
|
|
2003
|
+
onWakeWorkspace?: (() => void) | undefined;
|
|
2524
2004
|
themeType?: "dark" | "light" | undefined;
|
|
2525
2005
|
className?: string | undefined;
|
|
2526
2006
|
};
|
|
@@ -2531,7 +2011,7 @@ type SandboxFilesProps = {
|
|
|
2531
2011
|
* surface deliberately does NOT replicate the changed-files list, and does not
|
|
2532
2012
|
* diff here — one job per tab). The agent commits; the human reviews.
|
|
2533
2013
|
*/
|
|
2534
|
-
declare function SandboxFiles({ files, git, fileSystemAvailable, usePierre, editable, onEditIntent, requestedPath, requestedPathRequestId, requestedPathReady, themeType, className, }: SandboxFilesProps): react_jsx_runtime.JSX.Element;
|
|
2014
|
+
declare function SandboxFiles({ files, git, fileSystemAvailable, usePierre, editable, onEditIntent, requestedPath, requestedPathRequestId, requestedPathReady, workspaceResting, workspaceWaking, liveWorkspaceReady, onWakeWorkspace, themeType, className, }: SandboxFilesProps): react_jsx_runtime.JSX.Element;
|
|
2535
2015
|
|
|
2536
2016
|
type DesktopViewerProps = {
|
|
2537
2017
|
/** The desktop cell of the negotiated capabilities (`capabilities.DesktopStream`). */
|
|
@@ -2659,6 +2139,15 @@ type WorkspaceNotification = {
|
|
|
2659
2139
|
/** The workbench's canonical tab ids (a host injects extras around these). */
|
|
2660
2140
|
declare const WORKBENCH_TAB_CHANGES = "changes";
|
|
2661
2141
|
declare const WORKBENCH_TAB_FILES = "files";
|
|
2142
|
+
declare const WORKBENCH_TAB_TERMINAL = "terminal";
|
|
2143
|
+
declare const WORKBENCH_TAB_DESKTOP = "desktop";
|
|
2144
|
+
/**
|
|
2145
|
+
* The built-in workbench surfaces in their canonical display order. Hosts can
|
|
2146
|
+
* pass a subset through `surfaces`; omission preserves the complete standalone
|
|
2147
|
+
* workbench.
|
|
2148
|
+
*/
|
|
2149
|
+
declare const WORKBENCH_SURFACES: readonly ["changes", "files", "terminal", "desktop"];
|
|
2150
|
+
type SandboxWorkspaceSurface = (typeof WORKBENCH_SURFACES)[number];
|
|
2662
2151
|
/**
|
|
2663
2152
|
* Decide a workspace tab from an already-local event log: the newest
|
|
2664
2153
|
* `workspace.revision.captured` announce carries the change surface stats, so
|
|
@@ -2671,7 +2160,9 @@ declare const WORKBENCH_TAB_FILES = "files";
|
|
|
2671
2160
|
*/
|
|
2672
2161
|
declare function initialWorkspaceTab(events: SessionEvent[] | undefined, override?: string | null): string;
|
|
2673
2162
|
type WorkspaceMachine = {
|
|
2674
|
-
/**
|
|
2163
|
+
/** Whether at least one built-in workbench surface is enabled. */
|
|
2164
|
+
enabled: boolean;
|
|
2165
|
+
/** The derived live/waking/offline chip model. */
|
|
2675
2166
|
chip: MachineChip;
|
|
2676
2167
|
/** The machine these surfaces are bound to (the Modal group box or a
|
|
2677
2168
|
* self-hosted machine), or null while the fleet is still resolving. */
|
|
@@ -2684,6 +2175,12 @@ type UseSandboxWorkspaceTabsOptions = ClientOverride & {
|
|
|
2684
2175
|
sessionId: string;
|
|
2685
2176
|
/** Live event log (usually `useSessionEvents().events`). */
|
|
2686
2177
|
events: SessionEvent[];
|
|
2178
|
+
/**
|
|
2179
|
+
* Built-in surfaces this host wants to expose. Omit for all four. A disabled
|
|
2180
|
+
* surface is behaviorally dormant: its data hooks, warm intents, stream
|
|
2181
|
+
* attachment, and navigation callbacks are not activated.
|
|
2182
|
+
*/
|
|
2183
|
+
surfaces?: readonly SandboxWorkspaceSurface[] | undefined;
|
|
2687
2184
|
/** Override the source-driven default tab (e.g. a host landing tab id). When
|
|
2688
2185
|
* omitted the workbench picks Changes-vs-Files from capture or live Git. */
|
|
2689
2186
|
initialTab?: string | null | undefined;
|
|
@@ -2704,7 +2201,8 @@ type UseSandboxWorkspaceTabsResult = {
|
|
|
2704
2201
|
tabs: WorkspaceTab[];
|
|
2705
2202
|
/** The source-driven default tab: Changes when the first authoritative capture
|
|
2706
2203
|
* or live Git result has changes, else Files (a host `initialTab` overrides).
|
|
2707
|
-
* null while that source resolves
|
|
2204
|
+
* null while that source resolves, or permanently when neither Changes nor
|
|
2205
|
+
* Files is enabled; the choice latches once. */
|
|
2708
2206
|
defaultTab: string | null;
|
|
2709
2207
|
/** The machine-state model for the dock-header chip. */
|
|
2710
2208
|
machine: WorkspaceMachine;
|
|
@@ -2721,6 +2219,11 @@ type SandboxWorkspaceProps = ClientOverride & {
|
|
|
2721
2219
|
events: SessionEvent[];
|
|
2722
2220
|
/** The chat / primary pane shown beside the dock. */
|
|
2723
2221
|
primary: ReactNode;
|
|
2222
|
+
/**
|
|
2223
|
+
* Built-in surfaces this host wants to expose. Omit for Changes, Files,
|
|
2224
|
+
* Terminal, and Desktop. Disabled surfaces remain behaviorally dormant.
|
|
2225
|
+
*/
|
|
2226
|
+
surfaces?: readonly SandboxWorkspaceSurface[] | undefined;
|
|
2724
2227
|
/** Host tabs injected BEFORE the workbench tabs (e.g. a "Run" landing tab). */
|
|
2725
2228
|
leadingTabs?: WorkspaceTab[] | undefined;
|
|
2726
2229
|
/** Host tabs injected AFTER the workbench tabs (e.g. a "Debug" tab). */
|
|
@@ -2882,4 +2385,4 @@ declare function isCreditExhaustion(input: {
|
|
|
2882
2385
|
*/
|
|
2883
2386
|
declare function humanizeFailureReason(reason: string | null): string | null;
|
|
2884
2387
|
|
|
2885
|
-
export { ActivityDisclosure, type ActivityDisclosureProps,
|
|
2388
|
+
export { ActivityDisclosure, type ActivityDisclosureProps, ActivityItem, ActivityRail, type ActivityRailProps, AgentMessageItem, type ApplyPatchOperation, ApprovalSurface, type ApprovalSurfaceMessages, type ApprovalSurfaceProps, AuthNeededItem, BodyNote, CREDIT_EXHAUSTION_MESSAGE, CapturedFileUnavailableError, type CapturedFileUnavailableReason, ChatComposer, ChatComposerMessages, type ChatComposerProps, ClientOverride, CodeEditor, type CodeEditorProps, type CodexAccountsClientLike, CommandContext, CommandPalette, type CommandPaletteProps, ComposerState, ComposerTranscriptionControlProps, type CreateToolRegistryOptions, type DeriveMachineChipInput, DesktopViewer, type DesktopViewerProps, type DesktopWebSocketFactory, type DesktopWebSocketLike, type DiffTheme, DiffView, type DiffViewProps, type DisclosureChip, DisclosureDefaultsProvider, FileBrowser, type FileBrowserProps, type FileTreeNode, type FileTreeStatus, FileWriteConflictError, FleetTile, type FleetTileProps, type HumanInputAnswerDraft, HumanInputForm, type HumanInputFormMessages, type HumanInputFormProps, LightboxProvider, type MachineChip, type MachineChipState, Markdown, type MarkdownProps, MediaEmpty, MediaSkeleton, MessageTimeline, type MessageTimelineProps, ModelPicker, type ModelPickerProps, OpenGeniProvider, type OpenGeniProviderProps, type ParsedCommandLine, PayloadBlock, PendingApproval, PierreDiff, type PierreDiffProps, PierreFile, type PierreFileProps, QueueSurface, type QueueSurfaceProps, SESSION_STATUS_META, SandboxFiles, type SandboxFilesProps, type SandboxGitFileDiff, SandboxTerminal, type SandboxTerminalProps, SandboxWorkspace, type SandboxWorkspaceProps, type SandboxWorkspaceSurface, type SandboxWriteFileOptions, ScreenshotFigure, type SessionCapabilitiesState, SessionClientLike, SessionStatus, type SessionStatusMeta, type SessionStatusProps, SlashArg, SlashCommand, SlashCommandContext, StatusDot, type StatusDotProps, TermBlock, type TerminalChunk, type TerminalStreamStatus, Thumbnail, TimelineItem, TimelineRow, ToolCallItem, type ToolRegistry, type ToolRegistryEntry, type ToolRenderer, type ToolRendererProps, TurnOutcome, TurnSummary, type TurnSummaryProps, type UseAvailableModelsOptions, type UseAvailableModelsResult, type UseBillingUsageOptions, type UseBillingUsageResult, type UseCodexAccountsOptions, type UseCodexAccountsResult, type UseDesktopStreamOptions, type UseDesktopStreamResult, type UseEnvironmentsOptions, type UseEnvironmentsResult, UseFileAttachmentsResult, type UseGoalOptions, type UseGoalResult, type UseMachineChipOptions, type UsePacksOptions, type UsePacksResult, type UseRelayFrameStreamOptions, type UseRelayFrameStreamResult, type UseRigChangesOptions, type UseRigChangesResult, type UseRigOptions, type UseRigResult, type UseRigVersionsOptions, type UseRigVersionsResult, type UseRigsOptions, type UseRigsResult, type UseSandboxFilesOptions, type UseSandboxFilesResult, type UseSandboxGitOptions, type UseSandboxGitResult, type UseSandboxTerminalOptions, type UseSandboxTerminalResult, type UseSandboxWorkspaceTabsOptions, type UseSandboxWorkspaceTabsResult, type UseScheduledTasksOptions, type UseScheduledTasksResult, type UseSessionCapabilitiesOptions, type UseSessionCapabilitiesResult, type UseSessionLineageOptions, type UseSessionLineageResult, type UseSessionOptions, type UseSessionResult, type UseTerminalStreamOptions, type UseTerminalStreamResult, UseTurnQueueResult, type UseVariableSetsOptions, type UseVariableSetsResult, type UseWorkspaceCaptureOptions, type UseWorkspaceCaptureResult, type UseWorkspaceEditOptions, type UseWorkspaceEditResult, type UseWorkspaceSessionsOptions, type UseWorkspaceSessionsResult, type UseWorkspacesOptions, type UseWorkspacesResult, UserMessageItem, WORKBENCH_SURFACES, WORKBENCH_TAB_CHANGES, WORKBENCH_TAB_DESKTOP, WORKBENCH_TAB_FILES, WORKBENCH_TAB_TERMINAL, WorkspaceDock, type WorkspaceDockProps, type WorkspaceEditConflict, type WorkspaceEditState, type WorkspaceMachine, type WorkspaceNotification, type WorkspaceTab, type XtermTheme, answersFromDrafts, applyPatchOps, argHint, cn, controlCaret, createDefaultToolRegistry, createToolRegistry, defaultApprovalSurfaceMessages, defaultCommands, defaultHumanInputFormMessages, defaultToolRegistry, deriveMachineChip, execTruncated, filterCommands, firstMissingRequiredArg, formatAsOf, formatBytes, formatRelativeTime, gitFileDiffToPatch, hasPermission, humanizeFailureReason, initialWorkspaceTab, isApplyPatch, isCodexAccountEvent, isCreditExhaustion, isExecSessionLostBanner, isGoalEvent, isLineageRefreshEvent, isTitleEvent, languageForPath, looksBinary, matchCommand, parseCommandLine, parseExecBannerSessionId, parseToolArgs, rawTypeOf, redactSecrets, sandboxCommandExitCode, sessionDisplayTitle, stringifyPayload, stripExecBanner, tailPeek, truncate, tryParseJson, unwrapMcpOutput, useAvailableModels, useBillingUsage, useCodexAccounts, useDesktopStream, useEnvironments, useGoal, useLightbox, useLightboxOptional, useMachineChip, usePacks, useRelayFrameStream, useRig, useRigChanges, useRigVersions, useRigs, useSandboxFiles, useSandboxGit, useSandboxTerminal, useSandboxWorkspaceTabs, useScheduledTasks, useSession, useSessionCapabilities, useSessionLineage, useTerminalStream, useVariableSets, useWorkspaceCapture, useWorkspaceEdit, useWorkspaceSessions, useWorkspaces, v4aToGitFileDiff, xtermThemeFromTokens };
|