@exaudeus/workrail 3.15.0 → 3.17.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 (164) hide show
  1. package/dist/application/services/workflow-service.d.ts +2 -0
  2. package/dist/application/services/workflow-service.js +3 -0
  3. package/dist/application/use-cases/raw-workflow-file-scanner.js +10 -13
  4. package/dist/cli/commands/index.d.ts +1 -1
  5. package/dist/cli/commands/index.js +2 -1
  6. package/dist/cli/commands/init.d.ts +10 -0
  7. package/dist/cli/commands/init.js +72 -0
  8. package/dist/cli.js +13 -1
  9. package/dist/config/config-file.d.ts +8 -0
  10. package/dist/config/config-file.js +141 -0
  11. package/dist/config/feature-flags.js +8 -0
  12. package/dist/console/assets/index-BZNM03t1.css +1 -0
  13. package/dist/console/assets/index-BwJelCXK.js +28 -0
  14. package/dist/console/index.html +2 -2
  15. package/dist/di/container.d.ts +1 -0
  16. package/dist/di/container.js +24 -7
  17. package/dist/infrastructure/session/HttpServer.d.ts +3 -4
  18. package/dist/infrastructure/session/HttpServer.js +58 -106
  19. package/dist/infrastructure/storage/caching-workflow-storage.d.ts +2 -0
  20. package/dist/infrastructure/storage/caching-workflow-storage.js +15 -6
  21. package/dist/infrastructure/storage/file-workflow-storage.js +3 -4
  22. package/dist/infrastructure/storage/schema-validating-workflow-storage.js +9 -8
  23. package/dist/manifest.json +303 -247
  24. package/dist/mcp/assert-output.d.ts +37 -0
  25. package/dist/mcp/assert-output.js +53 -0
  26. package/dist/mcp/boundary-coercion.d.ts +1 -0
  27. package/dist/mcp/boundary-coercion.js +44 -0
  28. package/dist/mcp/dev-mode.d.ts +2 -0
  29. package/dist/mcp/dev-mode.js +16 -0
  30. package/dist/mcp/handler-factory.d.ts +1 -1
  31. package/dist/mcp/handler-factory.js +20 -16
  32. package/dist/mcp/handlers/session.js +8 -9
  33. package/dist/mcp/handlers/shared/request-workflow-reader.d.ts +1 -0
  34. package/dist/mcp/handlers/shared/request-workflow-reader.js +90 -20
  35. package/dist/mcp/handlers/v2-advance-core/event-builders.d.ts +2 -0
  36. package/dist/mcp/handlers/v2-advance-core/event-builders.js +6 -6
  37. package/dist/mcp/handlers/v2-advance-core/index.d.ts +2 -0
  38. package/dist/mcp/handlers/v2-advance-core/index.js +4 -3
  39. package/dist/mcp/handlers/v2-advance-core/input-validation.d.ts +2 -0
  40. package/dist/mcp/handlers/v2-advance-core/input-validation.js +32 -9
  41. package/dist/mcp/handlers/v2-advance-core/outcome-blocked.d.ts +2 -0
  42. package/dist/mcp/handlers/v2-advance-core/outcome-blocked.js +1 -1
  43. package/dist/mcp/handlers/v2-advance-core/outcome-success.d.ts +2 -0
  44. package/dist/mcp/handlers/v2-advance-core/outcome-success.js +1 -1
  45. package/dist/mcp/handlers/v2-checkpoint.d.ts +1 -1
  46. package/dist/mcp/handlers/v2-checkpoint.js +5 -6
  47. package/dist/mcp/handlers/v2-execution/advance.d.ts +4 -2
  48. package/dist/mcp/handlers/v2-execution/advance.js +5 -7
  49. package/dist/mcp/handlers/v2-execution/continue-advance.d.ts +1 -0
  50. package/dist/mcp/handlers/v2-execution/continue-advance.js +59 -27
  51. package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +2 -1
  52. package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +11 -10
  53. package/dist/mcp/handlers/v2-execution/index.js +2 -0
  54. package/dist/mcp/handlers/v2-execution/replay.d.ts +8 -4
  55. package/dist/mcp/handlers/v2-execution/replay.js +50 -30
  56. package/dist/mcp/handlers/v2-execution/start.d.ts +2 -3
  57. package/dist/mcp/handlers/v2-execution/start.js +58 -30
  58. package/dist/mcp/handlers/v2-execution/workflow-object-cache.d.ts +5 -0
  59. package/dist/mcp/handlers/v2-execution/workflow-object-cache.js +19 -0
  60. package/dist/mcp/handlers/v2-execution-helpers.d.ts +1 -0
  61. package/dist/mcp/handlers/v2-execution-helpers.js +23 -7
  62. package/dist/mcp/handlers/v2-resume.d.ts +1 -1
  63. package/dist/mcp/handlers/v2-resume.js +3 -4
  64. package/dist/mcp/handlers/v2-state-conversion.js +5 -1
  65. package/dist/mcp/handlers/v2-workflow.d.ts +80 -0
  66. package/dist/mcp/handlers/v2-workflow.js +40 -23
  67. package/dist/mcp/handlers/workflow.d.ts +2 -5
  68. package/dist/mcp/handlers/workflow.js +15 -12
  69. package/dist/mcp/output-schemas.d.ts +25 -27
  70. package/dist/mcp/output-schemas.js +7 -7
  71. package/dist/mcp/server.js +23 -4
  72. package/dist/mcp/tool-call-timing.d.ts +24 -0
  73. package/dist/mcp/tool-call-timing.js +85 -0
  74. package/dist/mcp/transports/http-entry.js +3 -2
  75. package/dist/mcp/transports/http-listener.d.ts +1 -0
  76. package/dist/mcp/transports/http-listener.js +25 -0
  77. package/dist/mcp/transports/shutdown-hooks.d.ts +4 -1
  78. package/dist/mcp/transports/shutdown-hooks.js +3 -2
  79. package/dist/mcp/transports/stdio-entry.js +6 -28
  80. package/dist/mcp/v2-response-formatter.d.ts +1 -1
  81. package/dist/mcp/v2-response-formatter.js +2 -5
  82. package/dist/mcp/validation/schema-introspection.d.ts +1 -0
  83. package/dist/mcp/validation/schema-introspection.js +15 -5
  84. package/dist/mcp/validation/suggestion-generator.js +2 -2
  85. package/dist/runtime/adapters/node-process-signals.d.ts +1 -0
  86. package/dist/runtime/adapters/node-process-signals.js +5 -0
  87. package/dist/runtime/adapters/noop-process-signals.d.ts +1 -0
  88. package/dist/runtime/adapters/noop-process-signals.js +2 -0
  89. package/dist/runtime/ports/process-signals.d.ts +1 -0
  90. package/dist/types/workflow-definition.d.ts +5 -1
  91. package/dist/types/workflow-definition.js +2 -0
  92. package/dist/types/workflow.d.ts +3 -0
  93. package/dist/types/workflow.js +35 -26
  94. package/dist/v2/durable-core/domain/context-template-resolver.js +2 -2
  95. package/dist/v2/durable-core/domain/function-definition-expander.js +2 -17
  96. package/dist/v2/durable-core/domain/prompt-renderer.d.ts +2 -0
  97. package/dist/v2/durable-core/domain/prompt-renderer.js +22 -18
  98. package/dist/v2/durable-core/domain/recap-recovery.js +23 -16
  99. package/dist/v2/durable-core/domain/retrieval-contract.js +13 -7
  100. package/dist/v2/durable-core/schemas/compiled-workflow/index.js +4 -3
  101. package/dist/v2/durable-core/session-index.d.ts +22 -0
  102. package/dist/v2/durable-core/session-index.js +58 -0
  103. package/dist/v2/durable-core/sorted-event-log.d.ts +6 -0
  104. package/dist/v2/durable-core/sorted-event-log.js +15 -0
  105. package/dist/v2/infra/local/fs/index.js +8 -8
  106. package/dist/v2/infra/local/pinned-workflow-store/index.d.ts +2 -0
  107. package/dist/v2/infra/local/pinned-workflow-store/index.js +49 -0
  108. package/dist/v2/infra/local/remembered-roots-store/index.d.ts +3 -1
  109. package/dist/v2/infra/local/remembered-roots-store/index.js +6 -3
  110. package/dist/v2/infra/local/session-store/index.d.ts +1 -1
  111. package/dist/v2/infra/local/session-store/index.js +71 -61
  112. package/dist/v2/infra/local/session-summary-provider/index.js +9 -4
  113. package/dist/v2/infra/local/snapshot-store/index.js +2 -1
  114. package/dist/v2/infra/local/workspace-anchor/index.js +4 -2
  115. package/dist/v2/ports/pinned-workflow-store.port.d.ts +2 -0
  116. package/dist/v2/ports/session-event-log-store.port.d.ts +1 -1
  117. package/dist/v2/projections/assessment-consequences.d.ts +2 -1
  118. package/dist/v2/projections/assessment-consequences.js +0 -5
  119. package/dist/v2/projections/assessments.d.ts +2 -1
  120. package/dist/v2/projections/assessments.js +2 -4
  121. package/dist/v2/projections/gaps.d.ts +2 -1
  122. package/dist/v2/projections/gaps.js +0 -5
  123. package/dist/v2/projections/preferences.d.ts +2 -1
  124. package/dist/v2/projections/preferences.js +0 -5
  125. package/dist/v2/projections/run-context.d.ts +2 -2
  126. package/dist/v2/projections/run-context.js +0 -5
  127. package/dist/v2/projections/run-dag.js +7 -1
  128. package/dist/v2/projections/run-execution-trace.d.ts +8 -0
  129. package/dist/v2/projections/run-execution-trace.js +124 -0
  130. package/dist/v2/projections/run-status-signals.d.ts +2 -2
  131. package/dist/v2/usecases/console-routes.d.ts +3 -1
  132. package/dist/v2/usecases/console-routes.js +124 -25
  133. package/dist/v2/usecases/console-service.d.ts +1 -0
  134. package/dist/v2/usecases/console-service.js +83 -25
  135. package/dist/v2/usecases/console-types.d.ts +53 -0
  136. package/dist/v2/usecases/worktree-service.js +32 -1
  137. package/package.json +6 -5
  138. package/spec/workflow.schema.json +18 -0
  139. package/workflows/adaptive-ticket-creation.json +23 -16
  140. package/workflows/architecture-scalability-audit.json +29 -22
  141. package/workflows/bug-investigation.agentic.v2.json +7 -0
  142. package/workflows/coding-task-workflow-agentic.json +7 -0
  143. package/workflows/coding-task-workflow-agentic.lean.v2.json +16 -8
  144. package/workflows/coding-task-workflow-agentic.v2.json +7 -0
  145. package/workflows/cross-platform-code-conversion.v2.json +7 -0
  146. package/workflows/document-creation-workflow.json +15 -8
  147. package/workflows/documentation-update-workflow.json +15 -8
  148. package/workflows/intelligent-test-case-generation.json +7 -0
  149. package/workflows/learner-centered-course-workflow.json +9 -2
  150. package/workflows/mr-review-workflow.agentic.v2.json +7 -0
  151. package/workflows/personal-learning-materials-creation-branched.json +15 -8
  152. package/workflows/presentation-creation.json +12 -5
  153. package/workflows/production-readiness-audit.json +7 -0
  154. package/workflows/relocation-workflow-us.json +39 -32
  155. package/workflows/scoped-documentation-workflow.json +33 -26
  156. package/workflows/ui-ux-design-workflow.json +7 -0
  157. package/workflows/workflow-diagnose-environment.json +6 -0
  158. package/workflows/workflow-for-workflows.json +7 -0
  159. package/workflows/workflow-for-workflows.v2.json +23 -11
  160. package/workflows/wr.discovery.json +8 -1
  161. package/dist/console/assets/index-BZYIjrzJ.js +0 -28
  162. package/dist/console/assets/index-OLCKbDdm.css +0 -1
  163. package/dist/mcp/handlers/v2-resolve-refs-envelope.d.ts +0 -5
  164. package/dist/mcp/handlers/v2-resolve-refs-envelope.js +0 -17
