@kanyun-ai-infra/agenthub 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,4652 @@
1
+ var __typeError = (msg) => {
2
+ throw TypeError(msg);
3
+ };
4
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
7
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
8
+
9
+ // ../contracts/dist/chunk-DDAAVRWG.js
10
+ var __defProp = Object.defineProperty;
11
+ var __defProps = Object.defineProperties;
12
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
13
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
14
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
15
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
16
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17
+ var __spreadValues = (a, b) => {
18
+ for (var prop in b || (b = {}))
19
+ if (__hasOwnProp.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ if (__getOwnPropSymbols)
22
+ for (var prop of __getOwnPropSymbols(b)) {
23
+ if (__propIsEnum.call(b, prop))
24
+ __defNormalProp(a, prop, b[prop]);
25
+ }
26
+ return a;
27
+ };
28
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
29
+
30
+ // ../contracts/dist/index.js
31
+ import { z } from "zod";
32
+ import { z as z2 } from "zod";
33
+ import { z as z3 } from "zod";
34
+ import { z as z4 } from "zod";
35
+ import { z as z5 } from "zod";
36
+ import { z as z9 } from "zod";
37
+ import { z as z8 } from "zod";
38
+ import { z as z6 } from "zod";
39
+ import { z as z7 } from "zod";
40
+ import { z as z10 } from "zod";
41
+ import { z as z11 } from "zod";
42
+ import { z as z12 } from "zod";
43
+ import { z as z13 } from "zod";
44
+ import { z as z14 } from "zod";
45
+ import { z as z15 } from "zod";
46
+ import { z as z17 } from "zod";
47
+ import { z as z16 } from "zod";
48
+ import { z as z18 } from "zod";
49
+ import { z as z19 } from "zod";
50
+ import { z as z20 } from "zod";
51
+ import { z as z21 } from "zod";
52
+ import { z as z22 } from "zod";
53
+ import { z as z23 } from "zod";
54
+ import { z as z24 } from "zod";
55
+ import { z as z25 } from "zod";
56
+ import { z as z28 } from "zod";
57
+ import { z as z26 } from "zod";
58
+ import { z as z27 } from "zod";
59
+ import { z as z29 } from "zod";
60
+ import { z as z33 } from "zod";
61
+ import { z as z32 } from "zod";
62
+ import { z as z31 } from "zod";
63
+ import { z as z30 } from "zod";
64
+ import { z as z35 } from "zod";
65
+ import { z as z34 } from "zod";
66
+ import { z as z36 } from "zod";
67
+ import { z as z37 } from "zod";
68
+ import { z as z39 } from "zod";
69
+ import { z as z38 } from "zod";
70
+ import { z as z40 } from "zod";
71
+ import { z as z41 } from "zod";
72
+ import { z as z42 } from "zod";
73
+ import { z as z43 } from "zod";
74
+ import { z as z44 } from "zod";
75
+ import { z as z45 } from "zod";
76
+ import { z as z46 } from "zod";
77
+ var RunStatusSchema = z.enum([
78
+ "queued",
79
+ "provisioning",
80
+ "preparing",
81
+ "running",
82
+ "finalizing_prepare",
83
+ "finalizing_uploading",
84
+ "finalizing_verifying",
85
+ "finalizing_metadata_commit",
86
+ "finalized",
87
+ "completed",
88
+ "failed",
89
+ "worker_unreachable",
90
+ "finalizing_retryable_failed",
91
+ "finalizing_timeout",
92
+ "finalizing_manual_intervention"
93
+ ]);
94
+ var RunDeliveryPhaseSchema = z.enum(["in_progress", "completed", "failed"]);
95
+ var TriggerSourceSchema = z.enum([
96
+ "user",
97
+ "webhook",
98
+ "alert",
99
+ "cron",
100
+ "wecom_chat",
101
+ "jira"
102
+ ]);
103
+ var ProviderTypeSchema = z.enum([
104
+ // Legacy runtime keys (do NOT reorder; preserves persisted values).
105
+ "claude-code",
106
+ "codex",
107
+ // ModelGate vendor expansion (names mirror ModelGate `owned_by`).
108
+ "deepseek",
109
+ "google",
110
+ "zhipu",
111
+ "volcengine",
112
+ "tencent",
113
+ "moonshot",
114
+ "minimax",
115
+ "dashscope",
116
+ "xiaomi"
117
+ ]);
118
+ var AttachmentMetaSchema = z.object({
119
+ /** OSS original URL (Agent Worker downloads via this) */
120
+ ossUrl: z.string().min(1),
121
+ /** Original filename */
122
+ filename: z.string().min(1).max(255),
123
+ /** File size in bytes */
124
+ size: z.number().int().positive(),
125
+ /** Media type classification */
126
+ mediaType: z.enum(["image", "document", "code", "notebook"]),
127
+ /** MIME type */
128
+ mimeType: z.string()
129
+ });
130
+ var RunSpecSchema = z.object({
131
+ prompt: z.string().min(1),
132
+ projectId: z.string().uuid(),
133
+ agentId: z.string().uuid().optional(),
134
+ agentMode: z.enum(["task", "chat"]).optional(),
135
+ repo: z.string().optional(),
136
+ ref: z.string().optional(),
137
+ model: z.string().optional(),
138
+ provider: ProviderTypeSchema.optional().default("claude-code"),
139
+ runnerRequired: z.boolean().optional().default(false),
140
+ triggerSource: TriggerSourceSchema.optional().default("user"),
141
+ triggerRef: z.string().optional(),
142
+ githubInstallationId: z.string().optional(),
143
+ attachments: z.array(AttachmentMetaSchema).max(5).optional(),
144
+ /**
145
+ * LDAP of the user whose action created this run. Populated by
146
+ * Portal / 企微 entry points. Null / undefined for webhook / automation
147
+ * triggers where we cannot identify a single human, in which case
148
+ * prepareWorkspace falls back to the service-level Bedrock key.
149
+ * See specs/features/user-bedrock-credentials.md.
150
+ */
151
+ triggerUserLdap: z.string().min(1).optional(),
152
+ /**
153
+ * Per-run override for the effective MCP / Skills enable list (spec
154
+ * §6.3). Either field being present (including `[]`) writes into the
155
+ * corresponding `runs.enabled_*` column; `undefined` leaves the
156
+ * column NULL, in which case the runtime resolver falls through to
157
+ * `agents.enabled_*`.
158
+ *
159
+ * Phase 1 has no Portal UI surface for this — the field is reserved
160
+ * for SDK / webhook automations. See specs/features/mcp-and-skills.md.
161
+ *
162
+ * Element shape is validated by the API layer (Zod) — at the
163
+ * RunService layer we accept already-validated arrays as opaque to
164
+ * keep the service free of contracts re-imports.
165
+ */
166
+ // Element shape validated at the API layer; RunService accepts opaque arrays
167
+ // (see comment above) so no further runtime check here.
168
+ enabledMcpServers: z.array(z.any()).optional(),
169
+ enabledSkills: z.array(z.any()).optional()
170
+ });
171
+ var RunSchema = z.object({
172
+ id: z.string().uuid(),
173
+ agentId: z.string().uuid(),
174
+ parentRunId: z.string().uuid().nullable(),
175
+ status: RunStatusSchema,
176
+ prompt: z.string(),
177
+ projectId: z.string().uuid(),
178
+ repoUrl: z.string().nullable(),
179
+ targetRef: z.string().nullable(),
180
+ modelOverride: z.string().nullable(),
181
+ runnerRequired: z.boolean(),
182
+ runtimeProfileVersion: z.number().int().nullable(),
183
+ runtimeProfileSnapshot: z.record(z.unknown()).nullable(),
184
+ activeStreamId: z.string().nullable(),
185
+ agentStreamId: z.string().nullable(),
186
+ provider: ProviderTypeSchema.default("claude-code"),
187
+ triggerSource: TriggerSourceSchema,
188
+ triggerRef: z.string().nullable(),
189
+ githubInstallationId: z.string().nullable(),
190
+ retryCount: z.number().int().default(0),
191
+ maxRetries: z.number().int().default(3),
192
+ pullRequestUrl: z.string().nullable(),
193
+ errorMessage: z.string().nullable(),
194
+ attachmentsJson: z.array(AttachmentMetaSchema).nullable(),
195
+ /** LDAP of the triggering user; null when unknown (webhook / automation). */
196
+ triggerUserLdap: z.string().nullable(),
197
+ createdAt: z.date(),
198
+ updatedAt: z.date(),
199
+ startedAt: z.date().nullable(),
200
+ completedAt: z.date().nullable()
201
+ });
202
+ var LEGACY_MODEL_ALIASES = Object.freeze({
203
+ opus: "claude-opus-4-7",
204
+ sonnet: "claude-sonnet-4-6",
205
+ haiku: "claude-haiku-4-5"
206
+ });
207
+ var BEDROCK_COMPATIBLE_MODEL_IDS = Object.freeze(
208
+ /* @__PURE__ */ new Set(["opus", "sonnet", "haiku"])
209
+ );
210
+ var MODELGATE_VENDOR_TYPES = [
211
+ "anthropic",
212
+ "openai",
213
+ "deepseek",
214
+ "google",
215
+ "zhipu",
216
+ "volcengine",
217
+ "tencent",
218
+ "moonshot",
219
+ "minimax",
220
+ "dashscope",
221
+ "xiaomi"
222
+ ];
223
+ var ModelGateVendorTypeSchema = z2.enum(MODELGATE_VENDOR_TYPES);
224
+ var AgentModeSchema = z3.enum(["task", "chat"]);
225
+ var AgentStatusSchema = z3.enum(["active", "closed", "deleted"]);
226
+ var ExternalChatSourceSchema = z3.enum(["wecom"]);
227
+ var AgentSchema = z3.object({
228
+ id: z3.string().uuid(),
229
+ projectId: z3.string().uuid(),
230
+ sandboxId: z3.string().nullable(),
231
+ agentMode: AgentModeSchema,
232
+ status: AgentStatusSchema,
233
+ customTitle: z3.string().max(200).nullable(),
234
+ /**
235
+ * Baseline git ref captured at agent (task) creation. Frozen for the
236
+ * lifetime of the agent so follow-up runs always re-clone from the
237
+ * branch the user originally selected. Nullable for chat-mode agents
238
+ * and pre-migration rows; consumers fall back to project.defaultBranch.
239
+ */
240
+ baseRef: z3.string().nullable(),
241
+ /**
242
+ * Per-agent system prompt (managed_agent profile Phase D). Seeded at
243
+ * creation from the workload default and frozen for the agent's lifetime.
244
+ * `null` → control-worker omits `PilotCoderRunConfigV1.systemPrompt` and
245
+ * agent-worker falls back to the platform-level `SYSTEM_PROMPT`.
246
+ */
247
+ systemPrompt: z3.string().nullable(),
248
+ createdBy: z3.string().nullable(),
249
+ messagesJson: z3.unknown().nullable(),
250
+ // JSONB - lightweight snapshot
251
+ lastCheckpointId: z3.string().uuid().nullable(),
252
+ activeStreamId: z3.string().nullable(),
253
+ /** External IM source that created this agent. See specs/features/wecom-chat-integration.md. */
254
+ externalChatSource: ExternalChatSourceSchema.nullable(),
255
+ /** External IM user identifier (e.g. WeCom userid). Unique per (project, source, chatid). */
256
+ externalChatUserid: z3.string().nullable(),
257
+ /** External IM chat/conversation identifier. NULL for single chats; set to WeCom `chatid`
258
+ * for group-chat conversations. Part of the composite uniqueness key (2026-04-22). */
259
+ externalChatChatid: z3.string().nullable(),
260
+ createdAt: z3.date(),
261
+ updatedAt: z3.date(),
262
+ lastActiveAt: z3.date()
263
+ });
264
+ var ArtifactKindSchema = z4.enum([
265
+ "diff",
266
+ "patch",
267
+ "log",
268
+ "screenshot",
269
+ "video",
270
+ "build",
271
+ "report"
272
+ ]);
273
+ var ArtifactManifestSchema = z4.object({
274
+ path: z4.string(),
275
+ kind: ArtifactKindSchema,
276
+ contentType: z4.string(),
277
+ size: z4.number().int().nonnegative(),
278
+ checksum: z4.string(),
279
+ required: z4.boolean()
280
+ });
281
+ var ArtifactSchema = z4.object({
282
+ id: z4.string().uuid(),
283
+ runId: z4.string().uuid(),
284
+ kind: ArtifactKindSchema,
285
+ path: z4.string(),
286
+ storagePath: z4.string(),
287
+ contentType: z4.string(),
288
+ size: z4.number().int().nonnegative(),
289
+ checksum: z4.string(),
290
+ createdAt: z4.date()
291
+ });
292
+ var CreateRunResponseSchema = z5.object({
293
+ runId: z5.string().uuid(),
294
+ agentId: z5.string().uuid(),
295
+ isNewAgent: z5.boolean()
296
+ });
297
+ var ApiResponseSchema = z5.object({
298
+ success: z5.boolean(),
299
+ data: z5.unknown().optional(),
300
+ error: z5.string().optional(),
301
+ code: z5.string().optional(),
302
+ message: z5.string().optional()
303
+ });
304
+ var FollowUpRequestSchema = z5.object({
305
+ runId: z5.string().uuid(),
306
+ message: z5.string().min(1)
307
+ });
308
+ var AbortRequestSchema = z5.object({
309
+ runId: z5.string().uuid(),
310
+ reason: z5.string().optional()
311
+ });
312
+ var GitProviderSchema = z6.enum(["gitlab", "github"]);
313
+ var ProjectKindSchema = z6.enum(["coding", "general"]);
314
+ var ProjectSchema = z6.object({
315
+ id: z6.string().uuid(),
316
+ name: z6.string().min(1),
317
+ kind: ProjectKindSchema.default("coding"),
318
+ /**
319
+ * `true` for the built-in `Platform Default` project (id =
320
+ * `PLATFORM_DEFAULT_PROJECT_ID`). System projects are visible to every
321
+ * authenticated user but read-only at the UI layer.
322
+ *
323
+ * See plans/admin-ui-project-namespacing.md §L1.1 (C3).
324
+ */
325
+ isSystem: z6.boolean().default(false),
326
+ gitProvider: GitProviderSchema.nullable(),
327
+ gitlabProjectId: z6.string().nullable(),
328
+ gitlabProjectPath: z6.string().nullable(),
329
+ githubRepoFullName: z6.string().nullable(),
330
+ githubRepoId: z6.string().nullable(),
331
+ /** Cached installation id for follow-up runs; authoritative value is on runs. */
332
+ githubInstallationId: z6.string().nullable(),
333
+ repoUrl: z6.string().nullable(),
334
+ defaultBranch: z6.string().default("main"),
335
+ defaultModel: z6.string().nullable(),
336
+ description: z6.string().nullable(),
337
+ webhookEnabled: z6.boolean().default(false),
338
+ webhookTriggerLabel: z6.string().default("pilot"),
339
+ webhookSecret: z6.string().nullable(),
340
+ webhookPromptTemplate: z6.string().nullable(),
341
+ /** WeCom aibot long-connection integration toggle. See specs/features/wecom-chat-integration.md. */
342
+ wecomEnabled: z6.boolean().default(false),
343
+ /** WeCom aibot ID; unique across projects, reverse-lookup from incoming messages. */
344
+ wecomBotId: z6.string().nullable(),
345
+ /** Reference to `credential_bindings.name` holding the long-connection SDK secret. */
346
+ wecomSecretRef: z6.string().nullable(),
347
+ /** Optional prompt prefix prepended to user message when creating a wecom_chat Run. */
348
+ wecomPromptTemplate: z6.string().nullable(),
349
+ createdAt: z6.date(),
350
+ updatedAt: z6.date()
351
+ });
352
+ var WebhookTriggerContextSchema = z7.discriminatedUnion("provider", [
353
+ z7.object({
354
+ provider: z7.literal("github"),
355
+ /** `owner/repo`, e.g. `pilot-ai/pilot` */
356
+ repoFullName: z7.string().min(1),
357
+ /** Issue or Pull Request number. */
358
+ number: z7.number().int().positive(),
359
+ /** True when the trigger came from a PR (GitHub issue_comment fires for both). */
360
+ isPr: z7.boolean(),
361
+ /** Id of the @mention comment that triggered the run (if applicable). */
362
+ commentId: z7.number().int().positive().optional(),
363
+ /**
364
+ * Installation token minted by Control Worker (GitHub App). TTL ≤ 1h;
365
+ * Agent Worker uses this to back `GitHubClient` directly.
366
+ */
367
+ installationToken: z7.string().min(1),
368
+ /** Custom GitHub API base URL (GitHub Enterprise). */
369
+ apiUrl: z7.string().url().optional()
370
+ }),
371
+ z7.object({
372
+ provider: z7.literal("gitlab"),
373
+ /** `group/subgroup/project`. */
374
+ projectPath: z7.string().min(1),
375
+ /** Issue IID or Merge Request IID. */
376
+ iid: z7.number().int().positive(),
377
+ /** True when the trigger came from an MR note. */
378
+ isMr: z7.boolean(),
379
+ /** Id of the note that triggered the run (if applicable). */
380
+ noteId: z7.number().int().positive().optional(),
381
+ /** Decrypted OAuth / PAT token used to build `GitLabClient`. */
382
+ accessToken: z7.string().min(1),
383
+ /** GitLab instance URL (e.g. `https://gitlab.example.com`). */
384
+ instanceUrl: z7.string().url()
385
+ })
386
+ ]);
387
+ var CheckpointStatusSchema = z8.enum(["in_progress", "completed", "failed"]);
388
+ var RecoveryTypeSchema = z8.enum([
389
+ "normal",
390
+ // 正常恢复(有 checkpoint)
391
+ "zero_context",
392
+ // 零起点恢复(无 checkpoint,预期)
393
+ "context_loss"
394
+ // 上下文丢失(有 checkpoint 但丢失,异常)
395
+ ]);
396
+ var DegradedReasonSchema = z8.enum([
397
+ "no_checkpoint",
398
+ // 无 checkpoint
399
+ "context_mismatch",
400
+ // 上下文不一致
401
+ "checkpoint_corrupt",
402
+ // Checkpoint 损坏
403
+ "checkpoint_storage_unavailable"
404
+ // 对象存储 checkpoint 不可用(Phase 2 未实现)
405
+ ]);
406
+ var CheckpointTriggerSourceSchema = z8.enum([
407
+ "finalization",
408
+ // Run Finalization 后(Phase 1)
409
+ "turn_count",
410
+ // Turn 计数触发(Phase 2)
411
+ "time_interval",
412
+ // 定时器触发(Phase 2)
413
+ "critical_tool",
414
+ // 关键工具调用触发(Phase 2)
415
+ "idle"
416
+ // Sandbox idle 前触发(Phase 2)
417
+ ]);
418
+ var RunCheckpointSchema = z8.object({
419
+ id: z8.string().uuid(),
420
+ agentId: z8.string().uuid(),
421
+ runId: z8.string().uuid().nullable(),
422
+ checkpointStatus: CheckpointStatusSchema,
423
+ messagesSnapshot: z8.array(z8.unknown()).nullable(),
424
+ messagesSnapshotRef: z8.string().nullable(),
425
+ lastEventCursor: z8.number().int().nullable(),
426
+ pendingToolCalls: z8.unknown().nullable(),
427
+ workspaceDeltaManifestRef: z8.string().nullable(),
428
+ runtimeProfileSnapshot: z8.record(z8.unknown()).nullable(),
429
+ triggerSource: CheckpointTriggerSourceSchema.nullable().optional(),
430
+ degradedRecovery: z8.boolean().default(false),
431
+ createdAt: z8.date()
432
+ });
433
+ var AgentRestoreRequestSchema = z8.object({
434
+ runId: z8.string(),
435
+ agentId: z8.string(),
436
+ messages: z8.array(z8.unknown()),
437
+ messagesHash: z8.string(),
438
+ lastEventId: z8.number().int().optional(),
439
+ pendingToolCalls: z8.array(z8.unknown()).optional(),
440
+ workspaceHydrationRef: z8.string().optional(),
441
+ runtimeProfileSnapshot: z8.record(z8.unknown()).optional(),
442
+ degradedRecovery: z8.boolean().optional()
443
+ });
444
+ var AgentRestoreResponseSchema = z8.object({
445
+ success: z8.boolean(),
446
+ recovered: z8.boolean(),
447
+ messagesHash: z8.string().optional(),
448
+ messagesCount: z8.number().int().optional(),
449
+ degradedRecovery: z8.boolean().optional(),
450
+ error: z8.string().optional()
451
+ });
452
+ var McpServerEntrySchema = z8.union([
453
+ // stdio entry
454
+ z8.object({
455
+ command: z8.string().min(1),
456
+ args: z8.array(z8.string()).optional(),
457
+ env: z8.record(z8.string()).optional()
458
+ }).passthrough(),
459
+ // http / sse entry
460
+ z8.object({
461
+ type: z8.enum(["http", "sse"]),
462
+ url: z8.string().url(),
463
+ headers: z8.record(z8.string()).optional()
464
+ }).passthrough()
465
+ ]);
466
+ var McpServersMapSchema = z8.record(McpServerEntrySchema);
467
+ var PromptRequestSchema = z8.object({
468
+ runId: z8.string().optional(),
469
+ agentId: z8.string().optional(),
470
+ prompt: z8.string().min(1),
471
+ provider: ProviderTypeSchema.optional(),
472
+ model: z8.string().optional(),
473
+ workspacePath: z8.string().optional(),
474
+ /**
475
+ * Directory holding the bootstrap-rendered `.mcp.json`. Decoupled from
476
+ * `workspacePath` (which is the agent CWD = user repo) so MCP config never
477
+ * lands inside the user's project tree. When omitted, agent-worker falls
478
+ * back to `workspacePath` for backwards compatibility.
479
+ */
480
+ mcpConfigDir: z8.string().optional(),
481
+ attachments: z8.array(AttachmentMetaSchema).max(5).optional(),
482
+ /**
483
+ * Runtime-derived context for webhook-triggered runs. When present, Agent
484
+ * Worker injects a set of read-only provider tools so the agent can pull
485
+ * Issue/PR body / history / diff on demand. See `webhook-context.ts`.
486
+ */
487
+ triggerContext: WebhookTriggerContextSchema.optional(),
488
+ /**
489
+ * Resolved MCP servers to inject directly into the SDK (preferred over
490
+ * `<mcpConfigDir>/.mcp.json`). When omitted, the agent-worker falls back
491
+ * to reading `.mcp.json` from `mcpConfigDir` / `workspacePath` (the legacy
492
+ * bootstrap path).
493
+ */
494
+ mcpServers: McpServersMapSchema.optional(),
495
+ /**
496
+ * Run-scoped environment variables to inject into the AI CLI subprocess
497
+ * spawned by agent-worker (e.g. `MCP_<NAME>_BEARER_TOKEN` referenced by
498
+ * codex `config.toml`'s `bearer_token_env_var`). Pilot keeps these out
499
+ * of the on-disk config files so tokens never land on the sandbox FS.
500
+ * Merged into `ProviderConfig.env` by agent-worker.
501
+ */
502
+ env: z8.record(z8.string(), z8.string()).optional(),
503
+ projectKind: ProjectKindSchema.optional().default("coding")
504
+ });
505
+ var FollowupRequestSchema = z8.object({
506
+ runId: z8.string().optional(),
507
+ agentId: z8.string().optional(),
508
+ message: z8.string(),
509
+ provider: ProviderTypeSchema.optional(),
510
+ model: z8.string().optional(),
511
+ workspacePath: z8.string().optional(),
512
+ /** See `PromptRequestSchema.mcpConfigDir`. */
513
+ mcpConfigDir: z8.string().optional(),
514
+ expectedMessagesHash: z8.string().optional(),
515
+ expectedMessagesCount: z8.number().int().optional(),
516
+ attachments: z8.array(AttachmentMetaSchema).max(5).optional(),
517
+ /** See `PromptRequestSchema.mcpServers` — same semantics for follow-ups. */
518
+ mcpServers: McpServersMapSchema.optional(),
519
+ /** See `PromptRequestSchema.env` — same semantics for follow-ups. */
520
+ env: z8.record(z8.string(), z8.string()).optional(),
521
+ projectKind: ProjectKindSchema.optional().default("coding")
522
+ });
523
+ var RunnerRestorePolicySchema = z8.enum(["restart", "lazy-start", "skip"]);
524
+ var HydrationCategorySchema = z8.enum([
525
+ "conversation",
526
+ "workspace",
527
+ "runtimeEnv",
528
+ "runner",
529
+ "attachments",
530
+ "artifactsRef"
531
+ ]);
532
+ var HydrationManifestEntrySchema = z8.object({
533
+ category: HydrationCategorySchema,
534
+ ref: z8.string(),
535
+ checksum: z8.string().optional(),
536
+ size: z8.number().int().optional()
537
+ });
538
+ var UIMessageChunkTypeSchema = z9.enum([
539
+ "text-start",
540
+ "text-delta",
541
+ "text-end",
542
+ "reasoning-start",
543
+ "reasoning-delta",
544
+ "reasoning-end",
545
+ "tool-input-start",
546
+ "tool-input-delta",
547
+ "tool-input-available",
548
+ "tool-output-available",
549
+ "tool-output-error",
550
+ "start",
551
+ "finish",
552
+ "error",
553
+ "start-step",
554
+ "finish-step"
555
+ ]);
556
+ var UIMessageChunkSchema = z9.object({
557
+ type: UIMessageChunkTypeSchema,
558
+ id: z9.string().optional(),
559
+ content: z9.string().optional(),
560
+ delta: z9.string().optional(),
561
+ toolCallId: z9.string().optional(),
562
+ toolName: z9.string().optional(),
563
+ input: z9.unknown().optional(),
564
+ output: z9.string().optional(),
565
+ errorText: z9.string().optional(),
566
+ reason: z9.string().optional(),
567
+ preliminary: z9.boolean().optional()
568
+ });
569
+ var RunEventSchema = z9.object({
570
+ id: z9.string().uuid(),
571
+ runId: z9.string().uuid(),
572
+ eventType: z9.string(),
573
+ payload: z9.unknown(),
574
+ cursor: z9.number().int(),
575
+ createdAt: z9.date()
576
+ });
577
+ var AgentRecoveryStartedEventSchema = z9.object({
578
+ type: z9.literal("agent_recovery_started"),
579
+ agentId: z9.string(),
580
+ sandboxId: z9.string(),
581
+ degradedRecovery: z9.boolean(),
582
+ degradedReason: DegradedReasonSchema.optional(),
583
+ recoveryType: RecoveryTypeSchema
584
+ });
585
+ var AgentRecoveryHydratedEventSchema = z9.object({
586
+ type: z9.literal("agent_recovery_hydrated"),
587
+ agentId: z9.string(),
588
+ checkpointId: z9.string().nullable(),
589
+ messagesCount: z9.number(),
590
+ degradedRecovery: z9.boolean()
591
+ });
592
+ var RecoveredFromCheckpointEventSchema = z9.object({
593
+ type: z9.literal("recovered_from_checkpoint"),
594
+ checkpointId: z9.string(),
595
+ lastEventCursor: z9.number().int().nullable()
596
+ });
597
+ var AgentRecoveryCompletedEventSchema = z9.object({
598
+ type: z9.literal("agent_recovery_completed"),
599
+ agentId: z9.string(),
600
+ degradedRecovery: z9.boolean()
601
+ });
602
+ var AgentRecoveryFailedEventSchema = z9.object({
603
+ type: z9.literal("agent_recovery_failed"),
604
+ agentId: z9.string(),
605
+ errorStage: z9.string(),
606
+ errorMessage: z9.string(),
607
+ degradedReason: DegradedReasonSchema.optional(),
608
+ contextExpected: z9.number().optional(),
609
+ contextActual: z9.number().optional()
610
+ });
611
+ var SandboxStatusSchema = z10.enum([
612
+ "creating",
613
+ "running",
614
+ "idle",
615
+ "destroying",
616
+ "destroyed",
617
+ "error"
618
+ ]);
619
+ var SandboxPublicEndpointSchema = z10.object({
620
+ name: z10.string(),
621
+ url: z10.string(),
622
+ host: z10.string(),
623
+ path: z10.string()
624
+ });
625
+ var SandboxInfoSchema = z10.object({
626
+ id: z10.string(),
627
+ status: SandboxStatusSchema,
628
+ podIp: z10.string().nullable(),
629
+ agentEndpoint: z10.string().nullable(),
630
+ createdAt: z10.date(),
631
+ ttlSeconds: z10.number().int().optional(),
632
+ templateName: z10.string().optional(),
633
+ labels: z10.record(z10.string()).optional(),
634
+ /**
635
+ * GAP 3 — sandbox-actual public endpoints transited from the provider SDK.
636
+ * Optional/absent for providers that do not report them (and for legacy
637
+ * call sites); downstream consumers MUST treat absence as "no transit data"
638
+ * and fall back to declaration-derived URLs.
639
+ */
640
+ publicEndpoints: z10.array(SandboxPublicEndpointSchema).optional()
641
+ });
642
+ var CreateSandboxOptionsSchema = z10.object({
643
+ templateName: z10.string(),
644
+ /**
645
+ * Caller-supplied stable claim name. When omitted, the provider lets the
646
+ * sandbox control plane generate a per-sandbox id (`claim-<nanoTS>`), which
647
+ * changes on every create — so the derived public ingress host
648
+ * (`<hostPrefix>-<claimName>.<baseDomain>`) drifts across recreate.
649
+ *
650
+ * Supplying a stable, caller-controlled value (e.g. a project-scoped key)
651
+ * keeps the ingress host stable across abort→recreate cycles (GAP 1 = B:
652
+ * scale-to-zero is abort + recreate, not pause/wake). MUST be DNS-label safe
653
+ * (lowercase alphanumeric + hyphen); the control plane truncates the
654
+ * `<hostPrefix>-<claimName>` first label to 63 chars, so callers must ensure
655
+ * the distinguishing portion fits within budget.
656
+ */
657
+ claimName: z10.string().optional(),
658
+ image: z10.string().optional(),
659
+ env: z10.record(z10.string()).optional(),
660
+ ttlSeconds: z10.number().int().positive().optional(),
661
+ metadata: z10.record(z10.string()).optional(),
662
+ labels: z10.record(z10.string()).optional()
663
+ });
664
+ var ExecResultSchema = z10.object({
665
+ exitCode: z10.number().int(),
666
+ stdout: z10.string(),
667
+ stderr: z10.string()
668
+ });
669
+ var MergeRequestStatusSchema = z11.enum(["creating", "open", "merged", "closed", "failed"]);
670
+ var MergeRequestSchema = z11.object({
671
+ id: z11.string().uuid(),
672
+ runId: z11.string().uuid(),
673
+ projectId: z11.string().uuid(),
674
+ externalId: z11.string().nullable(),
675
+ externalUrl: z11.string().nullable(),
676
+ sourceBranch: z11.string(),
677
+ targetBranch: z11.string(),
678
+ title: z11.string(),
679
+ description: z11.string().nullable(),
680
+ status: MergeRequestStatusSchema,
681
+ createdAt: z11.date(),
682
+ updatedAt: z11.date()
683
+ });
684
+ var HealthCheckConfigSchema = z12.object({
685
+ type: z12.enum(["http", "tcp", "command"]),
686
+ port: z12.number().int().optional(),
687
+ path: z12.string().optional(),
688
+ command: z12.string().optional(),
689
+ intervalMs: z12.number().int().positive().default(5e3),
690
+ timeoutMs: z12.number().int().positive().default(3e3),
691
+ retries: z12.number().int().nonnegative().default(3)
692
+ });
693
+ var RuntimeProfileSchema = z12.object({
694
+ id: z12.string().uuid(),
695
+ projectId: z12.string().uuid(),
696
+ version: z12.number().int().positive(),
697
+ env: z12.record(z12.string()).default({}),
698
+ secretRefs: z12.record(z12.string()).default({}),
699
+ workingDirectory: z12.string().default("/workspace"),
700
+ runnerCommand: z12.string().optional(),
701
+ runnerPorts: z12.array(z12.number().int().positive()).optional(),
702
+ healthCheck: HealthCheckConfigSchema.optional(),
703
+ prepareCommands: z12.array(z12.string()).optional(),
704
+ status: z12.enum(["active", "archived"]).default("active"),
705
+ createdAt: z12.date(),
706
+ updatedAt: z12.date()
707
+ });
708
+ var MAX_SUMMARIZE_PROMPT_CHARS = 1e4;
709
+ var SummarizeRequestSchema = z13.object({
710
+ /** Full diff text (legacy mode). Optional when repoDir is provided. */
711
+ diff: z13.string().min(1).optional(),
712
+ /** Workspace repo directory path (agentic mode). Must be an absolute path. */
713
+ repoDir: z13.string().startsWith("/", { message: "repoDir must be an absolute path" }).optional(),
714
+ /** Git diff reference, e.g. "--cached" or "origin/main...HEAD". */
715
+ diffRef: z13.string().regex(/^(--cached|[a-zA-Z0-9_.\-\/~^]+(\.\.\.?[a-zA-Z0-9_.\-\/~^]+)?)$/, {
716
+ message: "diffRef must be '--cached' or a valid git ref (e.g. 'origin/main..HEAD', 'origin/main...HEAD')"
717
+ }).optional(),
718
+ prompt: z13.string().max(MAX_SUMMARIZE_PROMPT_CHARS).optional(),
719
+ model: z13.string().optional()
720
+ }).refine((data) => data.diff || data.repoDir, {
721
+ message: "Either 'diff' or 'repoDir' must be provided"
722
+ });
723
+ var SummarizeResponseSchema = z13.object({
724
+ commitMessage: z13.string().min(1).max(200).describe(
725
+ "Single-line commit message in conventional commits format: <type>(<scope>): <description>"
726
+ ),
727
+ prTitle: z13.string().min(1).max(256).describe(
728
+ "Pull request title, descriptive. Aim for under 72 characters but the schema accepts up to 256 (GitHub/GitLab hard limit) to tolerate model overshoot."
729
+ ),
730
+ prDescription: z13.string().min(1).describe(
731
+ "Pull request description in markdown. Start with ## Changes, then list key changes as bullet points."
732
+ )
733
+ });
734
+ var MAX_WORKSPACE_DIFF_BYTES = 20 * 1024 * 1024;
735
+ var WorkspaceDiffStatResponseSchema = z14.object({
736
+ filesChanged: z14.number().int().nonnegative(),
737
+ insertions: z14.number().int().nonnegative(),
738
+ deletions: z14.number().int().nonnegative(),
739
+ estimatedBytes: z14.number().int().nonnegative()
740
+ });
741
+ var AGENT_PUSH_OUTPUT_TRUNCATE_BYTES = 8 * 1024;
742
+ var AGENT_PUSH_MAX_ATTEMPTS = 3;
743
+ var AgentPushRetryReasonSchema = z15.enum([
744
+ "gnutls_recv_error",
745
+ "rpc_failed",
746
+ "connection_reset",
747
+ "timeout",
748
+ "broken_pipe",
749
+ "early_eof",
750
+ "dns"
751
+ ]);
752
+ var AgentPushAuthSchema = z15.discriminatedUnion("kind", [
753
+ z15.object({
754
+ kind: z15.literal("github"),
755
+ username: z15.string().min(1),
756
+ token: z15.string().min(1)
757
+ }),
758
+ z15.object({
759
+ kind: z15.literal("gitlab"),
760
+ token: z15.string().min(1)
761
+ })
762
+ ]);
763
+ var AgentPushRequestSchema = z15.object({
764
+ /** Absolute path inside the sandbox to the git working directory. */
765
+ repoDir: z15.string().refine((s) => s.startsWith("/"), {
766
+ message: "repoDir must be an absolute path"
767
+ }),
768
+ /** Remote name, typically `origin`. */
769
+ remote: z15.string().min(1).default("origin"),
770
+ /** Branch to push. */
771
+ branch: z15.string().min(1),
772
+ /** When true, appends `--force`. Default `false`. */
773
+ force: z15.boolean().default(false),
774
+ auth: AgentPushAuthSchema
775
+ });
776
+ var AgentPushResponseSchema = z15.object({
777
+ /** Convenience flag — equivalent to `exitCode === 0`. */
778
+ ok: z15.boolean(),
779
+ /**
780
+ * Final `git push` process exit code (from the last attempt if
781
+ * retries happened). `0` on success. Non-zero values follow git's
782
+ * own conventions (e.g. `128` for fatal errors).
783
+ */
784
+ exitCode: z15.number().int(),
785
+ /** Captured stdout, truncated per AGENT_PUSH_OUTPUT_TRUNCATE_BYTES. */
786
+ stdout: z15.string(),
787
+ /** Captured stderr, truncated per AGENT_PUSH_OUTPUT_TRUNCATE_BYTES. */
788
+ stderr: z15.string(),
789
+ /** Total wall time across all attempts, in milliseconds. */
790
+ durationMs: z15.number().int().nonnegative(),
791
+ /**
792
+ * Number of attempts actually made. Always ≥ 1 and
793
+ * ≤ AGENT_PUSH_MAX_ATTEMPTS.
794
+ */
795
+ attempts: z15.number().int().min(1).max(AGENT_PUSH_MAX_ATTEMPTS),
796
+ /**
797
+ * Reason for the most recent retry. Present only when `attempts > 1`.
798
+ * Absent when the initial attempt succeeded or when the failure was
799
+ * classified as non-transient (auth failure, non-fast-forward, etc.).
800
+ */
801
+ lastRetryReason: AgentPushRetryReasonSchema.optional()
802
+ });
803
+ var CredentialsBrokerRequestSchema = z16.object({}).strict();
804
+ var GitProviderCredentialSchema = z16.object({
805
+ /** Git hosting provider name. */
806
+ provider: z16.enum(["github", "gitlab"]),
807
+ /**
808
+ * Short-lived access token. For GitHub App, this is an installation
809
+ * token (~1 hour TTL). For GitLab OAuth, this is the just-refreshed
810
+ * access token.
811
+ */
812
+ accessToken: z16.string().min(1),
813
+ /** ISO-8601 expiry; callers MUST NOT use the token beyond this. */
814
+ expiresAt: z16.string().datetime(),
815
+ /**
816
+ * Monotonic rotation counter. The Pod Agent uses this to invalidate
817
+ * its in-memory cache on refresh; bumps every time the broker hands
818
+ * out a token (so two consecutive calls return different versions
819
+ * even if the upstream provider returned the same string).
820
+ */
821
+ rotationVersion: z16.number().int().nonnegative(),
822
+ /** GitLab only: the instance base URL the token was minted for. */
823
+ instanceUrl: z16.string().url().optional()
824
+ });
825
+ var LlmCredentialSchema = z16.object({
826
+ /** LLM provider name. `bedrock` covers the per-LDAP AK/SK path. */
827
+ provider: z16.enum(["bedrock", "anthropic"]),
828
+ /** Base URL the Worker / proxy should target. */
829
+ baseUrl: z16.string().url(),
830
+ /**
831
+ * HTTP headers the proxy must send upstream. May contain the
832
+ * Bedrock-related AWS overrides (encoded as headers consumed by the
833
+ * Pod-Agent local proxy, not as bare AWS sig v4 yet — see proposal in
834
+ * `docs/proposals/pilot-v2-llm-proxy.md`).
835
+ */
836
+ headers: z16.record(z16.string(), z16.string()),
837
+ /**
838
+ * Optional expiry. Bedrock AK/SK are long-lived; this is present only
839
+ * when the underlying credential issuer (e.g. STS-backed Bedrock
840
+ * adapter in the future) returns a TTL.
841
+ */
842
+ expiresAt: z16.string().datetime().optional()
843
+ });
844
+ var OssCredentialSchema = z16.object({
845
+ /** OSS region (e.g. `oss-cn-beijing`). */
846
+ region: z16.string().min(1),
847
+ /** Target bucket. */
848
+ bucket: z16.string().min(1),
849
+ /**
850
+ * Per-session prefix the Worker MUST stay within (the presigned URL
851
+ * is scoped to a single object key, but the prefix is exposed so the
852
+ * client can compose multi-key flows by requesting fresh URLs).
853
+ */
854
+ prefix: z16.string().min(1),
855
+ /**
856
+ * Pre-signed PUT URL for the Session's default artifact object key
857
+ * (`${prefix}artifact.bin` by convention). Phase 1 fallback in place
858
+ * of true STS credentials. Single-use semantics: callers needing a
859
+ * different object key MUST call this endpoint again.
860
+ */
861
+ presignedUploadUrl: z16.string().url(),
862
+ /** ISO-8601 expiry of the presigned URL. */
863
+ expiresAt: z16.string().datetime(),
864
+ // Reserved for the future STS variant. Optional today.
865
+ stsAccessKeyId: z16.string().optional(),
866
+ stsSecretAccessKey: z16.string().optional(),
867
+ stsSessionToken: z16.string().optional()
868
+ });
869
+ var CredentialsBrokerErrorCodeSchema = z16.enum([
870
+ // 401 — authentication failures
871
+ "MISSING_SESSION_TOKEN",
872
+ "MISSING_POD_AGENT_TOKEN",
873
+ "SESSION_TOKEN_INVALID",
874
+ "SESSION_TOKEN_REVOKED",
875
+ "SESSION_TOKEN_EXPIRED",
876
+ "POD_AGENT_TOKEN_INVALID",
877
+ // 403 — authorization failures
878
+ "SESSION_TOKEN_SESSION_MISMATCH",
879
+ // 404 — session does not exist
880
+ "SESSION_NOT_FOUND",
881
+ // 503 — upstream credential issuer (GitHub App / Vault / OSS) is down
882
+ "GIT_PROVIDER_NOT_CONFIGURED",
883
+ "GIT_TOKEN_UNAVAILABLE",
884
+ "LLM_CREDENTIAL_UNAVAILABLE",
885
+ "OSS_STS_UNAVAILABLE",
886
+ // 500 — fallthrough
887
+ "INTERNAL_ERROR"
888
+ ]);
889
+ var InvalidateKeysRequestSchema = z17.object({
890
+ sessionId: z17.string().uuid(),
891
+ runId: z17.string().uuid().optional(),
892
+ ldap: z17.string().min(1).max(255),
893
+ provider: z17.enum(["claude-code", "codex"]),
894
+ observedAt: z17.string().datetime({ offset: true }),
895
+ reason: z17.string().max(500).optional()
896
+ });
897
+ var InvalidateKeysResponseSchema = z17.object({
898
+ pushed: z17.boolean(),
899
+ /** Optional sub-status; useful for clients to surface diagnostic detail
900
+ * without parsing prose. */
901
+ reasonCode: z17.string().max(100).optional()
902
+ });
903
+ var ReloadCredentialsRequestSchema = z17.object({
904
+ env: z17.record(z17.string().min(1), z17.string()).refine((rec) => Object.keys(rec).length > 0, {
905
+ message: "env must contain at least one entry"
906
+ })
907
+ });
908
+ var ReloadCredentialsResponseSchema = z17.object({
909
+ applied: z17.array(z17.string())
910
+ });
911
+ var PodAgentGitPushRequestSchema = z18.object({
912
+ /** Lease token issued by pod-agent at worker startup; same value used by clone. */
913
+ leaseToken: z18.string().min(1),
914
+ /** Absolute workspace path returned by an earlier `/pilot/workspace/clone`. */
915
+ workspaceDir: z18.string().refine((s) => s.startsWith("/"), {
916
+ message: "workspaceDir must be an absolute path"
917
+ }),
918
+ /** Remote name. Defaults to `origin`. */
919
+ remote: z18.string().min(1).default("origin"),
920
+ /** Branch to push. */
921
+ branch: z18.string().min(1),
922
+ /** Whether to add `--force`. Default `false`. */
923
+ force: z18.boolean().default(false)
924
+ }).strict();
925
+ var PodAgentGitPushResponseSchema = z18.discriminatedUnion("kind", [
926
+ z18.object({
927
+ kind: z18.literal("ok"),
928
+ /** Final `git push` process exit code (0 = success). */
929
+ exitCode: z18.number().int(),
930
+ /** Captured stdout, truncated per AGENT_PUSH_OUTPUT_TRUNCATE_BYTES. */
931
+ stdout: z18.string(),
932
+ /** Captured stderr, truncated per AGENT_PUSH_OUTPUT_TRUNCATE_BYTES. */
933
+ stderr: z18.string(),
934
+ /** Total wall time across all attempts, in milliseconds. */
935
+ durationMs: z18.number().int().nonnegative(),
936
+ /** Number of attempts actually made (1..AGENT_PUSH_MAX_ATTEMPTS). */
937
+ attempts: z18.number().int().min(1).max(AGENT_PUSH_MAX_ATTEMPTS),
938
+ /** Reason for the most recent retry; present only when attempts > 1. */
939
+ lastRetryReason: AgentPushRetryReasonSchema.optional()
940
+ }),
941
+ z18.object({
942
+ kind: z18.literal("failed"),
943
+ /** Human-readable failure reason; safe to surface in delivery audit row. */
944
+ reason: z18.string().min(1),
945
+ /** Coarse failure category for caller branching. */
946
+ code: z18.enum(["AUTH_FETCH_FAILED", "INVALID_WORKSPACE", "INTERNAL", "TRANSPORT_FAILED"]).optional()
947
+ })
948
+ ]);
949
+ var WecomMsgTypeSchema = z19.enum([
950
+ "text",
951
+ "image",
952
+ "file",
953
+ "mixed",
954
+ "voice",
955
+ "video",
956
+ "stream"
957
+ ]);
958
+ var WecomChatTypeSchema = z19.enum(["single", "group"]);
959
+ var WecomSenderSchema = z19.object({
960
+ userid: z19.string().min(1)
961
+ });
962
+ var WecomTextContentSchema = z19.object({
963
+ content: z19.string()
964
+ });
965
+ var WecomImageContentSchema = z19.object({
966
+ url: z19.string().url(),
967
+ /** AES-256-CBC key (Base64) tied to this specific payload. Present in
968
+ * long-connection mode — use with SDK `decryptFile(buffer, aesKey)`. */
969
+ aeskey: z19.string().optional()
970
+ });
971
+ var WecomFileContentSchema = z19.object({
972
+ url: z19.string().url(),
973
+ /** AES-256-CBC key (Base64) tied to this specific payload. */
974
+ aeskey: z19.string().optional()
975
+ });
976
+ var WecomVoiceContentSchema = z19.object({
977
+ /** Voice transcribed to text by WeCom (not a URL). */
978
+ content: z19.string()
979
+ });
980
+ var WecomVideoContentSchema = z19.object({
981
+ url: z19.string().url(),
982
+ /** AES-256-CBC key (Base64) tied to this specific payload. */
983
+ aeskey: z19.string().optional()
984
+ });
985
+ var WecomMixedItemSchema = z19.discriminatedUnion("msgtype", [
986
+ z19.object({ msgtype: z19.literal("text"), text: WecomTextContentSchema }),
987
+ z19.object({ msgtype: z19.literal("image"), image: WecomImageContentSchema })
988
+ ]);
989
+ var WecomMixedContentSchema = z19.object({
990
+ msg_item: z19.array(WecomMixedItemSchema).min(1)
991
+ });
992
+ var WecomQuoteSchema = z19.object({
993
+ msgtype: z19.enum(["text", "image", "mixed", "voice", "file", "video"]),
994
+ text: WecomTextContentSchema.optional(),
995
+ image: WecomImageContentSchema.optional(),
996
+ mixed: WecomMixedContentSchema.optional(),
997
+ voice: WecomVoiceContentSchema.optional(),
998
+ file: WecomFileContentSchema.optional(),
999
+ video: WecomVideoContentSchema.optional()
1000
+ });
1001
+ var WecomStreamRefSchema = z19.object({
1002
+ id: z19.string().min(1)
1003
+ });
1004
+ var wecomBasePayload = {
1005
+ /** Unique message id for dedup (potential duplicate delivery). */
1006
+ msgid: z19.string().min(1),
1007
+ /** WeCom aibot id, used to reverse-lookup which Pilot project owns this bot. */
1008
+ aibotid: z19.string().min(1),
1009
+ /** Group chat id; only present when chattype === "group". */
1010
+ chatid: z19.string().optional(),
1011
+ chattype: WecomChatTypeSchema,
1012
+ from: WecomSenderSchema,
1013
+ /** Temporary push URL for active replies (short-lived). Optional in stream frames. */
1014
+ response_url: z19.string().optional(),
1015
+ /** Optional quote reference if the user quoted a prior message. */
1016
+ quote: WecomQuoteSchema.optional()
1017
+ };
1018
+ var WecomMessagePayloadSchema = z19.discriminatedUnion("msgtype", [
1019
+ z19.object(__spreadProps(__spreadValues({}, wecomBasePayload), {
1020
+ msgtype: z19.literal("text"),
1021
+ text: WecomTextContentSchema
1022
+ })),
1023
+ z19.object(__spreadProps(__spreadValues({}, wecomBasePayload), {
1024
+ msgtype: z19.literal("image"),
1025
+ image: WecomImageContentSchema
1026
+ })),
1027
+ z19.object(__spreadProps(__spreadValues({}, wecomBasePayload), {
1028
+ msgtype: z19.literal("file"),
1029
+ file: WecomFileContentSchema
1030
+ })),
1031
+ z19.object(__spreadProps(__spreadValues({}, wecomBasePayload), {
1032
+ msgtype: z19.literal("mixed"),
1033
+ mixed: WecomMixedContentSchema
1034
+ })),
1035
+ z19.object(__spreadProps(__spreadValues({}, wecomBasePayload), {
1036
+ msgtype: z19.literal("voice"),
1037
+ voice: WecomVoiceContentSchema
1038
+ })),
1039
+ z19.object(__spreadProps(__spreadValues({}, wecomBasePayload), {
1040
+ msgtype: z19.literal("video"),
1041
+ video: WecomVideoContentSchema
1042
+ })),
1043
+ z19.object(__spreadProps(__spreadValues({}, wecomBasePayload), {
1044
+ msgtype: z19.literal("stream"),
1045
+ stream: WecomStreamRefSchema
1046
+ }))
1047
+ ]);
1048
+ var WecomConfigActionSchema = z20.enum(["enable", "update", "disable"]);
1049
+ var WecomConfigChangeEventSchema = z20.object({
1050
+ projectId: z20.string().min(1),
1051
+ action: WecomConfigActionSchema,
1052
+ /**
1053
+ * Current bot id post-change. `null` on disable when the operator
1054
+ * cleared it alongside the disable; absent when the patch didn't
1055
+ * touch bot_id.
1056
+ */
1057
+ botId: z20.string().nullable().optional()
1058
+ });
1059
+ var WecomCredentialLayerSchema = z21.enum(["user", "owner", "project", "service"]);
1060
+ var WecomPushTargetSchema = z21.object({
1061
+ /** Project that owns the bot — used by dispatcher subscribers to
1062
+ * filter messages addressed to bots this pod doesn't lead. */
1063
+ projectId: z21.string().min(1),
1064
+ /** Agent id the run belongs to. Rendered into the card's `card_action`
1065
+ * Portal link so the user can jump to `/agents/<agentId>` to read
1066
+ * the result. */
1067
+ agentId: z21.string().min(1),
1068
+ /** "single" or "group" — chooses whether the dispatcher prefixes the
1069
+ * outbound card with a `<@triggerUserid>` markdown so the original
1070
+ * sender gets a real @ notification (template_card cannot carry
1071
+ * inline mentions). */
1072
+ chatType: z21.enum(["single", "group"]),
1073
+ /** Destination passed verbatim to `wsClient.sendMessage`. Userid for
1074
+ * single chats, chatid for group chats. */
1075
+ chatTarget: z21.string().min(1),
1076
+ /** Userid that triggered the run. Used (a) to build the `<@userid>`
1077
+ * markdown in group-chat pushes and (b) by future audit / logging. */
1078
+ triggerUserid: z21.string().min(1),
1079
+ /** Layer the layered Git-credential resolver landed on, when the
1080
+ * resolver was wired and produced a hit. Absent → `null` semantically:
1081
+ * resolver wired but no tier matched (user should configure a PAT)
1082
+ * iff `credentialResolverEnabled` is true; otherwise legacy
1083
+ * pre-resolver deployment (env PAT path). */
1084
+ credentialLayer: WecomCredentialLayerSchema.optional(),
1085
+ /** True iff the resolver was wired into the message handler. Lets
1086
+ * the dispatcher distinguish "no PAT in any tier → user-actionable
1087
+ * error card" from "legacy deployment, env PAT was the intended
1088
+ * path → generic error card". */
1089
+ credentialResolverEnabled: z21.boolean()
1090
+ });
1091
+ var WecomPushEventSchema = z21.object({
1092
+ runId: z21.string().uuid(),
1093
+ success: z21.boolean(),
1094
+ /** Optional human-readable error reason. Only meaningful when
1095
+ * `success === false`; ignored otherwise. */
1096
+ reason: z21.string().optional()
1097
+ });
1098
+ var GitTokenSchema = z22.string().transform((s) => s.trim()).pipe(
1099
+ z22.string().min(1, "token must not be empty").max(1024).regex(
1100
+ /^[\x21-\x7e]+$/,
1101
+ "token must contain only printable ASCII characters (no whitespace or special symbols)"
1102
+ )
1103
+ );
1104
+ var UserGitCredentialMetadataSchema = z22.object({
1105
+ provider: GitProviderSchema,
1106
+ instanceUrl: z22.string().url(),
1107
+ tokenScope: z22.string().nullable(),
1108
+ expiresAt: z22.coerce.date().nullable(),
1109
+ lastValidatedAt: z22.coerce.date(),
1110
+ createdAt: z22.coerce.date(),
1111
+ updatedAt: z22.coerce.date()
1112
+ });
1113
+ var UpsertUserGitCredentialSchema = z22.object({
1114
+ provider: GitProviderSchema,
1115
+ instanceUrl: z22.string().url(),
1116
+ token: GitTokenSchema,
1117
+ tokenScope: z22.string().optional(),
1118
+ expiresAt: z22.coerce.date().optional()
1119
+ });
1120
+ var UserGitCredentialKeySchema = z22.object({
1121
+ provider: GitProviderSchema,
1122
+ instanceUrl: z22.string().url()
1123
+ });
1124
+ var ProjectSharedCredentialMetadataSchema = z22.object({
1125
+ sharedGitlabTokenConfigured: z22.boolean().default(false),
1126
+ sharedGithubTokenConfigured: z22.boolean().default(false)
1127
+ });
1128
+ var UpsertProjectSharedCredentialSchema = z22.object({
1129
+ provider: GitProviderSchema,
1130
+ token: GitTokenSchema
1131
+ });
1132
+ var PlatformScopeSchema = z23.enum([
1133
+ // Project-level (clamped by target_project_ids ∩ ACL)
1134
+ "project:read",
1135
+ "project:settings",
1136
+ "agents:write",
1137
+ "runs:create",
1138
+ "runs:stream",
1139
+ "runs:abort",
1140
+ "runs:merge",
1141
+ "files:upload",
1142
+ "pool:acquire",
1143
+ // User-level (not clamped by project allowlist)
1144
+ "user:credentials",
1145
+ "integrations:git:read",
1146
+ // Admin-only (separate approval)
1147
+ "sessions:terminate",
1148
+ "resources:cleanup",
1149
+ "pool:admin",
1150
+ "admin:bedrock-sync"
1151
+ ]);
1152
+ var ScopeTemplateSchema = z23.enum([
1153
+ "read_only",
1154
+ "ci_automation",
1155
+ "trigger_only",
1156
+ "full_automation",
1157
+ "custom"
1158
+ ]);
1159
+ var PlatformTokenPayloadSchema = z24.object({
1160
+ /** Discriminator. Rejects cross-system JWTs (reskill-api, summarization-api, ...). */
1161
+ type: z24.literal("platform-api"),
1162
+ /** Owner LDAP. */
1163
+ sub: z24.string().min(1),
1164
+ /** Corresponds to `platform_tokens.id`. */
1165
+ jti: z24.string().uuid(),
1166
+ /** Issued-at (seconds). */
1167
+ iat: z24.number().int().nonnegative(),
1168
+ /** Expiry (seconds). Omit for never-expiring tokens. */
1169
+ exp: z24.number().int().positive().optional()
1170
+ });
1171
+ var SDKMessageTypeSchema = z25.enum([
1172
+ // Assistant text output.
1173
+ "text-delta",
1174
+ // Assistant reasoning (when the model supports it).
1175
+ "reasoning",
1176
+ // A tool invocation by the agent (input available).
1177
+ "tool-use",
1178
+ // A tool result (output available).
1179
+ "tool-result",
1180
+ // A tool failure.
1181
+ "tool-error",
1182
+ // Finalize-stage progress (preparing / uploading / verifying / ...).
1183
+ "finalize-progress",
1184
+ // Terminal error from the run.
1185
+ "error",
1186
+ // Stream completed successfully (run finalized).
1187
+ "done",
1188
+ // Step boundaries (used by multi-step agents).
1189
+ "step-start",
1190
+ "step-end"
1191
+ ]);
1192
+ var SDKMessageSchema = z25.object({
1193
+ type: SDKMessageTypeSchema,
1194
+ /** Monotonically increasing stream cursor from the server. Usable for resume. */
1195
+ cursor: z25.number().int().nonnegative().optional(),
1196
+ /** Stable per-message identifier when the server provides one. */
1197
+ id: z25.string().optional(),
1198
+ /** Raw text for `text-delta` / `reasoning`. */
1199
+ text: z25.string().optional(),
1200
+ /** Tool invocation details when `type === 'tool-use' | 'tool-result' | 'tool-error'`. */
1201
+ tool: z25.object({
1202
+ name: z25.string(),
1203
+ callId: z25.string().optional(),
1204
+ input: z25.unknown().optional(),
1205
+ output: z25.string().optional(),
1206
+ error: z25.string().optional()
1207
+ }).optional(),
1208
+ /** Finalize progress snapshot for `type === 'finalize-progress'`. */
1209
+ progress: z25.object({
1210
+ stage: z25.string(),
1211
+ detail: z25.string().optional()
1212
+ }).optional(),
1213
+ /** Error detail for `type === 'error'`. */
1214
+ error: z25.object({
1215
+ message: z25.string(),
1216
+ code: z25.string().optional()
1217
+ }).optional(),
1218
+ /**
1219
+ * Terminal run status for `type === 'done'`. Mirrors the DB
1220
+ * run-status enum so callers can branch without another fetch.
1221
+ */
1222
+ runStatus: RunStatusSchema.optional()
1223
+ }).passthrough();
1224
+ var McpStdioConfigSchema = z26.object({
1225
+ type: z26.literal("stdio"),
1226
+ command: z26.string().min(1),
1227
+ args: z26.array(z26.string()).optional(),
1228
+ env: z26.record(z26.string(), z26.string()).optional()
1229
+ });
1230
+ var McpSseConfigSchema = z26.object({
1231
+ type: z26.literal("sse"),
1232
+ url: z26.string().url(),
1233
+ headers: z26.record(z26.string(), z26.string()).optional()
1234
+ });
1235
+ var McpHttpConfigSchema = z26.object({
1236
+ type: z26.literal("http"),
1237
+ url: z26.string().url(),
1238
+ headers: z26.record(z26.string(), z26.string()).optional()
1239
+ });
1240
+ var MCPServerConfigSchema = z26.discriminatedUnion("type", [
1241
+ McpStdioConfigSchema,
1242
+ McpSseConfigSchema,
1243
+ McpHttpConfigSchema
1244
+ ]);
1245
+ var McpTemplateSnapshotSchema = z26.object({
1246
+ transportType: z26.enum(["stdio", "sse", "http"]),
1247
+ serverConfig: MCPServerConfigSchema,
1248
+ requiredVars: z26.array(z26.string()).optional(),
1249
+ version: z26.string().optional()
1250
+ });
1251
+ var EnabledMcpServerSchema = z26.object({
1252
+ rushMcpId: z26.string().min(1),
1253
+ displayName: z26.string().min(1),
1254
+ templateSnapshot: McpTemplateSnapshotSchema,
1255
+ extraConfigValues: z26.record(z26.string(), z26.string()).optional(),
1256
+ toolFilter: z26.array(z26.string()).optional(),
1257
+ disabled: z26.boolean().optional()
1258
+ });
1259
+ var EnabledMcpServerListSchema = z26.array(EnabledMcpServerSchema);
1260
+ var EnabledMcpRefSchema = z26.object({
1261
+ rushMcpId: z26.string().min(1),
1262
+ disabled: z26.boolean().optional(),
1263
+ extraConfigValuesOverride: z26.record(z26.string(), z26.string()).optional()
1264
+ });
1265
+ var EnabledMcpRefListSchema = z26.array(EnabledMcpRefSchema);
1266
+ var EnabledMcpEntrySchema = z26.union([EnabledMcpServerSchema, EnabledMcpRefSchema]);
1267
+ var EnabledMcpEntryListSchema = z26.array(EnabledMcpEntrySchema);
1268
+ var SkillSourceTypeSchema = z27.enum([
1269
+ "github",
1270
+ "gitlab",
1271
+ "registry",
1272
+ "local",
1273
+ "oss_url",
1274
+ "custom_url"
1275
+ ]);
1276
+ var ResolvedSkillArtifactSchema = z27.object({
1277
+ sourceType: SkillSourceTypeSchema,
1278
+ /**
1279
+ * Direct repo / file URL for `github` / `gitlab` source types. For
1280
+ * `registry` / `oss_url` / `local` / `custom_url`, rush stores the
1281
+ * actual download artifact in `skill_versions` (different per
1282
+ * version) so this field is empty / unused at install time — the
1283
+ * installer goes through `RushRegistryClient.resolveDownloadUrl`
1284
+ * instead.
1285
+ */
1286
+ sourceUrl: z27.string().optional().default(""),
1287
+ skillPath: z27.string().optional(),
1288
+ integrity: z27.string().optional(),
1289
+ version: z27.string().optional()
1290
+ });
1291
+ var EnabledSkillSchema = z27.object({
1292
+ rushSkillName: z27.string().min(1),
1293
+ displayName: z27.string().min(1),
1294
+ resolvedArtifact: ResolvedSkillArtifactSchema
1295
+ });
1296
+ var EnabledSkillListSchema = z27.array(EnabledSkillSchema);
1297
+ var EnabledSkillRefSchema = z27.object({
1298
+ rushSkillName: z27.string().min(1)
1299
+ });
1300
+ var EnabledSkillRefListSchema = z27.array(EnabledSkillRefSchema);
1301
+ var EnabledSkillEntrySchema = z27.union([EnabledSkillSchema, EnabledSkillRefSchema]);
1302
+ var EnabledSkillEntryListSchema = z27.array(EnabledSkillEntrySchema);
1303
+ var SdkAgentSummarySchema = z28.object({
1304
+ agentId: z28.string().uuid(),
1305
+ title: z28.string(),
1306
+ project: z28.object({
1307
+ id: z28.string().uuid(),
1308
+ name: z28.string(),
1309
+ gitProvider: GitProviderSchema.nullable()
1310
+ }),
1311
+ agentMode: z28.enum(["task", "chat"]),
1312
+ productStatus: z28.enum(["idle", "running", "needs_attention", "completed"]),
1313
+ model: z28.string().nullable(),
1314
+ isAutomation: z28.boolean(),
1315
+ latestRun: z28.object({
1316
+ runId: z28.string().uuid(),
1317
+ promptSummary: z28.string(),
1318
+ status: z28.string(),
1319
+ updatedAt: z28.string().datetime(),
1320
+ startedAt: z28.string().datetime().nullable(),
1321
+ completedAt: z28.string().datetime().nullable(),
1322
+ hasArtifacts: z28.boolean(),
1323
+ hasReview: z28.boolean(),
1324
+ hasDiff: z28.boolean(),
1325
+ hasCommits: z28.boolean(),
1326
+ hasPullRequest: z28.boolean()
1327
+ }).nullable(),
1328
+ lastActiveAt: z28.string().datetime()
1329
+ });
1330
+ var ListAgentsQuerySchema = z28.object({
1331
+ projectId: z28.string().uuid().optional(),
1332
+ limit: z28.number().int().min(1).max(100).optional()
1333
+ });
1334
+ var ListAgentsResponseSchema = z28.object({
1335
+ items: z28.array(SdkAgentSummarySchema),
1336
+ nextCursor: z28.string().nullable()
1337
+ });
1338
+ var PilotApiVersionSchema = z28.enum(["v1", "v2"]);
1339
+ var SdkCreateAgentRequestSchema = z28.object({
1340
+ projectId: z28.string().uuid().optional(),
1341
+ gitProvider: GitProviderSchema.optional(),
1342
+ gitlabProjectPath: z28.string().trim().min(1).optional(),
1343
+ githubRepoFullName: z28.string().trim().min(1).optional(),
1344
+ repoUrl: z28.string().min(1).optional(),
1345
+ /**
1346
+ * Baseline git ref frozen on the agent for the lifetime of follow-up
1347
+ * runs. Optional — server falls back to project.defaultBranch.
1348
+ */
1349
+ baseRef: z28.string().optional(),
1350
+ prompt: z28.string().min(1),
1351
+ agentMode: z28.enum(["task", "chat"]).optional(),
1352
+ model: z28.string().optional(),
1353
+ provider: ProviderTypeSchema.optional(),
1354
+ githubInstallationId: z28.string().optional(),
1355
+ attachments: z28.array(AttachmentMetaSchema).max(5).optional(),
1356
+ /**
1357
+ * Optional MCP / Skill enable lists frozen on the new agent at
1358
+ * creation time.
1359
+ *
1360
+ * Both fields accept the same union the home-composer
1361
+ * pre-edit and `PUT /api/agents/:id/mcp-skills` accept (see
1362
+ * `EnabledMcpEntrySchema` / `EnabledSkillEntrySchema`):
1363
+ * full snapshot **OR** ref into the global credential store.
1364
+ *
1365
+ * `POST /api/agents` semantics (Pilot Web):
1366
+ * - Omitted lists + no CLI seed header → new agent starts with empty
1367
+ * `enabled_*` (interactive / SDK default; spec §4.3).
1368
+ * - Omitted lists + Pilot CLI request (`x-pilot-cli-seed-from-project: 1`) →
1369
+ * server seeds from `projects.enabled_mcp_servers` / `enabled_skills`.
1370
+ * - Either list provided → explicit caller choice; omitted dimension
1371
+ * still follows the seed rule above; `agents.mcp_skills_customized = true`
1372
+ * when any list is caller-supplied.
1373
+ *
1374
+ * See `specs/features/mcp-and-skills.md` §4.4.
1375
+ */
1376
+ enabledMcpServers: EnabledMcpEntryListSchema.optional(),
1377
+ enabledSkills: EnabledSkillEntryListSchema.optional(),
1378
+ /**
1379
+ * Caller-explicit per-run lifecycle selector. Same semantics as
1380
+ * `SdkCreateRunRequestSchema.pilotApiVersion` — see `PilotApiVersionSchema`
1381
+ * JSDoc for the three-layer LOCK and routing precedence.
1382
+ *
1383
+ * Three-layer LOCK (agents):
1384
+ * L1 SDK `SdkCreateAgentRequestSchema.pilotApiVersion` — this file
1385
+ * L2 API `apps/web/app/api/agents/route.ts` — body field
1386
+ * L3 RT `packages/control-plane/src/run-service.ts` — `runs.pilot_api_version`
1387
+ *
1388
+ * Optional; when omitted, server falls through to `decideRoute()` then
1389
+ * default `"v1"`.
1390
+ */
1391
+ pilotApiVersion: PilotApiVersionSchema.optional()
1392
+ }).superRefine((data, ctx) => {
1393
+ const hasProjectId = typeof data.projectId === "string" && data.projectId.length > 0;
1394
+ const hasGitlabPath = !!data.gitlabProjectPath;
1395
+ const hasGithubRepo = !!data.githubRepoFullName;
1396
+ const hasGitProvider = !!data.gitProvider;
1397
+ if (hasProjectId) {
1398
+ if (hasGitProvider || hasGitlabPath || hasGithubRepo || data.repoUrl) {
1399
+ ctx.addIssue({
1400
+ code: z28.ZodIssueCode.custom,
1401
+ message: "projectId is exclusive with gitProvider / gitlabProjectPath / githubRepoFullName / repoUrl.",
1402
+ path: ["projectId"]
1403
+ });
1404
+ }
1405
+ return;
1406
+ }
1407
+ if (!hasGitProvider) {
1408
+ ctx.addIssue({
1409
+ code: z28.ZodIssueCode.custom,
1410
+ message: "Provide either projectId, or (gitProvider + gitlabProjectPath) / (gitProvider + githubRepoFullName).",
1411
+ path: ["gitProvider"]
1412
+ });
1413
+ return;
1414
+ }
1415
+ if (data.gitProvider === "gitlab") {
1416
+ if (!hasGitlabPath) {
1417
+ ctx.addIssue({
1418
+ code: z28.ZodIssueCode.custom,
1419
+ message: "gitProvider=gitlab requires gitlabProjectPath.",
1420
+ path: ["gitlabProjectPath"]
1421
+ });
1422
+ }
1423
+ if (hasGithubRepo) {
1424
+ ctx.addIssue({
1425
+ code: z28.ZodIssueCode.custom,
1426
+ message: "gitProvider=gitlab must not carry githubRepoFullName.",
1427
+ path: ["githubRepoFullName"]
1428
+ });
1429
+ }
1430
+ } else if (data.gitProvider === "github") {
1431
+ if (!hasGithubRepo) {
1432
+ ctx.addIssue({
1433
+ code: z28.ZodIssueCode.custom,
1434
+ message: "gitProvider=github requires githubRepoFullName.",
1435
+ path: ["githubRepoFullName"]
1436
+ });
1437
+ }
1438
+ if (hasGitlabPath) {
1439
+ ctx.addIssue({
1440
+ code: z28.ZodIssueCode.custom,
1441
+ message: "gitProvider=github must not carry gitlabProjectPath.",
1442
+ path: ["gitlabProjectPath"]
1443
+ });
1444
+ }
1445
+ }
1446
+ });
1447
+ var SdkCreateAgentResponseSchema = z28.object({
1448
+ agentId: z28.string().uuid(),
1449
+ runId: z28.string().uuid(),
1450
+ isNewAgent: z28.boolean()
1451
+ });
1452
+ var SdkMergeAgentRequestSchema = z28.object({
1453
+ /** Optional custom commit message. Server falls back to the model output. */
1454
+ commitMessage: z28.string().min(1).max(200).optional(),
1455
+ /** Optional PR title override. */
1456
+ prTitle: z28.string().min(1).max(256).optional(),
1457
+ /** Optional PR description override. */
1458
+ prDescription: z28.string().optional()
1459
+ });
1460
+ var SdkMergeAgentResponseSchema = z28.object({
1461
+ mergeRequestId: z28.string().uuid(),
1462
+ externalUrl: z28.string(),
1463
+ externalId: z28.string()
1464
+ });
1465
+ var SdkPatchAgentRequestSchema = z28.object({
1466
+ customTitle: z28.string().max(200).nullable().optional(),
1467
+ status: z28.enum(["active", "closed"]).optional()
1468
+ });
1469
+ var SdkCreateRunRequestSchema = z28.object({
1470
+ projectId: z28.string().uuid(),
1471
+ prompt: z28.string().min(1),
1472
+ agentId: z28.string().uuid().optional(),
1473
+ parentRunId: z28.string().uuid().optional(),
1474
+ repo: z28.string().optional(),
1475
+ ref: z28.string().optional(),
1476
+ model: z28.string().optional(),
1477
+ provider: ProviderTypeSchema.optional(),
1478
+ attachments: z28.array(AttachmentMetaSchema).max(5).optional(),
1479
+ /**
1480
+ * Per-run override of the MCP / Skill enable lists.
1481
+ *
1482
+ * When omitted, the run inherits whatever lives on the agent (Portal /
1483
+ * SDK create without MCP/Skill body and without CLI seed header → empty
1484
+ * lists on the agent; see `SdkCreateAgentRequestSchema`).
1485
+ *
1486
+ * Same union shape as the create-agent fields: snapshot OR ref.
1487
+ * Useful for one-off runs that need a different toolset than the
1488
+ * conversational defaults baked onto the agent.
1489
+ *
1490
+ * See `specs/features/mcp-and-skills.md` §6.3 (per-run override).
1491
+ */
1492
+ enabledMcpServers: EnabledMcpEntryListSchema.optional(),
1493
+ enabledSkills: EnabledSkillEntryListSchema.optional(),
1494
+ /**
1495
+ * Caller-explicit Pilot runtime API version override for this run.
1496
+ *
1497
+ * Defaults to **server-decided**: when omitted, the server consults
1498
+ * the traffic-split router (PR-TS-1 D5/D6) for the v1/v2 routing
1499
+ * decision and persists it to `runs.pilot_api_version`. When passed
1500
+ * explicitly, the caller value wins regardless of the router state
1501
+ * (see `run-service.ts` line 99-114 and PR-TS-1 D5 explicit-wins
1502
+ * test `run-service-pilot-api-version.test.ts` line 134-149).
1503
+ *
1504
+ * Use this opt-in carefully — it bypasses the canary / kill-switch
1505
+ * gates. Most callers should leave this unset and trust the router.
1506
+ */
1507
+ pilotApiVersion: PilotApiVersionSchema.optional()
1508
+ });
1509
+ var SdkCreateRunResponseSchema = z28.object({
1510
+ run: z28.lazy(() => SdkRunSummarySchema)
1511
+ });
1512
+ var SdkAbortRunRequestSchema = z28.object({
1513
+ reason: z28.string().max(500).optional()
1514
+ });
1515
+ var SdkAbortRunResponseSchema = z28.object({
1516
+ aborted: z28.boolean(),
1517
+ status: RunStatusSchema
1518
+ });
1519
+ var SdkRunSummarySchema = z28.object({
1520
+ runId: z28.string().uuid(),
1521
+ agentId: z28.string().uuid(),
1522
+ projectId: z28.string().uuid(),
1523
+ status: RunStatusSchema,
1524
+ prompt: z28.string(),
1525
+ model: z28.string().nullable(),
1526
+ provider: ProviderTypeSchema,
1527
+ triggerSource: TriggerSourceSchema,
1528
+ pullRequestUrl: z28.string().nullable(),
1529
+ errorMessage: z28.string().nullable(),
1530
+ createdAt: z28.string().datetime(),
1531
+ startedAt: z28.string().datetime().nullable(),
1532
+ completedAt: z28.string().datetime().nullable()
1533
+ });
1534
+ var SdkStreamRunQuerySchema = z28.object({
1535
+ lastCursor: z28.number().int().nonnegative().optional()
1536
+ });
1537
+ var SdkProjectSummarySchema = z28.object({
1538
+ id: z28.string().uuid(),
1539
+ name: z28.string(),
1540
+ // `kind` is now `NOT NULL DEFAULT 'coding'` in the DB (migration
1541
+ // 0034), so the server always emits a concrete value — `.default()`
1542
+ // would silently mask a missing-field bug instead of surfacing it.
1543
+ // Keep the field strict so SDK consumers can rely on the union
1544
+ // without runtime fallbacks.
1545
+ kind: ProjectKindSchema,
1546
+ gitProvider: GitProviderSchema.nullable(),
1547
+ repoUrl: z28.string().nullable(),
1548
+ gitlabProjectPath: z28.string().nullable(),
1549
+ githubRepoFullName: z28.string().nullable(),
1550
+ webhookEnabled: z28.boolean(),
1551
+ webhookTriggerLabel: z28.string(),
1552
+ jiraEnabled: z28.boolean(),
1553
+ wecomEnabled: z28.boolean(),
1554
+ ownerLdap: z28.string().nullable(),
1555
+ role: z28.enum(["owner", "member", "admin"])
1556
+ });
1557
+ var ListProjectsRequestSchema = z28.object({
1558
+ kind: ProjectKindSchema.optional()
1559
+ });
1560
+ var CreateGeneralProjectRequestSchema = z28.object({
1561
+ name: z28.string().trim().min(1).max(255),
1562
+ kind: z28.literal("general"),
1563
+ description: z28.string().trim().max(2e3).optional()
1564
+ });
1565
+ var CreateGeneralProjectResponseSchema = z28.object({
1566
+ projectId: z28.string().uuid()
1567
+ });
1568
+ var ListProjectsResponseSchema = z28.object({
1569
+ items: z28.array(SdkProjectSummarySchema)
1570
+ });
1571
+ var SdkProjectSettingsSchema = z28.object({
1572
+ id: z28.string().uuid(),
1573
+ webhookEnabled: z28.boolean(),
1574
+ webhookTriggerLabel: z28.string(),
1575
+ webhookPromptTemplate: z28.string().nullable(),
1576
+ wecomEnabled: z28.boolean(),
1577
+ wecomBotId: z28.string().nullable(),
1578
+ wecomPromptTemplate: z28.string().nullable(),
1579
+ jiraEnabled: z28.boolean().optional(),
1580
+ jiraBaseUrl: z28.string().nullable().optional(),
1581
+ jiraProjectKey: z28.string().nullable().optional(),
1582
+ jiraTriggerLabel: z28.string().optional(),
1583
+ jiraPromptTemplate: z28.string().nullable().optional()
1584
+ });
1585
+ var UpdateProjectSettingsRequestSchema = z28.object({
1586
+ webhookEnabled: z28.boolean().optional(),
1587
+ webhookTriggerLabel: z28.string().min(1).max(100).optional(),
1588
+ webhookPromptTemplate: z28.string().nullable().optional(),
1589
+ wecomEnabled: z28.boolean().optional(),
1590
+ wecomBotId: z28.string().min(1).max(100).nullable().optional(),
1591
+ wecomPromptTemplate: z28.string().nullable().optional(),
1592
+ jiraEnabled: z28.boolean().optional(),
1593
+ jiraBaseUrl: z28.string().url().nullable().optional(),
1594
+ jiraProjectKey: z28.string().min(1).max(64).nullable().optional(),
1595
+ jiraTriggerLabel: z28.string().min(1).max(100).optional(),
1596
+ jiraPromptTemplate: z28.string().nullable().optional()
1597
+ });
1598
+ var SdkAutomationRunSchema = z28.object({
1599
+ runId: z28.string().uuid(),
1600
+ agentId: z28.string().uuid(),
1601
+ projectId: z28.string().uuid(),
1602
+ projectName: z28.string(),
1603
+ gitProvider: GitProviderSchema.nullable(),
1604
+ repoFullName: z28.string().nullable(),
1605
+ status: z28.string(),
1606
+ productStatus: z28.enum(["idle", "running", "needs_attention", "completed"]),
1607
+ promptSummary: z28.string(),
1608
+ triggerRef: z28.string().nullable(),
1609
+ triggerType: z28.enum(["label", "mention", "wecom", "jira"]),
1610
+ issueUrl: z28.string().nullable(),
1611
+ pullRequestUrl: z28.string().nullable(),
1612
+ errorMessage: z28.string().nullable(),
1613
+ createdAt: z28.string().datetime(),
1614
+ updatedAt: z28.string().datetime(),
1615
+ startedAt: z28.string().datetime().nullable(),
1616
+ completedAt: z28.string().datetime().nullable()
1617
+ });
1618
+ var ListAutomationRunsQuerySchema = z28.object({
1619
+ projectId: z28.string().uuid().optional(),
1620
+ limit: z28.number().int().min(1).max(100).optional(),
1621
+ cursor: z28.string().optional()
1622
+ });
1623
+ var ListAutomationRunsResponseSchema = z28.object({
1624
+ items: z28.array(SdkAutomationRunSchema),
1625
+ nextCursor: z28.string().nullable()
1626
+ });
1627
+ var CreatePlatformTokenRequestSchema = z28.object({
1628
+ name: z28.string().min(1).max(200),
1629
+ description: z28.string().max(2e3).optional(),
1630
+ scopes: z28.array(PlatformScopeSchema).min(1),
1631
+ scopeTemplate: ScopeTemplateSchema,
1632
+ /** NULL means "all projects I currently have access to". */
1633
+ targetProjectIds: z28.array(z28.string().uuid()).nullable(),
1634
+ /** ISO-8601 string. Omit for never-expire. */
1635
+ expiresAt: z28.string().datetime().optional()
1636
+ });
1637
+ var CreatePlatformTokenResponseSchema = z28.object({
1638
+ id: z28.string().uuid(),
1639
+ name: z28.string(),
1640
+ /** The **only** time the full token is returned. */
1641
+ token: z28.string(),
1642
+ tokenPrefix: z28.string(),
1643
+ scopes: z28.array(PlatformScopeSchema),
1644
+ scopeTemplate: ScopeTemplateSchema,
1645
+ targetProjectIds: z28.array(z28.string().uuid()).nullable(),
1646
+ createdAt: z28.string().datetime(),
1647
+ expiresAt: z28.string().datetime().nullable()
1648
+ });
1649
+ var PlatformTokenInfoSchema = z28.object({
1650
+ id: z28.string().uuid(),
1651
+ name: z28.string(),
1652
+ description: z28.string().nullable(),
1653
+ tokenPrefix: z28.string(),
1654
+ scopes: z28.array(PlatformScopeSchema),
1655
+ scopeTemplate: ScopeTemplateSchema.nullable(),
1656
+ targetProjectIds: z28.array(z28.string().uuid()).nullable(),
1657
+ createdAt: z28.string().datetime(),
1658
+ expiresAt: z28.string().datetime().nullable(),
1659
+ lastUsedAt: z28.string().datetime().nullable(),
1660
+ revokedAt: z28.string().datetime().nullable(),
1661
+ revokedReason: z28.string().nullable()
1662
+ });
1663
+ var ListPlatformTokensResponseSchema = z28.object({
1664
+ items: z28.array(PlatformTokenInfoSchema)
1665
+ });
1666
+ var PatchPlatformTokenRequestSchema = z28.object({
1667
+ name: z28.string().min(1).max(200).optional(),
1668
+ description: z28.string().max(2e3).nullable().optional(),
1669
+ /**
1670
+ * Allowed to *shrink* the scope set (for tightening); forbidden to
1671
+ * widen. Server enforces `new_scopes ⊆ old_scopes`.
1672
+ */
1673
+ scopes: z28.array(PlatformScopeSchema).min(1).optional()
1674
+ });
1675
+ var X_PILOT_API_VERSION_HEADER = "x-pilot-api-version";
1676
+ var DeliveryResultPhaseSchema = z29.enum(["in_progress", "completed", "failed"]);
1677
+ var DeliveryResultArtifactItemSchema = z29.object({
1678
+ /** Artifact category. Workers MAY add new kinds; storage is opaque. */
1679
+ kind: z29.enum(["diff", "log", "general"]),
1680
+ /**
1681
+ * Logical path inside the sandbox workspace (used as the idempotency
1682
+ * key together with `runId`). Two writes with the same `(runId, path)`
1683
+ * pair collapse to a single row via `ON CONFLICT DO NOTHING`.
1684
+ */
1685
+ path: z29.string().min(1).max(1024),
1686
+ /** Object key inside the OSS bucket where the artifact was uploaded. */
1687
+ storagePath: z29.string().min(1).max(1024),
1688
+ /** Reported byte size of the upload. */
1689
+ size: z29.number().int().nonnegative(),
1690
+ /**
1691
+ * SHA-256 digest in the form `sha256:<hex>`. Workers compute this
1692
+ * before upload so a later integrity check can cross-verify the
1693
+ * stored object. Length cap 128 mirrors the `artifacts.checksum`
1694
+ * column width.
1695
+ */
1696
+ checksum: z29.string().min(1).max(128),
1697
+ /** MIME content type recorded for downloads / preview. */
1698
+ contentType: z29.string().min(1).max(255)
1699
+ }).strict();
1700
+ var DeliveryResultUpdateSchema = z29.object({
1701
+ /**
1702
+ * The PR / MR URL the agent created. First-write-wins per spec
1703
+ * (`UPDATE ... WHERE pull_request_url IS NULL`); subsequent writes
1704
+ * are recorded in the response as "skipped" rather than as an error
1705
+ * so Worker retries stay idempotent.
1706
+ */
1707
+ pullRequestUrl: z29.string().url().max(1024).optional(),
1708
+ /**
1709
+ * Append-set of artifacts uploaded for this run. Each item is
1710
+ * upserted independently via the `unique(run_id, path)` constraint;
1711
+ * the response indicates how many of the submitted items resulted
1712
+ * in a new row.
1713
+ */
1714
+ artifacts: z29.array(DeliveryResultArtifactItemSchema).max(64).optional(),
1715
+ /**
1716
+ * Drive the `runs.delivery_phase` column via the L1.2
1717
+ * `RunService.recordDeliveryPhase` helper. `failed` requires
1718
+ * `failedReason`; the service throws `INVALID_INPUT` otherwise.
1719
+ */
1720
+ phase: DeliveryResultPhaseSchema.optional(),
1721
+ /** Non-empty failure reason; required iff `phase === "failed"`. */
1722
+ failedReason: z29.string().min(1).max(2048).optional(),
1723
+ /**
1724
+ * When `true`, increment `runs.delivery_attempts` by 1 alongside
1725
+ * the phase write. Workers SHOULD set this on every delivery
1726
+ * (re)attempt so the audit row reflects retry count.
1727
+ */
1728
+ incrementAttempts: z29.boolean().optional()
1729
+ }).strict().refine(
1730
+ (data) => data.pullRequestUrl !== void 0 || data.artifacts !== void 0 || data.phase !== void 0 || data.failedReason !== void 0 || data.incrementAttempts !== void 0,
1731
+ {
1732
+ message: "At least one of pullRequestUrl / artifacts / phase / failedReason / incrementAttempts MUST be provided"
1733
+ }
1734
+ );
1735
+ var DeliveryResultUpdateResponseSchema = z29.object({
1736
+ success: z29.literal(true),
1737
+ data: z29.object({
1738
+ /** Subset of the request fields whose persisted state actually
1739
+ * changed. `pullRequestUrl` is omitted on second-write (PR URL
1740
+ * already set) so callers can detect idempotent replays. */
1741
+ applied: z29.array(
1742
+ z29.enum(["pullRequestUrl", "artifacts", "phase", "failedReason", "incrementAttempts"])
1743
+ ),
1744
+ /** Number of newly inserted artifact rows. Always 0 when `artifacts`
1745
+ * wasn't in the request. */
1746
+ artifactsInserted: z29.number().int().nonnegative()
1747
+ })
1748
+ });
1749
+ var DeliveryResultErrorCodeSchema = z29.enum([
1750
+ // 400 — request was malformed or schema-invalid
1751
+ "VALIDATION_ERROR",
1752
+ // 401 — Authorization header missing or session token invalid/expired
1753
+ "MISSING_SESSION_TOKEN",
1754
+ "SESSION_TOKEN_INVALID",
1755
+ "SESSION_TOKEN_EXPIRED",
1756
+ "SESSION_TOKEN_REVOKED",
1757
+ // 403 — the session token belongs to a different session than the URL
1758
+ "SESSION_TOKEN_SESSION_MISMATCH",
1759
+ // 404 — the URL session id / corresponding run does not exist
1760
+ "SESSION_NOT_FOUND",
1761
+ "RUN_NOT_FOUND",
1762
+ // 500 — fallthrough
1763
+ "INTERNAL_ERROR"
1764
+ ]);
1765
+ var ResourceProfileSchema = z30.object({
1766
+ cpu: z30.string().min(1),
1767
+ memory: z30.string().min(1),
1768
+ disk: z30.string().min(1).optional(),
1769
+ gpu: z30.string().min(1).optional()
1770
+ }).strict();
1771
+ var TraceContextSchema = z30.object({
1772
+ traceId: z30.string().min(1),
1773
+ spanId: z30.string().min(1),
1774
+ parentSpanId: z30.string().min(1).optional()
1775
+ }).strict();
1776
+ var TemplateKindSchema = z30.enum(["claude-code", "codex", "amp"]);
1777
+ var RepoCoordinatesSchema = z30.object({
1778
+ repoUrl: z30.string().min(1),
1779
+ targetRef: z30.string().min(1)
1780
+ }).strict();
1781
+ var ProvisionRequestSchema = z30.object({
1782
+ idempotencyKey: z30.string().min(1),
1783
+ template: TemplateKindSchema,
1784
+ resourceProfile: ResourceProfileSchema,
1785
+ repoCoordinates: RepoCoordinatesSchema.optional(),
1786
+ env: z30.record(z30.string(), z30.string()),
1787
+ trace: TraceContextSchema,
1788
+ deadlineMs: z30.number().int().positive()
1789
+ }).strict();
1790
+ var WorkerProtocolVersionSchema = z31.enum(["v1"]);
1791
+ var SessionRefSchema = z31.object({
1792
+ sessionId: z31.string().min(1),
1793
+ runtimeBindingId: z31.string().min(1)
1794
+ }).strict();
1795
+ var FORBIDDEN_V1_PRIMITIVE_KEYS = ["runId", "agentId", "projectId", "provider"];
1796
+ function forbidV1Primitives(val, ctx) {
1797
+ for (const k of FORBIDDEN_V1_PRIMITIVE_KEYS) {
1798
+ if (k in val) {
1799
+ ctx.addIssue({
1800
+ code: z31.ZodIssueCode.custom,
1801
+ path: [k],
1802
+ message: `R-WP-01: v1 primitive '${k}' is forbidden on v2 dispatch envelopes`
1803
+ });
1804
+ }
1805
+ }
1806
+ }
1807
+ var WorkerProtocolPromptRequestSchema = z31.object({
1808
+ idempotencyKey: z31.string().min(1),
1809
+ session: SessionRefSchema,
1810
+ protocolVersion: WorkerProtocolVersionSchema,
1811
+ promptText: z31.string().min(1),
1812
+ trace: TraceContextSchema,
1813
+ // Legacy wall-clock deadline. Kept for back-compat with workers/dispatchers
1814
+ // that have not yet adopted the idle/hardCap split. NEW behavior:
1815
+ // - When `idleTimeoutMs` is supplied, framework uses idle-based deadline
1816
+ // (reset on each ctx.events.append success) plus optional `hardCapMs`
1817
+ // absolute upper bound; the legacy `deadlineMs` is ignored.
1818
+ // - When only `deadlineMs` is supplied, framework falls back to the
1819
+ // original wall-clock behavior (single setTimeout = deadlineMs).
1820
+ deadlineMs: z31.number().int().positive(),
1821
+ // Idle timeout: framework fails the turn with `wp_handshake_timeout` if no
1822
+ // `ctx.events.append` succeeds within this many ms. Reset each time the
1823
+ // handler emits a session_event chunk — long-running but actively-streaming
1824
+ // handlers are NOT killed by the wall-clock alone.
1825
+ idleTimeoutMs: z31.number().int().positive().optional(),
1826
+ // Hard upper bound that fires regardless of activity (defense against
1827
+ // infinite-loop handlers that keep emitting). Optional companion to
1828
+ // `idleTimeoutMs`; when omitted, no hard cap is armed.
1829
+ hardCapMs: z31.number().int().positive().optional()
1830
+ }).passthrough().superRefine(forbidV1Primitives);
1831
+ var WorkerProtocolFollowupRequestSchema = z31.object({
1832
+ idempotencyKey: z31.string().min(1),
1833
+ session: SessionRefSchema,
1834
+ protocolVersion: WorkerProtocolVersionSchema,
1835
+ parentTurnId: z31.string().min(1),
1836
+ followupText: z31.string().min(1),
1837
+ trace: TraceContextSchema,
1838
+ // See `WorkerProtocolPromptRequestSchema.deadlineMs` for the legacy /
1839
+ // idle / hardCap precedence rules; same semantics apply for follow-up.
1840
+ deadlineMs: z31.number().int().positive(),
1841
+ idleTimeoutMs: z31.number().int().positive().optional(),
1842
+ hardCapMs: z31.number().int().positive().optional()
1843
+ }).passthrough().superRefine(forbidV1Primitives);
1844
+ var WorkerProtocolAbortReasonSchema = z31.discriminatedUnion("kind", [
1845
+ z31.object({ kind: z31.literal("user"), userId: z31.string().min(1).optional() }).strict(),
1846
+ z31.object({ kind: z31.literal("timeout") }).strict(),
1847
+ z31.object({ kind: z31.literal("system"), hint: z31.string().min(1) }).strict()
1848
+ ]);
1849
+ var WorkerProtocolAbortRequestSchema = z31.object({
1850
+ idempotencyKey: z31.string().min(1),
1851
+ session: SessionRefSchema,
1852
+ protocolVersion: WorkerProtocolVersionSchema,
1853
+ turnId: z31.string().min(1),
1854
+ reason: WorkerProtocolAbortReasonSchema,
1855
+ trace: TraceContextSchema
1856
+ }).passthrough().superRefine(forbidV1Primitives);
1857
+ var WorkerProtocolRestoreRequestSchema = z31.object({
1858
+ idempotencyKey: z31.string().min(1),
1859
+ session: SessionRefSchema,
1860
+ protocolVersion: WorkerProtocolVersionSchema,
1861
+ replayCursor: z31.string().min(1).optional(),
1862
+ trace: TraceContextSchema,
1863
+ // See `WorkerProtocolPromptRequestSchema.deadlineMs` for the legacy /
1864
+ // idle / hardCap precedence rules.
1865
+ deadlineMs: z31.number().int().positive(),
1866
+ idleTimeoutMs: z31.number().int().positive().optional(),
1867
+ hardCapMs: z31.number().int().positive().optional()
1868
+ }).passthrough().superRefine(forbidV1Primitives);
1869
+ var WP_FAILURE_REASON_KINDS = [
1870
+ "wp_protocol_violation",
1871
+ "wp_handshake_timeout",
1872
+ "wp_unsupported_version",
1873
+ "wp_invalid_envelope",
1874
+ "wp_stream_terminated",
1875
+ "wp_replay_lost"
1876
+ ];
1877
+ var WP_FAILURE_REASON_ENUM = z31.enum(WP_FAILURE_REASON_KINDS);
1878
+ var DispatchOutcomeSchema = z31.discriminatedUnion("kind", [
1879
+ z31.object({
1880
+ kind: z31.literal("accepted"),
1881
+ turnId: z31.string().min(1),
1882
+ protocolVersion: WorkerProtocolVersionSchema,
1883
+ observedAt: z31.string().min(1)
1884
+ }).strict(),
1885
+ z31.object({
1886
+ kind: z31.literal("rejected"),
1887
+ reason: WP_FAILURE_REASON_ENUM,
1888
+ observedAt: z31.string().min(1),
1889
+ message: z31.string().min(1).optional()
1890
+ }).strict(),
1891
+ z31.object({
1892
+ kind: z31.literal("idempotent_replay"),
1893
+ turnId: z31.string().min(1),
1894
+ priorOutcome: z31.enum(["accepted", "rejected"]),
1895
+ observedAt: z31.string().min(1)
1896
+ }).strict(),
1897
+ z31.object({
1898
+ kind: z31.literal("transport_failed"),
1899
+ reason: WP_FAILURE_REASON_ENUM,
1900
+ observedAt: z31.string().min(1),
1901
+ message: z31.string().min(1).optional()
1902
+ }).strict()
1903
+ ]);
1904
+ var WorkerProtocolAcceptedPayloadSchema = z32.object({
1905
+ turnId: z32.string().min(1),
1906
+ protocolVersion: WorkerProtocolVersionSchema
1907
+ }).strict();
1908
+ var WorkerProtocolRejectedPayloadSchema = z32.object({
1909
+ reason: z32.enum(WP_FAILURE_REASON_KINDS),
1910
+ message: z32.string().min(1).optional()
1911
+ }).strict();
1912
+ var WorkerProtocolFailedReasonSchema = z32.enum([
1913
+ "wp_handshake_timeout",
1914
+ "wp_aborted_by_signal",
1915
+ "wp_protocol_violation",
1916
+ "wp_replay_lost",
1917
+ "wp_session_terminated"
1918
+ ]);
1919
+ var WorkerProtocolFailedPayloadSchema = z32.object({
1920
+ reason: WorkerProtocolFailedReasonSchema,
1921
+ message: z32.string().min(1).optional(),
1922
+ abortContext: z32.object({
1923
+ reason: WorkerProtocolAbortReasonSchema,
1924
+ requestedAt: z32.string().min(1).optional()
1925
+ }).strict().optional()
1926
+ }).strict().refine((p) => p.reason !== "wp_aborted_by_signal" || p.abortContext !== void 0, {
1927
+ message: "abortContext required when reason = wp_aborted_by_signal"
1928
+ });
1929
+ var WorkerProtocolCompletedPayloadSchema = z32.record(z32.unknown());
1930
+ var EVENT_TYPE_REGEX = /^([a-z][a-z0-9_]*)\.([a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)?)$/;
1931
+ var EventTypeSchema = z33.string().min(1).max(100, "event_type must not exceed SESSION_EVENT_TYPE_MAX_LENGTH (100)").regex(EVENT_TYPE_REGEX, "event_type must be {domain}.{action} in lowercase snake_case");
1932
+ var EVENT_DOMAINS = [
1933
+ "user",
1934
+ "agent",
1935
+ "session",
1936
+ "span",
1937
+ "worker_protocol",
1938
+ "vault"
1939
+ ];
1940
+ var EVENT_DOMAIN_SET = new Set(EVENT_DOMAINS);
1941
+ var UserMessagePayloadSchema = z33.object({
1942
+ content: z33.array(
1943
+ z33.union([
1944
+ z33.object({ type: z33.literal("text"), text: z33.string() }).strict(),
1945
+ z33.object({ type: z33.literal("image"), source: z33.unknown() }).strict(),
1946
+ z33.object({ type: z33.literal("file"), source: z33.unknown() }).strict()
1947
+ ])
1948
+ )
1949
+ }).strict();
1950
+ var UserInterruptPayloadSchema = z33.object({}).strict();
1951
+ var UserToolConfirmationPayloadSchema = z33.object({
1952
+ toolUseId: z33.string().min(1),
1953
+ result: z33.enum(["allow", "deny"]),
1954
+ denyMessage: z33.string().optional()
1955
+ }).strict();
1956
+ var UserToolResultPayloadSchema = z33.object({
1957
+ toolUseId: z33.string().min(1),
1958
+ content: z33.array(z33.unknown())
1959
+ }).strict();
1960
+ var AgentMessagePayloadSchema = z33.object({
1961
+ content: z33.array(
1962
+ z33.union([
1963
+ z33.object({ type: z33.literal("text"), text: z33.string() }).strict(),
1964
+ z33.object({ type: z33.literal("image"), source: z33.unknown() }).strict()
1965
+ ])
1966
+ )
1967
+ }).strict();
1968
+ var AgentToolUsePayloadSchema = z33.object({
1969
+ toolUseId: z33.string().min(1),
1970
+ toolName: z33.string().min(1),
1971
+ input: z33.record(z33.unknown())
1972
+ }).strict();
1973
+ var AgentToolResultPayloadSchema = z33.object({
1974
+ toolUseId: z33.string().min(1),
1975
+ content: z33.array(z33.unknown()),
1976
+ isError: z33.boolean().optional()
1977
+ }).strict();
1978
+ var AgentMcpToolUsePayloadSchema = z33.object({
1979
+ toolUseId: z33.string().min(1),
1980
+ mcpServerName: z33.string().min(1),
1981
+ toolName: z33.string().min(1),
1982
+ input: z33.record(z33.unknown())
1983
+ }).strict();
1984
+ var AgentCompletedPayloadSchema = z33.object({}).passthrough();
1985
+ var AGENT_SESSION_RESET_REASONS = [
1986
+ "session_terminal",
1987
+ // R-ASB-05 dim (a) — session.status === "failed"
1988
+ "session_lifecycle_terminal",
1989
+ // ready session whose lifecycle_phase is terminating/terminated
1990
+ "binding_missing",
1991
+ // dim (b) — no alive runtime_binding row
1992
+ "ttl_expired",
1993
+ // dim (c) — ttl_expires_at within REPROVISION_BUFFER_MS
1994
+ "keepalive_unhealthy",
1995
+ // dim (d) — MF-4 mark-unhealthy latch tripped
1996
+ "max_lifetime",
1997
+ // dim (e) — MF-5 24h+ session age
1998
+ "agent_session_null"
1999
+ // pre-dim — agent.session_id was NULL on dispatch
2000
+ ];
2001
+ var AgentSessionResetReasonSchema = z33.enum(AGENT_SESSION_RESET_REASONS);
2002
+ var AgentSessionResetPayloadSchema = z33.object({
2003
+ oldSessionId: z33.string().uuid(),
2004
+ newSessionId: z33.string().uuid(),
2005
+ reason: AgentSessionResetReasonSchema,
2006
+ triggeredByRunId: z33.string().uuid(),
2007
+ triggeredAt: z33.string().datetime()
2008
+ }).strict();
2009
+ var AGENT_RECOVERY_ERROR_STAGES = ["provision", "startup", "hydrate", "dispatch"];
2010
+ var AgentRecoveryErrorStageSchema = z33.enum(AGENT_RECOVERY_ERROR_STAGES);
2011
+ var AgentRecoveryStartedV2PayloadSchema = z33.object({
2012
+ /** 1-based attempt counter (first revive of this session = 1). */
2013
+ revivalAttempts: z33.number().int().min(1),
2014
+ /**
2015
+ * REV-INV-7 cap for the chain (typically 3). Optional for backward
2016
+ * compatibility with events emitted before the same-session retry
2017
+ * landed; consumers MUST treat absence as "unknown" rather than
2018
+ * "no cap" — they can fall back to `revivalAttempts >= 3` as the
2019
+ * default budget if they need a UI cue.
2020
+ */
2021
+ maxRevivalAttempts: z33.number().int().min(1).optional(),
2022
+ /** `runtime_bindings.id` of the row this revival is superseding. */
2023
+ predecessorBindingId: z33.string().uuid(),
2024
+ /** UUID of this revival pipeline run; correlates the 4 lifecycle events. */
2025
+ attemptId: z33.string().uuid()
2026
+ }).strict();
2027
+ var AgentRecoveryHydratedV2PayloadSchema = z33.object({
2028
+ messagesCount: z33.number().int().nonnegative(),
2029
+ /** Canonical SHA-256 hex of restored messages (see `pilot-v2-restore-envelope.md` R-RES-03). */
2030
+ messagesHash: z33.string().min(1),
2031
+ degradedRecovery: z33.boolean()
2032
+ }).strict();
2033
+ var AgentRecoveryCompletedV2PayloadSchema = z33.object({
2034
+ degradedRecovery: z33.boolean(),
2035
+ /** Raw `session_events` rows scanned before any cap-trim. */
2036
+ eventsSeen: z33.number().int().nonnegative(),
2037
+ attemptId: z33.string().uuid()
2038
+ }).strict();
2039
+ var AgentRecoveryFailedV2PayloadSchema = z33.object({
2040
+ errorStage: AgentRecoveryErrorStageSchema,
2041
+ /** Human-readable, MUST NOT include credentials / PII. */
2042
+ error: z33.string().min(1),
2043
+ attemptId: z33.string().uuid()
2044
+ }).strict();
2045
+ var SessionStatusCreatedPayloadSchema = z33.object({ sessionId: z33.string().uuid(), createdAt: z33.string() }).strict();
2046
+ var SessionStatusProvisioningPayloadSchema = z33.object({
2047
+ sessionId: z33.string().uuid(),
2048
+ runtimeBindingId: z33.string().optional(),
2049
+ provisionStartedAt: z33.string()
2050
+ }).strict();
2051
+ var SessionStatusStartingPayloadSchema = z33.object({
2052
+ sessionId: z33.string().uuid(),
2053
+ runtimeBindingId: z33.string(),
2054
+ sandboxId: z33.string(),
2055
+ workerEndpoint: z33.string()
2056
+ }).strict();
2057
+ var SessionStatusReadyPayloadSchema = z33.object({
2058
+ sessionId: z33.string().uuid(),
2059
+ readyAt: z33.string(),
2060
+ gateAggregate: z33.object({ worker: z33.literal(true) }).passthrough()
2061
+ }).strict();
2062
+ var SessionStatusFailedPayloadSchema = z33.object({
2063
+ sessionId: z33.string().uuid(),
2064
+ failedAt: z33.string(),
2065
+ primaryFailure: z33.object({
2066
+ source: z33.string(),
2067
+ code: z33.string(),
2068
+ message: z33.string().optional()
2069
+ })
2070
+ }).strict();
2071
+ var SessionIdlePayloadSchema = z33.object({
2072
+ sessionId: z33.string().uuid(),
2073
+ stopReason: z33.object({
2074
+ type: z33.enum(["requires_action", "end_turn"]),
2075
+ eventIds: z33.array(z33.string()).optional()
2076
+ })
2077
+ }).strict();
2078
+ var EventTypeSessionStatusSchema = z33.enum([
2079
+ "session.status_created",
2080
+ "session.status_provisioning",
2081
+ "session.status_starting",
2082
+ "session.status_ready",
2083
+ "session.status_failed"
2084
+ ]);
2085
+ var SpanStartPayloadSchema = z33.object({
2086
+ spanId: z33.string().min(1),
2087
+ parentSpanId: z33.string().optional(),
2088
+ name: z33.string().min(1),
2089
+ startedAt: z33.string(),
2090
+ attributes: z33.record(z33.unknown()).optional()
2091
+ }).strict();
2092
+ var SpanEndPayloadSchema = z33.object({
2093
+ spanId: z33.string().min(1),
2094
+ endedAt: z33.string(),
2095
+ status: z33.enum(["ok", "error"]).optional()
2096
+ }).strict();
2097
+ var SpanEventPayloadSchema = z33.object({
2098
+ spanId: z33.string().min(1),
2099
+ eventName: z33.string().min(1),
2100
+ attributes: z33.record(z33.unknown()).optional()
2101
+ }).strict();
2102
+ var VaultArchivedPayloadSchema = z33.object({ vaultId: z33.string().min(1), archivedAt: z33.string() }).strict();
2103
+ var VaultDeletedPayloadSchema = z33.object({ vaultId: z33.string().min(1), deletedAt: z33.string() }).strict();
2104
+ var VaultCredentialArchivedPayloadSchema = z33.object({
2105
+ vaultId: z33.string().min(1),
2106
+ credentialId: z33.string().min(1),
2107
+ archivedAt: z33.string()
2108
+ }).strict();
2109
+ var VaultCredentialDeletedPayloadSchema = z33.object({
2110
+ vaultId: z33.string().min(1),
2111
+ credentialId: z33.string().min(1),
2112
+ deletedAt: z33.string()
2113
+ }).strict();
2114
+ var VaultCredentialRefreshFailedPayloadSchema = z33.object({
2115
+ vaultId: z33.string().min(1),
2116
+ credentialId: z33.string().min(1),
2117
+ failedStatus: z33.enum(["invalid", "unknown"]),
2118
+ lastRefreshedAt: z33.string()
2119
+ }).strict();
2120
+ var VaultCredentialTargetNotAllowedPayloadSchema = z33.object({
2121
+ sessionId: z33.string().uuid(),
2122
+ vaultId: z33.string().optional(),
2123
+ credentialId: z33.string().optional(),
2124
+ mcpServerUrl: z33.string(),
2125
+ reason: z33.literal("target_not_in_revision_allowlist"),
2126
+ recoverable: z33.literal(false),
2127
+ occurredAt: z33.string()
2128
+ }).strict();
2129
+ var STANDARD_EVENT_PAYLOAD_SCHEMAS = {
2130
+ "user.message": UserMessagePayloadSchema,
2131
+ "user.interrupt": UserInterruptPayloadSchema,
2132
+ "user.tool_confirmation": UserToolConfirmationPayloadSchema,
2133
+ "user.tool_result": UserToolResultPayloadSchema,
2134
+ "agent.message": AgentMessagePayloadSchema,
2135
+ "agent.tool_use": AgentToolUsePayloadSchema,
2136
+ "agent.tool_result": AgentToolResultPayloadSchema,
2137
+ "agent.mcp_tool_use": AgentMcpToolUsePayloadSchema,
2138
+ "agent.completed": AgentCompletedPayloadSchema,
2139
+ "agent.session_reset": AgentSessionResetPayloadSchema,
2140
+ "agent.recovery_started": AgentRecoveryStartedV2PayloadSchema,
2141
+ "agent.recovery_hydrated": AgentRecoveryHydratedV2PayloadSchema,
2142
+ "agent.recovery_completed": AgentRecoveryCompletedV2PayloadSchema,
2143
+ "agent.recovery_failed": AgentRecoveryFailedV2PayloadSchema,
2144
+ "session.status_created": SessionStatusCreatedPayloadSchema,
2145
+ "session.status_provisioning": SessionStatusProvisioningPayloadSchema,
2146
+ "session.status_starting": SessionStatusStartingPayloadSchema,
2147
+ "session.status_ready": SessionStatusReadyPayloadSchema,
2148
+ "session.status_failed": SessionStatusFailedPayloadSchema,
2149
+ "session.idle": SessionIdlePayloadSchema,
2150
+ "span.start": SpanStartPayloadSchema,
2151
+ "span.end": SpanEndPayloadSchema,
2152
+ "span.event": SpanEventPayloadSchema,
2153
+ "vault.archived": VaultArchivedPayloadSchema,
2154
+ "vault.deleted": VaultDeletedPayloadSchema,
2155
+ "vault.credential_archived": VaultCredentialArchivedPayloadSchema,
2156
+ "vault.credential_deleted": VaultCredentialDeletedPayloadSchema,
2157
+ "vault.credential_refresh_failed": VaultCredentialRefreshFailedPayloadSchema,
2158
+ "vault.credential_target_not_allowed": VaultCredentialTargetNotAllowedPayloadSchema,
2159
+ // §1.5 worker_protocol.* — 4 kinds × 5 suffixes = 20 standard event types
2160
+ "worker_protocol.prompt.dispatched": WorkerProtocolPromptRequestSchema,
2161
+ "worker_protocol.prompt.accepted": WorkerProtocolAcceptedPayloadSchema,
2162
+ "worker_protocol.prompt.rejected": WorkerProtocolRejectedPayloadSchema,
2163
+ "worker_protocol.prompt.completed": WorkerProtocolCompletedPayloadSchema,
2164
+ "worker_protocol.prompt.failed": WorkerProtocolFailedPayloadSchema,
2165
+ "worker_protocol.followup.dispatched": WorkerProtocolFollowupRequestSchema,
2166
+ "worker_protocol.followup.accepted": WorkerProtocolAcceptedPayloadSchema,
2167
+ "worker_protocol.followup.rejected": WorkerProtocolRejectedPayloadSchema,
2168
+ "worker_protocol.followup.completed": WorkerProtocolCompletedPayloadSchema,
2169
+ "worker_protocol.followup.failed": WorkerProtocolFailedPayloadSchema,
2170
+ "worker_protocol.abort.dispatched": WorkerProtocolAbortRequestSchema,
2171
+ "worker_protocol.abort.accepted": WorkerProtocolAcceptedPayloadSchema,
2172
+ "worker_protocol.abort.rejected": WorkerProtocolRejectedPayloadSchema,
2173
+ "worker_protocol.abort.completed": WorkerProtocolCompletedPayloadSchema,
2174
+ "worker_protocol.abort.failed": WorkerProtocolFailedPayloadSchema,
2175
+ "worker_protocol.restore.dispatched": WorkerProtocolRestoreRequestSchema,
2176
+ "worker_protocol.restore.accepted": WorkerProtocolAcceptedPayloadSchema,
2177
+ "worker_protocol.restore.rejected": WorkerProtocolRejectedPayloadSchema,
2178
+ "worker_protocol.restore.completed": WorkerProtocolCompletedPayloadSchema,
2179
+ "worker_protocol.restore.failed": WorkerProtocolFailedPayloadSchema
2180
+ };
2181
+ var STANDARD_EVENT_TYPES = Object.keys(
2182
+ STANDARD_EVENT_PAYLOAD_SCHEMAS
2183
+ );
2184
+ var StandardEventTypeSchema = z33.enum(STANDARD_EVENT_TYPES);
2185
+ var POD_AGENT_ENDPOINT_PORT = 8790;
2186
+ var AgentPortSpecSchema = z34.object({
2187
+ name: z34.string().min(1).max(63),
2188
+ port: z34.number().int().min(1).max(65535),
2189
+ protocol: z34.literal("TCP")
2190
+ }).strict();
2191
+ var IngressPathTypeSchema = z34.enum(["prefix", "exact"]);
2192
+ var IngressSpecSchema = z34.object({
2193
+ name: z34.string().min(1).max(63),
2194
+ backendPort: z34.number().int().min(1).max(65535).refine((p) => p !== POD_AGENT_ENDPOINT_PORT, {
2195
+ message: `backendPort ${POD_AGENT_ENDPOINT_PORT} is reserved for the platform pod-agent endpoint and MUST NOT be exposed via ingress.`
2196
+ }),
2197
+ hostPrefix: z34.string().min(1).max(63),
2198
+ path: z34.string().min(1).startsWith("/"),
2199
+ pathType: IngressPathTypeSchema
2200
+ }).strict();
2201
+ var AgentPublicEndpointSchema = z34.object({
2202
+ /** Stable name; matches the originating `IngressSpec.name`. */
2203
+ name: z34.string().min(1).max(63),
2204
+ /** TCP port the ingress targets; equals `IngressSpec.backendPort`. */
2205
+ backendPort: z34.number().int().min(1).max(65535),
2206
+ /**
2207
+ * Declaration-derived public URL (`https://{hostPrefix}.{baseDomain}{path}`).
2208
+ * Best-effort — clients MUST validate reachability via standard HTTP
2209
+ * error handling; sandbox-side reconciliation is platform-internal.
2210
+ */
2211
+ url: z34.string().url(),
2212
+ /** Path prefix or exact match; must start with `/`. */
2213
+ path: z34.string().min(1).startsWith("/"),
2214
+ /** Business-facing pathType (lowercase). */
2215
+ pathType: IngressPathTypeSchema
2216
+ }).strict();
2217
+ var WorkloadKindSchema = z35.enum([
2218
+ "managed_agent",
2219
+ "batch_task",
2220
+ "external_worker",
2221
+ "self_managed"
2222
+ ]);
2223
+ var SessionStatusSchema = z35.enum([
2224
+ "created",
2225
+ "provisioning",
2226
+ "starting",
2227
+ "ready",
2228
+ "failed"
2229
+ ]);
2230
+ var SessionUsageKindSchema = z35.enum(["run_scoped", "conversation", "prewarmed"]);
2231
+ var StartupGateStatusSchema = z35.enum(["true", "false", "unknown", "stale"]);
2232
+ var FailureReasonSourceSchema = z35.enum([
2233
+ "control_plane",
2234
+ "scheduler",
2235
+ "runtime_provider",
2236
+ "pod_agent",
2237
+ "worker"
2238
+ ]);
2239
+ var FailureReasonCodeSchema = z35.enum([
2240
+ "TEMPLATE_NOT_FOUND",
2241
+ "POOL_NOT_READY",
2242
+ "SANDBOX_CREATE_FAILED",
2243
+ "SANDBOX_CREATE_TIMEOUT",
2244
+ "POD_AGENT_UNREACHABLE",
2245
+ "WORKER_START_FAILED",
2246
+ "WORKER_PROCESS_EXITED",
2247
+ "WORKER_HEALTH_FAILED",
2248
+ "WORKER_INTERNAL_ERROR",
2249
+ "WORKER_HEALTH_TIMEOUT",
2250
+ "GATE_REPORTED_FAILED",
2251
+ "GATE_READY_TIMEOUT",
2252
+ "PERMISSION_DENIED",
2253
+ "UNKNOWN_STARTUP_FAILURE"
2254
+ ]);
2255
+ var WorkerHealthStateSchema = z35.enum(["heartbeat", "ready", "failed"]);
2256
+ var WorkerHealthReasonCodeSchema = z35.enum([
2257
+ "WORKER_BOOTING",
2258
+ "WORKER_READY",
2259
+ "WORKER_PROCESS_EXITED",
2260
+ "WORKER_HEALTH_CHECK_FAILED",
2261
+ "WORKER_INTERNAL_ERROR"
2262
+ ]);
2263
+ var WorkerEndpointSpecSchema = z35.object({
2264
+ port: z35.number().int().positive(),
2265
+ basePath: z35.string().optional()
2266
+ });
2267
+ var WorkerHealthSpecSchema = z35.object({
2268
+ transport: z35.literal("control_plane_pull"),
2269
+ path: z35.literal("/pilot/worker/health"),
2270
+ pollIntervalSeconds: z35.number().int().positive(),
2271
+ requestTimeoutSeconds: z35.number().int().positive(),
2272
+ staleAfterSeconds: z35.number().int().positive(),
2273
+ startupTimeoutSeconds: z35.number().int().positive()
2274
+ });
2275
+ var P0_WORKER_HEALTH_SPEC = {
2276
+ transport: "control_plane_pull",
2277
+ path: "/pilot/worker/health",
2278
+ pollIntervalSeconds: 5,
2279
+ requestTimeoutSeconds: 3,
2280
+ staleAfterSeconds: 15,
2281
+ startupTimeoutSeconds: 60
2282
+ };
2283
+ var ImageDigestSchema = z35.string().min(1).regex(/^sha256:[0-9a-fA-F]{64}$/, "Image digest must be a sha256 digest");
2284
+ var ImageProvenanceSchema = z35.discriminatedUnion("kind", [
2285
+ z35.object({
2286
+ kind: z35.literal("image_asset"),
2287
+ imageAssetId: z35.string().min(1),
2288
+ imageRef: z35.string().min(1).optional(),
2289
+ imageDigest: ImageDigestSchema,
2290
+ sourceCommit: z35.string().min(1).optional(),
2291
+ sourceRef: z35.string().min(1).optional(),
2292
+ metadata: z35.record(z35.unknown()).optional()
2293
+ }).strict(),
2294
+ z35.object({
2295
+ kind: z35.literal("platform_image"),
2296
+ platformImageId: z35.string().min(1),
2297
+ version: z35.string().min(1),
2298
+ imageRef: z35.string().min(1).optional(),
2299
+ imageDigest: ImageDigestSchema,
2300
+ metadata: z35.record(z35.unknown()).optional()
2301
+ }).strict(),
2302
+ z35.object({
2303
+ kind: z35.literal("legacy_external_template"),
2304
+ providerTemplateName: z35.string().min(1),
2305
+ metadata: z35.record(z35.unknown()).optional()
2306
+ }).strict()
2307
+ ]);
2308
+ var RuntimeTemplateSnapshotSchema = z35.object({
2309
+ provider: z35.literal("kanyun"),
2310
+ providerTemplateName: z35.string().min(1),
2311
+ providerPoolName: z35.string().min(1).optional(),
2312
+ imageProvenance: ImageProvenanceSchema.optional(),
2313
+ defaultWorkerEndpoint: WorkerEndpointSpecSchema,
2314
+ healthSpec: WorkerHealthSpecSchema.default(P0_WORKER_HEALTH_SPEC),
2315
+ /**
2316
+ * PR-E0 / §6 Wave 1 — business worker listen port (`POD_AGENT_WORKER_PORT`).
2317
+ * Defaults to 8787 in the auto-create API; persisted into the snapshot so a
2318
+ * published Revision freezes the value even if the source `runtime_templates`
2319
+ * row is later mutated.
2320
+ */
2321
+ workerPort: z35.number().int().min(1).max(65535).optional(),
2322
+ /**
2323
+ * Internal-only additional business container ports. Strict — does NOT
2324
+ * carry expose/hostPrefix/path; public exposure is declared via `ingresses[]`.
2325
+ */
2326
+ agentPorts: z35.array(AgentPortSpecSchema).optional(),
2327
+ /**
2328
+ * Independent public ingress rules. Each entry's `backendPort` MUST reference
2329
+ * `workerPort` or one of `agentPorts[].port`; cross-field validation is the
2330
+ * caller's responsibility via `validateRuntimeTemplateNetwork()` from
2331
+ * `@pilot/contracts` after `.parse(snapshot)`.
2332
+ */
2333
+ ingresses: z35.array(IngressSpecSchema).optional(),
2334
+ /**
2335
+ * Per-workload sandbox TTL (seconds) — lets each business define how long its
2336
+ * runtime sandbox lives before the provider reclaims it. Read by
2337
+ * `SessionStartupService` when provisioning; when omitted, the platform
2338
+ * `DEFAULT_TTL_SECONDS` applies (backward-compatible). A keep-alive service
2339
+ * extends the TTL while the session is active, so this primarily governs how
2340
+ * long an *idle* sandbox persists. Capped at 30 days to bound resource usage.
2341
+ */
2342
+ ttlSeconds: z35.number().int().positive().max(30 * 24 * 60 * 60).optional(),
2343
+ /**
2344
+ * Selects which set of handlers the agent-worker process registers
2345
+ * (`coder` for the JSON-payload pilot-coder loop, `echo` for the bare-text
2346
+ * managed_agent Default UI demo). Read by control-plane at startWorker
2347
+ * dispatch, forwarded via `PodAgentStartWorkerRequest.agentFlavor`,
2348
+ * eventually injected by pod-agent as `PILOT_AGENT_FLAVOR` env var.
2349
+ * Undefined → agent-worker defaults to coder (existing behavior,
2350
+ * backward-compatible for all existing snapshots).
2351
+ *
2352
+ * Locked enum: extend ONLY after the corresponding `FLAVOR_REGISTRY`
2353
+ * entry exists in `apps/agent-worker/src/v2/init.ts` (otherwise the
2354
+ * worker falls back to coder + console.warn).
2355
+ */
2356
+ agentFlavor: z35.enum(["coder", "echo"]).optional(),
2357
+ metadata: z35.record(z35.unknown()).optional()
2358
+ });
2359
+ var WorkerContractRefSchema = z35.object({
2360
+ kind: WorkloadKindSchema,
2361
+ name: z35.string().optional(),
2362
+ version: z35.string().optional(),
2363
+ metadata: z35.record(z35.unknown()).optional()
2364
+ });
2365
+ var SESSION_CONFIG_VALUE_KEY_MAX_LENGTH = 100;
2366
+ var SESSION_EVENT_ID_MAX_LENGTH = 100;
2367
+ var SESSION_EVENT_TYPE_MAX_LENGTH = 100;
2368
+ var RESERVED_SESSION_CONFIG_ENV_PREFIXES = ["PILOT_", "SESSION_", "PLATFORM_"];
2369
+ function isReservedSessionConfigEnvKey(key) {
2370
+ return RESERVED_SESSION_CONFIG_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
2371
+ }
2372
+ var SessionConfigValuesSchema = z35.record(z35.string()).superRefine((values, ctx) => {
2373
+ for (const key of Object.keys(values)) {
2374
+ if (key.length > SESSION_CONFIG_VALUE_KEY_MAX_LENGTH) {
2375
+ ctx.addIssue({
2376
+ code: z35.ZodIssueCode.too_big,
2377
+ maximum: SESSION_CONFIG_VALUE_KEY_MAX_LENGTH,
2378
+ type: "string",
2379
+ inclusive: true,
2380
+ message: `Config value key must be at most ${SESSION_CONFIG_VALUE_KEY_MAX_LENGTH} characters`,
2381
+ path: [key]
2382
+ });
2383
+ }
2384
+ if (isReservedSessionConfigEnvKey(key)) {
2385
+ ctx.addIssue({
2386
+ code: z35.ZodIssueCode.custom,
2387
+ message: `Config value key ${key} uses a reserved Pilot platform prefix`,
2388
+ path: [key]
2389
+ });
2390
+ }
2391
+ }
2392
+ });
2393
+ var SessionEventSchema = z35.object({
2394
+ id: z35.string().uuid(),
2395
+ sessionId: z35.string().uuid(),
2396
+ eventId: z35.string().min(1).max(SESSION_EVENT_ID_MAX_LENGTH),
2397
+ eventType: z35.string().min(1).max(SESSION_EVENT_TYPE_MAX_LENGTH),
2398
+ payload: z35.unknown().optional(),
2399
+ createdAt: z35.string()
2400
+ });
2401
+ var SessionEventAppendRequestSchema = z35.object({
2402
+ eventId: z35.string().min(1).max(SESSION_EVENT_ID_MAX_LENGTH).optional(),
2403
+ eventType: z35.string().min(1).max(SESSION_EVENT_TYPE_MAX_LENGTH),
2404
+ payload: z35.unknown().optional()
2405
+ });
2406
+ var SessionTokenClaimsSchema = z35.object({
2407
+ type: z35.literal("pilot-session"),
2408
+ jti: z35.string().uuid(),
2409
+ session_id: z35.string().uuid(),
2410
+ workload_id: z35.string().uuid(),
2411
+ revision_id: z35.string().uuid(),
2412
+ tenant_id: z35.string().uuid(),
2413
+ iat: z35.number().int().nonnegative(),
2414
+ exp: z35.number().int().positive().optional()
2415
+ });
2416
+ var WorkloadIdentityClaimSchema = z35.object({
2417
+ type: z35.literal("pilot-workload-identity"),
2418
+ workload_id: z35.string().uuid(),
2419
+ revision_id: z35.string().uuid(),
2420
+ tenant_id: z35.string().uuid()
2421
+ });
2422
+ var StartupGatePolicySchema = z35.object({
2423
+ required: z35.array(z35.string().min(1)).min(1),
2424
+ optional: z35.array(z35.string().min(1)).optional()
2425
+ });
2426
+ var StartupGateConditionSchema = z35.object({
2427
+ gate: z35.string().min(1),
2428
+ status: StartupGateStatusSchema,
2429
+ reasonCode: z35.string().optional(),
2430
+ message: z35.string().optional(),
2431
+ observedAt: z35.string(),
2432
+ lastTransitionAt: z35.string().optional(),
2433
+ metadata: z35.record(z35.unknown()).optional()
2434
+ });
2435
+ var FailureReasonSchema = z35.object({
2436
+ code: FailureReasonCodeSchema,
2437
+ source: FailureReasonSourceSchema,
2438
+ message: z35.string(),
2439
+ observedAt: z35.string(),
2440
+ metadata: z35.record(z35.unknown()).optional()
2441
+ });
2442
+ var FailureReasonCandidateSchema = z35.object({
2443
+ code: z35.string().min(1),
2444
+ message: z35.string(),
2445
+ observedAt: z35.string().optional(),
2446
+ metadata: z35.record(z35.unknown()).optional()
2447
+ });
2448
+ var WorkerReportedConditionSchema = z35.object({
2449
+ gate: z35.string().min(1),
2450
+ status: StartupGateStatusSchema,
2451
+ reasonCode: z35.string().optional(),
2452
+ message: z35.string().optional(),
2453
+ observedAt: z35.string().optional(),
2454
+ metadata: z35.record(z35.unknown()).optional()
2455
+ });
2456
+ var WorkerHealthObservationSchema = z35.object({
2457
+ state: WorkerHealthStateSchema,
2458
+ reasonCode: WorkerHealthReasonCodeSchema.optional(),
2459
+ message: z35.string().optional(),
2460
+ metadata: z35.record(z35.unknown()).optional(),
2461
+ conditions: z35.array(WorkerReportedConditionSchema).optional()
2462
+ });
2463
+ var PodAgentHealthResponseSchema = z35.discriminatedUnion("kind", [
2464
+ z35.object({
2465
+ kind: z35.literal("worker_health"),
2466
+ observedAt: z35.string(),
2467
+ worker: WorkerHealthObservationSchema
2468
+ }),
2469
+ z35.object({
2470
+ kind: z35.literal("worker_start_failed"),
2471
+ observedAt: z35.string(),
2472
+ failureCandidate: FailureReasonCandidateSchema
2473
+ })
2474
+ ]);
2475
+ var PodAgentStartWorkerRequestSchema = z35.object({
2476
+ sessionId: z35.string().uuid(),
2477
+ workloadId: z35.string().uuid(),
2478
+ revisionId: z35.string().uuid(),
2479
+ runtimeBindingId: z35.string().uuid(),
2480
+ workerContract: WorkerContractRefSchema,
2481
+ healthSpec: WorkerHealthSpecSchema,
2482
+ env: z35.record(z35.string()).optional(),
2483
+ metadata: z35.record(z35.unknown()).optional(),
2484
+ /**
2485
+ * Pod-Agent-only auth factor for upcoming Pilot v2 internal credentials API
2486
+ * (`POST /api/internal/credentials/*`). The token is generated by control-plane
2487
+ * at session creation time, stored on the session row, and delivered to
2488
+ * pod-agent **once** via this start request. Pod-agent MUST hold it in memory
2489
+ * only and MUST NOT forward it to the supervised worker process (neither via
2490
+ * env, file, nor IPC). See `specs/features/pilot-v2-pod-agent-oci-runtime-layer.md`
2491
+ * § "podAgentToken (Pod-Agent Auth Factor)" for the full contract.
2492
+ *
2493
+ * Backward-compat: optional in P3 Pre-P1 — pre-existing callers (legacy
2494
+ * control-worker, `--smoke` check) may omit it; pod-agent then operates in
2495
+ * `legacy` mode (no `podAgentToken` held, any future internal-credentials
2496
+ * API calls SHALL reject). P3 Phase 1 L1.4 will tighten control-plane to
2497
+ * always send this field; the schema may be promoted to required in a
2498
+ * separate spec PR after the v1 retirement window closes.
2499
+ */
2500
+ podAgentToken: z35.string().min(32).optional(),
2501
+ /**
2502
+ * Optional agent-worker handler flavor selector. Pod-agent forwards this
2503
+ * verbatim into the spawned child as `PILOT_AGENT_FLAVOR` env var (see
2504
+ * `apps/pod-agent/src/process-manager.ts → buildWorkerEnv`). Undefined →
2505
+ * pod-agent omits the env var, agent-worker `resolveFlavor()` falls back
2506
+ * to coder. Source of truth lives in
2507
+ * `RuntimeTemplateSnapshot.agentFlavor`; control-plane is responsible
2508
+ * for projecting that into this field at `startWorker` call time.
2509
+ */
2510
+ agentFlavor: z35.enum(["coder", "echo"]).optional(),
2511
+ /**
2512
+ * Optional agent-worker bundle tarball URL (v2 hot-deploy). When set,
2513
+ * pod-agent downloads + extracts this tarball over the baked
2514
+ * `/opt/pilot/agent-worker` dist BEFORE spawning the worker, so the
2515
+ * running binary matches the latest `apps/agent-worker` build rather
2516
+ * than whatever was baked into the Kanyun pod image. Mirrors the v1
2517
+ * `OrchestrationService.deployAgentWorker` mechanism (which has no v2
2518
+ * equivalent — see
2519
+ * `docs/handoff/2026-06-10-echo-runtime-coordinator-actions.md` §2).
2520
+ *
2521
+ * The URL is resolved by control-worker (`PodAgentHttpClient`) from
2522
+ * `AGENT_WORKER_BUNDLE_OSS_KEY` (presigned) / `AGENT_WORKER_BUNDLE_URL`
2523
+ * env — the same env contract v1 already uses. control-plane stays
2524
+ * OSS-agnostic and does NOT populate this field.
2525
+ *
2526
+ * Backward-compat: optional. Omitted → pod-agent skips hot-deploy and
2527
+ * runs the baked dist (legacy behavior). Old pod-agents that predate
2528
+ * this field ignore it (zod strip), also falling back to baked dist.
2529
+ */
2530
+ agentWorkerBundleUrl: z35.string().url().optional()
2531
+ });
2532
+ var PodAgentStartWorkerResponseSchema = z35.discriminatedUnion("kind", [
2533
+ z35.object({
2534
+ kind: z35.literal("accepted"),
2535
+ observedAt: z35.string(),
2536
+ metadata: z35.record(z35.unknown()).optional()
2537
+ }),
2538
+ z35.object({
2539
+ kind: z35.literal("worker_start_failed"),
2540
+ observedAt: z35.string(),
2541
+ failureCandidate: FailureReasonCandidateSchema
2542
+ })
2543
+ ]);
2544
+ var CreateSessionRequestSchema = z35.object({
2545
+ /**
2546
+ * P4 Phase 1.5 — optional caller-supplied resource id. When present, the
2547
+ * control-plane uses this UUID as the new Session row's primary key
2548
+ * (caller-controlled pin); when omitted, the control-plane generates a
2549
+ * `randomUUID()` (legacy / backward-compat behavior).
2550
+ *
2551
+ * Naming note: the field is intentionally named `sessionId` (not `id`) to
2552
+ * align with `CreateSessionResponseSchema.sessionId`. Despite the same
2553
+ * name on request and response, the semantics differ:
2554
+ * - request.sessionId = caller-supplied PK pin (write-side)
2555
+ * - response.sessionId = the actual Session row id (read-side, equal to
2556
+ * the request pin when supplied, or to the control-plane-generated
2557
+ * UUID when omitted)
2558
+ *
2559
+ * Use case: portal `POST /api/agents` dispatches v2 runs via
2560
+ * `dispatchV2AgentSession` and needs `runId === sessionId ===
2561
+ * runtimeBindingId` per `pilot-v2-managed-agent-handler-contract.md`
2562
+ * § "Managed-agent runtime binding cohort". Caller pins this field to
2563
+ * the freshly created run id so the entire cohort shares one UUID.
2564
+ */
2565
+ sessionId: z35.string().uuid().optional(),
2566
+ projectId: z35.string().uuid(),
2567
+ workloadId: z35.string().uuid(),
2568
+ revisionId: z35.string().uuid().optional(),
2569
+ idempotencyScope: z35.string().min(1).optional(),
2570
+ idempotencyKey: z35.string().min(1).optional(),
2571
+ configValues: SessionConfigValuesSchema.optional(),
2572
+ metadata: z35.record(z35.unknown()).optional(),
2573
+ /**
2574
+ * GAP1-B (rush-app v2 migration) — optional caller-supplied stable runtime
2575
+ * claim name. Forwarded to the runtime provider's `create()` as the sandbox
2576
+ * `claimName`, which the sandbox control plane embeds in the public ingress
2577
+ * host (`<hostPrefix>-<claimName>.<baseDomain>`). Supplying a stable,
2578
+ * project-scoped value keeps preview URLs stable across abort→recreate
2579
+ * (scale-to-zero) cycles; omitted → control plane generates a per-sandbox
2580
+ * `claim-<nanoTS>` (host drifts on every recreate).
2581
+ *
2582
+ * MUST be DNS-label safe (lowercase alphanumeric + hyphen); the sandbox
2583
+ * control plane truncates the `<hostPrefix>-<claimName>` first label to 63
2584
+ * chars, so the distinguishing portion must fit within budget. Callers
2585
+ * (e.g. rush-app) typically derive it from a project-scoped key such as
2586
+ * `rush-<normalizedProjectId>`.
2587
+ */
2588
+ runtimeClaimName: z35.string().min(1).max(48).regex(
2589
+ /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/,
2590
+ "runtimeClaimName must be DNS-label safe (lowercase alphanumeric and hyphens, no leading/trailing hyphen)"
2591
+ ).optional(),
2592
+ /**
2593
+ * PR-1 / §INV-2.1 — optional list of vault `public_id` values to bind to
2594
+ * this Session. The control plane resolves each `vlt_*` public_id to the
2595
+ * internal uuid, inserts `session_vault_bindings` rows, and freezes an
2596
+ * `allowedMcpTargets` snapshot from the active credentials' MCP URLs.
2597
+ *
2598
+ * Constraints (PR1-E):
2599
+ * - Each entry MUST match `^vlt_[a-z0-9]+$` (lowercase alphanumeric).
2600
+ * - Maximum 64 entries per request.
2601
+ * - Duplicates are rejected at the Zod layer (→ 400).
2602
+ * Requires `vaults:read` (or `vaults:admin`) scope (PR1-B → 403 if absent).
2603
+ */
2604
+ vault_ids: z35.array(z35.string().regex(/^vlt_[a-z0-9]+$/, "vault_id must match vlt_[a-z0-9]+")).max(64, "vault_ids must have at most 64 entries").optional()
2605
+ }).strict().refine(
2606
+ (data) => {
2607
+ if (!data.vault_ids) return true;
2608
+ return new Set(data.vault_ids).size === data.vault_ids.length;
2609
+ },
2610
+ {
2611
+ message: "vault_ids must not contain duplicates",
2612
+ path: ["vault_ids"]
2613
+ }
2614
+ );
2615
+ var CreateSessionResponseSchema = z35.object({
2616
+ sessionId: z35.string().uuid(),
2617
+ status: SessionStatusSchema,
2618
+ /**
2619
+ * PR-1 / §INV-2.1 — MCP target URLs frozen at Session creation time.
2620
+ * Present only when the request supplied `vault_ids`; absent otherwise.
2621
+ * Each entry is a URL string (no internal uuids exposed — INV-1.1).
2622
+ */
2623
+ allowed_mcp_targets: z35.array(z35.string().url()).optional()
2624
+ });
2625
+ var RESERVED_HEADERS = /* @__PURE__ */ new Set([
2626
+ "authorization",
2627
+ "host",
2628
+ "content-length",
2629
+ "content-encoding",
2630
+ "transfer-encoding",
2631
+ "connection",
2632
+ "upgrade",
2633
+ "cookie",
2634
+ "set-cookie",
2635
+ "server",
2636
+ "date"
2637
+ ]);
2638
+ function isReservedHeader(name) {
2639
+ const lower = name.toLowerCase();
2640
+ return RESERVED_HEADERS.has(lower) || lower.startsWith("x-pilot-");
2641
+ }
2642
+ var VaultCredentialAuthTypeSchema = z36.enum(["mcp_oauth", "static_bearer"]);
2643
+ var VaultCredentialRefreshStatusSchema = z36.enum([
2644
+ "success",
2645
+ "failed_invalid",
2646
+ "failed_unknown"
2647
+ ]);
2648
+ var CustomHeadersSchema = z36.record(z36.string().min(1).max(100), z36.string().min(0).max(2048)).refine((m) => Object.keys(m).length <= 32, {
2649
+ message: "vault_credential_custom_headers_too_many_entries"
2650
+ }).refine((m) => Object.keys(m).every((k) => !isReservedHeader(k)), {
2651
+ message: "vault_credential_reserved_header_conflict"
2652
+ });
2653
+ var McpOAuthCredentialSchema = z36.object({
2654
+ type: z36.literal("mcp_oauth"),
2655
+ mcpServerUrl: z36.string().url(),
2656
+ /**
2657
+ * Initial access token; write-only after create — never returned
2658
+ * by `VaultCredentialRecord` (per INV-3 / Claude write-only
2659
+ * invariant).
2660
+ */
2661
+ accessToken: z36.string().min(1),
2662
+ expiresAt: z36.string().datetime(),
2663
+ customHeaders: CustomHeadersSchema.optional(),
2664
+ refresh: z36.object({
2665
+ tokenEndpoint: z36.string().url(),
2666
+ clientId: z36.string().min(1),
2667
+ scope: z36.string().optional(),
2668
+ /** Write-only; never returned. */
2669
+ refreshToken: z36.string().min(1),
2670
+ tokenEndpointAuth: z36.discriminatedUnion("type", [
2671
+ z36.object({ type: z36.literal("none") }).strict(),
2672
+ z36.object({
2673
+ type: z36.literal("client_secret_basic"),
2674
+ clientSecret: z36.string().min(1)
2675
+ }).strict(),
2676
+ z36.object({
2677
+ type: z36.literal("client_secret_post"),
2678
+ clientSecret: z36.string().min(1)
2679
+ }).strict()
2680
+ ])
2681
+ }).strict()
2682
+ }).strict();
2683
+ var StaticBearerCredentialSchema = z36.object({
2684
+ type: z36.literal("static_bearer"),
2685
+ mcpServerUrl: z36.string().url(),
2686
+ accessToken: z36.string().min(1),
2687
+ customHeaders: CustomHeadersSchema.optional()
2688
+ }).strict();
2689
+ var CreateVaultRequestSchema = z36.object({
2690
+ workspaceId: z36.string().uuid(),
2691
+ displayName: z36.string().min(1).max(200),
2692
+ external_user_id: z36.string().min(1).max(200),
2693
+ metadata: z36.record(z36.unknown()).optional()
2694
+ }).strict();
2695
+ var VaultRecordSchema = z36.object({
2696
+ type: z36.literal("vault"),
2697
+ /** INV-1.1 public_id, `vlt_*` prefix. */
2698
+ id: z36.string().regex(/^vlt_[a-zA-Z0-9]+$/),
2699
+ workspaceId: z36.string().uuid(),
2700
+ /**
2701
+ * INV-1 second ownership layer — Pilot Platform Token actor /
2702
+ * credential owner principal id (IdP-agnostic per spec round 6).
2703
+ * Set server-side at create time from the Platform Token actor
2704
+ * identity; immutable. NOT a terminal user; NOT equivalent to
2705
+ * `external_user_id`.
2706
+ */
2707
+ actorId: z36.string().min(1),
2708
+ /** INV-1 third ownership layer — opaque business-side identifier. */
2709
+ external_user_id: z36.string().min(1),
2710
+ displayName: z36.string().min(1),
2711
+ metadata: z36.record(z36.unknown()).optional(),
2712
+ createdAt: z36.string().datetime(),
2713
+ updatedAt: z36.string().datetime(),
2714
+ archivedAt: z36.string().datetime().nullable()
2715
+ }).strict();
2716
+ var ListVaultsFilterSchema = z36.object({
2717
+ /**
2718
+ * Business-opaque cohort filter. Pilot does not interpret the
2719
+ * value — it is matched verbatim against the stored
2720
+ * `external_user_id` column.
2721
+ */
2722
+ external_user_id: z36.string().min(1).optional(),
2723
+ /** When true, archived rows are included; default `false`. */
2724
+ includeArchived: z36.boolean().optional()
2725
+ }).strict();
2726
+ var CreateCredentialRequestSchema = z36.object({
2727
+ displayName: z36.string().min(1).max(200),
2728
+ auth: z36.discriminatedUnion("type", [McpOAuthCredentialSchema, StaticBearerCredentialSchema])
2729
+ }).strict();
2730
+ var UpdateCredentialRequestSchema = z36.object({
2731
+ displayName: z36.string().min(1).max(200).optional(),
2732
+ customHeaders: CustomHeadersSchema.optional(),
2733
+ auth: z36.object({
2734
+ accessToken: z36.string().min(1).optional(),
2735
+ expiresAt: z36.string().datetime().optional(),
2736
+ refresh: z36.object({
2737
+ refreshToken: z36.string().min(1).optional()
2738
+ }).strict().optional()
2739
+ }).strict().optional()
2740
+ }).strict();
2741
+ var VaultCredentialRecordSchema = z36.object({
2742
+ type: z36.literal("vault_credential"),
2743
+ /** INV-1.1 public_id, `vcrd_*` prefix. */
2744
+ id: z36.string().regex(/^vcrd_[a-zA-Z0-9]+$/),
2745
+ /** INV-1.1 public_id reference to parent vault. */
2746
+ vaultId: z36.string().regex(/^vlt_[a-zA-Z0-9]+$/),
2747
+ displayName: z36.string().min(1),
2748
+ authType: VaultCredentialAuthTypeSchema,
2749
+ mcpServerUrl: z36.string().url(),
2750
+ expiresAt: z36.string().datetime().nullable(),
2751
+ lastRefreshedAt: z36.string().datetime().nullable(),
2752
+ lastRefreshStatus: VaultCredentialRefreshStatusSchema.nullable(),
2753
+ createdAt: z36.string().datetime(),
2754
+ updatedAt: z36.string().datetime(),
2755
+ archivedAt: z36.string().datetime().nullable()
2756
+ }).strict();
2757
+ var ListCredentialsFilterSchema = z36.object({
2758
+ /** Filter by upstream MCP server URL. */
2759
+ mcpServerUrl: z36.string().url().optional(),
2760
+ includeArchived: z36.boolean().optional()
2761
+ }).strict();
2762
+ var ResolvedCredentialSchema = z36.object({
2763
+ vaultId: z36.string().regex(/^vlt_[a-zA-Z0-9]+$/),
2764
+ credentialId: z36.string().regex(/^vcrd_[a-zA-Z0-9]+$/),
2765
+ authType: VaultCredentialAuthTypeSchema,
2766
+ accessToken: z36.string().min(1),
2767
+ expiresAt: z36.string().datetime().nullable(),
2768
+ customHeaders: CustomHeadersSchema
2769
+ }).strict();
2770
+ var VaultCredentialValidationSchema = z36.object({
2771
+ status: z36.enum(["valid", "invalid", "unknown"]),
2772
+ message: z36.string().optional(),
2773
+ validatedAt: z36.string().datetime()
2774
+ }).strict();
2775
+ var ScheduleTargetKindSchema = z37.enum(["workload", "agent", "inline_v1", "inline_v2"]);
2776
+ var ScheduleApiVersionPreferenceSchema = z37.enum(["v1", "v2"]);
2777
+ var ScheduleLifecycleStatusSchema = z37.enum(["active", "disabled", "deleted"]);
2778
+ var ScheduleConcurrencyPolicySchema = z37.enum(["allow", "forbid"]);
2779
+ var ScheduleMisfirePolicySchema = z37.enum(["skip", "fire_once_immediately"]);
2780
+ var ScheduleTriggerSourceSchema = z37.enum(["cron", "manual"]);
2781
+ var ScheduleTriggerStatusSchema = z37.enum([
2782
+ "pending",
2783
+ "dispatched",
2784
+ "skipped",
2785
+ "failed_to_dispatch"
2786
+ ]);
2787
+ var ScheduleSkippedReasonSchema = z37.enum([
2788
+ "misfire",
2789
+ "concurrency_forbidden",
2790
+ "schedule_disabled",
2791
+ "out_of_window"
2792
+ ]);
2793
+ var ScheduleFailureReasonCodeSchema = z37.enum([
2794
+ "TARGET_NOT_FOUND",
2795
+ "TARGET_DISABLED",
2796
+ "REVISION_NOT_FOUND",
2797
+ "PERMISSION_DENIED",
2798
+ "UPSTREAM_UNAVAILABLE",
2799
+ "DOWNSTREAM_TIMEOUT",
2800
+ "ORPHANED_PENDING_TRIGGER",
2801
+ "UNKNOWN_DISPATCH_FAILURE"
2802
+ ]);
2803
+ var ScheduleApiErrorCodeSchema = z37.enum([
2804
+ "INVALID_CRON",
2805
+ "INVALID_TIMEZONE",
2806
+ "INVALID_TARGET",
2807
+ "UNSUPPORTED_VERSION_COMBO",
2808
+ "PROJECT_NOT_FOUND",
2809
+ "WORKLOAD_NOT_FOUND",
2810
+ "AGENT_NOT_FOUND",
2811
+ "REVISION_NOT_FOUND",
2812
+ "REVISION_NOT_FOR_TARGET_WORKLOAD",
2813
+ "TARGET_NOT_IN_PROJECT",
2814
+ "SCHEDULE_NOT_FOUND",
2815
+ "SCHEDULE_DISABLED",
2816
+ "CONCURRENCY_FORBIDDEN",
2817
+ "SCHEDULE_TRIGGER_CONFLICT",
2818
+ "FORBIDDEN_FIELD",
2819
+ "PERMISSION_DENIED",
2820
+ // P1.2: inline_v2 schedule references a workload slug that cannot be
2821
+ // resolved to any (workloadId, revisionId). Distinct from
2822
+ // WORKLOAD_NOT_FOUND (which is keyed by ID) — slug resolution is
2823
+ // dispatcher-time and surfaces a different remediation path.
2824
+ "WORKLOAD_SLUG_NOT_FOUND",
2825
+ // P1.2: project-or-owner anchor missing — caller submitted neither
2826
+ // projectId nor ownerLdap (or ownerLdap was empty for an inline
2827
+ // kind). 400.
2828
+ "MISSING_PROJECT_OR_OWNER",
2829
+ // Server-side internal error (DB returned no row, dispatcher failed
2830
+ // synchronously, etc.). Surfaces as HTTP 500 / SDK ScheduleClientError
2831
+ // category=platform_error. Distinct from `PERMISSION_DENIED` which
2832
+ // signals "the user is not authorized" — internal errors are not the
2833
+ // caller's fault. Spec §"API Error Codes".
2834
+ "INTERNAL_ERROR"
2835
+ ]);
2836
+ var SCHEDULE_DISPLAY_NAME_MAX_LENGTH = 200;
2837
+ var SCHEDULE_DESCRIPTION_MAX_LENGTH = 1e3;
2838
+ var SCHEDULE_FAILURE_REASON_MESSAGE_MAX_LENGTH = 2e3;
2839
+ var SCHEDULE_MISFIRE_GRACE_SECONDS_MIN = 0;
2840
+ var SCHEDULE_MISFIRE_GRACE_SECONDS_MAX = 3600;
2841
+ var SCHEDULE_MISFIRE_GRACE_SECONDS_DEFAULT = 60;
2842
+ var SCHEDULE_FAILURE_THRESHOLD_MIN = 1;
2843
+ var SCHEDULE_FAILURE_THRESHOLD_MAX = 100;
2844
+ var SCHEDULE_FAILURE_THRESHOLD_DEFAULT = 5;
2845
+ function isValidIanaTimezone(value) {
2846
+ if (!value || value.length > 100) return false;
2847
+ try {
2848
+ new Intl.DateTimeFormat("en-US", { timeZone: value });
2849
+ return true;
2850
+ } catch (e) {
2851
+ return false;
2852
+ }
2853
+ }
2854
+ function isCronStructurallyValid(value) {
2855
+ const trimmed = value.trim();
2856
+ if (!trimmed) return false;
2857
+ const segments = trimmed.split(/\s+/);
2858
+ return segments.length === 5 || segments.length === 6;
2859
+ }
2860
+ var TimezoneStringSchema = z37.string().min(1, "timezone must be a non-empty IANA identifier").refine(isValidIanaTimezone, "timezone must be a valid IANA identifier");
2861
+ var CronExpressionSchema = z37.string().min(1, "cronExpression must be non-empty").max(200, "cronExpression must be at most 200 characters").refine(isCronStructurallyValid, "cronExpression must have 5 or 6 whitespace-separated segments");
2862
+ var IsoDatetimeSchema = z37.string().datetime({ offset: true });
2863
+ var SCHEDULE_PAYLOAD_PROMPT_MAX_LENGTH = 5e4;
2864
+ var SchedulePayloadV1Schema = z37.object({
2865
+ /** Required for v1 — `RunService.createRun` rejects empty prompts. */
2866
+ prompt: z37.string().min(1).max(SCHEDULE_PAYLOAD_PROMPT_MAX_LENGTH),
2867
+ repo: z37.string().max(2048).optional(),
2868
+ ref: z37.string().max(255).optional(),
2869
+ model: z37.string().max(255).optional(),
2870
+ /**
2871
+ * P1.6: tightened from `z.string().max(64).optional()` to
2872
+ * `ProviderTypeSchema.optional()`. Catches invalid provider strings
2873
+ * at schedule create / update time rather than letting the
2874
+ * dispatcher cast them through `RunSpec` and surface as a generic
2875
+ * Zod error on fire (P1.3 review [CONSIDER]).
2876
+ */
2877
+ provider: ProviderTypeSchema.optional(),
2878
+ /**
2879
+ * LDAP of the user whose action created this schedule. Forwarded
2880
+ * verbatim to `runs.triggerUserLdap` so per-user Bedrock credentials
2881
+ * (specs/features/user-bedrock-credentials.md) resolve correctly on
2882
+ * cron-triggered runs. Null / undefined falls back to the
2883
+ * service-level Bedrock key.
2884
+ */
2885
+ triggerUserLdap: z37.string().min(1).max(255).optional()
2886
+ }).strict();
2887
+ var SchedulePayloadV2Schema = z37.object({
2888
+ /**
2889
+ * Sandbox-environment overrides forwarded to
2890
+ * `CreateSessionRequest.configValues`. Reserved-env-key sanitization
2891
+ * is enforced at the SessionStartupService boundary; the schema
2892
+ * here keeps the shape opaque to avoid duplicating that policy.
2893
+ */
2894
+ configValues: z37.record(z37.string(), z37.string()).optional(),
2895
+ /** Free-form audit metadata; non-functional. */
2896
+ metadata: z37.record(z37.string(), z37.unknown()).optional()
2897
+ }).strict();
2898
+ var ScheduleInlineV1PayloadSchema = z37.object({
2899
+ prompt: z37.string().min(1).max(SCHEDULE_PAYLOAD_PROMPT_MAX_LENGTH),
2900
+ repo: z37.string().min(1).max(2048).optional(),
2901
+ ref: z37.string().min(1).max(255).optional(),
2902
+ model: z37.string().max(255).optional(),
2903
+ /**
2904
+ * P1.6: see `SchedulePayloadV1Schema.provider` — same rationale.
2905
+ * Closes the unsafe `as RunSpec["provider"]` cast in
2906
+ * `schedule-dispatcher.ts dispatchInlineV1` (P1.3 review [CONSIDER]).
2907
+ */
2908
+ provider: ProviderTypeSchema.optional(),
2909
+ triggerUserLdap: z37.string().min(1).max(255).optional(),
2910
+ /**
2911
+ * Per-fire MCP / Skills enable lists — same wire shape the home
2912
+ * composer sends to `POST /api/agents` (run-level override, spec
2913
+ * §4.3 "对话级别"). The dispatcher forwards these onto the
2914
+ * synthesised `RunSpec` so each cron-created Run resolves the same
2915
+ * MCPs / skills the user would get by clicking "新建任务" with the
2916
+ * same toggles. Omitted ⇒ no customization (empty resolution).
2917
+ *
2918
+ * Stored verbatim in `payload_json`; refs are resolved against the
2919
+ * owner's global credential store at run start, so a schedule keeps
2920
+ * working as long as the owner keeps the referenced MCP/skill
2921
+ * installed.
2922
+ */
2923
+ enabledMcpServers: EnabledMcpEntryListSchema.optional(),
2924
+ enabledSkills: EnabledSkillEntryListSchema.optional(),
2925
+ /**
2926
+ * User-uploaded attachments — same wire shape the home composer
2927
+ * sends to `POST /api/agents` (`RunSpec.attachments`). Files are
2928
+ * uploaded once at schedule-authoring time to the owner's project
2929
+ * OSS space; the dispatcher forwards the stored `ossUrl` references
2930
+ * onto every synthesised `RunSpec`, so each cron-created Run sees
2931
+ * the same attachments. Capped at 5 to match `RunSpec.attachments`.
2932
+ */
2933
+ attachments: z37.array(AttachmentMetaSchema).max(5).optional()
2934
+ }).strict();
2935
+ var SCHEDULE_INLINE_V2_WORKLOAD_SLUG_REGEX = /^[a-z0-9][a-z0-9-]{0,127}$/;
2936
+ var ScheduleInlineV2PayloadSchema = z37.object({
2937
+ workloadSlug: z37.string().min(1).max(128).refine(
2938
+ (s) => SCHEDULE_INLINE_V2_WORKLOAD_SLUG_REGEX.test(s),
2939
+ "workloadSlug must be lowercase alphanumeric / dashes (1..128 chars)"
2940
+ ),
2941
+ /** Default `"latest"`; UUID strings are treated as revision pin. */
2942
+ revisionSelector: z37.union([z37.literal("latest"), z37.string().uuid()]).default("latest"),
2943
+ configValues: z37.record(z37.string(), z37.string()).optional(),
2944
+ metadata: z37.record(z37.string(), z37.unknown()).optional()
2945
+ }).strict();
2946
+ var RawPayloadSchema = z37.record(z37.string(), z37.unknown());
2947
+ var ADMISSIBLE_TARGET_VERSION_COMBOS = ["workload:v2", "agent:v1", "inline_v1:v1", "inline_v1:v2", "inline_v2:v2"];
2948
+ function refineTargetFields(schema) {
2949
+ return schema.superRefine((value, ctx) => {
2950
+ switch (value.targetKind) {
2951
+ case "workload": {
2952
+ if (!value.targetWorkloadId) {
2953
+ ctx.addIssue({
2954
+ code: z37.ZodIssueCode.custom,
2955
+ message: "targetWorkloadId is required when targetKind is 'workload'",
2956
+ path: ["targetWorkloadId"]
2957
+ });
2958
+ }
2959
+ if (value.targetAgentId) {
2960
+ ctx.addIssue({
2961
+ code: z37.ZodIssueCode.custom,
2962
+ message: "targetAgentId must be omitted when targetKind is 'workload'",
2963
+ path: ["targetAgentId"]
2964
+ });
2965
+ }
2966
+ break;
2967
+ }
2968
+ case "agent": {
2969
+ if (!value.targetAgentId) {
2970
+ ctx.addIssue({
2971
+ code: z37.ZodIssueCode.custom,
2972
+ message: "targetAgentId is required when targetKind is 'agent'",
2973
+ path: ["targetAgentId"]
2974
+ });
2975
+ }
2976
+ if (value.targetWorkloadId) {
2977
+ ctx.addIssue({
2978
+ code: z37.ZodIssueCode.custom,
2979
+ message: "targetWorkloadId must be omitted when targetKind is 'agent'",
2980
+ path: ["targetWorkloadId"]
2981
+ });
2982
+ }
2983
+ if (value.targetRevisionId) {
2984
+ ctx.addIssue({
2985
+ code: z37.ZodIssueCode.custom,
2986
+ message: "targetRevisionId is only allowed when targetKind is 'workload'",
2987
+ path: ["targetRevisionId"]
2988
+ });
2989
+ }
2990
+ break;
2991
+ }
2992
+ case "inline_v1":
2993
+ case "inline_v2": {
2994
+ if (value.targetWorkloadId) {
2995
+ ctx.addIssue({
2996
+ code: z37.ZodIssueCode.custom,
2997
+ message: `targetWorkloadId must be omitted when targetKind is '${value.targetKind}'`,
2998
+ path: ["targetWorkloadId"]
2999
+ });
3000
+ }
3001
+ if (value.targetAgentId) {
3002
+ ctx.addIssue({
3003
+ code: z37.ZodIssueCode.custom,
3004
+ message: `targetAgentId must be omitted when targetKind is '${value.targetKind}'`,
3005
+ path: ["targetAgentId"]
3006
+ });
3007
+ }
3008
+ if (value.targetRevisionId) {
3009
+ ctx.addIssue({
3010
+ code: z37.ZodIssueCode.custom,
3011
+ message: `targetRevisionId must be omitted when targetKind is '${value.targetKind}' (use payload.revisionSelector for inline_v2)`,
3012
+ path: ["targetRevisionId"]
3013
+ });
3014
+ }
3015
+ break;
3016
+ }
3017
+ }
3018
+ const combo = `${value.targetKind}:${value.pilotApiVersionPreference}`;
3019
+ if (!ADMISSIBLE_TARGET_VERSION_COMBOS.includes(combo)) {
3020
+ ctx.addIssue({
3021
+ code: z37.ZodIssueCode.custom,
3022
+ message: `Unsupported (targetKind, pilotApiVersionPreference) combination. Admissible: ${ADMISSIBLE_TARGET_VERSION_COMBOS.join(
3023
+ ", "
3024
+ )}`,
3025
+ path: ["pilotApiVersionPreference"]
3026
+ });
3027
+ }
3028
+ const isInline = value.targetKind === "inline_v1" || value.targetKind === "inline_v2";
3029
+ if (!isInline && !value.projectId) {
3030
+ ctx.addIssue({
3031
+ code: z37.ZodIssueCode.custom,
3032
+ message: `projectId is required when targetKind is '${value.targetKind}'`,
3033
+ path: ["projectId"]
3034
+ });
3035
+ }
3036
+ const hasProject = Boolean(value.projectId);
3037
+ const hasOwner = Boolean(value.ownerLdap && value.ownerLdap.length > 0);
3038
+ if (!hasProject && !hasOwner) {
3039
+ ctx.addIssue({
3040
+ code: z37.ZodIssueCode.custom,
3041
+ message: "At least one of projectId / ownerLdap must be present (project-or-owner anchor)",
3042
+ path: ["ownerLdap"]
3043
+ });
3044
+ }
3045
+ });
3046
+ }
3047
+ function refineLifecycleWindow(schema) {
3048
+ return schema.superRefine((value, ctx) => {
3049
+ if (value.startAt && value.endAt) {
3050
+ const start = Date.parse(value.startAt);
3051
+ const end = Date.parse(value.endAt);
3052
+ if (Number.isFinite(start) && Number.isFinite(end) && end <= start) {
3053
+ ctx.addIssue({
3054
+ code: z37.ZodIssueCode.custom,
3055
+ message: "endAt must be strictly later than startAt",
3056
+ path: ["endAt"]
3057
+ });
3058
+ }
3059
+ }
3060
+ });
3061
+ }
3062
+ var CreateScheduleRequestBaseSchema = z37.object({
3063
+ /**
3064
+ * Host project. Required for `targetKind ∈ {workload, agent}` (P0
3065
+ * shape); MAY be null for `inline_v1` / `inline_v2`. When null, the
3066
+ * `ownerLdap` field becomes the sole authorization anchor.
3067
+ */
3068
+ projectId: z37.string().uuid().nullable().optional(),
3069
+ /**
3070
+ * LDAP of the schedule owner (P1.2). Distinct from the implicit
3071
+ * `createdBy` which is captured server-side from the auth context.
3072
+ * MUST be non-empty when `projectId` is null. The route handler is
3073
+ * authoritative for enforcing "createdBy === ownerLdap" on create
3074
+ * (delegation / ownership transfer is an explicit follow-up).
3075
+ */
3076
+ ownerLdap: z37.string().min(1).max(255).optional(),
3077
+ displayName: z37.string().min(1, "displayName must be non-empty").max(SCHEDULE_DISPLAY_NAME_MAX_LENGTH),
3078
+ description: z37.string().max(SCHEDULE_DESCRIPTION_MAX_LENGTH).optional(),
3079
+ cronExpression: CronExpressionSchema,
3080
+ timezone: TimezoneStringSchema,
3081
+ targetKind: ScheduleTargetKindSchema,
3082
+ targetWorkloadId: z37.string().uuid().optional(),
3083
+ targetRevisionId: z37.string().uuid().optional(),
3084
+ targetAgentId: z37.string().uuid().optional(),
3085
+ pilotApiVersionPreference: ScheduleApiVersionPreferenceSchema,
3086
+ concurrencyPolicy: ScheduleConcurrencyPolicySchema.default("allow"),
3087
+ misfirePolicy: ScheduleMisfirePolicySchema.default("skip"),
3088
+ misfireGraceSeconds: z37.number().int().min(SCHEDULE_MISFIRE_GRACE_SECONDS_MIN).max(SCHEDULE_MISFIRE_GRACE_SECONDS_MAX).default(SCHEDULE_MISFIRE_GRACE_SECONDS_DEFAULT),
3089
+ consecutiveFailureThreshold: z37.number().int().min(SCHEDULE_FAILURE_THRESHOLD_MIN).max(SCHEDULE_FAILURE_THRESHOLD_MAX).default(SCHEDULE_FAILURE_THRESHOLD_DEFAULT),
3090
+ startAt: IsoDatetimeSchema.optional(),
3091
+ endAt: IsoDatetimeSchema.optional(),
3092
+ /**
3093
+ * Dispatch parameter payload. Shape is determined by
3094
+ * `pilotApiVersionPreference` and validated by `refinePayload` (see
3095
+ * below). Stored verbatim into `schedule_definitions.payload_json`.
3096
+ */
3097
+ payload: RawPayloadSchema
3098
+ }).strict();
3099
+ function refinePayload(schema) {
3100
+ return schema.superRefine((value, ctx) => {
3101
+ let payloadSchema;
3102
+ switch (value.targetKind) {
3103
+ case "workload":
3104
+ payloadSchema = SchedulePayloadV2Schema;
3105
+ break;
3106
+ case "agent":
3107
+ payloadSchema = SchedulePayloadV1Schema;
3108
+ break;
3109
+ case "inline_v1":
3110
+ payloadSchema = ScheduleInlineV1PayloadSchema;
3111
+ break;
3112
+ case "inline_v2":
3113
+ payloadSchema = ScheduleInlineV2PayloadSchema;
3114
+ break;
3115
+ }
3116
+ const result = payloadSchema.safeParse(value.payload);
3117
+ if (!result.success) {
3118
+ for (const issue of result.error.issues) {
3119
+ ctx.addIssue({
3120
+ code: z37.ZodIssueCode.custom,
3121
+ message: issue.message,
3122
+ path: ["payload", ...issue.path]
3123
+ });
3124
+ }
3125
+ }
3126
+ });
3127
+ }
3128
+ var CreateScheduleRequestSchema = refinePayload(
3129
+ refineLifecycleWindow(refineTargetFields(CreateScheduleRequestBaseSchema))
3130
+ );
3131
+ var UpdateScheduleRequestBaseSchema = z37.object({
3132
+ displayName: z37.string().min(1).max(SCHEDULE_DISPLAY_NAME_MAX_LENGTH).optional(),
3133
+ description: z37.string().max(SCHEDULE_DESCRIPTION_MAX_LENGTH).nullable().optional(),
3134
+ /**
3135
+ * Convenience field — `true` ⇒ lifecycle_status='active',
3136
+ * `false` ⇒ lifecycle_status='disabled'. Cannot reach `deleted`
3137
+ * via PATCH (use DELETE).
3138
+ */
3139
+ enabled: z37.boolean().optional(),
3140
+ cronExpression: CronExpressionSchema.optional(),
3141
+ timezone: TimezoneStringSchema.optional(),
3142
+ concurrencyPolicy: ScheduleConcurrencyPolicySchema.optional(),
3143
+ misfirePolicy: ScheduleMisfirePolicySchema.optional(),
3144
+ misfireGraceSeconds: z37.number().int().min(SCHEDULE_MISFIRE_GRACE_SECONDS_MIN).max(SCHEDULE_MISFIRE_GRACE_SECONDS_MAX).optional(),
3145
+ consecutiveFailureThreshold: z37.number().int().min(SCHEDULE_FAILURE_THRESHOLD_MIN).max(SCHEDULE_FAILURE_THRESHOLD_MAX).optional(),
3146
+ endAt: IsoDatetimeSchema.nullable().optional(),
3147
+ /**
3148
+ * Replaces the entire dispatch payload. Null is forbidden — to
3149
+ * "clear" optional sub-fields, send a payload object that omits
3150
+ * them. Payload shape (v1 vs v2) is fixed at create time per
3151
+ * INV-5; the route handler validates against the schedule's
3152
+ * stored `pilotApiVersionPreference` before persisting.
3153
+ */
3154
+ payload: RawPayloadSchema.optional()
3155
+ }).strict();
3156
+ var UpdateScheduleRequestSchema = UpdateScheduleRequestBaseSchema.refine(
3157
+ (data) => Object.keys(data).length > 0,
3158
+ { message: "PATCH body must contain at least one field" }
3159
+ );
3160
+ var ScheduleViewBaseSchema = z37.object({
3161
+ id: z37.string().uuid(),
3162
+ /**
3163
+ * Nullable since P1.2 — only inline kinds may have null projectId in
3164
+ * persisted form; workload / agent kinds keep it set (enforced at
3165
+ * create time and by DB shape CHECK).
3166
+ */
3167
+ projectId: z37.string().uuid().nullable(),
3168
+ /**
3169
+ * Owner LDAP (P1.2). NOT NULL in DB; the read shape exposes it for
3170
+ * UI to render "owned by" labels and for permission checks on
3171
+ * project-less schedules.
3172
+ */
3173
+ ownerLdap: z37.string(),
3174
+ displayName: z37.string(),
3175
+ description: z37.string().nullable(),
3176
+ cronExpression: z37.string(),
3177
+ timezone: z37.string(),
3178
+ targetKind: ScheduleTargetKindSchema,
3179
+ targetWorkloadId: z37.string().uuid().nullable(),
3180
+ targetRevisionId: z37.string().uuid().nullable(),
3181
+ targetAgentId: z37.string().uuid().nullable(),
3182
+ pilotApiVersionPreference: ScheduleApiVersionPreferenceSchema,
3183
+ lifecycleStatus: ScheduleLifecycleStatusSchema,
3184
+ concurrencyPolicy: ScheduleConcurrencyPolicySchema,
3185
+ misfirePolicy: ScheduleMisfirePolicySchema,
3186
+ misfireGraceSeconds: z37.number().int().nonnegative(),
3187
+ startAt: IsoDatetimeSchema.nullable(),
3188
+ endAt: IsoDatetimeSchema.nullable(),
3189
+ payload: RawPayloadSchema,
3190
+ consecutiveFailureCount: z37.number().int().nonnegative(),
3191
+ consecutiveFailureThreshold: z37.number().int().positive(),
3192
+ lastTriggerAt: IsoDatetimeSchema.nullable(),
3193
+ nextFireAt: IsoDatetimeSchema.nullable(),
3194
+ createdBy: z37.string(),
3195
+ createdAt: IsoDatetimeSchema,
3196
+ updatedAt: IsoDatetimeSchema,
3197
+ deletedAt: IsoDatetimeSchema.nullable()
3198
+ });
3199
+ var ScheduleViewSchema = refineTargetFields(
3200
+ ScheduleViewBaseSchema
3201
+ );
3202
+ var ScheduleListItemSchema = ScheduleViewBaseSchema.pick({
3203
+ id: true,
3204
+ projectId: true,
3205
+ ownerLdap: true,
3206
+ displayName: true,
3207
+ cronExpression: true,
3208
+ timezone: true,
3209
+ targetKind: true,
3210
+ targetWorkloadId: true,
3211
+ targetAgentId: true,
3212
+ pilotApiVersionPreference: true,
3213
+ lifecycleStatus: true,
3214
+ lastTriggerAt: true,
3215
+ nextFireAt: true,
3216
+ createdAt: true,
3217
+ updatedAt: true
3218
+ });
3219
+ var ScheduleListResponseSchema = z37.object({
3220
+ items: z37.array(ScheduleListItemSchema),
3221
+ nextCursor: z37.string().optional()
3222
+ });
3223
+ var ScheduleTriggerViewSchema = z37.object({
3224
+ id: z37.string().uuid(),
3225
+ scheduleId: z37.string().uuid(),
3226
+ firedAt: IsoDatetimeSchema,
3227
+ triggerSource: ScheduleTriggerSourceSchema,
3228
+ status: ScheduleTriggerStatusSchema,
3229
+ dispatchedAt: IsoDatetimeSchema.nullable(),
3230
+ dispatchedRunId: z37.string().uuid().nullable(),
3231
+ dispatchedSessionId: z37.string().uuid().nullable(),
3232
+ /**
3233
+ * Owning agent of the dispatched Run / Session, when one exists.
3234
+ * Resolved by joining `runs.agent_id` on the dispatched run/session id
3235
+ * (cohort invariant: `run.id === session.id`). Lets the UI deep-link
3236
+ * the trigger to `/agents/:agentId`. Null for pure-workload v2
3237
+ * dispatches (no agent) and for non-dispatched triggers.
3238
+ */
3239
+ dispatchedAgentId: z37.string().uuid().nullable(),
3240
+ skippedReason: ScheduleSkippedReasonSchema.nullable(),
3241
+ failureReasonCode: ScheduleFailureReasonCodeSchema.nullable(),
3242
+ failureReasonMessage: z37.string().max(SCHEDULE_FAILURE_REASON_MESSAGE_MAX_LENGTH).nullable(),
3243
+ idempotencyKey: z37.string(),
3244
+ attemptCount: z37.number().int().nonnegative(),
3245
+ blockingTriggerId: z37.string().uuid().nullable(),
3246
+ createdAt: IsoDatetimeSchema
3247
+ }).superRefine((trigger, ctx) => {
3248
+ if (trigger.status === "dispatched") {
3249
+ if (!trigger.dispatchedAt) {
3250
+ ctx.addIssue({
3251
+ code: z37.ZodIssueCode.custom,
3252
+ message: "dispatchedAt is required when status is 'dispatched'",
3253
+ path: ["dispatchedAt"]
3254
+ });
3255
+ }
3256
+ const hasRun = trigger.dispatchedRunId !== null;
3257
+ const hasSession = trigger.dispatchedSessionId !== null;
3258
+ if (hasRun === hasSession) {
3259
+ ctx.addIssue({
3260
+ code: z37.ZodIssueCode.custom,
3261
+ message: "Exactly one of dispatchedRunId / dispatchedSessionId must be set when status is 'dispatched'",
3262
+ path: ["dispatchedRunId"]
3263
+ });
3264
+ }
3265
+ } else {
3266
+ if (trigger.dispatchedAt !== null) {
3267
+ ctx.addIssue({
3268
+ code: z37.ZodIssueCode.custom,
3269
+ message: "dispatchedAt must be null when status is not 'dispatched'",
3270
+ path: ["dispatchedAt"]
3271
+ });
3272
+ }
3273
+ }
3274
+ if (trigger.status === "skipped" && trigger.skippedReason === null) {
3275
+ ctx.addIssue({
3276
+ code: z37.ZodIssueCode.custom,
3277
+ message: "skippedReason is required when status is 'skipped'",
3278
+ path: ["skippedReason"]
3279
+ });
3280
+ }
3281
+ if (trigger.status !== "skipped" && trigger.skippedReason !== null) {
3282
+ ctx.addIssue({
3283
+ code: z37.ZodIssueCode.custom,
3284
+ message: "skippedReason must be null when status is not 'skipped'",
3285
+ path: ["skippedReason"]
3286
+ });
3287
+ }
3288
+ if (trigger.status === "failed_to_dispatch" && trigger.failureReasonCode === null) {
3289
+ ctx.addIssue({
3290
+ code: z37.ZodIssueCode.custom,
3291
+ message: "failureReasonCode is required when status is 'failed_to_dispatch'",
3292
+ path: ["failureReasonCode"]
3293
+ });
3294
+ }
3295
+ if (trigger.status !== "failed_to_dispatch" && trigger.failureReasonCode !== null) {
3296
+ ctx.addIssue({
3297
+ code: z37.ZodIssueCode.custom,
3298
+ message: "failureReasonCode must be null when status is not 'failed_to_dispatch'",
3299
+ path: ["failureReasonCode"]
3300
+ });
3301
+ }
3302
+ if (trigger.blockingTriggerId !== null && !(trigger.status === "skipped" && trigger.skippedReason === "concurrency_forbidden")) {
3303
+ ctx.addIssue({
3304
+ code: z37.ZodIssueCode.custom,
3305
+ message: "blockingTriggerId is only meaningful for skipped+concurrency_forbidden rows",
3306
+ path: ["blockingTriggerId"]
3307
+ });
3308
+ }
3309
+ });
3310
+ var ScheduleTriggerListResponseSchema = z37.object({
3311
+ items: z37.array(ScheduleTriggerViewSchema),
3312
+ nextCursor: z37.string().optional()
3313
+ });
3314
+ var RunScheduleResponseSchema = z37.object({
3315
+ triggerId: z37.string().uuid(),
3316
+ dispatchedRunId: z37.string().uuid().optional(),
3317
+ dispatchedSessionId: z37.string().uuid().optional()
3318
+ }).superRefine((value, ctx) => {
3319
+ const hasRun = value.dispatchedRunId !== void 0;
3320
+ const hasSession = value.dispatchedSessionId !== void 0;
3321
+ if (hasRun === hasSession) {
3322
+ ctx.addIssue({
3323
+ code: z37.ZodIssueCode.custom,
3324
+ message: "Exactly one of dispatchedRunId / dispatchedSessionId must be present in run-now response"
3325
+ });
3326
+ }
3327
+ });
3328
+ var ScheduleApiErrorBodySchema = z37.object({
3329
+ error: z37.object({
3330
+ code: ScheduleApiErrorCodeSchema,
3331
+ message: z37.string(),
3332
+ details: z37.record(z37.unknown()).optional()
3333
+ })
3334
+ });
3335
+ var RevisionWorkerContractRefSchema = WorkerContractRefSchema.pick({
3336
+ kind: true,
3337
+ name: true,
3338
+ version: true
3339
+ }).strict();
3340
+ var PILOT_WORKLOAD_MANIFEST_API_VERSION = "pilot.zhenguanyu.com/v0alpha1";
3341
+ var PILOT_WORKLOAD_MANIFEST_LEGACY_API_VERSION = "pilot.kanyun.ai/v0alpha1";
3342
+ var PILOT_WORKLOAD_MANIFEST_API_VERSIONS = [
3343
+ PILOT_WORKLOAD_MANIFEST_API_VERSION,
3344
+ PILOT_WORKLOAD_MANIFEST_LEGACY_API_VERSION
3345
+ ];
3346
+ var PilotWorkloadManifestApiVersionSchema = z38.enum(PILOT_WORKLOAD_MANIFEST_API_VERSIONS);
3347
+ var WORKLOAD_MANIFEST_NAME_MAX_LENGTH = 100;
3348
+ var WORKLOAD_MANIFEST_DISPLAY_NAME_MAX_LENGTH = 255;
3349
+ var WORKLOAD_MANIFEST_REF_NAME_MAX_LENGTH = 255;
3350
+ var WorkloadManifestErrorCodeSchema = z38.enum([
3351
+ "MANIFEST_UNSUPPORTED_API_VERSION",
3352
+ "MANIFEST_UNSUPPORTED_KIND",
3353
+ "MANIFEST_VALIDATION_ERROR",
3354
+ "WORKLOAD_KIND_UNSUPPORTED",
3355
+ "WORKLOAD_NOT_FOUND",
3356
+ "WORKLOAD_KIND_MISMATCH",
3357
+ "PROJECT_DEFAULT_RUNTIME_MISSING",
3358
+ "RUNTIME_TEMPLATE_NOT_FOUND",
3359
+ "REVISION_REGISTRATION_CONFLICT",
3360
+ // Cross-project safety: thrown when `applyRevisionManifest` resolves a
3361
+ // workload and a runtime template that live in different projects.
3362
+ // Mirrors the `revisions_project_consistency` DB trigger; the
3363
+ // application-layer check exits early with a friendlier error code
3364
+ // before the trigger fires raw `check_violation` SQLSTATE 23514.
3365
+ // Plan: plans/admin-ui-project-namespacing.md §C2.
3366
+ "REVISION_CROSS_PROJECT",
3367
+ "IMAGE_PROVENANCE_REQUIRED",
3368
+ "IMAGE_PROVENANCE_INVALID",
3369
+ "LEGACY_PROVENANCE_NOT_ALLOWED"
3370
+ ]);
3371
+ var ActiveWorkloadKindSchema = z38.enum(["managed_agent", "self_managed"]);
3372
+ var DeferredWorkloadKindSchema = z38.enum(["external_worker", "batch_task"]);
3373
+ var DNS_LABEL_STYLE_PATTERN = /^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/;
3374
+ var WorkloadManifestNameSchema = z38.string().min(1).max(WORKLOAD_MANIFEST_NAME_MAX_LENGTH).regex(DNS_LABEL_STYLE_PATTERN, "Name must be DNS-label-style");
3375
+ var WorkloadManifestDisplayNameSchema = z38.string().min(1).max(WORKLOAD_MANIFEST_DISPLAY_NAME_MAX_LENGTH);
3376
+ var WorkloadManifestRefNameSchema = z38.string().min(1).max(WORKLOAD_MANIFEST_REF_NAME_MAX_LENGTH);
3377
+ var WorkloadManifestObjectRefSchema = z38.object({
3378
+ name: WorkloadManifestRefNameSchema
3379
+ }).strict();
3380
+ var WorkloadManifestMetadataBaseSchema = z38.object({
3381
+ name: WorkloadManifestNameSchema,
3382
+ labels: z38.record(z38.string()).optional(),
3383
+ annotations: z38.record(z38.string()).optional()
3384
+ }).strict();
3385
+ var WorkloadManifestMetadataSchema = WorkloadManifestMetadataBaseSchema.extend({
3386
+ displayName: WorkloadManifestDisplayNameSchema
3387
+ }).strict();
3388
+ var RevisionManifestMetadataSchema = WorkloadManifestMetadataBaseSchema.extend({
3389
+ workload: WorkloadManifestNameSchema
3390
+ }).strict();
3391
+ var WorkloadManifestCapabilityRefsSchema = z38.object({
3392
+ modelRef: WorkloadManifestObjectRefSchema.optional(),
3393
+ toolRefs: z38.array(WorkloadManifestObjectRefSchema).optional(),
3394
+ mcpRefs: z38.array(WorkloadManifestObjectRefSchema).optional()
3395
+ }).strict();
3396
+ var WorkloadManifestPolicyRefsSchema = z38.object({
3397
+ credentialPolicyRef: WorkloadManifestObjectRefSchema.optional(),
3398
+ readinessPolicyRef: WorkloadManifestObjectRefSchema.optional(),
3399
+ actionPolicyRef: WorkloadManifestObjectRefSchema.optional(),
3400
+ trafficPolicyRef: WorkloadManifestObjectRefSchema.optional()
3401
+ }).strict();
3402
+ var WorkloadManifestWorkerContractDefaultsSchema = z38.object({
3403
+ name: WorkloadManifestRefNameSchema.optional(),
3404
+ version: z38.string().min(1).max(WORKLOAD_MANIFEST_NAME_MAX_LENGTH).optional()
3405
+ }).strict();
3406
+ var WORKLOAD_MANIFEST_MODEL_MAX_LENGTH = 255;
3407
+ var WorkloadManifestModelSchema = z38.string().min(1).max(WORKLOAD_MANIFEST_MODEL_MAX_LENGTH);
3408
+ var WORKLOAD_MANIFEST_SYSTEM_PROMPT_MAX_LENGTH = 32768;
3409
+ var WorkloadManifestSystemPromptSchema = z38.string().min(1).max(WORKLOAD_MANIFEST_SYSTEM_PROMPT_MAX_LENGTH);
3410
+ var ManagedAgentProfileSnapshotSchema = z38.object({
3411
+ model: WorkloadManifestModelSchema.optional(),
3412
+ systemPrompt: WorkloadManifestSystemPromptSchema.optional(),
3413
+ enabledSkills: EnabledSkillEntryListSchema.optional(),
3414
+ enabledMcpServers: EnabledMcpEntryListSchema.optional(),
3415
+ configValues: SessionConfigValuesSchema.optional()
3416
+ }).strict();
3417
+ var ManagedAgentOverridesSchema = z38.object({
3418
+ model: WorkloadManifestModelSchema.nullable().optional(),
3419
+ systemPrompt: WorkloadManifestSystemPromptSchema.nullable().optional(),
3420
+ enabledSkills: EnabledSkillEntryListSchema.optional(),
3421
+ enabledMcpServers: EnabledMcpEntryListSchema.optional()
3422
+ }).strict();
3423
+ var WorkloadManifestDefaultsSchema = z38.object({
3424
+ runtimeTemplateRef: WorkloadManifestObjectRefSchema.optional(),
3425
+ workerContract: WorkloadManifestWorkerContractDefaultsSchema.optional(),
3426
+ capabilityRefs: WorkloadManifestCapabilityRefsSchema.optional(),
3427
+ configValues: SessionConfigValuesSchema.optional(),
3428
+ model: WorkloadManifestModelSchema.optional(),
3429
+ /**
3430
+ * Workload-level **default system prompt** (managed_agent profile
3431
+ * Phase D). Seeded onto `agents.system_prompt` at agent creation and
3432
+ * forwarded per-run as `PilotCoderRunConfigV1.systemPrompt`. See
3433
+ * `specs/features/pilot-v2-managed-agent-profile.md` §"Phase D".
3434
+ */
3435
+ systemPrompt: WorkloadManifestSystemPromptSchema.optional(),
3436
+ /**
3437
+ * Workload-level **default enabled skills** (managed_agent profile
3438
+ * Phase C). Persisted into `workloads.manifest_defaults_json` and
3439
+ * seeded into `agents.enabled_skills` at agent creation when the
3440
+ * caller does not supply explicit skills. Accepts the snapshot-or-ref
3441
+ * union (same write contract as `projects.enabled_skills`); the
3442
+ * `POST /api/workloads` route resolves any refs into full
3443
+ * `EnabledSkill` snapshots via the rush registry before persisting so
3444
+ * the workload default is self-contained (no per-user install
3445
+ * dependency). See `specs/features/pilot-v2-managed-agent-profile.md`
3446
+ * §"Phase C".
3447
+ */
3448
+ enabledSkills: EnabledSkillEntryListSchema.optional(),
3449
+ /**
3450
+ * Workload-level **default enabled MCP servers** (managed_agent
3451
+ * profile Phase C2). Persisted into `workloads.manifest_defaults_json`
3452
+ * and seeded into `agents.enabled_mcp_servers` at agent creation when
3453
+ * the caller does not supply explicit MCP servers. Accepts the
3454
+ * snapshot-or-ref union (same write contract as
3455
+ * `projects.enabled_mcp_servers`); the `POST /api/workloads` route
3456
+ * resolves any refs into full `EnabledMcpServer` snapshots via the
3457
+ * rush registry before persisting so the workload default is
3458
+ * self-contained.
3459
+ *
3460
+ * Resolution at `POST /api/workloads` produces a mix:
3461
+ * - **credential-free** MCP (rush `requiredVars` empty, Phase C2) →
3462
+ * frozen `EnabledMcpServer` snapshot (self-contained, cross-user
3463
+ * identical).
3464
+ * - **credentialed** MCP (rush `requiredVars` non-empty, Phase C3) →
3465
+ * bare `EnabledMcpRef { rushMcpId }`; the credential is NOT frozen
3466
+ * here, it resolves per running user from `user_mcp_installs` at
3467
+ * bootstrap (ref-resolver), with per-MCP failure isolation when an
3468
+ * install is missing (`mcp-and-skills.md` §4.2).
3469
+ *
3470
+ * Inline plaintext credentials (`extraConfigValues` /
3471
+ * `extraConfigValuesOverride`) are rejected at resolution — a
3472
+ * cross-user workload default never stores one user's secret. See
3473
+ * `specs/features/pilot-v2-managed-agent-profile.md` §"Phase C".
3474
+ */
3475
+ enabledMcpServers: EnabledMcpEntryListSchema.optional()
3476
+ }).strict();
3477
+ var WORKLOAD_MANIFEST_UI_DISPLAY_NAME_MAX_LENGTH = 255;
3478
+ var WORKLOAD_MANIFEST_UI_PROMPT_PLACEHOLDER_MAX_LENGTH = 500;
3479
+ var WorkloadManifestUiHintSchema = z38.object({
3480
+ displayName: z38.string().min(1).max(WORKLOAD_MANIFEST_UI_DISPLAY_NAME_MAX_LENGTH).optional(),
3481
+ promptPlaceholder: z38.string().min(1).max(WORKLOAD_MANIFEST_UI_PROMPT_PLACEHOLDER_MAX_LENGTH).optional(),
3482
+ enableAttachments: z38.boolean().optional(),
3483
+ artifactsView: z38.enum(["none", "panel"]).optional()
3484
+ }).strict();
3485
+ var WorkloadManifestSchema = z38.object({
3486
+ apiVersion: PilotWorkloadManifestApiVersionSchema,
3487
+ kind: z38.literal("Workload"),
3488
+ metadata: WorkloadManifestMetadataSchema,
3489
+ spec: z38.object({
3490
+ contract: z38.object({
3491
+ kind: WorkloadKindSchema
3492
+ }).strict(),
3493
+ defaults: WorkloadManifestDefaultsSchema.optional(),
3494
+ policyRefs: WorkloadManifestPolicyRefsSchema.optional(),
3495
+ ui: WorkloadManifestUiHintSchema.optional()
3496
+ }).strict()
3497
+ }).strict();
3498
+ var RevisionManifestStartupSchema = z38.object({
3499
+ requiredGates: z38.array(z38.string().min(1)).optional(),
3500
+ optionalGates: z38.array(z38.string().min(1)).optional()
3501
+ }).strict();
3502
+ var RevisionManifestPublishSchema = z38.object({
3503
+ setDefault: z38.boolean().default(true)
3504
+ }).strict();
3505
+ var RevisionRuntimeEnvironmentInputSchema = RuntimeTemplateSnapshotSchema.omit({
3506
+ defaultWorkerEndpoint: true
3507
+ }).strict();
3508
+ var RevisionRuntimeEnvironmentOverridesSchema = RevisionRuntimeEnvironmentInputSchema.partial().strict();
3509
+ var RevisionRuntimeSchema = z38.object({
3510
+ /**
3511
+ * Complete publish-time Runtime Environment input. Control-plane resolves
3512
+ * and freezes this into `revisions.runtime_template_snapshot_json`; DB
3513
+ * compatibility still records a runtime source/profile id separately.
3514
+ */
3515
+ environment: RevisionRuntimeEnvironmentInputSchema.optional(),
3516
+ /**
3517
+ * Runtime source/profile reference. During the RuntimeTemplate
3518
+ * compatibility window this maps to `runtime_templates.name`.
3519
+ */
3520
+ profileRef: WorkloadManifestObjectRefSchema.optional(),
3521
+ /**
3522
+ * Publish-time overrides applied to `profileRef`'s resolved environment.
3523
+ */
3524
+ overrides: RevisionRuntimeEnvironmentOverridesSchema.optional()
3525
+ }).strict().superRefine((runtime, ctx) => {
3526
+ if (!runtime.environment && !runtime.profileRef) {
3527
+ ctx.addIssue({
3528
+ code: z38.ZodIssueCode.custom,
3529
+ path: ["environment"],
3530
+ message: "runtime must provide environment or profileRef"
3531
+ });
3532
+ }
3533
+ if (runtime.environment && runtime.overrides) {
3534
+ ctx.addIssue({
3535
+ code: z38.ZodIssueCode.custom,
3536
+ path: ["overrides"],
3537
+ message: "runtime.overrides is only allowed with runtime.profileRef"
3538
+ });
3539
+ }
3540
+ if (runtime.overrides && !runtime.profileRef) {
3541
+ ctx.addIssue({
3542
+ code: z38.ZodIssueCode.custom,
3543
+ path: ["profileRef"],
3544
+ message: "runtime.profileRef is required when runtime.overrides is provided"
3545
+ });
3546
+ }
3547
+ });
3548
+ var RevisionManifestSpecSchema = z38.object({
3549
+ runtimeTemplateRef: WorkloadManifestObjectRefSchema.optional(),
3550
+ runtime: RevisionRuntimeSchema.optional(),
3551
+ workerContract: RevisionWorkerContractRefSchema,
3552
+ capabilityRefs: WorkloadManifestCapabilityRefsSchema.optional(),
3553
+ startup: RevisionManifestStartupSchema.optional(),
3554
+ publish: RevisionManifestPublishSchema.default({ setDefault: true }),
3555
+ configValues: SessionConfigValuesSchema.optional(),
3556
+ policyRefs: WorkloadManifestPolicyRefsSchema.optional(),
3557
+ managedAgentProfileSnapshot: ManagedAgentProfileSnapshotSchema.optional()
3558
+ }).strict().superRefine((spec, ctx) => {
3559
+ var _a, _b, _c;
3560
+ const profileRefName = (_b = (_a = spec.runtime) == null ? void 0 : _a.profileRef) == null ? void 0 : _b.name;
3561
+ const legacyRuntimeTemplateRefName = (_c = spec.runtimeTemplateRef) == null ? void 0 : _c.name;
3562
+ if (profileRefName && legacyRuntimeTemplateRefName && profileRefName !== legacyRuntimeTemplateRefName) {
3563
+ ctx.addIssue({
3564
+ code: z38.ZodIssueCode.custom,
3565
+ path: ["runtimeTemplateRef"],
3566
+ message: "runtimeTemplateRef must match runtime.profileRef when both compatibility refs are provided"
3567
+ });
3568
+ }
3569
+ if (spec.managedAgentProfileSnapshot !== void 0 && spec.workerContract.kind !== "managed_agent") {
3570
+ ctx.addIssue({
3571
+ code: z38.ZodIssueCode.custom,
3572
+ path: ["managedAgentProfileSnapshot"],
3573
+ message: "managedAgentProfileSnapshot is only allowed for managed_agent revisions"
3574
+ });
3575
+ }
3576
+ });
3577
+ var RevisionManifestSchema = z38.object({
3578
+ apiVersion: PilotWorkloadManifestApiVersionSchema,
3579
+ kind: z38.literal("Revision"),
3580
+ metadata: RevisionManifestMetadataSchema,
3581
+ spec: RevisionManifestSpecSchema
3582
+ }).strict();
3583
+ var PilotWorkloadManifestSchema = z38.discriminatedUnion("kind", [
3584
+ WorkloadManifestSchema,
3585
+ RevisionManifestSchema
3586
+ ]);
3587
+ var MANAGED_AGENT_PROFILE_KIND = "ManagedAgentProfile";
3588
+ var ManagedAgentProfileMetadataSchema = z39.object({
3589
+ name: WorkloadManifestNameSchema,
3590
+ displayName: WorkloadManifestDisplayNameSchema,
3591
+ labels: z39.record(z39.string()).optional(),
3592
+ annotations: z39.record(z39.string()).optional()
3593
+ }).strict();
3594
+ var ManagedAgentProfileSpecSchema = z39.object({
3595
+ runtimeTemplateRef: WorkloadManifestObjectRefSchema,
3596
+ env: SessionConfigValuesSchema.optional(),
3597
+ ui: WorkloadManifestUiHintSchema.optional(),
3598
+ // Phase B (🟡): workload-level default model id. Projected to
3599
+ // `manifest.spec.defaults.model`, persisted in
3600
+ // `workloads.manifest_defaults_json`, and read at session creation as
3601
+ // the default for `sessions.metadata.model` when the caller does not
3602
+ // pin one. See `specs/features/pilot-v2-managed-agent-profile.md`
3603
+ // §"Phase B" for the resolution order.
3604
+ model: WorkloadManifestModelSchema.optional(),
3605
+ // Phase C (🟡): workload-level default enabled skills as friendly rush
3606
+ // skill names (e.g. `@kanyun/data-analysis-skills`). Projected to
3607
+ // `manifest.spec.defaults.enabledSkills` as `EnabledSkillRef[]`,
3608
+ // resolved to full snapshots at `POST /api/workloads`, and seeded into
3609
+ // `agents.enabled_skills` at agent creation when the caller omits
3610
+ // skills. See `specs/features/pilot-v2-managed-agent-profile.md`
3611
+ // §"Phase C".
3612
+ skills: z39.array(z39.string().min(1)).optional(),
3613
+ // Phase C2/C3 (🟡): workload-level default MCP servers as friendly rush
3614
+ // MCP ids (e.g. `github`). Projected to
3615
+ // `manifest.spec.defaults.enabledMcpServers` as `EnabledMcpRef[]`. At
3616
+ // `POST /api/workloads` each ref resolves by credential need:
3617
+ // credential-free templates freeze into `EnabledMcpServer` snapshots
3618
+ // (C2); credentialed templates persist as bare refs resolved per running
3619
+ // user at bootstrap (C3). Seeded into `agents.enabled_mcp_servers` at
3620
+ // agent creation when the caller omits MCP servers. See
3621
+ // `specs/features/pilot-v2-managed-agent-profile.md` §"Phase C".
3622
+ mcpServers: z39.array(z39.string().min(1)).optional(),
3623
+ // Phase D: workload-level default system prompt. Projected to
3624
+ // `manifest.spec.defaults.systemPrompt`, seeded onto
3625
+ // `agents.system_prompt` at agent creation, and forwarded per-run as
3626
+ // `PilotCoderRunConfigV1.systemPrompt`. agent-worker uses it instead of
3627
+ // the platform-level `SYSTEM_PROMPT` fallback. See
3628
+ // `specs/features/pilot-v2-managed-agent-profile.md` §"Phase D".
3629
+ systemPrompt: WorkloadManifestSystemPromptSchema.optional()
3630
+ }).strict();
3631
+ var ManagedAgentProfileSchema = z39.object({
3632
+ apiVersion: PilotWorkloadManifestApiVersionSchema,
3633
+ kind: z39.literal(MANAGED_AGENT_PROFILE_KIND),
3634
+ metadata: ManagedAgentProfileMetadataSchema,
3635
+ spec: ManagedAgentProfileSpecSchema
3636
+ }).strict();
3637
+ var PlatformProjectSchema = z40.object({
3638
+ id: z40.string().uuid(),
3639
+ slug: WorkloadManifestNameSchema,
3640
+ displayName: WorkloadManifestDisplayNameSchema,
3641
+ description: z40.string().nullable().optional(),
3642
+ defaultRuntimeTemplateRefName: WorkloadManifestRefNameSchema.nullable().optional(),
3643
+ createdAt: z40.string().optional(),
3644
+ updatedAt: z40.string().optional()
3645
+ }).strict();
3646
+ var CreatePlatformProjectRequestSchema = z40.object({
3647
+ slug: WorkloadManifestNameSchema,
3648
+ displayName: WorkloadManifestDisplayNameSchema,
3649
+ description: z40.string().max(2e3).optional(),
3650
+ defaultRuntimeTemplateRefName: WorkloadManifestRefNameSchema.optional()
3651
+ }).strict();
3652
+ var ListPlatformProjectsResponseSchema = z40.object({
3653
+ projects: z40.array(PlatformProjectSchema)
3654
+ }).strict();
3655
+ var PlatformWorkloadDefaultsSchema = z40.object({
3656
+ workerContract: WorkloadManifestWorkerContractDefaultsSchema.optional(),
3657
+ configValues: SessionConfigValuesSchema.optional(),
3658
+ model: z40.string().min(1).max(255).optional(),
3659
+ systemPrompt: z40.string().min(1).max(32768).optional(),
3660
+ enabledSkills: EnabledSkillEntryListSchema.optional(),
3661
+ enabledMcpServers: EnabledMcpEntryListSchema.optional()
3662
+ }).strict();
3663
+ var CreatePlatformWorkloadRequestSchema = z40.object({
3664
+ projectId: z40.string().uuid(),
3665
+ slug: WorkloadManifestNameSchema,
3666
+ displayName: WorkloadManifestDisplayNameSchema,
3667
+ kind: ActiveWorkloadKindSchema,
3668
+ defaults: PlatformWorkloadDefaultsSchema.optional(),
3669
+ ui: WorkloadManifestUiHintSchema.optional()
3670
+ }).strict();
3671
+ var PlatformWorkloadSchema = z40.object({
3672
+ id: z40.string().uuid(),
3673
+ projectId: z40.string().uuid(),
3674
+ slug: WorkloadManifestNameSchema,
3675
+ displayName: WorkloadManifestDisplayNameSchema,
3676
+ kind: ActiveWorkloadKindSchema,
3677
+ defaultRevisionId: z40.string().uuid().nullable().optional(),
3678
+ createdAt: z40.string().optional(),
3679
+ updatedAt: z40.string().optional()
3680
+ }).strict();
3681
+ var PublishPlatformRevisionWorkerContractSchema = z40.object({
3682
+ kind: ActiveWorkloadKindSchema,
3683
+ name: WorkloadManifestRefNameSchema.optional(),
3684
+ version: z40.string().min(1).max(100).optional()
3685
+ }).strict();
3686
+ var PublishPlatformRevisionRequestSchema = z40.object({
3687
+ projectId: z40.string().uuid(),
3688
+ workloadSlug: WorkloadManifestNameSchema,
3689
+ version: WorkloadManifestNameSchema,
3690
+ workerContract: PublishPlatformRevisionWorkerContractSchema,
3691
+ setDefault: z40.boolean().default(true),
3692
+ startup: z40.object({
3693
+ requiredGates: z40.array(z40.string().min(1)).optional(),
3694
+ optionalGates: z40.array(z40.string().min(1)).optional()
3695
+ }).strict().optional(),
3696
+ configValues: SessionConfigValuesSchema.optional(),
3697
+ managedAgentProfileSnapshot: ManagedAgentProfileSnapshotSchema.optional(),
3698
+ runtime: RevisionRuntimeSchema.optional()
3699
+ }).strict();
3700
+ var PlatformRevisionSchema = z40.object({
3701
+ id: z40.string().uuid(),
3702
+ projectId: z40.string().uuid(),
3703
+ workloadId: z40.string().uuid(),
3704
+ workloadSlug: WorkloadManifestNameSchema.optional(),
3705
+ version: WorkloadManifestNameSchema,
3706
+ runtimeSnapshotHash: z40.string().nullable().optional(),
3707
+ createdAt: z40.string().optional()
3708
+ }).strict();
3709
+ var GetPlatformSessionResponseSchema = z40.object({
3710
+ id: z40.string().uuid(),
3711
+ projectId: z40.string().uuid(),
3712
+ workloadId: z40.string().uuid(),
3713
+ revisionId: z40.string().uuid(),
3714
+ status: SessionStatusSchema,
3715
+ createdAt: z40.string().optional(),
3716
+ updatedAt: z40.string().optional()
3717
+ }).strict();
3718
+ var CreatePlatformSessionRequestSchema = CreateSessionRequestSchema;
3719
+ var CreatePlatformSessionResponseSchema = CreateSessionResponseSchema;
3720
+ function platformWorkloadCreateToManifest(input) {
3721
+ const defaults = input.defaults ? omitUndefined(input.defaults) : void 0;
3722
+ return WorkloadManifestSchema.parse({
3723
+ apiVersion: PILOT_WORKLOAD_MANIFEST_API_VERSION,
3724
+ kind: "Workload",
3725
+ metadata: {
3726
+ name: input.slug,
3727
+ displayName: input.displayName
3728
+ },
3729
+ spec: __spreadValues(__spreadValues({
3730
+ contract: { kind: input.kind }
3731
+ }, defaults ? { defaults } : {}), input.ui ? { ui: input.ui } : {})
3732
+ });
3733
+ }
3734
+ function omitUndefined(input) {
3735
+ return Object.fromEntries(
3736
+ Object.entries(input).filter((entry) => entry[1] !== void 0)
3737
+ );
3738
+ }
3739
+ function platformRevisionPublishToManifest(input) {
3740
+ return RevisionManifestSchema.parse({
3741
+ apiVersion: PILOT_WORKLOAD_MANIFEST_API_VERSION,
3742
+ kind: "Revision",
3743
+ metadata: {
3744
+ name: input.version,
3745
+ workload: input.workloadSlug
3746
+ },
3747
+ spec: __spreadValues(__spreadValues(__spreadValues(__spreadProps(__spreadValues({}, input.runtime ? { runtime: input.runtime } : {}), {
3748
+ workerContract: input.workerContract,
3749
+ publish: RevisionManifestPublishSchema.parse({ setDefault: input.setDefault })
3750
+ }), input.startup ? { startup: input.startup } : {}), input.configValues ? { configValues: input.configValues } : {}), input.managedAgentProfileSnapshot ? { managedAgentProfileSnapshot: input.managedAgentProfileSnapshot } : {})
3751
+ });
3752
+ }
3753
+ var PilotCoderSkillsInstallSchema = z41.object({
3754
+ gitlabDomain: z41.string().optional(),
3755
+ gitlabToken: z41.string().optional(),
3756
+ githubToken: z41.string().optional()
3757
+ }).strict();
3758
+ var PilotCoderTriggerRefSchema = z41.discriminatedUnion("type", [
3759
+ z41.object({
3760
+ type: z41.literal("github_issue"),
3761
+ number: z41.number().int().positive(),
3762
+ commentId: z41.number().int().positive().optional()
3763
+ }).strict(),
3764
+ z41.object({
3765
+ type: z41.literal("github_pr"),
3766
+ number: z41.number().int().positive(),
3767
+ commentId: z41.number().int().positive().optional()
3768
+ }).strict(),
3769
+ z41.object({
3770
+ type: z41.literal("gitlab_issue"),
3771
+ iid: z41.number().int().positive(),
3772
+ noteId: z41.number().int().positive().optional()
3773
+ }).strict(),
3774
+ z41.object({
3775
+ type: z41.literal("gitlab_mr"),
3776
+ iid: z41.number().int().positive(),
3777
+ noteId: z41.number().int().positive().optional()
3778
+ }).strict(),
3779
+ z41.object({
3780
+ type: z41.literal("jira_issue"),
3781
+ key: z41.string().min(1)
3782
+ }).strict(),
3783
+ z41.object({
3784
+ type: z41.literal("schedule"),
3785
+ scheduleId: z41.string().min(1)
3786
+ }).strict(),
3787
+ z41.object({
3788
+ type: z41.literal("opaque"),
3789
+ value: z41.string().min(1)
3790
+ }).strict()
3791
+ ]);
3792
+ var PilotCoderRunConfigV1Schema = z41.object({
3793
+ runId: z41.string().min(1),
3794
+ agentId: z41.string().min(1),
3795
+ provider: ProviderTypeSchema.optional(),
3796
+ model: z41.string().optional(),
3797
+ /**
3798
+ * Phase D — per-agent system prompt. Sourced by control-worker from
3799
+ * `agents.system_prompt` (seeded from a managed_agent profile's
3800
+ * `spec.systemPrompt` workload default). When present, agent-worker
3801
+ * uses it verbatim as the LLM `system` prompt **instead of** the
3802
+ * platform-level `SYSTEM_PROMPT` / `SYSTEM_PROMPT_GENERAL` fallback
3803
+ * (`getSystemPrompt(projectKind)`); when absent the platform default
3804
+ * is used, so v1 payloads stay backward-compatible.
3805
+ *
3806
+ * Routed per-run via the dispatch payload (not worker env) so multiple
3807
+ * workloads sharing a pod stay cleanly isolated. Deployment ordering:
3808
+ * contracts ship first (both control-worker and agent-worker must
3809
+ * recognize this key before control-worker starts populating it), since
3810
+ * `PilotCoderRunConfigV1Schema` is `.strict()`.
3811
+ */
3812
+ systemPrompt: z41.string().min(1).optional(),
3813
+ workspacePath: z41.string().optional(),
3814
+ mcpConfigDir: z41.string().optional(),
3815
+ attachments: z41.array(AttachmentMetaSchema).max(5).optional(),
3816
+ triggerContext: WebhookTriggerContextSchema.optional(),
3817
+ mcpServers: McpServersMapSchema.optional(),
3818
+ env: z41.record(z41.string(), z41.string()).optional(),
3819
+ projectKind: ProjectKindSchema.optional(),
3820
+ /**
3821
+ * v2-only — resolved skill artifact list, populated by
3822
+ * control-plane `v2McpResolve` (see `apps/control-worker/src/worker.ts`).
3823
+ * Each entry MUST be fully resolved (i.e. the legacy `EnabledSkill`
3824
+ * shape with `resolvedArtifact`) — refs (`EnabledSkillRef`) are
3825
+ * lookup-time-only and never travel on the wire.
3826
+ *
3827
+ * Agent-worker `run-agent-loop.ts` consumes this list and invokes
3828
+ * `@pilot/skills` `ensureSkillsInstalled` to materialize each
3829
+ * skill under `$HOME/.claude/skills/<dir>/` (claude-code provider)
3830
+ * or `$HOME/.codex/skills/<dir>/` (codex provider) before the LLM
3831
+ * loop spins up.
3832
+ *
3833
+ * In v1 this work was done by `mcpSkillsBootstrap` against the
3834
+ * sandbox SDK; v2 sandboxes live in a separate namespace and that
3835
+ * SDK 404s on them, so installation moved into the in-sandbox
3836
+ * agent-worker process. See `specs/features/pilot-v2-sdk-worker-substrate-api.md`
3837
+ * for the namespace rationale.
3838
+ */
3839
+ skills: z41.array(EnabledSkillSchema).optional(),
3840
+ skillsInstall: PilotCoderSkillsInstallSchema.optional(),
3841
+ /**
3842
+ * P3 L3.3 — delivery-related fields populated by control-worker from
3843
+ * `runs.*` / `agents.*` columns so the worker delivery loop can act
3844
+ * without re-querying control-plane. All fields are optional: v1
3845
+ * payloads predate L3.3 and senders without delivery (e.g. interactive
3846
+ * chat sessions) MUST still encode successfully.
3847
+ *
3848
+ * `repoUrl` mirrors `runs.repo_url` (nullable; omitted when null).
3849
+ * `baseBranch` is the PR/MR target branch (sourced from
3850
+ * `agents.base_ref` or `runs.target_ref` per dispatch site choice).
3851
+ * `triggerSource` mirrors `runs.trigger_source`. `triggerRef` is the
3852
+ * structured / parsed form of `runs.trigger_ref`. `prTitle` /
3853
+ * `prTemplate` are user / trigger-source specified overrides for the
3854
+ * delivery PR description; if neither column / setting exists yet on
3855
+ * the v1 data model, the dispatcher omits them (forward-compat).
3856
+ */
3857
+ repoUrl: z41.string().min(1).optional(),
3858
+ baseBranch: z41.string().min(1).optional(),
3859
+ triggerSource: TriggerSourceSchema.optional(),
3860
+ triggerRef: PilotCoderTriggerRefSchema.optional(),
3861
+ prTitle: z41.string().min(1).optional(),
3862
+ prTemplate: z41.string().min(1).optional()
3863
+ }).strict();
3864
+ var PilotCoderPromptPayloadV1Schema = z41.object({
3865
+ schemaVersion: z41.literal("v1"),
3866
+ kind: z41.literal("prompt"),
3867
+ prompt: z41.string().min(1),
3868
+ config: PilotCoderRunConfigV1Schema
3869
+ }).strict();
3870
+ var PilotCoderFollowupPayloadV1Schema = z41.object({
3871
+ schemaVersion: z41.literal("v1"),
3872
+ kind: z41.literal("followup"),
3873
+ message: z41.string().min(1),
3874
+ config: PilotCoderRunConfigV1Schema,
3875
+ expectedMessagesHash: z41.string().optional(),
3876
+ expectedMessagesCount: z41.number().int().nonnegative().optional()
3877
+ }).strict();
3878
+ var PilotCoderRestorePayloadV1Schema = z41.object({
3879
+ schemaVersion: z41.literal("v1"),
3880
+ kind: z41.literal("restore"),
3881
+ config: PilotCoderRunConfigV1Schema,
3882
+ messages: z41.array(z41.unknown()),
3883
+ messagesHash: z41.string().min(1),
3884
+ lastEventId: z41.number().int().nonnegative().optional(),
3885
+ pendingToolCalls: z41.array(z41.unknown()).optional(),
3886
+ workspaceHydrationRef: z41.string().optional(),
3887
+ runtimeProfileSnapshot: z41.record(z41.unknown()).optional(),
3888
+ degradedRecovery: z41.boolean().optional()
3889
+ }).strict();
3890
+ var GatewayErrorCodeSchema = z42.enum([
3891
+ "gateway_invalid_session_token",
3892
+ "gateway_session_not_found",
3893
+ "gateway_missing_mcp_target",
3894
+ "gateway_invalid_mcp_target",
3895
+ "gateway_invalid_mcp_method",
3896
+ "gateway_not_a_mcp_path",
3897
+ "gateway_mcp_target_not_allowed",
3898
+ "gateway_vault_unreachable",
3899
+ "gateway_credential_refresh_failed",
3900
+ "gateway_credential_refresh_timeout",
3901
+ "gateway_upstream_unreachable",
3902
+ "gateway_upstream_error",
3903
+ "gateway_upstream_timeout",
3904
+ "gateway_request_too_large",
3905
+ "gateway_response_too_large"
3906
+ ]);
3907
+ var WebhookEventTypeSchema = z43.enum([
3908
+ /** v1/v2 Run reached terminal `completed`. */
3909
+ "run.completed",
3910
+ /** v1/v2 Run reached terminal `failed`. */
3911
+ "run.failed",
3912
+ /** v2 Session startup reached terminal `ready`. */
3913
+ "session.status_ready",
3914
+ /** v2 Session startup reached terminal `failed`. */
3915
+ "session.status_failed",
3916
+ /** v2 Session post-ready lifecycle entered `idle`. */
3917
+ "session.lifecycle_idle",
3918
+ /** v2 Session post-ready lifecycle entered `terminating`. */
3919
+ "session.lifecycle_terminating",
3920
+ /** v2 Session post-ready lifecycle reached `terminated`. */
3921
+ "session.lifecycle_terminated"
3922
+ ]);
3923
+ var WEBHOOK_EVENT_TYPES = WebhookEventTypeSchema.options;
3924
+ var WebhookEventPayloadSchema = z43.object({
3925
+ event_id: z43.string().min(1).max(255),
3926
+ event_type: WebhookEventTypeSchema,
3927
+ /** ISO-8601 instant at which the transition was recorded. */
3928
+ occurred_at: z43.string(),
3929
+ project_id: z43.string().uuid(),
3930
+ run_id: z43.string().uuid().optional(),
3931
+ agent_id: z43.string().uuid().optional(),
3932
+ session_id: z43.string().uuid().optional(),
3933
+ lifecycle_phase: z43.enum(["idle", "terminating", "terminated"]).optional(),
3934
+ lifecycle_transition_id: z43.string().uuid().optional(),
3935
+ idle_since: z43.string().optional(),
3936
+ grace_deadline: z43.string().optional(),
3937
+ reason: z43.string().optional(),
3938
+ terminate_deadline: z43.string().optional()
3939
+ }).strict();
3940
+ var WebhookSubscriptionStatusSchema = z43.enum(["active", "disabled"]);
3941
+ var CreateWebhookSubscriptionRequestSchema = z43.object({
3942
+ projectId: z43.string().uuid(),
3943
+ /** Subscriber endpoint. https required outside dev; SSRF-validated. */
3944
+ url: z43.string().url().max(1024),
3945
+ /** Event types to deliver. At least one. */
3946
+ events: z43.array(WebhookEventTypeSchema).min(1).max(WEBHOOK_EVENT_TYPES.length),
3947
+ /** Optional operator note shown in list responses. */
3948
+ description: z43.string().max(512).optional()
3949
+ }).strict();
3950
+ var UpdateWebhookSubscriptionRequestSchema = z43.object({
3951
+ url: z43.string().url().max(1024).optional(),
3952
+ events: z43.array(WebhookEventTypeSchema).min(1).max(WEBHOOK_EVENT_TYPES.length).optional(),
3953
+ description: z43.string().max(512).nullable().optional(),
3954
+ /**
3955
+ * `active` re-enables a subscription that was auto-disabled after
3956
+ * consecutive failures (resets the failure counter); `disabled`
3957
+ * pauses delivery without deleting history.
3958
+ */
3959
+ status: WebhookSubscriptionStatusSchema.optional()
3960
+ }).strict().refine(
3961
+ (data) => data.url !== void 0 || data.events !== void 0 || data.description !== void 0 || data.status !== void 0,
3962
+ { message: "At least one of url / events / description / status MUST be provided" }
3963
+ );
3964
+ var WebhookSubscriptionSchema = z43.object({
3965
+ id: z43.string().uuid(),
3966
+ projectId: z43.string().uuid(),
3967
+ url: z43.string(),
3968
+ events: z43.array(WebhookEventTypeSchema),
3969
+ description: z43.string().nullable(),
3970
+ status: WebhookSubscriptionStatusSchema,
3971
+ consecutiveFailures: z43.number().int().nonnegative(),
3972
+ createdBy: z43.string(),
3973
+ createdAt: z43.string(),
3974
+ updatedAt: z43.string()
3975
+ });
3976
+ var WebhookSubscriptionWithSecretSchema = z43.object({
3977
+ subscription: WebhookSubscriptionSchema,
3978
+ secret: z43.string()
3979
+ });
3980
+ var WebhookSubscriptionErrorCodeSchema = z43.enum([
3981
+ // 400
3982
+ "VALIDATION_ERROR",
3983
+ /** URL failed SSRF policy (non-https, private/loopback/link-local IP…). */
3984
+ "WEBHOOK_URL_FORBIDDEN",
3985
+ // 404
3986
+ "SUBSCRIPTION_NOT_FOUND",
3987
+ "PROJECT_NOT_FOUND",
3988
+ // 409
3989
+ "SUBSCRIPTION_LIMIT_EXCEEDED",
3990
+ // 500
3991
+ "INTERNAL_ERROR"
3992
+ ]);
3993
+ var SessionPrewarmingIdentitySchema = z44.object({
3994
+ projectIdGenerator: z44.literal("nanoid"),
3995
+ claimNameTemplate: z44.string().min(1),
3996
+ idempotencyScopePrefix: z44.string().min(1)
3997
+ }).strict();
3998
+ var SessionPrewarmingSessionTemplateSchema = z44.object({
3999
+ configValues: z44.record(z44.string(), z44.string()),
4000
+ metadata: z44.record(z44.string(), z44.unknown()).optional()
4001
+ }).strict();
4002
+ var BusinessReadyProbeSchema = z44.object({
4003
+ endpointName: z44.enum(["api", "preview"]),
4004
+ path: z44.string().min(1),
4005
+ successCodes: z44.array(z44.number().int().min(100).max(599)).min(1),
4006
+ timeoutMs: z44.number().int().min(500).max(3e4)
4007
+ }).strict();
4008
+ var SessionPrewarmingSpecSchema = z44.object({
4009
+ targetReadyCount: z44.number().int().min(1).max(50),
4010
+ reVerifyIntervalSeconds: z44.number().int().min(60).max(3600),
4011
+ warmingTimeoutSeconds: z44.number().int().min(60).max(600),
4012
+ claimingLeaseTtlSeconds: z44.number().int().min(10).max(120),
4013
+ replenishIntervalSeconds: z44.number().int().min(5).max(300),
4014
+ maxConcurrentWarming: z44.number().int().min(1).max(10),
4015
+ identity: SessionPrewarmingIdentitySchema,
4016
+ sessionTemplate: SessionPrewarmingSessionTemplateSchema,
4017
+ businessReadyProbe: BusinessReadyProbeSchema.optional()
4018
+ }).strict();
4019
+ var AcquireSessionRequestSchema = z44.object({
4020
+ workloadId: z44.string().uuid(),
4021
+ clientMutationId: z44.string().min(1).max(255)
4022
+ }).strict();
4023
+ var AcquireSessionResponseSchema = z44.object({
4024
+ leaseToken: z44.string().min(1),
4025
+ leaseExpiresAt: z44.string().datetime(),
4026
+ sessionId: z44.string().uuid(),
4027
+ projectId: z44.string().min(1),
4028
+ runtimeClaimName: z44.string().min(1),
4029
+ configValues: z44.record(z44.string(), z44.string()),
4030
+ apiUrl: z44.string().url(),
4031
+ previewUrl: z44.string().url().optional()
4032
+ }).strict();
4033
+ var FinalizeAcquireRequestSchema = z44.object({
4034
+ leaseToken: z44.string().min(1),
4035
+ sessionId: z44.string().uuid(),
4036
+ clientMutationId: z44.string().min(1).max(255).optional()
4037
+ }).strict();
4038
+ var AbortAcquireRequestSchema = z44.object({
4039
+ leaseToken: z44.string().min(1),
4040
+ sessionId: z44.string().uuid()
4041
+ }).strict();
4042
+ var WorkloadLifecycleKindSchema = z45.enum(["managed_agent", "self_managed"]);
4043
+ var WorkloadLifecycleConfigSchema = z45.object({
4044
+ idleEnabled: z45.boolean().nullable(),
4045
+ idleAfterSeconds: z45.number().int().min(300).max(86400).nullable(),
4046
+ idleGraceSeconds: z45.number().int().min(60).max(3600).nullable(),
4047
+ maxSessionLifetimeMs: z45.number().int().min(36e5).max(6048e5).nullable()
4048
+ }).strict();
4049
+ var WorkloadLifecycleConfigUpdateSchema = WorkloadLifecycleConfigSchema.partial().strict();
4050
+ var EffectiveWorkloadLifecycleConfigSchema = z45.object({
4051
+ idleEnabled: z45.boolean(),
4052
+ idleAfterSeconds: z45.number().int().min(300).max(86400),
4053
+ idleGraceSeconds: z45.number().int().min(60).max(3600),
4054
+ maxSessionLifetimeMs: z45.number().int().min(36e5).max(6048e5)
4055
+ }).strict();
4056
+ var WorkloadLifecycleConfigResponseSchema = z45.object({
4057
+ workloadId: z45.string().uuid(),
4058
+ kind: WorkloadLifecycleKindSchema,
4059
+ config: WorkloadLifecycleConfigSchema,
4060
+ effective: EffectiveWorkloadLifecycleConfigSchema
4061
+ }).strict();
4062
+ var UuidSchema = z46.string().uuid();
4063
+ var NonEmptyUuidArraySchema = z46.array(UuidSchema).min(1).max(200);
4064
+ var CleanupPrefixSchema = z46.string().trim().min(5).max(128).regex(
4065
+ /^(?:e2e|tmp|test|cc)-[A-Za-z0-9][A-Za-z0-9._:-]*$/,
4066
+ "prefix must start with an allowed cleanup namespace: e2e-, tmp-, test-, or cc-"
4067
+ );
4068
+ var SessionTerminateRequestSchema = z46.object({
4069
+ reason: z46.string().trim().min(1).max(50).default("api"),
4070
+ deadlineAt: z46.string().datetime().optional(),
4071
+ requireNoActiveWork: z46.boolean().default(true)
4072
+ }).strict();
4073
+ var ResourceCleanupSelectorSchema = z46.object({
4074
+ projectId: UuidSchema,
4075
+ prefix: CleanupPrefixSchema.optional(),
4076
+ workloadIds: NonEmptyUuidArraySchema.optional(),
4077
+ runtimeTemplateIds: NonEmptyUuidArraySchema.optional(),
4078
+ sessionIds: NonEmptyUuidArraySchema.optional()
4079
+ }).strict().superRefine((value, ctx) => {
4080
+ var _a, _b, _c;
4081
+ if (!value.prefix && !((_a = value.workloadIds) == null ? void 0 : _a.length) && !((_b = value.runtimeTemplateIds) == null ? void 0 : _b.length) && !((_c = value.sessionIds) == null ? void 0 : _c.length)) {
4082
+ ctx.addIssue({
4083
+ code: z46.ZodIssueCode.custom,
4084
+ message: "cleanup selector must include prefix or explicit ids",
4085
+ path: ["prefix"]
4086
+ });
4087
+ }
4088
+ });
4089
+ var ResourceCleanupPlanRequestSchema = z46.object({
4090
+ selector: ResourceCleanupSelectorSchema
4091
+ }).strict();
4092
+ var ResourceCleanupExecuteRequestSchema = z46.object({
4093
+ selector: ResourceCleanupSelectorSchema,
4094
+ expectedCleanupId: z46.string().min(16).max(64),
4095
+ confirm: z46.literal(true),
4096
+ terminateActiveSessions: z46.boolean().default(true),
4097
+ requireNoActiveWork: z46.boolean().default(true)
4098
+ }).strict();
4099
+ var ResourceCleanupResourceTypeSchema = z46.enum([
4100
+ "agents_session_refs",
4101
+ "runs_session_refs",
4102
+ "session_pool_slots",
4103
+ "session_pool_configs",
4104
+ "worker_protocol_jobs",
4105
+ "schedule_triggers",
4106
+ "schedule_definitions",
4107
+ "session_vault_bindings",
4108
+ "session_config_values",
4109
+ "session_tokens",
4110
+ "session_events",
4111
+ "session_startup_jobs",
4112
+ "session_failure_reasons",
4113
+ "startup_gate_conditions",
4114
+ "runtime_bindings",
4115
+ "sessions",
4116
+ "revision_config_values",
4117
+ "revisions",
4118
+ "workloads",
4119
+ "runtime_templates"
4120
+ ]);
4121
+ var ResourceCleanupBlockerSchema = z46.object({
4122
+ code: z46.string(),
4123
+ resourceType: z46.string(),
4124
+ resourceId: z46.string(),
4125
+ message: z46.string()
4126
+ }).strict();
4127
+ var ResourceCleanupStepSchema = z46.object({
4128
+ resourceType: ResourceCleanupResourceTypeSchema,
4129
+ action: z46.enum(["delete", "update_null"]),
4130
+ count: z46.number().int().nonnegative(),
4131
+ ids: z46.array(z46.string())
4132
+ }).strict();
4133
+ var ResourceCleanupResourceIdsSchema = z46.object({
4134
+ workloadIds: z46.array(UuidSchema),
4135
+ runtimeTemplateIds: z46.array(UuidSchema),
4136
+ revisionIds: z46.array(UuidSchema),
4137
+ sessionIds: z46.array(UuidSchema),
4138
+ runtimeBindingIds: z46.array(UuidSchema),
4139
+ sessionPoolSlotIds: z46.array(UuidSchema),
4140
+ sessionPoolConfigWorkloadIds: z46.array(UuidSchema),
4141
+ scheduleDefinitionIds: z46.array(UuidSchema),
4142
+ scheduleTriggerIds: z46.array(UuidSchema),
4143
+ runSessionRefIds: z46.array(UuidSchema),
4144
+ agentSessionRefIds: z46.array(UuidSchema),
4145
+ workerProtocolJobIds: z46.array(UuidSchema)
4146
+ }).strict();
4147
+ var ResourceCleanupPlanSchema = z46.object({
4148
+ cleanupId: z46.string(),
4149
+ generatedAt: z46.string().datetime(),
4150
+ selector: ResourceCleanupSelectorSchema,
4151
+ resources: ResourceCleanupResourceIdsSchema,
4152
+ counts: z46.record(ResourceCleanupResourceTypeSchema, z46.number().int().nonnegative()),
4153
+ steps: z46.array(ResourceCleanupStepSchema),
4154
+ blockers: z46.array(ResourceCleanupBlockerSchema)
4155
+ }).strict();
4156
+ var ResourceCleanupExecuteResultSchema = z46.object({
4157
+ cleanupId: z46.string(),
4158
+ deletedCounts: z46.record(ResourceCleanupResourceTypeSchema, z46.number().int().nonnegative()),
4159
+ updatedCounts: z46.record(ResourceCleanupResourceTypeSchema, z46.number().int().nonnegative()),
4160
+ terminatedSessions: z46.array(UuidSchema),
4161
+ readback: ResourceCleanupPlanSchema
4162
+ }).strict();
4163
+
4164
+ // src/errors.ts
4165
+ var PilotPlatformApiError = class extends Error {
4166
+ constructor(options) {
4167
+ super(options.message ?? `${options.code} (HTTP ${options.status})`, {
4168
+ cause: options.cause
4169
+ });
4170
+ this.name = "PilotPlatformApiError";
4171
+ this.status = options.status;
4172
+ this.code = options.code;
4173
+ this.requestId = options.requestId;
4174
+ }
4175
+ };
4176
+ var PilotPlatformUnauthenticatedError = class extends PilotPlatformApiError {
4177
+ constructor(options) {
4178
+ super({ ...options, status: 401 });
4179
+ this.name = "PilotPlatformUnauthenticatedError";
4180
+ }
4181
+ };
4182
+ var PilotPlatformForbiddenError = class extends PilotPlatformApiError {
4183
+ constructor(options) {
4184
+ super({ ...options, status: 403 });
4185
+ this.name = "PilotPlatformForbiddenError";
4186
+ }
4187
+ };
4188
+ var PilotPlatformNotFoundError = class extends PilotPlatformApiError {
4189
+ constructor(options) {
4190
+ super({ ...options, status: 404 });
4191
+ this.name = "PilotPlatformNotFoundError";
4192
+ }
4193
+ };
4194
+ var PilotPlatformServerError = class extends PilotPlatformApiError {
4195
+ constructor(options) {
4196
+ super(options);
4197
+ this.name = "PilotPlatformServerError";
4198
+ }
4199
+ };
4200
+ function pilotPlatformErrorFromResponse(params) {
4201
+ const parsed = extractErrorBody(params.body);
4202
+ const code = parsed.code ?? defaultCodeForStatus(params.status);
4203
+ const message = parsed.message ?? parsed.error;
4204
+ const base = { code, message, requestId: params.requestId };
4205
+ if (params.status === 401) return new PilotPlatformUnauthenticatedError(base);
4206
+ if (params.status === 403) return new PilotPlatformForbiddenError(base);
4207
+ if (params.status === 404) return new PilotPlatformNotFoundError(base);
4208
+ if (params.status >= 500 && params.status < 600) {
4209
+ return new PilotPlatformServerError({ ...base, status: params.status });
4210
+ }
4211
+ return new PilotPlatformApiError({ ...base, status: params.status });
4212
+ }
4213
+ function extractErrorBody(body) {
4214
+ if (!body || typeof body !== "object") return {};
4215
+ const record = body;
4216
+ return {
4217
+ error: typeof record.error === "string" ? record.error : void 0,
4218
+ code: typeof record.code === "string" ? record.code : void 0,
4219
+ message: typeof record.message === "string" ? record.message : void 0
4220
+ };
4221
+ }
4222
+ function defaultCodeForStatus(status) {
4223
+ if (status === 401) return "UNAUTHENTICATED";
4224
+ if (status === 403) return "FORBIDDEN";
4225
+ if (status === 404) return "NOT_FOUND";
4226
+ if (status >= 500) return "SERVER_ERROR";
4227
+ return "REQUEST_FAILED";
4228
+ }
4229
+
4230
+ // src/resources/projects.ts
4231
+ var ProjectsResource = class {
4232
+ constructor(client) {
4233
+ this.client = client;
4234
+ }
4235
+ async create(request, options = {}) {
4236
+ const body = CreatePlatformProjectRequestSchema.parse(request);
4237
+ const response = await this.client.request("/api/projects", {
4238
+ method: "POST",
4239
+ body,
4240
+ signal: options.signal
4241
+ });
4242
+ return PlatformProjectSchema.parse(response);
4243
+ }
4244
+ async list(options = {}) {
4245
+ const response = await this.client.request("/api/projects", {
4246
+ method: "GET",
4247
+ signal: options.signal
4248
+ });
4249
+ return ListPlatformProjectsResponseSchema.parse(response).projects;
4250
+ }
4251
+ async get(projectId, options = {}) {
4252
+ const response = await this.client.request(
4253
+ `/api/projects/${encodeURIComponent(projectId)}`,
4254
+ {
4255
+ method: "GET",
4256
+ signal: options.signal,
4257
+ cache: "no-store"
4258
+ }
4259
+ );
4260
+ return PlatformProjectSchema.parse(response);
4261
+ }
4262
+ };
4263
+
4264
+ // src/resources/sessions.ts
4265
+ var SessionsResource = class {
4266
+ constructor(client) {
4267
+ this.client = client;
4268
+ }
4269
+ async create(request, options = {}) {
4270
+ const body = CreatePlatformSessionRequestSchema.parse(request);
4271
+ const envelope = await this.client.request("/api/sessions", {
4272
+ method: "POST",
4273
+ body,
4274
+ signal: options.signal
4275
+ });
4276
+ return CreatePlatformSessionResponseSchema.parse(envelope?.data);
4277
+ }
4278
+ async get(sessionId, options = {}) {
4279
+ const envelope = await this.client.request(
4280
+ `/api/sessions/${encodeURIComponent(sessionId)}`,
4281
+ {
4282
+ method: "GET",
4283
+ signal: options.signal,
4284
+ cache: "no-store",
4285
+ headers: {
4286
+ "Cache-Control": "no-cache",
4287
+ Pragma: "no-cache"
4288
+ }
4289
+ }
4290
+ );
4291
+ if (!envelope?.data || typeof envelope.data !== "object") {
4292
+ throw new PilotPlatformApiError({
4293
+ status: 0,
4294
+ code: "MALFORMED_SESSION_RESPONSE",
4295
+ message: "GET /api/sessions/:id did not return a {data: ...} envelope."
4296
+ });
4297
+ }
4298
+ return envelope.data;
4299
+ }
4300
+ async wait(sessionId, options = {}) {
4301
+ const intervalMs = options.intervalMs ?? 1e3;
4302
+ const timeoutMs = options.timeoutMs ?? 12e4;
4303
+ const startedAt = Date.now();
4304
+ while (true) {
4305
+ if (options.signal?.aborted) throw options.signal.reason;
4306
+ const snapshot = await this.get(sessionId, { signal: options.signal });
4307
+ const status = snapshot.session?.status;
4308
+ if (status === "ready") return snapshot;
4309
+ if (status === "failed") {
4310
+ throw new PilotPlatformApiError({
4311
+ status: 0,
4312
+ code: "SESSION_FAILED",
4313
+ message: `Session ${sessionId} failed while waiting for readiness.`
4314
+ });
4315
+ }
4316
+ if (Date.now() - startedAt >= timeoutMs) {
4317
+ throw new PilotPlatformApiError({
4318
+ status: 0,
4319
+ code: "SESSION_WAIT_TIMEOUT",
4320
+ message: `Timed out waiting for session ${sessionId} to become ready.`
4321
+ });
4322
+ }
4323
+ await sleep(intervalMs, options.signal);
4324
+ }
4325
+ }
4326
+ };
4327
+ function sleep(ms, signal) {
4328
+ if (ms <= 0) return Promise.resolve();
4329
+ return new Promise((resolve, reject) => {
4330
+ const timer = setTimeout(resolve, ms);
4331
+ signal?.addEventListener(
4332
+ "abort",
4333
+ () => {
4334
+ clearTimeout(timer);
4335
+ reject(signal.reason);
4336
+ },
4337
+ { once: true }
4338
+ );
4339
+ });
4340
+ }
4341
+
4342
+ // src/resources/workloads.ts
4343
+ var WorkloadsResource = class {
4344
+ constructor(client) {
4345
+ this.client = client;
4346
+ }
4347
+ async create(request, options = {}) {
4348
+ const body = CreatePlatformWorkloadRequestSchema.parse(request);
4349
+ const envelope = await this.client.request("/api/workloads", {
4350
+ method: "POST",
4351
+ body,
4352
+ signal: options.signal,
4353
+ query: options.dryRun ? { dryRun: true } : void 0
4354
+ });
4355
+ return unwrapEnvelope(envelope, "POST /api/workloads", ["status", "workload"]);
4356
+ }
4357
+ async publishRevision(request, options = {}) {
4358
+ const body = PublishPlatformRevisionRequestSchema.parse(request);
4359
+ const path = `/api/workloads/${encodeURIComponent(body.workloadSlug)}/revisions`;
4360
+ const envelope = await this.client.request(path, {
4361
+ method: "POST",
4362
+ body,
4363
+ signal: options.signal,
4364
+ query: options.dryRun ? { dryRun: true } : void 0
4365
+ });
4366
+ return unwrapEnvelope(envelope, `POST ${path}`, [
4367
+ "status",
4368
+ "workloadId",
4369
+ "runtimeTemplateId",
4370
+ "resolved"
4371
+ ]);
4372
+ }
4373
+ async applyManifest(options) {
4374
+ const envelope = await this.client.request(
4375
+ "/api/workloads",
4376
+ buildManifestRequest(options.manifest, options)
4377
+ );
4378
+ return unwrapEnvelope(envelope, "POST /api/workloads", ["status", "workload"]);
4379
+ }
4380
+ async applyRevisionManifest(options) {
4381
+ const path = `/api/workloads/${encodeURIComponent(options.workloadSlug)}/revisions`;
4382
+ const envelope = await this.client.request(
4383
+ path,
4384
+ buildManifestRequest(options.manifest, options)
4385
+ );
4386
+ return unwrapEnvelope(envelope, `POST ${path}`, [
4387
+ "status",
4388
+ "workloadId",
4389
+ "runtimeTemplateId",
4390
+ "resolved"
4391
+ ]);
4392
+ }
4393
+ };
4394
+ function buildManifestRequest(manifest, options) {
4395
+ const init = {
4396
+ method: "POST",
4397
+ signal: options.signal,
4398
+ query: {
4399
+ projectId: options.projectId,
4400
+ ...options.dryRun ? { dryRun: true } : {}
4401
+ }
4402
+ };
4403
+ if (isYamlInput(manifest)) {
4404
+ init.rawBody = manifest.yaml;
4405
+ init.headers = { "Content-Type": "application/yaml" };
4406
+ } else if (isJsonStringInput(manifest)) {
4407
+ init.rawBody = manifest.json;
4408
+ init.headers = { "Content-Type": "application/json" };
4409
+ } else {
4410
+ init.body = manifest;
4411
+ }
4412
+ return init;
4413
+ }
4414
+ function isYamlInput(value) {
4415
+ return typeof value === "object" && value !== null && "yaml" in value && typeof value.yaml === "string";
4416
+ }
4417
+ function isJsonStringInput(value) {
4418
+ return typeof value === "object" && value !== null && "json" in value && typeof value.json === "string";
4419
+ }
4420
+ function unwrapEnvelope(envelope, routeLabel, requiredKeys) {
4421
+ const data = envelope?.data;
4422
+ if (!data) {
4423
+ throw new PilotPlatformApiError({
4424
+ status: 0,
4425
+ code: "MALFORMED_PLATFORM_RESPONSE",
4426
+ message: `${routeLabel} did not return a {data: ...} envelope.`
4427
+ });
4428
+ }
4429
+ for (const key of requiredKeys) {
4430
+ if (!(key in data)) {
4431
+ throw new PilotPlatformApiError({
4432
+ status: 0,
4433
+ code: "MALFORMED_PLATFORM_RESPONSE",
4434
+ message: `${routeLabel} response is missing required field '${String(key)}'.`
4435
+ });
4436
+ }
4437
+ }
4438
+ return data;
4439
+ }
4440
+
4441
+ // src/client.ts
4442
+ var AGENTHUB_SDK_USER_AGENT = "@kanyun-ai-infra/agenthub/0.1.0";
4443
+ var _token;
4444
+ var PilotPlatformClient = class {
4445
+ constructor(config = {}) {
4446
+ __privateAdd(this, _token);
4447
+ const controlPlaneUrl = config.controlPlaneUrl ?? readEnv("PILOT_CONTROL_PLANE_URL") ?? readEnv("KANYUN_PILOT_CONTROL_PLANE_URL");
4448
+ const token = config.token ?? readEnv("PILOT_TOKEN");
4449
+ if (!controlPlaneUrl) {
4450
+ throw new PilotPlatformApiError({
4451
+ status: 0,
4452
+ code: "CONFIG_MISSING_CONTROL_PLANE_URL",
4453
+ message: "PilotPlatformClient requires `controlPlaneUrl` or PILOT_CONTROL_PLANE_URL."
4454
+ });
4455
+ }
4456
+ if (!token) {
4457
+ throw new PilotPlatformUnauthenticatedError({
4458
+ code: "CONFIG_MISSING_TOKEN",
4459
+ message: "PilotPlatformClient requires `token` or PILOT_TOKEN."
4460
+ });
4461
+ }
4462
+ const normalizedControlPlaneUrl = stripTrailingSlash(controlPlaneUrl);
4463
+ try {
4464
+ const parsed = new URL(normalizedControlPlaneUrl);
4465
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
4466
+ throw new Error(`Unsupported protocol: ${parsed.protocol}`);
4467
+ }
4468
+ } catch (error) {
4469
+ throw new PilotPlatformApiError({
4470
+ status: 0,
4471
+ code: "CONFIG_INVALID_CONTROL_PLANE_URL",
4472
+ message: `controlPlaneUrl is not a valid http(s) URL: ${controlPlaneUrl}`,
4473
+ cause: error
4474
+ });
4475
+ }
4476
+ this.controlPlaneUrl = normalizedControlPlaneUrl;
4477
+ __privateSet(this, _token, token);
4478
+ this.fetchImpl = config.fetch ?? globalThis.fetch.bind(globalThis);
4479
+ this.defaultHeaders = { ...config.defaultHeaders ?? {} };
4480
+ this.defaultSignal = config.signal;
4481
+ this.userAgent = config.userAgent ?? AGENTHUB_SDK_USER_AGENT;
4482
+ this.pilotApiVersion = config.pilotApiVersion ?? "v2";
4483
+ this.projects = new ProjectsResource(this);
4484
+ this.workloads = new WorkloadsResource(this);
4485
+ this.sessions = new SessionsResource(this);
4486
+ }
4487
+ async request(path, init = {}) {
4488
+ const res = await this.rawRequest(path, init);
4489
+ if (init.raw) return res;
4490
+ const text = await res.text();
4491
+ if (!text) return void 0;
4492
+ try {
4493
+ return JSON.parse(text);
4494
+ } catch (error) {
4495
+ throw new PilotPlatformApiError({
4496
+ status: res.status,
4497
+ code: "INVALID_JSON_RESPONSE",
4498
+ message: `Control Plane returned non-JSON body: ${text.slice(0, 200)}`,
4499
+ requestId: res.headers.get("x-request-id") ?? void 0,
4500
+ cause: error
4501
+ });
4502
+ }
4503
+ }
4504
+ async rawRequest(path, init = {}) {
4505
+ if (init.rawBody !== void 0 && init.body !== void 0) {
4506
+ throw new PilotPlatformApiError({
4507
+ status: 0,
4508
+ code: "INVALID_REQUEST_BODY",
4509
+ message: "body and rawBody are mutually exclusive."
4510
+ });
4511
+ }
4512
+ const headers = new Headers();
4513
+ addHeaders(headers, { Accept: "application/json", "User-Agent": this.userAgent });
4514
+ addHeaders(headers, this.defaultHeaders);
4515
+ addHeaders(headers, init.headers);
4516
+ headers.delete("authorization");
4517
+ headers.set("Authorization", `Bearer ${__privateGet(this, _token)}`);
4518
+ headers.set(X_PILOT_API_VERSION_HEADER, this.pilotApiVersion);
4519
+ let body;
4520
+ if (init.rawBody !== void 0) {
4521
+ body = init.rawBody;
4522
+ } else if (init.body !== void 0) {
4523
+ body = JSON.stringify(init.body);
4524
+ headers.set("Content-Type", "application/json");
4525
+ }
4526
+ let res;
4527
+ const url = this.composeUrl(path, init.query);
4528
+ try {
4529
+ res = await this.fetchImpl(url, {
4530
+ method: init.method ?? "GET",
4531
+ headers,
4532
+ body,
4533
+ signal: mergeSignals(this.defaultSignal, init.signal),
4534
+ cache: init.cache
4535
+ });
4536
+ } catch (error) {
4537
+ if (isAbortError(error)) throw error;
4538
+ throw new PilotPlatformApiError({
4539
+ status: 0,
4540
+ code: "NETWORK_ERROR",
4541
+ message: `Request to ${url} failed: ${error?.message ?? String(error)}`,
4542
+ cause: error
4543
+ });
4544
+ }
4545
+ if (res.ok) return res;
4546
+ const text = await res.text();
4547
+ let parsed = void 0;
4548
+ if (text) {
4549
+ try {
4550
+ parsed = JSON.parse(text);
4551
+ } catch {
4552
+ parsed = { error: text };
4553
+ }
4554
+ }
4555
+ throw pilotPlatformErrorFromResponse({
4556
+ status: res.status,
4557
+ body: parsed,
4558
+ requestId: res.headers.get("x-request-id") ?? void 0
4559
+ });
4560
+ }
4561
+ composeUrl(path, query) {
4562
+ const base = new URL(`${this.controlPlaneUrl}/`);
4563
+ const normalized = path.startsWith("//") || /^[a-z][a-z0-9+.-]*:/i.test(path) ? path : path.startsWith("/") ? path : `/${path}`;
4564
+ let full;
4565
+ try {
4566
+ full = new URL(normalized, base);
4567
+ } catch (error) {
4568
+ throw new PilotPlatformApiError({
4569
+ status: 0,
4570
+ code: "INVALID_REQUEST_URL",
4571
+ message: `Could not resolve path "${path}" against controlPlaneUrl.`,
4572
+ cause: error
4573
+ });
4574
+ }
4575
+ if (full.origin !== base.origin) {
4576
+ throw new PilotPlatformApiError({
4577
+ status: 0,
4578
+ code: "CROSS_ORIGIN_REQUEST_BLOCKED",
4579
+ message: `Refusing to send Bearer token to foreign origin ${full.origin}.`
4580
+ });
4581
+ }
4582
+ if (query) {
4583
+ for (const [key, value] of Object.entries(query)) {
4584
+ if (value === void 0 || value === null) continue;
4585
+ full.searchParams.set(key, String(value));
4586
+ }
4587
+ }
4588
+ return full.toString();
4589
+ }
4590
+ };
4591
+ _token = new WeakMap();
4592
+ function stripTrailingSlash(url) {
4593
+ return url.endsWith("/") ? url.slice(0, -1) : url;
4594
+ }
4595
+ function addHeaders(target, source) {
4596
+ if (!source) return;
4597
+ for (const [key, value] of Object.entries(source)) {
4598
+ if (value === void 0 || value === null) continue;
4599
+ target.set(key, value);
4600
+ }
4601
+ }
4602
+ function readEnv(key) {
4603
+ const env = globalThis.process?.env;
4604
+ const value = env?.[key];
4605
+ return value && value.length > 0 ? value : void 0;
4606
+ }
4607
+ function isAbortError(error) {
4608
+ return error instanceof Error && (error.name === "AbortError" || error.code === "ABORT_ERR");
4609
+ }
4610
+ function mergeSignals(...signals) {
4611
+ const active = signals.filter((signal) => !!signal);
4612
+ if (active.length === 0) return void 0;
4613
+ if (active.length === 1) return active[0];
4614
+ const anyFn = AbortSignal.any;
4615
+ if (typeof anyFn === "function") return anyFn(active);
4616
+ const controller = new AbortController();
4617
+ for (const signal of active) {
4618
+ if (signal.aborted) {
4619
+ controller.abort(signal.reason);
4620
+ break;
4621
+ }
4622
+ signal.addEventListener("abort", () => controller.abort(signal.reason), { once: true });
4623
+ }
4624
+ return controller.signal;
4625
+ }
4626
+ export {
4627
+ AGENTHUB_SDK_USER_AGENT,
4628
+ CreatePlatformProjectRequestSchema,
4629
+ CreatePlatformSessionRequestSchema,
4630
+ CreatePlatformSessionResponseSchema,
4631
+ CreatePlatformWorkloadRequestSchema,
4632
+ ListPlatformProjectsResponseSchema,
4633
+ PILOT_WORKLOAD_MANIFEST_API_VERSION,
4634
+ PILOT_WORKLOAD_MANIFEST_LEGACY_API_VERSION,
4635
+ PilotPlatformApiError,
4636
+ PilotPlatformClient,
4637
+ PilotPlatformForbiddenError,
4638
+ PilotPlatformNotFoundError,
4639
+ PilotPlatformServerError,
4640
+ PilotPlatformUnauthenticatedError,
4641
+ PlatformProjectSchema,
4642
+ PlatformRevisionSchema,
4643
+ PlatformWorkloadSchema,
4644
+ ProjectsResource,
4645
+ PublishPlatformRevisionRequestSchema,
4646
+ SessionsResource,
4647
+ WorkloadsResource,
4648
+ pilotPlatformErrorFromResponse,
4649
+ platformRevisionPublishToManifest,
4650
+ platformWorkloadCreateToManifest
4651
+ };
4652
+ //# sourceMappingURL=index.js.map