@exaudeus/workrail 2.0.0 → 3.0.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.
Files changed (72) hide show
  1. package/dist/application/services/compiler/template-registry.d.ts +4 -2
  2. package/dist/application/services/compiler/template-registry.js +97 -5
  3. package/dist/application/services/workflow-compiler.d.ts +5 -1
  4. package/dist/application/services/workflow-compiler.js +20 -7
  5. package/dist/application/use-cases/raw-workflow-file-scanner.d.ts +1 -1
  6. package/dist/application/use-cases/raw-workflow-file-scanner.js +2 -0
  7. package/dist/application/use-cases/validate-workflow-registry.js +2 -1
  8. package/dist/config/feature-flags.js +8 -0
  9. package/dist/di/container.js +10 -1
  10. package/dist/di/tokens.d.ts +1 -0
  11. package/dist/di/tokens.js +1 -0
  12. package/dist/engine/engine-factory.d.ts +3 -0
  13. package/dist/engine/engine-factory.js +295 -0
  14. package/dist/engine/index.d.ts +3 -0
  15. package/dist/engine/index.js +12 -0
  16. package/dist/engine/types.d.ts +130 -0
  17. package/dist/engine/types.js +18 -0
  18. package/dist/infrastructure/storage/file-workflow-storage.d.ts +1 -0
  19. package/dist/infrastructure/storage/file-workflow-storage.js +18 -3
  20. package/dist/infrastructure/storage/workflow-resolution.d.ts +9 -6
  21. package/dist/infrastructure/storage/workflow-resolution.js +14 -1
  22. package/dist/manifest.json +166 -94
  23. package/dist/mcp/handlers/shared/request-workflow-reader.d.ts +19 -0
  24. package/dist/mcp/handlers/shared/request-workflow-reader.js +50 -0
  25. package/dist/mcp/handlers/v2-checkpoint.d.ts +31 -1
  26. package/dist/mcp/handlers/v2-checkpoint.js +76 -64
  27. package/dist/mcp/handlers/v2-execution/continue-advance.d.ts +2 -0
  28. package/dist/mcp/handlers/v2-execution/continue-advance.js +5 -5
  29. package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +2 -0
  30. package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +17 -22
  31. package/dist/mcp/handlers/v2-execution/index.d.ts +10 -17
  32. package/dist/mcp/handlers/v2-execution/index.js +44 -54
  33. package/dist/mcp/handlers/v2-execution/replay.d.ts +4 -15
  34. package/dist/mcp/handlers/v2-execution/replay.js +52 -128
  35. package/dist/mcp/handlers/v2-execution/start.d.ts +4 -3
  36. package/dist/mcp/handlers/v2-execution/start.js +32 -49
  37. package/dist/mcp/handlers/v2-token-ops.d.ts +45 -24
  38. package/dist/mcp/handlers/v2-token-ops.js +372 -32
  39. package/dist/mcp/handlers/v2-workflow.d.ts +1 -1
  40. package/dist/mcp/handlers/v2-workflow.js +25 -4
  41. package/dist/mcp/output-schemas.d.ts +104 -283
  42. package/dist/mcp/output-schemas.js +24 -22
  43. package/dist/mcp/server.js +8 -0
  44. package/dist/mcp/tool-descriptions.js +9 -2
  45. package/dist/mcp/types.d.ts +4 -0
  46. package/dist/mcp/v2/tools.d.ts +32 -53
  47. package/dist/mcp/v2/tools.js +27 -37
  48. package/dist/mcp/v2-response-formatter.js +12 -16
  49. package/dist/runtime/runtime-mode.d.ts +2 -0
  50. package/dist/v2/durable-core/domain/prompt-renderer.d.ts +1 -0
  51. package/dist/v2/durable-core/domain/prompt-renderer.js +5 -3
  52. package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +14 -14
  53. package/dist/v2/durable-core/schemas/session/events.d.ts +4 -4
  54. package/dist/v2/durable-core/schemas/session/validation-event.d.ts +2 -2
  55. package/dist/v2/durable-core/tokens/payloads.d.ts +32 -32
  56. package/dist/v2/durable-core/tokens/short-token.d.ts +38 -0
  57. package/dist/v2/durable-core/tokens/short-token.js +126 -0
  58. package/dist/v2/durable-core/tokens/token-patterns.d.ts +4 -0
  59. package/dist/v2/durable-core/tokens/token-patterns.js +9 -0
  60. package/dist/v2/infra/in-memory/token-alias-store/index.d.ts +11 -0
  61. package/dist/v2/infra/in-memory/token-alias-store/index.js +38 -0
  62. package/dist/v2/infra/local/data-dir/index.d.ts +1 -0
  63. package/dist/v2/infra/local/data-dir/index.js +3 -0
  64. package/dist/v2/infra/local/token-alias-store/index.d.ts +16 -0
  65. package/dist/v2/infra/local/token-alias-store/index.js +117 -0
  66. package/dist/v2/ports/data-dir.port.d.ts +1 -0
  67. package/dist/v2/ports/token-alias-store.port.d.ts +33 -0
  68. package/dist/v2/ports/token-alias-store.port.js +2 -0
  69. package/package.json +8 -1
  70. package/workflows/coding-task-workflow-agentic.lean.v2.json +224 -0
  71. package/workflows/routines/philosophy-alignment.json +12 -12
  72. package/workflows/routines/tension-driven-design.json +63 -0
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleV2CheckpointWorkflow = handleV2CheckpointWorkflow;
4
+ exports.executeCheckpoint = executeCheckpoint;
4
5
  const neverthrow_1 = require("neverthrow");