@@ -15,6 +15,8 @@ const v2_state_conversion_js_1 = require("../v2-state-conversion.js");
15
15
  const constants_js_1 = require("../../../v2/durable-core/constants.js");
16
16
  const index_js_2 = require("./index.js");
17
17
  const assessments_js_1 = require("../../../v2/projections/assessments.js");
18
+ const assert_output_js_1 = require("../../assert-output.js");
19
+ const sorted_event_log_js_1 = require("../../../v2/durable-core/sorted-event-log.js");
18
20
  function buildAdvancedReplayResponse(args) {
19
21
  const { sessionId, runId, fromNodeId, toNodeId, attemptId, toSnapshot, workflow, truth, workflowHash, ports, sha256, aliasStore, entropy } = args;
20
22
  const toNodeIdBranded = (0, index_js_1.asNodeId)(String(toNodeId));
@@ -75,29 +77,34 @@ function buildAdvancedReplayResponse(args) {
75
77
  runId: (0, index_js_1.asRunId)(String(runId)),
76
78
  nodeId: (0, index_js_1.asNodeId)(String(toNodeIdBranded)),
77
79
  rehydrateOnly: false,
80
+ precomputedIndex: args.precomputedIndex,
81
+ cleanResponseFormat: args.cleanResponseFormat,
78
82
  });
