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