@codemation/core 0.0.19 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/EngineRuntimeRegistration.types-0sgV2XL2.d.ts +42 -0
  3. package/dist/EngineWorkflowRunnerService-Dx7bJsJR.d.cts +73 -0
  4. package/dist/InMemoryRunDataFactory-qIYQEar7.d.cts +94 -0
  5. package/dist/{InMemoryLiveWorkflowRepository-DxoualoC.d.ts → RunIntentService-BCvGdOSY.d.ts} +438 -9
  6. package/dist/{RunIntentService-C1nu_YwM.js → RunIntentService-BFA48UpH.js} +252 -67
  7. package/dist/RunIntentService-BFA48UpH.js.map +1 -0
  8. package/dist/{InMemoryLiveWorkflowRepository-orY1VsWG.d.cts → RunIntentService-CV8izV8t.d.cts} +214 -7
  9. package/dist/{RunIntentService-ZkjpY7MS.cjs → RunIntentService-DcxXf_AM.cjs} +262 -65
  10. package/dist/RunIntentService-DcxXf_AM.cjs.map +1 -0
  11. package/dist/bootstrap/index.cjs +14 -1135
  12. package/dist/bootstrap/index.d.cts +7 -60
  13. package/dist/bootstrap/index.d.ts +4 -40
  14. package/dist/bootstrap/index.js +3 -1122
  15. package/dist/bootstrap-D67Sf2BF.js +1136 -0
  16. package/dist/bootstrap-D67Sf2BF.js.map +1 -0
  17. package/dist/bootstrap-DoQHAEQJ.cjs +1203 -0
  18. package/dist/bootstrap-DoQHAEQJ.cjs.map +1 -0
  19. package/dist/{index-BIewO9-9.d.ts → index-CueSzHsf.d.ts} +37 -260
  20. package/dist/index.cjs +99 -223
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +201 -6
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.js +93 -218
  25. package/dist/index.js.map +1 -1
  26. package/dist/testing.cjs +329 -3
  27. package/dist/testing.cjs.map +1 -1
  28. package/dist/testing.d.cts +181 -4
  29. package/dist/testing.d.ts +181 -3
  30. package/dist/testing.js +319 -2
  31. package/dist/testing.js.map +1 -1
  32. package/dist/workflowActivationPolicy-B8HzTk3o.js +201 -0
  33. package/dist/workflowActivationPolicy-B8HzTk3o.js.map +1 -0
  34. package/dist/workflowActivationPolicy-BzyzXLa_.cjs +231 -0
  35. package/dist/workflowActivationPolicy-BzyzXLa_.cjs.map +1 -0
  36. package/package.json +1 -1
  37. package/src/ai/AgentConnectionNodeCollector.ts +99 -0
  38. package/src/ai/AgentToolFactory.ts +38 -2
  39. package/src/ai/AiHost.ts +1 -1
  40. package/src/authoring/defineNode.types.ts +6 -0
  41. package/src/browser.ts +11 -0
  42. package/src/contracts/executionPersistenceContracts.ts +186 -0
  43. package/src/contracts/index.ts +1 -0
  44. package/src/contracts/runFinishedAtFactory.ts +5 -2
  45. package/src/contracts/runTypes.ts +10 -0
  46. package/src/contracts/runtimeTypes.ts +6 -2
  47. package/src/contracts/workflowTypes.ts +3 -2
  48. package/src/events/EventPublishingWorkflowExecutionRepository.ts +5 -0
  49. package/src/execution/ActivationEnqueueService.ts +8 -8
  50. package/src/execution/PersistedRunStateTerminalBuilder.ts +3 -0
  51. package/src/index.ts +6 -0
  52. package/src/orchestration/NodeExecutionRequestHandlerService.ts +11 -6
  53. package/src/orchestration/RunContinuationService.ts +94 -24
  54. package/src/runStorage/InMemoryWorkflowExecutionRepository.ts +14 -1
  55. package/src/scheduler/DefaultDrivingScheduler.ts +21 -11
  56. package/src/scheduler/InlineDrivingScheduler.ts +17 -21
  57. package/src/testing/CapturingScheduler.ts +15 -0
  58. package/src/testing/EngineTestKitRunIdFactory.ts +24 -0
  59. package/src/testing/InMemoryTriggerSetupStateRepository.ts +21 -0
  60. package/src/testing/PrefixedSequentialIdGenerator.ts +17 -0
  61. package/src/testing/RegistrarEngineTestKit.types.ts +76 -0
  62. package/src/testing/RegistrarEngineTestKitFactory.ts +154 -0
  63. package/src/testing/SubWorkflowRunnerTestNode.ts +83 -0
  64. package/src/testing/WorkflowTestHarnessManualTrigger.ts +39 -0
  65. package/src/testing/WorkflowTestKit.types.ts +9 -0
  66. package/src/testing/WorkflowTestKitBuilder.ts +77 -0
  67. package/src/testing/WorkflowTestKitNodeRegistrationContextFactory.ts +17 -0
  68. package/src/testing/WorkflowTestKitRunNodeWorkflowFactory.ts +26 -0
  69. package/src/testing.ts +19 -0
  70. package/src/types/index.ts +1 -0
  71. package/src/workflow/definition/ConnectionNodeIdFactory.ts +28 -0
  72. package/dist/InMemoryLiveWorkflowRepository-BTzHpQ6e.cjs +0 -151
  73. package/dist/InMemoryLiveWorkflowRepository-BTzHpQ6e.cjs.map +0 -1
  74. package/dist/InMemoryLiveWorkflowRepository-BoLNnVLg.js +0 -139
  75. package/dist/InMemoryLiveWorkflowRepository-BoLNnVLg.js.map +0 -1
  76. package/dist/RunIntentService-C1nu_YwM.js.map +0 -1
  77. package/dist/RunIntentService-DjbxzBBP.d.cts +0 -288
  78. package/dist/RunIntentService-ZkjpY7MS.cjs.map +0 -1
  79. package/dist/WorkflowSnapshotCodec-DSEzKyt3.d.cts +0 -22
  80. package/dist/bootstrap/index.cjs.map +0 -1
  81. package/dist/bootstrap/index.js.map +0 -1
@@ -1,1126 +1,6 @@
1
- const require_RunIntentService = require('../RunIntentService-ZkjpY7MS.cjs');
2
- const require_InMemoryLiveWorkflowRepository = require('../InMemoryLiveWorkflowRepository-BTzHpQ6e.cjs');
3
- let tsyringe = require("tsyringe");
4
- tsyringe = require_RunIntentService.__toESM(tsyringe);
1
+ const require_RunIntentService = require('../RunIntentService-DcxXf_AM.cjs');
2
+ const require_bootstrap = require('../bootstrap-DoQHAEQJ.cjs');
5
3
 