79
83
  if (result.isErr()) {
80
84
  return (0, neverthrow_1.errAsync)({ kind: 'prompt_render_failed', message: result.error.message });
81
85
  }
82
86
  blockedMeta = result.value;
83
87
  }
84
- const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId: toNodeIdBranded });
88
+ const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId: toNodeIdBranded, precomputedIndex: args.precomputedIndex });
85
89
  const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: false, isComplete, pending: blockedMeta });
86
- return nextTokensMint.andThen((nextTokens) => retryContinueMint.andThen((retryContinueToken) => (0, neverthrow_1.okAsync)(output_schemas_js_1.V2ContinueWorkflowOutputSchema.parse({
87
- kind: 'blocked',
88
- continueToken: pending ? nextTokens.continueToken : undefined,
89
- checkpointToken: pending ? nextTokens.checkpointToken : undefined,
90
- isComplete,
91
- pending: (0, output_schemas_js_1.toPendingStep)(blockedMeta),
92
- preferences,
93
- nextIntent,
94
- nextCall: (0, index_js_2.buildNextCall)({ continueToken: pending ? nextTokens.continueToken : undefined, isComplete, pending: blockedMeta, retryContinueToken }),
95
- blockers,
96
- retryable,
97
- retryContinueToken,
98
- validation,
99
- assessmentFollowup,
100
- }))));
90
+ return nextTokensMint.andThen((nextTokens) => retryContinueMint.andThen((retryContinueToken) => {
91
+ const out = (0, assert_output_js_1.assertOutput)({
92
+ kind: 'blocked',
93
+ continueToken: pending ? nextTokens.continueToken : undefined,
94
+ checkpointToken: pending ? nextTokens.checkpointToken : undefined,
95
+ isComplete,
96
+ pending: (0, output_schemas_js_1.toPendingStep)(blockedMeta),
97
+ preferences,
98
+ nextIntent,
99
+ nextCall: (0, index_js_2.buildNextCall)({ continueToken: pending ? nextTokens.continueToken : undefined, isComplete, pending: blockedMeta, retryContinueToken }),
100
+ blockers,
101
+ retryable,
102
+ retryContinueToken,
103
+ validation,
104
+ assessmentFollowup,
105
+ }, assert_output_js_1.assertContinueTokenPresence);
106
+ return (0, neverthrow_1.okAsync)(out);
107
+ }));
101
108
  }
102
109
  let okMeta = null;
103
110
  if (pending) {
@@ -109,29 +116,39 @@ function buildAdvancedReplayResponse(args) {
109
116
  runId: (0, index_js_1.asRunId)(String(runId)),
110
117
  nodeId: (0, index_js_1.asNodeId)(String(toNodeIdBranded)),
111
118
  rehydrateOnly: false,
119
+ precomputedIndex: args.precomputedIndex,
120
+ cleanResponseFormat: args.cleanResponseFormat,
112
121
  });
113
122
  if (result.isErr()) {
114
123
  return (0, neverthrow_1.errAsync)({ kind: 'prompt_render_failed', message: result.error.message });
115
124
  }
116
125
  okMeta = result.value;
117
126
  }
118
- const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId: toNodeIdBranded });
127
+ const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId: toNodeIdBranded, precomputedIndex: args.precomputedIndex });
119
128
  const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: false, isComplete, pending: okMeta });
120
129
  const stepContext = buildStepContext(truth.events, fromNodeId);