5
6
  const types_js_1 = require("../types.js");
6
7
  const output_schemas_js_1 = require("../output-schemas.js");
@@ -13,19 +14,23 @@ const constants_js_1 = require("../../v2/durable-core/constants.js");
13
14
  function findNodeCreated(events, nodeId) {
14
15
  return events.find((e) => e.kind === constants_js_1.EVENT_KIND.NODE_CREATED && e.scope?.nodeId === String(nodeId));
15
16
  }
16
- function mintStateTokenForNode(originalNode, sessionId, runId, nodeId, tokenCodecPorts) {
17
+ function mintStateTokenForNode(originalNode, sessionId, runId, nodeId, tokenCodecPorts, aliasStore, entropy) {
17
18
  const wfRefRes = (0, workflow_hash_ref_js_1.deriveWorkflowHashRef)(originalNode.data.workflowHash);
18
19
  if (wfRefRes.isErr()) {
19
- return { ok: false, error: { kind: 'precondition_failed', message: 'Cannot derive workflowHashRef for stateToken.' } };
20
+ return (0, neverthrow_1.errAsync)({ kind: 'precondition_failed', message: 'Cannot derive workflowHashRef for stateToken.' });
20
21
  }
21
- const stateTokenRes = (0, v2_token_ops_js_1.signTokenOrErr)({
22
- payload: { tokenVersion: 1, tokenKind: 'state', sessionId, runId, nodeId, workflowHashRef: wfRefRes.value },
22
+ return (0, v2_token_ops_js_1.mintSingleShortToken)({
23
+ kind: 'state',
24
+ entry: {
25
+ sessionId: String(sessionId),
26
+ runId: String(runId),
27
+ nodeId: String(nodeId),
28
+ workflowHashRef: String(wfRefRes.value),
29
+ },
23
30
  ports: tokenCodecPorts,
24
- });
25
- if (stateTokenRes.isErr()) {
26
- return { ok: false, error: { kind: 'token_signing_failed', cause: stateTokenRes.error } };
27
- }
28
- return { ok: true, value: stateTokenRes.value };
31
+ aliasStore,
32
+ entropy,
33
+ }).mapErr((failure) => ({ kind: 'token_signing_failed', cause: failure }));
29
34
  }
30
35
  function validateEvents(rawEvents) {
31
36
  const validated = [];
@@ -48,65 +53,68 @@ async function handleV2CheckpointWorkflow(input, ctx) {
48
53
  return executeCheckpoint(input, guard.ctx).match((payload) => (0, types_js_1.success)(payload), (e) => mapCheckpointErrorToToolError(e));
49
54
  }
50
55
  function executeCheckpoint(input, ctx) {
51
- const { gate, sessionStore, tokenCodecPorts, idFactory } = ctx.v2;
52
- const tokenRes = (0, v2_token_ops_js_1.parseCheckpointTokenOrFail)(input.checkpointToken, tokenCodecPorts);
53
- if (!tokenRes.ok) {
54
- return (0, neverthrow_1.errAsync)({ kind: 'validation_failed', failure: tokenRes.failure });
55
- }
56
- const token = tokenRes.token;
57
- const sessionId = (0, index_js_1.asSessionId)(String(token.payload.sessionId));
58
- const runId = (0, index_js_1.asRunId)(String(token.payload.runId));
59
- const nodeId = (0, index_js_1.asNodeId)(String(token.payload.nodeId));
60
- const attemptId = (0, index_js_1.asAttemptId)(String(token.payload.attemptId));
61
- const dedupeKey = `checkpoint:${String(sessionId)}:${String(runId)}:${String(nodeId)}:${String(attemptId)}`;
62
- return sessionStore.load(sessionId)
63
- .mapErr((cause) => ({ kind: 'store_failed', cause }))
64
- .andThen((truth) => {
65
- const originalNode = findNodeCreated(truth.events, nodeId);
66
- if (!originalNode) {
67
- return (0, neverthrow_1.errAsync)({ kind: 'missing_node_or_run' });
68
- }
69
- const alreadyRecorded = truth.events.some((e) => e.dedupeKey === dedupeKey);
70
- if (alreadyRecorded) {
71
- return replayCheckpoint(truth.events, dedupeKey, originalNode, sessionId, runId, nodeId, tokenCodecPorts);
72
- }
73
- return gate.withHealthySessionLock(sessionId, (lock) => {
74
- return sessionStore.load(sessionId)
75
- .mapErr((cause) => ({ kind: 'store_failed', cause }))
76
- .andThen((truthLocked) => {
77
- const originalNodeLocked = findNodeCreated(truthLocked.events, nodeId);
78
- if (!originalNodeLocked) {
79
- return (0, neverthrow_1.errAsync)({ kind: 'missing_node_or_run' });
80
- }
81
- const alreadyRecordedLocked = truthLocked.events.some((e) => e.dedupeKey === dedupeKey);
82
- if (alreadyRecordedLocked) {
83
- return replayCheckpoint(truthLocked.events, dedupeKey, originalNodeLocked, sessionId, runId, nodeId, tokenCodecPorts);
56
+ const { gate, sessionStore, tokenCodecPorts, idFactory, tokenAliasStore, entropy } = ctx.v2;
57
+ return (0, v2_token_ops_js_1.parseCheckpointTokenOrFail)(input.checkpointToken, tokenCodecPorts, tokenAliasStore)
58
+ .mapErr((failure) => ({ kind: 'validation_failed', failure }))
59
+ .andThen((token) => {
60
+ const sessionId = (0, index_js_1.asSessionId)(String(token.payload.sessionId));
61
+ const runId = (0, index_js_1.asRunId)(String(token.payload.runId));
62
+ const nodeId = (0, index_js_1.asNodeId)(String(token.payload.nodeId));
63
+ const attemptId = (0, index_js_1.asAttemptId)(String(token.payload.attemptId));
64
+ const dedupeKey = `checkpoint:${String(sessionId)}:${String(runId)}:${String(nodeId)}:${String(attemptId)}`;
65
+ return sessionStore.load(sessionId)
66
+ .mapErr((cause) => ({ kind: 'store_failed', cause }))
67
+ .andThen((truth) => {
68
+ const originalNode = findNodeCreated(truth.events, nodeId);
69
+ if (!originalNode) {
70
+ return (0, neverthrow_1.errAsync)({ kind: 'missing_node_or_run' });
71
+ }
72
+ const alreadyRecorded = truth.events.some((e) => e.dedupeKey === dedupeKey);
73
+ if (alreadyRecorded) {
74
+ return replayCheckpoint(truth.events, dedupeKey, originalNode, sessionId, runId, nodeId, attemptId, tokenCodecPorts, tokenAliasStore, entropy);
75
+ }
76
+ return gate.withHealthySessionLock(sessionId, (lock) => {
77
+ return sessionStore.load(sessionId)
78
+ .mapErr((cause) => ({ kind: 'store_failed', cause }))
79
+ .andThen((truthLocked) => {
80
+ const originalNodeLocked = findNodeCreated(truthLocked.events, nodeId);
81
+ if (!originalNodeLocked) {
82
+ return (0, neverthrow_1.errAsync)({ kind: 'missing_node_or_run' });
83
+ }
84
+ const alreadyRecordedLocked = truthLocked.events.some((e) => e.dedupeKey === dedupeKey);
85
+ if (alreadyRecordedLocked) {
86
+ return replayCheckpoint(truthLocked.events, dedupeKey, originalNodeLocked, sessionId, runId, nodeId, attemptId, tokenCodecPorts, tokenAliasStore, entropy);
87
+ }
88
+ return writeCheckpoint(truthLocked, dedupeKey, originalNodeLocked, sessionId, runId, nodeId, attemptId, idFactory.mintNodeId(), () => idFactory.mintEventId(), lock, sessionStore, tokenCodecPorts, tokenAliasStore, entropy);
89
+ });
90
+ }).mapErr((gateErr) => {
91
+ if (isGateError(gateErr)) {
92
+ return { kind: 'gate_failed', cause: gateErr };
84
93
  }
85
- return writeCheckpoint(truthLocked, dedupeKey, originalNodeLocked, sessionId, runId, nodeId, idFactory.mintNodeId(), () => idFactory.mintEventId(), lock, sessionStore, tokenCodecPorts);
94
+ return gateErr;
86
95
  });
87
- }).mapErr((gateErr) => {
88
- if (isGateError(gateErr)) {
89
- return { kind: 'gate_failed', cause: gateErr };
90
- }
91
- return gateErr;
92
96
  });
93
97
  });
94
98
  }
95
- function replayCheckpoint(events, dedupeKey, originalNode, sessionId, runId, nodeId, tokenCodecPorts) {
99
+ function replayCheckpoint(events, dedupeKey, originalNode, sessionId, runId, nodeId, attemptId, tokenCodecPorts, aliasStore, entropy) {
96
100
  const existingCheckpointNode = events.find((e) => e.kind === constants_js_1.EVENT_KIND.NODE_CREATED && e.dedupeKey === `checkpoint_node:${dedupeKey}`);
97
101
  const checkpointNodeId = existingCheckpointNode
98
102
  ? String(existingCheckpointNode.scope?.nodeId ?? 'unknown')
99
103
  : 'unknown';
100
- const tokenResult = mintStateTokenForNode(originalNode, sessionId, runId, nodeId, tokenCodecPorts);
101
- if (!tokenResult.ok)
102
- return (0, neverthrow_1.errAsync)(tokenResult.error);
103
- return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2CheckpointWorkflowOutputSchema.parse({
104
+ const workflowHashRefRes = (0, workflow_hash_ref_js_1.deriveWorkflowHashRef)(originalNode.data.workflowHash);
105
+ const workflowHashRef = workflowHashRefRes.isOk() ? workflowHashRefRes.value : undefined;
106
+ return mintStateTokenForNode(originalNode, sessionId, runId, nodeId, tokenCodecPorts, aliasStore, entropy)
107
+ .andThen((stateTokenValue) => (0, v2_token_ops_js_1.mintContinueAndCheckpointTokens)({
108
+ entry: { sessionId: String(sessionId), runId: String(runId), nodeId: String(nodeId), attemptId: String(attemptId), workflowHashRef },
109
+ ports: tokenCodecPorts, aliasStore, entropy,
110
+ }).andThen(({ continueToken }) => (0, neverthrow_1.okAsync)(output_schemas_js_1.V2CheckpointWorkflowOutputSchema.parse({
104
111
  checkpointNodeId,
105
- stateToken: tokenResult.value,
106
- nextCall: { tool: 'continue_workflow', params: { intent: 'rehydrate', stateToken: tokenResult.value } },
107
- }));
112
+ stateToken: stateTokenValue,
113
+ nextCall: { tool: 'continue_workflow', params: { continueToken } },
114
+ }))))
115
+ .mapErr((e) => ({ kind: 'store_failed', cause: e }));
108
116
  }
109
- function writeCheckpoint(truth, dedupeKey, originalNode, sessionId, runId, nodeId, checkpointNodeId, mintEventId, lock, sessionStore, tokenCodecPorts) {
117
+ function writeCheckpoint(truth, dedupeKey, originalNode, sessionId, runId, nodeId, attemptId, checkpointNodeId, mintEventId, lock, sessionStore, tokenCodecPorts, aliasStore, entropy) {
110
118
  const nodeCreatedEventId = mintEventId();
111
119
  const edgeCreatedEventId = mintEventId();
112
120
  const rawEvents = [
@@ -156,14 +164,18 @@ function writeCheckpoint(truth, dedupeKey, originalNode, sessionId, runId, nodeI
156
164
  return sessionStore.append(lock, { events: validated, snapshotPins })
157
165
  .mapErr((cause) => ({ kind: 'store_failed', cause }))
158
166
  .andThen(() => {
159
- const tokenResult = mintStateTokenForNode(originalNode, sessionId, runId, nodeId, tokenCodecPorts);
160
- if (!tokenResult.ok)
161
- return (0, neverthrow_1.errAsync)(tokenResult.error);
162
- return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2CheckpointWorkflowOutputSchema.parse({
167
+ const workflowHashRefRes = (0, workflow_hash_ref_js_1.deriveWorkflowHashRef)(originalNode.data.workflowHash);
168
+ const workflowHashRef = workflowHashRefRes.isOk() ? workflowHashRefRes.value : undefined;
169
+ return mintStateTokenForNode(originalNode, sessionId, runId, nodeId, tokenCodecPorts, aliasStore, entropy)
170
+ .andThen((stateTokenValue) => (0, v2_token_ops_js_1.mintContinueAndCheckpointTokens)({
171
+ entry: { sessionId: String(sessionId), runId: String(runId), nodeId: String(nodeId), attemptId: String(attemptId), workflowHashRef },
172
+ ports: tokenCodecPorts, aliasStore, entropy,
173
+ }).andThen(({ continueToken }) => (0, neverthrow_1.okAsync)(output_schemas_js_1.V2CheckpointWorkflowOutputSchema.parse({
163
174
  checkpointNodeId: String(checkpointNodeId),
164
- stateToken: tokenResult.value,
165
- nextCall: { tool: 'continue_workflow', params: { intent: 'rehydrate', stateToken: tokenResult.value } },
166
- }));
175
+ stateToken: stateTokenValue,
176
+ nextCall: { tool: 'continue_workflow', params: { continueToken } },
177
+ }))))
178
+ .mapErr((e) => ({ kind: 'store_failed', cause: e }));
167
179
  });
168
180
  }
169
181
  function mapCheckpointErrorToToolError(e) {
@@ -26,4 +26,6 @@ export declare function handleAdvanceIntent(args: {
26
26
  readonly mintEventId: () => string;
27
27
  };
28
28
  readonly sha256: Sha256PortV2;
29
+ readonly aliasStore: import('../../../v2/ports/token-alias-store.port.js').TokenAliasStorePortV2;
30
+ readonly entropy: import('../../../v2/ports/random-entropy.port.js').RandomEntropyPortV2;
29
31
  }): RA<z.infer<typeof V2ContinueWorkflowOutputSchema>, ContinueWorkflowError>;
@@ -11,7 +11,7 @@ const constants_js_1 = require("../../../v2/durable-core/constants.js");
11
11
  const replay_js_1 = require("./replay.js");
12
12
  const advance_js_1 = require("./advance.js");
13
13
  function handleAdvanceIntent(args) {
14
- const { input, sessionId, runId, nodeId, attemptId, workflowHashRef, truth, gate, sessionStore, snapshotStore, pinnedStore, tokenCodecPorts, idFactory, sha256 } = args;
14
+ const { input, sessionId, runId, nodeId, attemptId, workflowHashRef, truth, gate, sessionStore, snapshotStore, pinnedStore, tokenCodecPorts, idFactory, sha256, aliasStore, entropy } = args;
15
15
  const dedupeKey = `advance_recorded:${sessionId}:${nodeId}:${attemptId}`;
16
16
  const runStarted = truth.events.find((e) => e.kind === constants_js_1.EVENT_KIND.RUN_STARTED && e.scope.runId === String(runId));
17
17
  if (!runStarted) {
@@ -85,12 +85,12 @@ function handleAdvanceIntent(args) {
85
85
  nodeId,
86
86
  workflowHash,
87
87
  attemptId,
88
- inputStateToken: input.stateToken,
89
- inputAckToken: input.ackToken,
90
88
  pinnedWorkflow,
91
89
  snapshotStore,
92
90
  sha256,
93
91
  tokenCodecPorts,
92
+ aliasStore,
93
+ entropy,
94
94
  });
95
95
  }
96
96
  return gate
@@ -162,12 +162,12 @@ function handleAdvanceIntent(args) {
162
162
  nodeId,
163
163
  workflowHash,
164
164
  attemptId,
165
- inputStateToken: input.stateToken,
166
- inputAckToken: input.ackToken,
167
165
  pinnedWorkflow,
168
166
  snapshotStore,
169
167
  sha256,
170
168
  tokenCodecPorts,
169
+ aliasStore,
170
+ entropy,
171
171
  });
172
172
  });
173
173
  });
@@ -19,4 +19,6 @@ export declare function handleRehydrateIntent(args: {
19
19
  readonly idFactory: {
20
20
  readonly mintAttemptId: () => import('../../../v2/durable-core/tokens/index.js').AttemptId;
21
21
  };
22
+ readonly aliasStore: import('../../../v2/ports/token-alias-store.port.js').TokenAliasStorePortV2;
23
+ readonly entropy: import('../../../v2/ports/random-entropy.port.js').RandomEntropyPortV2;
22
24
  }): RA<z.infer<typeof V2ContinueWorkflowOutputSchema>, ContinueWorkflowError>;
@@ -16,7 +16,7 @@ const v2_state_conversion_js_1 = require("../v2-state-conversion.js");
16
16
  const constants_js_1 = require("../../../v2/durable-core/constants.js");
17
17
  const index_js_2 = require("./index.js");
18
18
  function handleRehydrateIntent(args) {
19
- const { input, sessionId, runId, nodeId, workflowHashRef, truth, tokenCodecPorts, pinnedStore, snapshotStore, idFactory } = args;
19
+ const { input, sessionId, runId, nodeId, workflowHashRef, truth, tokenCodecPorts, pinnedStore, snapshotStore, idFactory, aliasStore, entropy } = args;
20
20
  const runStarted = truth.events.find((e) => e.kind === constants_js_1.EVENT_KIND.RUN_STARTED && e.scope.runId === String(runId));
21
21
  const workflowId = runStarted?.data.workflowId;
22
22
  if (!runStarted || typeof workflowId !== 'string' || workflowId.trim() === '') {
@@ -75,28 +75,24 @@ function handleRehydrateIntent(args) {
75
75
  const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: true, isComplete, pending: null });
76
76
  return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2ContinueWorkflowOutputSchema.parse({
77
77
  kind: 'ok',
78
- stateToken: input.stateToken,
79
78
  isComplete,
80
79
  pending: null,
81
80
  preferences,
82
81
  nextIntent,
83
- nextCall: (0, index_js_2.buildNextCall)({ stateToken: input.stateToken, ackToken: undefined, isComplete, pending: null }),
82
+ nextCall: null,
84
83
  }));
85
84
  }
86
85
  const attemptId = (0, v2_token_ops_js_1.newAttemptId)(idFactory);
87
- const ackTokenRes = (0, v2_token_ops_js_1.signTokenOrErr)({
88
- payload: { tokenVersion: 1, tokenKind: 'ack', sessionId, runId, nodeId, attemptId },
89
- ports: tokenCodecPorts,
90
- });
91
- if (ackTokenRes.isErr())
92
- return (0, neverthrow_1.errAsync)({ kind: 'token_signing_failed', cause: ackTokenRes.error });
93
- const checkpointTokenRes = (0, v2_token_ops_js_1.signTokenOrErr)({
94
- payload: { tokenVersion: 1, tokenKind: 'checkpoint', sessionId, runId, nodeId, attemptId },
95
- ports: tokenCodecPorts,
96
- });
97
- if (checkpointTokenRes.isErr())
98
- return (0, neverthrow_1.errAsync)({ kind: 'token_signing_failed', cause: checkpointTokenRes.error });
99
- return pinnedStore.get(workflowHash)
86
+ const entryBase = {
87
+ sessionId: String(sessionId),
88
+ runId: String(runId),
89
+ nodeId: String(nodeId),
90
+ attemptId: String(attemptId),
91
+ workflowHashRef: String(workflowHashRef),
92
+ };
93
+ return (0, v2_token_ops_js_1.mintContinueAndCheckpointTokens)({ entry: entryBase, ports: tokenCodecPorts, aliasStore, entropy })
94
+ .mapErr((failure) => ({ kind: 'token_signing_failed', cause: failure }))
95
+ .andThen(({ continueToken: continueTokenValue, checkpointToken: checkpointTokenValue }) => pinnedStore.get(workflowHash)
100
96
  .mapErr((cause) => ({ kind: 'pinned_workflow_store_failed', cause }))
101
97
  .andThen((pinned) => {
102
98
  if (!pinned)
@@ -131,15 +127,14 @@ function handleRehydrateIntent(args) {
131
127
  const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: true, isComplete, pending: meta });
132
128
  return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2ContinueWorkflowOutputSchema.parse({
133
129
  kind: 'ok',
134
- stateToken: input.stateToken,
135
- ackToken: ackTokenRes.value,
136
- checkpointToken: checkpointTokenRes.value,
130
+ continueToken: continueTokenValue,
131
+ checkpointToken: checkpointTokenValue,
137
132
  isComplete,
138
- pending: { stepId: meta.stepId, title: meta.title, prompt: meta.prompt },
133
+ pending: (0, output_schemas_js_1.toPendingStep)(meta),
139
134
  preferences,
140
135
  nextIntent,
141
- nextCall: (0, index_js_2.buildNextCall)({ stateToken: input.stateToken, ackToken: ackTokenRes.value, isComplete, pending: meta }),
136
+ nextCall: (0, index_js_2.buildNextCall)({ continueToken: continueTokenValue, isComplete, pending: meta }),
142
137
  }));
143
- });
138
+ }));
144
139
  });
