@exaudeus/workrail 1.14.1 → 1.15.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.
@@ -349,9 +349,9 @@ let ValidationEngine = ValidationEngine_1 = class ValidationEngine {
349
349
  switch (step.loop.type) {
350
350
  case 'while':
351
351
  case 'until':
352
- if (!step.loop.condition) {
353
- issues.push(`${step.loop.type} loop requires a condition`);
354
- suggestions.push(`Add a condition that evaluates to false (for while) or true (for until) to exit the loop`);
352
+ if (!step.loop.condition && !step.loop.conditionSource) {
353
+ issues.push(`${step.loop.type} loop requires a condition or conditionSource`);
354
+ suggestions.push(`Add a conditionSource (preferred) or a condition field to control loop exit`);
355
355
  }
356
356
  break;
357
357
  case 'for':
@@ -94,8 +94,8 @@
94
94
  "bytes": 2030
95
95
  },
96
96
  "application/services/validation-engine.js": {
97
- "sha256": "a2ad656656b8d2554d0a08f6e230c190c72939d11cdba329b8de268d9ad52584",
98
- "bytes": 31342
97
+ "sha256": "19d8d4e058bf27bd2869e96622544f7c342c934aae7b8e2d3371f4b0e71aa49a",
98
+ "bytes": 31378
99
99
  },
100
100
  "application/services/workflow-compiler.d.ts": {
101
101
  "sha256": "41d0643ae2f07e5ce77a6e02344b5ca5b3c26bde828fbb307528a2ae097ac9d5",
@@ -582,8 +582,8 @@
582
582
  "bytes": 838
583
583
  },
584
584
  "mcp/handler-factory.js": {
585
- "sha256": "8cc0d3e1a7871048b9033a90fb63b3dfd91148c16d22ac5336a767ed2d04a10b",
586
- "bytes": 3907
585
+ "sha256": "b9d0b1843530f042c2ef7d33ac614042ee4e775a084ea8de7a4572cacb0519db",
586
+ "bytes": 4349
587
587
  },
588
588
  "mcp/handlers/session.d.ts": {
589
589
  "sha256": "38926e69a0e4935d1dbcdc53848be9fff0e4d8f96827883da3216f217918fa82",
@@ -686,8 +686,8 @@
686
686
  "bytes": 5712
687
687
  },
688
688
  "mcp/handlers/v2-execution-helpers.js": {
689
- "sha256": "9ac62b0d64ea10a89b18e79a01b1f5b05d35e40eddcb7a9f93a3bcbe737e85b3",
690
- "bytes": 18751
689
+ "sha256": "59b6531ca1c0136335d41967b768af9b347f4167aa909ba77cb1bf5b5108e81c",
690
+ "bytes": 18725
691
691
  },
692
692
  "mcp/handlers/v2-execution.d.ts": {
693
693
  "sha256": "f76cd1bb6a6e25c5a37a1f5b01b1046f4afd41162b620f3be3861509e1fcd1d3",
@@ -814,8 +814,8 @@
814
814
  "bytes": 168
815
815
  },
816
816
  "mcp/server.js": {
817
- "sha256": "c29e4ad8a9ed43304654f59725a7dd50a6fe5cd4cde9e7db2678ae9a7ccd0557",
818
- "bytes": 12643
817
+ "sha256": "4ca61965fdf522e5cc839e26220491638f03053a12f23c4eaf000b54b50ab7ad",
818
+ "bytes": 12934
819
819
  },
820
820
  "mcp/tool-description-provider.d.ts": {
821
821
  "sha256": "1d46abc3112e11b68e57197e846f5708293ec9b2281fa71a9124ee2aad71e41b",
@@ -830,8 +830,8 @@
830
830
  "bytes": 132
831
831
  },
832
832
  "mcp/tool-descriptions.js": {
833
- "sha256": "1444469a7f3ac328573cc8af0cca347754e17fb184a832f78405fd4f21ed6350",
834
- "bytes": 17534
833
+ "sha256": "b689f4b8d83398a9ee7cf8ff5b36536bccd458b65040e801de3693937dc4aab6",
834
+ "bytes": 17639
835
835
  },
836
836
  "mcp/tool-factory.d.ts": {
837
837
  "sha256": "0fe3c6b863b2d7aef0c3d659ff54f3a9ee8a0a3c2005b6565d2f8ad517bc7211",
@@ -881,6 +881,14 @@
881
881
  "sha256": "e81dbbcf86f0f8c88edad0b27d78bc93acebd83e52f919cdf69f9c7906233bfc",
882
882
  "bytes": 2674
883
883
  },
884
+ "mcp/v2-response-formatter.d.ts": {
885
+ "sha256": "51d09b828d7dcfa1c82607d4f27030c8913b2c7502ee2fb65c0cfc7618916701",
886
+ "bytes": 81
887
+ },
888
+ "mcp/v2-response-formatter.js": {
889
+ "sha256": "a2e0b576e49bdf66272dcd56ce91f451456afc236e8957af5e574bb458b30727",
890
+ "bytes": 6949
891
+ },
884
892
  "mcp/v2/tool-registry.d.ts": {
885
893
  "sha256": "d4d4927728c3cab1c014661d499dd0119538371bc6c5e821a4cd31df7abebedf",
886
894
  "bytes": 408
@@ -894,8 +902,8 @@
894
902
  "bytes": 6567
895
903
  },
896
904
  "mcp/v2/tools.js": {
897
- "sha256": "0d55830445ed414f31f52fc2775ea631fe1cb3f91b04e4dda33850dd2d8572cd",
898
- "bytes": 7506
905
+ "sha256": "8534b0a7c08877b30022914f32b2e7b739aca4112f55762a56c89599df7fa3dd",
906
+ "bytes": 7875
899
907
  },
900
908
  "mcp/validation/bounded-json.d.ts": {
901
909
  "sha256": "82203ac6123d5c6989606c3b5405aaea99ab829c8958835f9ae3ba45b8bc8fd5",
@@ -1358,16 +1366,16 @@
1358
1366
  "bytes": 935
1359
1367
  },
1360
1368
  "v2/durable-core/domain/prompt-renderer.js": {
1361
- "sha256": "3dd32e6335bc1aabe24f2477312975af8ef548daf5c7aad5e7f6b4e7aa2f5a78",
1362
- "bytes": 9074
1369
+ "sha256": "2b086cfb9330221f05c29b6945390855e3bf0efaba8af84671793ad1b26d082b",
1370
+ "bytes": 12378
1363
1371
  },
1364
1372
  "v2/durable-core/domain/reason-model.d.ts": {
1365
1373
  "sha256": "650fcb2d9969a4e6123cccbd4913f4d57aeab21a19bb907aa1e11f95e5a95089",
1366
1374
  "bytes": 3762
1367
1375
  },
1368
1376
  "v2/durable-core/domain/reason-model.js": {
1369
- "sha256": "23421e96b87cc59fec1a9205979410d27b2607c5b5cb98302902d0bcf32dfe3d",
1370
- "bytes": 11820
1377
+ "sha256": "7fb414218faac148451a717c9e9a6a18e6aada92d003443d90dd895e7473f9e8",
1378
+ "bytes": 11933
1371
1379
  },
1372
1380
  "v2/durable-core/domain/recap-recovery.d.ts": {
1373
1381
  "sha256": "82e7b20a22d409f729ccf79d345c00a7e27f1898a465dfca4cd789ff7766a3d6",
@@ -1538,12 +1546,12 @@
1538
1546
  "bytes": 1728
1539
1547
  },
1540
1548
  "v2/durable-core/schemas/artifacts/loop-control.d.ts": {
1541
- "sha256": "2575028ca2f52f4562857edd76696f6a6cd57f7aaa916346b00c76f62fdec498",
1542
- "bytes": 2743
1549
+ "sha256": "f1201fe5ab9680b11959985bf6004adcd8227de74b8151a6b4457553d6394203",
1550
+ "bytes": 2792
1543
1551
  },
1544
1552
  "v2/durable-core/schemas/artifacts/loop-control.js": {
1545
- "sha256": "1e0b70991023554e0ea3c858517aee7ffd050ab695a2f31768c4ec3d8de1cf92",
1546
- "bytes": 2152
1553
+ "sha256": "8f0cb5a113d7700a2a0aca158a7463bd5528b40d2e16dc14d1596e997c5b3b0d",
1554
+ "bytes": 2243
1547
1555
  },
1548
1556
  "v2/durable-core/schemas/compiled-workflow/index.d.ts": {
1549
1557
  "sha256": "d909c13d0d46bba1dcd411a0c53e767cf7e4c8bc5206581344ca1e7315552d95",
@@ -2182,20 +2190,20 @@
2182
2190
  "bytes": 204
2183
2191
  },
2184
2192
  "v2/usecases/console-routes.js": {
2185
- "sha256": "336dfa1d5fc86889b68ae5363a9f7a5b7832064beada2fc0150cb32c7deb4598",
2186
- "bytes": 2196
2193
+ "sha256": "317a54962044e3631bb5ce2647c6e8080c065ae0506da52ac4a2352954b9814f",
2194
+ "bytes": 2734
2187
2195
  },
2188
2196
  "v2/usecases/console-service.d.ts": {
2189
- "sha256": "787b1e01e7e30354f56203822142e825069bd42fba476797df6672c96dd5b555",
2190
- "bytes": 1083
2197
+ "sha256": "88bf7eb84bad74c048f76038b0d2631d49f2256587e42907fe2df14fc58f67e1",
2198
+ "bytes": 1506
2191
2199
  },
2192
2200
  "v2/usecases/console-service.js": {
2193
- "sha256": "e3df9ceaf0fcca2e55f7625f4610a053629b360638f469446ab8f576d32be8a9",
2194
- "bytes": 7183
2201
+ "sha256": "21e129a7eb43523ef10eb941849ca5383ce7c1f4ecbdf2150a11166982c24845",
2202
+ "bytes": 23404
2195
2203
  },
2196
2204
  "v2/usecases/console-types.d.ts": {
2197
- "sha256": "84c4c839b5285f5a29d85b7b4188e7948f92be1f34e44618cc0c9c85a1c11a18",
2198
- "bytes": 1799
2205
+ "sha256": "8c2a66a2c3f5c317c9988853a75f04d83358b7ff98ece0d7861528ea4e23402d",
2206
+ "bytes": 3575
2199
2207
  },
2200
2208
  "v2/usecases/console-types.js": {
2201
2209
  "sha256": "d43aa81f5bc89faa359e0f97c814ba25155591ff078fbb9bfd40f8c7c9683230",
@@ -7,12 +7,21 @@ const types_js_1 = require("./types.js");
7
7
  const index_js_1 = require("./validation/index.js");
8
8
  const bounded_json_js_1 = require("./validation/bounded-json.js");
9
9
  const v2_execution_helpers_js_1 = require("./handlers/v2-execution-helpers.js");
10
+ const v2_response_formatter_js_1 = require("./v2-response-formatter.js");
11
+ const jsonResponsesOverride = process.env.WORKRAIL_JSON_RESPONSES === 'true';
10
12
  function toMcpResult(result) {
11
13
  switch (result.type) {
12
- case 'success':
14
+ case 'success': {
15
+ if (!jsonResponsesOverride) {
16
+ const nl = (0, v2_response_formatter_js_1.formatV2ExecutionResponse)(result.data);
17
+ if (nl !== null) {
18
+ return { content: [{ type: 'text', text: nl }] };
19
+ }
20
+ }
13
21
  return {
14
22
  content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }],
15
23
  };
24
+ }
16
25
  case 'error':
17
26
  return {
18
27
  content: [{
@@ -92,7 +92,7 @@ function mapTokenDecodeErrorToToolError(e) {
92
92
  const bech32mErr = e.details.bech32mError;
93
93
  if (bech32mErr.code === 'BECH32M_CHECKSUM_FAILED') {
94
94
  return (0, types_js_1.errNotRetryable)('TOKEN_INVALID_FORMAT', 'Token corrupted (bech32m checksum failed). Likely copy/paste error.', {
95
- suggestion: 'Copy the entire token string exactly as returned. Use triple-click to select the complete line.',
95
+ suggestion: 'Use the exact token string as returned. Do not truncate or modify it.',
96
96
  details: {
97
97
  errorType: 'corruption_detected',
98
98
  estimatedPosition: bech32mErr.position ?? null,
@@ -144,6 +144,8 @@ async function startServer() {
144
144
  directoryListing: ctx.v2.directoryListing,
145
145
  dataDir: ctx.v2.dataDir,
146
146
  sessionStore: ctx.v2.sessionStore,
147
+ snapshotStore: ctx.v2.snapshotStore,
148
+ pinnedWorkflowStore: ctx.v2.pinnedStore,
147
149
  });
148
150
  ctx.httpServer.mountRoutes((app) => mountConsoleRoutes(app, consoleService));
149
151
  console.error('[Console] v2 Console API routes mounted at /api/v2/');
@@ -229,6 +231,10 @@ async function startServer() {
229
231
  processSignals.on('SIGINT', () => shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGINT' }));
230
232
  processSignals.on('SIGTERM', () => shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGTERM' }));
231
233
  processSignals.on('SIGHUP', () => shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGHUP' }));
234
+ process.stdin.on('end', () => {
235
+ console.error('[MCP] stdin closed, initiating shutdown');
236
+ shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGHUP' });
237
+ });
232
238
  let shutdownStarted = false;
233
239
  shutdownEvents.onShutdown((event) => {
234
240
  if (shutdownStarted)
@@ -63,17 +63,15 @@ Remember: inspecting is read-only. Call start_workflow when ready to begin.`,
63
63
 
64
64
  The workflow represents the user's plan for this task. Each step will tell you exactly what to do. Your job is to execute each step's instructions and report back.
65
65
 
66
- What you'll receive:
67
- - pending.prompt: The first step's instructions — read this and do what it says
68
- - nextCall: A pre-built template for your next continue_workflow call (copy its params when done)
69
- - nextIntent: How to approach this step (usually "perform_pending_then_continue")
70
- - preferences: Execution mode settings (autonomy level, risk policy)
66
+ The response contains your first step's instructions as the main content, with tokens in a JSON code block at the end. The step title is the heading, and the step prompt is the body.
71
67
 
72
68
  What to do:
73
- 1. Read pending.prompt and execute the step exactly as described
74
- 2. When done, call continue_workflow using the params from nextCall (it has stateToken and ackToken pre-filled)
75
- 3. Optionally add output.notesMarkdown summarizing your work
76
- 4. Don't predict what comes next - the workflow will tell you
69
+ 1. Read the step instructions (the main body of the response) and execute them exactly
70
+ 2. When done, call continue_workflow with the stateToken and ackToken from the JSON block at the end
71
+ 3. Add output.notesMarkdown documenting your work (see notes guidance below)
72
+ 4. Don't predict what comes next the workflow will tell you
73
+
74
+ Notes guidance: Write output.notesMarkdown for a human reader who will reference it later. Include what you did, key decisions and trade-offs, what you produced (files, endpoints, test results), and anything notable (risks, open questions, things you deliberately skipped). Use markdown formatting. Be specific — names, paths, numbers. 10–30 lines is ideal; too short is worse than too long.
77
75
 
78
76
  Workspace anchoring: Pass workspacePath (the "Workspace:" path from your system parameters) so this session can be found by resume_session in future chats. Without it, session discovery may not work.
79
77
 
@@ -81,13 +79,13 @@ Context auto-loads: If you provide context at start, WorkRail remembers it. On f
81
79
  continue_workflow: `Get the next step in the workflow (WorkRail v2, feature-flagged).
82
80
 
83
81
  QUICK START — How to call back after completing a step:
84
- Copy the params from the "nextCall" field of the previous response. It has stateToken and ackToken pre-filled. Just add your output if desired.
82
+ Copy the stateToken and ackToken from the JSON code block at the end of the previous response. Just add your output.
85
83
 
86
84
  Two modes:
87
85
 
88
86
  ADVANCE (with ackToken):
89
87
  - "I completed the current step; give me the next one"
90
- - Requires: stateToken + ackToken (both provided in nextCall.params)
88
+ - Requires: stateToken + ackToken (from the JSON block in previous response)
91
89
  - Optional: output (your work summary), context (if facts changed)
92
90
  - Result: WorkRail advances to next step and returns it
93
91
 
@@ -101,22 +99,14 @@ Intent is auto-inferred: ackToken present → advance, ackToken absent → rehyd
101
99
  You can set intent explicitly if you prefer, but it's optional.
102
100
 
103
101
  Reading the response:
104
- - pending.prompt: The step's instructions what to do
105
- - nextCall: Pre-built template for your next call — how to proceed when done (null if workflow complete)
106
- - nextIntent: How to approach this step — execute it, confirm first, or continue working on it
107
-
108
- nextIntent values:
109
- - "perform_pending_then_continue": Execute this step, then use nextCall to advance
110
- - "await_user_confirmation": Auto-confirm and proceed (you don't need to wait for user in agent mode)
111
- - "rehydrate_only": You just recovered state; continue working on the current step, then use nextCall
112
- - "complete": Workflow finished; nextCall is null
102
+ The response is natural language with your step instructions as the main content. A JSON code block at the end contains the tokens for your next call. The response tells you directly what to do — execute the step, retry with corrections, wait for user input, or acknowledge completion.
113
103
 
114
104
  Parameters:
115
- - stateToken (required): From nextCall.params or previous response
116
- - ackToken (required for advance): From nextCall.params or previous response
105
+ - stateToken (required): From the JSON block in the previous response
106
+ - ackToken (required for advance): From the JSON block in the previous response
117
107
  - intent (optional): "advance" or "rehydrate" — auto-inferred from ackToken if omitted
118
- - context (optional): NEW facts only. Omit if unchanged - WorkRail auto-loads previous context
119
- - output.notesMarkdown (optional, advance only): Fresh summary of THIS step only - never accumulated
108
+ - context (optional): NEW facts only. Omit if unchanged WorkRail auto-loads previous context
109
+ - output.notesMarkdown (advance only): Recap of THIS step what you did, key decisions, what you produced, anything notable. Write for a human reviewer. Use markdown, be specific (names, paths, numbers). 10–30 lines; never accumulate previous steps.
120
110
 
121
111
  The workflow is the user's structured instructions. Follow each step exactly as described.`,
122
112
  checkpoint_workflow: `Save a checkpoint on the current workflow step (WorkRail v2, feature-flagged).
@@ -216,18 +206,14 @@ This is read-only. Call start_workflow when ready to commit to following the wor
216
206
 
217
207
  The workflow is the USER'S VOICE expressing their plan for this task. Each step is a DIRECT INSTRUCTION from the user (or workflow author representing user intent). You MUST execute each step exactly as specified.
218
208
 
219
- What you receive:
220
- - pending.prompt: The user's first instruction — execute this EXACTLY as described
221
- - nextCall: Pre-built template for your next continue_workflow call — copy its params when done
222
- - nextIntent: How to approach this step (execute, confirm, etc.)
223
- - preferences: User's execution mode preferences (autonomy, risk tolerance)
209
+ The response contains your first step's instructions as the main content (heading + body), with tokens in a JSON code block at the end.
224
210
 
225
211
  REQUIRED BEHAVIOR:
226
- 1. Execute the pending step EXACTLY as the prompt describes
227
- 2. When done, call continue_workflow using the params from nextCall (stateToken and ackToken are pre-filled)
228
- 3. Optionally add output.notesMarkdown summarizing your work
212
+ 1. Execute the step instructions (the main body of the response) EXACTLY as described
213
+ 2. When done, call continue_workflow with the stateToken and ackToken from the JSON block at the end
214
+ 3. Add output.notesMarkdown documenting your work — write for a human reader who will reference it later. Include what you did, key decisions/trade-offs, what you produced (files, endpoints, test results), and anything notable (risks, open questions, deliberate omissions). Use markdown formatting, be specific (names, paths, numbers). 10–30 lines; too short is worse than too long.
229
215
  4. Round-trip tokens UNCHANGED (don't decode, inspect, or modify them)
230
- 5. Follow the workflow to completion - don't improvise alternative approaches
216
+ 5. Follow the workflow to completion don't improvise alternative approaches
231
217
 
232
218
  Workspace anchoring (IMPORTANT):
233
219
  - Pass workspacePath set to the "Workspace:" value from your system parameters
@@ -240,15 +226,15 @@ Context handling:
240
226
  - Only pass context again if facts have CHANGED (e.g., user provided new information)`,
241
227
  continue_workflow: `Get your next INSTRUCTION from the workflow (WorkRail v2, feature-flagged).
242
228
 
243
- The workflow represents the USER'S PLAN. The pending step returned is a DIRECT INSTRUCTION you MUST follow.
229
+ The workflow represents the USER'S PLAN. The step returned is a DIRECT INSTRUCTION you MUST follow.
244
230
 
245
- HOW TO CALL — Copy nextCall.params from the previous response. It has stateToken and ackToken pre-filled. Add output if desired.
231
+ HOW TO CALL — Copy the stateToken and ackToken from the JSON code block at the end of the previous response. Add output if desired.
246
232
 
247
233
  Two modes:
248
234
 
249
235
  ADVANCE (with ackToken):
250
236
  - Purpose: "I completed the current step; give me the next instruction"
251
- - Requires: stateToken + ackToken (both in nextCall.params from previous response)
237
+ - Requires: stateToken + ackToken (from the JSON block in the previous response)
252
238
  - Optional: output (your work summary), context (if facts changed)
253
239
  - Result: WorkRail advances to next step
254
240
  - Idempotent: Safe to retry with same tokens if unsure
@@ -264,29 +250,21 @@ Intent is auto-inferred: ackToken present → advance, ackToken absent → rehyd
264
250
  You can set intent explicitly if you prefer, but it's optional.
265
251
 
266
252
  REQUIRED BEHAVIOR:
267
- 1. Execute the step EXACTLY as specified in pending.prompt
268
- 2. When done, call continue_workflow using nextCall.params — do NOT construct params manually
269
- 3. Do NOT predict what comes next - call continue_workflow and the workflow will tell you
253
+ 1. Execute the step EXACTLY as described in the response body
254
+ 2. When done, call continue_workflow with tokens from the JSON block — do NOT construct params manually
255
+ 3. Do NOT predict what comes next call continue_workflow and the workflow will tell you
270
256
  4. Do NOT skip steps, combine steps, or improvise your own approach
271
257
 
272
258
  Reading the response:
273
- - pending.prompt: The step's instructions WHAT to do
274
- - nextCall: Pre-built call template — HOW to proceed when done (null if complete)
275
- - nextIntent: Step disposition — HOW to approach this step
276
-
277
- nextIntent is PRESCRIPTIVE (not advisory):
278
- - "perform_pending_then_continue": Execute this step, then use nextCall to advance
279
- - "await_user_confirmation": Auto-confirm and proceed (workflow represents user's intent)
280
- - "rehydrate_only": State recovery occurred; continue working on current step, then use nextCall
281
- - "complete": Workflow finished; nextCall is null
259
+ The response is natural language. The step instructions are the main content (heading + body). A JSON code block at the end has the tokens for your next call. The response tells you directly what to do — execute the step, retry with corrections, wait for user input, or acknowledge completion.
282
260
 
283
261
  Parameters:
284
- - stateToken (required): From nextCall.params or previous response
285
- - ackToken (required for advance): From nextCall.params or previous response
262
+ - stateToken (required): From the JSON block in the previous response
263
+ - ackToken (required for advance): From the JSON block in the previous response
286
264
  - intent (optional): "advance" or "rehydrate" — auto-inferred from ackToken if omitted
287
265
  - context (optional): NEW facts only (auto-merges with previous). Omit if unchanged
288
- - output.notesMarkdown (optional, advance only): Summary of THIS step only (fresh, never accumulated)
289
-
266
+ - output.notesMarkdown (advance only): Recap of THIS step what you did, key decisions, what you produced, anything notable. Write for a human reviewer. Use markdown, be specific (names, paths, numbers). 10–30 lines; never accumulate previous steps.
267
+
290
268
  The workflow is the user's structured will. Follow it exactly — it may validate, loop, or branch in ways you don't predict.`,
291
269
  checkpoint_workflow: `Save a checkpoint on the current workflow step (WorkRail v2, feature-flagged).
292
270
 
@@ -24,7 +24,13 @@ exports.V2ContinueWorkflowInputShape = zod_1.z.object({
24
24
  context: zod_1.z.record(zod_1.z.unknown()).optional().describe('External facts (only if CHANGED since last call). Omit this entirely if no facts changed. WorkRail auto-merges with previous context. Example: if context={branch:"main"} at start, do NOT re-pass it unless branch changed. Pass only NEW or OVERRIDDEN values.'),
25
25
  output: zod_1.z
26
26
  .object({
27
- notesMarkdown: zod_1.z.string().min(1).optional().describe('Summary of work completed in THIS step only — fresh and specific to this step. Do NOT append previous step notes. WorkRail concatenates notes across steps automatically. WRONG: "Phase 0: planning. Phase 1: implemented." RIGHT: "Implemented OAuth2 with 3 endpoints; added token validation middleware." Aim for ≤10 lines.'),
27
+ notesMarkdown: zod_1.z.string().min(1).optional().describe('Recap of THIS step only (WorkRail concatenates across steps automatically never repeat earlier notes). ' +
28
+ 'Write for a human reader who will review your work later. Include: ' +
29
+ '(1) What you did and the key decisions/trade-offs made, ' +
30
+ '(2) What you found or produced (files changed, endpoints added, test results, etc.), ' +
31
+ '(3) Anything the reader should know (risks, open questions, things you chose NOT to do and why). ' +
32
+ 'Use markdown: headings, bullet lists, bold for emphasis. Be specific — names, paths, numbers, not vague summaries. ' +
33
+ 'Good length: 10–30 lines. Too short is worse than too long.'),
28
34
  artifacts: zod_1.z.array(zod_1.z.unknown()).optional().describe('Optional structured artifacts (schema is workflow/contract-defined)'),
29
35
  })
30
36
  .optional()
@@ -0,0 +1 @@
1
+ export declare function formatV2ExecutionResponse(data: unknown): string | null;
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatV2ExecutionResponse = formatV2ExecutionResponse;
4
+ function isV2ExecutionResponse(data) {
5
+ if (typeof data !== 'object' || data === null)
6
+ return false;
7
+ const d = data;
8
+ return (typeof d.stateToken === 'string' &&
9
+ 'pending' in d &&
10
+ typeof d.nextIntent === 'string' &&
11
+ typeof d.preferences === 'object' && d.preferences !== null);
12
+ }
13
+ function isBlocked(data) {
14
+ return 'kind' in data && data.kind === 'blocked';
15
+ }
16
+ const AUTONOMY_LABEL = {
17
+ guided: 'guided mode',
18
+ full_auto_stop_on_user_deps: 'full autonomy (stop on user deps)',
19
+ full_auto_never_stop: 'full autonomy (never stop)',
20
+ };
21
+ const RISK_LABEL = {
22
+ conservative: 'conservative risk',
23
+ balanced: 'balanced risk',
24
+ aggressive: 'aggressive risk',
25
+ };
26
+ function formatPreferences(prefs) {
27
+ const autonomy = AUTONOMY_LABEL[prefs.autonomy] ?? prefs.autonomy;
28
+ const risk = RISK_LABEL[prefs.riskPolicy] ?? prefs.riskPolicy;
29
+ return `Preferences: ${autonomy}, ${risk}.`;
30
+ }
31
+ const BLOCKER_HEADING = {
32
+ USER_ONLY_DEPENDENCY: 'User Input Required',
33
+ MISSING_REQUIRED_OUTPUT: 'Missing Required Output',
34
+ INVALID_REQUIRED_OUTPUT: 'Invalid Output',
35
+ MISSING_REQUIRED_NOTES: 'Missing Required Notes',
36
+ MISSING_CONTEXT_KEY: 'Missing Context',
37
+ CONTEXT_BUDGET_EXCEEDED: 'Context Budget Exceeded',
38
+ REQUIRED_CAPABILITY_UNKNOWN: 'Unknown Capability Required',
39
+ REQUIRED_CAPABILITY_UNAVAILABLE: 'Capability Unavailable',
40
+ INVARIANT_VIOLATION: 'Invariant Violation',
41
+ STORAGE_CORRUPTION_DETECTED: 'Storage Error',
42
+ };
43
+ const PERSONA_USER = '---------\nUSER\n---------';
44
+ const PERSONA_SYSTEM = '---------\nSYSTEM\n---------';
45
+ function formatTokenBlock(data) {
46
+ const params = {};
47
+ if (data.nextCall) {
48
+ params.stateToken = data.nextCall.params.stateToken;
49
+ if (data.nextCall.params.ackToken) {
50
+ params.ackToken = data.nextCall.params.ackToken;
51
+ }
52
+ }
53
+ else {
54
+ params.stateToken = data.stateToken;
55
+ }
56
+ const lines = [];
57
+ lines.push('```json');
58
+ lines.push(JSON.stringify(params));
59
+ lines.push('```');
60
+ if (data.checkpointToken) {
61
+ lines.push('');
62
+ lines.push(`Checkpoint token (for \`checkpoint_workflow\`): \`${data.checkpointToken}\``);
63
+ }
64
+ return lines.join('\n');
65
+ }
66
+ function formatComplete(_data) {
67
+ return [
68
+ PERSONA_SYSTEM,
69
+ '',
70
+ '# Workflow Complete',
71
+ '',
72
+ 'The workflow has finished. No further steps to execute.',
73
+ ].join('\n');
74
+ }
75
+ function formatBlocked(data) {
76
+ if (data.retryable) {
77
+ return formatBlockedRetryable(data);
78
+ }
79
+ return formatBlockedNonRetryable(data);
80
+ }
81
+ function formatBlockedRetryable(data) {
82
+ const firstBlocker = data.blockers.blockers[0];
83
+ const heading = firstBlocker ? (BLOCKER_HEADING[firstBlocker.code] ?? firstBlocker.code) : 'Blocked';
84
+ const lines = [];
85
+ lines.push(PERSONA_SYSTEM);
86
+ lines.push('');
87
+ lines.push(`# Blocked: ${heading}`);
88
+ if (data.pending)
89
+ lines.push(`<!-- stepId: ${data.pending.stepId} -->`);
90
+ lines.push('');
91
+ for (const b of data.blockers.blockers) {
92
+ lines.push(b.message);
93
+ if (b.suggestedFix) {
94
+ lines.push('');
95
+ lines.push(`**What to do:** ${b.suggestedFix}`);
96
+ }
97
+ lines.push('');
98
+ }
99
+ if (data.validation) {
100
+ if (data.validation.issues.length > 0) {
101
+ lines.push('**Issues:**');
102
+ for (const issue of data.validation.issues)
103
+ lines.push(`- ${issue}`);
104
+ lines.push('');
105
+ }
106
+ if (data.validation.suggestions.length > 0) {
107
+ lines.push('**Suggestions:**');
108
+ for (const s of data.validation.suggestions)
109
+ lines.push(`- ${s}`);
110
+ lines.push('');
111
+ }
112
+ }
113
+ lines.push('Retry with corrected output:');
114
+ lines.push('');
115
+ lines.push(formatTokenBlock(data));
116
+ return lines.join('\n');
117
+ }
118
+ function formatBlockedNonRetryable(data) {
119
+ const firstBlocker = data.blockers.blockers[0];
120
+ const heading = firstBlocker ? (BLOCKER_HEADING[firstBlocker.code] ?? firstBlocker.code) : 'Blocked';
121
+ const lines = [];
122
+ lines.push(PERSONA_SYSTEM);
123
+ lines.push('');
124
+ lines.push(`# Blocked: ${heading}`);
125
+ if (data.pending)
126
+ lines.push(`<!-- stepId: ${data.pending.stepId} -->`);
127
+ lines.push('');
128
+ for (const b of data.blockers.blockers) {
129
+ lines.push(b.message);
130
+ if (b.suggestedFix) {
131
+ lines.push('');
132
+ lines.push(`**What to do:** ${b.suggestedFix}`);
133
+ }
134
+ lines.push('');
135
+ }
136
+ lines.push('You cannot proceed without resolving this. Inform the user and wait for their response, then call `continue_workflow` with the updated context.');
137
+ lines.push('');
138
+ lines.push(formatTokenBlock(data));
139
+ return lines.join('\n');
140
+ }
141
+ function formatRehydrate(data) {
142
+ const lines = [];
143
+ if (data.pending) {
144
+ lines.push(PERSONA_USER);
145
+ lines.push('');
146
+ lines.push(`# ${data.pending.title} (resumed)`);
147
+ lines.push(`<!-- stepId: ${data.pending.stepId} -->`);
148
+ lines.push('');
149
+ lines.push(data.pending.prompt);
150
+ lines.push('');
151
+ }
152
+ lines.push(PERSONA_SYSTEM);
153
+ lines.push('');
154
+ if (!data.pending) {
155
+ lines.push('# State Recovered');
156
+ lines.push('');
157
+ lines.push('No pending step. The workflow may be complete or waiting for external input.');
158
+ lines.push('');
159
+ }
160
+ lines.push('Continue working on this step. When done, call `continue_workflow` to advance.');
161
+ lines.push('');
162
+ lines.push(formatTokenBlock(data));
163
+ return lines.join('\n');
164
+ }
165
+ function formatSuccess(data) {
166
+ const lines = [];
167
+ if (data.pending) {
168
+ lines.push(PERSONA_USER);
169
+ lines.push('');
170
+ lines.push(`# ${data.pending.title}`);
171
+ lines.push(`<!-- stepId: ${data.pending.stepId} -->`);
172
+ lines.push('');
173
+ lines.push(data.pending.prompt);
174
+ lines.push('');
175
+ }
176
+ lines.push(PERSONA_SYSTEM);
177
+ lines.push('');
178
+ lines.push('Execute this step, then call `continue_workflow` to advance.');
179
+ lines.push('');
180
+ lines.push('Include `output.notesMarkdown` documenting your work — what you did, key decisions, what you produced, and anything notable.');
181
+ lines.push('');
182
+ lines.push(formatTokenBlock(data));
183
+ lines.push('');
184
+ lines.push(formatPreferences(data.preferences));
185
+ return lines.join('\n');
186
+ }
187
+ function formatV2ExecutionResponse(data) {
188
+ if (!isV2ExecutionResponse(data))
189
+ return null;
190
+ if (data.nextIntent === 'complete' && !data.pending) {
191
+ return formatComplete(data);
192
+ }
193
+ if (isBlocked(data)) {
194
+ return formatBlocked(data);
195
+ }
196
+ if (data.nextIntent === 'rehydrate_only') {
197
+ return formatRehydrate(data);
198
+ }
199
+ return formatSuccess(data);
200
+ }