121
- return nextTokensMint.andThen((nextTokens) => (0, neverthrow_1.okAsync)(output_schemas_js_1.V2ContinueWorkflowOutputSchema.parse({
122
- kind: 'ok',
123
- continueToken: pending ? nextTokens.continueToken : undefined,
124
- checkpointToken: pending ? nextTokens.checkpointToken : undefined,
125
- isComplete,
126
- pending: (0, output_schemas_js_1.toPendingStep)(okMeta),
127
- preferences,
128
- nextIntent,
129
- nextCall: (0, index_js_2.buildNextCall)({ continueToken: pending ? nextTokens.continueToken : undefined, isComplete, pending: okMeta }),
130
- stepContext,
131
- })));
130
+ return nextTokensMint.andThen((nextTokens) => {
131
+ const out = (0, assert_output_js_1.assertOutput)({
132
+ kind: 'ok',
133
+ continueToken: pending ? nextTokens.continueToken : undefined,
134
+ checkpointToken: pending ? nextTokens.checkpointToken : undefined,
135
+ isComplete,
136
+ pending: (0, output_schemas_js_1.toPendingStep)(okMeta),
137
+ preferences,
138
+ nextIntent,
139
+ nextCall: (0, index_js_2.buildNextCall)({ continueToken: pending ? nextTokens.continueToken : undefined, isComplete, pending: okMeta }),
140
+ stepContext,
141
+ }, assert_output_js_1.assertContinueTokenPresence);
142
+ return (0, neverthrow_1.okAsync)(out);
143
+ });
132
144
  }
133
145
  function buildStepContext(events, completedNodeId) {
134
- const projection = (0, assessments_js_1.projectAssessmentsV2)(events);
146
+ const sortedEventsRes = (0, sorted_event_log_js_1.asSortedEventLog)(events);
147
+ if (sortedEventsRes.isErr()) {
148
+ console.warn(`[workrail:replay] stepContext events unsorted for node '${String(completedNodeId)}' — stepContext will be absent: ${sortedEventsRes.error.message}`);
149
+ return undefined;
150
+ }
151
+ const projection = (0, assessments_js_1.projectAssessmentsV2)(sortedEventsRes.value);
135
152
  if (projection.isErr()) {
136
153
  console.warn(`[workrail:replay] stepContext projection failed for node '${String(completedNodeId)}' — stepContext will be absent: ${projection.error.message}`);
137
154
  return undefined;
@@ -160,7 +177,8 @@ function replayFromRecordedAdvance(args) {
160
177
  });
161
178
  }
162
179
  const toNodeId = (0, index_js_1.asNodeId)(String(recordedEvent.data.outcome.toNodeId));
163
- const toNode = truth.events.find((e) => e.kind === constants_js_1.EVENT_KIND.NODE_CREATED && e.scope?.nodeId === String(toNodeId));
180
+ const toNode = args.precomputedIndex?.nodeCreatedByNodeId.get(String(toNodeId))
181
+ ?? truth.events.find((e) => e.kind === constants_js_1.EVENT_KIND.NODE_CREATED && e.scope?.nodeId === String(toNodeId));
164
182
  if (!toNode) {
165
183
  return (0, neverthrow_1.errAsync)({
166
184
  kind: 'invariant_violation',
@@ -191,6 +209,8 @@ function replayFromRecordedAdvance(args) {
191
209
  sha256,
192
210
  aliasStore,
193
211
  entropy,
212
+ precomputedIndex: args.precomputedIndex,
213
+ cleanResponseFormat: args.cleanResponseFormat,
194
214
  });
195
215
  });
196
216
  }
@@ -1,6 +1,5 @@
1
1
  import type { V2ToolContext } from '../../types.js';
2
- import { V2StartWorkflowOutputSchema } from '../../output-schemas.js';
3
- import { createWorkflow } from '../../../types/workflow.js';
2
+ import type { V2StartWorkflowOutputSchema } from '../../output-schemas.js';
4
3
  import type { DomainEventV1 } from '../../../v2/durable-core/schemas/session/index.js';
5
4
  import { type SessionId, type RunId, type NodeId, type WorkflowHash } from '../../../v2/durable-core/ids/index.js';
6
5
  import type { Sha256PortV2 } from '../../../v2/ports/sha256.port.js';
