@hyperdrive.bot/paseo-protocol 0.3.41 → 0.3.43
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/agent-state-bucket.d.ts +28 -4
- package/dist/agent-state-bucket.js +28 -4
- package/dist/generated/validation/ws-outbound.aot.js +26832 -26599
- package/dist/messages.d.ts +401 -84
- package/dist/messages.js +65 -2
- package/dist/validation/ws-outbound-schema-metadata.d.ts +58 -20
- package/dist/workflow/compile.d.ts +33 -0
- package/dist/workflow/compile.js +172 -0
- package/dist/workflow/definition.d.ts +134 -0
- package/dist/workflow/definition.js +362 -0
- package/package.json +1 -1
package/dist/messages.js
CHANGED
|
@@ -101,7 +101,9 @@ export const MutableDaemonConfigSchema = z
|
|
|
101
101
|
.passthrough(),
|
|
102
102
|
browserTools: MutableBrowserToolsConfigSchema.default({ enabled: false }),
|
|
103
103
|
providers: z.record(z.string(), MutableDaemonProviderConfigSchema).default({}),
|
|
104
|
-
metadataGeneration: MutableMetadataGenerationConfigSchema.default({
|
|
104
|
+
metadataGeneration: MutableMetadataGenerationConfigSchema.default({
|
|
105
|
+
providers: [],
|
|
106
|
+
}),
|
|
105
107
|
autoArchiveAfterMerge: z.boolean().default(false),
|
|
106
108
|
enableTerminalAgentHooks: z.boolean().default(false),
|
|
107
109
|
appendSystemPrompt: z.string().default(""),
|
|
@@ -154,6 +156,38 @@ export const WorkflowPhaseSchema = z.object({
|
|
|
154
156
|
storyCount: z.number().int().nonnegative().optional(),
|
|
155
157
|
completedStoryCount: z.number().int().nonnegative().optional(),
|
|
156
158
|
});
|
|
159
|
+
/**
|
|
160
|
+
* Per-step agent config (Epic 2, Story 2.1). A CLOSED subset of the daemon's
|
|
161
|
+
* `AgentSessionConfig`: every key optional, and `.strict()` so an unknown key is a
|
|
162
|
+
* parse ERROR rather than a silent strip. Silent-strip is the failure this schema
|
|
163
|
+
* exists to prevent: a typo'd `provider:` would otherwise spawn the default agent
|
|
164
|
+
* with no signal, which is exactly the "silent fallback to the default" the epic forbids.
|
|
165
|
+
*
|
|
166
|
+
* Deliberately excluded, each for a reason:
|
|
167
|
+
* - `cwd`: workflow-owned. A step must not relocate its child. Also forced at merge time.
|
|
168
|
+
* - `extra` / `mcpServers` / `featureValues`: arbitrary nested structure, i.e. the
|
|
169
|
+
* "deterministic via code" escape hatch this PRD exists to close.
|
|
170
|
+
* - `title`: owned by `initialTitle`, which the manager sets from `node.title`.
|
|
171
|
+
* - `daemonAppendSystemPrompt`: runtime-only, never persisted (`agent-sdk-types.ts:565-568`).
|
|
172
|
+
* - `internal`: workflow children must stay listable (`AgentManager.listAgents` filters
|
|
173
|
+
* on `!agent.internal`, `agent-manager.ts:810-813`).
|
|
174
|
+
*
|
|
175
|
+
* Widening this vocabulary requires a schema edit AND a new test. It must never widen
|
|
176
|
+
* by accident from a config file.
|
|
177
|
+
*/
|
|
178
|
+
export const WorkflowAgentPresetSchema = z
|
|
179
|
+
.object({
|
|
180
|
+
provider: z.string().optional(),
|
|
181
|
+
model: z.string().optional(),
|
|
182
|
+
modeId: z.string().optional(),
|
|
183
|
+
systemPrompt: z.string().optional(),
|
|
184
|
+
thinkingOptionId: z.string().optional(),
|
|
185
|
+
approvalPolicy: z.string().optional(),
|
|
186
|
+
sandboxMode: z.string().optional(),
|
|
187
|
+
networkAccess: z.boolean().optional(),
|
|
188
|
+
webSearch: z.boolean().optional(),
|
|
189
|
+
})
|
|
190
|
+
.strict();
|
|
157
191
|
// Live/wire snapshot of a workflow. New fields must be additive (.optional() with a
|
|
158
192
|
// sensible default) to preserve back-compat — a 6-month-old client must still parse this.
|
|
159
193
|
export const WorkflowSnapshotSchema = z.object({
|
|
@@ -162,6 +196,12 @@ export const WorkflowSnapshotSchema = z.object({
|
|
|
162
196
|
status: WorkflowStatusSchema,
|
|
163
197
|
title: z.string().nullable().optional(),
|
|
164
198
|
labels: z.record(z.string(), z.string()).default({}),
|
|
199
|
+
// Epic 2, Story 2.2: named agent presets a task's `agentType` selects. `.optional()`
|
|
200
|
+
// with NO `.default({})` on purpose: a default would stamp an empty map onto every
|
|
201
|
+
// record written before this field existed, and would make "an old record has no
|
|
202
|
+
// presets" untestable. Placed on the SNAPSHOT rather than only on the stored record so
|
|
203
|
+
// `STORED_WORKFLOW_SCHEMA` stays a bare alias and `persist` needs no change.
|
|
204
|
+
agentPresets: z.record(z.string(), WorkflowAgentPresetSchema).optional(),
|
|
165
205
|
phases: z.array(WorkflowPhaseSchema).default([]),
|
|
166
206
|
childAgentIds: z.array(z.string()).default([]),
|
|
167
207
|
totalStoryCount: z.number().int().nonnegative().optional(),
|
|
@@ -268,6 +308,10 @@ export const WorkflowEventsResponseSchema = z.object({
|
|
|
268
308
|
// by BOTH this client-facing `workflow.start` RPC and the `workflow_start` MCP
|
|
269
309
|
// tool (no second divergent copy). The CLI's `child_process` / `claude -p`
|
|
270
310
|
// spawning is deliberately NOT modelled — `agentManager.createAgent` replaces it.
|
|
311
|
+
// `WorkflowAgentPresetSchema` / `WorkflowAgentPreset` are declared ABOVE
|
|
312
|
+
// `WorkflowSnapshotSchema` (Epic 2, Story 2.2): the snapshot references the preset
|
|
313
|
+
// schema, and a `const` referenced before its initialiser runs is a runtime TDZ
|
|
314
|
+
// `ReferenceError` at module load, which `tsc --noEmit` does not catch.
|
|
271
315
|
/** One task node — becomes one child agent when the workflow starts. */
|
|
272
316
|
export const WorkflowTaskNodeSchema = z.object({
|
|
273
317
|
id: z.string(),
|
|
@@ -279,6 +323,7 @@ export const WorkflowTaskNodeSchema = z.object({
|
|
|
279
323
|
parallelizable: z.boolean(),
|
|
280
324
|
estimatedMinutes: z.number(),
|
|
281
325
|
agentType: z.string().optional(),
|
|
326
|
+
agentConfig: WorkflowAgentPresetSchema.optional(),
|
|
282
327
|
targetFiles: z.array(z.string()).optional(),
|
|
283
328
|
});
|
|
284
329
|
/** Decomposed task graph driving child-agent spawning. */
|
|
@@ -316,6 +361,7 @@ export const WorkflowStartRequestSchema = z.object({
|
|
|
316
361
|
model: z.string().optional(),
|
|
317
362
|
title: z.string().optional(),
|
|
318
363
|
labels: z.record(z.string(), z.string()).optional(),
|
|
364
|
+
agentPresets: z.record(z.string(), WorkflowAgentPresetSchema).optional(),
|
|
319
365
|
});
|
|
320
366
|
export const WorkflowStartResponseSchema = z.object({
|
|
321
367
|
type: z.literal("workflow.start.response"),
|
|
@@ -1184,8 +1230,25 @@ const WorkspaceStateBucketSchema = z.enum([
|
|
|
1184
1230
|
"failed",
|
|
1185
1231
|
"running",
|
|
1186
1232
|
"attention",
|
|
1233
|
+
// COMPAT(pendingBucket): added in 0.3.42. A settled agent that still owns
|
|
1234
|
+
// armed background work (monitor / cron / background shell / live subagent).
|
|
1235
|
+
"pending",
|
|
1187
1236
|
"done",
|
|
1188
1237
|
]);
|
|
1238
|
+
/**
|
|
1239
|
+
* Client-side tolerant form of {@link WorkspaceStateBucketSchema}.
|
|
1240
|
+
*
|
|
1241
|
+
* A newer daemon may send a bucket an older app build has never heard of. A
|
|
1242
|
+
* bare `z.enum` THROWS on that, which fails the whole workspace-descriptor
|
|
1243
|
+
* parse and blanks the list — a total outage from an additive change. The
|
|
1244
|
+
* `.catch` degrades one field instead.
|
|
1245
|
+
*
|
|
1246
|
+
* The fallback is deliberately `running`, not `done`: an unknown bucket means
|
|
1247
|
+
* "this daemon knows about a state we don't", and the safe direction is to keep
|
|
1248
|
+
* the workspace VISIBLE rather than silently filing it under finished. Guessing
|
|
1249
|
+
* "done" would reproduce the exact class of bug the pending bucket exists to fix.
|
|
1250
|
+
*/
|
|
1251
|
+
const IncomingWorkspaceStateBucketSchema = WorkspaceStateBucketSchema.catch("running");
|
|
1189
1252
|
export const FetchWorkspacesRequestMessageSchema = z.object({
|
|
1190
1253
|
type: z.literal("fetch_workspaces_request"),
|
|
1191
1254
|
requestId: z.string(),
|
|
@@ -3126,7 +3189,7 @@ export const WorkspaceDescriptorPayloadSchema = z
|
|
|
3126
3189
|
// is derived from the branch/directory.
|
|
3127
3190
|
title: z.string().nullable().optional(),
|
|
3128
3191
|
archivingAt: z.string().nullable().optional().default(null),
|
|
3129
|
-
status:
|
|
3192
|
+
status: IncomingWorkspaceStateBucketSchema,
|
|
3130
3193
|
// Best-effort workspace status entry timestamp. Old daemons omit the
|
|
3131
3194
|
// field; old clients treat missing and null equivalently. The transform
|
|
3132
3195
|
// coerces a missing field to `null` so downstream code never has to
|
|
@@ -489,13 +489,14 @@ export declare const WSOutboundMessageSchema: {
|
|
|
489
489
|
name: import("zod").ZodString;
|
|
490
490
|
title: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
491
491
|
archivingAt: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>>;
|
|
492
|
-
status: import("zod").ZodEnum<{
|
|
492
|
+
status: import("zod").ZodCatch<import("zod").ZodEnum<{
|
|
493
493
|
running: "running";
|
|
494
494
|
attention: "attention";
|
|
495
495
|
needs_input: "needs_input";
|
|
496
496
|
failed: "failed";
|
|
497
|
+
pending: "pending";
|
|
497
498
|
done: "done";
|
|
498
|
-
}
|
|
499
|
+
}>>;
|
|
499
500
|
statusEnteredAt: import("zod").ZodPipe<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, import("zod").ZodTransform<string | null, string | null | undefined>>;
|
|
500
501
|
activityAt: import("zod").ZodNullable<import("zod").ZodString>;
|
|
501
502
|
diffStat: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
|
|
@@ -673,7 +674,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
673
674
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
674
675
|
name: string;
|
|
675
676
|
archivingAt: string | null;
|
|
676
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
677
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
677
678
|
statusEnteredAt: string | null;
|
|
678
679
|
activityAt: string | null;
|
|
679
680
|
scripts: {
|
|
@@ -776,7 +777,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
776
777
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
777
778
|
name: string;
|
|
778
779
|
archivingAt: string | null;
|
|
779
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
780
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
780
781
|
statusEnteredAt: string | null;
|
|
781
782
|
activityAt: string | null;
|
|
782
783
|
scripts: {
|
|
@@ -1560,13 +1561,14 @@ export declare const WSOutboundMessageSchema: {
|
|
|
1560
1561
|
name: import("zod").ZodString;
|
|
1561
1562
|
title: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
1562
1563
|
archivingAt: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>>;
|
|
1563
|
-
status: import("zod").ZodEnum<{
|
|
1564
|
+
status: import("zod").ZodCatch<import("zod").ZodEnum<{
|
|
1564
1565
|
running: "running";
|
|
1565
1566
|
attention: "attention";
|
|
1566
1567
|
needs_input: "needs_input";
|
|
1567
1568
|
failed: "failed";
|
|
1569
|
+
pending: "pending";
|
|
1568
1570
|
done: "done";
|
|
1569
|
-
}
|
|
1571
|
+
}>>;
|
|
1570
1572
|
statusEnteredAt: import("zod").ZodPipe<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, import("zod").ZodTransform<string | null, string | null | undefined>>;
|
|
1571
1573
|
activityAt: import("zod").ZodNullable<import("zod").ZodString>;
|
|
1572
1574
|
diffStat: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
|
|
@@ -1744,7 +1746,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
1744
1746
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
1745
1747
|
name: string;
|
|
1746
1748
|
archivingAt: string | null;
|
|
1747
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
1749
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
1748
1750
|
statusEnteredAt: string | null;
|
|
1749
1751
|
activityAt: string | null;
|
|
1750
1752
|
scripts: {
|
|
@@ -1847,7 +1849,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
1847
1849
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
1848
1850
|
name: string;
|
|
1849
1851
|
archivingAt: string | null;
|
|
1850
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
1852
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
1851
1853
|
statusEnteredAt: string | null;
|
|
1852
1854
|
activityAt: string | null;
|
|
1853
1855
|
scripts: {
|
|
@@ -2005,13 +2007,14 @@ export declare const WSOutboundMessageSchema: {
|
|
|
2005
2007
|
name: import("zod").ZodString;
|
|
2006
2008
|
title: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
2007
2009
|
archivingAt: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>>;
|
|
2008
|
-
status: import("zod").ZodEnum<{
|
|
2010
|
+
status: import("zod").ZodCatch<import("zod").ZodEnum<{
|
|
2009
2011
|
running: "running";
|
|
2010
2012
|
attention: "attention";
|
|
2011
2013
|
needs_input: "needs_input";
|
|
2012
2014
|
failed: "failed";
|
|
2015
|
+
pending: "pending";
|
|
2013
2016
|
done: "done";
|
|
2014
|
-
}
|
|
2017
|
+
}>>;
|
|
2015
2018
|
statusEnteredAt: import("zod").ZodPipe<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, import("zod").ZodTransform<string | null, string | null | undefined>>;
|
|
2016
2019
|
activityAt: import("zod").ZodNullable<import("zod").ZodString>;
|
|
2017
2020
|
diffStat: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
|
|
@@ -2189,7 +2192,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
2189
2192
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
2190
2193
|
name: string;
|
|
2191
2194
|
archivingAt: string | null;
|
|
2192
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
2195
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
2193
2196
|
statusEnteredAt: string | null;
|
|
2194
2197
|
activityAt: string | null;
|
|
2195
2198
|
scripts: {
|
|
@@ -2292,7 +2295,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
2292
2295
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
2293
2296
|
name: string;
|
|
2294
2297
|
archivingAt: string | null;
|
|
2295
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
2298
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
2296
2299
|
statusEnteredAt: string | null;
|
|
2297
2300
|
activityAt: string | null;
|
|
2298
2301
|
scripts: {
|
|
@@ -3005,13 +3008,14 @@ export declare const WSOutboundMessageSchema: {
|
|
|
3005
3008
|
name: import("zod").ZodString;
|
|
3006
3009
|
title: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
3007
3010
|
archivingAt: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>>;
|
|
3008
|
-
status: import("zod").ZodEnum<{
|
|
3011
|
+
status: import("zod").ZodCatch<import("zod").ZodEnum<{
|
|
3009
3012
|
running: "running";
|
|
3010
3013
|
attention: "attention";
|
|
3011
3014
|
needs_input: "needs_input";
|
|
3012
3015
|
failed: "failed";
|
|
3016
|
+
pending: "pending";
|
|
3013
3017
|
done: "done";
|
|
3014
|
-
}
|
|
3018
|
+
}>>;
|
|
3015
3019
|
statusEnteredAt: import("zod").ZodPipe<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, import("zod").ZodTransform<string | null, string | null | undefined>>;
|
|
3016
3020
|
activityAt: import("zod").ZodNullable<import("zod").ZodString>;
|
|
3017
3021
|
diffStat: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
|
|
@@ -3189,7 +3193,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
3189
3193
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
3190
3194
|
name: string;
|
|
3191
3195
|
archivingAt: string | null;
|
|
3192
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
3196
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
3193
3197
|
statusEnteredAt: string | null;
|
|
3194
3198
|
activityAt: string | null;
|
|
3195
3199
|
scripts: {
|
|
@@ -3292,7 +3296,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
3292
3296
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
3293
3297
|
name: string;
|
|
3294
3298
|
archivingAt: string | null;
|
|
3295
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
3299
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
3296
3300
|
statusEnteredAt: string | null;
|
|
3297
3301
|
activityAt: string | null;
|
|
3298
3302
|
scripts: {
|
|
@@ -3475,6 +3479,17 @@ export declare const WSOutboundMessageSchema: {
|
|
|
3475
3479
|
}>;
|
|
3476
3480
|
title: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
3477
3481
|
labels: import("zod").ZodDefault<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodString>>;
|
|
3482
|
+
agentPresets: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodObject<{
|
|
3483
|
+
provider: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3484
|
+
model: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3485
|
+
modeId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3486
|
+
systemPrompt: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3487
|
+
thinkingOptionId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3488
|
+
approvalPolicy: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3489
|
+
sandboxMode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3490
|
+
networkAccess: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
3491
|
+
webSearch: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
3492
|
+
}, import("zod/v4/core").$strict>>>;
|
|
3478
3493
|
phases: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodObject<{
|
|
3479
3494
|
id: import("zod").ZodString;
|
|
3480
3495
|
title: import("zod").ZodString;
|
|
@@ -3514,6 +3529,17 @@ export declare const WSOutboundMessageSchema: {
|
|
|
3514
3529
|
}>;
|
|
3515
3530
|
title: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
3516
3531
|
labels: import("zod").ZodDefault<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodString>>;
|
|
3532
|
+
agentPresets: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodObject<{
|
|
3533
|
+
provider: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3534
|
+
model: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3535
|
+
modeId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3536
|
+
systemPrompt: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3537
|
+
thinkingOptionId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3538
|
+
approvalPolicy: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3539
|
+
sandboxMode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3540
|
+
networkAccess: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
3541
|
+
webSearch: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
3542
|
+
}, import("zod/v4/core").$strict>>>;
|
|
3517
3543
|
phases: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodObject<{
|
|
3518
3544
|
id: import("zod").ZodString;
|
|
3519
3545
|
title: import("zod").ZodString;
|
|
@@ -3553,6 +3579,17 @@ export declare const WSOutboundMessageSchema: {
|
|
|
3553
3579
|
}>;
|
|
3554
3580
|
title: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
3555
3581
|
labels: import("zod").ZodDefault<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodString>>;
|
|
3582
|
+
agentPresets: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodObject<{
|
|
3583
|
+
provider: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3584
|
+
model: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3585
|
+
modeId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3586
|
+
systemPrompt: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3587
|
+
thinkingOptionId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3588
|
+
approvalPolicy: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3589
|
+
sandboxMode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
3590
|
+
networkAccess: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
3591
|
+
webSearch: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
3592
|
+
}, import("zod/v4/core").$strict>>>;
|
|
3556
3593
|
phases: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodObject<{
|
|
3557
3594
|
id: import("zod").ZodString;
|
|
3558
3595
|
title: import("zod").ZodString;
|
|
@@ -5009,13 +5046,14 @@ export declare const WSOutboundMessageSchema: {
|
|
|
5009
5046
|
name: import("zod").ZodString;
|
|
5010
5047
|
title: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
5011
5048
|
archivingAt: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>>;
|
|
5012
|
-
status: import("zod").ZodEnum<{
|
|
5049
|
+
status: import("zod").ZodCatch<import("zod").ZodEnum<{
|
|
5013
5050
|
running: "running";
|
|
5014
5051
|
attention: "attention";
|
|
5015
5052
|
needs_input: "needs_input";
|
|
5016
5053
|
failed: "failed";
|
|
5054
|
+
pending: "pending";
|
|
5017
5055
|
done: "done";
|
|
5018
|
-
}
|
|
5056
|
+
}>>;
|
|
5019
5057
|
statusEnteredAt: import("zod").ZodPipe<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, import("zod").ZodTransform<string | null, string | null | undefined>>;
|
|
5020
5058
|
activityAt: import("zod").ZodNullable<import("zod").ZodString>;
|
|
5021
5059
|
diffStat: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
|
|
@@ -5193,7 +5231,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
5193
5231
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
5194
5232
|
name: string;
|
|
5195
5233
|
archivingAt: string | null;
|
|
5196
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
5234
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
5197
5235
|
statusEnteredAt: string | null;
|
|
5198
5236
|
activityAt: string | null;
|
|
5199
5237
|
scripts: {
|
|
@@ -5296,7 +5334,7 @@ export declare const WSOutboundMessageSchema: {
|
|
|
5296
5334
|
workspaceKind: "worktree" | "checkout" | "directory" | "local_checkout";
|
|
5297
5335
|
name: string;
|
|
5298
5336
|
archivingAt: string | null;
|
|
5299
|
-
status: "running" | "attention" | "needs_input" | "failed" | "done";
|
|
5337
|
+
status: "running" | "attention" | "needs_input" | "failed" | "pending" | "done";
|
|
5300
5338
|
statusEnteredAt: string | null;
|
|
5301
5339
|
activityAt: string | null;
|
|
5302
5340
|
scripts: {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type LoopParamValues } from "../fleet/params.js";
|
|
2
|
+
import type { WorkflowAgentPreset, WorkflowTaskGraph } from "../messages.js";
|
|
3
|
+
import { type WorkflowDefinition } from "./definition.js";
|
|
4
|
+
/** Ambient run identity. Passed IN so the compiler stays a pure function of its
|
|
5
|
+
* arguments; the CLI stamps these. Never produced here. */
|
|
6
|
+
export interface WorkflowCompileSession {
|
|
7
|
+
id: string;
|
|
8
|
+
createdAt: string;
|
|
9
|
+
outputDirectory: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CompileWorkflowArgs {
|
|
12
|
+
definition: WorkflowDefinition;
|
|
13
|
+
values: LoopParamValues;
|
|
14
|
+
session: WorkflowCompileSession;
|
|
15
|
+
}
|
|
16
|
+
export interface CompiledWorkflow {
|
|
17
|
+
graph: WorkflowTaskGraph;
|
|
18
|
+
agentPresets: Record<string, WorkflowAgentPreset>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Compile one definition against one set of input values.
|
|
22
|
+
*
|
|
23
|
+
* Validates BEFORE it emits, and reports EVERY issue in one throw rather than stopping
|
|
24
|
+
* at the first: a definition can carry a bad input value, an undeclared token and an
|
|
25
|
+
* unknown agent name simultaneously, and three sequential throws would hide the second
|
|
26
|
+
* and third until the first is fixed. On any issue nothing is returned and no partial
|
|
27
|
+
* graph is observable.
|
|
28
|
+
*
|
|
29
|
+
* @throws {WorkflowDefinitionError} carrying the union of the value issues, the
|
|
30
|
+
* definition issues, and the unresolved-reference issues this module adds.
|
|
31
|
+
*/
|
|
32
|
+
export declare function compileWorkflowDefinition(args: CompileWorkflowArgs): CompiledWorkflow;
|
|
33
|
+
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { defaultLoopParams, validateLoopParams } from "../fleet/params.js";
|
|
2
|
+
import { createWorkflowTokenPattern, renderWorkflowInputValue, SUBSTITUTABLE_STEP_FIELDS, validateWorkflowDefinition, WorkflowDefinitionError, } from "./definition.js";
|
|
3
|
+
/**
|
|
4
|
+
* Compile one definition against one set of input values.
|
|
5
|
+
*
|
|
6
|
+
* Validates BEFORE it emits, and reports EVERY issue in one throw rather than stopping
|
|
7
|
+
* at the first: a definition can carry a bad input value, an undeclared token and an
|
|
8
|
+
* unknown agent name simultaneously, and three sequential throws would hide the second
|
|
9
|
+
* and third until the first is fixed. On any issue nothing is returned and no partial
|
|
10
|
+
* graph is observable.
|
|
11
|
+
*
|
|
12
|
+
* @throws {WorkflowDefinitionError} carrying the union of the value issues, the
|
|
13
|
+
* definition issues, and the unresolved-reference issues this module adds.
|
|
14
|
+
*/
|
|
15
|
+
export function compileWorkflowDefinition(args) {
|
|
16
|
+
const { definition, session, values } = args;
|
|
17
|
+
// Defaults on the LEFT so a supplied value always wins over a declared default.
|
|
18
|
+
// `defaultLoopParams` only emits a key when the field's `default` parses as a
|
|
19
|
+
// `LoopParamValue`, so a field with no default contributes nothing here - which is
|
|
20
|
+
// exactly the gap the declared-but-unresolved issue below closes.
|
|
21
|
+
const merged = {
|
|
22
|
+
...defaultLoopParams({ fields: definition.inputs }),
|
|
23
|
+
...values,
|
|
24
|
+
};
|
|
25
|
+
const declaredKeys = new Set(definition.inputs.map((field) => field.key));
|
|
26
|
+
const valueIssues = validateLoopParams({ fields: definition.inputs }, merged);
|
|
27
|
+
// Each of the three failure shapes has exactly ONE reporter. A required input that is
|
|
28
|
+
// missing is already located at `inputs[<key>]`, so the reference pass below stays
|
|
29
|
+
// silent about it rather than restating the same root cause at every step that
|
|
30
|
+
// mentions it.
|
|
31
|
+
const reportedKeys = new Set(valueIssues.map((issue) => issue.key));
|
|
32
|
+
const rendered = definition.steps.map((step) => renderStepFields({ step, values: merged, declaredKeys, reportedKeys }));
|
|
33
|
+
const issues = [
|
|
34
|
+
...valueIssues.map((issue) => ({
|
|
35
|
+
path: `inputs[${issue.key}]`,
|
|
36
|
+
message: issue.message,
|
|
37
|
+
})),
|
|
38
|
+
// Deliberately duplicated with `parseWorkflowDefinition`, and it stays: the two
|
|
39
|
+
// guard different entry points - a CLI that parsed a file, versus any caller
|
|
40
|
+
// invoking this compiler directly with a hand-built object.
|
|
41
|
+
...validateWorkflowDefinition(definition),
|
|
42
|
+
...rendered.flatMap((entry) => entry.issues),
|
|
43
|
+
];
|
|
44
|
+
if (issues.length > 0) {
|
|
45
|
+
throw new WorkflowDefinitionError(issues);
|
|
46
|
+
}
|
|
47
|
+
const graph = {
|
|
48
|
+
// What the manager's `title ?? graph.goal` default reads, so `--title` stays optional.
|
|
49
|
+
goal: definition.name,
|
|
50
|
+
// Ported ballast: the CLI's reusable master-prompt template. Zero readers on
|
|
51
|
+
// 25fe57635 (only the TS interface and the Zod schema mention it).
|
|
52
|
+
masterPrompt: "",
|
|
53
|
+
metadata: {
|
|
54
|
+
// Emitted EMPTY on purpose. `resolveExecutionLayers` honours a declared list only
|
|
55
|
+
// when non-empty, then falls through to Kahn layering over `dependencies`. A
|
|
56
|
+
// precomputed list here would be a second derivation that can disagree with `needs`.
|
|
57
|
+
executionLayers: [],
|
|
58
|
+
// Upper bound, not a cap - nothing enforces it. Zero readers.
|
|
59
|
+
maxParallelism: definition.steps.length,
|
|
60
|
+
totalTasks: definition.steps.length,
|
|
61
|
+
// Unknown. Zero readers.
|
|
62
|
+
estimatedDuration: 0,
|
|
63
|
+
// Per-file task generation is a CLI concept with no paseo reader.
|
|
64
|
+
perFileMode: false,
|
|
65
|
+
// `storyFormat` and `totalFiles` are omitted, not defaulted: both are optional and
|
|
66
|
+
// neither has a definition-side vocabulary, so `false`/`0` would be a claim where
|
|
67
|
+
// an absent key is honestly "not specified".
|
|
68
|
+
},
|
|
69
|
+
// Ambient run identity, supplied by the caller so this stays a pure function.
|
|
70
|
+
// `outputDirectory` has zero readers on 25fe57635 but is schema-required.
|
|
71
|
+
session,
|
|
72
|
+
tasks: rendered.map(buildTask),
|
|
73
|
+
};
|
|
74
|
+
// Shallow copy: a caller mutating the returned presets must not reach back into the
|
|
75
|
+
// definition. Populating them onto the wire is Story 3.3's job.
|
|
76
|
+
return { graph, agentPresets: { ...definition.agents } };
|
|
77
|
+
}
|
|
78
|
+
/** Substitute every token in one field's text, iterating Story 3.1's scanner. */
|
|
79
|
+
function substituteTokens(args) {
|
|
80
|
+
const issues = [];
|
|
81
|
+
// A FRESH pattern per call. A module-level `/g` regex carries `lastIndex` between
|
|
82
|
+
// calls, which would make the result depend on scan order.
|
|
83
|
+
const text = args.text.replace(createWorkflowTokenPattern(), (raw, body) => {
|
|
84
|
+
const name = body.trim();
|
|
85
|
+
if (!args.declaredKeys.has(name)) {
|
|
86
|
+
// Undeclared, or malformed (a body that is not a bare identifier is never a
|
|
87
|
+
// declared key). `validateWorkflowDefinition` already reports both, located at
|
|
88
|
+
// this same path, so reporting again here would double-count one mistake. The
|
|
89
|
+
// raw token is returned unrendered; the union above is non-empty, so the caller
|
|
90
|
+
// throws and this interim string is never observable.
|
|
91
|
+
return raw;
|
|
92
|
+
}
|
|
93
|
+
const value = args.values[name];
|
|
94
|
+
if (value === undefined) {
|
|
95
|
+
if (args.reportedKeys.has(name)) {
|
|
96
|
+
// Already located at `inputs[<name>]` by the value pass (required and missing).
|
|
97
|
+
return raw;
|
|
98
|
+
}
|
|
99
|
+
// Declared, referenced, and has no value. `validateLoopParams` cannot catch this
|
|
100
|
+
// (a non-required field with no value is legal to it) and Story 3.1 cannot
|
|
101
|
+
// (the input IS declared). Only the compiler knows the token is referenced.
|
|
102
|
+
// Reporting it is what keeps the token from rendering as "" or "undefined".
|
|
103
|
+
issues.push({
|
|
104
|
+
path: args.path,
|
|
105
|
+
message: `step "${args.stepId}" references ${raw}, which is a declared input with no value: supply --input ${name}=... or give the field a default`,
|
|
106
|
+
});
|
|
107
|
+
return raw;
|
|
108
|
+
}
|
|
109
|
+
return renderWorkflowInputValue(value);
|
|
110
|
+
});
|
|
111
|
+
return { text, issues };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Render every substitutable field of one step.
|
|
115
|
+
*
|
|
116
|
+
* Iterates `SUBSTITUTABLE_STEP_FIELDS` rather than a second hard-coded list, so this
|
|
117
|
+
* module and Story 3.1's validator cannot disagree about which fields accept a token.
|
|
118
|
+
* `id` and `needs` are absent from that constant on purpose: a topology that depends on
|
|
119
|
+
* runtime values could not be validated at authoring time.
|
|
120
|
+
*/
|
|
121
|
+
function renderStepFields(args) {
|
|
122
|
+
const fields = {};
|
|
123
|
+
const issues = [];
|
|
124
|
+
for (const field of SUBSTITUTABLE_STEP_FIELDS) {
|
|
125
|
+
const text = args.step[field];
|
|
126
|
+
if (text === undefined) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const result = substituteTokens({
|
|
130
|
+
text,
|
|
131
|
+
values: args.values,
|
|
132
|
+
declaredKeys: args.declaredKeys,
|
|
133
|
+
reportedKeys: args.reportedKeys,
|
|
134
|
+
path: `steps[${args.step.id}].${field}`,
|
|
135
|
+
stepId: args.step.id,
|
|
136
|
+
});
|
|
137
|
+
fields[field] = result.text;
|
|
138
|
+
issues.push(...result.issues);
|
|
139
|
+
}
|
|
140
|
+
return { step: args.step, fields, issues };
|
|
141
|
+
}
|
|
142
|
+
/** One task node per step, in definition order. */
|
|
143
|
+
function buildTask(rendered) {
|
|
144
|
+
const { fields, step } = rendered;
|
|
145
|
+
// `step.id` never carries a token, so a fallback that came from it needs no rendering.
|
|
146
|
+
const title = fields.title ?? step.id;
|
|
147
|
+
return {
|
|
148
|
+
id: step.id, // never substituted
|
|
149
|
+
dependencies: step.needs, // never substituted
|
|
150
|
+
// Falls back through the SUBSTITUTED title before the id, so a token in the title
|
|
151
|
+
// reaches the description rather than the description inheriting an unrendered one.
|
|
152
|
+
description: fields.description ?? title,
|
|
153
|
+
// `prompt` is required by `WorkflowStepSchema`, so `renderStepFields` always renders
|
|
154
|
+
// it; the fallback exists only to keep the expression total.
|
|
155
|
+
prompt: fields.prompt ?? step.prompt,
|
|
156
|
+
title,
|
|
157
|
+
// `""` is the schema-satisfying empty, and `outputFile` has no reader anywhere.
|
|
158
|
+
outputFile: fields.outputFile ?? "",
|
|
159
|
+
// Ported ballast from the bmad-workflow CLI. Verified zero readers on 25fe57635:
|
|
160
|
+
// the only occurrences of `parallelizable` in the tree are its two declarations.
|
|
161
|
+
parallelizable: true,
|
|
162
|
+
// Same: no reader. The definition has no duration vocabulary and this epic does not
|
|
163
|
+
// invent one.
|
|
164
|
+
estimatedMinutes: 0,
|
|
165
|
+
// Conditional spread so the key is ABSENT rather than present-with-`undefined`: the
|
|
166
|
+
// schema says optional, and absent is the honest encoding of "this step names no agent".
|
|
167
|
+
...(step.agent === undefined ? {} : { agentType: step.agent }),
|
|
168
|
+
// `targetFiles` is never emitted: the definition has no vocabulary for it and this
|
|
169
|
+
// epic does not invent one.
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=compile.js.map
|