@exaudeus/workrail 1.5.0 → 1.5.2

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 (163) hide show
  1. package/dist/application/services/workflow-compiler.js +14 -2
  2. package/dist/infrastructure/session/HttpServer.js +7 -2
  3. package/dist/infrastructure/session/SessionManager.d.ts +12 -4
  4. package/dist/infrastructure/session/SessionManager.js +30 -15
  5. package/dist/manifest.json +417 -217
  6. package/dist/mcp/error-mapper.d.ts +1 -1
  7. package/dist/mcp/error-mapper.js +12 -8
  8. package/dist/mcp/handler-factory.js +8 -1
  9. package/dist/mcp/handlers/session.js +36 -58
  10. package/dist/mcp/handlers/v2-advance-core/event-builders.d.ts +37 -0
  11. package/dist/mcp/handlers/v2-advance-core/event-builders.js +114 -0
  12. package/dist/mcp/handlers/v2-advance-core/index.d.ts +67 -0
  13. package/dist/mcp/handlers/v2-advance-core/index.js +119 -0
  14. package/dist/mcp/handlers/v2-advance-core/input-validation.d.ts +44 -0
  15. package/dist/mcp/handlers/v2-advance-core/input-validation.js +58 -0
  16. package/dist/mcp/handlers/v2-advance-core/outcome-blocked.d.ts +16 -0
  17. package/dist/mcp/handlers/v2-advance-core/outcome-blocked.js +64 -0
  18. package/dist/mcp/handlers/v2-advance-core/outcome-success.d.ts +15 -0
  19. package/dist/mcp/handlers/v2-advance-core/outcome-success.js +136 -0
  20. package/dist/mcp/handlers/v2-advance-core.d.ts +3 -45
  21. package/dist/mcp/handlers/v2-advance-core.js +3 -431
  22. package/dist/mcp/handlers/v2-advance-events.d.ts +61 -0
  23. package/dist/mcp/handlers/v2-advance-events.js +126 -0
  24. package/dist/mcp/handlers/v2-checkpoint.js +11 -14
  25. package/dist/mcp/handlers/v2-context-budget.js +2 -2
  26. package/dist/mcp/handlers/v2-error-mapping.d.ts +3 -3
  27. package/dist/mcp/handlers/v2-error-mapping.js +31 -27
  28. package/dist/mcp/handlers/v2-execution/advance.d.ts +32 -0
  29. package/dist/mcp/handlers/v2-execution/advance.js +50 -0
  30. package/dist/mcp/handlers/v2-execution/continue-advance.d.ts +29 -0
  31. package/dist/mcp/handlers/v2-execution/continue-advance.js +167 -0
  32. package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +22 -0
  33. package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +145 -0
  34. package/dist/mcp/handlers/v2-execution/index.d.ts +31 -0
  35. package/dist/mcp/handlers/v2-execution/index.js +102 -0
  36. package/dist/mcp/handlers/v2-execution/replay.d.ts +55 -0
  37. package/dist/mcp/handlers/v2-execution/replay.js +225 -0
  38. package/dist/mcp/handlers/v2-execution/start.d.ts +52 -0
  39. package/dist/mcp/handlers/v2-execution/start.js +331 -0
  40. package/dist/mcp/handlers/v2-execution-helpers.d.ts +26 -2
  41. package/dist/mcp/handlers/v2-execution-helpers.js +76 -60
  42. package/dist/mcp/handlers/v2-execution.d.ts +1 -23
  43. package/dist/mcp/handlers/v2-execution.js +5 -898
  44. package/dist/mcp/handlers/v2-state-conversion.d.ts +0 -5
  45. package/dist/mcp/handlers/v2-state-conversion.js +2 -21
  46. package/dist/mcp/handlers/v2-token-ops.d.ts +1 -1
  47. package/dist/mcp/handlers/v2-workflow.js +85 -78
  48. package/dist/mcp/output-schemas.d.ts +197 -34
  49. package/dist/mcp/output-schemas.js +12 -5
  50. package/dist/mcp/tool-descriptions.js +22 -16
  51. package/dist/mcp/types.d.ts +10 -0
  52. package/dist/mcp/types.js +10 -0
  53. package/dist/mcp/v2/tools.d.ts +45 -7
  54. package/dist/mcp/v2/tools.js +7 -3
  55. package/dist/types/workflow-definition.d.ts +3 -2
  56. package/dist/v2/durable-core/canonical/jcs.js +8 -1
  57. package/dist/v2/durable-core/constants.d.ts +60 -0
  58. package/dist/v2/durable-core/constants.js +55 -1
  59. package/dist/v2/durable-core/domain/ack-advance-append-plan.d.ts +14 -13
  60. package/dist/v2/durable-core/domain/ack-advance-append-plan.js +143 -116
  61. package/dist/v2/durable-core/domain/blocked-node-builder.js +9 -3
  62. package/dist/v2/durable-core/domain/blocking-decision.d.ts +2 -0
  63. package/dist/v2/durable-core/domain/blocking-decision.js +29 -12
  64. package/dist/v2/durable-core/domain/bundle-builder.d.ts +1 -0
  65. package/dist/v2/durable-core/domain/bundle-builder.js +1 -1
  66. package/dist/v2/durable-core/domain/bundle-validator.js +3 -2
  67. package/dist/v2/durable-core/domain/decision-trace-builder.js +7 -9
  68. package/dist/v2/durable-core/domain/function-definition-expander.js +1 -3
  69. package/dist/v2/durable-core/domain/gap-builder.js +2 -1
  70. package/dist/v2/durable-core/domain/observation-builder.js +2 -1
  71. package/dist/v2/durable-core/domain/outputs.d.ts +2 -1
  72. package/dist/v2/durable-core/domain/outputs.js +3 -2
  73. package/dist/v2/durable-core/domain/reason-model.d.ts +1 -1
  74. package/dist/v2/durable-core/domain/reason-model.js +4 -9
  75. package/dist/v2/durable-core/domain/validation-criteria-validator.js +2 -2
  76. package/dist/v2/durable-core/domain/validation-event-builder.js +4 -6
  77. package/dist/v2/durable-core/domain/validation-loader.js +2 -1
  78. package/dist/v2/durable-core/domain/validation-requirements-extractor.js +12 -18
  79. package/dist/v2/durable-core/encoding/base32-lower.d.ts +13 -1
  80. package/dist/v2/durable-core/encoding/base32-lower.js +13 -3
  81. package/dist/v2/durable-core/encoding/hex-to-bytes.d.ts +6 -0
  82. package/dist/v2/durable-core/encoding/hex-to-bytes.js +19 -0
  83. package/dist/v2/durable-core/ids/attempt-id-derivation.d.ts +6 -1
  84. package/dist/v2/durable-core/ids/attempt-id-derivation.js +9 -19
  85. package/dist/v2/durable-core/ids/event-ids.d.ts +9 -0
  86. package/dist/v2/durable-core/ids/event-ids.js +18 -0
  87. package/dist/v2/durable-core/ids/index.d.ts +13 -33
  88. package/dist/v2/durable-core/ids/index.js +22 -63
  89. package/dist/v2/durable-core/ids/session-ids.d.ts +9 -0
  90. package/dist/v2/durable-core/ids/session-ids.js +18 -0
  91. package/dist/v2/durable-core/ids/snapshot-ids.d.ts +6 -0
  92. package/dist/v2/durable-core/ids/snapshot-ids.js +10 -0
  93. package/dist/v2/durable-core/ids/token-ids.d.ts +3 -0
  94. package/dist/v2/durable-core/ids/token-ids.js +6 -0
  95. package/dist/v2/durable-core/ids/workflow-hash-ref.d.ts +3 -0
  96. package/dist/v2/durable-core/ids/workflow-hash-ref.js +5 -4
  97. package/dist/v2/durable-core/ids/workflow-ids.d.ts +11 -0
  98. package/dist/v2/durable-core/ids/workflow-ids.js +21 -0
  99. package/dist/v2/durable-core/lib/utf8-byte-length.d.ts +1 -0
  100. package/dist/v2/durable-core/lib/utf8-byte-length.js +6 -0
  101. package/dist/v2/durable-core/schemas/artifacts/loop-control.d.ts +6 -6
  102. package/dist/v2/durable-core/schemas/artifacts/loop-control.js +2 -1
  103. package/dist/v2/durable-core/schemas/execution-snapshot/blocked-snapshot.d.ts +28 -28
  104. package/dist/v2/durable-core/schemas/execution-snapshot/blocked-snapshot.js +5 -7
  105. package/dist/v2/durable-core/schemas/execution-snapshot/execution-snapshot.v1.d.ts +296 -296
  106. package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +466 -471
  107. package/dist/v2/durable-core/schemas/export-bundle/index.js +0 -8
  108. package/dist/v2/durable-core/schemas/lib/dedupe-key.d.ts +9 -1
  109. package/dist/v2/durable-core/schemas/lib/dedupe-key.js +4 -3
  110. package/dist/v2/durable-core/schemas/lib/utf8-byte-length.d.ts +1 -0
  111. package/dist/v2/durable-core/schemas/lib/utf8-byte-length.js +6 -0
  112. package/dist/v2/durable-core/schemas/session/blockers.d.ts +305 -0
  113. package/dist/v2/durable-core/schemas/session/blockers.js +80 -0
  114. package/dist/v2/durable-core/schemas/session/dag-topology.d.ts +77 -0
  115. package/dist/v2/durable-core/schemas/session/dag-topology.js +45 -0
  116. package/dist/v2/durable-core/schemas/session/events.d.ts +56 -56
  117. package/dist/v2/durable-core/schemas/session/events.js +11 -182
  118. package/dist/v2/durable-core/schemas/session/gaps.d.ts +211 -0
  119. package/dist/v2/durable-core/schemas/session/gaps.js +37 -0
  120. package/dist/v2/durable-core/schemas/session/outputs.d.ts +148 -0
  121. package/dist/v2/durable-core/schemas/session/outputs.js +44 -0
  122. package/dist/v2/durable-core/schemas/session/validation-event.js +5 -7
  123. package/dist/v2/durable-core/tokens/token-codec.d.ts +1 -18
  124. package/dist/v2/durable-core/tokens/token-codec.js +0 -67
  125. package/dist/v2/durable-core/tokens/token-signer.d.ts +1 -8
  126. package/dist/v2/durable-core/tokens/token-signer.js +0 -43
  127. package/dist/v2/infra/local/base32/index.js +1 -23
  128. package/dist/v2/infra/local/bech32m/index.js +1 -1
  129. package/dist/v2/infra/local/data-dir/index.d.ts +7 -6
  130. package/dist/v2/infra/local/data-dir/index.js +3 -3
  131. package/dist/v2/infra/local/directory-listing/index.d.ts +2 -2
  132. package/dist/v2/infra/local/session-store/index.js +198 -182
  133. package/dist/v2/infra/local/session-summary-provider/index.js +5 -2
  134. package/dist/v2/infra/local/snapshot-store/index.js +2 -2
  135. package/dist/v2/ports/data-dir.port.d.ts +7 -6
  136. package/dist/v2/ports/fs.port.d.ts +18 -7
  137. package/dist/v2/ports/session-event-log-store.port.d.ts +5 -2
  138. package/dist/v2/projections/advance-outcomes.d.ts +1 -7
  139. package/dist/v2/projections/advance-outcomes.js +2 -1
  140. package/dist/v2/projections/artifacts.js +3 -2
  141. package/dist/v2/projections/capabilities.d.ts +1 -7
  142. package/dist/v2/projections/capabilities.js +2 -1
  143. package/dist/v2/projections/gaps.d.ts +1 -7
  144. package/dist/v2/projections/gaps.js +2 -1
  145. package/dist/v2/projections/node-outputs.d.ts +1 -7
  146. package/dist/v2/projections/node-outputs.js +4 -3
  147. package/dist/v2/projections/preferences.d.ts +1 -7
  148. package/dist/v2/projections/preferences.js +2 -1
  149. package/dist/v2/projections/projection-error.d.ts +7 -0
  150. package/dist/v2/projections/projection-error.js +2 -0
  151. package/dist/v2/projections/resume-ranking.js +3 -3
  152. package/dist/v2/projections/run-context.d.ts +1 -7
  153. package/dist/v2/projections/run-context.js +4 -2
  154. package/dist/v2/projections/run-dag.d.ts +9 -9
  155. package/dist/v2/projections/run-dag.js +88 -65
  156. package/dist/v2/projections/run-status-signals.d.ts +1 -7
  157. package/dist/v2/projections/run-status-signals.js +3 -2
  158. package/dist/v2/usecases/execution-session-gate.js +2 -5
  159. package/dist/v2/usecases/export-session.js +4 -2
  160. package/dist/v2/usecases/import-session.d.ts +3 -3
  161. package/package.json +1 -1
  162. package/workflows/coding-task-workflow-agentic.json +0 -9
  163. package/workflows/workflow-for-workflows.json +18 -5