145
140
  }
@@ -1,31 +1,24 @@
1
- import type { ToolContext, ToolResult } from '../../types.js';
1
+ import type { ToolContext, ToolResult, V2ToolContext } from '../../types.js';
2
2
  import type { V2ContinueWorkflowInput, V2StartWorkflowInput } from '../../v2/tools.js';
3
- type NextCallAdvance = {
3
+ import { V2ContinueWorkflowOutputSchema } from '../../output-schemas.js';
4
+ import { ResultAsync as RA } from 'neverthrow';
5
+ import { type ContinueWorkflowError } from '../v2-execution-helpers.js';
6
+ import * as z from 'zod';
7
+ type NextCallTemplate = {
4
8
  readonly tool: 'continue_workflow';
5
9
  readonly params: {
6
- readonly intent: 'advance';
7
- readonly stateToken: string;
8
- readonly ackToken: string;
10
+ readonly continueToken: string;
9
11
  };
10
12
  };
11
- type NextCallRehydrate = {
12
- readonly tool: 'continue_workflow';
13
- readonly params: {
14
- readonly intent: 'rehydrate';
15
- readonly stateToken: string;
16
- };
17
- };
18
- type NextCallTemplate = NextCallAdvance | NextCallRehydrate;
19
13
  export declare function buildNextCall(args: {
20
- readonly stateToken: string;
21
- readonly ackToken: string | undefined;
14
+ readonly continueToken?: string;
22
15
  readonly isComplete: boolean;
23
16
  readonly pending: {
24
17
  readonly stepId: string;
25
18
  } | null;
26
- readonly retryable?: boolean;
27
- readonly retryAckToken?: string;
19
+ readonly retryContinueToken?: string;
28
20
  }): NextCallTemplate | null;
29
21
  export declare function handleV2StartWorkflow(input: V2StartWorkflowInput, ctx: ToolContext): Promise<ToolResult<unknown>>;
30
22
  export declare function handleV2ContinueWorkflow(input: V2ContinueWorkflowInput, ctx: ToolContext): Promise<ToolResult<unknown>>;
23
+ export declare function executeContinueWorkflow(input: V2ContinueWorkflowInput, ctx: V2ToolContext): RA<z.infer<typeof V2ContinueWorkflowOutputSchema>, ContinueWorkflowError>;
31
24
  export {};
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildNextCall = buildNextCall;
4
4
  exports.handleV2StartWorkflow = handleV2StartWorkflow;
5
5
  exports.handleV2ContinueWorkflow = handleV2ContinueWorkflow;
6
+ exports.executeContinueWorkflow = executeContinueWorkflow;
6
7
  const types_js_1 = require("../../types.js");
7
8
  const index_js_1 = require("../../../v2/durable-core/tokens/index.js");
8
9
  const index_js_2 = require("../../../v2/durable-core/ids/index.js");
@@ -16,18 +17,13 @@ const continue_advance_js_1 = require("./continue-advance.js");
16
17
  function buildNextCall(args) {
17
18
  if (args.isComplete && !args.pending)
18
19
  return null;
19
- if (args.retryable && args.retryAckToken) {
20
- return {
21
- tool: 'continue_workflow',
22
- params: { intent: 'advance', stateToken: args.stateToken, ackToken: args.retryAckToken },
23
- };
20
+ if (args.retryContinueToken) {
21
+ return { tool: 'continue_workflow', params: { continueToken: args.retryContinueToken } };
24
22
  }
25
- if (!args.ackToken)
26
- return null;
27
- return {
28
- tool: 'continue_workflow',
29
- params: { intent: 'advance', stateToken: args.stateToken, ackToken: args.ackToken },
30
- };
23
+ if (args.continueToken) {
24
+ return { tool: 'continue_workflow', params: { continueToken: args.continueToken } };
25
+ }
26
+ return null;
31
27
  }
32
28
  async function handleV2StartWorkflow(input, ctx) {
33
29
  const guard = (0, types_js_1.requireV2Context)(ctx);
@@ -42,61 +38,55 @@ async function handleV2ContinueWorkflow(input, ctx) {
42
38
  return executeContinueWorkflow(input, guard.ctx).match((payload) => (0, types_js_1.success)(payload), (e) => (0, v2_execution_helpers_js_1.mapContinueWorkflowErrorToToolError)(e));
43
39
  }
44
40
  function executeContinueWorkflow(input, ctx) {
45
- const { gate, sessionStore, snapshotStore, pinnedStore, sha256, tokenCodecPorts, idFactory } = ctx.v2;
46
- const stateRes = (0, v2_token_ops_js_1.parseStateTokenOrFail)(input.stateToken, tokenCodecPorts);
47
- if (!stateRes.ok)
48
- return (0, neverthrow_1.errAsync)({ kind: 'validation_failed', failure: stateRes.failure });
49
- const state = stateRes.token;
41
+ const { gate, sessionStore, snapshotStore, pinnedStore, sha256, tokenCodecPorts, idFactory, tokenAliasStore, entropy } = ctx.v2;
50
42
  const ctxCheck = (0, v2_context_budget_js_1.checkContextBudget)({ tool: 'continue_workflow', context: input.context });
51
43
  if (!ctxCheck.ok)
52
44
  return (0, neverthrow_1.errAsync)({ kind: 'validation_failed', failure: ctxCheck.error });
53
- const sessionId = (0, index_js_2.asSessionId)(state.payload.sessionId);
54
- const runId = (0, index_js_2.asRunId)(state.payload.runId);
55
- const nodeId = (0, index_js_2.asNodeId)(state.payload.nodeId);
56
- const workflowHashRef = state.payload.workflowHashRef;
57
- if (input.intent === 'rehydrate') {
45
+ return (0, v2_token_ops_js_1.parseContinueTokenOrFail)(input.continueToken, tokenCodecPorts, tokenAliasStore)
46
+ .mapErr((failure) => ({ kind: 'validation_failed', failure }))
47
+ .andThen((resolved) => {
48
+ const sessionId = (0, index_js_2.asSessionId)(resolved.sessionId);
49
+ const runId = (0, index_js_2.asRunId)(resolved.runId);
50
+ const nodeId = (0, index_js_2.asNodeId)(resolved.nodeId);
51
+ const workflowHashRef = resolved.workflowHashRef;
52
+ if (input.intent === 'rehydrate') {
53
+ return sessionStore.load(sessionId)
54
+ .mapErr((cause) => ({ kind: 'session_load_failed', cause }))
55
+ .andThen((truth) => (0, continue_rehydrate_js_1.handleRehydrateIntent)({
56
+ input,
57
+ sessionId,
58
+ runId,
59
+ nodeId,
60
+ workflowHashRef,
61
+ truth,
62
+ tokenCodecPorts,
63
+ pinnedStore,
64
+ snapshotStore,
65
+ idFactory,
66
+ aliasStore: tokenAliasStore,
67
+ entropy,
68
+ }));
69
+ }
70
+ const attemptId = (0, index_js_1.asAttemptId)(resolved.attemptId);
58
71
  return sessionStore.load(sessionId)
59
72
  .mapErr((cause) => ({ kind: 'session_load_failed', cause }))
60
- .andThen((truth) => (0, continue_rehydrate_js_1.handleRehydrateIntent)({
73
+ .andThen((truth) => (0, continue_advance_js_1.handleAdvanceIntent)({
61
74
  input,
62
75
  sessionId,
63
76
  runId,
64
77
  nodeId,
78
+ attemptId,
65
79
  workflowHashRef,
66
80
  truth,
67
- tokenCodecPorts,
68
- pinnedStore,
81
+ gate,
82
+ sessionStore,
69
83
  snapshotStore,
84
+ pinnedStore,
85
+ tokenCodecPorts,
70
86
  idFactory,
87
+ sha256,
88
+ aliasStore: tokenAliasStore,
89
+ entropy,
71
90
  }));
72
- }
73
- if (!input.ackToken) {
74
- return (0, neverthrow_1.errAsync)({ kind: 'validation_failed', failure: (0, types_js_1.error)('VALIDATION_ERROR', 'ackToken is required for advance intent') });
75
- }
76
- const ackRes = (0, v2_token_ops_js_1.parseAckTokenOrFail)(input.ackToken, tokenCodecPorts);
77
- if (!ackRes.ok)
78
- return (0, neverthrow_1.errAsync)({ kind: 'validation_failed', failure: ackRes.failure });
79
- const ack = ackRes.token;
80
- const scopeRes = (0, index_js_1.assertTokenScopeMatchesStateBinary)(state, ack);
81
- if (scopeRes.isErr())
82
- return (0, neverthrow_1.errAsync)({ kind: 'validation_failed', failure: (0, v2_execution_helpers_js_1.mapTokenDecodeErrorToToolError)(scopeRes.error) });
83
- const attemptId = (0, index_js_1.asAttemptId)(ack.payload.attemptId);
84
- return sessionStore.load(sessionId)
85
- .mapErr((cause) => ({ kind: 'session_load_failed', cause }))
86
- .andThen((truth) => (0, continue_advance_js_1.handleAdvanceIntent)({
87
- input,
88
- sessionId,
89
- runId,
90
- nodeId,
91
- attemptId,
92
- workflowHashRef,
93
- truth,
94
- gate,
95
- sessionStore,
96
- snapshotStore,
97
- pinnedStore,
98
- tokenCodecPorts,
99
- idFactory,
100
- sha256,
101
- }));
91
+ });
102
92
  }
@@ -10,19 +10,6 @@ import type { TokenCodecPorts } from '../../../v2/durable-core/tokens/token-code
10
10
  import { ResultAsync as RA } from 'neverthrow';
11
11
  import { type ContinueWorkflowError } from '../v2-execution-helpers.js';
12
12
  import * as z from 'zod';
13
- export declare function buildBlockedReplayResponse(args: {
14
- readonly sessionId: SessionId;
15
- readonly runId: RunId;
16
- readonly nodeId: NodeId;
17
- readonly attemptId: AttemptId;
18
- readonly blockers: import('../../../v2/durable-core/schemas/session/blockers.js').BlockerReportV1;
19
- readonly snapshot: ExecutionSnapshotFileV1 | null;
20
- readonly truth: LoadedSessionTruthV2;
21
- readonly workflow: ReturnType<typeof createWorkflow>;
22
- readonly inputStateToken: string;
23
- readonly inputAckToken: string;
24
- readonly ports: TokenCodecPorts;
25
- }): RA<z.infer<typeof V2ContinueWorkflowOutputSchema>, ContinueWorkflowError>;
26
13
  export declare function buildAdvancedReplayResponse(args: {
27
14
  readonly sessionId: SessionId;
28
15
  readonly runId: RunId;
@@ -35,6 +22,8 @@ export declare function buildAdvancedReplayResponse(args: {
35
22
  readonly workflowHash: WorkflowHash;
36
23
  readonly ports: TokenCodecPorts;
37
24
  readonly sha256: Sha256PortV2;
25
+ readonly aliasStore: import('../../../v2/ports/token-alias-store.port.js').TokenAliasStorePortV2;
26
+ readonly entropy: import('../../../v2/ports/random-entropy.port.js').RandomEntropyPortV2;
38
27
  }): RA<z.infer<typeof V2ContinueWorkflowOutputSchema>, ContinueWorkflowError>;
39
28
  export declare function replayFromRecordedAdvance(args: {
40
29
  readonly recordedEvent: Extract<DomainEventV1, {
@@ -46,10 +35,10 @@ export declare function replayFromRecordedAdvance(args: {
46
35
  readonly nodeId: NodeId;
47
36
  readonly workflowHash: WorkflowHash;
48
37
  readonly attemptId: AttemptId;
49
- readonly inputStateToken: string;
50
- readonly inputAckToken: string;
51
38
  readonly pinnedWorkflow: ReturnType<typeof createWorkflow>;
52
39
  readonly snapshotStore: import('../../../v2/ports/snapshot-store.port.js').SnapshotStorePortV2;
53
40
  readonly sha256: Sha256PortV2;
54
41
  readonly tokenCodecPorts: TokenCodecPorts;
42
+ readonly aliasStore: import('../../../v2/ports/token-alias-store.port.js').TokenAliasStorePortV2;
43
+ readonly entropy: import('../../../v2/ports/random-entropy.port.js').RandomEntropyPortV2;
55
44
  }): RA<z.infer<typeof V2ContinueWorkflowOutputSchema>, ContinueWorkflowError>;