6
- //#region src/policies/executionLimits/EngineExecutionLimitsPolicyFactory.ts
7
- /**
8
- * Builds {@link EngineExecutionLimitsPolicy} by merging {@link ENGINE_EXECUTION_LIMITS_DEFAULTS} with optional `overrides` (e.g. host `runtime.engineExecutionLimits`).
9
- */
10
- var EngineExecutionLimitsPolicyFactory = class {
11
- create(overrides) {
12
- return new require_RunIntentService.EngineExecutionLimitsPolicy({
13
- ...require_RunIntentService.ENGINE_EXECUTION_LIMITS_DEFAULTS,
14
- ...overrides
15
- });
16
- }
17
- };
18
-
19
- //#endregion
20
- //#region src/policies/storage/RunTerminalPersistenceCoordinator.ts
21
- var RunTerminalPersistenceCoordinator = class {
22
- constructor(runRepository, storageEvaluator) {
23
- this.runRepository = runRepository;
24
- this.storageEvaluator = storageEvaluator;
25
- }
26
- async maybeDeleteAfterTerminalState(args) {
27
- if (await this.storageEvaluator.shouldPersist(args.workflow, args.state.policySnapshot, {
28
- runId: args.state.runId,
29
- workflowId: args.state.workflowId,
30
- workflow: args.workflow,
31
- finalStatus: args.finalStatus,
32
- startedAt: args.state.startedAt,
33
- finishedAt: args.finishedAt
34
- })) return;
35
- if (!this.runRepository.deleteRun) return;
36
- await this.runRepository.deleteRun(args.state.runId);
37
- }
38
- };
39
-
40
- //#endregion
41
- //#region src/policies/WorkflowPolicyErrorServices.ts
42
- var WorkflowPolicyErrorServices = class {
43
- constructor(nodeResolver) {
44
- this.nodeResolver = nodeResolver;
45
- }
46
- resolveNodeErrorHandler(spec) {
47
- if (!spec) return void 0;
48
- if (typeof spec === "object" && spec !== null && "handle" in spec && typeof spec.handle === "function") return spec;
49
- return this.nodeResolver.resolve(spec);
50
- }
51
- resolveWorkflowErrorHandler(spec) {
52
- if (!spec) return void 0;
53
- if (typeof spec === "object" && spec !== null && "onError" in spec && typeof spec.onError === "function") return spec;
54
- return this.nodeResolver.resolve(spec);
55
- }
56
- };
57
-
58
- //#endregion
59
- //#region src/policies/storage/WorkflowStoragePolicyEvaluator.ts
60
- var WorkflowStoragePolicyEvaluator = class {
61
- constructor(nodeResolver) {
62
- this.nodeResolver = nodeResolver;
63
- }
64
- async shouldPersist(workflow, snapshot, args) {
65
- const spec = workflow.storagePolicy;
66
- if (spec === void 0) return this.modeMatches(snapshot?.storagePolicy ?? "ALL", args);
67
- if (typeof spec === "string") return this.modeMatches(spec, args);
68
- const resolver = this.nodeResolver.resolve(spec);
69
- return Boolean(await resolver.shouldPersist(args));
70
- }
71
- modeMatches(mode, args) {
72
- if (mode === "ALL") return true;
73
- if (mode === "NEVER") return false;
74
- if (mode === "SUCCESS") return args.finalStatus === "completed";
75
- if (mode === "ERROR") return args.finalStatus === "failed";
76
- return true;
77
- }
78
- };
79
-
80
- //#endregion
81
- //#region src/runStorage/RunSummaryMapper.ts
82
- /** Maps persisted run state to API run summaries for listings. */
83
- var RunSummaryMapper = class {
84
- static fromPersistedState(state) {
85
- return {
86
- runId: state.runId,
87
- workflowId: state.workflowId,
88
- startedAt: state.startedAt,
89
- status: state.status,
90
- finishedAt: require_RunIntentService.RunFinishedAtFactory.resolveIso(state),
91
- parent: state.parent,
92
- executionOptions: state.executionOptions
93
- };
94
- }
95
- };
96
-
97
- //#endregion
98
- //#region src/runStorage/InMemoryWorkflowExecutionRepository.ts
99
- var InMemoryWorkflowExecutionRepository = class {
100
- runs = /* @__PURE__ */ new Map();
101
- async createRun(args) {
102
- this.runs.set(args.runId, {
103
- runId: args.runId,
104
- workflowId: args.workflowId,
105
- startedAt: args.startedAt,
106
- parent: args.parent,
107
- executionOptions: args.executionOptions,
108
- control: args.control,
109
- workflowSnapshot: args.workflowSnapshot,
110
- mutableState: args.mutableState,
111
- policySnapshot: args.policySnapshot,
112
- engineCounters: args.engineCounters,
113
- status: "running",
114
- queue: [],
115
- outputsByNode: {},
116
- nodeSnapshotsByNodeId: {},
117
- connectionInvocations: []
118
- });
119
- }
120
- async load(runId) {
121
- return this.runs.get(runId);
122
- }
123
- async save(state) {
124
- this.runs.set(state.runId, state);
125
- }
126
- async deleteRun(runId) {
127
- this.runs.delete(runId);
128
- }
129
- async listRuns(args) {
130
- const limit = args?.limit ?? 50;
131
- return [...this.runs.values()].filter((s) => args?.workflowId ? s.workflowId === args.workflowId : true).sort((a, b) => b.startedAt.localeCompare(a.startedAt)).slice(0, limit).map((s) => RunSummaryMapper.fromPersistedState(s));
132
- }
133
- async listRunsOlderThan(args) {
134
- const limit = args.limit ?? 100;
135
- const out = [];
136
- for (const s of this.runs.values()) {
137
- if (s.status !== "completed" && s.status !== "failed") continue;
138
- const finishedAt = require_RunIntentService.RunFinishedAtFactory.resolveIso(s);
139
- if (!finishedAt || finishedAt >= args.beforeIso) continue;
140
- out.push({
141
- runId: s.runId,
142
- workflowId: s.workflowId,
143
- startedAt: s.startedAt,
144
- finishedAt
145
- });
146
- }
147
- out.sort((a, b) => a.finishedAt.localeCompare(b.finishedAt));
148
- return out.slice(0, limit);
149
- }
150
- };
151
-
152
- //#endregion
153
- //#region src/orchestration/NodeExecutionRequestHandlerService.ts
154
- var NodeExecutionRequestHandlerService = class {
155
- constructor(workflowExecutionRepository, workflowSnapshotResolver, runDataFactory, runExecutionContextFactory, nodeStatePublisherFactory, nodeActivationRequestComposer, nodeExecutor, continuation, executionLimitsPolicy) {
156
- this.workflowExecutionRepository = workflowExecutionRepository;
157
- this.workflowSnapshotResolver = workflowSnapshotResolver;
158
- this.runDataFactory = runDataFactory;
159
- this.runExecutionContextFactory = runExecutionContextFactory;
160
- this.nodeStatePublisherFactory = nodeStatePublisherFactory;
161
- this.nodeActivationRequestComposer = nodeActivationRequestComposer;
162
- this.nodeExecutor = nodeExecutor;
163
- this.continuation = continuation;
164
- this.executionLimitsPolicy = executionLimitsPolicy;
165
- }
166
- async handleNodeExecutionRequest(request) {
167
- const state = await this.workflowExecutionRepository.load(request.runId);
168
- if (!state) throw new Error(`Unknown runId: ${request.runId}`);
169
- if (state.workflowId !== request.workflowId) throw new Error(`workflowId mismatch for run ${request.runId}: ${state.workflowId} vs ${request.workflowId}`);
170
- if (state.status !== "pending" || !state.pending) return;
171
- if (state.pending.activationId !== request.activationId || state.pending.nodeId !== request.nodeId) return;
172
- const workflow = this.resolvePersistedWorkflow(state);
173
- if (!workflow) throw new Error(`Unknown workflowId: ${state.workflowId}`);
174
- const definition = workflow.nodes.find((node) => node.id === request.nodeId);
175
- if (!definition) throw new Error(`Unknown nodeId: ${request.nodeId}`);
176
- if (definition.kind !== "node") throw new Error(`Node ${request.nodeId} is not runnable`);
177
- const resolvedParent = request.parent ?? state.parent;
178
- const data = this.runDataFactory.create(state.outputsByNode);
179
- const limits = this.resolveEngineLimitsFromState(state);
180
- const base = this.runExecutionContextFactory.create({
181
- runId: state.runId,
182
- workflowId: state.workflowId,
183
- nodeId: request.nodeId,
184
- parent: resolvedParent,
185
- subworkflowDepth: state.executionOptions?.subworkflowDepth ?? 0,
186
- engineMaxNodeActivations: limits.engineMaxNodeActivations,
187
- engineMaxSubworkflowDepth: limits.engineMaxSubworkflowDepth,
188
- data,
189
- nodeState: this.nodeStatePublisherFactory.create(state.runId, state.workflowId, resolvedParent)
190
- });
191
- const activationRequest = this.nodeActivationRequestComposer.createSingleFromDefinitionWithActivation({
192
- activationId: request.activationId,
193
- runId: request.runId,
194
- workflowId: request.workflowId,
195
- parent: resolvedParent,
196
- executionOptions: request.executionOptions ?? state.executionOptions,
197
- base,
198
- data,
199
- definition: {
200
- id: definition.id,
201
- config: definition.config
202
- },
203
- batchId: state.pending.batchId ?? "batch_1",
204
- input: request.input
205
- });
206
- await this.continuation.markNodeRunning({
207
- runId: activationRequest.runId,
208
- activationId: activationRequest.activationId,
209
- nodeId: activationRequest.nodeId,
210
- inputsByPort: { in: activationRequest.input }
211
- });
212
- let outputs;
213
- try {
214
- outputs = await this.nodeExecutor.execute(activationRequest);
215
- } catch (error) {
216
- await this.resumeAfterExecutionError(activationRequest, this.asError(error));
217
- return;
218
- }
219
- await this.resumeAfterExecutionResult(activationRequest, outputs ?? {});
220
- }
221
- resolvePersistedWorkflow(state) {
222
- return this.workflowSnapshotResolver.resolve({
223
- workflowId: state.workflowId,
224
- workflowSnapshot: state.workflowSnapshot
225
- });
226
- }
227
- resolveEngineLimitsFromState(state) {
228
- const fallback = this.executionLimitsPolicy.createRootExecutionOptions();
229
- return {
230
- engineMaxNodeActivations: state.executionOptions?.maxNodeActivations ?? fallback.maxNodeActivations,
231
- engineMaxSubworkflowDepth: state.executionOptions?.maxSubworkflowDepth ?? fallback.maxSubworkflowDepth
232
- };
233
- }
234
- async resumeAfterExecutionResult(request, outputs) {
235
- try {
236
- await this.continuation.resumeFromNodeResult({
237
- runId: request.runId,
238
- activationId: request.activationId,
239
- nodeId: request.nodeId,
240
- outputs
241
- });
242
- } catch (error) {
243
- this.rethrowUnlessIgnorableContinuationError(error);
244
- }
245
- }
246
- async resumeAfterExecutionError(request, error) {
247
- try {
248
- await this.continuation.resumeFromNodeError({
249
- runId: request.runId,
250
- activationId: request.activationId,
251
- nodeId: request.nodeId,
252
- error
253
- });
254
- } catch (continuationError) {
255
- this.rethrowUnlessIgnorableContinuationError(continuationError);
256
- }
257
- }
258
- asError(error) {
259
- return error instanceof Error ? error : new Error(String(error));
260
- }
261
- rethrowUnlessIgnorableContinuationError(error) {
262
- if (this.isIgnorableContinuationError(error)) return;
263
- throw this.asError(error);
264
- }
265
- isIgnorableContinuationError(error) {
266
- const message = this.asError(error).message;
267
- return message.includes(" is not pending") || message.includes("activationId mismatch") || message.includes("nodeId mismatch");
268
- }
269
- };
270
-
271
- //#endregion
272
- //#region src/planning/RunQueuePlanner.ts
273
- var RunQueuePlanner = class {
274
- constructor(topology, nodeInstances) {
275
- this.topology = topology;
276
- this.nodeInstances = nodeInstances;
277
- }
278
- validateNodeKinds() {
279
- for (const [toNodeId, inputs] of this.topology.expectedInputsByNode.entries()) {
280
- if (inputs.length <= 1) {
281
- const only = inputs[0];
282
- if (only && only !== "in") {
283
- const inst$1 = this.nodeInstances.get(toNodeId);
284
- if (!this.isMultiInputNode(inst$1)) throw new Error(`Node ${toNodeId} only supports input 'in' (got '${only}').`);
285
- }
286
- continue;
287
- }
288
- const inst = this.nodeInstances.get(toNodeId);
289
- if (!this.isMultiInputNode(inst)) throw new Error(`Node ${toNodeId} has ${inputs.length} inbound edges. Insert a Merge node to combine branches.`);
290
- }
291
- }
292
- seedFromTrigger(args) {
293
- const queue = [];
294
- for (const e of this.topology.outgoingByNode.get(args.startNodeId) ?? []) {
295
- if (e.output !== "main") continue;
296
- this.enqueueEdge(queue, {
297
- batchId: args.batchId,
298
- to: e.to,
299
- from: {
300
- nodeId: args.startNodeId,
301
- output: "main"
302
- },
303
- items: args.items
304
- });
305
- }
306
- return queue;
307
- }
308
- applyOutputs(queue, args) {
309
- for (const e of this.topology.outgoingByNode.get(args.fromNodeId) ?? []) {
310
- const outItems = args.outputs[e.output] ?? [];
311
- this.enqueueEdge(queue, {
312
- batchId: args.batchId,
313
- to: e.to,
314
- from: {
315
- nodeId: args.fromNodeId,
316
- output: e.output
317
- },
318
- items: outItems
319
- });
320
- }
321
- }
322
- nextActivation(queue) {
323
- const readyCollect = this.resolveReadyCollect(queue);
324
- if (readyCollect) return readyCollect;
325
- const jobIdx = queue.findIndex((q) => !q.collect);
326
- if (jobIdx === -1) {
327
- if (queue.length === 0) return null;
328
- const sealedCollect = this.resolveSealedCollect(queue);
329
- if (sealedCollect) return sealedCollect;
330
- const stuck = queue[0];
331
- throw new Error(this.describeUnsatisfiedCollect(stuck));
332
- }
333
- const job = queue.splice(jobIdx, 1)[0];
334
- const def = this.topology.defsById.get(job.nodeId);
335
- if (!def || def.kind !== "node") return this.nextActivation(queue);
336
- return {
337
- kind: "single",
338
- nodeId: job.nodeId,
339
- input: job.input,
340
- batchId: job.batchId ?? "batch_1"
341
- };
342
- }
343
- sumItemsByPort(inputsByPort) {
344
- let n = 0;
345
- for (const v of Object.values(inputsByPort)) n += v?.length ?? 0;
346
- return n;
347
- }
348
- resolveReadyCollect(queue) {
349
- for (let i = 0; i < queue.length; i++) {
350
- const ready = this.tryDequeueCollect(queue, i);
351
- if (ready) return ready;
352
- }
353
- return null;
354
- }
355
- resolveSealedCollect(queue) {
356
- for (let i = 0; i < queue.length; i++) {
357
- const queueEntry = queue[i];
358
- if (!queueEntry.collect) continue;
359
- const received = queueEntry.collect.received;
360
- if (Object.keys(received).length === 0) continue;
361
- this.fillMissingCollectInputs(queueEntry);
362
- const ready = this.tryDequeueCollect(queue, i);
363
- if (ready) return ready;
364
- }
365
- return null;
366
- }
367
- tryDequeueCollect(queue, index) {
368
- const queueEntry = queue[index];
369
- if (!queueEntry.collect) return null;
370
- const batchId = queueEntry.batchId ?? "batch_1";
371
- const expected = queueEntry.collect.expectedInputs ?? [];
372
- const received = queueEntry.collect.received;
373
- for (const input of expected) if (!(input in received)) return null;
374
- queue.splice(index, 1);
375
- return {
376
- kind: "multi",
377
- nodeId: queueEntry.nodeId,
378
- inputsByPort: received,
379
- batchId
380
- };
381
- }
382
- fillMissingCollectInputs(queueEntry) {
383
- if (!queueEntry.collect) return;
384
- const received = queueEntry.collect.received;
385
- for (const input of queueEntry.collect.expectedInputs ?? []) if (!(input in received)) received[input] = [];
386
- }
387
- enqueueEdge(queue, args) {
388
- const target = this.nodeInstances.get(args.to.nodeId);
389
- if (!this.isMultiInputNode(target)) {
390
- if (args.items.length === 0) {
391
- if (this.shouldContinueAfterEmptyOutputFromSource(args.from.nodeId)) {
392
- queue.push({
393
- nodeId: args.to.nodeId,
394
- input: args.items,
395
- toInput: args.to.input,
396
- batchId: args.batchId,
397
- from: args.from
398
- });
399
- return;
400
- }
401
- this.propagateEmptyPath(queue, args.to.nodeId, args.batchId);
402
- return;
403
- }
404
- queue.push({
405
- nodeId: args.to.nodeId,
406
- input: args.items,
407
- toInput: args.to.input,
408
- batchId: args.batchId,
409
- from: args.from
410
- });
411
- return;
412
- }
413
- const expected = this.topology.expectedInputsByNode.get(args.to.nodeId) ?? [];
414
- let collect = queue.find((q) => q.nodeId === args.to.nodeId && (q.batchId ?? "batch_1") === args.batchId && !!q.collect);
415
- if (!collect) {
416
- collect = {
417
- nodeId: args.to.nodeId,
418
- input: [],
419
- batchId: args.batchId,
420
- collect: {
421
- expectedInputs: expected,
422
- received: {}
423
- }
424
- };
425
- queue.push(collect);
426
- }
427
- const received = collect.collect.received;
428
- received[args.to.input] = args.items;
429
- }
430
- shouldContinueAfterEmptyOutputFromSource(fromNodeId) {
431
- const def = this.topology.defsById.get(fromNodeId);
432
- if (!def) return false;
433
- return def.config.continueWhenEmptyOutput === true;
434
- }
435
- propagateEmptyPath(queue, nodeId, batchId) {
436
- for (const edge of this.topology.outgoingByNode.get(nodeId) ?? []) this.enqueueEdge(queue, {
437
- batchId,
438
- to: edge.to,
439
- from: {
440
- nodeId,
441
- output: edge.output
442
- },
443
- items: []
444
- });
445
- }
446
- isMultiInputNode(n) {
447
- return typeof n?.executeMulti === "function";
448
- }
449
- describeUnsatisfiedCollect(queueEntry) {
450
- const batchId = queueEntry.batchId ?? "batch_1";
451
- const expectedInputs = queueEntry.collect?.expectedInputs ?? [];
452
- const receivedInputs = Object.keys(queueEntry.collect?.received ?? {});
453
- const missingInputs = expectedInputs.filter((input) => !receivedInputs.includes(input));
454
- const mergeNodeLabel = this.formatNodeLabel(queueEntry.nodeId);
455
- const receivedSummary = this.describeReceivedInputs(queueEntry);
456
- const missingSummary = this.describeMissingInputs(queueEntry.nodeId, missingInputs);
457
- return [
458
- `Multi-input collect is stuck at ${mergeNodeLabel} (batchId=${batchId}).`,
459
- `Expected inputs: ${this.formatInputList(expectedInputs)}.`,
460
- `Received inputs: ${receivedSummary}.`,
461
- `Missing inputs: ${missingSummary}.`
462
- ].join(" ");
463
- }
464
- describeReceivedInputs(queueEntry) {
465
- const received = queueEntry.collect?.received ?? {};
466
- const receivedEntries = Object.entries(received);
467
- if (receivedEntries.length === 0) return "none";
468
- return receivedEntries.map(([input, items]) => `${input} (${items.length} item${items.length === 1 ? "" : "s"})`).join(", ");
469
- }
470
- describeMissingInputs(nodeId, missingInputs) {
471
- if (missingInputs.length === 0) return "none";
472
- return missingInputs.map((input) => {
473
- const sources = this.findSources(nodeId, input);
474
- if (sources.length === 0) return input;
475
- return `${input} from ${sources.join(" or ")}`;
476
- }).join(", ");
477
- }
478
- findSources(nodeId, input) {
479
- const matches = [];
480
- for (const [sourceNodeId, edges] of this.topology.outgoingByNode.entries()) for (const edge of edges) if (edge.to.nodeId === nodeId && edge.to.input === input) matches.push(this.formatNodeLabel(sourceNodeId));
481
- return matches;
482
- }
483
- formatInputList(inputs) {
484
- return inputs.length > 0 ? `[${inputs.join(", ")}]` : "[]";
485
- }
486
- formatNodeLabel(nodeId) {
487
- const definition = this.topology.defsById.get(nodeId);
488
- const instance = this.nodeInstances.get(nodeId);
489
- const typeName = definition?.type && typeof definition.type === "function" ? definition.type.name : instance && typeof instance === "object" && "constructor" in instance ? instance.constructor.name ?? "Node" : "Node";
490
- return definition?.name ? `"${definition.name}" (${typeName}:${nodeId})` : `${typeName}:${nodeId}`;
491
- }
492
- };
493
-
494
- //#endregion
495
- //#region src/planning/EngineWorkflowPlanningFactory.ts
496
- var EngineWorkflowPlanningFactory = class {
497
- constructor(workflowNodeInstanceFactory) {
498
- this.workflowNodeInstanceFactory = workflowNodeInstanceFactory;
499
- }
500
- create(workflow) {
501
- this.validateAcyclic(workflow);
502
- const topology = require_RunIntentService.WorkflowTopology.fromWorkflow(workflow);
503
- const planner = new RunQueuePlanner(topology, this.workflowNodeInstanceFactory.createNodes(workflow));
504
- planner.validateNodeKinds();
505
- return {
506
- topology,
507
- planner
508
- };
509
- }
510
- validateAcyclic(workflow) {
511
- const classifier = require_RunIntentService.WorkflowExecutableNodeClassifierFactory.create(workflow);
512
- const outgoing = /* @__PURE__ */ new Map();
513
- const visitState = /* @__PURE__ */ new Map();
514
- for (const node of workflow.nodes) if (classifier.isExecutableNodeId(node.id)) visitState.set(node.id, "unvisited");
515
- for (const edge of workflow.edges) {
516
- if (!classifier.isExecutableNodeId(edge.from.nodeId) || !classifier.isExecutableNodeId(edge.to.nodeId)) continue;
517
- const destinations = outgoing.get(edge.from.nodeId) ?? [];
518
- destinations.push(edge.to.nodeId);
519
- outgoing.set(edge.from.nodeId, destinations);
520
- }
521
- for (const node of workflow.nodes) if (classifier.isExecutableNodeId(node.id) && visitState.get(node.id) === "unvisited") this.depthFirstSearch(node.id, outgoing, visitState);
522
- }
523
- depthFirstSearch(nodeId, outgoing, visitState) {
524
- visitState.set(nodeId, "visiting");
525
- for (const toNodeId of outgoing.get(nodeId) ?? []) {
526
- const state = visitState.get(toNodeId);
527
- if (state === "visiting") throw new Error(`Workflow graph contains a directed cycle (edge ${nodeId} -> ${toNodeId}).`);
528
- if (state === "unvisited") this.depthFirstSearch(toNodeId, outgoing, visitState);
529
- }
530
- visitState.set(nodeId, "done");
531
- }
532
- };
533
-
534
- //#endregion
535
- //#region src/orchestration/TriggerRuntimeService.ts
536
- var TriggerRuntimeService = class {
537
- credentialResolverFactory;
538
- triggerCleanupHandlesByKey = /* @__PURE__ */ new Map();
539
- constructor(workflowRepository, workflowActivationPolicy, runIdFactory, runDataFactory, executionContextFactory, credentialResolverFactory, nodeExecutionStatePublisherFactory, nodeResolver, triggerSetupStateRepository, emitHandler, executionLimitsPolicy, diagnostics) {
540
- this.workflowRepository = workflowRepository;
541
- this.workflowActivationPolicy = workflowActivationPolicy;
542
- this.runIdFactory = runIdFactory;
543
- this.runDataFactory = runDataFactory;
544
- this.executionContextFactory = executionContextFactory;
545
- this.nodeExecutionStatePublisherFactory = nodeExecutionStatePublisherFactory;
546
- this.nodeResolver = nodeResolver;
547
- this.triggerSetupStateRepository = triggerSetupStateRepository;
548
- this.emitHandler = emitHandler;
549
- this.executionLimitsPolicy = executionLimitsPolicy;
550
- this.diagnostics = diagnostics;
551
- this.credentialResolverFactory = credentialResolverFactory;
552
- }
553
- async startTriggers() {
554
- for (const wf of this.workflowRepository.list()) {
555
- if (!this.workflowActivationPolicy.isActive(wf.id)) {
556
- const summaries = this.formatTriggerSummaries(wf);
557
- if (summaries.length > 0) this.logInfo(`Workflow "${wf.name}" (${wf.id}) is inactive; skipping trigger setup — ${summaries.join("; ")}.`);
558
- continue;
559
- }
560
- await this.startTriggersForWorkflow(wf);
561
- }
562
- }
563
- async syncWorkflowTriggersForActivation(workflowId) {
564
- const wf = this.workflowRepository.get(workflowId);
565
- if (!wf) return;
566
- const summaries = this.formatTriggerSummaries(wf);
567
- if (summaries.length > 0) this.logInfo(`Workflow "${wf.name}" (${wf.id}): stopping triggers — ${summaries.join("; ")}.`);
568
- await this.stopTriggersForWorkflow(wf);
569
- if (this.workflowActivationPolicy.isActive(workflowId)) {
570
- if (summaries.length > 0) this.logInfo(`Workflow "${wf.name}" (${wf.id}): activation on; starting triggers — ${summaries.join("; ")}.`);
571
- await this.startTriggersForWorkflow(wf);
572
- } else this.logInfo(`Workflow "${wf.name}" (${wf.id}): activation off; triggers not started.`);
573
- }
574
- async stop() {
575
- for (const workflow of this.workflowRepository.list()) await this.stopTriggersForWorkflow(workflow);
576
- }
577
- async createTriggerTestItems(args) {
578
- const definition = args.workflow.nodes.find((node$1) => node$1.id === args.nodeId);
579
- if (!definition) throw new Error(`Unknown trigger nodeId: ${args.nodeId}`);
580
- if (definition.kind !== "trigger") throw new Error(`Node ${args.nodeId} is not a trigger`);
581
- const node = this.nodeResolver.resolve(definition.type);
582
- if (!this.isTestableTriggerNode(node)) return;
583
- const data = this.runDataFactory.create();
584
- const runId = this.runIdFactory.makeRunId();
585
- const trigger = {
586
- workflowId: args.workflow.id,
587
- nodeId: definition.id
588
- };
589
- const previousState = await this.triggerSetupStateRepository.load(trigger);
590
- return await node.getTestItems({
591
- ...this.createExecutionContext({
592
- runId,
593
- workflowId: args.workflow.id,
594
- nodeId: definition.id,
595
- data
596
- }),
597
- trigger,
598
- nodeId: definition.id,
599
- config: definition.config,
600
- previousState: previousState?.state
601
- });
602
- }
603
- async startTriggersForWorkflow(wf) {
604
- for (const def of wf.nodes) {
605
- if (def.kind !== "trigger") continue;
606
- const node = this.nodeResolver.resolve(def.type);
607
- const data = this.runDataFactory.create();
608
- const triggerRunId = this.runIdFactory.makeRunId();
609
- const trigger = {
610
- workflowId: wf.id,
611
- nodeId: def.id
612
- };
613
- await this.stopTrigger(trigger);
614
- const previousState = await this.triggerSetupStateRepository.load(trigger);
615
- let nextState;
616
- try {
617
- nextState = await node.setup({
618
- ...this.createExecutionContext({
619
- runId: triggerRunId,
620
- workflowId: wf.id,
621
- nodeId: def.id,
622
- data
623
- }),
624
- trigger,
625
- config: def.config,
626
- previousState: previousState?.state,
627
- registerCleanup: (cleanup) => {
628
- this.registerTriggerCleanupHandle(trigger, cleanup);
629
- },
630
- emit: async (items) => {
631
- await this.emitHandler.emit(wf, def.id, items);
632
- }
633
- });
634
- } catch (triggerError) {
635
- await this.stopTrigger(trigger);
636
- const message = triggerError instanceof Error ? triggerError.message : String(triggerError);
637
- this.logWarn(`Skipping trigger setup for workflow ${wf.id} node ${def.id}: ${message}`);
638
- continue;
639
- }
640
- if (nextState === void 0) await this.triggerSetupStateRepository.delete(trigger);
641
- else await this.triggerSetupStateRepository.save({
642
- trigger,
643
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
644
- state: nextState
645
- });
646
- }
647
- }
648
- async stopTriggersForWorkflow(workflow) {
649
- for (const node of workflow.nodes) {
650
- if (node.kind !== "trigger") continue;
651
- await this.stopTrigger({
652
- workflowId: workflow.id,
653
- nodeId: node.id
654
- });
655
- }
656
- }
657
- createExecutionContext(args) {
658
- const nodeState = this.nodeExecutionStatePublisherFactory.create(args.runId, args.workflowId, void 0);
659
- const rootLimits = this.executionLimitsPolicy.createRootExecutionOptions();
660
- return this.executionContextFactory.create({
661
- runId: args.runId,
662
- workflowId: args.workflowId,
663
- parent: void 0,
664
- subworkflowDepth: rootLimits.subworkflowDepth ?? 0,
665
- engineMaxNodeActivations: rootLimits.maxNodeActivations,
666
- engineMaxSubworkflowDepth: rootLimits.maxSubworkflowDepth,
667
- data: args.data,
668
- nodeState,
669
- getCredential: this.credentialResolverFactory.create(args.workflowId, args.nodeId)
670
- });
671
- }
672
- registerTriggerCleanupHandle(trigger, cleanup) {
673
- const key = this.toTriggerKey(trigger);
674
- const cleanups = this.triggerCleanupHandlesByKey.get(key) ?? [];
675
- cleanups.push(cleanup);
676
- this.triggerCleanupHandlesByKey.set(key, cleanups);
677
- }
678
- async stopTrigger(trigger) {
679
- const key = this.toTriggerKey(trigger);
680
- const cleanups = this.triggerCleanupHandlesByKey.get(key) ?? [];
681
- this.triggerCleanupHandlesByKey.delete(key);
682
- for (const cleanup of [...cleanups].reverse()) await cleanup.stop();
683
- }
684
- toTriggerKey(trigger) {
685
- return `${trigger.workflowId}:${trigger.nodeId}`;
686
- }
687
- formatTriggerSummaries(wf) {
688
- const out = [];
689
- for (const def of wf.nodes) {
690
- if (def.kind !== "trigger") continue;
691
- out.push(this.describeTriggerNode(def));
692
- }
693
- return out;
694
- }
695
- describeTriggerNode(def) {
696
- const label = def.name !== void 0 && def.name.trim().length > 0 ? def.name.trim() : String(def.id);
697
- const cfg = def.config;
698
- if (typeof cfg.endpointKey === "string" && cfg.endpointKey.trim().length > 0) return `${label} (webhook "${cfg.endpointKey.trim()}")`;
699
- return label;
700
- }
701
- logInfo(message) {
702
- if (this.diagnostics) this.diagnostics.info(message);
703
- }
704
- logWarn(message) {
705
- if (this.diagnostics) this.diagnostics.warn(message);
706
- else console.warn(`[engine] ${message}`);
707
- }
708
- isTestableTriggerNode(node) {
709
- return typeof node.getTestItems === "function";
710
- }
711
- };
712
-
713
- //#endregion
714
- //#region src/orchestration/EngineWaiters.ts
715
- var EngineWaiters = class {
716
- completionWaiters = /* @__PURE__ */ new Map();
717
- webhookResponseWaiters = /* @__PURE__ */ new Map();
718
- waitForCompletion(runId) {
719
- return new Promise((resolve) => {
720
- const list = this.completionWaiters.get(runId) ?? [];
721
- list.push(resolve);
722
- this.completionWaiters.set(runId, list);
723
- });
724
- }
725
- waitForWebhookResponse(runId) {
726
- return new Promise((resolve) => {
727
- const list = this.webhookResponseWaiters.get(runId) ?? [];
728
- list.push(resolve);
729
- this.webhookResponseWaiters.set(runId, list);
730
- });
731
- }
732
- resolveRunCompletion(result) {
733
- if (result.status !== "completed" && result.status !== "failed") return;
734
- const list = this.completionWaiters.get(result.runId);
735
- if (!list || list.length === 0) return;
736
- this.completionWaiters.delete(result.runId);
737
- for (const r of list) r(result);
738
- }
739
- resolveWebhookResponse(result) {
740
- const list = this.webhookResponseWaiters.get(result.runId);
741
- if (!list || list.length === 0) return;
742
- this.webhookResponseWaiters.delete(result.runId);
743
- for (const resolve of list) resolve(result);
744
- }
745
- };
746
-
747
- //#endregion
748
- //#region src/orchestration/Engine.ts
749
- /**
750
- * Runtime facade for orchestration, continuation, triggers, and webhook routing.
751
- * Prefer {@link import("../intents/RunIntentService").RunIntentService} for host/HTTP invocation boundaries.
752
- * The class token is exported from `@codemation/core/bootstrap` (not the main `@codemation/core` barrel).
753
- */
754
- var Engine = class {
755
- constructor(deps) {
756
- this.deps = deps;
757
- }
758
- loadWorkflows(workflows) {
759
- this.deps.tokenRegistry.registerFromWorkflows?.(workflows);
760
- this.deps.liveWorkflowRepository.setWorkflows(workflows);
761
- this.deps.webhookTriggerMatcher.onEngineWorkflowsLoaded?.();
762
- }
763
- getTokenRegistry() {
764
- return this.deps.tokenRegistry;
765
- }
766
- resolveWorkflowSnapshot(args) {
767
- return this.deps.workflowSnapshotResolver.resolve(args);
768
- }
769
- async startTriggers() {
770
- return await this.deps.triggerRuntime.startTriggers();
771
- }
772
- async syncWorkflowTriggersForActivation(workflowId) {
773
- await this.deps.triggerRuntime.syncWorkflowTriggersForActivation(workflowId);
774
- this.deps.webhookTriggerMatcher.reloadWebhookRoutes?.();
775
- }
776
- async start(workflows) {
777
- await this.stop();
778
- this.loadWorkflows(workflows);
779
- await this.startTriggers();
780
- }
781
- async stop() {
782
- await this.deps.triggerRuntime.stop();
783
- this.deps.webhookTriggerMatcher.onEngineStopped?.();
784
- }
785
- resolveWebhookTrigger(args) {
786
- const entry = this.deps.webhookTriggerMatcher.lookup(args.endpointPath);
787
- if (!entry) return { status: "notFound" };
788
- if (!entry.methods.includes(args.method)) return {
789
- status: "methodNotAllowed",
790
- match: entry
791
- };
792
- return {
793
- status: "ok",
794
- match: entry
795
- };
796
- }
797
- async createTriggerTestItems(args) {
798
- return await this.deps.triggerRuntime.createTriggerTestItems(args);
799
- }
800
- async runWorkflow(wf, startAt, items, parent, executionOptions, persistedStateOverrides) {
801
- return await this.deps.runStartService.runWorkflow(wf, startAt, items, parent, executionOptions, persistedStateOverrides);
802
- }
803
- async runWorkflowFromState(request) {
804
- return await this.deps.runStartService.runWorkflowFromState(request);
805
- }
806
- async markNodeRunning(args) {
807
- return await this.deps.runContinuationService.markNodeRunning(args);
808
- }
809
- async resumeFromNodeResult(args) {
810
- return await this.deps.runContinuationService.resumeFromNodeResult(args);
811
- }
812
- async resumeFromNodeError(args) {
813
- return await this.deps.runContinuationService.resumeFromNodeError(args);
814
- }
815
- async resumeFromStepResult(args) {
816
- return await this.deps.runContinuationService.resumeFromStepResult(args);
817
- }
818
- async resumeFromStepError(args) {
819
- return await this.deps.runContinuationService.resumeFromStepError(args);
820
- }
821
- async waitForCompletion(runId) {
822
- return await this.deps.runContinuationService.waitForCompletion(runId);
823
- }
824
- async waitForWebhookResponse(runId) {
825
- return await this.deps.runContinuationService.waitForWebhookResponse(runId);
826
- }
827
- async handleNodeExecutionRequest(request) {
828
- await this.deps.nodeExecutionRequestHandler.handleNodeExecutionRequest(request);
829
- }
830
- };
831
-
832
- //#endregion
833
- //#region src/runtime/EngineFactory.ts
834
- /**
835
- * Composes the {@link Engine} graph from {@link EngineCompositionDeps}. Production wiring usually goes through
836
- * {@link import("../bootstrap/runtime/EngineRuntimeRegistrar").EngineRuntimeRegistrar}; this factory remains for tests and custom composition.
837
- * Exported from `@codemation/core/bootstrap` (not the main `@codemation/core` barrel).
838
- */
839
- var EngineFactory = class {
840
- create(deps) {
841
- const waiters = new EngineWaiters();
842
- const credentialResolverFactory = new require_RunIntentService.CredentialResolverFactory(deps.credentialSessions);
843
- const nodeEventPublisher = new require_RunIntentService.NodeEventPublisher(deps.eventBus);
844
- const nodeStatePublisherFactory = new require_RunIntentService.NodeRunStateWriterFactory(deps.workflowExecutionRepository, nodeEventPublisher);
845
- const planningFactory = new EngineWorkflowPlanningFactory(deps.workflowNodeInstanceFactory);
846
- const executionLimitsPolicy = deps.executionLimitsPolicy ?? new require_RunIntentService.EngineExecutionLimitsPolicy();
847
- const workflowSnapshotCodec = deps.workflowSnapshotCodec ?? new require_InMemoryLiveWorkflowRepository.WorkflowSnapshotCodec(deps.tokenRegistry);
848
- const missingRuntimeFallbacks = deps.missingRuntimeFallbacks ?? new require_RunIntentService.MissingRuntimeFallbacks();
849
- const workflowSnapshotResolver = new require_RunIntentService.WorkflowSnapshotResolver(deps.workflowRepository, deps.tokenRegistry, workflowSnapshotCodec, missingRuntimeFallbacks);
850
- const semantics = new require_RunIntentService.RunStateSemantics(new require_RunIntentService.MissingRuntimeExecutionMarker());
851
- const activationEnqueueService = new require_RunIntentService.ActivationEnqueueService(deps.activationScheduler, deps.workflowExecutionRepository, nodeEventPublisher);
852
- const runExecutionContextFactory = new require_RunIntentService.WorkflowRunExecutionContextFactory(deps.executionContextFactory, credentialResolverFactory);
853
- const nodeActivationRequestComposer = new require_RunIntentService.NodeActivationRequestComposer(deps.activationIdFactory, credentialResolverFactory);
854
- const persistedRunStateTerminalBuilder = new require_RunIntentService.PersistedRunStateTerminalBuilder();
855
- const storagePolicyEvaluator = new WorkflowStoragePolicyEvaluator(deps.nodeResolver);
856
- const terminalPersistence = new RunTerminalPersistenceCoordinator(deps.workflowExecutionRepository, storagePolicyEvaluator);
857
- const policyErrorServices = new WorkflowPolicyErrorServices(deps.nodeResolver);
858
- const runStartService = new require_RunIntentService.RunStartService(deps.runIdFactory, deps.workflowExecutionRepository, deps.runDataFactory, workflowSnapshotCodec, planningFactory, nodeStatePublisherFactory, runExecutionContextFactory, nodeActivationRequestComposer, activationEnqueueService, semantics, waiters, deps.workflowPolicyRuntimeDefaults, executionLimitsPolicy);
859
- const runContinuationService = new require_RunIntentService.RunContinuationService(deps.activationIdFactory, deps.workflowExecutionRepository, deps.runDataFactory, runExecutionContextFactory, workflowSnapshotResolver, planningFactory, nodeStatePublisherFactory, credentialResolverFactory, nodeActivationRequestComposer, persistedRunStateTerminalBuilder, activationEnqueueService, nodeEventPublisher, semantics, waiters, policyErrorServices, terminalPersistence, executionLimitsPolicy);
860
- const nodeExecutionRequestHandler = new NodeExecutionRequestHandlerService(deps.workflowExecutionRepository, workflowSnapshotResolver, deps.runDataFactory, runExecutionContextFactory, nodeStatePublisherFactory, nodeActivationRequestComposer, deps.nodeExecutor, runContinuationService, executionLimitsPolicy);
861
- const triggerRuntime = new TriggerRuntimeService(deps.workflowRepository, deps.workflowActivationPolicy, deps.runIdFactory, deps.runDataFactory, deps.executionContextFactory, credentialResolverFactory, nodeStatePublisherFactory, deps.nodeResolver, deps.triggerSetupStateRepository, { emit: async (workflow, triggerNodeId, items) => {
862
- await runStartService.runWorkflow(workflow, triggerNodeId, items, void 0);
863
- } }, executionLimitsPolicy, deps.triggerRuntimeDiagnostics);
864
- const engine = new Engine({
865
- liveWorkflowRepository: deps.liveWorkflowRepository,
866
- tokenRegistry: deps.tokenRegistry,
867
- webhookTriggerMatcher: deps.webhookTriggerMatcher,
868
- workflowSnapshotResolver,
869
- triggerRuntime,
870
- runStartService,
871
- runContinuationService,
872
- nodeExecutionRequestHandler
873
- });
874
- deps.activationScheduler.setContinuation?.(engine);
875
- return engine;
876
- }
877
- };
878
-
879
- //#endregion
880
- //#region src/runtime/EngineWorkflowRunnerService.ts
881
- var EngineWorkflowRunnerService = class {
882
- constructor(engine, workflowRepository) {
883
- this.engine = engine;
884
- this.workflowRepository = workflowRepository;
885
- }
886
- async runById(args) {
887
- const { workflowId, startAt, items, parent } = args;
888
- const wf = this.workflowRepository.get(workflowId);
889
- if (!wf) throw new Error(`Unknown workflowId: ${workflowId}`);
890
- const startNodeId = startAt ?? this.findDefaultStartNodeId(wf);
891
- const scheduled = await this.engine.runWorkflow(wf, startNodeId, items, parent);
892
- if (scheduled.status !== "pending") return scheduled;
893
- return await this.engine.waitForCompletion(scheduled.runId);
894
- }
895
- findDefaultStartNodeId(wf) {
896
- return require_RunIntentService.WorkflowExecutableNodeClassifierFactory.create(wf).findDefaultExecutableStartNodeId(wf);
897
- }
898
- };
899
-
900
- //#endregion
901
- //#region src/runtime/EngineWorkflowRunnerServiceFactory.ts
902
- var EngineWorkflowRunnerServiceFactory = class {
903
- create(engine, workflowRepository) {
904
- return new EngineWorkflowRunnerService(engine, workflowRepository);
905
- }
906
- };
907
-
908
- //#endregion
909
- //#region src/runtime/RunIntentServiceFactory.ts
910
- var RunIntentServiceFactory = class {
911
- create(engine, workflowRepository) {
912
- return new require_RunIntentService.RunIntentService(engine, workflowRepository);
913
- }
914
- };
915
-
916
- //#endregion
917
- //#region src/runtime/WorkflowRepositoryWebhookTriggerMatcher.ts
918
- /**
919
- * Resolves webhook HTTP routes from the live workflow repository (no trigger setup / registration).
920
- * Maintains an in-memory index keyed by user-defined endpoint path for O(1) lookups after reload.
921
- */
922
- var WorkflowRepositoryWebhookTriggerMatcher = class {
923
- routeByPath = /* @__PURE__ */ new Map();
924
- engineRoutesActive = false;
925
- constructor(workflowRepository, workflowActivationPolicy, diagnostics) {
926
- this.workflowRepository = workflowRepository;
927
- this.workflowActivationPolicy = workflowActivationPolicy;
928
- this.diagnostics = diagnostics;
929
- }
930
- onEngineWorkflowsLoaded() {
931
- this.engineRoutesActive = true;
932
- this.rebuildRouteIndex();
933
- }
934
- onEngineStopped() {
935
- this.engineRoutesActive = false;
936
- this.routeByPath.clear();
937
- }
938
- reloadWebhookRoutes() {
939
- if (!this.engineRoutesActive) return;
940
- this.rebuildRouteIndex();
941
- }
942
- lookup(endpointPath) {
943
- if (!this.engineRoutesActive) return;
944
- const normalized = this.normalizeEndpointPath(endpointPath);
945
- return this.routeByPath.get(normalized);
946
- }
947
- match(args) {
948
- const entry = this.lookup(args.endpointPath);
949
- if (!entry) return;
950
- return entry.methods.includes(args.method) ? entry : void 0;
951
- }
952
- rebuildRouteIndex() {
953
- this.routeByPath.clear();
954
- for (const workflow of this.workflowRepository.list()) {
955
- if (!this.workflowActivationPolicy.isActive(workflow.id)) {
956
- if (workflow.nodes.filter((n) => n.kind === "trigger").length > 0) {
957
- const paths = this.collectWebhookEndpointPaths(workflow);
958
- if (paths.length > 0) this.diagnostics?.info?.(`Workflow "${workflow.name}" (${workflow.id}) is inactive; webhook routes not registered: ${paths.map((p) => `"${p}"`).join(", ")}`);
959
- else this.diagnostics?.info?.(`Workflow "${workflow.name}" (${workflow.id}) is inactive; no repository webhook routes for its triggers (other trigger kinds are unchanged).`);
960
- }
961
- continue;
962
- }
963
- for (const def of workflow.nodes) {
964
- const match = this.tryMatchFromTriggerNode(workflow, def);
965
- if (!match) continue;
966
- const key = this.normalizeEndpointPath(match.endpointPath);
967
- const existing = this.routeByPath.get(key);
968
- if (existing) this.diagnostics?.warn(`Duplicate webhook endpoint path "${key}" (workflows "${existing.workflowId}" and "${match.workflowId}"); using "${match.workflowId}".`);
969
- this.routeByPath.set(key, match);
970
- }
971
- }
972
- }
973
- collectWebhookEndpointPaths(workflow) {
974
- const paths = [];
975
- for (const def of workflow.nodes) {
976
- if (def.kind !== "trigger") continue;
977
- const match = this.tryMatchFromTriggerNode(workflow, def);
978
- if (match) paths.push(match.endpointPath);
979
- }
980
- return paths;
981
- }
982
- tryMatchFromTriggerNode(workflow, def) {
983
- if (def.kind !== "trigger") return;
984
- const config = def.config;
985
- if (typeof config.endpointKey !== "string" || config.endpointKey.length === 0) return;
986
- if (!Array.isArray(config.methods) || config.methods.length === 0) return;
987
- const methods = config.methods;
988
- const parseJsonBody = typeof config.parseJsonBody === "function" ? config.parseJsonBody.bind(config) : void 0;
989
- return {
990
- endpointPath: config.endpointKey,
991
- workflowId: workflow.id,
992
- nodeId: def.id,
993
- methods: [...methods],
994
- parseJsonBody
995
- };
996
- }
997
- normalizeEndpointPath(endpointPath) {
998
- return endpointPath.trim();
999
- }
1000
- };
1001
-
1002
- //#endregion
1003
- //#region src/runtime/WorkflowRepositoryWebhookTriggerMatcherFactory.ts
1004
- var WorkflowRepositoryWebhookTriggerMatcherFactory = class {
1005
- create(workflowRepository, workflowActivationPolicy, diagnostics) {
1006
- return new WorkflowRepositoryWebhookTriggerMatcher(workflowRepository, workflowActivationPolicy, diagnostics);
1007
- }
1008
- };
1009
-
1010
- //#endregion
1011
- //#region src/scheduler/InlineDrivingSchedulerFactory.ts
1012
- var InlineDrivingSchedulerFactory = class {
1013
- create(nodeExecutor) {
1014
- return new require_RunIntentService.InlineDrivingScheduler(nodeExecutor);
1015
- }
1016
- };
1017
-
1018
- //#endregion
1019
- //#region src/bootstrap/runtime/EngineRuntimeRegistrar.ts
1020
- /**
1021
- * Container-first entry: call on a host/test container **after** workflow, run, node, and credential
1022
- * ports are registered. The registrar owns the default inline scheduler, engine binding,
1023
- * and intent-surface wiring so hosts only override the seams they actually replace.
1024
- */
1025
- var EngineRuntimeRegistrar = class {
1026
- register(container, options) {
1027
- this.registerSupportFactories(container);
1028
- this.registerExecutionLimitsPolicy(container, options);
1029
- this.ensureWorkflowNodeInstanceFactory(container);
1030
- this.ensureNodeExecutor(container);
1031
- this.registerDefaultActivationScheduler(container);
1032
- this.registerEngine(container, options);
1033
- this.registerIntentServices(container);
1034
- }
1035
- registerSupportFactories(container) {
1036
- container.register(EngineExecutionLimitsPolicyFactory, { useClass: EngineExecutionLimitsPolicyFactory });
1037
- container.register(require_RunIntentService.NodeInstanceFactoryFactory, { useClass: require_RunIntentService.NodeInstanceFactoryFactory });
1038
- container.register(require_RunIntentService.DefaultAsyncSleeper, { useClass: require_RunIntentService.DefaultAsyncSleeper });
1039
- container.register(require_RunIntentService.InProcessRetryRunnerFactory, { useClass: require_RunIntentService.InProcessRetryRunnerFactory });
1040
- container.register(require_RunIntentService.NodeExecutorFactory, { useClass: require_RunIntentService.NodeExecutorFactory });
1041
- container.register(InlineDrivingSchedulerFactory, { useClass: InlineDrivingSchedulerFactory });
1042
- container.register(RunIntentServiceFactory, { useClass: RunIntentServiceFactory });
1043
- container.register(EngineWorkflowRunnerServiceFactory, { useClass: EngineWorkflowRunnerServiceFactory });
1044
- container.register(WorkflowRepositoryWebhookTriggerMatcherFactory, { useClass: WorkflowRepositoryWebhookTriggerMatcherFactory });
1045
- }
1046
- registerExecutionLimitsPolicy(container, options) {
1047
- if (container.isRegistered(require_RunIntentService.CoreTokens.EngineExecutionLimitsPolicy, true)) return;
1048
- container.register(require_RunIntentService.CoreTokens.EngineExecutionLimitsPolicy, { useFactory: (0, tsyringe.instanceCachingFactory)((dependencyContainer) => {
1049
- const merged = options?.resolveEngineExecutionLimits?.() ?? options?.engineExecutionLimits;
1050
- return dependencyContainer.resolve(EngineExecutionLimitsPolicyFactory).create(merged);
1051
- }) });
1052
- }
1053
- ensureWorkflowNodeInstanceFactory(container) {
1054
- if (container.isRegistered(require_RunIntentService.CoreTokens.WorkflowNodeInstanceFactory, true)) return;
1055
- container.register(require_RunIntentService.CoreTokens.WorkflowNodeInstanceFactory, { useFactory: (0, tsyringe.instanceCachingFactory)((dependencyContainer) => {
1056
- return dependencyContainer.resolve(require_RunIntentService.NodeInstanceFactoryFactory).create(dependencyContainer.resolve(require_RunIntentService.CoreTokens.NodeResolver));
1057
- }) });
1058
- }
1059
- ensureNodeExecutor(container) {
1060
- if (container.isRegistered(require_RunIntentService.NodeExecutor, true)) return;
1061
- container.register(require_RunIntentService.NodeExecutor, { useFactory: (0, tsyringe.instanceCachingFactory)((dependencyContainer) => {
1062
- const retryRunner = dependencyContainer.resolve(require_RunIntentService.InProcessRetryRunnerFactory).create(dependencyContainer.resolve(require_RunIntentService.DefaultAsyncSleeper));
1063
- return dependencyContainer.resolve(require_RunIntentService.NodeExecutorFactory).create(dependencyContainer.resolve(require_RunIntentService.CoreTokens.WorkflowNodeInstanceFactory), retryRunner);
1064
- }) });
1065
- }
1066
- registerDefaultActivationScheduler(container) {
1067
- if (container.isRegistered(require_RunIntentService.CoreTokens.NodeActivationScheduler, true)) return;
1068
- container.register(require_RunIntentService.InlineDrivingScheduler, { useFactory: (0, tsyringe.instanceCachingFactory)((dependencyContainer) => {
1069
- return dependencyContainer.resolve(InlineDrivingSchedulerFactory).create(dependencyContainer.resolve(require_RunIntentService.NodeExecutor));
1070
- }) });
1071
- container.register(require_RunIntentService.CoreTokens.NodeActivationScheduler, { useFactory: (0, tsyringe.instanceCachingFactory)((dependencyContainer) => {
1072
- return dependencyContainer.resolve(require_RunIntentService.InlineDrivingScheduler);
1073
- }) });
1074
- }
1075
- registerEngine(container, options) {
1076
- container.register(EngineFactory, { useClass: EngineFactory });
1077
- const matcherProvider = this.resolveMatcherProvider(options);
1078
- container.register(Engine, { useFactory: (0, tsyringe.instanceCachingFactory)((dependencyContainer) => {
1079
- const liveWorkflowRepository = dependencyContainer.resolve(require_RunIntentService.CoreTokens.LiveWorkflowRepository);
1080
- const nodeResolver = dependencyContainer.resolve(require_RunIntentService.CoreTokens.NodeResolver);
1081
- const tokenRegistryLike = dependencyContainer.resolve(require_RunIntentService.CoreTokens.PersistedWorkflowTokenRegistry);
1082
- const workflowActivationPolicy = dependencyContainer.resolve(require_RunIntentService.CoreTokens.WorkflowActivationPolicy);
1083
- const webhookTriggerMatcher = matcherProvider.createMatcher(dependencyContainer);
1084
- const workflowNodeInstanceFactory = dependencyContainer.resolve(require_RunIntentService.CoreTokens.WorkflowNodeInstanceFactory);
1085
- const triggerRuntimeDiagnostics = options?.triggerRuntimeDiagnosticsProvider?.create(dependencyContainer);
1086
- return dependencyContainer.resolve(EngineFactory).create({
1087
- credentialSessions: dependencyContainer.resolve(require_RunIntentService.CoreTokens.CredentialSessionService),
1088
- liveWorkflowRepository,
1089
- workflowRepository: dependencyContainer.resolve(require_RunIntentService.CoreTokens.WorkflowRepository),
1090
- workflowActivationPolicy,
1091
- nodeResolver,
1092
- triggerSetupStateRepository: dependencyContainer.resolve(require_RunIntentService.CoreTokens.TriggerSetupStateRepository),
1093
- webhookTriggerMatcher,
1094
- runIdFactory: dependencyContainer.resolve(require_RunIntentService.CoreTokens.RunIdFactory),
1095
- activationIdFactory: dependencyContainer.resolve(require_RunIntentService.CoreTokens.ActivationIdFactory),
1096
- workflowExecutionRepository: dependencyContainer.resolve(require_RunIntentService.CoreTokens.WorkflowExecutionRepository),
1097
- activationScheduler: dependencyContainer.resolve(require_RunIntentService.CoreTokens.NodeActivationScheduler),
1098
- runDataFactory: dependencyContainer.resolve(require_RunIntentService.CoreTokens.RunDataFactory),
1099
- executionContextFactory: dependencyContainer.resolve(require_RunIntentService.CoreTokens.ExecutionContextFactory),
1100
- nodeExecutor: dependencyContainer.resolve(require_RunIntentService.NodeExecutor),
1101
- eventBus: dependencyContainer.resolve(require_RunIntentService.CoreTokens.RunEventBus),
1102
- tokenRegistry: tokenRegistryLike,
1103
- workflowNodeInstanceFactory,
1104
- executionLimitsPolicy: dependencyContainer.resolve(require_RunIntentService.CoreTokens.EngineExecutionLimitsPolicy),
1105
- triggerRuntimeDiagnostics
1106
- });
1107
- }) });
1108
- }
1109
- registerIntentServices(container) {
1110
- container.register(require_RunIntentService.RunIntentService, { useFactory: (0, tsyringe.instanceCachingFactory)((dependencyContainer) => {
1111
- return dependencyContainer.resolve(RunIntentServiceFactory).create(dependencyContainer.resolve(Engine), dependencyContainer.resolve(require_RunIntentService.CoreTokens.WorkflowRepository));
1112
- }) });
1113
- container.register(require_RunIntentService.CoreTokens.WorkflowRunnerService, { useFactory: (0, tsyringe.instanceCachingFactory)((dependencyContainer) => {
1114
- return dependencyContainer.resolve(EngineWorkflowRunnerServiceFactory).create(dependencyContainer.resolve(Engine), dependencyContainer.resolve(require_RunIntentService.CoreTokens.WorkflowRepository));
1115
- }) });
1116
- }
1117
- resolveMatcherProvider(options) {
1118
- if (options?.webhookTriggerMatcherProvider) return options.webhookTriggerMatcherProvider;
1119
- return { createMatcher: (container) => container.resolve(WorkflowRepositoryWebhookTriggerMatcherFactory).create(container.resolve(require_RunIntentService.CoreTokens.WorkflowRepository), container.resolve(require_RunIntentService.CoreTokens.WorkflowActivationPolicy), options?.webhookTriggerRoutingDiagnostics) };
1120
- }
1121
- };
1122
-
1123
- //#endregion
1124
4
  exports.ConfigDrivenOffloadPolicy = require_RunIntentService.ConfigDrivenOffloadPolicy;
