1import * as Effect from "effect/Effect";
2import * as Schema from "effect/Schema";
3import * as SchemaTransformation from "effect/SchemaTransformation";
4
5import {
6 ContextTransferId,
7 IsoDateTime,
8 MessageId,
9 NodeId,
10 NonNegativeInt,
11 PositiveInt,
12 ProjectId,
13 RunId,
14 ScheduledTaskId,
15 SecretRef,
16 ThreadId,
17 TrimmedNonEmptyString,
18 TurnItemId,
19} from "./baseSchemas.ts";
20import {
21 ScheduledTaskRunStatus,
22 ScheduledTaskSchedule,
23 ScheduledTaskUpsertSchedule,
24} from "./scheduledTask.ts";
25import { ProviderInteractionMode, RuntimeMode } from "./providerPolicy.ts";
26import { ThreadLinkedPullRequest } from "./threadPullRequest.ts";
27import { ThreadTitleRegeneration } from "./threadTitle.ts";
28import {
29 OrchestrationV2Actor,
30 OrchestrationV2CreationSource,
31 OrchestrationV2RunStatus,
32 OrchestrationV2TurnItemStatus,
33} from "./orchestrationV2.ts";
34import {
35 ProviderOptionDescriptor,
36 ProviderOptionSelection,
37 ProviderOptionSelectionValue,
38} from "./model.ts";
39import { ProviderDriverKind, ProviderInstanceId } from "./providerInstance.ts";
40
41const OrchestratorMcpPrompt = TrimmedNonEmptyString.check(Schema.isMaxLength(120_000)).annotate({
42 description: "Complete task or message text for the target agent.",
43});
44const OrchestratorMcpTitle = TrimmedNonEmptyString.check(Schema.isMaxLength(512)).annotate({
45 description: "Optional concise display title.",
46});
47const OrchestratorMcpClientRequestId = TrimmedNonEmptyString.check(
48 Schema.isMaxLength(256),
49).annotate({ description: "Stable idempotency key to reuse when retrying this mutation." });
50
51/**
52 * OpenCode 1.15 has been observed serializing nested MCP union objects as JSON
53 * strings. Keep the structured object as the documented form while accepting
54 * that compatibility shape at the tool boundary and decoding it immediately.
55 */
56const OrchestratorMcpScheduleFromJsonString = Schema.fromJsonString(
57 ScheduledTaskUpsertSchedule,
58).annotate({
59 description:
60 "Compatibility-only JSON encoding of the schedule object. Prefer a structured object.",
61});
62
63const OrchestratorMcpSchedule = Schema.Union([
64 ScheduledTaskUpsertSchedule,
65 OrchestratorMcpScheduleFromJsonString,
66]).annotate({
67 description:
68 "Trigger object: {type:'interval', everyMs}, {type:'fixed_time', timeOfDay, weekdays?}, or {type:'webhook'} to run on each request to a generated URL. Never stringify it unless the provider requires the compatibility form.",
69});
70
71/**
72 * Shorthand `{ id: value }` record form for target model options. Unlike the
73 * legacy-tolerant `ProviderOptionSelections` persistence schema, this decodes
74 * strictly: a value that is not a string or boolean fails the request rather
75 * than being silently dropped.
76 */
77const OrchestratorMcpTargetOptionsFromRecord = Schema.Record(
78 Schema.String,
79 ProviderOptionSelectionValue,
80).pipe(
81 Schema.decodeTo(
82 Schema.Array(ProviderOptionSelection),
83 SchemaTransformation.transformEffect({
84 decode: (record) =>
85 Effect.succeed(Object.entries(record).map(([id, value]) => ({ id, value }))),
86 encode: (selections: ReadonlyArray<ProviderOptionSelection>) =>
87 Effect.succeed(
88 Object.fromEntries(selections.map((selection) => [selection.id, selection.value])),
89 ),
90 }),
91 ),
92);
93
94export const OrchestratorMcpTargetOptions = Schema.Union([
95 Schema.Array(ProviderOptionSelection),
96 OrchestratorMcpTargetOptionsFromRecord,
97]);
98export type OrchestratorMcpTargetOptions = typeof OrchestratorMcpTargetOptions.Type;
99
100export const OrchestratorMcpTarget = Schema.Struct({
101 providerInstanceId: Schema.optional(
102 ProviderInstanceId.annotate({
103 description: "Configured provider instance id from orchestrator_capabilities.",
104 }),
105 ),
106 driverKind: Schema.optional(
107 ProviderDriverKind.annotate({
108 description: "Provider driver kind; prefer providerInstanceId when available.",
109 }),
110 ),
111 model: Schema.optional(
112 TrimmedNonEmptyString.annotate({
113 description: "Model id advertised for the selected provider instance.",
114 }),
115 ),
116 /**
117 * Model option selections for the child (for example reasoning effort).
118 * Accepts the canonical `[{ id, value }]` array or the shorthand
119 * `{ id: value }` record; valid ids come from the option descriptors
120 * advertised by orchestrator_capabilities. When omitted, options inherit
121 * from the parent only when the child runs the parent's provider and model.
122 */
123 options: Schema.optional(
124 OrchestratorMcpTargetOptions.annotate({
125 description: "Model option selections advertised by orchestrator_capabilities.",
126 }),
127 ),
128});
129export type OrchestratorMcpTarget = typeof OrchestratorMcpTarget.Type;
130
131export const OrchestratorMcpRuntimeMode = Schema.Union([Schema.Literal("inherit"), RuntimeMode]);
132export type OrchestratorMcpRuntimeMode = typeof OrchestratorMcpRuntimeMode.Type;
133
134export const OrchestratorMcpInteractionMode = Schema.Union([
135 Schema.Literal("inherit"),
136 ProviderInteractionMode,
137]);
138export type OrchestratorMcpInteractionMode = typeof OrchestratorMcpInteractionMode.Type;
139
140export const OrchestratorMcpTaskRole = Schema.Literals([
141 "implementation",
142 "research",
143 "review",
144 "design",
145 "test",
146 "general",
147]);
148export type OrchestratorMcpTaskRole = typeof OrchestratorMcpTaskRole.Type;
149
150export const OrchestratorMcpDelegatedTaskStatus = Schema.Literals([
151 "queued",
152 "running",
153 "waiting",
154 "completed",
155 "failed",
156 "cancelled",
157 "interrupted",
158]);
159export type OrchestratorMcpDelegatedTaskStatus = typeof OrchestratorMcpDelegatedTaskStatus.Type;
160
161export const OrchestratorMcpTerminalDelegatedTaskStatus = Schema.Literals([
162 "completed",
163 "failed",
164 "cancelled",
165 "interrupted",
166]);
167export type OrchestratorMcpTerminalDelegatedTaskStatus =
168 typeof OrchestratorMcpTerminalDelegatedTaskStatus.Type;
169
170export const OrchestratorMcpDelegateTaskInput = Schema.Struct({
171 task: OrchestratorMcpPrompt.annotate({
172 description: "Self-contained task for one delegated child agent/subagent.",
173 }),
174 target: Schema.optional(OrchestratorMcpTarget),
175 title: Schema.optional(OrchestratorMcpTitle),
176 role: Schema.optional(OrchestratorMcpTaskRole),
177 isolation: Schema.optional(
178 Schema.Literals(["shared", "worktree"]).annotate({
179 description:
180 "Defaults to shared: use the parent's checkout. Worktree creates a separate checkout from the parent's current local commit before starting the child. Uncommitted edits are not copied.",
181 }),
182 ),
183 mode: Schema.optional(
184 Schema.Literals(["async", "wait"]).annotate({
185 description:
186 "Defaults to async. Use wait only when this turn needs the child's result before you can continue.",
187 }),
188 ),
189 timeoutMs: Schema.optional(Schema.Number).annotate({
190 description:
191 "Wait budget for mode=wait only. Default 10 minutes. Elapsing it returns waitTimedOut=true on that call and does not cancel the child.",
192 }),
193 clientRequestId: Schema.optional(OrchestratorMcpClientRequestId),
194 runtimeMode: Schema.optional(
195 OrchestratorMcpRuntimeMode.annotate({
196 description:
197 "Defaults to inherit; omit it unless the user asks for a supervised child. A narrower mode is not a read-only switch: on most providers, approval-required and auto-accept-edits pause the child at each action that needs approval until a person approves it in the child's thread, which this thread cannot do. To limit what the child does, say so in the task. A mode ranked above this thread's is rejected; that ranking does not promise the child's provider permissions are narrower than this thread's.",
198 }),
199 ),
200 interactionMode: Schema.optional(OrchestratorMcpInteractionMode),
201});
202export type OrchestratorMcpDelegateTaskInput = typeof OrchestratorMcpDelegateTaskInput.Type;
203
204export const OrchestratorMcpDelegateTaskResult = Schema.Struct({
205 taskId: NodeId,
206 childThreadId: ThreadId,
207 childRunId: Schema.NullOr(RunId),
208 childNodeId: NodeId,
209 status: OrchestratorMcpDelegatedTaskStatus,
210 workState: Schema.Literals(["working", "waiting_for_children", "result_available"]),
211 hasPendingChildRuns: Schema.Boolean,
212 latestTerminalRunId: Schema.NullOr(RunId),
213 latestTerminalStatus: Schema.NullOr(OrchestratorMcpTerminalDelegatedTaskStatus),
214 latestTerminalSummary: Schema.NullOr(Schema.String),
215 latestTerminalResultContextTransferId: Schema.NullOr(ContextTransferId),
216 providerInstanceId: ProviderInstanceId,
217 model: Schema.NullOr(Schema.String),
218 summary: Schema.NullOr(Schema.String),
219 resultContextTransferId: Schema.NullOr(ContextTransferId),
220 hasPendingQuestion: Schema.Boolean.annotate({
221 description:
222 "Blocking question ends mode=wait. Pass threadId=childThreadId to t3_pending_request_list, t3_pending_request_read (with requestId) and t3_pending_request_respond, or ask the user; the task's completion still wakes this thread.",
223 }),
224 waitTimedOut: Schema.Boolean.annotate({
225 description:
226 "True only on that mode=wait call when timeoutMs elapsed. The timeout does not cancel the child. Later task_status reads return false and use status for liveness.",
227 }),
228});
229export type OrchestratorMcpDelegateTaskResult = typeof OrchestratorMcpDelegateTaskResult.Type;
230
231export const OrchestratorMcpTaskStatusInput = Schema.Struct({
232 taskId: NodeId,
233});
234export type OrchestratorMcpTaskStatusInput = typeof OrchestratorMcpTaskStatusInput.Type;
235
236export const OrchestratorMcpTaskCancelInput = Schema.Struct({
237 taskId: NodeId,
238 reason: Schema.optional(Schema.String.check(Schema.isMaxLength(2_000))),
239 clientRequestId: Schema.optional(OrchestratorMcpClientRequestId),
240});
241export type OrchestratorMcpTaskCancelInput = typeof OrchestratorMcpTaskCancelInput.Type;
242
243export const OrchestratorMcpTaskCancelResult = Schema.Struct({
244 taskId: NodeId,
245 status: Schema.Literals(["cancel_requested", "completed", "failed", "cancelled", "interrupted"]),
246});
247export type OrchestratorMcpTaskCancelResult = typeof OrchestratorMcpTaskCancelResult.Type;
248
249export const OrchestratorMcpCreateThreadRequest = Schema.Struct({
250 prompt: Schema.optional(OrchestratorMcpPrompt),
251 title: Schema.optional(OrchestratorMcpTitle),
252 target: Schema.optional(OrchestratorMcpTarget),
253 runtimeMode: Schema.optional(OrchestratorMcpRuntimeMode),
254 interactionMode: Schema.optional(OrchestratorMcpInteractionMode),
255});
256export type OrchestratorMcpCreateThreadRequest = typeof OrchestratorMcpCreateThreadRequest.Type;
257
258export const OrchestratorMcpCreateThreadsInput = Schema.Struct({
259 threads: Schema.Array(OrchestratorMcpCreateThreadRequest).check(
260 Schema.isMinLength(1),
261 Schema.isMaxLength(20),
262 ),
263 clientRequestId: Schema.optional(OrchestratorMcpClientRequestId),
264});
265export type OrchestratorMcpCreateThreadsInput = typeof OrchestratorMcpCreateThreadsInput.Type;
266
267export const OrchestratorMcpCreatedThreadStatus = Schema.Union([
268 Schema.Literal("idle"),
269 Schema.Literal("preparing"),
270 Schema.Literal("starting"),
271 OrchestratorMcpDelegatedTaskStatus,
272 Schema.Literal("rolled_back"),
273]);
274export type OrchestratorMcpCreatedThreadStatus = typeof OrchestratorMcpCreatedThreadStatus.Type;
275
276export const OrchestratorMcpCreatedThread = Schema.Struct({
277 threadId: ThreadId,
278 runId: Schema.NullOr(RunId),
279 status: OrchestratorMcpCreatedThreadStatus,
280 title: Schema.String,
281 createdBy: OrchestrationV2Actor,
282 creationSource: OrchestrationV2CreationSource,
283 providerInstanceId: ProviderInstanceId,
284 model: Schema.String,
285});
286export type OrchestratorMcpCreatedThread = typeof OrchestratorMcpCreatedThread.Type;
287
288export const OrchestratorMcpCreateThreadsResult = Schema.Struct({
289 threads: Schema.Array(OrchestratorMcpCreatedThread),
290});
291export type OrchestratorMcpCreateThreadsResult = typeof OrchestratorMcpCreateThreadsResult.Type;
292
293export const OrchestratorMcpThreadStatus = Schema.Union([
294 Schema.Literal("idle"),
295 OrchestrationV2RunStatus,
296]);
297export type OrchestratorMcpThreadStatus = typeof OrchestratorMcpThreadStatus.Type;
298
299const OrchestratorMcpProjectTarget = Schema.optional(
300 ProjectId.annotate({
301 description:
302 "Project to act on. Omit for the calling thread's project; required when the caller is not a T3 thread.",
303 }),
304);
305
306export const OrchestratorMcpThreadListInput = Schema.Struct({
307 projectId: OrchestratorMcpProjectTarget,
308 statuses: Schema.optional(
309 Schema.Array(OrchestratorMcpThreadStatus).check(Schema.isMaxLength(10)),
310 ),
311 titleContains: Schema.optional(TrimmedNonEmptyString.check(Schema.isMaxLength(256))),
312 settled: Schema.optional(Schema.Boolean),
313 snoozed: Schema.optional(Schema.Boolean),
314 includeSubagents: Schema.optional(Schema.Boolean),
315 cursor: Schema.optional(NonNegativeInt),
316 limit: Schema.optional(PositiveInt.check(Schema.isLessThanOrEqualTo(100))),
317});
318export type OrchestratorMcpThreadListInput = typeof OrchestratorMcpThreadListInput.Type;
319
320export const OrchestratorMcpThreadListItem = Schema.Struct({
321 threadId: ThreadId,
322 title: Schema.String,
323 createdBy: OrchestrationV2Actor,
324 creationSource: OrchestrationV2CreationSource,
325 status: OrchestratorMcpThreadStatus,
326 latestRunId: Schema.NullOr(RunId),
327 providerInstanceId: ProviderInstanceId,
328 model: Schema.String,
329 runtimeMode: RuntimeMode,
330 interactionMode: ProviderInteractionMode,
331 linkedPullRequest: Schema.NullOr(ThreadLinkedPullRequest),
332 settled: Schema.Boolean,
333 settledAt: Schema.NullOr(IsoDateTime),
334 snoozed: Schema.Boolean,
335 /** When a snoozed thread wakes; null when it is not snoozed. */
336 snoozedUntil: Schema.NullOr(IsoDateTime),
337 parentThreadId: Schema.NullOr(ThreadId),
338 relationshipToParent: Schema.NullOr(Schema.Literals(["fork", "subagent"])),
339 itemCount: NonNegativeInt,
340 createdAt: IsoDateTime,
341 updatedAt: IsoDateTime,
342});
343export type OrchestratorMcpThreadListItem = typeof OrchestratorMcpThreadListItem.Type;
344
345export const OrchestratorMcpThreadListResult = Schema.Struct({
346 projectId: ProjectId,
347 /** The calling thread, or null when the caller is not a T3 thread. */
348 currentThreadId: Schema.NullOr(ThreadId),
349 threads: Schema.Array(OrchestratorMcpThreadListItem),
350 nextCursor: Schema.NullOr(NonNegativeInt),
351 total: NonNegativeInt,
352});
353export type OrchestratorMcpThreadListResult = typeof OrchestratorMcpThreadListResult.Type;
354
355export const OrchestratorMcpThreadReadInput = Schema.Struct({
356 threadId: ThreadId,
357 itemId: Schema.optional(TurnItemId),
358 textOffset: Schema.optional(NonNegativeInt),
359 view: Schema.optional(Schema.Literals(["messages", "activity"])),
360 afterPosition: Schema.optional(NonNegativeInt),
361 limit: Schema.optional(PositiveInt.check(Schema.isLessThanOrEqualTo(100))),
362 runLimit: Schema.optional(PositiveInt.check(Schema.isLessThanOrEqualTo(50))),
363 maxCharsPerItem: Schema.optional(PositiveInt.check(Schema.isLessThanOrEqualTo(50_000))),
364});
365export type OrchestratorMcpThreadReadInput = typeof OrchestratorMcpThreadReadInput.Type;
366
367export const OrchestratorMcpThreadDetail = Schema.Struct({
368 threadId: ThreadId,
369 projectId: ProjectId,
370 title: Schema.String,
371 createdBy: OrchestrationV2Actor,
372 creationSource: OrchestrationV2CreationSource,
373 status: OrchestratorMcpThreadStatus,
374 latestRunId: Schema.NullOr(RunId),
375 activeRunId: Schema.NullOr(RunId),
376 providerInstanceId: ProviderInstanceId,
377 model: Schema.String,
378 runtimeMode: RuntimeMode,
379 interactionMode: ProviderInteractionMode,
380 linkedPullRequest: Schema.NullOr(ThreadLinkedPullRequest),
381 titleRegeneration: Schema.NullOr(ThreadTitleRegeneration),
382 branch: Schema.NullOr(Schema.String),
383 worktreePath: Schema.NullOr(Schema.String),
384 parentThreadId: Schema.NullOr(ThreadId),
385 relationshipToParent: Schema.NullOr(Schema.Literals(["fork", "subagent"])),
386 runCount: NonNegativeInt,
387 itemCount: NonNegativeInt,
388 pendingRequestCount: NonNegativeInt,
389 archived: Schema.Boolean,
390 settled: Schema.Boolean,
391 settledAt: Schema.NullOr(IsoDateTime),
392 snoozed: Schema.Boolean,
393 /** When a snoozed thread wakes; null when it is not snoozed. */
394 snoozedUntil: Schema.NullOr(IsoDateTime),
395 createdAt: IsoDateTime,
396 updatedAt: IsoDateTime,
397});
398export type OrchestratorMcpThreadDetail = typeof OrchestratorMcpThreadDetail.Type;
399
400export const OrchestratorMcpThreadRun = Schema.Struct({
401 runId: RunId,
402 ordinal: PositiveInt,
403 status: OrchestrationV2RunStatus,
404 providerInstanceId: ProviderInstanceId,
405 model: Schema.String,
406 requestedAt: IsoDateTime,
407 startedAt: Schema.NullOr(IsoDateTime),
408 completedAt: Schema.NullOr(IsoDateTime),
409});
410export type OrchestratorMcpThreadRun = typeof OrchestratorMcpThreadRun.Type;
411
412export const OrchestratorMcpThreadTimelineItem = Schema.Struct({
413 position: NonNegativeInt,
414 visibility: Schema.Literals(["local", "inherited", "synthetic"]),
415 sourceThreadId: ThreadId,
416 itemId: TurnItemId,
417 subagentId: Schema.optional(NodeId),
418 runId: Schema.NullOr(RunId),
419 messageId: Schema.NullOr(MessageId),
420 createdBy: Schema.NullOr(OrchestrationV2Actor),
421 creationSource: Schema.NullOr(OrchestrationV2CreationSource),
422 type: Schema.String,
423 status: OrchestrationV2TurnItemStatus,
424 title: Schema.NullOr(Schema.String),
425 text: Schema.NullOr(Schema.String),
426 textTruncated: Schema.Boolean,
427 nextTextOffset: Schema.optional(Schema.NullOr(NonNegativeInt)),
428 updatedAt: IsoDateTime,
429});
430export type OrchestratorMcpThreadTimelineItem = typeof OrchestratorMcpThreadTimelineItem.Type;
431
432export const OrchestratorMcpThreadReadResult = Schema.Struct({
433 thread: OrchestratorMcpThreadDetail,
434 recentRuns: Schema.Array(OrchestratorMcpThreadRun),
435 items: Schema.Array(OrchestratorMcpThreadTimelineItem),
436 nextPosition: Schema.NullOr(NonNegativeInt),
437 hasMore: Schema.Boolean,
438});
439export type OrchestratorMcpThreadReadResult = typeof OrchestratorMcpThreadReadResult.Type;
440
441export const OrchestratorMcpThreadSendInput = Schema.Struct({
442 threadId: ThreadId,
443 message: OrchestratorMcpPrompt,
444 mode: Schema.optional(Schema.Literals(["auto", "queue", "steer", "restart"])),
445 clientRequestId: Schema.optional(OrchestratorMcpClientRequestId),
446});
447export type OrchestratorMcpThreadSendInput = typeof OrchestratorMcpThreadSendInput.Type;
448
449export const OrchestratorMcpThreadSendResult = Schema.Struct({
450 threadId: ThreadId,
451 messageId: MessageId,
452 runId: RunId,
453 /** Fresh task for a follow-up to an app-owned child; the previous task stays terminal. */
454 taskId: Schema.optional(NodeId),
455 status: OrchestrationV2RunStatus,
456 delivery: Schema.Literals(["started", "queued", "steered", "restarted"]),
457});
458export type OrchestratorMcpThreadSendResult = typeof OrchestratorMcpThreadSendResult.Type;
459
460export const OrchestratorMcpThreadWaitInput = Schema.Struct({
461 threadId: ThreadId,
462 runId: Schema.optional(RunId),
463 timeoutMs: Schema.optional(Schema.Number),
464});
465export type OrchestratorMcpThreadWaitInput = typeof OrchestratorMcpThreadWaitInput.Type;
466
467export const OrchestratorMcpThreadWaitResult = Schema.Struct({
468 threadId: ThreadId,
469 runId: Schema.NullOr(RunId),
470 status: OrchestratorMcpThreadStatus,
471 timedOut: Schema.Boolean,
472});
473export type OrchestratorMcpThreadWaitResult = typeof OrchestratorMcpThreadWaitResult.Type;
474
475export const OrchestratorMcpThreadInterruptInput = Schema.Struct({
476 threadId: ThreadId,
477 runId: Schema.optional(RunId),
478 reason: Schema.optional(Schema.String.check(Schema.isMaxLength(2_000))),
479 clientRequestId: Schema.optional(OrchestratorMcpClientRequestId),
480});
481export type OrchestratorMcpThreadInterruptInput = typeof OrchestratorMcpThreadInterruptInput.Type;
482
483export const OrchestratorMcpThreadInterruptResult = Schema.Struct({
484 threadId: ThreadId,
485 runId: Schema.NullOr(RunId),
486 status: Schema.Union([
487 Schema.Literal("interrupt_requested"),
488 Schema.Literal("no_active_run"),
489 Schema.Literals(["completed", "failed", "cancelled", "interrupted", "rolled_back"]),
490 ]),
491});
492export type OrchestratorMcpThreadInterruptResult = typeof OrchestratorMcpThreadInterruptResult.Type;
493
494export const OrchestratorMcpProviderCapability = Schema.Struct({
495 providerInstanceId: ProviderInstanceId,
496 driverKind: ProviderDriverKind,
497 displayName: Schema.NullOr(Schema.String),
498 models: Schema.Array(
499 Schema.Struct({
500 id: Schema.String,
501 label: Schema.NullOr(Schema.String),
502 /** Model options a target may select (for example reasoning effort). */
503 options: Schema.optional(Schema.Array(ProviderOptionDescriptor)),
504 }),
505 ),
506 /** Runtime modes the provider offers; omitted when it offers all of them. */
507 runtimeModes: Schema.optional(Schema.Array(RuntimeMode)),
508 canRunChildTask: Schema.Boolean,
509 canRunCrossProviderChildTask: Schema.Boolean,
510 constraints: Schema.Array(Schema.String),
511});
512export type OrchestratorMcpProviderCapability = typeof OrchestratorMcpProviderCapability.Type;
513
514export const OrchestratorMcpCapabilitiesResult = Schema.Struct({
515 /** The calling thread, or null when the caller is not a T3 thread. */
516 parentThreadId: Schema.NullOr(ThreadId),
517 /** The calling thread's selection, or null when the caller is not a T3 thread. */
518 inheritedProviderInstanceId: Schema.NullOr(ProviderInstanceId),
519 inheritedModel: Schema.NullOr(Schema.String),
520 runtimeMode: RuntimeMode,
521 interactionMode: ProviderInteractionMode,
522 providers: Schema.Array(OrchestratorMcpProviderCapability),
523 features: Schema.Struct({
524 appOwnedSubagents: Schema.Boolean,
525 asyncPolling: Schema.Boolean,
526 cancellation: Schema.Boolean,
527 batchThreadCreation: Schema.Boolean,
528 threadManagement: Schema.Boolean,
529 incrementalThreadRead: Schema.Boolean,
530 scheduledTasks: Schema.Boolean,
531 maxBatchThreads: Schema.Number,
532 }),
533});
534export type OrchestratorMcpCapabilitiesResult = typeof OrchestratorMcpCapabilitiesResult.Type;
535
536export const OrchestratorMcpScheduleTaskInput = Schema.Struct({
537 projectId: OrchestratorMcpProjectTarget,
538 prompt: OrchestratorMcpPrompt.annotate({
539 description: "Prompt executed on every scheduled run.",
540 }),
541 schedule: OrchestratorMcpSchedule,
542 title: Schema.optional(OrchestratorMcpTitle),
543 enabled: Schema.optional(
544 Schema.Boolean.annotate({ description: "Whether the schedule starts enabled; defaults true." }),
545 ),
546 /**
547 * When true (the default), the scheduled task fires into the calling thread
548 * on each run instead of launching a fresh thread. This is the recurring
549 * "wake up in this thread" behaviour reserved for agent-created tasks.
550 */
551 bindToCurrentThread: Schema.optional(
552 Schema.Boolean.annotate({
553 description:
554 "True (default) posts each run into this thread; false creates a fresh top-level thread per run.",
555 }),
556 ),
557 clientRequestId: Schema.optional(OrchestratorMcpClientRequestId),
558});
559export type OrchestratorMcpScheduleTaskInput = typeof OrchestratorMcpScheduleTaskInput.Type;
560
561/** Summary of a scheduled task returned by the schedule/list/update tools. */
562export const OrchestratorMcpScheduledTask = Schema.Struct({
563 scheduledTaskId: ScheduledTaskId,
564 title: Schema.String,
565 prompt: Schema.String,
566 enabled: Schema.Boolean,
567 projectId: ProjectId,
568 boundThreadId: Schema.NullOr(ThreadId),
569 schedule: ScheduledTaskSchedule,
570 nextRunAt: Schema.NullOr(IsoDateTime),
571 lastRunStatus: ScheduledTaskRunStatus,
572 /** For webhook tasks: the public T3 Connect URL. Absent when this environment has no managed tunnel. */
573 webhookUrl: Schema.optional(Schema.String).annotate({
574 description:
575 "Public URL to give the sender. Absent when this environment has no T3 Connect managed tunnel; the user must enable T3 Connect remote access first.",
576 }),
577 webhookSignature: Schema.optional(Schema.Literals(["none", "set"])).annotate({
578 description: "Whether requests must carry a valid signature.",
579 }),
580});
581export type OrchestratorMcpScheduledTask = typeof OrchestratorMcpScheduledTask.Type;
582
583export const OrchestratorMcpScheduleTaskResult = OrchestratorMcpScheduledTask;
584export type OrchestratorMcpScheduleTaskResult = typeof OrchestratorMcpScheduleTaskResult.Type;
585
586export const OrchestratorMcpListScheduledTasksInput = Schema.Struct({
587 projectId: Schema.optional(
588 ProjectId.annotate({
589 description:
590 "Only list this project's tasks. Omit for the calling thread's project, or for every project when the caller is not a T3 thread.",
591 }),
592 ),
593});
594export type OrchestratorMcpListScheduledTasksInput =
595 typeof OrchestratorMcpListScheduledTasksInput.Type;
596
597export const OrchestratorMcpListScheduledTasksResult = Schema.Struct({
598 tasks: Schema.Array(OrchestratorMcpScheduledTask),
599});
600export type OrchestratorMcpListScheduledTasksResult =
601 typeof OrchestratorMcpListScheduledTasksResult.Type;
602
603export const OrchestratorMcpUpdateScheduledTaskInput = Schema.Struct({
604 scheduledTaskId: ScheduledTaskId,
605 prompt: Schema.optional(OrchestratorMcpPrompt),
606 title: Schema.optional(OrchestratorMcpTitle),
607 schedule: Schema.optional(OrchestratorMcpSchedule),
608 enabled: Schema.optional(Schema.Boolean),
609 bindToCurrentThread: Schema.optional(Schema.Boolean),
610});
611export type OrchestratorMcpUpdateScheduledTaskInput =
612 typeof OrchestratorMcpUpdateScheduledTaskInput.Type;
613
614export const OrchestratorMcpRequestSecretInput = Schema.Struct({
615 label: TrimmedNonEmptyString.annotate({
616 description: "What you need, shown as the card's title, e.g. 'GitHub webhook secret'.",
617 }),
618 reason: TrimmedNonEmptyString.annotate({
619 description:
620 "One or two sentences on what it is for and where the user gets or also enters it.",
621 }),
622 placeholder: Schema.optional(TrimmedNonEmptyString).annotate({
623 description: "Hint inside the input, e.g. 'Paste your GitHub token'.",
624 }),
625 timeoutMs: Schema.optional(
626 Schema.Int.check(Schema.isBetween({ minimum: 1_000, maximum: 60 * 60 * 1_000 })),
627 ).annotate({ description: "How long to wait for the user. Default 10 minutes." }),
628 clientRequestId: Schema.optional(OrchestratorMcpClientRequestId).annotate({
629 description:
630 "Reuse when retrying a call that lost its result, so the user sees one card and its answer is returned again. Use a new id to ask again after timed_out or cancelled.",
631 }),
632});
633export type OrchestratorMcpRequestSecretInput = typeof OrchestratorMcpRequestSecretInput.Type;
634
635export const OrchestratorMcpRequestSecretResult = Schema.Union([
636 Schema.Struct({
637 status: Schema.Literal("saved").annotate({ description: "secretRef holds the value." }),
638 secretRef: SecretRef.annotate({
639 description:
640 "Pass it to a tool that accepts a secretRef; it works once, and you never see the value.",
641 }),
642 }),
643 Schema.Struct({
644 status: Schema.Literals(["declined", "cancelled", "timed_out"]).annotate({
645 description:
646 "declined: the user chose not to. cancelled: the request ended with the run. timed_out: the user did not answer in time; the card is closed, so ask again with a new clientRequestId if still needed.",
647 }),
648 }),
649]);
650export type OrchestratorMcpRequestSecretResult = typeof OrchestratorMcpRequestSecretResult.Type;
651
652export const OrchestratorMcpDeleteScheduledTaskInput = Schema.Struct({
653 scheduledTaskId: ScheduledTaskId,
654});
655export type OrchestratorMcpDeleteScheduledTaskInput =
656 typeof OrchestratorMcpDeleteScheduledTaskInput.Type;
657
658export const OrchestratorMcpDeleteScheduledTaskResult = Schema.Struct({
659 scheduledTaskId: ScheduledTaskId,
660 deleted: Schema.Boolean,
661});
662export type OrchestratorMcpDeleteScheduledTaskResult =
663 typeof OrchestratorMcpDeleteScheduledTaskResult.Type;
664
665export class OrchestratorMcpFailure extends Schema.TaggedError<OrchestratorMcpFailure>()(
666 "OrchestratorMcpFailure",
667 {
668 code: Schema.Literals([
669 "capability_denied",
670 "parent_not_active",
671 "provider_unavailable",
672 "model_unavailable",
673 "runtime_mode_escalation_denied",
674 "interaction_mode_escalation_denied",
675 "task_not_found",
676 "task_not_cancellable",
677 "thread_not_found",
678 "run_not_found",
679 "thread_not_sendable",
680 "thread_not_interruptible",
681 "invalid_request",
682 "orchestration_error",
683 "thread_credential_required",
684 "target_required",
685 ]),
686 message: Schema.String,
687 },
688) {}