@@ -26,7 +25,7 @@ export declare function loadAndPinWorkflow(args: {
26
25
  }): RA<{
27
26
  readonly workflow: import('../../../types/workflow.js').Workflow;
28
27
  readonly workflowHash: WorkflowHash;
29
- readonly pinnedWorkflow: ReturnType<typeof createWorkflow>;
28
+ readonly pinnedWorkflow: import('../../../types/workflow.js').Workflow;
30
29
  readonly firstStep: {
31
30
  readonly id: string;
32
31
  };
@@ -6,15 +6,14 @@ exports.mintStartTokens = mintStartTokens;
6
6
  exports.executeStartWorkflow = executeStartWorkflow;
7
7
  const output_schemas_js_1 = require("../../output-schemas.js");
8
8
  const step_instance_key_js_1 = require("../../../v2/durable-core/schemas/execution-snapshot/step-instance-key.js");
9
- const workflow_js_1 = require("../../../types/workflow.js");
10
9
  const index_js_1 = require("../../../v2/durable-core/ids/index.js");
11
10
  const workflow_hash_ref_js_1 = require("../../../v2/durable-core/ids/workflow-hash-ref.js");
12
11
  const neverthrow_1 = require("neverthrow");
13
12
  const workflow_validation_pipeline_js_1 = require("../../../application/services/workflow-validation-pipeline.js");
14
13
  const hashing_js_1 = require("../../../v2/durable-core/canonical/hashing.js");
15
14
  const observation_builder_js_1 = require("../../../v2/durable-core/domain/observation-builder.js");
16
- const workflow_source_js_1 = require("../../../types/workflow-source.js");
17
15
  const workflow_definition_js_1 = require("../../../types/workflow-definition.js");
16
+ const workflow_object_cache_js_1 = require("./workflow-object-cache.js");
18
17
  const prompt_renderer_js_1 = require("../../../v2/durable-core/domain/prompt-renderer.js");
19
18
  const v2_workspace_resolution_js_1 = require("../v2-workspace-resolution.js");
20
19
  const v2_token_ops_js_1 = require("../v2-token-ops.js");
@@ -27,6 +26,8 @@ const request_workflow_reader_js_1 = require("../shared/request-workflow-reader.
27
26
  const step_content_envelope_js_1 = require("../../step-content-envelope.js");
28
27
  const v2_workspace_resolution_js_2 = require("../v2-workspace-resolution.js");
29
28
  const v2_reference_resolver_js_1 = require("../v2-reference-resolver.js");
29
+ const with_timeout_js_1 = require("../shared/with-timeout.js");
30
+ const REFERENCE_RESOLUTION_TIMEOUT_MS = 5000;
30
31
  function loadAndPinWorkflow(args) {
31
32
  const { workflowId, workflowReader, crypto, pinnedStore, validationPipelineDeps, workspacePath, resolvedRootUris } = args;
32
33
  return neverthrow_1.ResultAsync.fromPromise(workflowReader.getWorkflowById(workflowId), (e) => ({
@@ -73,13 +74,13 @@ function loadAndPinWorkflow(args) {
73
74
  return pinnedStore.get(workflowHash)
74
75
  .mapErr((cause) => ({ kind: 'pinned_workflow_store_failed', cause }))
75
76
  .andThen((existingPinned) => {
76
- if (!existingPinned) {
77
- return pinnedStore.put(workflowHash, enrichedCompiled)
78
- .mapErr((cause) => ({ kind: 'pinned_workflow_store_failed', cause }));
77
+ if (existingPinned) {
78
+ return (0, neverthrow_1.okAsync)(existingPinned);
79
79
  }
80
- return (0, neverthrow_1.okAsync)(undefined);
80
+ return pinnedStore.put(workflowHash, enrichedCompiled)
81
+ .mapErr((cause) => ({ kind: 'pinned_workflow_store_failed', cause }))
82
+ .map(() => enrichedCompiled);
81
83
  })
82
- .andThen(() => pinnedStore.get(workflowHash).mapErr((cause) => ({ kind: 'pinned_workflow_store_failed', cause })))
83
84
  .andThen((pinned) => {
84
85
  if (!pinned || pinned.sourceKind !== 'v1_pinned' || !(0, workflow_definition_js_1.hasWorkflowDefinitionShape)(pinned.definition)) {
85
86
  return (0, neverthrow_1.errAsync)({
@@ -87,7 +88,7 @@ function loadAndPinWorkflow(args) {
87
88
  message: 'Failed to pin executable workflow snapshot (missing or invalid pinned workflow).',
88
89
  });
89
90
  }
90
- const pinnedWorkflow = (0, workflow_js_1.createWorkflow)(pinned.definition, (0, workflow_source_js_1.createBundledSource)());
91
+ const pinnedWorkflow = (0, workflow_object_cache_js_1.getCachedWorkflow)(workflowHash, pinned.definition);
91
92
  const resolution = (0, start_construction_js_1.resolveFirstStep)(workflow, pinned);
92
93
  if (resolution.isErr()) {
93
94
  const error = resolution.error.reason === 'no_steps'
@@ -240,10 +241,11 @@ function executeStartWorkflow(input, ctx) {
240
241
  workspacePath: input.workspacePath,
241
242
  resolvedRootUris: ctx.v2.resolvedRootUris,
242
243
  rememberedRootsStore: ctx.v2.rememberedRootsStore,
244
+ managedSourceStore: ctx.v2.managedSourceStore,
243
245
  }), (err) => ({
244
246
  kind: 'precondition_failed',
245
247
  message: `Failed to initialize workflow reader: ${String(err)}`,
246
- })).map(({ reader, stalePaths }) => ({
248
+ })).map(({ reader, stalePaths, managedStoreError }) => ({
247
249
  workflowReader: {
248
250
  getWorkflowById: async (workflowId) => {
249
251
  const requestResult = await reader.getWorkflowById(workflowId);
@@ -253,21 +255,24 @@ function executeStartWorkflow(input, ctx) {
253
255
  },
254
256
  },
255
257
  stalePaths,
258
+ managedStoreError,
256
259
  }))
257
- : (0, neverthrow_1.okAsync)({ workflowReader: ctx.workflowService, stalePaths: [] });
258
- return readerRA.andThen(({ workflowReader, stalePaths }) => loadAndPinWorkflow({
259
- workflowId: input.workflowId,
260
- workflowReader,
261
- crypto,
262
- pinnedStore,
263
- validationPipelineDeps,
264
- workspacePath: input.workspacePath,
265
- resolvedRootUris: ctx.v2.resolvedRootUris,
266
- })
267
- .andThen(({ workflow, firstStep, workflowHash, pinnedWorkflow, resolvedReferences }) => {
268
- const anchorsRA = (0, v2_workspace_resolution_js_1.resolveWorkspaceAnchors)(ctx.v2, input.workspacePath)
269
- .map((anchors) => (0, observation_builder_js_1.anchorsToObservations)(anchors));
270
- return anchorsRA.andThen((observations) => {
260
+ : (0, neverthrow_1.okAsync)({ workflowReader: ctx.workflowService, stalePaths: [], managedStoreError: undefined });
261
+ const anchorsRA = (0, v2_workspace_resolution_js_1.resolveWorkspaceAnchors)(ctx.v2, input.workspacePath)
262
+ .map((anchors) => (0, observation_builder_js_1.anchorsToObservations)(anchors))
263
+ .mapErr((x) => x);
264
+ return readerRA.andThen(({ workflowReader, stalePaths, managedStoreError }) => {
265
+ const pinnedRA = loadAndPinWorkflow({
266
+ workflowId: input.workflowId,
267
+ workflowReader,
268
+ crypto,
269
+ pinnedStore,
270
+ validationPipelineDeps,
271
+ workspacePath: input.workspacePath,
272
+ resolvedRootUris: ctx.v2.resolvedRootUris,
273
+ });
274
+ return neverthrow_1.ResultAsync.combine([pinnedRA, anchorsRA])
275
+ .andThen(([{ workflow, firstStep, workflowHash, pinnedWorkflow, resolvedReferences }, observations]) => {
271
276
  const sessionId = idFactory.mintSessionId();
272
277
  const runId = idFactory.mintRunId();
273
278
  const nodeId = idFactory.mintNodeId();
@@ -309,16 +314,17 @@ function executeStartWorkflow(input, ctx) {
309
314
  idFactory,
310
315
  goal: input.goal,
311
316
  });
317
+ const emptyTruth = { manifest: [], events: [] };
312
318
  return gate.withHealthySessionLock(sessionId, (lock) => sessionStore.append(lock, {
313
319
  events,
314
320
  snapshotPins: [{ snapshotRef, eventIndex: 2, createdByEventId: events[2].eventId }],
315
- }))
321
+ }, emptyTruth))
316
322
  .mapErr((cause) => ({ kind: 'session_append_failed', cause }))
317
- .map(() => ({ workflow, firstStep, workflowHash, pinnedWorkflow, resolvedReferences, sessionId, runId, nodeId }));
323
+ .map(() => ({ workflow, firstStep, workflowHash, pinnedWorkflow, resolvedReferences, sessionId, runId, nodeId, stalePaths, managedStoreError }));
318
324
  });
319
325
  });
320
326
  })
321
- .andThen(({ pinnedWorkflow, firstStep, workflowHash, sessionId, runId, nodeId, resolvedReferences }) => {
327
+ .andThen(({ pinnedWorkflow, firstStep, workflowHash, sessionId, runId, nodeId, resolvedReferences, stalePaths, managedStoreError }) => {
322
328
  const wfRefRes = (0, workflow_hash_ref_js_1.deriveWorkflowHashRef)(workflowHash);
323
329
  if (wfRefRes.isErr()) {
324
330
  return (0, neverthrow_1.errAsync)({
@@ -346,6 +352,7 @@ function executeStartWorkflow(input, ctx) {
346
352
  runId: (0, index_js_1.asRunId)(String(runId)),
347
353
  nodeId: (0, index_js_1.asNodeId)(String(nodeId)),
348
354
  rehydrateOnly: false,
355
+ cleanResponseFormat: ctx.featureFlags?.isEnabled('cleanResponseFormat') ?? false,
349
356
  });
350
357
  if (metaResult.isErr()) {
351
358
  return (0, neverthrow_1.errAsync)({
@@ -361,7 +368,10 @@ function executeStartWorkflow(input, ctx) {
361
368
  meta,
362
369
  references: resolvedReferences,
363
370
  });
364
- const parsed = output_schemas_js_1.V2StartWorkflowOutputSchema.parse({
371
+ const startWarnings = managedStoreError !== undefined
372
+ ? [`Managed workflow source store was temporarily unavailable (${managedStoreError}). Managed sources were not loaded.`]
373
+ : undefined;
374
+ const parsed = {
365
375
  continueToken: tokens.continueToken,
366
376
  checkpointToken: tokens.checkpointToken,
367
377
  isComplete: false,
@@ -370,16 +380,34 @@ function executeStartWorkflow(input, ctx) {
370
380
  nextIntent,
371
381
  nextCall: (0, index_js_2.buildNextCall)({ continueToken: tokens.continueToken, isComplete: false, pending }),
372
382
  ...(stalePaths.length > 0 ? { staleRoots: [...stalePaths] } : {}),
373
- });
383
+ ...(startWarnings !== undefined ? { warnings: startWarnings } : {}),
384
+ };
374
385
  return (0, neverthrow_1.okAsync)({ response: parsed, contentEnvelope });
375
386
  });
376
- }));
387
+ });
377
388
  }
378
389
  function enrichPinnedSnapshotWithResolvedReferences(snapshot, references, workspacePath) {
379
390
  if (references.length === 0) {
380
391
  return (0, neverthrow_1.okAsync)({ snapshot, resolvedReferences: [] });
381
392
  }
382
- return neverthrow_1.ResultAsync.fromPromise((0, v2_reference_resolver_js_1.resolveWorkflowReferences)(references, workspacePath), () => ({ kind: 'reference_resolution_failed' })).map((result) => {
393
+ const allUnresolved = references.map((ref) => ({
394
+ id: ref.id,
395
+ title: ref.title,
396
+ source: ref.source,
397
+ purpose: ref.purpose,
398
+ authoritative: ref.authoritative,
399
+ resolveFrom: (ref.resolveFrom ?? 'workspace'),
400
+ status: 'unresolved',
401
+ }));
402
+ const resolutionPromise = (0, with_timeout_js_1.withTimeout)((0, v2_reference_resolver_js_1.resolveWorkflowReferences)(references, workspacePath), REFERENCE_RESOLUTION_TIMEOUT_MS, 'reference_resolution').catch(() => null);
403
+ return neverthrow_1.ResultAsync.fromPromise(resolutionPromise, () => ({ kind: 'reference_resolution_failed' })).map((result) => {
404
+ if (result === null) {
405
+ console.warn('[workrail:reference-resolution] timed out; all references marked unresolved');
406
+ return {
407
+ snapshot: { ...snapshot, resolvedReferences: [...allUnresolved] },
408
+ resolvedReferences: allUnresolved,
409
+ };
410
+ }
383
411
  for (const warning of result.warnings) {
384
412
  console.warn(`[workrail:reference-resolution] ${warning.message}`);
385
413
  }
@@ -0,0 +1,5 @@
1
+ import type { WorkflowDefinition } from '../../../types/workflow-definition.js';
2
+ import type { Workflow } from '../../../types/workflow.js';
3
+ import type { WorkflowHash } from '../../../v2/durable-core/ids/index.js';
4
+ export declare function getCachedWorkflow(workflowHash: WorkflowHash, definition: WorkflowDefinition): Workflow;
5
+ export declare function clearWorkflowObjectCacheForTesting(): void;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCachedWorkflow = getCachedWorkflow;
4
+ exports.clearWorkflowObjectCacheForTesting = clearWorkflowObjectCacheForTesting;
5
+ const workflow_js_1 = require("../../../types/workflow.js");
6
+ const workflow_source_js_1 = require("../../../types/workflow-source.js");
7
+ const _cache = new Map();
8
+ function getCachedWorkflow(workflowHash, definition) {
9
+ const key = String(workflowHash);
10
+ const existing = _cache.get(key);
11
+ if (existing !== undefined)
12
+ return existing;
13
+ const wf = (0, workflow_js_1.createWorkflow)(definition, (0, workflow_source_js_1.createBundledSource)());
14
+ _cache.set(key, wf);
15
+ return wf;
16
+ }
17
+ function clearWorkflowObjectCacheForTesting() {
18
+ _cache.clear();
19
+ }
@@ -120,4 +120,5 @@ export declare function derivePreferencesOrDefault(args: {
120
120
  readonly truth: LoadedSessionTruthV2;
121
121
  readonly runId: RunId;
122
122
  readonly nodeId: NodeId;
123
+ readonly precomputedIndex?: import('../../v2/durable-core/session-index.js').SessionIndex;
123
124
  }): PreferencesV2;
@@ -266,20 +266,36 @@ function mapSessionOrGateErrorToToolError(e) {
266
266
  }
267
267
  const constants_js_1 = require("../../v2/durable-core/constants.js");
268
268
  const preferences_js_1 = require("../../v2/projections/preferences.js");
269
+ const sorted_event_log_js_1 = require("../../v2/durable-core/sorted-event-log.js");
269
270
  exports.defaultPreferences = {
270
271
  autonomy: 'guided',
271
272
  riskPolicy: 'conservative'
272
273
  };
273
274
  function derivePreferencesOrDefault(args) {
275
+ let sortedEventsForPrefs;
274
276
  const parentByNodeId = {};
275
- for (const e of args.truth.events) {
276
- if (e.kind !== constants_js_1.EVENT_KIND.NODE_CREATED)
277
- continue;
278
- if (e.scope?.runId !== String(args.runId))
279
- continue;
280
- parentByNodeId[String(e.scope.nodeId)] = e.data.parentNodeId;
277
+ if (args.precomputedIndex) {
278
+ sortedEventsForPrefs = args.precomputedIndex.sortedEvents;
279
+ for (const [nodeId, evt] of args.precomputedIndex.nodeCreatedByNodeId) {
280
+ if (evt.scope.runId === String(args.runId)) {
281
+ parentByNodeId[nodeId] = evt.data.parentNodeId ?? null;
282
+ }
283
+ }
284
+ }
285
+ else {
286
+ for (const e of args.truth.events) {
287
+ if (e.kind !== constants_js_1.EVENT_KIND.NODE_CREATED)
288
+ continue;
289
+ if (e.scope?.runId !== String(args.runId))
290
+ continue;
291
+ parentByNodeId[String(e.scope.nodeId)] = e.data.parentNodeId;
292
+ }
293
+ const sortedEventsRes = (0, sorted_event_log_js_1.asSortedEventLog)(args.truth.events);
294
+ if (sortedEventsRes.isErr())
295
+ return exports.defaultPreferences;
296
+ sortedEventsForPrefs = sortedEventsRes.value;
281
297
  }
282
- const prefs = (0, preferences_js_1.projectPreferencesV2)(args.truth.events, parentByNodeId);
298
+ const prefs = (0, preferences_js_1.projectPreferencesV2)(sortedEventsForPrefs, parentByNodeId);
283
299
  if (prefs.isErr())
284
300
  return exports.defaultPreferences;
285
301
  const p = prefs.value.byNodeId[String(args.nodeId)]?.effective;
@@ -1,7 +1,7 @@
1
1
  import type { z } from 'zod';
2
2
  import type { V2ResumeSessionInput } from '../v2/tools.js';
3
3
  import type { ToolContext, ToolResult } from '../types.js';
4
- import { V2ResumeSessionOutputSchema } from '../output-schemas.js';
4
+ import type { V2ResumeSessionOutputSchema } from '../output-schemas.js';
5
5
  type ResumeInput = z.infer<typeof V2ResumeSessionInput>;
6
6
  type ResumeOutput = z.infer<typeof V2ResumeSessionOutputSchema>;
7
7
  export declare function handleV2ResumeSession(input: ResumeInput, ctx: ToolContext): Promise<ToolResult<ResumeOutput>>;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleV2ResumeSession = handleV2ResumeSession;
4
4
  const types_js_1 = require("../types.js");
5
- const output_schemas_js_1 = require("../output-schemas.js");
6
5
  const v2_token_ops_js_1 = require("./v2-token-ops.js");
7
6
  const index_js_1 = require("../../v2/durable-core/ids/index.js");
8
7
  const resume_session_js_1 = require("../../v2/usecases/resume-session.js");
@@ -43,10 +42,10 @@ async function handleV2ResumeSession(input, ctx) {
43
42
  if (skipped > 0) {
44
43
  console.error(`[workrail:resume] ${skipped}/${candidates.length} candidate(s) skipped: token minting failed (workflowHashRef derivation or signing error)`);
45
44
  }
46
- const output = output_schemas_js_1.V2ResumeSessionOutputSchema.parse({
47
- candidates: outputCandidates,
45
+ const output = {
46
+ candidates: [...outputCandidates],
48
47
  totalEligible: totalFound,
49
- });
48
+ };
50
49
  return {
51
50
  type: 'success',
52
51
  data: output,
@@ -9,6 +9,7 @@ exports.derivePreferencesForNode = derivePreferencesForNode;
9
9
  exports.deriveNextIntent = deriveNextIntent;
10
10
  const step_instance_key_js_1 = require("../../v2/durable-core/schemas/execution-snapshot/step-instance-key.js");
11
11
  const preferences_js_1 = require("../../v2/projections/preferences.js");
12
+ const sorted_event_log_js_1 = require("../../v2/durable-core/sorted-event-log.js");
12
13
  const constants_js_1 = require("../../v2/durable-core/constants.js");
13
14
  function toV1ExecutionState(engineState) {
14
15
  if (engineState.kind === 'init')
@@ -94,7 +95,10 @@ function derivePreferencesForNode(args) {
94
95
  continue;
95
96
  parentByNodeId[String(e.scope.nodeId)] = e.data.parentNodeId;
96
97
  }
97
- const prefs = (0, preferences_js_1.projectPreferencesV2)(args.truth.events, parentByNodeId);
98
+ const sortedEventsRes = (0, sorted_event_log_js_1.asSortedEventLog)(args.truth.events);
99
+ if (sortedEventsRes.isErr())
100
+ return exports.defaultPreferences;
101
+ const prefs = (0, preferences_js_1.projectPreferencesV2)(sortedEventsRes.value, parentByNodeId);
98
102
  if (prefs.isErr())
99
103
  return exports.defaultPreferences;
100
104
  const p = prefs.value.byNodeId[String(args.nodeId)]?.effective;
@@ -1,6 +1,10 @@
1
1
  import type { ToolContext, ToolResult } from '../types.js';
2
2
  import type { V2InspectWorkflowInput, V2ListWorkflowsInput } from '../v2/tools.js';
3
3
  import type { StalenessSummary } from '../output-schemas.js';
4
+ import type { RememberedRootRecordV2 } from '../../v2/ports/remembered-roots-store.port.js';
5
+ import type { CryptoPortV2 } from '../../v2/durable-core/canonical/hashing.js';
6
+ import type { PinnedWorkflowStorePortV2 } from '../../v2/ports/pinned-workflow-store.port.js';
7
+ import type { Workflow } from '../../types/workflow.js';
4
8
  export declare function shouldShowStaleness(category: string | undefined, devMode?: boolean): boolean;
5
9
  interface WorkflowTagsFile {
6
10
  readonly tags: ReadonlyArray<{
@@ -22,6 +26,82 @@ export declare function buildTagSummary(tagsFile: WorkflowTagsFile, compiledWork
22
26
  examples: string[];
23
27
  }>;
24
28
  export declare function computeWorkflowStaleness(stamp: number | undefined, currentVersion: number | null): StalenessSummary | undefined;
29
+ interface WorkflowLookupReader {
30
+ readonly getWorkflowById: (id: string) => Promise<Workflow | null>;
31
+ readonly listWorkflowSummaries: () => Promise<readonly {
32
+ readonly id: string;
33
+ readonly name: string;
34
+ readonly description: string;
35
+ readonly version: string;
36
+ }[]>;
37
+ readonly loadAllWorkflows: () => Promise<readonly Workflow[]>;
38
+ }
25
39
  export declare function handleV2ListWorkflows(input: V2ListWorkflowsInput, ctx: ToolContext): Promise<ToolResult<unknown>>;
26
40
  export declare function handleV2InspectWorkflow(input: V2InspectWorkflowInput, ctx: ToolContext): Promise<ToolResult<unknown>>;
41
+ export declare function buildV2WorkflowListItem(options: {
42
+ readonly workflow: Workflow | null;
43
+ readonly summary: {
44
+ readonly id: string;
45
+ readonly name: string;
46
+ readonly description: string;
47
+ readonly version: string;
48
+ };
49
+ readonly workflowReader: WorkflowLookupReader;
50
+ readonly rememberedRootRecords: readonly RememberedRootRecordV2[];
51
+ readonly crypto: CryptoPortV2;
52
+ readonly pinnedStore: PinnedWorkflowStorePortV2;
53
+ }): Promise<{
54
+ workflowId: string;
55
+ name: string;
56
+ description: string;
57
+ version: string;
58
+ workflowHash: null;
59
+ kind: "workflow";
60
+ } | {
61
+ examples: string[];
62
+ workflowId: string;
63
+ name: string;
64
+ description: string;
65
+ version: string;
66
+ workflowHash: null;
67
+ kind: "workflow";
68
+ visibility: import("./shared/workflow-source-visibility.js").WorkflowVisibility;
69
+ } | {
70
+ examples?: undefined;
71
+ workflowId: string;
72
+ name: string;
73
+ description: string;
74
+ version: string;
75
+ workflowHash: null;
76
+ kind: "workflow";
77
+ visibility: import("./shared/workflow-source-visibility.js").WorkflowVisibility;
78
+ } | {
79
+ examples: string[];
80
+ staleness?: {
81
+ level: "none" | "possible" | "likely";
82
+ reason: string;
83
+ specVersionAtLastReview?: number | undefined;
84
+ } | undefined;
85
+ workflowId: string;
86
+ name: string;
87
+ description: string;
88
+ version: string;
89
+ workflowHash: never;
90
+ kind: "workflow";
91
+ visibility: import("./shared/workflow-source-visibility.js").WorkflowVisibility;
92
+ } | {
93
+ examples?: undefined;
94
+ staleness?: {
95
+ level: "none" | "possible" | "likely";
96
+ reason: string;
97
+ specVersionAtLastReview?: number | undefined;
98
+ } | undefined;
99
+ workflowId: string;
100
+ name: string;
101
+ description: string;
102
+ version: string;
103
+ workflowHash: never;
104
+ kind: "workflow";
105
+ visibility: import("./shared/workflow-source-visibility.js").WorkflowVisibility;
106
+ }>;
27
107
  export {};