1125
5
  exports.CredentialResolverFactory = require_RunIntentService.CredentialResolverFactory;
1126
6
  exports.DefaultAsyncSleeper = require_RunIntentService.DefaultAsyncSleeper;
@@ -1128,17 +8,17 @@ exports.DefaultDrivingScheduler = require_RunIntentService.DefaultDrivingSchedul
1128
8
  exports.DefaultExecutionBinaryService = require_RunIntentService.DefaultExecutionBinaryService;
1129
9
  exports.DefaultExecutionContextFactory = require_RunIntentService.DefaultExecutionContextFactory;
1130
10
  exports.ENGINE_EXECUTION_LIMITS_DEFAULTS = require_RunIntentService.ENGINE_EXECUTION_LIMITS_DEFAULTS;
1131
- exports.Engine = Engine;
11
+ exports.Engine = require_bootstrap.Engine;
1132
12
  exports.EngineExecutionLimitsPolicy = require_RunIntentService.EngineExecutionLimitsPolicy;
1133
- exports.EngineExecutionLimitsPolicyFactory = EngineExecutionLimitsPolicyFactory;
1134
- exports.EngineFactory = EngineFactory;
1135
- exports.EngineRuntimeRegistrar = EngineRuntimeRegistrar;
1136
- exports.EngineWorkflowRunnerService = EngineWorkflowRunnerService;
13
+ exports.EngineExecutionLimitsPolicyFactory = require_bootstrap.EngineExecutionLimitsPolicyFactory;
14
+ exports.EngineFactory = require_bootstrap.EngineFactory;
15
+ exports.EngineRuntimeRegistrar = require_bootstrap.EngineRuntimeRegistrar;
16
+ exports.EngineWorkflowRunnerService = require_bootstrap.EngineWorkflowRunnerService;
1137
17
  exports.HintOnlyOffloadPolicy = require_RunIntentService.HintOnlyOffloadPolicy;