@@ -22,6 +22,13 @@ let WorkflowCompiler = class WorkflowCompiler {
22
22
  }
23
23
  stepById.set(step.id, step);
24
24
  }
25
+ for (const step of steps) {
26
+ const contractRef = step.outputContract?.contractRef;
27
+ if (contractRef && !(0, index_1.isValidContractRef)(contractRef)) {
28
+ return (0, neverthrow_1.err)(error_1.Err.invalidState(`Step '${step.id}' declares unknown outputContract.contractRef '${contractRef}'. ` +
29
+ `Known contracts: ${index_1.LOOP_CONTROL_CONTRACT_REF}`));
30
+ }
31
+ }
25
32
  const compiledLoops = new Map();
26
33
  const loopBodyStepIds = new Set();
27
34
  for (const step of steps) {
@@ -33,6 +40,11 @@ let WorkflowCompiler = class WorkflowCompiler {
33
40
  return (0, neverthrow_1.err)(bodyResolved.error);
34
41
  for (const bodyStep of bodyResolved.value) {
35
42
  loopBodyStepIds.add(bodyStep.id);
43
+ const ref = bodyStep.outputContract?.contractRef;
44
+ if (ref && !(0, index_1.isValidContractRef)(ref)) {
45
+ return (0, neverthrow_1.err)(error_1.Err.invalidState(`Loop body step '${bodyStep.id}' in loop '${loop.id}' declares unknown outputContract.contractRef '${ref}'. ` +
46
+ `Known contracts: ${index_1.LOOP_CONTROL_CONTRACT_REF}`));
47
+ }
36
48
  }
37
49
  const conditionSource = this.deriveConditionSource(loop, bodyResolved.value);
38
50
  compiledLoops.set(loop.id, {
@@ -56,8 +68,8 @@ let WorkflowCompiler = class WorkflowCompiler {
56
68
  if (loop.loop.conditionSource) {
57
69
  return loop.loop.conditionSource;
58
70
  }
59
- const hasLoopControlContract = bodySteps.some((s) => s.outputContract?.contractRef === index_1.LOOP_CONTROL_CONTRACT_REF);
60
- if (hasLoopControlContract) {
71
+ const loopControlStep = bodySteps.find((s) => s.outputContract?.contractRef === index_1.LOOP_CONTROL_CONTRACT_REF);
72
+ if (loopControlStep) {
61
73
  return {
62
74
  kind: 'artifact_contract',
63
75
  contractRef: index_1.LOOP_CONTROL_CONTRACT_REF,
@@ -283,7 +283,12 @@ let HttpServer = class HttpServer {
283
283
  this.app.delete('/api/sessions/:workflow/:id', async (req, res) => {
284
284
  try {
285
285
  const { workflow, id } = req.params;
286
- await this.sessionManager.deleteSession(workflow, id);
286
+ const result = await this.sessionManager.deleteSession(workflow, id);
287
+ if (result.isErr()) {
288
+ const status = result.error.code === 'SESSION_NOT_FOUND' ? 404 : 500;
289
+ res.status(status).json({ success: false, error: result.error.message });
290
+ return;
291
+ }
287
292
  res.json({
288
293
  success: true,
289
294
  message: `Session ${workflow}/${id} deleted successfully`
@@ -291,7 +296,7 @@ let HttpServer = class HttpServer {
291
296
  }
292
297
  catch (error) {
293
298
  console.error('[HttpServer] Delete session error:', error);
294
- res.status(error.message?.includes('not found') ? 404 : 500).json({
299
+ res.status(500).json({
295
300
  success: false,
296
301
  error: error.message || 'Failed to delete session'
297
302
  });
@@ -1,6 +1,14 @@
1
1
  import { EventEmitter } from 'events';
2
+ import { type Result } from 'neverthrow';
2
3
  import { SessionDataNormalizer } from './SessionDataNormalizer';
3
4
  import { SessionDataValidator } from './SessionDataValidator';
5
+ export type SessionManagerError = {
6
+ readonly code: 'SESSION_NOT_FOUND';
7
+ readonly message: string;
8
+ } | {
9
+ readonly code: 'IO_ERROR';
10
+ readonly message: string;
11
+ };
4
12
  export interface Session {
5
13
  id: string;
6
14
  workflowId: string;
@@ -30,10 +38,10 @@ export declare class SessionManager extends EventEmitter {
30
38
  private findGitRepoRoot;
31
39
  private getProjectRoot;
32
40
  getSessionPath(workflowId: string, sessionId: string): string;
33
- createSession(workflowId: string, sessionId: string, initialData?: Record<string, any>): Promise<Session>;
34
- updateSession(workflowId: string, sessionId: string, updates: Record<string, any>): Promise<Session>;
35
- readSession(workflowId: string, sessionId: string, queryPath?: string): Promise<any>;
36
- deleteSession(workflowId: string, sessionId: string): Promise<void>;
41
+ createSession(workflowId: string, sessionId: string, initialData?: Record<string, any>): Promise<Result<Session, SessionManagerError>>;
42
+ updateSession(workflowId: string, sessionId: string, updates: Record<string, any>): Promise<Result<Session, SessionManagerError>>;
43
+ readSession(workflowId: string, sessionId: string, queryPath?: string): Promise<Result<unknown, SessionManagerError>>;
44
+ deleteSession(workflowId: string, sessionId: string): Promise<Result<void, SessionManagerError>>;
37
45
  deleteSessions(sessions: Array<{
38
46
  workflowId: string;
39
47
  sessionId: string;
@@ -24,6 +24,7 @@ const child_process_1 = require("child_process");
24
24
  const os_1 = __importDefault(require("os"));
25
25
  const events_1 = require("events");
26
26
  const tsyringe_1 = require("tsyringe");
27
+ const neverthrow_1 = require("neverthrow");
27
28
  const tokens_js_1 = require("../../di/tokens.js");
28
29
  const SessionDataNormalizer_1 = require("./SessionDataNormalizer");
29
30
  const SessionDataValidator_1 = require("./SessionDataValidator");
@@ -76,7 +77,12 @@ let SessionManager = class SessionManager extends events_1.EventEmitter {
76
77
  }
77
78
  async createSession(workflowId, sessionId, initialData = {}) {
78
79
  const sessionPath = this.getSessionPath(workflowId, sessionId);
79
- await promises_1.default.mkdir(path_1.default.dirname(sessionPath), { recursive: true });
80
+ try {
81
+ await promises_1.default.mkdir(path_1.default.dirname(sessionPath), { recursive: true });
82
+ }
83
+ catch (e) {
84
+ return (0, neverthrow_1.err)({ code: 'IO_ERROR', message: `Failed to create session directory: ${e instanceof Error ? e.message : String(e)}` });
85
+ }
80
86
  const session = {
81
87
  id: sessionId,
82
88
  workflowId,
@@ -86,15 +92,20 @@ let SessionManager = class SessionManager extends events_1.EventEmitter {
86
92
  updatedAt: new Date().toISOString(),
87
93
  data: initialData
88
94
  };
89
- await this.atomicWrite(sessionPath, session);
95
+ try {
96
+ await this.atomicWrite(sessionPath, session);
97
+ }
98
+ catch (e) {
99
+ return (0, neverthrow_1.err)({ code: 'IO_ERROR', message: `Failed to write session: ${e instanceof Error ? e.message : String(e)}` });
100
+ }
90
101
  await this.updateProjectMetadata();
91
- return session;
102
+ return (0, neverthrow_1.ok)(session);
92
103
  }
93
104
  async updateSession(workflowId, sessionId, updates) {
94
105
  const sessionPath = this.getSessionPath(workflowId, sessionId);
95
106
  const session = await this.getSession(workflowId, sessionId);
96
107
  if (!session) {
97
- throw new Error(`Session not found: ${workflowId}/${sessionId}`);
108
+ return (0, neverthrow_1.err)({ code: 'SESSION_NOT_FOUND', message: `Session not found: ${workflowId}/${sessionId}` });
98
109
  }
99
110
  const mergedData = this.deepMerge(session.data, updates);
100
111
  const normalizedData = this.normalizer.normalize(workflowId, mergedData);
@@ -104,36 +115,40 @@ let SessionManager = class SessionManager extends events_1.EventEmitter {
104
115
  }
105
116
  session.data = normalizedData;
106
117
  session.updatedAt = new Date().toISOString();
107
- await this.atomicWrite(sessionPath, session);
108
- return session;
118
+ try {
119
+ await this.atomicWrite(sessionPath, session);
120
+ }
121
+ catch (e) {
122
+ return (0, neverthrow_1.err)({ code: 'IO_ERROR', message: `Failed to write session: ${e instanceof Error ? e.message : String(e)}` });
123
+ }
124
+ return (0, neverthrow_1.ok)(session);
109
125
  }
110
126
  async readSession(workflowId, sessionId, queryPath) {
111
127
  const session = await this.getSession(workflowId, sessionId);
112
128
  if (!session) {
113
- throw new Error(`Session not found: ${workflowId}/${sessionId}`);
129
+ return (0, neverthrow_1.err)({ code: 'SESSION_NOT_FOUND', message: `Session not found: ${workflowId}/${sessionId}` });
114
130
  }
115
131
  if (!queryPath) {
116
- return session.data;
132
+ return (0, neverthrow_1.ok)(session.data);
117
133
  }
118
- return this.getPath(session.data, queryPath);
134
+ return (0, neverthrow_1.ok)(this.getPath(session.data, queryPath));
119
135
  }
120
136
  async deleteSession(workflowId, sessionId) {
121
137
  const sessionPath = this.getSessionPath(workflowId, sessionId);
122
138
  const exists = await promises_1.default.access(sessionPath).then(() => true).catch(() => false);
123
139
  if (!exists) {
124
- throw new Error(`Session not found: ${workflowId}/${sessionId}`);
140
+ return (0, neverthrow_1.err)({ code: 'SESSION_NOT_FOUND', message: `Session not found: ${workflowId}/${sessionId}` });
125
141
  }
126
142
  this.unwatchSession(workflowId, sessionId);
127
143
  await promises_1.default.unlink(sessionPath);
128
144
  await this.updateProjectMetadata();
145
+ return (0, neverthrow_1.ok)(undefined);
129
146
  }
130
147
  async deleteSessions(sessions) {
131
148
  for (const { workflowId, sessionId } of sessions) {
132
- try {
133
- await this.deleteSession(workflowId, sessionId);
134
- }
135
- catch (error) {
136
- console.error(`Failed to delete ${workflowId}/${sessionId}:`, error);
149
+ const res = await this.deleteSession(workflowId, sessionId);
150
+ if (res.isErr()) {
151
+ console.error(`Failed to delete ${workflowId}/${sessionId}:`, res.error.message);
137
152
  }
138
153
  }
139
154
  }