1import { OrchestrationMessageContext } from "./composerContext.ts";
2import * as Effect from "effect/Effect";
3import * as Schema from "effect/Schema";
4import * as SchemaAST from "effect/SchemaAST";
5import * as SchemaGetter from "effect/SchemaGetter";
6import * as SchemaTransformation from "effect/SchemaTransformation";
7
8import {
9 CheckpointId,
10 CheckpointRef,
11 CheckpointScopeId,
12 CommandId,
13 ContextHandoffId,
14 ContextTransferId,
15 EventId,
16 IsoDateTime,
17 MessageId,
18 NodeId,
19 ForwardCompatibleUnion,
20 ForwardCompatibleUnionArray,
21 hasUnknownUnionTag,
22 isUnknownUnionMember,
23 NonNegativeInt,
24 PlanId,
25 PositiveInt,
26 ProjectId,
27 ProviderSessionId,
28 ProviderThreadId,
29 ProviderTurnId,
30 RawEventId,
31 RunAttemptId,
32 RunId,
33 RuntimeRequestId,
34 ScheduledTaskId,
35 ThreadId,
36 TrimmedNonEmptyString,
37 TurnItemId,
38} from "./baseSchemas.ts";
39import { ChatAttachment } from "./chatAttachment.ts";
40import {
41 OrchestrationGetFullThreadDiffInput,
42 OrchestrationGetFullThreadDiffResult,
43 OrchestrationGetTurnDiffInput,
44 OrchestrationGetTurnDiffResult,
45} from "./checkpointDiff.ts";
46import { ModelSelection } from "./modelSelection.ts";
47import {
48 ThreadLinkedPullRequest,
49 ThreadPullRequestLink,
50 ThreadPullRequestKey,
51 ThreadPullRequestLinkSource,
52 ThreadPullRequestSnapshot,
53 ThreadPullRequestStack,
54 ThreadPullRequestWatch,
55} from "./threadPullRequest.ts";
56import {
57 ProviderApprovalDecision,
58 ProviderApprovalOption,
59 ProviderInteractionMode,
60 ProviderRequestKind,
61 ProviderUserInputAnswers,
62 UserInputAttachments,
63 UserInputAttachmentAnswerPayload,
64 RuntimeMode,
65} from "./providerPolicy.ts";
66import { ProviderDriverKind, ProviderInstanceId } from "./providerInstance.ts";
67import { OrchestrationProjectShell } from "./orchestrationProject.ts";
68import {
69 TurnTokenUsage,
70 ToolActivitySurface,
71 ToolActivityIcon,
72 ToolActivitySource,
73} from "./providerRuntime.ts";
74import { ThreadTokenUsageSnapshot } from "./providerRuntime.ts";
75
76export const OrchestrationV2Actor = Schema.Literals(["user", "agent", "system"]);
77export type OrchestrationV2Actor = typeof OrchestrationV2Actor.Type;
78
79export const OrchestrationV2CreationSource = Schema.Literals([
80 "web",
81 "mobile",
82 "mcp",
83 "provider",
84 "server",
85]);
86export type OrchestrationV2CreationSource = typeof OrchestrationV2CreationSource.Type;
87
88export const OrchestrationV2ThreadHistoryOrigin = Schema.Literals(["native", "v1_import"]);
89export type OrchestrationV2ThreadHistoryOrigin = typeof OrchestrationV2ThreadHistoryOrigin.Type;
90
91const OrchestrationV2CreationFields = {
92 createdBy: OrchestrationV2Actor,
93 creationSource: OrchestrationV2CreationSource,
94} as const;
95
96export const OrchestrationV2NativeRefStrength = Schema.Literals(["strong", "weak", "none"]);
97export type OrchestrationV2NativeRefStrength = typeof OrchestrationV2NativeRefStrength.Type;
98
99export const OrchestrationV2ProviderRef = Schema.Struct({
100 driver: ProviderDriverKind,
101 nativeId: Schema.NullOr(TrimmedNonEmptyString),
102 strength: OrchestrationV2NativeRefStrength,
103 fingerprint: Schema.optional(TrimmedNonEmptyString),
104 ordinal: Schema.optional(NonNegativeInt),
105});
106export type OrchestrationV2ProviderRef = typeof OrchestrationV2ProviderRef.Type;
107
108export const OrchestrationV2AppThreadLineage = Schema.Struct({
109 parentThreadId: Schema.NullOr(ThreadId),
110 relationshipToParent: Schema.NullOr(Schema.Literals(["fork", "subagent"])),
111 rootThreadId: ThreadId,
112});
113export type OrchestrationV2AppThreadLineage = typeof OrchestrationV2AppThreadLineage.Type;
114
115export const OrchestrationV2ContextTransferType = Schema.Literals([
116 "fork",
117 "provider_handoff",
118 "merge_back",
119 "subagent_spawn",
120 "subagent_result",
121]);
122export type OrchestrationV2ContextTransferType = typeof OrchestrationV2ContextTransferType.Type;
123
124export const OrchestrationV2ContextSourcePoint = Schema.Struct({
125 threadId: ThreadId,
126 runId: Schema.optional(RunId),
127 checkpointId: Schema.optional(CheckpointId),
128 turnItemId: Schema.optional(TurnItemId),
129 providerThreadRef: Schema.optional(OrchestrationV2ProviderRef),
130 providerTurnRef: Schema.optional(OrchestrationV2ProviderRef),
131});
132export type OrchestrationV2ContextSourcePoint = typeof OrchestrationV2ContextSourcePoint.Type;
133
134export const OrchestrationV2ThreadForkSourcePoint = Schema.Union([
135 Schema.Struct({ type: Schema.Literal("latest_stable") }),
136 Schema.Struct({ type: Schema.Literal("run"), runId: RunId }),
137 Schema.Struct({ type: Schema.Literal("checkpoint"), checkpointId: CheckpointId }),
138]);
139export type OrchestrationV2ThreadForkSourcePoint = typeof OrchestrationV2ThreadForkSourcePoint.Type;
140
141export const OrchestrationV2ContextTransferResolution = Schema.Union([
142 Schema.Struct({
143 strategy: Schema.Literal("native_fork"),
144 providerThreadRef: OrchestrationV2ProviderRef,
145 }),
146 Schema.Struct({
147 strategy: Schema.Literal("portable_context"),
148 contextHandoffId: ContextHandoffId,
149 }),
150 Schema.Struct({
151 strategy: Schema.Literal("delta_context"),
152 contextHandoffId: ContextHandoffId,
153 }),
154 Schema.Struct({
155 strategy: Schema.Literal("fork_delta_context"),
156 contextHandoffId: ContextHandoffId,
157 }),
158 Schema.Struct({
159 strategy: Schema.Literal("checkpoint_context"),
160 contextHandoffId: ContextHandoffId,
161 }),
162]);
163export type OrchestrationV2ContextTransferResolution =
164 typeof OrchestrationV2ContextTransferResolution.Type;
165
166export const OrchestrationV2ContextTransfer = Schema.Struct({
167 id: ContextTransferId,
168 type: OrchestrationV2ContextTransferType,
169 sourceThreadId: ThreadId,
170 targetThreadId: ThreadId,
171 sourcePoint: OrchestrationV2ContextSourcePoint,
172 basePoint: Schema.NullOr(OrchestrationV2ContextSourcePoint),
173 sourceProviderInstanceId: Schema.NullOr(ProviderInstanceId),
174 targetProviderInstanceId: Schema.NullOr(ProviderInstanceId),
175 targetRunId: Schema.NullOr(RunId),
176 status: Schema.Literals([
177 "pending",
178 "resolved_native",
179 "resolved_portable",
180 "failed",
181 "consumed",
182 "superseded",
183 ]),
184 resolution: Schema.NullOr(OrchestrationV2ContextTransferResolution),
185 createdBy: OrchestrationV2Actor,
186 error: Schema.NullOr(Schema.String),
187 createdAt: Schema.DateTimeUtc,
188 updatedAt: Schema.DateTimeUtc,
189 consumedAt: Schema.NullOr(Schema.DateTimeUtc),
190});
191export type OrchestrationV2ContextTransfer = typeof OrchestrationV2ContextTransfer.Type;
192
193export const OrchestrationV2SessionCapabilities = Schema.Struct({
194 supportsMultipleProviderThreadsPerSession: Schema.Boolean,
195 supportsModelSwitchInSession: Schema.Boolean,
196 supportsProviderSwitchingViaHandoff: Schema.Boolean,
197 supportsRuntimeModeSwitchInSession: Schema.Boolean,
198 pendingRequestsSurviveRestart: Schema.Boolean,
199});
200export type OrchestrationV2SessionCapabilities = typeof OrchestrationV2SessionCapabilities.Type;
201
202export const OrchestrationV2ThreadCapabilities = Schema.Struct({
203 canCreateEmptyThread: Schema.Boolean,
204 canReadThreadSnapshot: Schema.Boolean,
205 canRollbackThread: Schema.Boolean,
206 canForkThread: Schema.Boolean,
207 canForkFromTurn: Schema.Boolean,
208 canForkFromSubagentThread: Schema.Boolean,
209 exposesNativeThreadId: Schema.Boolean,
210});
211export type OrchestrationV2ThreadCapabilities = typeof OrchestrationV2ThreadCapabilities.Type;
212
213export const OrchestrationV2TurnCapabilities = Schema.Struct({
214 exposesNativeTurnId: Schema.Boolean,
215 emitsTurnStarted: Schema.Boolean,
216 emitsTurnCompleted: Schema.Boolean,
217 supportsInterrupt: Schema.Boolean,
218 supportsActiveSteering: Schema.Boolean,
219 // Some native steering mechanisms cancel pending tools before consuming the message.
220 activeSteeringInterruptsTools: Schema.optional(Schema.Boolean),
221 supportsSteeringByInterruptRestart: Schema.Boolean,
222 supportsQueuedMessages: Schema.Boolean,
223 terminalStatusQuality: Schema.Literals(["strong", "weak", "none"]),
224});
225export type OrchestrationV2TurnCapabilities = typeof OrchestrationV2TurnCapabilities.Type;
226
227export const OrchestrationV2StreamingCapabilities = Schema.Struct({
228 streamsAssistantText: Schema.Boolean,
229 streamsReasoning: Schema.Boolean,
230 streamsToolOutput: Schema.Boolean,
231 streamsPlanText: Schema.Boolean,
232 emitsMessageCompleted: Schema.Boolean,
233});
234export type OrchestrationV2StreamingCapabilities = typeof OrchestrationV2StreamingCapabilities.Type;
235
236export const OrchestrationV2ToolCapabilities = Schema.Struct({
237 exposesToolItemIds: Schema.Boolean,
238 emitsToolStarted: Schema.Boolean,
239 emitsToolCompleted: Schema.Boolean,
240 emitsToolOutput: Schema.Boolean,
241 supportsMcpTools: Schema.Boolean,
242 supportsDynamicToolCallbacks: Schema.Boolean,
243});
244export type OrchestrationV2ToolCapabilities = typeof OrchestrationV2ToolCapabilities.Type;
245
246export const OrchestrationV2ApprovalCapabilities = Schema.Struct({
247 supportsCommandApproval: Schema.Boolean,
248 supportsFileReadApproval: Schema.Boolean,
249 supportsFileChangeApproval: Schema.Boolean,
250 supportsApplyPatchApproval: Schema.Boolean,
251 approvalsHaveNativeRequestIds: Schema.Boolean,
252 approvalCallbacksAreLiveOnly: Schema.Boolean,
253 approvalsCanOriginateFromSubagents: Schema.Boolean,
254});
255export type OrchestrationV2ApprovalCapabilities = typeof OrchestrationV2ApprovalCapabilities.Type;
256
257export const OrchestrationV2PlanningCapabilities = Schema.Struct({
258 emitsPlanUpdated: Schema.Boolean,
259 emitsTodoList: Schema.Boolean,
260 emitsProposedPlan: Schema.Boolean,
261 supportsStructuredQuestions: Schema.Boolean,
262 planDeltasHaveItemIds: Schema.Boolean,
263});
264export type OrchestrationV2PlanningCapabilities = typeof OrchestrationV2PlanningCapabilities.Type;
265
266export const OrchestrationV2SubagentCapabilities = Schema.Struct({
267 supportsSubagents: Schema.Boolean,
268 exposesSubagentThreadIds: Schema.Boolean,
269 emitsSubagentLifecycle: Schema.Boolean,
270 canWaitForSubagents: Schema.Boolean,
271 canCloseSubagents: Schema.Boolean,
272 canForkSubagentThread: Schema.Boolean,
273});
274export type OrchestrationV2SubagentCapabilities = typeof OrchestrationV2SubagentCapabilities.Type;
275
276export const OrchestrationV2ContextCapabilities = Schema.Struct({
277 acceptsSystemContext: Schema.Boolean,
278 acceptsDeveloperContext: Schema.Boolean,
279 acceptsSyntheticUserContext: Schema.Boolean,
280 canGenerateSummaries: Schema.Boolean,
281 canConsumeHandoffSummaries: Schema.Boolean,
282 supportsDeltaHandoff: Schema.Boolean,
283 supportsFullThreadHandoff: Schema.Boolean,
284 maxRecommendedHandoffChars: Schema.NullOr(PositiveInt),
285});
286export type OrchestrationV2ContextCapabilities = typeof OrchestrationV2ContextCapabilities.Type;
287
288export const OrchestrationV2CheckpointCapabilities = Schema.Struct({
289 appCanCheckpointFilesystem: Schema.Boolean,
290 supportsNestedCheckpointScopes: Schema.Boolean,
291 providerCanRollbackConversation: Schema.Boolean,
292 providerRollbackReturnsSnapshot: Schema.Boolean,
293 providerCanReadConversationSnapshot: Schema.Boolean,
294});
295export type OrchestrationV2CheckpointCapabilities =
296 typeof OrchestrationV2CheckpointCapabilities.Type;
297
298export const OrchestrationV2RuntimePolicyCapabilities = Schema.Struct({
299 /**
300 * Where T3 runtime modes are actually enforced. "native" providers receive
301 * the approval and sandbox policy each turn and confine their own execution.
302 * "client-boundary" providers only have policy applied where T3 mediates the
303 * work (permission requests and client fs/terminal handlers); provider-owned
304 * execution is not confined, so sandbox guarantees are reduced.
305 */
306 enforcement: Schema.Literals(["native", "client-boundary"]),
307});
308export type OrchestrationV2RuntimePolicyCapabilities =
309 typeof OrchestrationV2RuntimePolicyCapabilities.Type;
310
311export const OrchestrationV2IdentityCapabilities = Schema.Struct({
312 nativeThreadIds: OrchestrationV2NativeRefStrength,
313 nativeTurnIds: OrchestrationV2NativeRefStrength,
314 nativeItemIds: OrchestrationV2NativeRefStrength,
315 nativeRequestIds: OrchestrationV2NativeRefStrength,
316});
317export type OrchestrationV2IdentityCapabilities = typeof OrchestrationV2IdentityCapabilities.Type;
318
319export const OrchestrationV2ProviderCapabilities = Schema.Struct({
320 sessions: OrchestrationV2SessionCapabilities,
321 threads: OrchestrationV2ThreadCapabilities,
322 turns: OrchestrationV2TurnCapabilities,
323 streaming: OrchestrationV2StreamingCapabilities,
324 tools: OrchestrationV2ToolCapabilities,
325 approvals: OrchestrationV2ApprovalCapabilities,
326 planning: OrchestrationV2PlanningCapabilities,
327 subagents: OrchestrationV2SubagentCapabilities,
328 context: OrchestrationV2ContextCapabilities,
329 checkpointing: OrchestrationV2CheckpointCapabilities,
330 identity: OrchestrationV2IdentityCapabilities,
331 // Events persisted before this field existed decode to the weaker
332 // client-boundary guarantee so replay never overclaims enforcement.
333 runtimePolicy: OrchestrationV2RuntimePolicyCapabilities.pipe(
334 Schema.withDecodingDefault(Effect.succeed({ enforcement: "client-boundary" as const })),
335 ),
336});
337export type OrchestrationV2ProviderCapabilities = typeof OrchestrationV2ProviderCapabilities.Type;
338
339export const OrchestrationV2LimitRecovery = Schema.Struct({
340 requestId: Schema.optional(CommandId),
341 runId: RunId,
342 resetAt: IsoDateTime,
343 autoResume: Schema.Boolean,
344 snooze: Schema.optional(Schema.Boolean),
345});
346export type OrchestrationV2LimitRecovery = typeof OrchestrationV2LimitRecovery.Type;
347
348/** A choice update preserves omitted options for this same run and reset. */
349export const OrchestrationV2LimitRecoveryUpdate = Schema.Struct({
350 runId: RunId,
351 resetAt: IsoDateTime,
352 autoResume: Schema.optional(Schema.Boolean),
353 snooze: Schema.optional(Schema.Boolean),
354}).check(
355 Schema.makeFilter(
356 (update) =>
357 update.autoResume !== undefined ||
358 update.snooze !== undefined ||
359 "A recovery update must include autoResume or snooze.",
360 ),
361);
362export type OrchestrationV2LimitRecoveryUpdate = typeof OrchestrationV2LimitRecoveryUpdate.Type;
363
364export const OrchestrationV2AppThread = Schema.Struct({
365 ...OrchestrationV2CreationFields,
366 id: ThreadId,
367 projectId: ProjectId,
368 title: TrimmedNonEmptyString,
369 providerInstanceId: ProviderInstanceId,
370 modelSelection: ModelSelection,
371 runtimeMode: RuntimeMode,
372 interactionMode: ProviderInteractionMode,
373 branch: Schema.NullOr(TrimmedNonEmptyString),
374 worktreePath: Schema.NullOr(TrimmedNonEmptyString),
375 /** Pull request the user linked to this thread (#8160); optional so
376 pre-linking servers still decode. */
377 linkedPullRequest: Schema.optional(Schema.NullOr(ThreadLinkedPullRequest)),
378 pullRequests: Schema.optional(Schema.Array(ThreadPullRequestLink)),
379 /** Pull request discovered from the thread's current branch. */
380 branchPullRequest: Schema.optional(Schema.NullOr(ThreadLinkedPullRequest)),
381 activeProviderThreadId: Schema.NullOr(ProviderThreadId),
382 historyOrigin: Schema.optional(OrchestrationV2ThreadHistoryOrigin),
383 lineage: OrchestrationV2AppThreadLineage,
384 forkedFrom: Schema.NullOr(
385 Schema.Union([
386 Schema.Struct({ type: Schema.Literal("run"), threadId: ThreadId, runId: RunId }),
387 Schema.Struct({ type: Schema.Literal("node"), nodeId: NodeId }),
388 Schema.Struct({
389 type: Schema.Literal("provider_thread"),
390 providerThreadId: ProviderThreadId,
391 providerTurnId: Schema.optional(ProviderTurnId),
392 }),
393 ]),
394 ),
395 createdAt: Schema.DateTimeUtc,
396 updatedAt: Schema.DateTimeUtc,
397 archivedAt: Schema.NullOr(Schema.DateTimeUtc),
398 settledOverride: Schema.NullOr(Schema.Literals(["settled", "active"])).pipe(
399 Schema.withDecodingDefault(Effect.succeed(null)),
400 ),
401 settledAt: Schema.NullOr(Schema.DateTimeUtc).pipe(
402 Schema.withDecodingDefault(Effect.succeed(null)),
403 ),
404 unsettledAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
405 snoozedUntil: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
406 snoozedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
407 /** Manual wakes restart inactivity without changing the sidebar's sort position. */
408 lastSnoozeWakeAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
409 limitRecovery: Schema.optional(Schema.NullOr(OrchestrationV2LimitRecovery)),
410 pinnedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
411 autoSettleDisabledAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
412 // Fractional-index slot in the user-arranged pinned order. Optional so
413 // payloads from pre-reorder servers still decode.
414 pinOrderKey: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),
415 /** Fractional-index slot in the user-arranged active order. */
416 activeOrderKey: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),
417 lastVisitedAt: Schema.NullOr(Schema.DateTimeUtc).pipe(
418 Schema.withDecodingDefault(Effect.succeed(null)),
419 ),
420 /** In-flight title regeneration marker; cleared when a new title lands. */
421 titleRegeneration: Schema.optional(
422 Schema.NullOr(
423 Schema.Struct({
424 requestId: CommandId,
425 startedAt: Schema.DateTimeUtc,
426 }),
427 ),
428 ),
429 /** Latest accepted rollback. Only its failure is recorded in `rollbackFailure`. */
430 rollbackRequestId: Schema.optional(CommandId),
431 /** Latest rollback that failed after every retry; cleared when the next rollback starts. */
432 rollbackFailure: Schema.optional(
433 Schema.NullOr(
434 Schema.Struct({
435 requestId: CommandId,
436 message: TrimmedNonEmptyString,
437 }),
438 ),
439 ),
440 deletedAt: Schema.NullOr(Schema.DateTimeUtc),
441});
442export type OrchestrationV2AppThread = typeof OrchestrationV2AppThread.Type;
443
444/**
445 * A subagent the provider spawned on its own (Claude's Agent tool, Codex or
446 * Cursor native subagents). The provider owns its conversation, so it cannot
447 * take messages; T3 delegate_task children (`creationSource: "mcp"`) can.
448 */
449export function isProviderNativeSubagentThread(
450 thread: Pick<OrchestrationV2AppThread, "lineage" | "creationSource">,
451): boolean {
452 return thread.lineage.relationshipToParent === "subagent" && thread.creationSource === "provider";
453}
454
455export const OrchestrationV2RunStatus = Schema.Literals([
456 "preparing",
457 "queued",
458 "starting",
459 "running",
460 "waiting",
461 "completed",
462 "interrupted",
463 "failed",
464 "cancelled",
465 "rolled_back",
466]);
467export type OrchestrationV2RunStatus = typeof OrchestrationV2RunStatus.Type;
468
469export const OrchestrationV2DelegatedCompletionTaskDeliveryState = Schema.Literals([
470 "pending",
471 "claimed",
472 "acknowledged",
473 "delivered",
474 "disposed",
475]);
476export type OrchestrationV2DelegatedCompletionTaskDeliveryState =
477 typeof OrchestrationV2DelegatedCompletionTaskDeliveryState.Type;
478
479export const OrchestrationV2DelegatedCompletionTaskDelivery = Schema.Struct({
480 state: OrchestrationV2DelegatedCompletionTaskDeliveryState,
481 observedByRunId: Schema.NullOr(RunId),
482});
483export type OrchestrationV2DelegatedCompletionTaskDelivery =
484 typeof OrchestrationV2DelegatedCompletionTaskDelivery.Type;
485
486export const OrchestrationV2DelegatedCompletionDelivery = Schema.Struct({
487 generation: PositiveInt,
488 messageId: MessageId,
489 taskIds: Schema.Array(NodeId),
490});
491export type OrchestrationV2DelegatedCompletionDelivery =
492 typeof OrchestrationV2DelegatedCompletionDelivery.Type;
493
494export const OrchestrationV2DelegatedCompletionCohort = Schema.Struct({
495 disposition: Schema.Literals(["open", "stopped", "disposed"]),
496 nextGeneration: PositiveInt,
497 delivery: Schema.NullOr(OrchestrationV2DelegatedCompletionDelivery),
498});
499export type OrchestrationV2DelegatedCompletionCohort =
500 typeof OrchestrationV2DelegatedCompletionCohort.Type;
501
502/** Background work that restart recovery cancelled; the next provider turn is told once. */
503export const OrchestrationV2RestartCancelledBackgroundWork = Schema.Struct({
504 kind: Schema.Literals(["subagent", "shell", "monitor", "task"]),
505 label: TrimmedNonEmptyString,
506 /** Stable identity (turn item or provider task id) so same-named work is not merged. */
507 id: Schema.optional(TrimmedNonEmptyString),
508});
509export type OrchestrationV2RestartCancelledBackgroundWork =
510 typeof OrchestrationV2RestartCancelledBackgroundWork.Type;
511
512/** Replaces a run's recorded restart-cancelled work without touching its lifecycle. */
513export const OrchestrationV2RunBackgroundWorkCancelled = Schema.Struct({
514 runId: RunId,
515 restartCancelledBackgroundWork: Schema.Array(OrchestrationV2RestartCancelledBackgroundWork),
516});
517export type OrchestrationV2RunBackgroundWorkCancelled =
518 typeof OrchestrationV2RunBackgroundWorkCancelled.Type;
519
520export const OrchestrationV2ThreadLaunchWorkspaceStrategy = Schema.Union([
521 Schema.Struct({
522 type: Schema.Literal("root"),
523 branch: Schema.optional(TrimmedNonEmptyString),
524 }),
525 Schema.Struct({
526 type: Schema.Literal("existing_worktree"),
527 worktreePath: TrimmedNonEmptyString,
528 branch: Schema.optional(TrimmedNonEmptyString),
529 }),
530 Schema.Struct({
531 type: Schema.Literal("worktree"),
532 baseRef: TrimmedNonEmptyString,
533 branch: Schema.optional(TrimmedNonEmptyString),
534 startFromOrigin: Schema.optional(Schema.Boolean),
535 }),
536]);
537export type OrchestrationV2ThreadLaunchWorkspaceStrategy =
538 typeof OrchestrationV2ThreadLaunchWorkspaceStrategy.Type;
539
540/** Failure code on the error item a failed workspace preparation leaves. */
541export const ORCHESTRATION_V2_WORKSPACE_PREPARATION_FAILURE_CODE = "workspace_preparation_failed";
542
543export const OrchestrationV2Run = Schema.Struct({
544 id: RunId,
545 threadId: ThreadId,
546 ordinal: PositiveInt,
547 providerInstanceId: ProviderInstanceId,
548 modelSelection: ModelSelection,
549 providerThreadId: Schema.NullOr(ProviderThreadId),
550 userMessageId: MessageId,
551 rootNodeId: Schema.NullOr(NodeId),
552 activeAttemptId: Schema.NullOr(RunAttemptId),
553 status: OrchestrationV2RunStatus,
554 queuePosition: Schema.optional(Schema.NullOr(PositiveInt)),
555 /** Restart recovery holds the queue until the user explicitly resumes it. */
556 queueHeld: Schema.optional(Schema.Boolean),
557 requestedAt: Schema.DateTimeUtc,
558 startedAt: Schema.NullOr(Schema.DateTimeUtc),
559 completedAt: Schema.NullOr(Schema.DateTimeUtc),
560 checkpointId: Schema.NullOr(CheckpointId),
561 contextHandoffId: Schema.NullOr(ContextHandoffId),
562 /** Links server-generated restart continuations to the interrupted run. */
563 restartContinuationOfRunId: Schema.optional(RunId),
564 /** The delegated task this run answers, including a follow-up in an existing child thread. */
565 delegatedTaskId: Schema.optional(NodeId),
566 /**
567 * Set on wake runs (background notifications, delegated task results,
568 * restart continuations): when the work they continue started. Read it
569 * through orchestrationV2RunWorkStartedAt.
570 */
571 workStartedAt: Schema.optional(Schema.DateTimeUtc),
572 /**
573 * Set by restart recovery on the thread's latest started run. Delivered to
574 * the provider with the first later run that reaches a provider turn.
575 */
576 restartCancelledBackgroundWork: Schema.optional(
577 Schema.Array(OrchestrationV2RestartCancelledBackgroundWork),
578 ),
579 sourcePlanRef: Schema.optional(
580 Schema.Struct({
581 threadId: ThreadId,
582 planId: PlanId,
583 }),
584 ),
585 delegatedCompletion: Schema.optional(OrchestrationV2DelegatedCompletionCohort),
586 /** How a launch prepares this run's workspace; prepared-run.retry repeats it. */
587 workspacePreparation: Schema.optional(OrchestrationV2ThreadLaunchWorkspaceStrategy),
588});
589export type OrchestrationV2Run = typeof OrchestrationV2Run.Type;
590
591/**
592 * When the work a run belongs to started. A wake does not start new work, so
593 * working timers count from the prompt that did, not from the latest wake.
594 */
595export function orchestrationV2RunWorkStartedAt(
596 run: Pick<OrchestrationV2Run, "workStartedAt" | "startedAt" | "requestedAt">,
597): OrchestrationV2Run["requestedAt"] {
598 return run.workStartedAt ?? run.startedAt ?? run.requestedAt;
599}
600
601export const OrchestrationV2RunAttempt = Schema.Struct({
602 id: RunAttemptId,
603 // Provider-thread rows can be reused after recovery; retain the native input destination.
604 nativeThreadId: Schema.optional(Schema.String),
605 runId: RunId,
606 attemptOrdinal: PositiveInt,
607 rootNodeId: NodeId,
608 providerInstanceId: ProviderInstanceId,
609 providerThreadId: ProviderThreadId,
610 providerTurnId: Schema.NullOr(ProviderTurnId),
611 reason: Schema.Literals(["initial", "steering_restart", "retry", "provider_recovery"]),
612 status: Schema.Literals([
613 "pending",
614 "running",
615 "completed",
616 "interrupted",
617 "failed",
618 "cancelled",
619 "superseded",
620 ]),
621 startedAt: Schema.NullOr(Schema.DateTimeUtc),
622 completedAt: Schema.NullOr(Schema.DateTimeUtc),
623});
624export type OrchestrationV2RunAttempt = typeof OrchestrationV2RunAttempt.Type;
625
626export const OrchestrationV2ExecutionNode = Schema.Struct({
627 id: NodeId,
628 threadId: ThreadId,
629 runId: Schema.NullOr(RunId),
630 parentNodeId: Schema.NullOr(NodeId),
631 rootNodeId: NodeId,
632 kind: Schema.Literals([
633 "root_turn",
634 "assistant_message",
635 "reasoning",
636 "plan",
637 "todo_list",
638 "tool_call",
639 "approval_request",
640 "user_input_request",
641 "subagent",
642 "hook",
643 "system",
644 ]),
645 status: Schema.Literals([
646 "idle",
647 "pending",
648 "running",
649 "waiting",
650 "completed",
651 "interrupted",
652 "failed",
653 "cancelled",
654 "rolled_back",
655 ]),
656 countsForRun: Schema.Boolean,
657 providerThreadId: Schema.NullOr(ProviderThreadId),
658 providerTurnId: Schema.NullOr(ProviderTurnId),
659 nativeItemRef: Schema.NullOr(OrchestrationV2ProviderRef),
660 runtimeRequestId: Schema.NullOr(RuntimeRequestId),
661 checkpointScopeId: Schema.NullOr(CheckpointScopeId),
662 startedAt: Schema.NullOr(Schema.DateTimeUtc),
663 completedAt: Schema.NullOr(Schema.DateTimeUtc),
664});
665export type OrchestrationV2ExecutionNode = typeof OrchestrationV2ExecutionNode.Type;
666
667/**
668 * One entry of a dynamic workflow's phase plan. The plan grows while the run
669 * executes: a phase a script only reaches at runtime joins the list when it
670 * starts, so a client must treat the list as append-only rather than as a
671 * fixed arc declared up front.
672 */
673export const OrchestrationV2WorkflowPhase = Schema.Struct({
674 index: NonNegativeInt,
675 title: TrimmedNonEmptyString,
676});
677export type OrchestrationV2WorkflowPhase = typeof OrchestrationV2WorkflowPhase.Type;
678
679/**
680 * One agent inside a workflow run. Timestamps are epoch milliseconds rather
681 * than `DateTimeUtc` because only the top-level entity fields are remapped for
682 * the JSON wire shape (see `OrchestrationV2SubagentJson`), so a nested
683 * `DateTimeUtc` would never be encoded.
684 */
685export const OrchestrationV2WorkflowAgent = Schema.Struct({
686 /** Spawn ordinal within the run. Stable identity: an agent keeps it across updates. */
687 index: NonNegativeInt,
688 label: TrimmedNonEmptyString,
689 /**
690 * Provider-assigned id, absent until the agent actually starts. Names the
691 * member's transcript file inside the run's transcript directory.
692 */
693 agentId: Schema.optional(TrimmedNonEmptyString),
694 /** The member's own thread, so the UI can open it like any subagent's. */
695 childThreadId: Schema.optional(ThreadId),
696 state: Schema.Literals(["queued", "running", "completed", "failed"]),
697 phaseIndex: Schema.optional(NonNegativeInt),
698 phaseTitle: Schema.optional(TrimmedNonEmptyString),
699 model: Schema.optional(TrimmedNonEmptyString),
700 /** Retry counter; > 1 means the agent was restarted after a provider error. */
701 attempt: Schema.optional(NonNegativeInt),
702 totalTokens: Schema.optional(NonNegativeInt),
703 toolCalls: Schema.optional(NonNegativeInt),
704 durationMs: Schema.optional(NonNegativeInt),
705 queuedAt: Schema.optional(NonNegativeInt),
706 startedAt: Schema.optional(NonNegativeInt),
707 /**
708 * Prompt and result excerpts. A workflow member's whole conversation is one
709 * prompt and one answer, so together these are its transcript as far as the
710 * provider exposes it — both are capped by the CLI at a few hundred
711 * characters.
712 */
713 prompt: Schema.optional(Schema.NonEmptyString),
714 result: Schema.optional(Schema.NonEmptyString),
715});
716export type OrchestrationV2WorkflowAgent = typeof OrchestrationV2WorkflowAgent.Type;
717
718/**
719 * Filesystem handles the provider reports when a run launches. The transcript
720 * directory is what makes a member's full answer readable: the progress
721 * snapshot only carries a capped excerpt, so the server reads the member's
722 * transcript from here to fill its thread.
723 */
724export const OrchestrationV2WorkflowRunHandles = Schema.Struct({
725 runId: Schema.optional(TrimmedNonEmptyString),
726 transcriptDir: Schema.optional(TrimmedNonEmptyString),
727 scriptPath: Schema.optional(TrimmedNonEmptyString),
728});
729export type OrchestrationV2WorkflowRunHandles = typeof OrchestrationV2WorkflowRunHandles.Type;
730
731/**
732 * Workflow-run shape carried by the coordinator subagent. The snapshot is the
733 * provider's own replace-in-full view of the run; members are additionally
734 * projected as subagents in their own right.
735 */
736export const OrchestrationV2SubagentWorkflow = Schema.Struct({
737 name: Schema.optional(TrimmedNonEmptyString),
738 runHandles: Schema.optional(OrchestrationV2WorkflowRunHandles),
739 phases: Schema.Array(OrchestrationV2WorkflowPhase),
740 agents: Schema.Array(OrchestrationV2WorkflowAgent),
741 totalTokens: Schema.optional(NonNegativeInt),
742 toolCalls: Schema.optional(NonNegativeInt),
743 durationMs: Schema.optional(NonNegativeInt),
744});
745export type OrchestrationV2SubagentWorkflow = typeof OrchestrationV2SubagentWorkflow.Type;
746
747export const OrchestrationV2Subagent = Schema.Struct({
748 id: NodeId,
749 threadId: ThreadId,
750 runId: Schema.NullOr(RunId),
751 parentNodeId: NodeId,
752 origin: Schema.Literals(["provider_native", "app_owned"]),
753 createdBy: OrchestrationV2Actor,
754 driver: ProviderDriverKind,
755 providerInstanceId: ProviderInstanceId,
756 providerThreadId: Schema.NullOr(ProviderThreadId),
757 childThreadId: Schema.NullOr(ThreadId),
758 nativeTaskRef: Schema.NullOr(OrchestrationV2ProviderRef),
759 prompt: Schema.String,
760 title: Schema.NullOr(Schema.String),
761 model: Schema.NullOr(Schema.String),
762 modelSelection: Schema.optional(ModelSelection),
763 // Parent-wake policy for app-owned tasks: "always" offers a continuation on
764 // every terminal (async delegations; queue_after_active sequences it behind
765 // a live parent run), "settled_only" offers only when the parent has no
766 // live run (wait-mode delegations, whose result returns through the
767 // blocking tool call). Absent on legacy records; treated as settled_only.
768 completionWake: Schema.optional(Schema.Literals(["always", "settled_only"])),
769 completionDelivery: Schema.optional(OrchestrationV2DelegatedCompletionTaskDelivery),
770 status: Schema.Literals([
771 "idle",
772 "pending",
773 "running",
774 "waiting",
775 "completed",
776 "failed",
777 "cancelled",
778 "interrupted",
779 ]),
780 progress: Schema.optional(Schema.String),
781 /** Present only on a workflow coordinator task; absent on ordinary subagents. */
782 workflow: Schema.optional(OrchestrationV2SubagentWorkflow),
783 result: Schema.NullOr(Schema.String),
784 startedAt: Schema.NullOr(Schema.DateTimeUtc),
785 completedAt: Schema.NullOr(Schema.DateTimeUtc),
786 updatedAt: Schema.DateTimeUtc,
787});
788export type OrchestrationV2Subagent = typeof OrchestrationV2Subagent.Type;
789
790/** Idle work is resumable, but does not keep a turn or its subscription alive. */
791export function isOrchestrationV2WorkActive(
792 status: OrchestrationV2ExecutionNode["status"],
793): boolean {
794 return status === "pending" || status === "running" || status === "waiting";
795}
796
797export const OrchestrationV2CheckpointScope = Schema.Struct({
798 id: CheckpointScopeId,
799 threadId: ThreadId,
800 runId: Schema.NullOr(RunId),
801 nodeId: NodeId,
802 parentScopeId: Schema.NullOr(CheckpointScopeId),
803 providerThreadId: Schema.NullOr(ProviderThreadId),
804 kind: Schema.Literals(["root_run", "subagent", "tool", "provider_thread", "manual"]),
805 ordinalWithinParent: NonNegativeInt,
806 advancesAppRunCount: Schema.Boolean,
807 cwd: TrimmedNonEmptyString,
808 createdAt: Schema.DateTimeUtc,
809});
810export type OrchestrationV2CheckpointScope = typeof OrchestrationV2CheckpointScope.Type;
811
812export const OrchestrationV2ProviderSession = Schema.Struct({
813 id: ProviderSessionId,
814 driver: ProviderDriverKind,
815 providerInstanceId: ProviderInstanceId,
816 status: Schema.Literals(["starting", "ready", "running", "waiting", "stopped", "error"]),
817 cwd: TrimmedNonEmptyString,
818 model: Schema.NullOr(TrimmedNonEmptyString),
819 capabilities: OrchestrationV2ProviderCapabilities,
820 createdAt: Schema.DateTimeUtc,
821 updatedAt: Schema.DateTimeUtc,
822 lastError: Schema.NullOr(Schema.String),
823});
824export type OrchestrationV2ProviderSession = typeof OrchestrationV2ProviderSession.Type;
825
826export const OrchestrationV2ProviderSessionDetached = Schema.Struct({
827 providerSessionId: ProviderSessionId,
828 detachedAt: Schema.DateTimeUtc,
829 reason: Schema.optional(Schema.String),
830});
831export type OrchestrationV2ProviderSessionDetached =
832 typeof OrchestrationV2ProviderSessionDetached.Type;
833
834/** The literal `kind` a union member is stored and sent with. */
835function encodedKind(member: Schema.Top): string {
836 const encoded = SchemaAST.toEncoded(member.ast);
837 const kind = SchemaAST.isObjects(encoded)
838 ? encoded.propertySignatures.find((property) => property.name === "kind")?.type
839 : undefined;
840 if (kind !== undefined && SchemaAST.isLiteral(kind) && typeof kind.literal === "string") {
841 return kind.literal;
842 }
843 throw new Error("Each member of a kind union needs a literal string `kind`.");
844}
845
846/**
847 * A union tagged by `kind` that tolerates kinds this build does not know.
848 * After the known members comes a decode-only arm: an object with an unknown
849 * `kind`, or none, decodes through `fallback` to a known member instead of
850 * failing, so a newer server can add kinds without breaking older clients and
851 * rows written before a kind existed still load. `unknown` builds that arm's
852 * input around the given `kind` field. A known kind whose fields do not decode
853 * still fails. Kinds are the encoded ones, which a member may rename on decode.
854 * The arm never encodes; values always match a known member first.
855 */
856function kindUnionWithFallback<
857 const Members extends ReadonlyArray<Schema.Top & { readonly Encoded: { readonly kind: string } }>,
858 Unknown extends Schema.Top,
859>(
860 members: Members,
861 unknown: (kind: Schema.optional<Schema.String>) => Unknown,
862 fallback: (value: Unknown["Type"]) => Schema.Union<Members>["Encoded"],
863) {
864 const knownKinds: ReadonlySet<string> = new Set(members.map(encodedKind));
865 const unknownKind = unknown(
866 Schema.optional(
867 Schema.String.check(
868 Schema.makeFilter(
869 (kind: string) => !knownKinds.has(kind) || "A known kind must decode in full.",
870 ),
871 ),
872 ),
873 ).pipe(
874 Schema.decodeTo(Schema.Union(members), {
875 decode: SchemaGetter.transform(fallback),
876 encode: SchemaGetter.forbidden(() => "Unknown kinds are decode-only."),
877 }),
878 );
879 // Members are tried in order, so the fallback must come last.
880 return Schema.Union([...members, unknownKind]);
881}
882
883const PendingBackgroundTaskFields = {
884 taskId: TrimmedNonEmptyString,
885 /** The work's name: a subagent's title, a command's description, a monitor's. */
886 description: Schema.optional(TrimmedNonEmptyString),
887};
888
889/**
890 * Provider-owned background work that can outlive the root turn (for example a
891 * Claude background Bash task). Associated with the provider thread so shared
892 * runtimes cannot make an unrelated app thread look busy. Adapters pick the
893 * kind; `background_task` is work they cannot name. Rosters persisted before
894 * kinds existed carry no `kind` and load as `background_task`.
895 */
896export const OrchestrationV2PendingBackgroundTask = kindUnionWithFallback(
897 [
898 Schema.Struct({
899 ...PendingBackgroundTaskFields,
900 kind: Schema.Literal("subagent"),
901 /** The subagent's own thread, when it has one. */
902 childThreadId: Schema.optional(ThreadId),
903 }),
904 Schema.Struct({ ...PendingBackgroundTaskFields, kind: Schema.Literal("command") }),
905 Schema.Struct({ ...PendingBackgroundTaskFields, kind: Schema.Literal("monitor") }),
906 Schema.Struct({ ...PendingBackgroundTaskFields, kind: Schema.Literal("background_task") }),
907 ],
908 (kind) => Schema.Struct({ ...PendingBackgroundTaskFields, kind }),
909 ({ taskId, description }) => ({
910 taskId,
911 ...(description === undefined ? {} : { description }),
912 kind: "background_task",
913 }),
914);
915export type OrchestrationV2PendingBackgroundTask = typeof OrchestrationV2PendingBackgroundTask.Type;
916
917/** Provider and adapter metadata that should not overwrite the app thread's title. */
918export const OrchestrationV2ProviderThreadNativeMetadata = Schema.Struct({
919 /** Provider-reported selection for display, separate from the app's saved preferences. */
920 modelSelection: Schema.optional(ModelSelection),
921 title: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),
922 updatedAt: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),
923 /** Version 2 scopes provider-derived item ids by provider instance. */
924 itemIdentityVersion: Schema.optional(Schema.Literal(2)),
925});
926export type OrchestrationV2ProviderThreadNativeMetadata =
927 typeof OrchestrationV2ProviderThreadNativeMetadata.Type;
928
929export const OrchestrationV2ProviderGoalStatus = Schema.Literals([
930 "active",
931 "paused",
932 "blocked",
933 "usage_limited",
934 "budget_limited",
935 "complete",
936]);
937export type OrchestrationV2ProviderGoalStatus = typeof OrchestrationV2ProviderGoalStatus.Type;
938
939/**
940 * A provider-native goal set with `/goal` (Codex and Claude). The provider
941 * keeps working until it judges the objective met and owns this state; T3
942 * mirrors the latest native report. Usage fields are provider-specific.
943 */
944export const OrchestrationV2ProviderGoal = Schema.Struct({
945 objective: TrimmedNonEmptyString,
946 status: OrchestrationV2ProviderGoalStatus,
947 /** Codex accounting for the goal across its turns. */
948 tokensUsed: Schema.optional(NonNegativeInt),
949 tokenBudget: Schema.optional(Schema.NullOr(NonNegativeInt)),
950 timeUsedSeconds: Schema.optional(NonNegativeInt),
951 /** Claude: evaluator checks that found the goal unmet, and the latest reason. */
952 checks: Schema.optional(NonNegativeInt),
953 lastCheck: Schema.optional(Schema.String),
954});
955export type OrchestrationV2ProviderGoal = typeof OrchestrationV2ProviderGoal.Type;
956
957export const OrchestrationV2ProviderThread = Schema.Struct({
958 id: ProviderThreadId,
959 driver: ProviderDriverKind,
960 providerInstanceId: ProviderInstanceId,
961 providerSessionId: Schema.NullOr(ProviderSessionId),
962 appThreadId: Schema.NullOr(ThreadId),
963 ownerNodeId: Schema.NullOr(NodeId),
964 nativeThreadRef: Schema.NullOr(OrchestrationV2ProviderRef),
965 nativeConversationHeadRef: Schema.NullOr(OrchestrationV2ProviderRef),
966 status: Schema.Literals(["not_loaded", "idle", "active", "archived", "closed", "error"]),
967 firstRunOrdinal: Schema.NullOr(PositiveInt),
968 lastRunOrdinal: Schema.NullOr(PositiveInt),
969 handoffIds: Schema.Array(ContextHandoffId),
970 forkedFrom: Schema.NullOr(
971 Schema.Struct({
972 providerThreadId: ProviderThreadId,
973 providerTurnId: Schema.optional(ProviderTurnId),
974 checkpointId: Schema.optional(CheckpointId),
975 }),
976 ),
977 // Optional Type so adapters can omit empty rosters; historical JSON decodes to [].
978 pendingBackgroundTasks: Schema.optional(Schema.Array(OrchestrationV2PendingBackgroundTask)).pipe(
979 Schema.withDecodingDefault(Effect.succeed([])),
980 ),
981 contextUsage: Schema.optional(Schema.NullOr(ThreadTokenUsageSnapshot)).pipe(
982 Schema.withDecodingDefault(Effect.succeed(null)),
983 ),
984 nativeMetadata: Schema.optional(Schema.NullOr(OrchestrationV2ProviderThreadNativeMetadata)).pipe(
985 Schema.withDecodingDefault(Effect.succeed(null)),
986 ),
987 /** Native goal on this provider thread; rows written before goals decode to null. */
988 goal: Schema.optional(Schema.NullOr(OrchestrationV2ProviderGoal)).pipe(
989 Schema.withDecodingDefault(Effect.succeed(null)),
990 ),
991 createdAt: Schema.DateTimeUtc,
992 updatedAt: Schema.DateTimeUtc,
993});
994export type OrchestrationV2ProviderThread = typeof OrchestrationV2ProviderThread.Type;
995
996export const OrchestrationV2HistoricalMessage = Schema.Struct({
997 role: Schema.Literals(["user", "assistant"]),
998 text: Schema.String,
999 runStatus: Schema.optional(Schema.String),
1000 threadId: ThreadId,
1001 runId: Schema.NullOr(RunId),
1002 itemId: TurnItemId,
1003 providerThreadId: Schema.NullOr(ProviderThreadId),
1004 status: Schema.String,
1005 kind: Schema.String,
1006});
1007export type OrchestrationV2HistoricalMessage = typeof OrchestrationV2HistoricalMessage.Type;
1008
1009export const OrchestrationV2ContextHandoff = Schema.Struct({
1010 id: ContextHandoffId,
1011 transferId: Schema.optional(Schema.NullOr(ContextTransferId)),
1012 threadId: ThreadId,
1013 targetRunId: RunId,
1014 fromProviderThreadIds: Schema.Array(ProviderThreadId),
1015 toProviderThreadId: ProviderThreadId,
1016 coveredRunOrdinals: Schema.Struct({
1017 from: PositiveInt,
1018 to: PositiveInt,
1019 }),
1020 strategy: Schema.Literals([
1021 "delta_since_target_last_seen",
1022 "fork_delta_summary",
1023 "full_thread_summary",
1024 "checkpoint_summary",
1025 "manual_context",
1026 ]),
1027 status: Schema.Literals(["pending", "ready", "failed", "superseded"]),
1028 summaryMessageId: Schema.NullOr(MessageId),
1029 summaryText: Schema.String,
1030 // Optional fields keep existing preview events and projections readable without a migration.
1031 history: Schema.optional(
1032 Schema.Struct({
1033 messages: Schema.Array(OrchestrationV2HistoricalMessage),
1034 coverage: Schema.String,
1035 omittedItems: NonNegativeInt,
1036 // IDs omitted during preparation, before the target's delivery budget is known.
1037 omittedItemIds: Schema.optional(Schema.Array(TurnItemId)),
1038 }),
1039 ),
1040 delivery: Schema.optional(
1041 Schema.Struct({
1042 nativeThreadId: Schema.String,
1043 status: Schema.Literals(["pending", "injected", "inline"]),
1044 itemIds: Schema.Array(TurnItemId),
1045 // Covered by recovery instructions, but not present in native model history.
1046 omittedItemIds: Schema.optional(Schema.Array(TurnItemId)),
1047 }),
1048 ),
1049 detailInTurnItem: Schema.optional(Schema.Literal(true)),
1050 createdByProviderInstanceId: Schema.NullOr(ProviderInstanceId),
1051 createdAt: Schema.DateTimeUtc,
1052 updatedAt: Schema.DateTimeUtc,
1053});
1054export type OrchestrationV2ContextHandoff = typeof OrchestrationV2ContextHandoff.Type;
1055
1056/** Live context usage reported by the provider mid-turn (#8144). */
1057export const OrchestrationV2ProviderTurnTokenUsage = Schema.Struct({
1058 usedTokens: NonNegativeInt,
1059 maxTokens: Schema.optional(Schema.NullOr(NonNegativeInt)),
1060 inputTokens: Schema.optional(NonNegativeInt),
1061 cachedInputTokens: Schema.optional(NonNegativeInt),
1062 outputTokens: Schema.optional(NonNegativeInt),
1063 reasoningOutputTokens: Schema.optional(NonNegativeInt),
1064 /** Prompt cache lifetime the provider wrote with this report. Clients treat
1065 the cache as cold once `updatedAt` is this old. */
1066 promptCacheTtlMs: Schema.optional(PositiveInt),
1067 /** ISO timestamp of the provider's report; string so wire encoding is stable. */
1068 updatedAt: Schema.String,
1069});
1070export type OrchestrationV2ProviderTurnTokenUsage =
1071 typeof OrchestrationV2ProviderTurnTokenUsage.Type;
1072
1073export const OrchestrationV2ProviderTurn = Schema.Struct({
1074 id: ProviderTurnId,
1075 providerThreadId: ProviderThreadId,
1076 nodeId: NodeId,
1077 runAttemptId: Schema.NullOr(RunAttemptId),
1078 nativeTurnRef: Schema.NullOr(OrchestrationV2ProviderRef),
1079 ordinal: PositiveInt,
1080 status: Schema.Literals([
1081 "pending",
1082 "running",
1083 "completed",
1084 "interrupted",
1085 "failed",
1086 "cancelled",
1087 ]),
1088 startedAt: Schema.NullOr(Schema.DateTimeUtc),
1089 completedAt: Schema.NullOr(Schema.DateTimeUtc),
1090 tokenUsage: Schema.optional(OrchestrationV2ProviderTurnTokenUsage),
1091 turnTokenUsage: Schema.optional(TurnTokenUsage),
1092});
1093export type OrchestrationV2ProviderTurn = typeof OrchestrationV2ProviderTurn.Type;
1094
1095/**
1096 * The provider turn a run attempt is on or ended with. A Codex goal keeps one
1097 * run open across several native turns, so an attempt's first turn is not
1098 * always its last.
1099 */
1100export function latestProviderTurnForAttempt<
1101 Turn extends Pick<OrchestrationV2ProviderTurn, "runAttemptId" | "ordinal">,
1102>(
1103 providerTurns: ReadonlyArray<Turn>,
1104 attemptId: RunAttemptId | null | undefined,
1105): Turn | undefined {
1106 let latest: Turn | undefined;
1107 for (const turn of providerTurns) {
1108 if (attemptId == null || turn.runAttemptId !== attemptId) continue;
1109 if (latest === undefined || turn.ordinal > latest.ordinal) latest = turn;
1110 }
1111 return latest;
1112}
1113
1114export const OrchestrationV2RuntimeRequest = Schema.Struct({
1115 id: RuntimeRequestId,
1116 nodeId: NodeId,
1117 providerTurnId: Schema.NullOr(ProviderTurnId),
1118 nativeRequestRef: Schema.NullOr(OrchestrationV2ProviderRef),
1119 kind: Schema.Union([
1120 ProviderRequestKind,
1121 Schema.Literals(["dynamic_tool_call", "user_input", "auth_refresh"]),
1122 ]),
1123 status: Schema.Literals(["pending", "resolved", "expired", "cancelled"]),
1124 responseCapability: Schema.Union([
1125 Schema.Struct({ type: Schema.Literal("live"), providerSessionId: ProviderSessionId }),
1126 Schema.Struct({ type: Schema.Literal("message") }),
1127 Schema.Struct({ type: Schema.Literal("not_resumable"), reason: Schema.String }),
1128 ]),
1129 createdAt: Schema.DateTimeUtc,
1130 resolvedAt: Schema.NullOr(Schema.DateTimeUtc),
1131 decision: Schema.optional(ProviderApprovalDecision),
1132 answers: Schema.optional(ProviderUserInputAnswers),
1133});
1134export type OrchestrationV2RuntimeRequest = typeof OrchestrationV2RuntimeRequest.Type;
1135
1136const SubagentNotificationSource = Schema.Struct({
1137 kind: Schema.Literal("subagent"),
1138 /** The subagent's own thread, when the notification reports one subagent. */
1139 childThreadId: Schema.optional(ThreadId),
1140});
1141const CommandNotificationSource = Schema.Struct({ kind: Schema.Literal("command") });
1142
1143/**
1144 * What a notification reports on. Several pieces of work of one kind share
1145 * that kind; mixed or unnamed work is `background_task`.
1146 *
1147 * Sources are stored and sent in the shape clients before `subagent` and
1148 * `command` existed decode, since they reject a kind they do not know: a
1149 * command is `background_command`, and a subagent is `background_task` with
1150 * `work: "subagent"`, a field those clients ignore. Encoding picks the first
1151 * member that fits, so those come first. The plain `subagent` and `command`
1152 * members after them decode values that were already decoded once.
1153 */
1154export const OrchestrationV2NotificationSource = kindUnionWithFallback(
1155 [
1156 Schema.Struct({
1157 kind: Schema.Literal("delegated_task"),
1158 taskIds: Schema.Array(NodeId),
1159 /** The task's own thread, when the notification reports one task. */
1160 childThreadId: Schema.optional(ThreadId),
1161 }),
1162 Schema.Struct({
1163 kind: Schema.Literal("background_task"),
1164 work: Schema.Literal("subagent"),
1165 childThreadId: Schema.optional(ThreadId),
1166 }).pipe(
1167 Schema.decodeTo(Schema.toType(SubagentNotificationSource), {
1168 decode: SchemaGetter.transform(({ childThreadId }) =>
1169 childThreadId === undefined
1170 ? { kind: "subagent" as const }
1171 : { kind: "subagent" as const, childThreadId },
1172 ),
1173 encode: SchemaGetter.transform(({ childThreadId }) => ({
1174 kind: "background_task" as const,
1175 work: "subagent" as const,
1176 ...(childThreadId === undefined ? {} : { childThreadId }),
1177 })),
1178 }),
1179 ),
1180 Schema.Struct({ kind: Schema.Literal("background_command").transform("command") }),
1181 SubagentNotificationSource,
1182 CommandNotificationSource,
1183 Schema.Struct({ kind: Schema.Literal("monitor") }),
1184 Schema.Struct({ kind: Schema.Literal("background_task") }),
1185 /** T3 Code itself, such as a restart continuing an interrupted turn. */
1186 Schema.Struct({ kind: Schema.Literal("system") }),
1187 ],
1188 (kind) => Schema.Struct({ kind }),
1189 () => ({ kind: "background_task" }),
1190);
1191export type OrchestrationV2NotificationSource = typeof OrchestrationV2NotificationSource.Type;
1192
1193// A notification records an observed event, not whether its payload has reached the agent.
1194// Provider delivery, wake policy, and agent-facing instructions belong to the backend.
1195export const OrchestrationV2Notification = Schema.Struct({
1196 source: OrchestrationV2NotificationSource,
1197 // Item status describes this timeline record; outcome describes the reported work.
1198 outcome: Schema.Literals(["completed", "failed", "cancelled", "updated", "unknown"]),
1199 summary: TrimmedNonEmptyString,
1200 detail: Schema.optional(Schema.String),
1201});
1202export type OrchestrationV2Notification = typeof OrchestrationV2Notification.Type;
1203
1204export const OrchestrationV2ConversationMessage = Schema.Struct({
1205 notification: Schema.optional(OrchestrationV2Notification),
1206 ...OrchestrationV2CreationFields,
1207 scheduledTaskId: Schema.optional(ScheduledTaskId),
1208 // The sending agent's thread in this environment, separate from the receiving thread.
1209 senderThreadId: Schema.optional(ThreadId),
1210 id: MessageId,
1211 threadId: ThreadId,
1212 runId: Schema.NullOr(RunId),
1213 nodeId: Schema.NullOr(NodeId),
1214 role: Schema.Literals(["user", "assistant", "system"]),
1215 text: Schema.String,
1216 context: Schema.optional(OrchestrationMessageContext),
1217 attachments: Schema.Array(ChatAttachment),
1218 streaming: Schema.Boolean,
1219 createdAt: Schema.DateTimeUtc,
1220 updatedAt: Schema.DateTimeUtc,
1221 delegatedCompletion: Schema.optional(
1222 Schema.Struct({
1223 parentRunId: RunId,
1224 generation: PositiveInt,
1225 taskIds: Schema.Array(NodeId),
1226 }),
1227 ),
1228});
1229export type OrchestrationV2ConversationMessage = typeof OrchestrationV2ConversationMessage.Type;
1230
1231export const OrchestrationV2PlanStep = Schema.Struct({
1232 id: TrimmedNonEmptyString,
1233 text: TrimmedNonEmptyString,
1234 status: Schema.Literals(["pending", "running", "completed"]),
1235 /** Durable server-owned boundary used to calculate elapsed time. */
1236 durationAnchorAt: Schema.optional(IsoDateTime),
1237 /** Elapsed time for a completed step. */
1238 durationMs: Schema.optional(NonNegativeInt),
1239});
1240export type OrchestrationV2PlanStep = typeof OrchestrationV2PlanStep.Type;
1241
1242export const OrchestrationV2UserInputQuestion = Schema.Struct({
1243 id: TrimmedNonEmptyString,
1244 header: TrimmedNonEmptyString,
1245 question: TrimmedNonEmptyString,
1246 options: Schema.Array(
1247 Schema.Struct({
1248 label: TrimmedNonEmptyString,
1249 description: TrimmedNonEmptyString,
1250 value: Schema.optional(Schema.String),
1251 }),
1252 ),
1253 multiSelect: Schema.optional(Schema.Boolean),
1254 allowCustomAnswer: Schema.optional(Schema.Boolean),
1255 /** Editable initial text. Answers preserve whitespace and allow an empty string when present. */
1256 initialAnswer: Schema.optional(Schema.String),
1257 required: Schema.optional(Schema.Boolean),
1258});
1259export type OrchestrationV2UserInputQuestion = typeof OrchestrationV2UserInputQuestion.Type;
1260
1261const OrchestrationV2PlanArtifactBaseFields = {
1262 id: PlanId,
1263 threadId: ThreadId,
1264 runId: Schema.NullOr(RunId),
1265 nodeId: NodeId,
1266 status: Schema.Literals(["draft", "active", "completed", "superseded"]),
1267 detailInTurnItem: Schema.optional(Schema.Literal(true)),
1268} as const;
1269
1270export const OrchestrationV2PlanArtifact = Schema.Union([
1271 Schema.Struct({
1272 ...OrchestrationV2PlanArtifactBaseFields,
1273 kind: Schema.Literal("proposed_plan"),
1274 markdown: Schema.String,
1275 }),
1276 Schema.Struct({
1277 ...OrchestrationV2PlanArtifactBaseFields,
1278 kind: Schema.Literal("todo_list"),
1279 steps: Schema.Array(OrchestrationV2PlanStep),
1280 explanation: Schema.optional(Schema.String),
1281 }),
1282]);
1283export type OrchestrationV2PlanArtifact = typeof OrchestrationV2PlanArtifact.Type;
1284
1285export const OrchestrationV2CheckpointFileSummary = Schema.Struct({
1286 path: TrimmedNonEmptyString,
1287 kind: TrimmedNonEmptyString,
1288 additions: NonNegativeInt,
1289 deletions: NonNegativeInt,
1290});
1291export type OrchestrationV2CheckpointFileSummary = typeof OrchestrationV2CheckpointFileSummary.Type;
1292
1293export const OrchestrationV2Checkpoint = Schema.Struct({
1294 id: CheckpointId,
1295 threadId: ThreadId,
1296 scopeId: CheckpointScopeId,
1297 runId: Schema.NullOr(RunId),
1298 nodeId: NodeId,
1299 parentCheckpointId: Schema.NullOr(CheckpointId),
1300 ordinalWithinScope: NonNegativeInt,
1301 appRunOrdinal: Schema.NullOr(PositiveInt),
1302 ref: CheckpointRef,
1303 status: Schema.Literals(["ready", "missing", "error", "stale"]),
1304 files: Schema.Array(OrchestrationV2CheckpointFileSummary),
1305 capturedAt: Schema.DateTimeUtc,
1306});
1307export type OrchestrationV2Checkpoint = typeof OrchestrationV2Checkpoint.Type;
1308
1309export const OrchestrationV2CheckpointRollbackRequest = Schema.Struct({
1310 scopeId: CheckpointScopeId,
1311 checkpointId: CheckpointId,
1312 requestedAt: Schema.DateTimeUtc,
1313});
1314export type OrchestrationV2CheckpointRollbackRequest =
1315 typeof OrchestrationV2CheckpointRollbackRequest.Type;
1316
1317export class OrchestrationV2CheckpointUnavailableError extends Schema.TaggedError<OrchestrationV2CheckpointUnavailableError>()(
1318 "OrchestrationV2CheckpointUnavailableError",
1319 {
1320 threadId: ThreadId,
1321 target: Schema.String,
1322 },
1323) {
1324 override get message(): string {
1325 return `Rollback target ${this.target} is unavailable for thread ${this.threadId}.`;
1326 }
1327}
1328
1329export const OrchestrationV2TurnItemStatus = Schema.Literals([
1330 "idle",
1331 "pending",
1332 "running",
1333 "waiting",
1334 "completed",
1335 "failed",
1336 "cancelled",
1337 "interrupted",
1338]);
1339
1340export type OrchestrationV2TurnItemStatus = typeof OrchestrationV2TurnItemStatus.Type;
1341
1342/** One structured file operation reported by a provider inside a file_change item. */
1343export const OrchestrationV2FileChangeDetail = Schema.Struct({
1344 operation: TrimmedNonEmptyString,
1345 path: TrimmedNonEmptyString,
1346 oldPath: Schema.optional(TrimmedNonEmptyString),
1347 fileType: Schema.optional(TrimmedNonEmptyString),
1348 mimeType: Schema.optional(TrimmedNonEmptyString),
1349});
1350export type OrchestrationV2FileChangeDetail = typeof OrchestrationV2FileChangeDetail.Type;
1351
1352export const OrchestrationV2ProviderFailureClass = Schema.Literals([
1353 "usage_limit",
1354 "provider_error",
1355 "transport_error",
1356 "permission_error",
1357 "validation_error",
1358 "unknown",
1359]);
1360export type OrchestrationV2ProviderFailureClass = typeof OrchestrationV2ProviderFailureClass.Type;
1361
1362const OrchestrationV2ProviderFailureMessage = TrimmedNonEmptyString.check(
1363 Schema.isMaxLength(4_096),
1364);
1365const OrchestrationV2ProviderFailureCode = TrimmedNonEmptyString.check(Schema.isMaxLength(128));
1366
1367/**
1368 * Transport-safe failure information suitable for persistence and display.
1369 * Producers must redact credentials before constructing this value. The
1370 * schema bounds every provider-controlled string as a second line of defense.
1371 */
1372export const OrchestrationV2ProviderFailure = Schema.Struct({
1373 class: OrchestrationV2ProviderFailureClass,
1374 message: OrchestrationV2ProviderFailureMessage,
1375 code: Schema.NullOr(OrchestrationV2ProviderFailureCode),
1376 retryable: Schema.NullOr(Schema.Boolean),
1377 /** Reported reset time; absent when the provider cannot name one. */
1378 resetAt: Schema.optional(Schema.NullOr(IsoDateTime)),
1379});
1380export type OrchestrationV2ProviderFailure = typeof OrchestrationV2ProviderFailure.Type;
1381
1382/**
1383 * Provider-reported retry progress. Some providers expose all fields (Claude),
1384 * while others only expose `willRetry` and encode counters in display text
1385 * (Codex), so the protocol-specific values remain nullable.
1386 */
1387export const OrchestrationV2ProviderRetry = Schema.Struct({
1388 attempt: PositiveInt,
1389 maxAttempts: Schema.NullOr(PositiveInt),
1390 retryDelayMs: Schema.NullOr(NonNegativeInt),
1391});
1392export type OrchestrationV2ProviderRetry = typeof OrchestrationV2ProviderRetry.Type;
1393
1394export const OrchestrationV2ProviderThreadDisposition = Schema.Literals(["reusable", "broken"]);
1395export type OrchestrationV2ProviderThreadDisposition =
1396 typeof OrchestrationV2ProviderThreadDisposition.Type;
1397
1398export const OrchestrationV2UserMessageInputIntent = Schema.Literals([
1399 "turn_start",
1400 "queued_turn",
1401 "steer",
1402 "promoted_queued_to_steer",
1403]);
1404export type OrchestrationV2UserMessageInputIntent =
1405 typeof OrchestrationV2UserMessageInputIntent.Type;
1406
1407const OrchestrationV2TurnItemBaseFields = {
1408 toolNonExecutionKind: Schema.optional(Schema.String),
1409 toolSurface: Schema.optional(ToolActivitySurface),
1410 toolIcon: Schema.optional(ToolActivityIcon),
1411 toolSource: Schema.optional(ToolActivitySource),
1412 id: TurnItemId,
1413 threadId: ThreadId,
1414 runId: Schema.NullOr(RunId),
1415 nodeId: Schema.NullOr(NodeId),
1416 providerThreadId: Schema.NullOr(ProviderThreadId),
1417 providerTurnId: Schema.NullOr(ProviderTurnId),
1418 nativeItemRef: Schema.NullOr(OrchestrationV2ProviderRef),
1419 parentItemId: Schema.NullOr(TurnItemId),
1420 ordinal: NonNegativeInt,
1421 status: OrchestrationV2TurnItemStatus,
1422 title: Schema.NullOr(Schema.String),
1423 startedAt: Schema.NullOr(Schema.DateTimeUtc),
1424 completedAt: Schema.NullOr(Schema.DateTimeUtc),
1425 updatedAt: Schema.DateTimeUtc,
1426} as const;
1427
1428export const OrchestrationV2FileSearchResult = Schema.Struct({
1429 fileName: TrimmedNonEmptyString,
1430 line: Schema.optional(PositiveInt),
1431 column: Schema.optional(PositiveInt),
1432 preview: Schema.optional(Schema.String),
1433});
1434export type OrchestrationV2FileSearchResult = typeof OrchestrationV2FileSearchResult.Type;
1435
1436export const OrchestrationV2WebSearchResult = Schema.Struct({
1437 title: Schema.optional(Schema.String),
1438 url: Schema.optional(TrimmedNonEmptyString),
1439 snippet: Schema.optional(Schema.String),
1440});
1441export type OrchestrationV2WebSearchResult = typeof OrchestrationV2WebSearchResult.Type;
1442
1443export const OrchestrationV2SecretRequestStatus = Schema.Literals([
1444 "pending",
1445 "saved",
1446 "declined",
1447 "cancelled",
1448]);
1449export type OrchestrationV2SecretRequestStatus = typeof OrchestrationV2SecretRequestStatus.Type;
1450
1451/**
1452 * A secret an agent asked the user for. The value never passes through
1453 * orchestration: the item carries only what was asked and how it was answered.
1454 */
1455const OrchestrationV2SecretRequestFields = {
1456 type: Schema.Literal("secret_request"),
1457 label: TrimmedNonEmptyString,
1458 reason: Schema.String,
1459 placeholder: Schema.optional(Schema.String),
1460 secretStatus: OrchestrationV2SecretRequestStatus,
1461} as const;
1462
1463export const OrchestrationV2TurnItem = Schema.Union([
1464 Schema.Struct({
1465 ...OrchestrationV2TurnItemBaseFields,
1466 type: Schema.Literal("notification"),
1467 ...OrchestrationV2Notification.fields,
1468 }),
1469 Schema.Struct({
1470 ...OrchestrationV2TurnItemBaseFields,
1471 ...OrchestrationV2CreationFields,
1472 type: Schema.Literal("user_message"),
1473 messageId: MessageId,
1474 scheduledTaskId: Schema.optional(ScheduledTaskId),
1475 senderThreadId: Schema.optional(ThreadId),
1476 inputIntent: OrchestrationV2UserMessageInputIntent,
1477 text: Schema.String,
1478 context: Schema.optional(OrchestrationMessageContext),
1479 attachments: Schema.Array(ChatAttachment),
1480 }),
1481 Schema.Struct({
1482 ...OrchestrationV2TurnItemBaseFields,
1483 type: Schema.Literal("assistant_message"),
1484 messageId: MessageId,
1485 text: Schema.String,
1486 attachments: Schema.optional(Schema.Array(ChatAttachment)),
1487 streaming: Schema.Boolean,
1488 }),
1489 Schema.Struct({
1490 ...OrchestrationV2TurnItemBaseFields,
1491 type: Schema.Literal("reasoning"),
1492 text: Schema.String,
1493 streaming: Schema.Boolean,
1494 }),
1495 Schema.Struct({
1496 ...OrchestrationV2TurnItemBaseFields,
1497 type: Schema.Literal("proposed_plan"),
1498 planId: PlanId,
1499 markdown: Schema.String,
1500 streaming: Schema.Boolean,
1501 }),
1502 Schema.Struct({
1503 ...OrchestrationV2TurnItemBaseFields,
1504 type: Schema.Literal("todo_list"),
1505 planId: PlanId,
1506 steps: Schema.Array(OrchestrationV2PlanStep),
1507 explanation: Schema.optional(Schema.String),
1508 }),
1509 Schema.Struct({
1510 ...OrchestrationV2TurnItemBaseFields,
1511 type: Schema.Literal("user_input_request"),
1512 requestId: RuntimeRequestId,
1513 questions: Schema.Array(OrchestrationV2UserInputQuestion),
1514 questionAnswer: Schema.optional(UserInputAttachmentAnswerPayload),
1515 responseMode: Schema.optional(Schema.Literal("message")),
1516 }),
1517 Schema.Struct({
1518 ...OrchestrationV2TurnItemBaseFields,
1519 type: Schema.Literal("file_change"),
1520 fileName: TrimmedNonEmptyString,
1521 additions: Schema.optional(NonNegativeInt),
1522 deletions: Schema.optional(NonNegativeInt),
1523 diffStr: Schema.optional(Schema.String),
1524 oldStr: Schema.optional(Schema.String),
1525 newStr: Schema.optional(Schema.String),
1526 changes: Schema.optional(Schema.Array(OrchestrationV2FileChangeDetail)),
1527 }),
1528 Schema.Struct({
1529 ...OrchestrationV2TurnItemBaseFields,
1530 type: Schema.Literal("command_execution"),
1531 input: Schema.String,
1532 output: Schema.optional(Schema.String),
1533 /** Set on the wire when output was withheld; fetch it with getTurnItem. */
1534 outputOmitted: Schema.optional(Schema.Boolean),
1535 outputIndicatesFailure: Schema.optional(Schema.Boolean),
1536 exitCode: Schema.optional(Schema.Int),
1537 }),
1538 Schema.Struct({
1539 ...OrchestrationV2TurnItemBaseFields,
1540 type: Schema.Literal("file_search"),
1541 pattern: Schema.optional(Schema.String),
1542 results: Schema.optional(Schema.Array(OrchestrationV2FileSearchResult)),
1543 }),
1544 Schema.Struct({
1545 ...OrchestrationV2TurnItemBaseFields,
1546 type: Schema.Literal("web_search"),
1547 patterns: Schema.optional(Schema.Array(Schema.String)),
1548 results: Schema.optional(Schema.Array(OrchestrationV2WebSearchResult)),
1549 }),
1550 Schema.Struct({
1551 ...OrchestrationV2TurnItemBaseFields,
1552 type: Schema.Literal("approval_request"),
1553 requestId: RuntimeRequestId,
1554 requestKind: ProviderRequestKind,
1555 prompt: Schema.optional(Schema.String),
1556 /** App requesting access, for mcp-elicitation approvals (#8058). */
1557 appName: Schema.optional(Schema.String),
1558 /** Approval choices advertised by the provider (#8058). */
1559 options: Schema.optional(Schema.Array(ProviderApprovalOption)),
1560 }),
1561 Schema.Struct({
1562 ...OrchestrationV2TurnItemBaseFields,
1563 type: Schema.Literal("checkpoint"),
1564 checkpointId: CheckpointId,
1565 scopeId: CheckpointScopeId,
1566 files: Schema.Array(OrchestrationV2CheckpointFileSummary),
1567 }),
1568 Schema.Struct({
1569 ...OrchestrationV2TurnItemBaseFields,
1570 type: Schema.Literal("run_interrupt_request"),
1571 message: Schema.String,
1572 }),
1573 Schema.Struct({
1574 ...OrchestrationV2TurnItemBaseFields,
1575 type: Schema.Literal("run_interrupt_result"),
1576 message: Schema.String,
1577 }),
1578 Schema.Struct({
1579 ...OrchestrationV2TurnItemBaseFields,
1580 type: Schema.Literal("system_notice"),
1581 message: Schema.String,
1582 }),
1583 Schema.Struct({
1584 ...OrchestrationV2TurnItemBaseFields,
1585 type: Schema.Literal("error"),
1586 failure: OrchestrationV2ProviderFailure,
1587 retry: Schema.optional(OrchestrationV2ProviderRetry),
1588 }),
1589 Schema.Struct({
1590 ...OrchestrationV2TurnItemBaseFields,
1591 type: Schema.Literal("compaction"),
1592 driver: Schema.NullOr(ProviderDriverKind),
1593 summary: Schema.optional(Schema.String),
1594 beforeTokenCount: Schema.optional(NonNegativeInt),
1595 afterTokenCount: Schema.optional(NonNegativeInt),
1596 }),
1597 Schema.Struct({
1598 ...OrchestrationV2TurnItemBaseFields,
1599 type: Schema.Literal("handoff"),
1600 contextHandoffId: ContextHandoffId,
1601 fromProviderThreadIds: Schema.Array(ProviderThreadId),
1602 toProviderThreadId: ProviderThreadId,
1603 fromProviderInstanceIds: Schema.Array(ProviderInstanceId),
1604 toProviderInstanceId: ProviderInstanceId,
1605 // Model selections active on the covered source runs and the target
1606 // model, so timelines can label the handoff by model rather than by
1607 // provider instance id. Absent on items persisted before these fields.
1608 fromModelSelections: Schema.optional(Schema.Array(ModelSelection)),
1609 toModel: Schema.optional(Schema.String),
1610 strategy: Schema.Literals([
1611 "delta_since_target_last_seen",
1612 "fork_delta_summary",
1613 "full_thread_summary",
1614 "checkpoint_summary",
1615 "manual_context",
1616 ]),
1617 summary: Schema.optional(Schema.String),
1618 }),
1619 Schema.Struct({
1620 ...OrchestrationV2TurnItemBaseFields,
1621 type: Schema.Literal("fork"),
1622 source: Schema.Union([
1623 Schema.Struct({ type: Schema.Literal("run"), threadId: ThreadId, runId: RunId }),
1624 Schema.Struct({ type: Schema.Literal("node"), nodeId: NodeId }),
1625 Schema.Struct({
1626 type: Schema.Literal("provider_thread"),
1627 providerThreadId: ProviderThreadId,
1628 providerTurnId: Schema.optional(ProviderTurnId),
1629 }),
1630 ]),
1631 targetThreadId: ThreadId,
1632 providerThreadId: Schema.optional(ProviderThreadId),
1633 }),
1634 Schema.Struct({
1635 ...OrchestrationV2TurnItemBaseFields,
1636 type: Schema.Literal("thread_created"),
1637 targetThreadId: ThreadId,
1638 targetRunId: Schema.NullOr(RunId),
1639 targetProviderInstanceId: ProviderInstanceId,
1640 targetModel: TrimmedNonEmptyString,
1641 }),
1642 Schema.Struct({
1643 ...OrchestrationV2TurnItemBaseFields,
1644 ...OrchestrationV2SecretRequestFields,
1645 }),
1646 Schema.Struct({
1647 ...OrchestrationV2TurnItemBaseFields,
1648 type: Schema.Literal("subagent"),
1649 subagentId: NodeId,
1650 origin: Schema.Literals(["provider_native", "app_owned"]),
1651 driver: ProviderDriverKind,
1652 providerInstanceId: ProviderInstanceId,
1653 childThreadId: Schema.NullOr(ThreadId),
1654 prompt: Schema.String,
1655 progress: Schema.optional(Schema.String),
1656 result: Schema.NullOr(Schema.String),
1657 }),
1658 Schema.Struct({
1659 ...OrchestrationV2TurnItemBaseFields,
1660 type: Schema.Literal("dynamic_tool"),
1661 toolName: Schema.NullOr(TrimmedNonEmptyString),
1662 viewedImagePath: Schema.optional(TrimmedNonEmptyString),
1663 input: Schema.Unknown,
1664 output: Schema.optional(Schema.Unknown),
1665 /** Set on the wire when output was withheld; fetch it with getTurnItem. */
1666 outputOmitted: Schema.optional(Schema.Boolean),
1667 }),
1668]);
1669export type OrchestrationV2TurnItem = typeof OrchestrationV2TurnItem.Type;
1670
1671/**
1672 * Turn item types grow over time, so clients decode them forward-compatibly:
1673 * an item whose type this build does not know is dropped from snapshots and
1674 * history instead of failing the thread. A known type that does not decode
1675 * still fails. Arrays of projected rows filter on the row's nested item.
1676 */
1677const isUnknownTurnItem = hasUnknownUnionTag(OrchestrationV2TurnItem.members, "type");
1678
1679const turnItemArray = <Members extends ReadonlyArray<Schema.Top & { readonly fields: object }>>(
1680 union: Schema.Union<Members>,
1681) => ForwardCompatibleUnionArray(union.members, "type");
1682
1683/** Projected rows whose nested item may be of a type this build does not know. */
1684const projectedTurnItemArray = <Row extends Schema.Top, Item extends Schema.Top>(
1685 row: Row,
1686 rowWithUnknownItem: Item,
1687) =>
1688 Schema.Array(rowWithUnknownItem).pipe(
1689 Schema.decodeTo(
1690 Schema.Array(Schema.toType(row)),
1691 SchemaTransformation.transform<ReadonlyArray<Row["Type"]>, ReadonlyArray<Item["Type"]>>({
1692 decode: (rows) =>
1693 rows.filter(
1694 (projected) => !isUnknownUnionMember((projected as { readonly item: unknown }).item),
1695 ) as ReadonlyArray<Row["Type"]>,
1696 encode: (rows) => rows,
1697 }),
1698 ),
1699 );
1700
1701export const OrchestrationV2ProjectedTurnItem = Schema.Struct({
1702 position: NonNegativeInt,
1703 visibility: Schema.Literals(["local", "inherited", "synthetic"]),
1704 sourceThreadId: ThreadId,
1705 sourceItemId: TurnItemId,
1706 item: OrchestrationV2TurnItem,
1707});
1708export type OrchestrationV2ProjectedTurnItem = typeof OrchestrationV2ProjectedTurnItem.Type;
1709
1710export const OrchestrationV2RawProviderEvent = Schema.Struct({
1711 id: RawEventId,
1712 driver: ProviderDriverKind,
1713 providerInstanceId: ProviderInstanceId,
1714 providerSessionId: ProviderSessionId,
1715 sequence: PositiveInt,
1716 direction: Schema.Literals(["incoming", "outgoing"]),
1717 messageKind: Schema.Literals(["request", "response", "notification", "error"]),
1718 method: Schema.NullOr(TrimmedNonEmptyString),
1719 jsonRpcId: Schema.NullOr(Schema.Union([Schema.String, Schema.Number])),
1720 payload: Schema.Unknown,
1721 observedAt: Schema.DateTimeUtc,
1722});
1723export type OrchestrationV2RawProviderEvent = typeof OrchestrationV2RawProviderEvent.Type;
1724
1725const OrchestrationV2EventBase = Schema.Struct({
1726 id: EventId,
1727 threadId: ThreadId,
1728 runId: Schema.optional(RunId),
1729 nodeId: Schema.optional(NodeId),
1730 driver: Schema.optional(ProviderDriverKind),
1731 providerInstanceId: Schema.optional(ProviderInstanceId),
1732 rawEventId: Schema.optional(RawEventId),
1733 occurredAt: Schema.DateTimeUtc,
1734});
1735
1736export const OrchestrationV2DomainEvent = Schema.Union([
1737 Schema.Struct({
1738 ...OrchestrationV2EventBase.fields,
1739 type: Schema.Literal("thread.created"),
1740 payload: OrchestrationV2AppThread,
1741 }),
1742 Schema.Struct({
1743 ...OrchestrationV2EventBase.fields,
1744 type: Schema.Literals([
1745 "thread.archived",
1746 "thread.unarchived",
1747 "thread.deleted",
1748 "thread.settled",
1749 "thread.unsettled",
1750 "thread.snoozed",
1751 "thread.unsnoozed",
1752 "thread.pinned",
1753 "thread.auto-settle-set",
1754 "thread.unpinned",
1755 "thread.pin-reordered",
1756 "thread.active-reordered",
1757 "thread.visited",
1758 "thread.marked-unread",
1759 "thread.metadata-updated",
1760 "thread.pull-request-synced",
1761 "thread.runtime-mode-updated",
1762 "thread.interaction-mode-updated",
1763 "thread.model-selection-updated",
1764 "thread.provider-switched",
1765 ]),
1766 payload: OrchestrationV2AppThread,
1767 }),
1768 Schema.Struct({
1769 ...OrchestrationV2EventBase.fields,
1770 type: Schema.Literal("thread.pull-request-link-updated"),
1771 payload: ThreadPullRequestLink,
1772 }),
1773 Schema.Struct({
1774 ...OrchestrationV2EventBase.fields,
1775 type: Schema.Literal("run.created"),
1776 payload: OrchestrationV2Run,
1777 }),
1778 Schema.Struct({
1779 ...OrchestrationV2EventBase.fields,
1780 type: Schema.Literal("run.updated"),
1781 payload: OrchestrationV2Run,
1782 }),
1783 Schema.Struct({
1784 ...OrchestrationV2EventBase.fields,
1785 type: Schema.Literal("run.background-work-cancelled"),
1786 payload: OrchestrationV2RunBackgroundWorkCancelled,
1787 }),
1788 Schema.Struct({
1789 ...OrchestrationV2EventBase.fields,
1790 type: Schema.Literal("run-attempt.created"),
1791 payload: OrchestrationV2RunAttempt,
1792 }),
1793 Schema.Struct({
1794 ...OrchestrationV2EventBase.fields,
1795 type: Schema.Literal("run-attempt.updated"),
1796 payload: OrchestrationV2RunAttempt,
1797 }),
1798 Schema.Struct({
1799 ...OrchestrationV2EventBase.fields,
1800 type: Schema.Literal("node.updated"),
1801 payload: OrchestrationV2ExecutionNode,
1802 }),
1803 Schema.Struct({
1804 ...OrchestrationV2EventBase.fields,
1805 type: Schema.Literal("subagent.updated"),
1806 payload: OrchestrationV2Subagent,
1807 }),
1808 Schema.Struct({
1809 ...OrchestrationV2EventBase.fields,
1810 type: Schema.Literals(["provider-session.attached", "provider-session.updated"]),
1811 payload: OrchestrationV2ProviderSession,
1812 }),
1813 Schema.Struct({
1814 ...OrchestrationV2EventBase.fields,
1815 type: Schema.Literal("provider-session.detached"),
1816 payload: OrchestrationV2ProviderSessionDetached,
1817 }),
1818 Schema.Struct({
1819 ...OrchestrationV2EventBase.fields,
1820 type: Schema.Literal("provider-thread.updated"),
1821 payload: OrchestrationV2ProviderThread,
1822 }),
1823 Schema.Struct({
1824 ...OrchestrationV2EventBase.fields,
1825 type: Schema.Literal("provider-turn.updated"),
1826 payload: OrchestrationV2ProviderTurn,
1827 }),
1828 Schema.Struct({
1829 ...OrchestrationV2EventBase.fields,
1830 type: Schema.Literal("runtime-request.updated"),
1831 payload: OrchestrationV2RuntimeRequest,
1832 }),
1833 Schema.Struct({
1834 ...OrchestrationV2EventBase.fields,
1835 type: Schema.Literal("message.updated"),
1836 payload: OrchestrationV2ConversationMessage,
1837 }),
1838 Schema.Struct({
1839 ...OrchestrationV2EventBase.fields,
1840 type: Schema.Literal("turn-item.updated"),
1841 payload: OrchestrationV2TurnItem,
1842 }),
1843 Schema.Struct({
1844 ...OrchestrationV2EventBase.fields,
1845 type: Schema.Literal("plan.updated"),
1846 payload: OrchestrationV2PlanArtifact,
1847 }),
1848 Schema.Struct({
1849 ...OrchestrationV2EventBase.fields,
1850 type: Schema.Literal("checkpoint-scope.created"),
1851 payload: OrchestrationV2CheckpointScope,
1852 }),
1853 Schema.Struct({
1854 ...OrchestrationV2EventBase.fields,
1855 type: Schema.Literal("checkpoint.captured"),
1856 payload: OrchestrationV2Checkpoint,
1857 }),
1858 Schema.Struct({
1859 ...OrchestrationV2EventBase.fields,
1860 type: Schema.Literal("checkpoint.rollback-requested"),
1861 payload: OrchestrationV2CheckpointRollbackRequest,
1862 }),
1863 Schema.Struct({
1864 ...OrchestrationV2EventBase.fields,
1865 type: Schema.Literal("context-handoff.updated"),
1866 payload: OrchestrationV2ContextHandoff,
1867 }),
1868 Schema.Struct({
1869 ...OrchestrationV2EventBase.fields,
1870 type: Schema.Literal("context-transfer.created"),
1871 payload: OrchestrationV2ContextTransfer,
1872 }),
1873 Schema.Struct({
1874 ...OrchestrationV2EventBase.fields,
1875 type: Schema.Literal("context-transfer.updated"),
1876 payload: OrchestrationV2ContextTransfer,
1877 }),
1878]);
1879export type OrchestrationV2DomainEvent = typeof OrchestrationV2DomainEvent.Type;
1880
1881export const OrchestrationV2ThreadProjection = Schema.Struct({
1882 thread: OrchestrationV2AppThread,
1883 runs: Schema.Array(OrchestrationV2Run),
1884 attempts: Schema.Array(OrchestrationV2RunAttempt),
1885 nodes: Schema.Array(OrchestrationV2ExecutionNode),
1886 subagents: Schema.Array(OrchestrationV2Subagent),
1887 providerSessions: Schema.Array(OrchestrationV2ProviderSession),
1888 providerThreads: Schema.Array(OrchestrationV2ProviderThread),
1889 providerTurns: Schema.Array(OrchestrationV2ProviderTurn),
1890 runtimeRequests: Schema.Array(OrchestrationV2RuntimeRequest),
1891 messages: Schema.Array(OrchestrationV2ConversationMessage),
1892 plans: Schema.Array(OrchestrationV2PlanArtifact),
1893 turnItems: turnItemArray(OrchestrationV2TurnItem),
1894 checkpointScopes: Schema.Array(OrchestrationV2CheckpointScope),
1895 checkpoints: Schema.Array(OrchestrationV2Checkpoint),
1896 contextHandoffs: Schema.Array(OrchestrationV2ContextHandoff),
1897 contextTransfers: Schema.Array(OrchestrationV2ContextTransfer),
1898 visibleTurnItems: projectedTurnItemArray(
1899 OrchestrationV2ProjectedTurnItem,
1900 OrchestrationV2ProjectedTurnItem.mapFields((fields) => ({
1901 ...fields,
1902 item: ForwardCompatibleUnion(OrchestrationV2TurnItem.members, "type"),
1903 })),
1904 ),
1905 updatedAt: Schema.DateTimeUtc,
1906});
1907export type OrchestrationV2ThreadProjection = typeof OrchestrationV2ThreadProjection.Type;
1908
1909export const OrchestrationV2ThreadTranscript = Schema.Struct({
1910 threadId: ThreadId,
1911 title: Schema.String,
1912 updatedAt: Schema.DateTimeUtc,
1913 items: Schema.Array(OrchestrationV2ProjectedTurnItem),
1914});
1915export type OrchestrationV2ThreadTranscript = typeof OrchestrationV2ThreadTranscript.Type;
1916
1917export const OrchestrationV2ShellThreadStatus = Schema.Union([
1918 Schema.Literal("idle"),
1919 OrchestrationV2RunStatus,
1920]);
1921export type OrchestrationV2ShellThreadStatus = typeof OrchestrationV2ShellThreadStatus.Type;
1922
1923export const OrchestrationV2PendingRuntimeRequestSummary = Schema.Struct({
1924 id: RuntimeRequestId,
1925 kind: OrchestrationV2RuntimeRequest.fields.kind,
1926 createdAt: Schema.DateTimeUtc,
1927});
1928export type OrchestrationV2PendingRuntimeRequestSummary =
1929 typeof OrchestrationV2PendingRuntimeRequestSummary.Type;
1930
1931export const OrchestrationV2LatestVisibleMessageSummary = Schema.Struct({
1932 id: MessageId,
1933 role: OrchestrationV2ConversationMessage.fields.role,
1934 text: Schema.String,
1935 updatedAt: Schema.DateTimeUtc,
1936});
1937export type OrchestrationV2LatestVisibleMessageSummary =
1938 typeof OrchestrationV2LatestVisibleMessageSummary.Type;
1939
1940export const OrchestrationV2ThreadShell = Schema.Struct({
1941 ...OrchestrationV2CreationFields,
1942 id: ThreadId,
1943 projectId: ProjectId,
1944 title: Schema.String,
1945 providerInstanceId: ProviderInstanceId,
1946 modelSelection: ModelSelection,
1947 runtimeMode: RuntimeMode,
1948 interactionMode: ProviderInteractionMode,
1949 branch: Schema.NullOr(TrimmedNonEmptyString),
1950 worktreePath: Schema.NullOr(TrimmedNonEmptyString),
1951 /** Pull request the user linked to this thread (#8160). */
1952 linkedPullRequest: Schema.optional(Schema.NullOr(ThreadLinkedPullRequest)),
1953 pullRequests: Schema.optional(Schema.Array(ThreadPullRequestLink)),
1954 /** Pull request discovered from the thread's current branch. */
1955 branchPullRequest: Schema.optional(Schema.NullOr(ThreadLinkedPullRequest)),
1956 lineage: OrchestrationV2AppThreadLineage,
1957 forkedFrom: Schema.NullOr(OrchestrationV2AppThread.fields.forkedFrom),
1958 activeProviderThreadId: Schema.NullOr(ProviderThreadId),
1959 historyOrigin: Schema.optional(OrchestrationV2ThreadHistoryOrigin),
1960 latestRunId: Schema.NullOr(RunId),
1961 latestRunRequestedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
1962 latestRunStartedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
1963 latestRunCompletedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
1964 activeRunId: Schema.NullOr(RunId),
1965 /**
1966 * orchestrationV2RunWorkStartedAt of the activity-owning run: a wake keeps
1967 * the start of the work it continues; request time while preparing.
1968 */
1969 activityRunStartedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
1970 activityRunStatus: Schema.optional(
1971 Schema.NullOr(Schema.Literals(["preparing", "starting", "running", "waiting"])),
1972 ),
1973 status: OrchestrationV2ShellThreadStatus,
1974 lastError: Schema.optional(Schema.NullOr(Schema.String)),
1975 lastErrorClass: Schema.optional(Schema.NullOr(OrchestrationV2ProviderFailureClass)),
1976 usageLimitResetAt: Schema.optional(Schema.NullOr(IsoDateTime)),
1977 pendingRuntimeRequest: Schema.NullOr(OrchestrationV2PendingRuntimeRequestSummary),
1978 latestVisibleMessage: Schema.NullOr(OrchestrationV2LatestVisibleMessageSummary),
1979 latestUserMessageAt: Schema.NullOr(Schema.DateTimeUtc),
1980 /**
1981 * The last message the user wrote. Wakes and agent messages also use the
1982 * user role, so they move latestUserMessageAt but not this.
1983 */
1984 latestUserAuthoredMessageAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
1985 hasActionableProposedPlan: Schema.Boolean,
1986 // Normalized post-settlement background work for sidebar Waiting pills.
1987 // Empty when the latest root run is still active or no pending work remains.
1988 pendingBackgroundTasks: Schema.optional(Schema.Array(OrchestrationV2PendingBackgroundTask)).pipe(
1989 Schema.withDecodingDefault(Effect.succeed([])),
1990 ),
1991 // Distinct provider instances that have owned a root provider thread here,
1992 // in first-use order, so lists can show where a handed-off thread has been.
1993 // Omitted by servers that predate it; decodes to [].
1994 providerInstanceHistory: Schema.optional(Schema.Array(ProviderInstanceId)).pipe(
1995 Schema.withDecodingDefault(Effect.succeed([])),
1996 ),
1997 /** Native goal on the active provider thread; omitted by servers without goals. */
1998 goal: Schema.optional(Schema.NullOr(OrchestrationV2ProviderGoal)),
1999 itemCount: NonNegativeInt,
2000 visibleItemCount: NonNegativeInt,
2001 createdAt: Schema.DateTimeUtc,
2002 updatedAt: Schema.DateTimeUtc,
2003 archivedAt: Schema.NullOr(Schema.DateTimeUtc),
2004 settledOverride: Schema.NullOr(Schema.Literals(["settled", "active"])),
2005 settledAt: Schema.NullOr(Schema.DateTimeUtc),
2006 unsettledAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
2007 snoozedUntil: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
2008 snoozedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
2009 limitRecovery: Schema.optional(Schema.NullOr(OrchestrationV2LimitRecovery)),
2010 /** Omitted by servers that predate thread pinning. */
2011 pinnedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
2012 autoSettleDisabledAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
2013 /** Slot in the user-arranged pinned order; omitted by pre-reorder servers. */
2014 pinOrderKey: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),
2015 /** Slot in the user-arranged active order; omitted by pre-reorder servers. */
2016 activeOrderKey: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),
2017 /**
2018 * Omitted by servers that predate server-side visited tracking; clients fall
2019 * back to their local visited state when the field is absent.
2020 */
2021 lastVisitedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtc)),
2022 /** In-flight title regeneration marker; null/absent when no request is pending. */
2023 titleRegeneration: Schema.optional(
2024 Schema.NullOr(
2025 Schema.Struct({
2026 requestId: CommandId,
2027 startedAt: Schema.DateTimeUtc,
2028 }),
2029 ),
2030 ),
2031 deletedAt: Schema.NullOr(Schema.DateTimeUtc),
2032});
2033export type OrchestrationV2ThreadShell = typeof OrchestrationV2ThreadShell.Type;
2034
2035export const OrchestrationV2ThreadShellSnapshot = Schema.Struct({
2036 schemaVersion: PositiveInt,
2037 snapshotSequence: NonNegativeInt,
2038 threads: Schema.Array(OrchestrationV2ThreadShell),
2039 archivedThreads: Schema.Array(OrchestrationV2ThreadShell),
2040});
2041export type OrchestrationV2ThreadShellSnapshot = typeof OrchestrationV2ThreadShellSnapshot.Type;
2042
2043export const OrchestrationV2ShellSnapshot = Schema.Struct({
2044 ...OrchestrationV2ThreadShellSnapshot.fields,
2045 projects: Schema.Array(OrchestrationProjectShell),
2046});
2047export type OrchestrationV2ShellSnapshot = typeof OrchestrationV2ShellSnapshot.Type;
2048
2049export const OrchestrationV2ShellStreamItem = Schema.Union([
2050 Schema.Struct({
2051 kind: Schema.Literal("synchronized"),
2052 }),
2053 Schema.Struct({
2054 kind: Schema.Literal("snapshot"),
2055 snapshot: OrchestrationV2ShellSnapshot,
2056 /**
2057 * Workspace roots whose repository-identity resolution completed for this
2058 * enrichment refresh. Omitted on authoritative HTTP/initial WebSocket
2059 * snapshots. Older clients ignore the field.
2060 */
2061 resolvedRepositoryIdentityRoots: Schema.optionalKey(Schema.Array(Schema.String)),
2062 }),
2063 Schema.Struct({
2064 kind: Schema.Literal("project.updated"),
2065 sequence: NonNegativeInt,
2066 project: OrchestrationProjectShell,
2067 }),
2068 Schema.Struct({
2069 kind: Schema.Literal("project.removed"),
2070 sequence: NonNegativeInt,
2071 projectId: ProjectId,
2072 }),
2073 Schema.Struct({
2074 kind: Schema.Literal("thread.updated"),
2075 sequence: NonNegativeInt,
2076 location: Schema.Literals(["active", "archive"]),
2077 thread: OrchestrationV2ThreadShell,
2078 }),
2079 Schema.Struct({
2080 kind: Schema.Literal("thread.removed"),
2081 sequence: NonNegativeInt,
2082 location: Schema.Literals(["active", "archive"]),
2083 threadId: ThreadId,
2084 }),
2085]);
2086export type OrchestrationV2ShellStreamItem = typeof OrchestrationV2ShellStreamItem.Type;
2087
2088export const OrchestrationV2StoredEvent = Schema.Struct({
2089 sequence: NonNegativeInt,
2090 commandId: Schema.NullOr(CommandId),
2091 event: OrchestrationV2DomainEvent,
2092});
2093export type OrchestrationV2StoredEvent = typeof OrchestrationV2StoredEvent.Type;
2094
2095export const OrchestrationV2AppThreadJson = OrchestrationV2AppThread.mapFields((fields) => ({
2096 ...fields,
2097 createdAt: Schema.DateTimeUtcFromString,
2098 updatedAt: Schema.DateTimeUtcFromString,
2099 archivedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2100 settledAt: Schema.NullOr(Schema.DateTimeUtcFromString).pipe(
2101 Schema.withDecodingDefault(Effect.succeed(null)),
2102 ),
2103 unsettledAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2104 snoozedUntil: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2105 snoozedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2106 lastSnoozeWakeAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2107 pinnedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2108 autoSettleDisabledAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2109 lastVisitedAt: Schema.NullOr(Schema.DateTimeUtcFromString).pipe(
2110 Schema.withDecodingDefault(Effect.succeed(null)),
2111 ),
2112 titleRegeneration: Schema.optional(
2113 Schema.NullOr(
2114 Schema.Struct({
2115 requestId: CommandId,
2116 startedAt: Schema.DateTimeUtcFromString,
2117 }),
2118 ),
2119 ),
2120 deletedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2121}));
2122export type OrchestrationV2AppThreadJson = typeof OrchestrationV2AppThreadJson.Type;
2123
2124export const OrchestrationV2RunJson = OrchestrationV2Run.mapFields((fields) => ({
2125 ...fields,
2126 requestedAt: Schema.DateTimeUtcFromString,
2127 startedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2128 completedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2129 workStartedAt: Schema.optional(Schema.DateTimeUtcFromString),
2130}));
2131export type OrchestrationV2RunJson = typeof OrchestrationV2RunJson.Type;
2132
2133export const OrchestrationV2RunAttemptJson = OrchestrationV2RunAttempt.mapFields((fields) => ({
2134 ...fields,
2135 startedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2136 completedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2137}));
2138export type OrchestrationV2RunAttemptJson = typeof OrchestrationV2RunAttemptJson.Type;
2139
2140export const OrchestrationV2ExecutionNodeJson = OrchestrationV2ExecutionNode.mapFields(
2141 (fields) => ({
2142 ...fields,
2143 startedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2144 completedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2145 }),
2146);
2147export type OrchestrationV2ExecutionNodeJson = typeof OrchestrationV2ExecutionNodeJson.Type;
2148
2149export const OrchestrationV2SubagentJson = OrchestrationV2Subagent.mapFields((fields) => ({
2150 ...fields,
2151 startedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2152 completedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2153 updatedAt: Schema.DateTimeUtcFromString,
2154}));
2155export type OrchestrationV2SubagentJson = typeof OrchestrationV2SubagentJson.Type;
2156
2157export const OrchestrationV2CheckpointScopeJson = OrchestrationV2CheckpointScope.mapFields(
2158 (fields) => ({
2159 ...fields,
2160 createdAt: Schema.DateTimeUtcFromString,
2161 }),
2162);
2163export type OrchestrationV2CheckpointScopeJson = typeof OrchestrationV2CheckpointScopeJson.Type;
2164
2165export const OrchestrationV2ProviderSessionJson = OrchestrationV2ProviderSession.mapFields(
2166 (fields) => ({
2167 ...fields,
2168 createdAt: Schema.DateTimeUtcFromString,
2169 updatedAt: Schema.DateTimeUtcFromString,
2170 }),
2171);
2172export type OrchestrationV2ProviderSessionJson = typeof OrchestrationV2ProviderSessionJson.Type;
2173
2174export const OrchestrationV2ProviderSessionDetachedJson =
2175 OrchestrationV2ProviderSessionDetached.mapFields((fields) => ({
2176 ...fields,
2177 detachedAt: Schema.DateTimeUtcFromString,
2178 }));
2179export type OrchestrationV2ProviderSessionDetachedJson =
2180 typeof OrchestrationV2ProviderSessionDetachedJson.Type;
2181
2182export const OrchestrationV2ProviderThreadJson = OrchestrationV2ProviderThread.mapFields(
2183 (fields) => ({
2184 ...fields,
2185 createdAt: Schema.DateTimeUtcFromString,
2186 updatedAt: Schema.DateTimeUtcFromString,
2187 }),
2188);
2189export type OrchestrationV2ProviderThreadJson = typeof OrchestrationV2ProviderThreadJson.Type;
2190
2191export const OrchestrationV2ContextHandoffJson = OrchestrationV2ContextHandoff.mapFields(
2192 (fields) => ({
2193 ...fields,
2194 createdAt: Schema.DateTimeUtcFromString,
2195 updatedAt: Schema.DateTimeUtcFromString,
2196 }),
2197);
2198export type OrchestrationV2ContextHandoffJson = typeof OrchestrationV2ContextHandoffJson.Type;
2199
2200export const OrchestrationV2ContextTransferJson = OrchestrationV2ContextTransfer.mapFields(
2201 (fields) => ({
2202 ...fields,
2203 createdAt: Schema.DateTimeUtcFromString,
2204 updatedAt: Schema.DateTimeUtcFromString,
2205 consumedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2206 }),
2207);
2208export type OrchestrationV2ContextTransferJson = typeof OrchestrationV2ContextTransferJson.Type;
2209
2210export const OrchestrationV2ProviderTurnJson = OrchestrationV2ProviderTurn.mapFields((fields) => ({
2211 ...fields,
2212 startedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2213 completedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2214}));
2215export type OrchestrationV2ProviderTurnJson = typeof OrchestrationV2ProviderTurnJson.Type;
2216
2217export const OrchestrationV2RuntimeRequestJson = OrchestrationV2RuntimeRequest.mapFields(
2218 (fields) => ({
2219 ...fields,
2220 createdAt: Schema.DateTimeUtcFromString,
2221 resolvedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2222 }),
2223);
2224export type OrchestrationV2RuntimeRequestJson = typeof OrchestrationV2RuntimeRequestJson.Type;
2225
2226export const OrchestrationV2ConversationMessageJson = OrchestrationV2ConversationMessage.mapFields(
2227 (fields) => ({
2228 ...fields,
2229 createdAt: Schema.DateTimeUtcFromString,
2230 updatedAt: Schema.DateTimeUtcFromString,
2231 }),
2232);
2233export type OrchestrationV2ConversationMessageJson =
2234 typeof OrchestrationV2ConversationMessageJson.Type;
2235
2236export const OrchestrationV2CheckpointJson = OrchestrationV2Checkpoint.mapFields((fields) => ({
2237 ...fields,
2238 capturedAt: Schema.DateTimeUtcFromString,
2239}));
2240export type OrchestrationV2CheckpointJson = typeof OrchestrationV2CheckpointJson.Type;
2241
2242export const OrchestrationV2CheckpointRollbackRequestJson =
2243 OrchestrationV2CheckpointRollbackRequest.mapFields((fields) => ({
2244 ...fields,
2245 requestedAt: Schema.DateTimeUtcFromString,
2246 }));
2247
2248const OrchestrationV2TurnItemJsonBaseFields = {
2249 ...OrchestrationV2TurnItemBaseFields,
2250 startedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2251 completedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2252 updatedAt: Schema.DateTimeUtcFromString,
2253} as const;
2254
2255export const OrchestrationV2TurnItemJson = Schema.Union([
2256 Schema.Struct({
2257 ...OrchestrationV2TurnItemJsonBaseFields,
2258 type: Schema.Literal("notification"),
2259 ...OrchestrationV2Notification.fields,
2260 }),
2261 Schema.Struct({
2262 ...OrchestrationV2TurnItemJsonBaseFields,
2263 ...OrchestrationV2CreationFields,
2264 type: Schema.Literal("user_message"),
2265 messageId: MessageId,
2266 scheduledTaskId: Schema.optional(ScheduledTaskId),
2267 senderThreadId: Schema.optional(ThreadId),
2268 inputIntent: OrchestrationV2UserMessageInputIntent,
2269 text: Schema.String,
2270 context: Schema.optional(OrchestrationMessageContext),
2271 attachments: Schema.Array(ChatAttachment),
2272 }),
2273 Schema.Struct({
2274 ...OrchestrationV2TurnItemJsonBaseFields,
2275 type: Schema.Literal("assistant_message"),
2276 messageId: MessageId,
2277 text: Schema.String,
2278 attachments: Schema.optional(Schema.Array(ChatAttachment)),
2279 streaming: Schema.Boolean,
2280 }),
2281 Schema.Struct({
2282 ...OrchestrationV2TurnItemJsonBaseFields,
2283 type: Schema.Literal("reasoning"),
2284 text: Schema.String,
2285 streaming: Schema.Boolean,
2286 }),
2287 Schema.Struct({
2288 ...OrchestrationV2TurnItemJsonBaseFields,
2289 type: Schema.Literal("proposed_plan"),
2290 planId: PlanId,
2291 markdown: Schema.String,
2292 streaming: Schema.Boolean,
2293 }),
2294 Schema.Struct({
2295 ...OrchestrationV2TurnItemJsonBaseFields,
2296 type: Schema.Literal("todo_list"),
2297 planId: PlanId,
2298 steps: Schema.Array(OrchestrationV2PlanStep),
2299 explanation: Schema.optional(Schema.String),
2300 }),
2301 Schema.Struct({
2302 ...OrchestrationV2TurnItemJsonBaseFields,
2303 type: Schema.Literal("user_input_request"),
2304 requestId: RuntimeRequestId,
2305 questions: Schema.Array(OrchestrationV2UserInputQuestion),
2306 questionAnswer: Schema.optional(UserInputAttachmentAnswerPayload),
2307 responseMode: Schema.optional(Schema.Literal("message")),
2308 }),
2309 Schema.Struct({
2310 ...OrchestrationV2TurnItemJsonBaseFields,
2311 type: Schema.Literal("file_change"),
2312 fileName: TrimmedNonEmptyString,
2313 additions: Schema.optional(NonNegativeInt),
2314 deletions: Schema.optional(NonNegativeInt),
2315 diffStr: Schema.optional(Schema.String),
2316 oldStr: Schema.optional(Schema.String),
2317 newStr: Schema.optional(Schema.String),
2318 changes: Schema.optional(Schema.Array(OrchestrationV2FileChangeDetail)),
2319 }),
2320 Schema.Struct({
2321 ...OrchestrationV2TurnItemJsonBaseFields,
2322 type: Schema.Literal("command_execution"),
2323 input: Schema.String,
2324 output: Schema.optional(Schema.String),
2325 /** Set on the wire when output was withheld; fetch it with getTurnItem. */
2326 outputOmitted: Schema.optional(Schema.Boolean),
2327 outputIndicatesFailure: Schema.optional(Schema.Boolean),
2328 exitCode: Schema.optional(Schema.Int),
2329 }),
2330 Schema.Struct({
2331 ...OrchestrationV2TurnItemJsonBaseFields,
2332 type: Schema.Literal("file_search"),
2333 pattern: Schema.optional(Schema.String),
2334 results: Schema.optional(Schema.Array(OrchestrationV2FileSearchResult)),
2335 }),
2336 Schema.Struct({
2337 ...OrchestrationV2TurnItemJsonBaseFields,
2338 type: Schema.Literal("web_search"),
2339 patterns: Schema.optional(Schema.Array(Schema.String)),
2340 results: Schema.optional(Schema.Array(OrchestrationV2WebSearchResult)),
2341 }),
2342 Schema.Struct({
2343 ...OrchestrationV2TurnItemJsonBaseFields,
2344 type: Schema.Literal("approval_request"),
2345 requestId: RuntimeRequestId,
2346 requestKind: ProviderRequestKind,
2347 prompt: Schema.optional(Schema.String),
2348 /** App requesting access, for mcp-elicitation approvals (#8058). */
2349 appName: Schema.optional(Schema.String),
2350 /** Approval choices advertised by the provider (#8058). */
2351 options: Schema.optional(Schema.Array(ProviderApprovalOption)),
2352 }),
2353 Schema.Struct({
2354 ...OrchestrationV2TurnItemJsonBaseFields,
2355 type: Schema.Literal("checkpoint"),
2356 checkpointId: CheckpointId,
2357 scopeId: CheckpointScopeId,
2358 files: Schema.Array(OrchestrationV2CheckpointFileSummary),
2359 }),
2360 Schema.Struct({
2361 ...OrchestrationV2TurnItemJsonBaseFields,
2362 type: Schema.Literal("run_interrupt_request"),
2363 message: Schema.String,
2364 }),
2365 Schema.Struct({
2366 ...OrchestrationV2TurnItemJsonBaseFields,
2367 type: Schema.Literal("run_interrupt_result"),
2368 message: Schema.String,
2369 }),
2370 Schema.Struct({
2371 ...OrchestrationV2TurnItemJsonBaseFields,
2372 type: Schema.Literal("system_notice"),
2373 message: Schema.String,
2374 }),
2375 Schema.Struct({
2376 ...OrchestrationV2TurnItemJsonBaseFields,
2377 type: Schema.Literal("error"),
2378 failure: OrchestrationV2ProviderFailure,
2379 retry: Schema.optional(OrchestrationV2ProviderRetry),
2380 }),
2381 Schema.Struct({
2382 ...OrchestrationV2TurnItemJsonBaseFields,
2383 type: Schema.Literal("compaction"),
2384 driver: Schema.NullOr(ProviderDriverKind),
2385 summary: Schema.optional(Schema.String),
2386 beforeTokenCount: Schema.optional(NonNegativeInt),
2387 afterTokenCount: Schema.optional(NonNegativeInt),
2388 }),
2389 Schema.Struct({
2390 ...OrchestrationV2TurnItemJsonBaseFields,
2391 type: Schema.Literal("handoff"),
2392 contextHandoffId: ContextHandoffId,
2393 fromProviderThreadIds: Schema.Array(ProviderThreadId),
2394 toProviderThreadId: ProviderThreadId,
2395 fromProviderInstanceIds: Schema.Array(ProviderInstanceId),
2396 toProviderInstanceId: ProviderInstanceId,
2397 fromModelSelections: Schema.optional(Schema.Array(ModelSelection)),
2398 toModel: Schema.optional(Schema.String),
2399 strategy: Schema.Literals([
2400 "delta_since_target_last_seen",
2401 "fork_delta_summary",
2402 "full_thread_summary",
2403 "checkpoint_summary",
2404 "manual_context",
2405 ]),
2406 summary: Schema.optional(Schema.String),
2407 }),
2408 Schema.Struct({
2409 ...OrchestrationV2TurnItemJsonBaseFields,
2410 type: Schema.Literal("fork"),
2411 source: Schema.Union([
2412 Schema.Struct({ type: Schema.Literal("run"), threadId: ThreadId, runId: RunId }),
2413 Schema.Struct({ type: Schema.Literal("node"), nodeId: NodeId }),
2414 Schema.Struct({
2415 type: Schema.Literal("provider_thread"),
2416 providerThreadId: ProviderThreadId,
2417 providerTurnId: Schema.optional(ProviderTurnId),
2418 }),
2419 ]),
2420 targetThreadId: ThreadId,
2421 providerThreadId: Schema.optional(ProviderThreadId),
2422 }),
2423 Schema.Struct({
2424 ...OrchestrationV2TurnItemJsonBaseFields,
2425 type: Schema.Literal("thread_created"),
2426 targetThreadId: ThreadId,
2427 targetRunId: Schema.NullOr(RunId),
2428 targetProviderInstanceId: ProviderInstanceId,
2429 targetModel: TrimmedNonEmptyString,
2430 }),
2431 Schema.Struct({
2432 ...OrchestrationV2TurnItemJsonBaseFields,
2433 ...OrchestrationV2SecretRequestFields,
2434 }),
2435 Schema.Struct({
2436 ...OrchestrationV2TurnItemJsonBaseFields,
2437 type: Schema.Literal("subagent"),
2438 subagentId: NodeId,
2439 origin: Schema.Literals(["provider_native", "app_owned"]),
2440 driver: ProviderDriverKind,
2441 providerInstanceId: ProviderInstanceId,
2442 childThreadId: Schema.NullOr(ThreadId),
2443 prompt: Schema.String,
2444 progress: Schema.optional(Schema.String),
2445 result: Schema.NullOr(Schema.String),
2446 }),
2447 Schema.Struct({
2448 ...OrchestrationV2TurnItemJsonBaseFields,
2449 type: Schema.Literal("dynamic_tool"),
2450 toolName: Schema.NullOr(TrimmedNonEmptyString),
2451 viewedImagePath: Schema.optional(TrimmedNonEmptyString),
2452 input: Schema.Unknown,
2453 output: Schema.optional(Schema.Unknown),
2454 /** Set on the wire when output was withheld; fetch it with getTurnItem. */
2455 outputOmitted: Schema.optional(Schema.Boolean),
2456 }),
2457]);
2458export type OrchestrationV2TurnItemJson = typeof OrchestrationV2TurnItemJson.Type;
2459
2460export const OrchestrationV2ProjectedTurnItemJson = OrchestrationV2ProjectedTurnItem.mapFields(
2461 (fields) => ({
2462 ...fields,
2463 item: OrchestrationV2TurnItemJson,
2464 }),
2465);
2466export type OrchestrationV2ProjectedTurnItemJson = typeof OrchestrationV2ProjectedTurnItemJson.Type;
2467
2468export const OrchestrationV2ThreadProjectionJson = OrchestrationV2ThreadProjection.mapFields(
2469 (fields) => ({
2470 ...fields,
2471 thread: OrchestrationV2AppThreadJson,
2472 runs: Schema.Array(OrchestrationV2RunJson),
2473 attempts: Schema.Array(OrchestrationV2RunAttemptJson),
2474 nodes: Schema.Array(OrchestrationV2ExecutionNodeJson),
2475 subagents: Schema.Array(OrchestrationV2SubagentJson),
2476 providerSessions: Schema.Array(OrchestrationV2ProviderSessionJson),
2477 providerThreads: Schema.Array(OrchestrationV2ProviderThreadJson),
2478 providerTurns: Schema.Array(OrchestrationV2ProviderTurnJson),
2479 runtimeRequests: Schema.Array(OrchestrationV2RuntimeRequestJson),
2480 messages: Schema.Array(OrchestrationV2ConversationMessageJson),
2481 plans: Schema.Array(OrchestrationV2PlanArtifact),
2482 turnItems: turnItemArray(OrchestrationV2TurnItemJson),
2483 checkpointScopes: Schema.Array(OrchestrationV2CheckpointScopeJson),
2484 checkpoints: Schema.Array(OrchestrationV2CheckpointJson),
2485 contextHandoffs: Schema.Array(OrchestrationV2ContextHandoffJson),
2486 contextTransfers: Schema.Array(OrchestrationV2ContextTransferJson),
2487 visibleTurnItems: projectedTurnItemArray(
2488 OrchestrationV2ProjectedTurnItemJson,
2489 OrchestrationV2ProjectedTurnItemJson.mapFields((fields) => ({
2490 ...fields,
2491 item: ForwardCompatibleUnion(OrchestrationV2TurnItemJson.members, "type"),
2492 })),
2493 ),
2494 updatedAt: Schema.DateTimeUtcFromString,
2495 }),
2496);
2497export type OrchestrationV2ThreadProjectionJson = typeof OrchestrationV2ThreadProjectionJson.Type;
2498
2499export const OrchestrationV2PendingRuntimeRequestSummaryJson =
2500 OrchestrationV2PendingRuntimeRequestSummary.mapFields((fields) => ({
2501 ...fields,
2502 createdAt: Schema.DateTimeUtcFromString,
2503 }));
2504export type OrchestrationV2PendingRuntimeRequestSummaryJson =
2505 typeof OrchestrationV2PendingRuntimeRequestSummaryJson.Type;
2506
2507export const OrchestrationV2LatestVisibleMessageSummaryJson =
2508 OrchestrationV2LatestVisibleMessageSummary.mapFields((fields) => ({
2509 ...fields,
2510 updatedAt: Schema.DateTimeUtcFromString,
2511 }));
2512export type OrchestrationV2LatestVisibleMessageSummaryJson =
2513 typeof OrchestrationV2LatestVisibleMessageSummaryJson.Type;
2514
2515export const OrchestrationV2ThreadShellJson = OrchestrationV2ThreadShell.mapFields((fields) => ({
2516 ...fields,
2517 latestRunRequestedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2518 latestRunStartedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2519 latestRunCompletedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2520 activityRunStartedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2521 pendingRuntimeRequest: Schema.NullOr(OrchestrationV2PendingRuntimeRequestSummaryJson),
2522 latestVisibleMessage: Schema.NullOr(OrchestrationV2LatestVisibleMessageSummaryJson),
2523 latestUserMessageAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2524 latestUserAuthoredMessageAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2525 createdAt: Schema.DateTimeUtcFromString,
2526 updatedAt: Schema.DateTimeUtcFromString,
2527 archivedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2528 settledAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2529 unsettledAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2530 snoozedUntil: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2531 snoozedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2532 pinnedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2533 autoSettleDisabledAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2534 lastVisitedAt: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)),
2535 titleRegeneration: Schema.optional(
2536 Schema.NullOr(
2537 Schema.Struct({
2538 requestId: CommandId,
2539 startedAt: Schema.DateTimeUtcFromString,
2540 }),
2541 ),
2542 ),
2543 deletedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
2544}));
2545export type OrchestrationV2ThreadShellJson = typeof OrchestrationV2ThreadShellJson.Type;
2546
2547export const OrchestrationV2ShellSnapshotJson = OrchestrationV2ShellSnapshot.mapFields(
2548 (fields) => ({
2549 ...fields,
2550 threads: Schema.Array(OrchestrationV2ThreadShellJson),
2551 archivedThreads: Schema.Array(OrchestrationV2ThreadShellJson),
2552 }),
2553);
2554export type OrchestrationV2ShellSnapshotJson = typeof OrchestrationV2ShellSnapshotJson.Type;
2555
2556const OrchestrationV2JsonEventBaseFields = {
2557 ...OrchestrationV2EventBase.fields,
2558 occurredAt: Schema.DateTimeUtcFromString,
2559} as const;
2560
2561export const OrchestrationV2RawProviderEventJson = OrchestrationV2RawProviderEvent.mapFields(
2562 (fields) => ({
2563 ...fields,
2564 observedAt: Schema.DateTimeUtcFromString,
2565 }),
2566);
2567export type OrchestrationV2RawProviderEventJson = typeof OrchestrationV2RawProviderEventJson.Type;
2568
2569export const OrchestrationV2DomainEventJson = Schema.Union([
2570 Schema.Struct({
2571 ...OrchestrationV2JsonEventBaseFields,
2572 type: Schema.Literal("thread.created"),
2573 payload: OrchestrationV2AppThreadJson,
2574 }),
2575 Schema.Struct({
2576 ...OrchestrationV2JsonEventBaseFields,
2577 type: Schema.Literals([
2578 "thread.archived",
2579 "thread.unarchived",
2580 "thread.deleted",
2581 "thread.settled",
2582 "thread.unsettled",
2583 "thread.snoozed",
2584 "thread.unsnoozed",
2585 "thread.pinned",
2586 "thread.auto-settle-set",
2587 "thread.unpinned",
2588 "thread.pin-reordered",
2589 "thread.active-reordered",
2590 "thread.visited",
2591 "thread.marked-unread",
2592 "thread.pull-request-synced",
2593 "thread.metadata-updated",
2594 "thread.runtime-mode-updated",
2595 "thread.interaction-mode-updated",
2596 "thread.model-selection-updated",
2597 "thread.provider-switched",
2598 ]),
2599 payload: OrchestrationV2AppThreadJson,
2600 }),
2601 Schema.Struct({
2602 ...OrchestrationV2JsonEventBaseFields,
2603 type: Schema.Literal("thread.pull-request-link-updated"),
2604 payload: ThreadPullRequestLink,
2605 }),
2606 Schema.Struct({
2607 ...OrchestrationV2JsonEventBaseFields,
2608 type: Schema.Literal("run.created"),
2609 payload: OrchestrationV2RunJson,
2610 }),
2611 Schema.Struct({
2612 ...OrchestrationV2JsonEventBaseFields,
2613 type: Schema.Literal("run.updated"),
2614 payload: OrchestrationV2RunJson,
2615 }),
2616 Schema.Struct({
2617 ...OrchestrationV2JsonEventBaseFields,
2618 type: Schema.Literal("run.background-work-cancelled"),
2619 payload: OrchestrationV2RunBackgroundWorkCancelled,
2620 }),
2621 Schema.Struct({
2622 ...OrchestrationV2JsonEventBaseFields,
2623 type: Schema.Literal("run-attempt.created"),
2624 payload: OrchestrationV2RunAttemptJson,
2625 }),
2626 Schema.Struct({
2627 ...OrchestrationV2JsonEventBaseFields,
2628 type: Schema.Literal("run-attempt.updated"),
2629 payload: OrchestrationV2RunAttemptJson,
2630 }),
2631 Schema.Struct({
2632 ...OrchestrationV2JsonEventBaseFields,
2633 type: Schema.Literal("node.updated"),
2634 payload: OrchestrationV2ExecutionNodeJson,
2635 }),
2636 Schema.Struct({
2637 ...OrchestrationV2JsonEventBaseFields,
2638 type: Schema.Literal("subagent.updated"),
2639 payload: OrchestrationV2SubagentJson,
2640 }),
2641 Schema.Struct({
2642 ...OrchestrationV2JsonEventBaseFields,
2643 type: Schema.Literals(["provider-session.attached", "provider-session.updated"]),
2644 payload: OrchestrationV2ProviderSessionJson,
2645 }),
2646 Schema.Struct({
2647 ...OrchestrationV2JsonEventBaseFields,
2648 type: Schema.Literal("provider-session.detached"),
2649 payload: OrchestrationV2ProviderSessionDetachedJson,
2650 }),
2651 Schema.Struct({
2652 ...OrchestrationV2JsonEventBaseFields,
2653 type: Schema.Literal("provider-thread.updated"),
2654 payload: OrchestrationV2ProviderThreadJson,
2655 }),
2656 Schema.Struct({
2657 ...OrchestrationV2JsonEventBaseFields,
2658 type: Schema.Literal("provider-turn.updated"),
2659 payload: OrchestrationV2ProviderTurnJson,
2660 }),
2661 Schema.Struct({
2662 ...OrchestrationV2JsonEventBaseFields,
2663 type: Schema.Literal("runtime-request.updated"),
2664 payload: OrchestrationV2RuntimeRequestJson,
2665 }),
2666 Schema.Struct({
2667 ...OrchestrationV2JsonEventBaseFields,
2668 type: Schema.Literal("message.updated"),
2669 payload: OrchestrationV2ConversationMessageJson,
2670 }),
2671 Schema.Struct({
2672 ...OrchestrationV2JsonEventBaseFields,
2673 type: Schema.Literal("turn-item.updated"),
2674 payload: OrchestrationV2TurnItemJson,
2675 }),
2676 Schema.Struct({
2677 ...OrchestrationV2JsonEventBaseFields,
2678 type: Schema.Literal("plan.updated"),
2679 payload: OrchestrationV2PlanArtifact,
2680 }),
2681 Schema.Struct({
2682 ...OrchestrationV2JsonEventBaseFields,
2683 type: Schema.Literal("checkpoint-scope.created"),
2684 payload: OrchestrationV2CheckpointScopeJson,
2685 }),
2686 Schema.Struct({
2687 ...OrchestrationV2JsonEventBaseFields,
2688 type: Schema.Literal("checkpoint.captured"),
2689 payload: OrchestrationV2CheckpointJson,
2690 }),
2691 Schema.Struct({
2692 ...OrchestrationV2JsonEventBaseFields,
2693 type: Schema.Literal("checkpoint.rollback-requested"),
2694 payload: OrchestrationV2CheckpointRollbackRequestJson,
2695 }),
2696 Schema.Struct({
2697 ...OrchestrationV2JsonEventBaseFields,
2698 type: Schema.Literal("context-handoff.updated"),
2699 payload: OrchestrationV2ContextHandoffJson,
2700 }),
2701 Schema.Struct({
2702 ...OrchestrationV2JsonEventBaseFields,
2703 type: Schema.Literal("context-transfer.created"),
2704 payload: OrchestrationV2ContextTransferJson,
2705 }),
2706 Schema.Struct({
2707 ...OrchestrationV2JsonEventBaseFields,
2708 type: Schema.Literal("context-transfer.updated"),
2709 payload: OrchestrationV2ContextTransferJson,
2710 }),
2711]);
2712export type OrchestrationV2DomainEventJson = typeof OrchestrationV2DomainEventJson.Type;
2713
2714export const OrchestrationV2StoredEventJson = Schema.Struct({
2715 sequence: NonNegativeInt,
2716 commandId: Schema.NullOr(CommandId),
2717 event: OrchestrationV2DomainEventJson,
2718});
2719export type OrchestrationV2StoredEventJson = typeof OrchestrationV2StoredEventJson.Type;
2720
2721export const OrchestrationV2Command = Schema.Union([
2722 Schema.Struct({
2723 type: Schema.Literal("thread.create"),
2724 ...OrchestrationV2CreationFields,
2725 commandId: CommandId,
2726 threadId: ThreadId,
2727 projectId: ProjectId,
2728 title: TrimmedNonEmptyString,
2729 modelSelection: ModelSelection,
2730 runtimeMode: RuntimeMode,
2731 interactionMode: ProviderInteractionMode,
2732 branch: Schema.NullOr(TrimmedNonEmptyString),
2733 worktreePath: Schema.NullOr(TrimmedNonEmptyString),
2734 importedNativeThread: Schema.optional(
2735 Schema.Struct({
2736 ref: Schema.Struct({
2737 driver: ProviderDriverKind,
2738 nativeId: TrimmedNonEmptyString,
2739 strength: Schema.Literal("strong"),
2740 }),
2741 metadata: Schema.optional(OrchestrationV2ProviderThreadNativeMetadata),
2742 }),
2743 ),
2744 }),
2745 Schema.Struct({
2746 type: Schema.Literal("thread.archive"),
2747 commandId: CommandId,
2748 threadId: ThreadId,
2749 snapshotSequence: Schema.optional(NonNegativeInt),
2750 }),
2751 Schema.Struct({
2752 type: Schema.Literal("thread.unarchive"),
2753 commandId: CommandId,
2754 threadId: ThreadId,
2755 }),
2756 Schema.Struct({
2757 type: Schema.Literal("thread.delete"),
2758 commandId: CommandId,
2759 threadId: ThreadId,
2760 }),
2761 Schema.Struct({
2762 type: Schema.Literal("thread.settle"),
2763 commandId: CommandId,
2764 threadId: ThreadId,
2765 settledAt: Schema.optional(Schema.DateTimeUtc),
2766 }),
2767 /**
2768 * Server-internal settlement (#8600): dispatched by the settlement sweep,
2769 * never by clients. Rejected when the thread changed after `snapshotAt` or
2770 * carries any explicit settled override, so automatic settlement can never
2771 * race a user action or clobber an explicit un-settle.
2772 */
2773 Schema.Struct({
2774 type: Schema.Literal("thread.auto-settle"),
2775 commandId: CommandId,
2776 threadId: ThreadId,
2777 snapshotAt: Schema.DateTimeUtc,
2778 settledAt: Schema.optional(Schema.DateTimeUtc),
2779 }),
2780 Schema.Struct({
2781 type: Schema.Literal("thread.unsettle"),
2782 commandId: CommandId,
2783 threadId: ThreadId,
2784 reason: Schema.Literal("user"),
2785 snapshotSequence: Schema.optional(NonNegativeInt),
2786 }),
2787 Schema.Struct({
2788 type: Schema.Literal("thread.snooze"),
2789 commandId: CommandId,
2790 threadId: ThreadId,
2791 snoozedUntil: IsoDateTime,
2792 }),
2793 Schema.Struct({
2794 type: Schema.Literal("thread.unsnooze"),
2795 commandId: CommandId,
2796 threadId: ThreadId,
2797 reason: Schema.Literal("user"),
2798 }),
2799 Schema.Struct({
2800 type: Schema.Literal("thread.auto-settle.set"),
2801 commandId: CommandId,
2802 threadId: ThreadId,
2803 enabled: Schema.Boolean,
2804 }),
2805 Schema.Struct({
2806 type: Schema.Literal("thread.pin"),
2807 commandId: CommandId,
2808 threadId: ThreadId,
2809 // Initial slot in the user-arranged pinned order (see thread.pin.reorder).
2810 // Optional: clients on pre-reorder servers omit it, and the pinned block
2811 // falls back to creation order for keyless threads.
2812 orderKey: Schema.optional(TrimmedNonEmptyString),
2813 }),
2814 Schema.Struct({
2815 type: Schema.Literal("thread.unpin"),
2816 commandId: CommandId,
2817 threadId: ThreadId,
2818 }),
2819 Schema.Struct({
2820 type: Schema.Literal("thread.pin.reorder"),
2821 commandId: CommandId,
2822 threadId: ThreadId,
2823 // Fractional-index key: pinned threads sort lexicographically by these
2824 // keys, so a drag writes one key to one thread — neighbors are never
2825 // touched. Clients compute a key that sorts between the dropped
2826 // position's neighbors.
2827 orderKey: TrimmedNonEmptyString,
2828 }),
2829 Schema.Struct({
2830 type: Schema.Literal("thread.active.reorder"),
2831 commandId: CommandId,
2832 threadId: ThreadId,
2833 orderKey: TrimmedNonEmptyString,
2834 }),
2835 Schema.Struct({
2836 type: Schema.Literal("thread.visit"),
2837 commandId: CommandId,
2838 threadId: ThreadId,
2839 /**
2840 * Watermark of the thread state the viewer has seen (typically the shell's
2841 * updatedAt). The server keeps the maximum of the stored and supplied
2842 * values, so replays and out-of-order deliveries cannot move it backwards.
2843 */
2844 visitedAt: IsoDateTime,
2845 }),
2846 Schema.Struct({
2847 type: Schema.Literal("thread.mark-unread"),
2848 commandId: CommandId,
2849 threadId: ThreadId,
2850 }),
2851 Schema.Struct({
2852 type: Schema.Literal("thread.metadata.update"),
2853 commandId: CommandId,
2854 threadId: ThreadId,
2855 title: Schema.optional(TrimmedNonEmptyString),
2856 /** Kick off (true) or abandon (false) an async title regeneration. */
2857 regenerateTitle: Schema.optional(Schema.Boolean),
2858 branch: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),
2859 worktreePath: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),
2860 expectedWorktreePath: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),
2861 /** Reject unless no message or run has landed on this thread. */
2862 expectedEmpty: Schema.optional(Schema.Boolean),
2863 limitRecovery: Schema.optional(Schema.NullOr(OrchestrationV2LimitRecoveryUpdate)),
2864 /** Link (object) or unlink (null) a pull request (#8160); absent leaves it unchanged. */
2865 linkedPullRequest: Schema.optional(Schema.NullOr(ThreadLinkedPullRequest)),
2866 }),
2867 Schema.Struct({
2868 type: Schema.Literal("thread.pull-request.link"),
2869 commandId: CommandId,
2870 threadId: ThreadId,
2871 ...ThreadPullRequestKey.fields,
2872 url: TrimmedNonEmptyString,
2873 source: ThreadPullRequestLinkSource,
2874 }),
2875 Schema.Struct({
2876 type: Schema.Literal("thread.pull-request.unlink"),
2877 commandId: CommandId,
2878 threadId: ThreadId,
2879 ...ThreadPullRequestKey.fields,
2880 }),
2881 Schema.Struct({
2882 type: Schema.Literal("thread.pull-request-link.sync"),
2883 commandId: CommandId,
2884 threadId: ThreadId,
2885 ...ThreadPullRequestKey.fields,
2886 snapshot: ThreadPullRequestSnapshot,
2887 stack: Schema.NullOr(ThreadPullRequestStack),
2888 }),
2889 /** Start or stop the server watching a linked pull request for this thread's agent. */
2890 Schema.Struct({
2891 type: Schema.Literal("thread.pull-request.watch"),
2892 commandId: CommandId,
2893 threadId: ThreadId,
2894 ...ThreadPullRequestKey.fields,
2895 watching: Schema.Boolean,
2896 /** Links the pull request first when starting a watch on one the thread has not linked. */
2897 link: Schema.optional(
2898 Schema.Struct({ url: TrimmedNonEmptyString, source: ThreadPullRequestLinkSource }),
2899 ),
2900 }),
2901 Schema.Struct({
2902 type: Schema.Literal("thread.pull-request.sync"),
2903 commandId: CommandId,
2904 threadId: ThreadId,
2905 projectId: ProjectId,
2906 snapshotSequence: NonNegativeInt,
2907 expected: Schema.Struct({
2908 workspaceRoot: TrimmedNonEmptyString,
2909 branch: Schema.NullOr(TrimmedNonEmptyString),
2910 worktreePath: Schema.NullOr(TrimmedNonEmptyString),
2911 linkedPullRequest: Schema.NullOr(ThreadLinkedPullRequest),
2912 branchPullRequest: Schema.NullOr(ThreadLinkedPullRequest),
2913 }),
2914 branchPullRequest: Schema.NullOr(ThreadLinkedPullRequest),
2915 linkedPullRequest: Schema.optional(ThreadLinkedPullRequest),
2916 }),
2917 Schema.Struct({
2918 type: Schema.Literal("thread.title.regeneration.complete"),
2919 commandId: CommandId,
2920 threadId: ThreadId,
2921 requestId: CommandId,
2922 title: Schema.optional(TrimmedNonEmptyString),
2923 }),
2924 Schema.Struct({
2925 type: Schema.Literal("thread.runtime-mode.set"),
2926 commandId: CommandId,
2927 threadId: ThreadId,
2928 runtimeMode: RuntimeMode,
2929 }),
2930 Schema.Struct({
2931 type: Schema.Literal("thread.interaction-mode.set"),
2932 commandId: CommandId,
2933 threadId: ThreadId,
2934 interactionMode: ProviderInteractionMode,
2935 }),
2936 Schema.Struct({
2937 type: Schema.Literal("thread.model-selection.set"),
2938 commandId: CommandId,
2939 threadId: ThreadId,
2940 modelSelection: ModelSelection,
2941 }),
2942 Schema.Struct({
2943 type: Schema.Literal("provider-session.detach"),
2944 commandId: CommandId,
2945 threadId: ThreadId,
2946 providerSessionId: ProviderSessionId,
2947 reason: Schema.optional(Schema.String),
2948 }),
2949 Schema.Struct({
2950 type: Schema.Literal("message.dispatch"),
2951 notification: Schema.optional(OrchestrationV2Notification),
2952 ...OrchestrationV2CreationFields,
2953 scheduledTaskId: Schema.optional(ScheduledTaskId),
2954 senderThreadId: Schema.optional(ThreadId),
2955 commandId: CommandId,
2956 threadId: ThreadId,
2957 messageId: MessageId,
2958 text: Schema.String,
2959 context: Schema.optional(OrchestrationMessageContext),
2960 attachments: Schema.Array(ChatAttachment),
2961 /** Seed the temporary title and generate a durable replacement for the first message. */
2962 titleSeed: Schema.optional(TrimmedNonEmptyString),
2963 modelSelection: Schema.optional(ModelSelection),
2964 sourcePlanRef: Schema.optional(Schema.Struct({ threadId: ThreadId, planId: PlanId })),
2965 restartContinuationOfRunId: Schema.optional(RunId),
2966 usageLimitContinuationOfRunId: Schema.optional(RunId),
2967 manualContinuationOfRunId: Schema.optional(RunId),
2968 usageLimitRecoveryRequestId: Schema.optional(CommandId),
2969 /** Resolve untargeted delivery against the server's serialized thread state. */
2970 deliveryIntent: Schema.optional(Schema.Literals(["auto", "steer", "restart"])),
2971 delegatedCompletion: Schema.optional(
2972 Schema.Struct({
2973 parentRunId: RunId,
2974 generation: PositiveInt,
2975 taskIds: Schema.Array(NodeId),
2976 }),
2977 ),
2978 dispatchMode: Schema.Union([
2979 Schema.Struct({
2980 type: Schema.Literal("defer_start"),
2981 workspaceStrategy: Schema.optional(OrchestrationV2ThreadLaunchWorkspaceStrategy),
2982 }),
2983 Schema.Struct({ type: Schema.Literal("steer_active"), targetRunId: RunId }),
2984 Schema.Struct({ type: Schema.Literal("restart_active"), targetRunId: RunId }),
2985 Schema.Struct({ type: Schema.Literal("queue_after_active") }),
2986 Schema.Struct({ type: Schema.Literal("start_immediately") }),
2987 ]),
2988 }),
2989 Schema.Struct({
2990 type: Schema.Literal("prepared-run.release"),
2991 commandId: CommandId,
2992 threadId: ThreadId,
2993 runId: RunId,
2994 }),
2995 /** Provider acceptance of a mailbox delivery; distinct from the agent reading its result. */
2996 Schema.Struct({
2997 type: Schema.Literal("notification.delivery.accept"),
2998 commandId: CommandId,
2999 threadId: ThreadId,
3000 messageId: MessageId,
3001 }),
3002 Schema.Struct({
3003 type: Schema.Literal("prepared-run.progress"),
3004 commandId: CommandId,
3005 threadId: ThreadId,
3006 runId: RunId,
3007 phase: Schema.Literals(["worktree", "setup"]),
3008 }),
3009 Schema.Struct({
3010 type: Schema.Literal("prepared-run.fail"),
3011 commandId: CommandId,
3012 threadId: ThreadId,
3013 runId: RunId,
3014 failure: OrchestrationV2ProviderFailure,
3015 }),
3016 /** Puts a run whose workspace preparation failed back into preparation. */
3017 Schema.Struct({
3018 type: Schema.Literal("prepared-run.retry"),
3019 commandId: CommandId,
3020 threadId: ThreadId,
3021 runId: RunId,
3022 }),
3023 /** Stops one provider-native child while its owning run keeps working. */
3024 Schema.Struct({
3025 type: Schema.Literal("subagent.stop"),
3026 commandId: CommandId,
3027 threadId: ThreadId,
3028 runId: RunId,
3029 subagentId: NodeId,
3030 }),
3031 Schema.Struct({
3032 type: Schema.Literal("run.interrupt"),
3033 commandId: CommandId,
3034 threadId: ThreadId,
3035 runId: RunId,
3036 reason: Schema.optional(Schema.String),
3037 /**
3038 * Set by the Stop button. Stop also holds the queue, ends the thread's pull request
3039 * watches, and stops every delegated task under the thread.
3040 */
3041 holdQueue: Schema.optional(Schema.Boolean),
3042 }),
3043 Schema.Struct({
3044 type: Schema.Literal("queued-message.promote-to-steer"),
3045 commandId: CommandId,
3046 threadId: ThreadId,
3047 queuedRunId: RunId,
3048 targetRunId: RunId,
3049 }),
3050 Schema.Struct({
3051 type: Schema.Literal("queue.resume"),
3052 commandId: CommandId,
3053 threadId: ThreadId,
3054 }),
3055 Schema.Struct({
3056 type: Schema.Literal("queued-run.reorder"),
3057 commandId: CommandId,
3058 threadId: ThreadId,
3059 runId: RunId,
3060 beforeRunId: Schema.NullOr(RunId),
3061 }),
3062 Schema.Struct({
3063 type: Schema.Literal("queued-run.cancel"),
3064 commandId: CommandId,
3065 threadId: ThreadId,
3066 runId: RunId,
3067 }),
3068 Schema.Struct({
3069 type: Schema.Literal("queued-run.edit"),
3070 context: Schema.optional(OrchestrationMessageContext),
3071 commandId: CommandId,
3072 threadId: ThreadId,
3073 runId: RunId,
3074 text: Schema.String,
3075 // Full replacement list. Absent = leave the message's attachments as-is,
3076 // so pre-attachment clients editing text keep the original attachments.
3077 attachments: Schema.optional(Schema.Array(ChatAttachment)),
3078 }),
3079 Schema.Struct({
3080 type: Schema.Literal("runtime-request.respond"),
3081 commandId: CommandId,
3082 threadId: ThreadId,
3083 requestId: RuntimeRequestId,
3084 decision: Schema.optional(ProviderApprovalDecision),
3085 answers: Schema.optional(ProviderUserInputAnswers),
3086 attachmentsByQuestionId: Schema.optional(UserInputAttachments),
3087 }),
3088 Schema.Struct({
3089 type: Schema.Literal("thread.user-input.dismiss"),
3090 commandId: CommandId,
3091 threadId: ThreadId,
3092 requestId: RuntimeRequestId,
3093 }),
3094 Schema.Struct({
3095 type: Schema.Literal("checkpoint.rollback"),
3096 restoreFiles: Schema.optional(Schema.Boolean),
3097 commandId: CommandId,
3098 threadId: ThreadId,
3099 scopeId: CheckpointScopeId,
3100 checkpointId: CheckpointId,
3101 }),
3102 Schema.Struct({
3103 type: Schema.Literal("thread.fork"),
3104 ...OrchestrationV2CreationFields,
3105 commandId: CommandId,
3106 sourceThreadId: ThreadId,
3107 targetThreadId: ThreadId,
3108 sourcePoint: OrchestrationV2ThreadForkSourcePoint,
3109 title: Schema.optional(TrimmedNonEmptyString),
3110 createdAt: Schema.optional(Schema.DateTimeUtc),
3111 }),
3112 Schema.Struct({
3113 type: Schema.Literal("thread.merge_back"),
3114 ...OrchestrationV2CreationFields,
3115 commandId: CommandId,
3116 sourceThreadId: ThreadId,
3117 targetThreadId: ThreadId,
3118 sourcePoint: OrchestrationV2ThreadForkSourcePoint,
3119 createdAt: Schema.optional(Schema.DateTimeUtc),
3120 }),
3121 Schema.Struct({
3122 type: Schema.Literal("delegated_task.request"),
3123 ...OrchestrationV2CreationFields,
3124 commandId: CommandId,
3125 parentThreadId: ThreadId,
3126 parentRunId: RunId,
3127 parentNodeId: NodeId,
3128 task: TrimmedNonEmptyString,
3129 title: Schema.optional(TrimmedNonEmptyString),
3130 modelSelection: ModelSelection,
3131 runtimeMode: RuntimeMode,
3132 interactionMode: ProviderInteractionMode,
3133 workspaceStrategy: Schema.optional(OrchestrationV2ThreadLaunchWorkspaceStrategy),
3134 // Omitted behaves as "settled_only" (no wake while the parent has a live
3135 // run); producers that want fire-and-forget wakes must set "always".
3136 completionWake: Schema.optional(Schema.Literals(["always", "settled_only"])),
3137 createdAt: Schema.optional(Schema.DateTimeUtc),
3138 }),
3139 Schema.Struct({
3140 type: Schema.Literal("delegated_task.wake-policy"),
3141 commandId: CommandId,
3142 parentThreadId: ThreadId,
3143 taskId: NodeId,
3144 completionWake: Schema.Literals(["always", "settled_only"]),
3145 }),
3146 Schema.Struct({
3147 type: Schema.Literal("delegated_task.completion-delivery.acknowledge"),
3148 commandId: CommandId,
3149 parentThreadId: ThreadId,
3150 taskId: NodeId,
3151 observedByRunId: Schema.NullOr(RunId),
3152 }),
3153 Schema.Struct({
3154 type: Schema.Literal("delegated_task.completion-delivery.dispose"),
3155 commandId: CommandId,
3156 parentThreadId: ThreadId,
3157 taskId: NodeId,
3158 }),
3159 Schema.Struct({
3160 type: Schema.Literal("thread.created.record"),
3161 commandId: CommandId,
3162 parentThreadId: ThreadId,
3163 parentRunId: RunId,
3164 parentNodeId: NodeId,
3165 targetThreadId: ThreadId,
3166 targetRunId: Schema.NullOr(RunId),
3167 }),
3168
3169 Schema.Struct({
3170 type: Schema.Literal("provider.switch"),
3171 commandId: CommandId,
3172 threadId: ThreadId,
3173 modelSelection: ModelSelection,
3174 }),
3175]);
3176export type OrchestrationV2Command = typeof OrchestrationV2Command.Type;
3177
3178/**
3179 * Commands only the server dispatches. They stay out of
3180 * `OrchestrationV2Command`, the `dispatchCommand` payload, so no client can
3181 * send them.
3182 */
3183const OrchestrationV2InternalCommand = Schema.Union([
3184 Schema.Struct({
3185 type: Schema.Literal("thread.ci-failed"),
3186 commandId: CommandId,
3187 threadId: ThreadId,
3188 snapshotSequence: NonNegativeInt,
3189 itemId: TurnItemId,
3190 pullRequestNumber: PositiveInt,
3191 url: TrimmedNonEmptyString,
3192 }),
3193 /**
3194 * Records what a pull request watch saw, and wakes the agent in the same transaction when
3195 * `wake` is set. Rejected once the watch started at `startedAt` has ended, and a wake is
3196 * rejected on a settled or archived thread, so a read that raced either changes nothing.
3197 */
3198 Schema.Struct({
3199 type: Schema.Literal("thread.pull-request-watch.sync"),
3200 commandId: CommandId,
3201 threadId: ThreadId,
3202 ...ThreadPullRequestKey.fields,
3203 startedAt: IsoDateTime,
3204 /** The watch to record, or null to end it. */
3205 watch: Schema.NullOr(ThreadPullRequestWatch),
3206 wake: Schema.optional(
3207 Schema.Struct({
3208 messageId: MessageId,
3209 text: Schema.String,
3210 notification: OrchestrationV2Notification,
3211 }),
3212 ),
3213 }),
3214 /** Records that the provider rollback `requestId` failed for good. */
3215 Schema.Struct({
3216 type: Schema.Literal("checkpoint.rollback.fail"),
3217 commandId: CommandId,
3218 threadId: ThreadId,
3219 requestId: CommandId,
3220 message: TrimmedNonEmptyString,
3221 }),
3222 /**
3223 * Follows a Stop once its provider returned: background work the settled
3224 * thread still shows on that provider thread is no longer reported by any
3225 * provider process, so it is marked interrupted. Only the stopped turn's run
3226 * and older runs are settled; a later run's work is its own. A subagent target
3227 * limits repair to that task and its runless child work, using a confirmed
3228 * provider outcome.
3229 */
3230 Schema.Struct({
3231 type: Schema.Literal("thread.background-work.settle"),
3232 commandId: CommandId,
3233 threadId: ThreadId,
3234 providerThreadId: ProviderThreadId,
3235 providerTurnId: ProviderTurnId,
3236 subagent: Schema.optional(
3237 Schema.Struct({
3238 id: NodeId,
3239 stoppedAt: Schema.DateTimeUtc,
3240 outcome: Schema.Struct({
3241 status: Schema.Literals(["completed", "failed", "cancelled"]),
3242 completedAt: Schema.DateTimeUtc,
3243 result: Schema.NullOr(Schema.String),
3244 }),
3245 }),
3246 ),
3247 }),
3248 /**
3249 * Stop for one thread, whatever it is doing: interrupts its running turn, holds its queue,
3250 * ends its pull request watches, and drops pending delegated-task wakes. Nothing to stop is
3251 * an accepted no-op. Delegated tasks under the thread get their own `thread.stop`.
3252 */
3253 Schema.Struct({
3254 type: Schema.Literal("thread.stop"),
3255 commandId: CommandId,
3256 threadId: ThreadId,
3257 reason: Schema.optional(Schema.String),
3258 }),
3259 /**
3260 * Records or updates a secret an agent asked the user for. Internal so no
3261 * client can mark a request saved without the value being stored.
3262 */
3263 Schema.Struct({
3264 type: Schema.Literal("secret_request.record"),
3265 commandId: CommandId,
3266 threadId: ThreadId,
3267 runId: RunId,
3268 nodeId: NodeId,
3269 turnItemId: TurnItemId,
3270 label: TrimmedNonEmptyString,
3271 reason: Schema.String,
3272 placeholder: Schema.optional(Schema.String),
3273 secretStatus: OrchestrationV2SecretRequestStatus,
3274 }),
3275]);
3276export type OrchestrationV2InternalCommand = typeof OrchestrationV2InternalCommand.Type;
3277
3278/** Everything the server's orchestrator accepts: client commands plus internal ones. */
3279export type OrchestrationV2ServerCommand = OrchestrationV2Command | OrchestrationV2InternalCommand;
3280
3281export const ORCHESTRATION_V2_WS_METHODS = {
3282 dispatchCommand: "orchestration.dispatchCommand",
3283 getTurnDiff: "orchestration.getTurnDiff",
3284 getFullThreadDiff: "orchestration.getFullThreadDiff",
3285 searchThreads: "orchestration.searchThreads",
3286 searchThread: "orchestration.searchThread",
3287 searchThreadStream: "orchestration.searchThreadStream",
3288 getArchivedShellSnapshot: "orchestration.getArchivedShellSnapshot",
3289 getThreadProjection: "orchestration.getThreadProjection",
3290 getWorkflowScript: "orchestration.getWorkflowScript",
3291 stopWorkflow: "orchestration.stopWorkflow",
3292 getTurnItem: "orchestration.getTurnItem",
3293 launchThread: "orchestration.launchThread",
3294 subscribeArchivedShell: "orchestration.subscribeArchivedShell",
3295 subscribeShell: "orchestration.subscribeShell",
3296 subscribeThread: "orchestration.subscribeThread",
3297} as const;
3298
3299export const OrchestrationV2ArchivedShellSnapshot = Schema.Struct({
3300 schemaVersion: PositiveInt,
3301 snapshotSequence: NonNegativeInt,
3302 projects: Schema.Array(OrchestrationProjectShell),
3303 threads: Schema.Array(OrchestrationV2ThreadShell),
3304});
3305export type OrchestrationV2ArchivedShellSnapshot = typeof OrchestrationV2ArchivedShellSnapshot.Type;
3306
3307export const OrchestrationV2ArchivedShellStreamItem = Schema.Union([
3308 Schema.Struct({
3309 kind: Schema.Literal("snapshot"),
3310 snapshot: OrchestrationV2ArchivedShellSnapshot,
3311 }),
3312 Schema.Struct({
3313 kind: Schema.Literal("thread.updated"),
3314 sequence: NonNegativeInt,
3315 thread: OrchestrationV2ThreadShell,
3316 }),
3317 Schema.Struct({
3318 kind: Schema.Literal("thread.removed"),
3319 sequence: NonNegativeInt,
3320 threadId: ThreadId,
3321 }),
3322]);
3323export type OrchestrationV2ArchivedShellStreamItem =
3324 typeof OrchestrationV2ArchivedShellStreamItem.Type;
3325
3326export const OrchestrationV2ThreadLaunchInput = Schema.Struct({
3327 commandId: CommandId,
3328 creationSource: Schema.optional(OrchestrationV2CreationSource),
3329 threadId: Schema.optional(ThreadId),
3330 reuseExistingThread: Schema.optional(Schema.Boolean),
3331 projectId: ProjectId,
3332 title: TrimmedNonEmptyString,
3333 generateTitle: Schema.optional(Schema.Boolean),
3334 modelSelection: ModelSelection,
3335 runtimeMode: RuntimeMode,
3336 interactionMode: ProviderInteractionMode,
3337 workspaceStrategy: OrchestrationV2ThreadLaunchWorkspaceStrategy,
3338 initialMessage: Schema.optional(
3339 Schema.Struct({
3340 messageId: Schema.optional(MessageId),
3341 text: Schema.String,
3342 context: Schema.optional(OrchestrationMessageContext),
3343 attachments: Schema.Array(ChatAttachment),
3344 }),
3345 ),
3346});
3347export type OrchestrationV2ThreadLaunchInput = typeof OrchestrationV2ThreadLaunchInput.Type;
3348
3349export const OrchestrationV2ThreadLaunchResult = Schema.Struct({
3350 threadId: ThreadId,
3351 projection: OrchestrationV2ThreadProjection,
3352 resumed: Schema.Boolean,
3353});
3354export type OrchestrationV2ThreadLaunchResult = typeof OrchestrationV2ThreadLaunchResult.Type;
3355
3356export const OrchestrationV2DispatchCommandResult = Schema.Struct({
3357 sequence: NonNegativeInt,
3358});
3359export type OrchestrationV2DispatchCommandResult = typeof OrchestrationV2DispatchCommandResult.Type;
3360
3361export const OrchestrationV2GetThreadProjectionInput = Schema.Struct({
3362 threadId: ThreadId,
3363});
3364export type OrchestrationV2GetThreadProjectionInput =
3365 typeof OrchestrationV2GetThreadProjectionInput.Type;
3366
3367export const OrchestrationV2SubscribeShellInput = Schema.Struct({
3368 /**
3369 * When provided, the server skips the initial full shell snapshot and instead
3370 * replays shell events after this sequence before streaming live events.
3371 * Clients that already hold a cached (or HTTP-loaded) shell snapshot pass its
3372 * sequence here so the subscription resumes without re-sending the entire
3373 * projects/threads list (overlapping events are deduped by sequence on the
3374 * client).
3375 */
3376 afterSequence: Schema.optionalKey(NonNegativeInt),
3377 /** Requests a marker between initial catch-up and live delivery. */
3378 requestCompletionMarker: Schema.optionalKey(Schema.Boolean),
3379});
3380export type OrchestrationV2SubscribeShellInput = typeof OrchestrationV2SubscribeShellInput.Type;
3381
3382export const OrchestrationV2SubscribeThreadInput = Schema.Struct({
3383 threadId: ThreadId,
3384 /**
3385 * When provided, the server skips the initial snapshot frame and instead
3386 * replays events after this sequence before streaming live events. Clients
3387 * that load the snapshot over HTTP pass the snapshot's sequence here so the
3388 * live subscription resumes without a gap (overlapping events are deduped by
3389 * sequence on the client).
3390 */
3391 afterSequence: Schema.optionalKey(NonNegativeInt),
3392 /** Requests a marker between initial catch-up and live delivery. */
3393 requestCompletionMarker: Schema.optionalKey(Schema.Boolean),
3394 /** Allows snapshot fallbacks to contain a bounded, pageable history window. */
3395 acceptBoundedSnapshot: Schema.optionalKey(Schema.Boolean),
3396 /**
3397 * Allows bounded snapshot fallbacks to omit `projection.turnItems` entries
3398 * that repeat local visible rows. See `turnItemsOmitLocalVisible`.
3399 */
3400 acceptCompactTurnItems: Schema.optionalKey(Schema.Boolean),
3401});
3402export type OrchestrationV2SubscribeThreadInput = typeof OrchestrationV2SubscribeThreadInput.Type;
3403
3404export const OrchestrationV2ThreadDetailSnapshot = Schema.Struct({
3405 snapshotSequence: NonNegativeInt,
3406 projection: OrchestrationV2ThreadProjection,
3407 /**
3408 * Progressive history metadata. Omitted on full-projection caches and older
3409 * clients. When present with hasMoreHistory/cursor, the projection is a
3410 * bounded window and must not be treated as a complete timeline.
3411 */
3412 historyCursor: Schema.optionalKey(Schema.NullOr(TrimmedNonEmptyString)),
3413 hasMoreHistory: Schema.optionalKey(Schema.Boolean),
3414 /**
3415 * Max local turn ordinal from the authoritative full projection at snapshot
3416 * time. Optional for backward-compatible warm cache entries.
3417 */
3418 latestLocalTurnOrdinal: Schema.optionalKey(Schema.NullOr(NonNegativeInt)),
3419});
3420export type OrchestrationV2ThreadDetailSnapshot = typeof OrchestrationV2ThreadDetailSnapshot.Type;
3421
3422/**
3423 * Progressive cold open: full control-plane projection arrays with only a
3424 * recent window of timeline rows. `historyCursor` is opaque; clients must not
3425 * parse it. Resume live events with `afterSequence = snapshotSequence`.
3426 */
3427export const OrchestrationV2ThreadBoundedSnapshot = Schema.Struct({
3428 snapshotSequence: NonNegativeInt,
3429 projection: OrchestrationV2ThreadProjection,
3430 historyCursor: Schema.NullOr(TrimmedNonEmptyString),
3431 hasMoreHistory: Schema.Boolean,
3432 /**
3433 * Max local turn ordinal over the authoritative full projection turnItems.
3434 * Clients use this as a partial-timeline watermark when the bounded window
3435 * has no local rows (inherited-only).
3436 */
3437 latestLocalTurnOrdinal: Schema.NullOr(NonNegativeInt),
3438 /** True when complete turns or required live control state exceed the usual byte budget. */
3439 payloadBudgetExceeded: Schema.optional(Schema.Boolean),
3440 /**
3441 * Set only for clients that opted in: `projection.turnItems` omits the items
3442 * of local visible rows, which lead the full list. Clients must restore them
3443 * with `boundedSnapshotProjection` before using the projection.
3444 */
3445 turnItemsOmitLocalVisible: Schema.optionalKey(Schema.Literal(true)),
3446});
3447export type OrchestrationV2ThreadBoundedSnapshot = typeof OrchestrationV2ThreadBoundedSnapshot.Type;
3448
3449/** Older timeline page for progressive history. Rows are chronological. */
3450export const OrchestrationV2ThreadHistoryPage = Schema.Struct({
3451 snapshotSequence: NonNegativeInt,
3452 items: projectedTurnItemArray(
3453 OrchestrationV2ProjectedTurnItem,
3454 OrchestrationV2ProjectedTurnItem.mapFields((fields) => ({
3455 ...fields,
3456 item: ForwardCompatibleUnion(OrchestrationV2TurnItem.members, "type"),
3457 })),
3458 ),
3459 nextCursor: Schema.NullOr(TrimmedNonEmptyString),
3460 hasMoreHistory: Schema.Boolean,
3461});
3462export type OrchestrationV2ThreadHistoryPage = typeof OrchestrationV2ThreadHistoryPage.Type;
3463
3464const knownDomainEventTypes: ReadonlySet<string> = new Set(
3465 OrchestrationV2DomainEvent.members.flatMap((member) => {
3466 const type = member.fields.type;
3467 return "literals" in type ? type.literals : [type.literal];
3468 }),
3469);
3470
3471/** Whether `type` is an {@link OrchestrationV2DomainEvent} discriminant in this build. */
3472export function isKnownOrchestrationV2EventType(type: string): boolean {
3473 return knownDomainEventTypes.has(type);
3474}
3475
3476/**
3477 * A thread event whose type this build does not know, or a turn-item.updated
3478 * carrying a turn item type it does not know. Newer servers add both; older
3479 * clients decode them to this case and skip them, still advancing their resume
3480 * cursor, instead of failing the whole subscription. A known type whose payload
3481 * does not decode still fails. Decode-only: servers never send it.
3482 */
3483const OrchestrationV2UnknownThreadStreamEvent = Schema.Struct({
3484 kind: Schema.Literal("event"),
3485 sequence: NonNegativeInt,
3486 event: Schema.Struct({
3487 type: Schema.String,
3488 payload: Schema.optional(Schema.Unknown),
3489 }).check(
3490 Schema.makeFilter(
3491 (event) =>
3492 !knownDomainEventTypes.has(event.type) ||
3493 (event.type === "turn-item.updated" && isUnknownTurnItem(event.payload)) ||
3494 "A known event type must decode in full.",
3495 ),
3496 ),
3497}).pipe(
3498 Schema.decodeTo(
3499 Schema.Struct({
3500 kind: Schema.Literal("unknown-event"),
3501 sequence: NonNegativeInt,
3502 eventType: Schema.String,
3503 }),
3504 {
3505 decode: SchemaGetter.transform((item) => ({
3506 kind: "unknown-event" as const,
3507 sequence: item.sequence,
3508 eventType: item.event.type,
3509 })),
3510 encode: SchemaGetter.forbidden(() => "Servers never send unknown thread events."),
3511 },
3512 ),
3513);
3514
3515export const OrchestrationV2ThreadStreamItem = Schema.Union([
3516 Schema.Struct({
3517 kind: Schema.Literal("synchronized"),
3518 }),
3519 Schema.Struct({
3520 kind: Schema.Literal("snapshot"),
3521 snapshotSequence: NonNegativeInt,
3522 projection: OrchestrationV2ThreadProjection,
3523 /**
3524 * Progressive history metadata is present on bounded socket fallbacks and
3525 * absent on legacy-compatible full snapshots.
3526 */
3527 historyCursor: Schema.optionalKey(Schema.NullOr(TrimmedNonEmptyString)),
3528 hasMoreHistory: Schema.optionalKey(Schema.Boolean),
3529 latestLocalTurnOrdinal: Schema.optionalKey(Schema.NullOr(NonNegativeInt)),
3530 payloadBudgetExceeded: Schema.optionalKey(Schema.Boolean),
3531 /** Same meaning as on `OrchestrationV2ThreadBoundedSnapshot`. */
3532 turnItemsOmitLocalVisible: Schema.optionalKey(Schema.Literal(true)),
3533 }),
3534 Schema.Struct({
3535 kind: Schema.Literal("event"),
3536 sequence: NonNegativeInt,
3537 event: OrchestrationV2DomainEvent,
3538 }),
3539 // After the known arm: union members are tried in order.
3540 OrchestrationV2UnknownThreadStreamEvent,
3541]);
3542export type OrchestrationV2ThreadStreamItem = typeof OrchestrationV2ThreadStreamItem.Type;
3543
3544export class OrchestrationV2DispatchCommandError extends Schema.TaggedError<OrchestrationV2DispatchCommandError>()(
3545 "OrchestrationV2DispatchCommandError",
3546 {
3547 commandId: CommandId,
3548 commandType: Schema.String,
3549 reason: Schema.optional(Schema.Literal("archive-condition-changed")),
3550 message: Schema.String,
3551 detail: Schema.optional(Schema.String),
3552 cause: Schema.optional(Schema.Defect()),
3553 },
3554) {}
3555
3556export class OrchestrationV2GetThreadProjectionError extends Schema.TaggedError<OrchestrationV2GetThreadProjectionError>()(
3557 "OrchestrationV2GetThreadProjectionError",
3558 {
3559 threadId: ThreadId,
3560 message: Schema.String,
3561 cause: Schema.optional(Schema.Defect()),
3562 },
3563) {}
3564
3565export class OrchestrationV2GetShellSnapshotError extends Schema.TaggedError<OrchestrationV2GetShellSnapshotError>()(
3566 "OrchestrationV2GetShellSnapshotError",
3567 {
3568 message: Schema.String,
3569 cause: Schema.optional(Schema.Defect()),
3570 },
3571) {}
3572
3573export class OrchestrationV2ThreadLaunchError extends Schema.TaggedError<OrchestrationV2ThreadLaunchError>()(
3574 "OrchestrationV2ThreadLaunchError",
3575 {
3576 commandId: CommandId,
3577 projectId: ProjectId,
3578 message: Schema.String,
3579 cause: Schema.optional(Schema.Defect()),
3580 },
3581) {}
3582
3583export const OrchestrationV2StopWorkflowInput = Schema.Struct({
3584 threadId: ThreadId,
3585 subagentId: NodeId,
3586});
3587export type OrchestrationV2StopWorkflowInput = typeof OrchestrationV2StopWorkflowInput.Type;
3588
3589export class OrchestrationV2StopWorkflowError extends Schema.TaggedError<OrchestrationV2StopWorkflowError>()(
3590 "OrchestrationV2StopWorkflowError",
3591 {
3592 threadId: ThreadId,
3593 subagentId: NodeId,
3594 reason: Schema.Literals(["not-running", "unsupported", "unavailable", "stop-failed"]),
3595 cause: Schema.optional(Schema.Defect()),
3596 },
3597) {
3598 override get message(): string {
3599 switch (this.reason) {
3600 case "not-running":
3601 return "This workflow is no longer running.";
3602 case "unsupported":
3603 return "This provider cannot stop a workflow.";
3604 case "unavailable":
3605 return "This workflow has no live provider task.";
3606 case "stop-failed":
3607 return "Failed to stop the workflow.";
3608 }
3609 }
3610}
3611
3612export const OrchestrationV2RpcError = Schema.Union([
3613 OrchestrationV2DispatchCommandError,
3614 OrchestrationV2GetThreadProjectionError,
3615 OrchestrationV2GetShellSnapshotError,
3616 OrchestrationV2ThreadLaunchError,
3617 OrchestrationV2StopWorkflowError,
3618]);
3619export type OrchestrationV2RpcError = typeof OrchestrationV2RpcError.Type;
3620
3621export const OrchestrationV2GetWorkflowScriptInput = Schema.Struct({
3622 threadId: ThreadId,
3623 /** Absolute path from the workflow's runHandles.scriptPath. The server
3624 * re-derives containment; the client value is a hint, never trusted. */
3625 scriptPath: TrimmedNonEmptyString,
3626});
3627export type OrchestrationV2GetWorkflowScriptInput =
3628 typeof OrchestrationV2GetWorkflowScriptInput.Type;
3629
3630export const OrchestrationV2GetWorkflowScriptResult = Schema.Struct({
3631 scriptPath: TrimmedNonEmptyString,
3632 contents: Schema.String,
3633 truncated: Schema.Boolean,
3634});
3635export type OrchestrationV2GetWorkflowScriptResult =
3636 typeof OrchestrationV2GetWorkflowScriptResult.Type;
3637
3638/**
3639 * Shared by every read of a file the Claude harness persisted for a workflow
3640 * run — the script and each member's transcript. One vocabulary because both
3641 * reads apply identical containment rules.
3642 */
3643const WORKFLOW_FILE_ERROR_MESSAGES = {
3644 "invalid-path": "Workflow files must be absolute paths with the expected extension.",
3645 "root-unavailable": "Workflow file root unavailable.",
3646 "not-found": "Workflow file not found.",
3647 "outside-root": "Path is outside the workflow files root.",
3648 "wrong-extension": "Resolved file has the wrong extension.",
3649 "not-regular-file": "Workflow file is not a regular file.",
3650 "changed-during-read": "Workflow file changed between resolution and open.",
3651 "read-failed": "Workflow file read failed.",
3652} as const;
3653
3654export class OrchestrationWorkflowFileError extends Schema.TaggedError<OrchestrationWorkflowFileError>()(
3655 "OrchestrationWorkflowFileError",
3656 {
3657 reason: Schema.Literals([
3658 "invalid-path",
3659 "root-unavailable",
3660 "not-found",
3661 "outside-root",
3662 "wrong-extension",
3663 "not-regular-file",
3664 "changed-during-read",
3665 "read-failed",
3666 ]),
3667 path: Schema.String,
3668 cause: Schema.optional(Schema.Defect()),
3669 },
3670) {
3671 override get message(): string {
3672 return WORKFLOW_FILE_ERROR_MESSAGES[this.reason];
3673 }
3674}
3675
3676export const OrchestrationV2GetTurnItemInput = Schema.Struct({
3677 threadId: ThreadId,
3678 itemId: TurnItemId,
3679 /** The item updatedAt the client last saw. Only keys the client cache. */
3680 revision: Schema.optional(Schema.String),
3681});
3682export type OrchestrationV2GetTurnItemInput = typeof OrchestrationV2GetTurnItemInput.Type;
3683
3684/** One persisted turn item with its full, size-bounded input and output. */
3685export const OrchestrationV2GetTurnItemResult = Schema.Struct({
3686 item: Schema.NullOr(OrchestrationV2TurnItem),
3687});
3688export type OrchestrationV2GetTurnItemResult = typeof OrchestrationV2GetTurnItemResult.Type;
3689
3690const WORKFLOW_SCRIPT_ERROR_MESSAGES = {
3691 "invalid-path": "Workflow scripts must be absolute .js paths.",
3692 "root-unavailable": "Script root unavailable.",
3693 "not-found": "Script not found.",
3694 "outside-root": "Script path is outside the workflow scripts root.",
3695 "not-js": "Resolved script is not a .js file.",
3696 "not-regular-file": "Script is not a regular file.",
3697 "changed-during-read": "Script changed between resolution and open.",
3698 "read-failed": "Script read failed.",
3699} as const;
3700
3701export class OrchestrationGetWorkflowScriptError extends Schema.TaggedError<OrchestrationGetWorkflowScriptError>()(
3702 "OrchestrationGetWorkflowScriptError",
3703 {
3704 reason: Schema.Literals([
3705 "invalid-path",
3706 "root-unavailable",
3707 "not-found",
3708 "outside-root",
3709 "not-js",
3710 "not-regular-file",
3711 "changed-during-read",
3712 "read-failed",
3713 ]),
3714 scriptPath: Schema.String,
3715 cause: Schema.optional(Schema.Defect()),
3716 },
3717) {
3718 override get message(): string {
3719 return WORKFLOW_SCRIPT_ERROR_MESSAGES[this.reason];
3720 }
3721}
3722
3723export const OrchestrationV2SearchThreadInput = Schema.Struct({
3724 threadId: ThreadId,
3725 // Match the skill labels displayed by this client, including custom display names.
3726 skills: Schema.optionalKey(
3727 Schema.Array(
3728 Schema.Struct({
3729 name: Schema.String.check(Schema.isMaxLength(200)),
3730 displayName: Schema.optional(Schema.String.check(Schema.isMaxLength(200))),
3731 }),
3732 ).check(Schema.isMaxLength(1_000)),
3733 ),
3734 query: TrimmedNonEmptyString.check(Schema.isMaxLength(200)),
3735 index: Schema.optionalKey(NonNegativeInt),
3736 // Select relative to an entry identity so updates before it do not shift navigation.
3737 offset: Schema.optionalKey(Schema.Int),
3738 start: Schema.optionalKey(
3739 Schema.Struct({ entryId: TrimmedNonEmptyString, occurrence: NonNegativeInt }),
3740 ),
3741});
3742export type OrchestrationV2SearchThreadInput = typeof OrchestrationV2SearchThreadInput.Type;
3743
3744export const OrchestrationV2ThreadFindMatch = Schema.Struct({
3745 entryId: TrimmedNonEmptyString,
3746 runId: Schema.NullOr(RunId),
3747 occurrence: NonNegativeInt,
3748});
3749export const OrchestrationV2SearchThreadResult = Schema.Struct({
3750 // Omitted by older servers. An early match has no final ordinal or total yet.
3751 complete: Schema.optionalKey(Schema.Boolean),
3752 snapshotSequence: NonNegativeInt,
3753 totalMatches: NonNegativeInt,
3754 activeIndex: NonNegativeInt,
3755 match: Schema.NullOr(OrchestrationV2ThreadFindMatch),
3756 // Counts and identities around the selection let clients step without another round trip.
3757 navigation: Schema.optionalKey(
3758 Schema.Array(
3759 Schema.Struct({
3760 entryId: TrimmedNonEmptyString,
3761 runId: Schema.NullOr(RunId),
3762 startIndex: NonNegativeInt,
3763 count: NonNegativeInt,
3764 }),
3765 ).check(Schema.isMaxLength(17)),
3766 ),
3767});
3768export type OrchestrationV2SearchThreadResult = typeof OrchestrationV2SearchThreadResult.Type;
3769
3770export class OrchestrationV2SearchThreadError extends Schema.TaggedError<OrchestrationV2SearchThreadError>()(
3771 "OrchestrationV2SearchThreadError",
3772 { cause: Schema.Defect() },
3773) {
3774 override get message(): string {
3775 return "Could not search this thread. Please retry.";
3776 }
3777}
3778
3779export const OrchestrationV2RpcSchemas = {
3780 searchThread: {
3781 input: OrchestrationV2SearchThreadInput,
3782 output: OrchestrationV2SearchThreadResult,
3783 },
3784 dispatchCommand: {
3785 input: OrchestrationV2Command,
3786 output: OrchestrationV2DispatchCommandResult,
3787 },
3788 getTurnDiff: {
3789 input: OrchestrationGetTurnDiffInput,
3790 output: OrchestrationGetTurnDiffResult,
3791 },
3792 getFullThreadDiff: {
3793 input: OrchestrationGetFullThreadDiffInput,
3794 output: OrchestrationGetFullThreadDiffResult,
3795 },
3796 getArchivedShellSnapshot: {
3797 input: Schema.Struct({}),
3798 output: OrchestrationV2ArchivedShellSnapshot,
3799 },
3800 getThreadProjection: {
3801 input: OrchestrationV2GetThreadProjectionInput,
3802 output: OrchestrationV2ThreadProjection,
3803 },
3804 stopWorkflow: {
3805 input: OrchestrationV2StopWorkflowInput,
3806 output: Schema.Void,
3807 },
3808 getWorkflowScript: {
3809 input: OrchestrationV2GetWorkflowScriptInput,
3810 output: OrchestrationV2GetWorkflowScriptResult,
3811 },
3812 getTurnItem: {
3813 input: OrchestrationV2GetTurnItemInput,
3814 output: OrchestrationV2GetTurnItemResult,
3815 },
3816 launchThread: {
3817 input: OrchestrationV2ThreadLaunchInput,
3818 output: OrchestrationV2ThreadLaunchResult,
3819 },
3820 subscribeArchivedShell: {
3821 input: Schema.Struct({}),
3822 output: OrchestrationV2ArchivedShellStreamItem,
3823 },
3824 subscribeShell: {
3825 input: OrchestrationV2SubscribeShellInput,
3826 output: OrchestrationV2ShellStreamItem,
3827 },
3828 subscribeThread: {
3829 input: OrchestrationV2SubscribeThreadInput,
3830 output: OrchestrationV2ThreadStreamItem,
3831 },
3832} as const;
3833
3834export const ProviderReplayEntry = Schema.Union([
3835 Schema.Struct({
3836 type: Schema.Literal("expect_outbound"),
3837 label: Schema.optional(TrimmedNonEmptyString),
3838 frame: Schema.Unknown,
3839 }),
3840 Schema.Struct({
3841 type: Schema.Literal("emit_inbound"),
3842 label: Schema.optional(TrimmedNonEmptyString),
3843 frame: Schema.Unknown,
3844 afterMs: Schema.optional(NonNegativeInt),
3845 }),
3846 Schema.Struct({
3847 type: Schema.Literal("runtime_exit"),
3848 status: Schema.Literals(["success", "error", "cancelled"]),
3849 error: Schema.optional(Schema.Unknown),
3850 }),
3851]);
3852export type ProviderReplayEntry = typeof ProviderReplayEntry.Type;
3853
3854export const ProviderReplayTranscript = Schema.Struct({
3855 provider: TrimmedNonEmptyString,
3856 protocol: TrimmedNonEmptyString,
3857 version: TrimmedNonEmptyString,
3858 scenario: TrimmedNonEmptyString,
3859 metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
3860 entries: Schema.Array(ProviderReplayEntry),
3861});
3862export type ProviderReplayTranscript = typeof ProviderReplayTranscript.Type;
3863
3864export const ProviderReplayTranscriptHeader = Schema.Struct({
3865 type: Schema.Literal("transcript_start"),
3866 provider: TrimmedNonEmptyString,
3867 protocol: TrimmedNonEmptyString,
3868 version: TrimmedNonEmptyString,
3869 scenario: TrimmedNonEmptyString,
3870 metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
3871});
3872export type ProviderReplayTranscriptHeader = typeof ProviderReplayTranscriptHeader.Type;
3873
3874export const ProviderReplayNdjsonRecord = Schema.Union([
3875 ProviderReplayTranscriptHeader,
3876 ProviderReplayEntry,
3877]);
3878export type ProviderReplayNdjsonRecord = typeof ProviderReplayNdjsonRecord.Type;