1138
18
  exports.InMemoryBinaryStorage = require_RunIntentService.InMemoryBinaryStorage;
1139
- exports.InMemoryLiveWorkflowRepository = require_InMemoryLiveWorkflowRepository.InMemoryLiveWorkflowRepository;
19
+ exports.InMemoryLiveWorkflowRepository = require_RunIntentService.InMemoryLiveWorkflowRepository;
1140
20
  exports.InMemoryRunDataFactory = require_RunIntentService.InMemoryRunDataFactory;
1141
- exports.InMemoryWorkflowExecutionRepository = InMemoryWorkflowExecutionRepository;
21
+ exports.InMemoryWorkflowExecutionRepository = require_bootstrap.InMemoryWorkflowExecutionRepository;
1142
22
  exports.InProcessRetryRunner = require_RunIntentService.InProcessRetryRunner;
1143
23
  exports.InlineDrivingScheduler = require_RunIntentService.InlineDrivingScheduler;
1144
24
  exports.LocalOnlyScheduler = require_RunIntentService.LocalOnlyScheduler;
@@ -1148,10 +28,9 @@ exports.NodeInstanceFactory = require_RunIntentService.NodeInstanceFactory;
1148
28
  exports.PersistedWorkflowTokenRegistry = require_RunIntentService.PersistedWorkflowTokenRegistry;
