@exaudeus/workrail 1.14.2 → 1.15.1
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/application/services/validation-engine.js +3 -3
- package/dist/manifest.json +36 -28
- package/dist/mcp/handler-factory.js +10 -1
- package/dist/mcp/handlers/v2-execution-helpers.js +1 -1
- package/dist/mcp/server.js +2 -0
- package/dist/mcp/tool-descriptions.js +30 -52
- package/dist/mcp/v2/tools.js +7 -1
- package/dist/mcp/v2-response-formatter.d.ts +1 -0
- package/dist/mcp/v2-response-formatter.js +200 -0
- package/dist/v2/durable-core/domain/prompt-renderer.js +55 -6
- package/dist/v2/durable-core/domain/reason-model.js +1 -1
- package/dist/v2/durable-core/schemas/artifacts/loop-control.d.ts +4 -4
- package/dist/v2/durable-core/schemas/artifacts/loop-control.js +5 -3
- package/dist/v2/usecases/console-routes.js +10 -0
- package/dist/v2/usecases/console-service.d.ts +8 -3
- package/dist/v2/usecases/console-service.js +421 -23
- package/dist/v2/usecases/console-types.d.ts +48 -0
- package/package.json +1 -1
- package/spec/workflow.schema.json +7 -3
- package/workflows/coding-task-workflow-agentic.json +9 -8
- package/workflows/design-thinking-workflow-autonomous.agentic.json +4 -4
- package/workflows/design-thinking-workflow.json +12 -12
- package/workflows/mr-review-workflow.agentic.json +2 -2
- package/workflows/mr-review-workflow.json +3 -3
- package/workflows/test-artifact-loop-control.json +4 -3
|
@@ -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
|
|
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':
|
package/dist/manifest.json
CHANGED
|
@@ -94,8 +94,8 @@
|
|
|
94
94
|
"bytes": 2030
|
|
95
95
|
},
|
|
96
96
|
"application/services/validation-engine.js": {
|
|
97
|
-
"sha256": "
|
|
98
|
-
"bytes":
|
|
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": "
|
|
586
|
-
"bytes":
|
|
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": "
|
|
690
|
-
"bytes":
|
|
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": "
|
|
818
|
-
"bytes":
|
|
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": "
|
|
834
|
-
"bytes":
|
|
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": "
|
|
898
|
-
"bytes":
|
|
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": "
|
|
1362
|
-
"bytes":
|
|
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": "
|
|
1370
|
-
"bytes":
|
|
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": "
|
|
1542
|
-
"bytes":
|
|
1549
|
+
"sha256": "f1201fe5ab9680b11959985bf6004adcd8227de74b8151a6b4457553d6394203",
|
|
1550
|
+
"bytes": 2792
|
|
1543
1551
|
},
|
|
1544
1552
|
"v2/durable-core/schemas/artifacts/loop-control.js": {
|
|
1545
|
-
"sha256": "
|
|
1546
|
-
"bytes":
|
|
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": "
|
|
2186
|
-
"bytes":
|
|
2193
|
+
"sha256": "317a54962044e3631bb5ce2647c6e8080c065ae0506da52ac4a2352954b9814f",
|
|
2194
|
+
"bytes": 2734
|
|
2187
2195
|
},
|
|
2188
2196
|
"v2/usecases/console-service.d.ts": {
|
|
2189
|
-
"sha256": "
|
|
2190
|
-
"bytes":
|
|
2197
|
+
"sha256": "88bf7eb84bad74c048f76038b0d2631d49f2256587e42907fe2df14fc58f67e1",
|
|
2198
|
+
"bytes": 1506
|
|
2191
2199
|
},
|
|
2192
2200
|
"v2/usecases/console-service.js": {
|
|
2193
|
-
"sha256": "
|
|
2194
|
-
"bytes":
|
|
2201
|
+
"sha256": "21e129a7eb43523ef10eb941849ca5383ce7c1f4ecbdf2150a11166982c24845",
|
|
2202
|
+
"bytes": 23404
|
|
2195
2203
|
},
|
|
2196
2204
|
"v2/usecases/console-types.d.ts": {
|
|
2197
|
-
"sha256": "
|
|
2198
|
-
"bytes":
|
|
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: '
|
|
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,
|
package/dist/mcp/server.js
CHANGED
|
@@ -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/');
|
|
@@ -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
|
-
|
|
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
|
|
74
|
-
2. When done, call continue_workflow
|
|
75
|
-
3.
|
|
76
|
-
4. Don't predict what comes next
|
|
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
|
|
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 (
|
|
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
|
-
|
|
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
|
|
116
|
-
- ackToken (required for advance): From
|
|
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
|
|
119
|
-
- output.notesMarkdown (
|
|
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
|
-
|
|
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
|
|
227
|
-
2. When done, call continue_workflow
|
|
228
|
-
3.
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
268
|
-
2. When done, call continue_workflow
|
|
269
|
-
3. Do NOT predict what comes next
|
|
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
|
-
|
|
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
|
|
285
|
-
- ackToken (required for advance): From
|
|
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 (
|
|
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
|
|
package/dist/mcp/v2/tools.js
CHANGED
|
@@ -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('
|
|
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
|
+
}
|