1149
29
  exports.RunIntentService = require_RunIntentService.RunIntentService;
1150
30
  exports.RunPolicySnapshotFactory = require_RunIntentService.RunPolicySnapshotFactory;
1151
- exports.RunSummaryMapper = RunSummaryMapper;
1152
- exports.RunTerminalPersistenceCoordinator = RunTerminalPersistenceCoordinator;
31
+ exports.RunSummaryMapper = require_bootstrap.RunSummaryMapper;
32
+ exports.RunTerminalPersistenceCoordinator = require_bootstrap.RunTerminalPersistenceCoordinator;
1153
33
  exports.UnavailableBinaryStorage = require_RunIntentService.UnavailableBinaryStorage;
1154
- exports.WorkflowPolicyErrorServices = WorkflowPolicyErrorServices;
1155
- exports.WorkflowRepositoryWebhookTriggerMatcher = WorkflowRepositoryWebhookTriggerMatcher;
1156
- exports.WorkflowStoragePolicyEvaluator = WorkflowStoragePolicyEvaluator;
1157
- //# sourceMappingURL=index.cjs.map
34
+ exports.WorkflowPolicyErrorServices = require_bootstrap.WorkflowPolicyErrorServices;
35
+ exports.WorkflowRepositoryWebhookTriggerMatcher = require_bootstrap.WorkflowRepositoryWebhookTriggerMatcher;
36
+ exports.WorkflowStoragePolicyEvaluator = require_bootstrap.WorkflowStoragePolicyEvaluator;