@codemation/core 0.11.1 → 0.12.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 +6 -0
- package/dist/{CostCatalogContract-DZgcUBE4.d.cts → CostCatalogContract-DD7fQ4FF.d.cts} +2 -2
- package/dist/{EngineRuntimeRegistration.types-Cggm5GVY.d.cts → EngineRuntimeRegistration.types-DTV5_7Jw.d.cts} +3 -3
- package/dist/{EngineRuntimeRegistration.types-BQbS9_gs.d.ts → EngineRuntimeRegistration.types-Dl92Hdoi.d.ts} +2 -2
- package/dist/InMemoryRunDataFactory-qMiYjhCK.d.cts +202 -0
- package/dist/{ItemsInputNormalizer-D-MH8MBs.js → ItemsInputNormalizer-BhuxvZh5.js} +2 -2
- package/dist/{ItemsInputNormalizer-D-MH8MBs.js.map → ItemsInputNormalizer-BhuxvZh5.js.map} +1 -1
- package/dist/{ItemsInputNormalizer-_Mfcd3YU.d.ts → ItemsInputNormalizer-C09a7iFP.d.ts} +2 -2
- package/dist/{ItemsInputNormalizer-C_dpn76M.d.cts → ItemsInputNormalizer-DLaD6rTl.d.cts} +3 -3
- package/dist/{ItemsInputNormalizer-CwdOhSAK.cjs → ItemsInputNormalizer-Div-fb6a.cjs} +2 -2
- package/dist/{ItemsInputNormalizer-CwdOhSAK.cjs.map → ItemsInputNormalizer-Div-fb6a.cjs.map} +1 -1
- package/dist/{RunIntentService-BVur7x9n.d.ts → RunIntentService-BOSGwmqn.d.ts} +18 -4
- package/dist/{RunIntentService-CEF-sFfI.d.cts → RunIntentService-CWMMrAP4.d.cts} +18 -4
- package/dist/{agentMcpTypes-ZiNbNsEi.d.cts → agentMcpTypes-DUmniLOY.d.cts} +183 -4
- package/dist/bootstrap/index.cjs +3 -3
- package/dist/bootstrap/index.d.cts +63 -7
- package/dist/bootstrap/index.d.ts +5 -5
- package/dist/bootstrap/index.js +3 -3
- package/dist/{bootstrap-D_Yyi0wL.js → bootstrap-CKTMMNmL.js} +173 -4
- package/dist/bootstrap-CKTMMNmL.js.map +1 -0
- package/dist/{bootstrap-BxuTFTLB.cjs → bootstrap-D460dCgS.cjs} +175 -4
- package/dist/bootstrap-D460dCgS.cjs.map +1 -0
- package/dist/browser.cjs +3 -2
- package/dist/browser.d.cts +4 -4
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +3 -3
- package/dist/contracts.d.cts +5 -5
- package/dist/contracts.d.ts +2 -2
- package/dist/{di-0Wop7z1y.js → di-DdsgWfVy.js} +31 -2
- package/dist/di-DdsgWfVy.js.map +1 -0
- package/dist/{di-BlEKdoZS.cjs → di-tO6R7VJV.cjs} +36 -1
- package/dist/di-tO6R7VJV.cjs.map +1 -0
- package/dist/{executionPersistenceContracts-BgZMRsTa.d.cts → executionPersistenceContracts-DenJJK2T.d.cts} +2 -2
- package/dist/{index-62Ba9f7D.d.ts → index-BZDhEQ6W.d.ts} +277 -101
- package/dist/{index-zWGtEhrf.d.ts → index-CSKKuK60.d.ts} +441 -5
- package/dist/index.cjs +71 -161
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +395 -97
- package/dist/index.d.ts +5 -5
- package/dist/index.js +56 -159
- package/dist/index.js.map +1 -1
- package/dist/{params-B5SENSzZ.d.cts → params-DqRvku2h.d.cts} +2 -2
- package/dist/{runtime-cxmUkk0l.js → runtime-BPZgnZ9G.js} +611 -16
- package/dist/runtime-BPZgnZ9G.js.map +1 -0
- package/dist/{runtime-DBzq5YBi.cjs → runtime-CyW9c9XM.cjs} +670 -15
- package/dist/runtime-CyW9c9XM.cjs.map +1 -0
- package/dist/testing.cjs +3 -3
- package/dist/testing.d.cts +3 -3
- package/dist/testing.d.ts +3 -3
- package/dist/testing.js +3 -3
- package/package.json +1 -1
- package/src/authoring/defineHumanApprovalNode.types.ts +379 -0
- package/src/authoring/index.ts +6 -0
- package/src/bootstrap/runtime/EngineRuntimeRegistrar.ts +29 -0
- package/src/contracts/CodemationTelemetryAttributeNames.ts +10 -0
- package/src/contracts/credentialTypes.ts +10 -0
- package/src/contracts/hitlSeamTypes.ts +34 -0
- package/src/contracts/humanTaskStoreTypes.ts +48 -0
- package/src/contracts/inboxChannelTypes.ts +58 -0
- package/src/contracts/index.ts +3 -0
- package/src/contracts/runTypes.ts +61 -3
- package/src/contracts/runtimeTypes.ts +112 -0
- package/src/credentials/CredentialMaterialProvider.types.ts +61 -0
- package/src/credentials/ManagedCredentialMaterialWriteError.ts +14 -0
- package/src/credentials/ManagedMaterialFetchError.ts +16 -0
- package/src/execution/ActivationEnqueueService.ts +16 -0
- package/src/execution/DefaultExecutionContextFactory.ts +11 -0
- package/src/execution/NodeExecutionSnapshotFactory.ts +7 -1
- package/src/execution/NodeExecutor.ts +60 -1
- package/src/execution/NodeExecutorFactory.ts +12 -2
- package/src/execution/NodeSuspensionHandler.ts +220 -0
- package/src/execution/PersistedRunStateTerminalBuilder.ts +5 -2
- package/src/execution/RunStateSemantics.ts +5 -0
- package/src/execution/RunSuspendedError.ts +21 -0
- package/src/index.ts +40 -0
- package/src/orchestration/Engine.ts +12 -2
- package/src/orchestration/EngineWaiters.ts +1 -1
- package/src/orchestration/NodeExecutionRequestHandlerService.ts +25 -2
- package/src/orchestration/RunContinuationService.ts +226 -2
- package/src/orchestration/TestSuiteOrchestrator.ts +5 -4
- package/src/runtime/RunIntentService.ts +3 -0
- package/src/workflow/dsl/ChainCursorResolver.ts +36 -0
- package/dist/InMemoryRunDataFactory-C7YItvHG.d.cts +0 -123
- package/dist/bootstrap-BxuTFTLB.cjs.map +0 -1
- package/dist/bootstrap-D_Yyi0wL.js.map +0 -1
- package/dist/di-0Wop7z1y.js.map +0 -1
- package/dist/di-BlEKdoZS.cjs.map +0 -1
- package/dist/runtime-DBzq5YBi.cjs.map +0 -1
- package/dist/runtime-cxmUkk0l.js.map +0 -1
|
@@ -5,13 +5,17 @@ import type {
|
|
|
5
5
|
NodeActivationRequest,
|
|
6
6
|
NodeExecutionContext,
|
|
7
7
|
NodeExecutionSnapshot,
|
|
8
|
+
NodeExecutionStatus,
|
|
8
9
|
NodeId,
|
|
9
10
|
NodeInputsByPort,
|
|
10
11
|
NodeOutputs,
|
|
11
12
|
PendingNodeExecution,
|
|
13
|
+
PendingResumeEntry,
|
|
12
14
|
PersistedRunSchedulingState,
|
|
13
15
|
PersistedRunState,
|
|
16
|
+
ResumeContext,
|
|
14
17
|
RunDataFactory,
|
|
18
|
+
RunHaltReason,
|
|
15
19
|
RunId,
|
|
16
20
|
RunQueueEntry,
|
|
17
21
|
RunResult,
|
|
@@ -146,6 +150,12 @@ export class RunContinuationService {
|
|
|
146
150
|
|
|
147
151
|
data.setOutputs(args.nodeId, args.outputs);
|
|
148
152
|
const completedAt = new Date().toISOString();
|
|
153
|
+
|
|
154
|
+
// Resolve HITL status from the node's decision output.
|
|
155
|
+
// Only fires when the output carries `item.json.decision.status` written by a
|
|
156
|
+
// defineHumanApprovalNode-based node. Non-HITL nodes never have this field.
|
|
157
|
+
const hitlResolution = this.resolveHitlStatus(args.outputs);
|
|
158
|
+
|
|
149
159
|
const completedSnapshot = this.semantics.createFinishedSnapshot({
|
|
150
160
|
workflow: wf,
|
|
151
161
|
previous: state.nodeSnapshotsByNodeId?.[args.nodeId],
|
|
@@ -157,8 +167,43 @@ export class RunContinuationService {
|
|
|
157
167
|
finishedAt: completedAt,
|
|
158
168
|
inputsByPort: pendingExecution.inputsByPort,
|
|
159
169
|
outputs: args.outputs,
|
|
170
|
+
hitlStatus: hitlResolution?.nodeStatus,
|
|
160
171
|
});
|
|
161
172
|
|
|
173
|
+
// Halt the run for HITL rejection / timeout outcomes.
|
|
174
|
+
if (hitlResolution?.halt) {
|
|
175
|
+
const haltedState = this.persistedRunStateTerminalBuilder.mergeTerminal({
|
|
176
|
+
state,
|
|
177
|
+
engineCounters: state.engineCounters ?? { completedNodeActivations: 0 },
|
|
178
|
+
status: "halted",
|
|
179
|
+
reason: hitlResolution.reason,
|
|
180
|
+
queue: [],
|
|
181
|
+
outputsByNode: data.dump(),
|
|
182
|
+
nodeSnapshotsByNodeId: {
|
|
183
|
+
...(state.nodeSnapshotsByNodeId ?? {}),
|
|
184
|
+
[args.nodeId]: completedSnapshot,
|
|
185
|
+
},
|
|
186
|
+
finishedAtIso: completedAt,
|
|
187
|
+
});
|
|
188
|
+
await this.workflowExecutionRepository.save(haltedState);
|
|
189
|
+
await this.nodeEventPublisher.publish("nodeCompleted", completedSnapshot);
|
|
190
|
+
await this.terminalPersistence.maybeDeleteAfterTerminalState({
|
|
191
|
+
workflow: wf,
|
|
192
|
+
state: haltedState,
|
|
193
|
+
finalStatus: "failed",
|
|
194
|
+
finishedAt: completedAt,
|
|
195
|
+
});
|
|
196
|
+
const result: RunResult = {
|
|
197
|
+
runId: state.runId,
|
|
198
|
+
workflowId: state.workflowId,
|
|
199
|
+
startedAt: state.startedAt,
|
|
200
|
+
status: "halted",
|
|
201
|
+
reason: hitlResolution.reason,
|
|
202
|
+
};
|
|
203
|
+
this.waiters.resolveRunCompletion(result);
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
|
|
162
207
|
const completedActivations = (state.engineCounters?.completedNodeActivations ?? 0) + 1;
|
|
163
208
|
const engineCounters = { completedNodeActivations: completedActivations };
|
|
164
209
|
const maxNodeActivations =
|
|
@@ -501,7 +546,7 @@ export class RunContinuationService {
|
|
|
501
546
|
return await this.resumeFromNodeError(args);
|
|
502
547
|
}
|
|
503
548
|
|
|
504
|
-
async waitForCompletion(runId: RunId): Promise<Extract<RunResult, { status: "completed" | "failed" }>> {
|
|
549
|
+
async waitForCompletion(runId: RunId): Promise<Extract<RunResult, { status: "completed" | "failed" | "halted" }>> {
|
|
505
550
|
const existing = await this.workflowExecutionRepository.load(runId);
|
|
506
551
|
if (existing?.status === "completed") {
|
|
507
552
|
const wf = this.resolvePersistedWorkflow(existing);
|
|
@@ -525,9 +570,18 @@ export class RunContinuationService {
|
|
|
525
570
|
error: { message: "Run failed" },
|
|
526
571
|
};
|
|
527
572
|
}
|
|
573
|
+
if (existing?.status === "halted") {
|
|
574
|
+
return {
|
|
575
|
+
runId: existing.runId,
|
|
576
|
+
workflowId: existing.workflowId,
|
|
577
|
+
startedAt: existing.startedAt,
|
|
578
|
+
status: "halted",
|
|
579
|
+
reason: existing.reason ?? "hitl-rejected",
|
|
580
|
+
};
|
|
581
|
+
}
|
|
528
582
|
|
|
529
583
|
const result = await this.waiters.waitForCompletion(runId);
|
|
530
|
-
if (result.status !== "completed" && result.status !== "failed") {
|
|
584
|
+
if (result.status !== "completed" && result.status !== "failed" && result.status !== "halted") {
|
|
531
585
|
throw new Error(`Unexpected run completion status: ${result.status}`);
|
|
532
586
|
}
|
|
533
587
|
return result;
|
|
@@ -537,6 +591,122 @@ export class RunContinuationService {
|
|
|
537
591
|
return await this.waiters.waitForWebhookResponse(runId);
|
|
538
592
|
}
|
|
539
593
|
|
|
594
|
+
/**
|
|
595
|
+
* Re-activate a previously suspended run item with a human decision.
|
|
596
|
+
*
|
|
597
|
+
* Called by the HITL resume endpoint. This method:
|
|
598
|
+
* 1. Loads `PersistedRunState` and locates the suspension entry by `taskId`.
|
|
599
|
+
* 2. Removes the entry from the `suspension` array; if empty, run stays `"suspended"` until
|
|
600
|
+
* enqueue flips it to `"pending"`.
|
|
601
|
+
* 3. Writes `pendingResume` onto the state so `NodeExecutionRequestHandlerService` can
|
|
602
|
+
* splice `resumeContext` into the node's execution context.
|
|
603
|
+
* 4. Reconstructs the original input from `outputsByNode` of the upstream node and
|
|
604
|
+
* enqueues a new activation via `activationEnqueueService`.
|
|
605
|
+
*
|
|
606
|
+
* @throws if the run is not found, not suspended, or the `taskId` is unknown.
|
|
607
|
+
*/
|
|
608
|
+
async resumeRun(args: { runId: RunId; taskId: string; resumeContext: ResumeContext }): Promise<RunResult> {
|
|
609
|
+
const state = await this.workflowExecutionRepository.load(args.runId);
|
|
610
|
+
if (!state) throw new Error(`Unknown runId: ${args.runId}`);
|
|
611
|
+
if (state.status !== "suspended") {
|
|
612
|
+
throw new Error(`Run ${args.runId} is not suspended (status: ${state.status})`);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const suspensionEntry = (state.suspension ?? []).find((s) => s.taskId === args.taskId);
|
|
616
|
+
if (!suspensionEntry) {
|
|
617
|
+
throw new Error(`No suspension entry with taskId "${args.taskId}" found on run ${args.runId}`);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const wf = this.resolvePersistedWorkflow(state);
|
|
621
|
+
if (!wf) throw new Error(`Unknown workflowId: ${state.workflowId}`);
|
|
622
|
+
|
|
623
|
+
const { topology, planner } = this.planningFactory.create(wf);
|
|
624
|
+
const def = topology.defsById.get(suspensionEntry.nodeId);
|
|
625
|
+
if (!def || def.kind !== "node") {
|
|
626
|
+
throw new Error(`Node ${suspensionEntry.nodeId} is not a runnable node`);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Reconstruct input: find the parent node that fed this node and use its main output.
|
|
630
|
+
// The single-item input corresponds to `itemIndex` in the original activation batch.
|
|
631
|
+
const data = this.runDataFactory.create(state.outputsByNode);
|
|
632
|
+
const limits = this.resolveEngineLimitsFromState(state);
|
|
633
|
+
const base = this.runExecutionContextFactory.create({
|
|
634
|
+
runId: state.runId,
|
|
635
|
+
workflowId: state.workflowId,
|
|
636
|
+
nodeId: suspensionEntry.nodeId,
|
|
637
|
+
parent: state.parent,
|
|
638
|
+
policySnapshot: state.policySnapshot,
|
|
639
|
+
subworkflowDepth: state.executionOptions?.subworkflowDepth ?? 0,
|
|
640
|
+
engineMaxNodeActivations: limits.engineMaxNodeActivations,
|
|
641
|
+
engineMaxSubworkflowDepth: limits.engineMaxSubworkflowDepth,
|
|
642
|
+
data,
|
|
643
|
+
nodeState: this.nodeStatePublisherFactory.create(state.runId, state.workflowId, state.parent),
|
|
644
|
+
testContext: state.executionOptions?.testContext,
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
// Find the original input items for this node from upstream outputs.
|
|
648
|
+
// Use the workflow edges to resolve the parent node. If no parent found, fall back to empty.
|
|
649
|
+
const parentEdges = wf.edges.filter((e) => e.to.nodeId === suspensionEntry.nodeId);
|
|
650
|
+
const parentNodeId = parentEdges[0]?.from.nodeId;
|
|
651
|
+
const parentOutputPort = parentEdges[0]?.from.output ?? "main";
|
|
652
|
+
const allParentItems = parentNodeId ? (data.getOutputItems(parentNodeId, parentOutputPort) ?? []) : [];
|
|
653
|
+
// Each suspended item gets its own resume; pass the single item at itemIndex.
|
|
654
|
+
const resumeInput =
|
|
655
|
+
allParentItems.length > suspensionEntry.itemIndex ? [allParentItems[suspensionEntry.itemIndex]!] : allParentItems;
|
|
656
|
+
|
|
657
|
+
const newActivationId = this.activationIdFactory.makeActivationId();
|
|
658
|
+
const pendingResume: PendingResumeEntry = {
|
|
659
|
+
activationId: newActivationId,
|
|
660
|
+
nodeId: suspensionEntry.nodeId,
|
|
661
|
+
resumeContext: args.resumeContext,
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
const remainingSuspensions = (state.suspension ?? []).filter((s) => s.taskId !== args.taskId);
|
|
665
|
+
|
|
666
|
+
// Thread resumeContext into the execution context so the inline scheduler path
|
|
667
|
+
// (InlineDrivingScheduler) delivers it directly to the node's ctx.resumeContext.
|
|
668
|
+
// On the worker path (BullMQ), NodeExecutionRequestHandlerService re-derives it
|
|
669
|
+
// from state.pendingResume — passing it here is additive and harmless.
|
|
670
|
+
const baseWithResume = { ...base, resumeContext: args.resumeContext };
|
|
671
|
+
|
|
672
|
+
const batchId = `resume_${newActivationId}`;
|
|
673
|
+
const request = this.nodeActivationRequestComposer.createSingleFromDefinitionWithActivation({
|
|
674
|
+
activationId: newActivationId,
|
|
675
|
+
runId: state.runId,
|
|
676
|
+
workflowId: state.workflowId,
|
|
677
|
+
parent: state.parent,
|
|
678
|
+
executionOptions: state.executionOptions,
|
|
679
|
+
base: baseWithResume,
|
|
680
|
+
data,
|
|
681
|
+
definition: { id: suspensionEntry.nodeId, config: def.config },
|
|
682
|
+
batchId,
|
|
683
|
+
input: resumeInput,
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
const { result, queuedSnapshot } = await this.activationEnqueueService.enqueueActivationWithSnapshot({
|
|
687
|
+
runId: state.runId,
|
|
688
|
+
workflowId: state.workflowId,
|
|
689
|
+
startedAt: state.startedAt,
|
|
690
|
+
parent: state.parent,
|
|
691
|
+
executionOptions: state.executionOptions,
|
|
692
|
+
control: state.control,
|
|
693
|
+
workflowSnapshot: state.workflowSnapshot,
|
|
694
|
+
mutableState: state.mutableState,
|
|
695
|
+
policySnapshot: state.policySnapshot,
|
|
696
|
+
pendingQueue: [],
|
|
697
|
+
request,
|
|
698
|
+
previousNodeSnapshotsByNodeId: state.nodeSnapshotsByNodeId ?? {},
|
|
699
|
+
planner,
|
|
700
|
+
engineCounters: state.engineCounters,
|
|
701
|
+
connectionInvocations: state.connectionInvocations ?? [],
|
|
702
|
+
suspension: remainingSuspensions.length > 0 ? remainingSuspensions : undefined,
|
|
703
|
+
pendingResume,
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
await this.nodeEventPublisher.publish("nodeQueued", queuedSnapshot);
|
|
707
|
+
return result;
|
|
708
|
+
}
|
|
709
|
+
|
|
540
710
|
private async resumeFromWebhookControl(args: {
|
|
541
711
|
state: NonNullable<Awaited<ReturnType<WorkflowExecutionRepository["load"]>>>;
|
|
542
712
|
schedulingState: PersistedRunSchedulingState | undefined;
|
|
@@ -996,6 +1166,60 @@ export class RunContinuationService {
|
|
|
996
1166
|
return result;
|
|
997
1167
|
}
|
|
998
1168
|
|
|
1169
|
+
/**
|
|
1170
|
+
* Inspects node outputs for a `decision.status` written by `defineHumanApprovalNode`.
|
|
1171
|
+
* Returns the first-class HITL node status and halt classification, or `undefined`
|
|
1172
|
+
* when the node is not a HITL approval node.
|
|
1173
|
+
*/
|
|
1174
|
+
private resolveHitlStatus(outputs: NodeOutputs):
|
|
1175
|
+
| {
|
|
1176
|
+
nodeStatus: Extract<
|
|
1177
|
+
NodeExecutionStatus,
|
|
1178
|
+
"hitl-approved" | "hitl-rejected" | "hitl-timeout" | "hitl-auto-accepted"
|
|
1179
|
+
>;
|
|
1180
|
+
halt: boolean;
|
|
1181
|
+
reason: RunHaltReason;
|
|
1182
|
+
}
|
|
1183
|
+
| { nodeStatus: Extract<NodeExecutionStatus, "hitl-approved" | "hitl-auto-accepted">; halt: false }
|
|
1184
|
+
| undefined {
|
|
1185
|
+
const firstItem = outputs?.main?.[0];
|
|
1186
|
+
const decisionStatus =
|
|
1187
|
+
firstItem &&
|
|
1188
|
+
typeof firstItem === "object" &&
|
|
1189
|
+
"json" in firstItem &&
|
|
1190
|
+
firstItem.json &&
|
|
1191
|
+
typeof firstItem.json === "object" &&
|
|
1192
|
+
"decision" in firstItem.json &&
|
|
1193
|
+
firstItem.json.decision &&
|
|
1194
|
+
typeof firstItem.json.decision === "object" &&
|
|
1195
|
+
"status" in firstItem.json.decision
|
|
1196
|
+
? (firstItem.json.decision as { status: string }).status
|
|
1197
|
+
: undefined;
|
|
1198
|
+
|
|
1199
|
+
if (!decisionStatus) return undefined;
|
|
1200
|
+
|
|
1201
|
+
if (decisionStatus === "approved") {
|
|
1202
|
+
return { nodeStatus: "hitl-approved", halt: false } as {
|
|
1203
|
+
nodeStatus: "hitl-approved";
|
|
1204
|
+
halt: false;
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
if (decisionStatus === "auto-accepted") {
|
|
1208
|
+
return { nodeStatus: "hitl-auto-accepted", halt: false } as {
|
|
1209
|
+
nodeStatus: "hitl-auto-accepted";
|
|
1210
|
+
halt: false;
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
if (decisionStatus === "rejected") {
|
|
1214
|
+
return { nodeStatus: "hitl-rejected", halt: true, reason: "hitl-rejected" as const };
|
|
1215
|
+
}
|
|
1216
|
+
if (decisionStatus === "timed-out") {
|
|
1217
|
+
return { nodeStatus: "hitl-timeout", halt: true, reason: "hitl-timeout" as const };
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
return undefined;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
999
1223
|
private formatNodeLabel(args: {
|
|
1000
1224
|
definition?: Readonly<{ id: NodeId; name?: string; type: unknown }>;
|
|
1001
1225
|
nodeId: NodeId;
|
|
@@ -33,7 +33,7 @@ export interface TestSuiteOrchestratorEngine {
|
|
|
33
33
|
parent?: ParentExecutionRef,
|
|
34
34
|
executionOptions?: RunExecutionOptions,
|
|
35
35
|
): Promise<RunResult>;
|
|
36
|
-
waitForCompletion(runId: RunId): Promise<Extract<RunResult, { status: "completed" | "failed" }>>;
|
|
36
|
+
waitForCompletion(runId: RunId): Promise<Extract<RunResult, { status: "completed" | "failed" | "halted" }>>;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export interface TestSuiteCaseOutcome {
|
|
@@ -275,16 +275,17 @@ export class TestSuiteOrchestrator {
|
|
|
275
275
|
...(args.testCaseLabel !== undefined ? { testCaseLabel: args.testCaseLabel } : {}),
|
|
276
276
|
});
|
|
277
277
|
|
|
278
|
-
let terminal: Extract<RunResult, { status: "completed" | "failed" }>;
|
|
278
|
+
let terminal: Extract<RunResult, { status: "completed" | "failed" | "halted" }>;
|
|
279
279
|
if (initial.status === "completed" || initial.status === "failed") {
|
|
280
280
|
terminal = initial;
|
|
281
281
|
} else {
|
|
282
282
|
terminal = await this.engine.waitForCompletion(runId);
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
// RunResult.status from the engine narrows to "completed" | "failed" here; widening to
|
|
285
|
+
// RunResult.status from the engine narrows to "completed" | "failed" | "halted" here; widening to
|
|
286
286
|
// "errored" / "cancelled" happens outside this code path (tracker downgrade for assertion
|
|
287
|
-
// failures; outer abort handling for cancelled).
|
|
287
|
+
// failures; outer abort handling for cancelled). Halted runs are treated as "failed" for
|
|
288
|
+
// test case status purposes.
|
|
288
289
|
const status: TestCaseRunStatus = terminal.status === "completed" ? "succeeded" : "failed";
|
|
289
290
|
await this.publish({
|
|
290
291
|
kind: "testCaseCompleted",
|
|
@@ -205,6 +205,9 @@ export class RunIntentService {
|
|
|
205
205
|
if (completed.status === "failed") {
|
|
206
206
|
throw new Error(completed.error.message);
|
|
207
207
|
}
|
|
208
|
+
if (completed.status === "halted") {
|
|
209
|
+
throw new Error(`Run halted: ${completed.reason}`);
|
|
210
|
+
}
|
|
208
211
|
return {
|
|
209
212
|
runId: completed.runId,
|
|
210
213
|
workflowId: completed.workflowId,
|
|
@@ -7,6 +7,9 @@ import type {
|
|
|
7
7
|
WorkflowDefinition,
|
|
8
8
|
} from "../../types";
|
|
9
9
|
|
|
10
|
+
import type { DefinedNodeCredentialBindings } from "../../authoring/defineNode.types";
|
|
11
|
+
import type { DefinedHumanApprovalNode, HumanApprovalOutputJson } from "../../authoring/defineHumanApprovalNode.types";
|
|
12
|
+
import { isHumanApprovalNode } from "../../authoring/defineHumanApprovalNode.types";
|
|
10
13
|
import { WorkflowBuilder } from "./WorkflowBuilder";
|
|
11
14
|
import { WhenBuilder } from "./WhenBuilder";
|
|
12
15
|
import type {
|
|
@@ -134,6 +137,39 @@ export class ChainCursor<TCurrentJson> {
|
|
|
134
137
|
return new ChainCursor<TNextJson>(this.wf, nextEndpoints);
|
|
135
138
|
}
|
|
136
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Chainable shorthand for `.then(node.create(config, metadata?.name, metadata?.nodeId))`.
|
|
142
|
+
*
|
|
143
|
+
* Signals to readers that this step suspends the run and waits for a human decision.
|
|
144
|
+
* Throws at workflow-build time if `node` was not created via `defineHumanApprovalNode`.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* workflow
|
|
149
|
+
* .trigger(...)
|
|
150
|
+
* .humanApproval(inboxApproval, { title: "Approve?", body: "...", priority: "normal" })
|
|
151
|
+
* .then(nextStep.create(...))
|
|
152
|
+
* .build();
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
humanApproval<
|
|
156
|
+
TKey extends string,
|
|
157
|
+
TConfig extends Record<string, unknown>,
|
|
158
|
+
TBindings extends DefinedNodeCredentialBindings | undefined = undefined,
|
|
159
|
+
>(
|
|
160
|
+
node: DefinedHumanApprovalNode<TKey, TConfig, TCurrentJson & Record<string, unknown>, TBindings>,
|
|
161
|
+
config: TConfig,
|
|
162
|
+
metadata?: { name?: string; nodeId?: string },
|
|
163
|
+
): ChainCursor<HumanApprovalOutputJson<TCurrentJson & Record<string, unknown>>> {
|
|
164
|
+
if (!isHumanApprovalNode(node)) {
|
|
165
|
+
throw new Error(
|
|
166
|
+
`.humanApproval() requires a node created via defineHumanApprovalNode (got '${(node as { key?: string }).key ?? String(node)}').`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
170
|
+
return this.then(node.create(config as any, metadata?.name, metadata?.nodeId));
|
|
171
|
+
}
|
|
172
|
+
|
|
137
173
|
build(): WorkflowDefinition {
|
|
138
174
|
return this.wf.build();
|
|
139
175
|
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { An as BinaryStorageStatResult, Ar as ExecutionTelemetryFactory, Bt as NodeOutputs, Ci as CredentialSessionService, Dn as BinaryBody, F as RunTestContext, Gt as PersistedRunPolicySnapshot, Ii as NodeId, In as ExecutionBinaryService, Jn as NodeExecutionContext, Jt as RunId, Kt as RunDataFactory, Ln as ExecutionContext, Mn as BinaryStorageWriteResult, On as BinaryStorage, Ot as MutableRunData, Qn as NodeExecutionStatePublisher, Rn as ExecutionContextFactory, Tn as RetryPolicySpec, Wt as ParentExecutionRef, Xt as RunnableNodeConfig, bt as Item, ei as CostTrackingTelemetryFactory, gt as BinaryAttachment, ii as CollectionsContext, kn as BinaryStorageReadResult, kt as NodeActivationId, qn as NodeBinaryAttachmentService, qt as RunDataSnapshot, zi as WorkflowId } from "./agentMcpTypes-ZiNbNsEi.cjs";
|
|
2
|
-
|
|
3
|
-
//#region src/execution/CredentialResolverFactory.d.ts
|
|
4
|
-
declare class CredentialResolverFactory {
|
|
5
|
-
private readonly credentialSessions;
|
|
6
|
-
constructor(credentialSessions: CredentialSessionService);
|
|
7
|
-
create(workflowId: WorkflowId, nodeId: NodeId, config?: NodeExecutionContext["config"]): NodeExecutionContext["getCredential"];
|
|
8
|
-
}
|
|
9
|
-
//#endregion
|
|
10
|
-
//#region src/binaries/UnavailableBinaryStorage.d.ts
|
|
11
|
-
declare class UnavailableBinaryStorage implements BinaryStorage {
|
|
12
|
-
readonly driverName = "unavailable";
|
|
13
|
-
write(): Promise<never>;
|
|
14
|
-
openReadStream(): Promise<undefined>;
|
|
15
|
-
stat(): Promise<{
|
|
16
|
-
exists: false;
|
|
17
|
-
}>;
|
|
18
|
-
delete(): Promise<void>;
|
|
19
|
-
deleteMany(): Promise<void>;
|
|
20
|
-
listByPrefix(): Promise<ReadonlyArray<string>>;
|
|
21
|
-
}
|
|
22
|
-
//#endregion
|
|
23
|
-
//#region src/binaries/DefaultExecutionBinaryServiceFactory.d.ts
|
|
24
|
-
declare class DefaultExecutionBinaryService implements ExecutionBinaryService {
|
|
25
|
-
private readonly storage;
|
|
26
|
-
private readonly workflowId;
|
|
27
|
-
private readonly runId;
|
|
28
|
-
private readonly now;
|
|
29
|
-
constructor(storage: BinaryStorage, workflowId: WorkflowId, runId: RunId, now: () => Date);
|
|
30
|
-
forNode(args: {
|
|
31
|
-
nodeId: NodeId;
|
|
32
|
-
activationId: NodeActivationId;
|
|
33
|
-
}): NodeBinaryAttachmentService;
|
|
34
|
-
openReadStream(attachment: BinaryAttachment): Promise<BinaryStorageReadResult | undefined>;
|
|
35
|
-
}
|
|
36
|
-
//#endregion
|
|
37
|
-
//#region src/execution/asyncSleeper.types.d.ts
|
|
38
|
-
interface AsyncSleeper {
|
|
39
|
-
sleep(ms: number): Promise<void>;
|
|
40
|
-
}
|
|
41
|
-
//#endregion
|
|
42
|
-
//#region src/execution/DefaultAsyncSleeper.d.ts
|
|
43
|
-
declare class DefaultAsyncSleeper implements AsyncSleeper {
|
|
44
|
-
sleep(ms: number): Promise<void>;
|
|
45
|
-
}
|
|
46
|
-
//#endregion
|
|
47
|
-
//#region src/execution/DefaultExecutionContextFactory.d.ts
|
|
48
|
-
declare class DefaultExecutionContextFactory implements ExecutionContextFactory {
|
|
49
|
-
private readonly binaryStorage;
|
|
50
|
-
private readonly telemetryFactory;
|
|
51
|
-
private readonly costTrackingFactory;
|
|
52
|
-
private readonly currentDate;
|
|
53
|
-
private readonly collections?;
|
|
54
|
-
private readonly telemetryDecoratorFactory;
|
|
55
|
-
constructor(binaryStorage?: BinaryStorage, telemetryFactory?: ExecutionTelemetryFactory, costTrackingFactory?: CostTrackingTelemetryFactory, currentDate?: () => Date, collections?: CollectionsContext | undefined);
|
|
56
|
-
create(args: {
|
|
57
|
-
runId: RunId;
|
|
58
|
-
workflowId: WorkflowId;
|
|
59
|
-
parent?: ParentExecutionRef;
|
|
60
|
-
policySnapshot?: PersistedRunPolicySnapshot;
|
|
61
|
-
subworkflowDepth: number;
|
|
62
|
-
engineMaxNodeActivations: number;
|
|
63
|
-
engineMaxSubworkflowDepth: number;
|
|
64
|
-
data: RunDataSnapshot;
|
|
65
|
-
nodeState?: NodeExecutionStatePublisher;
|
|
66
|
-
telemetry?: ExecutionContext["telemetry"];
|
|
67
|
-
getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
|
|
68
|
-
testContext?: RunTestContext;
|
|
69
|
-
}): ExecutionContext;
|
|
70
|
-
}
|
|
71
|
-
//#endregion
|
|
72
|
-
//#region src/execution/InProcessRetryRunner.d.ts
|
|
73
|
-
declare class InProcessRetryRunner {
|
|
74
|
-
private readonly sleeper;
|
|
75
|
-
constructor(sleeper: AsyncSleeper);
|
|
76
|
-
run<T>(policy: RetryPolicySpec | undefined, work: () => Promise<T>, shouldRetry?: (error: unknown) => boolean, warn?: (message: string) => void): Promise<T>;
|
|
77
|
-
private static delayAfterFailureMs;
|
|
78
|
-
private static normalizePolicy;
|
|
79
|
-
private static clampMaxAttempts;
|
|
80
|
-
private static assertPositiveInt;
|
|
81
|
-
private static assertNonNegativeFinite;
|
|
82
|
-
private static assertMultiplier;
|
|
83
|
-
}
|
|
84
|
-
//#endregion
|
|
85
|
-
//#region src/execution/ItemExprResolver.d.ts
|
|
86
|
-
/**
|
|
87
|
-
* Resolves {@link import("../contracts/itemExpr").ItemExpr} leaves on runnable config before {@link RunnableNode.execute}.
|
|
88
|
-
*/
|
|
89
|
-
declare class ItemExprResolver {
|
|
90
|
-
resolveConfigForItem<TConfig extends RunnableNodeConfig<any, any>>(ctx: NodeExecutionContext<TConfig>, item: Item, itemIndex: number, items: ReadonlyArray<Item>): Promise<NodeExecutionContext<TConfig>>;
|
|
91
|
-
}
|
|
92
|
-
//#endregion
|
|
93
|
-
//#region src/execution/RunnableOutputBehaviorResolver.d.ts
|
|
94
|
-
type RunnableOutputBehavior = Readonly<{
|
|
95
|
-
keepBinaries: boolean;
|
|
96
|
-
}>;
|
|
97
|
-
declare class RunnableOutputBehaviorResolver {
|
|
98
|
-
resolve(config: RunnableNodeConfig): RunnableOutputBehavior;
|
|
99
|
-
private isKeepBinariesEnabled;
|
|
100
|
-
}
|
|
101
|
-
//#endregion
|
|
102
|
-
//#region src/runStorage/InMemoryBinaryStorageRegistry.d.ts
|
|
103
|
-
declare class InMemoryBinaryStorage implements BinaryStorage {
|
|
104
|
-
readonly driverName = "memory";
|
|
105
|
-
private readonly values;
|
|
106
|
-
write(args: {
|
|
107
|
-
storageKey: string;
|
|
108
|
-
body: BinaryBody;
|
|
109
|
-
}): Promise<BinaryStorageWriteResult>;
|
|
110
|
-
openReadStream(storageKey: string): Promise<BinaryStorageReadResult | undefined>;
|
|
111
|
-
stat(storageKey: string): Promise<BinaryStorageStatResult>;
|
|
112
|
-
delete(storageKey: string): Promise<void>;
|
|
113
|
-
deleteMany(storageKeys: ReadonlyArray<string>): Promise<void>;
|
|
114
|
-
listByPrefix(prefix: string): Promise<ReadonlyArray<string>>;
|
|
115
|
-
}
|
|
116
|
-
//#endregion
|
|
117
|
-
//#region src/runStorage/InMemoryRunDataFactory.d.ts
|
|
118
|
-
declare class InMemoryRunDataFactory implements RunDataFactory {
|
|
119
|
-
create(initial?: Record<NodeId, NodeOutputs>): MutableRunData;
|
|
120
|
-
}
|
|
121
|
-
//#endregion
|
|
122
|
-
export { ItemExprResolver as a, DefaultAsyncSleeper as c, UnavailableBinaryStorage as d, CredentialResolverFactory as f, RunnableOutputBehaviorResolver as i, AsyncSleeper as l, InMemoryBinaryStorage as n, InProcessRetryRunner as o, RunnableOutputBehavior as r, DefaultExecutionContextFactory as s, InMemoryRunDataFactory as t, DefaultExecutionBinaryService as u };
|
|
123
|
-
//# sourceMappingURL=InMemoryRunDataFactory-C7YItvHG.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap-BxuTFTLB.cjs","names":["EngineExecutionLimitsPolicy","ENGINE_EXECUTION_LIMITS_DEFAULTS","RunFinishedAtFactory","out: RunPruneCandidate[]","RunFinishedAtFactory","engine: TestSuiteOrchestratorEngine","testSuiteRunIdFactory: TestSuiteRunIdFactory","credentialResolverFactory: CredentialResolverFactory","abortControllerFactory: AbortControllerFactory","eventBus: RunEventBus | undefined","currentDate: () => Date","setupContext: TestTriggerSetupContext","cases: TestSuiteCaseOutcome[]","waitForSlot: Promise<void> | undefined","releaseSlot: (() => void) | undefined","queue: Array<Promise<void>>","generationError: Error | undefined","status: TestSuiteRunStatus","executionOptions: RunExecutionOptions","terminal: Extract<RunResult, { status: \"completed\" | \"failed\" }>","status: TestCaseRunStatus","InlineDrivingScheduler","CoreTokens","NoOpAgentMcpIntegration","ItemExprResolver","NodeOutputNormalizer","RunnableOutputBehaviorResolver","ChildExecutionScopeFactory","NodeInstanceFactoryFactory","DefaultAsyncSleeper","InProcessRetryRunnerFactory","NodeExecutorFactory","RunIntentServiceFactory","EngineWorkflowRunnerServiceFactory","WorkflowRepositoryWebhookTriggerMatcherFactory","NodeExecutor","InlineDrivingScheduler","EngineFactory","Engine","RunIntentService"],"sources":["../src/policies/executionLimits/EngineExecutionLimitsPolicyFactory.ts","../src/runStorage/RunSummaryMapper.ts","../src/runStorage/InMemoryWorkflowExecutionRepository.ts","../src/orchestration/AbortControllerFactory.ts","../src/orchestration/TestSuiteOrchestrator.ts","../src/orchestration/TestSuiteRunIdFactory.ts","../src/scheduler/InlineDrivingSchedulerFactory.ts","../src/bootstrap/runtime/EngineRuntimeRegistrar.ts"],"sourcesContent":["import {\n EngineExecutionLimitsPolicy,\n ENGINE_EXECUTION_LIMITS_DEFAULTS,\n type EngineExecutionLimitsPolicyConfig,\n} from \"./EngineExecutionLimitsPolicy\";\n\n/**\n * Builds {@link EngineExecutionLimitsPolicy} by merging {@link ENGINE_EXECUTION_LIMITS_DEFAULTS} with optional `overrides` (e.g. host `runtime.engineExecutionLimits`).\n */\nexport class EngineExecutionLimitsPolicyFactory {\n create(overrides?: Partial<EngineExecutionLimitsPolicyConfig>): EngineExecutionLimitsPolicy {\n return new EngineExecutionLimitsPolicy({ ...ENGINE_EXECUTION_LIMITS_DEFAULTS, ...overrides });\n }\n}\n","import { RunFinishedAtFactory } from \"../contracts/runFinishedAtFactory\";\nimport type { PersistedRunState, RunSummary } from \"../types\";\n\n/** Maps persisted run state to API run summaries for listings. */\nexport class RunSummaryMapper {\n static fromPersistedState(state: PersistedRunState): RunSummary {\n return {\n runId: state.runId,\n workflowId: state.workflowId,\n startedAt: state.startedAt,\n status: state.status,\n finishedAt: RunFinishedAtFactory.resolveIso(state),\n parent: state.parent,\n executionOptions: state.executionOptions,\n };\n }\n}\n","import type {\n EngineRunCounters,\n NodeId,\n NodeOutputs,\n ParentExecutionRef,\n PersistedRunSchedulingState,\n PersistedRunState,\n RunId,\n RunSummary,\n WorkflowExecutionListingRepository,\n WorkflowExecutionPruneRepository,\n WorkflowExecutionRepository,\n RunPruneCandidate,\n WorkflowId,\n} from \"../types\";\nimport { RunFinishedAtFactory } from \"../contracts/runFinishedAtFactory\";\nimport { RunSummaryMapper } from \"./RunSummaryMapper\";\n\nexport class InMemoryWorkflowExecutionRepository\n implements WorkflowExecutionRepository, WorkflowExecutionListingRepository, WorkflowExecutionPruneRepository\n{\n private readonly runs = new Map<RunId, PersistedRunState>();\n\n async createRun(args: {\n runId: RunId;\n workflowId: WorkflowId;\n startedAt: string;\n parent?: ParentExecutionRef;\n executionOptions?: PersistedRunState[\"executionOptions\"];\n control?: PersistedRunState[\"control\"];\n workflowSnapshot?: PersistedRunState[\"workflowSnapshot\"];\n mutableState?: PersistedRunState[\"mutableState\"];\n policySnapshot?: PersistedRunState[\"policySnapshot\"];\n engineCounters?: EngineRunCounters;\n }): Promise<void> {\n this.runs.set(args.runId, {\n runId: args.runId,\n workflowId: args.workflowId,\n startedAt: args.startedAt,\n revision: 0,\n parent: args.parent,\n executionOptions: args.executionOptions,\n control: args.control,\n workflowSnapshot: args.workflowSnapshot,\n mutableState: args.mutableState,\n policySnapshot: args.policySnapshot,\n engineCounters: args.engineCounters,\n status: \"running\",\n queue: [],\n outputsByNode: {} as Record<NodeId, NodeOutputs>,\n nodeSnapshotsByNodeId: {},\n connectionInvocations: [],\n });\n }\n\n async load(runId: RunId): Promise<PersistedRunState | undefined> {\n return this.runs.get(runId);\n }\n\n async loadSchedulingState(runId: RunId): Promise<PersistedRunSchedulingState | undefined> {\n const state = this.runs.get(runId);\n if (!state) {\n return undefined;\n }\n return {\n pending: state.pending ? { ...state.pending } : undefined,\n queue: state.queue.map((entry) => ({ ...entry })),\n };\n }\n\n async save(state: PersistedRunState): Promise<void> {\n this.runs.set(state.runId, { ...state, revision: (state.revision ?? 0) + 1 });\n }\n\n async deleteRun(runId: RunId): Promise<void> {\n this.runs.delete(runId);\n }\n\n async listRuns(args?: Readonly<{ workflowId?: WorkflowId; limit?: number }>): Promise<ReadonlyArray<RunSummary>> {\n const limit = args?.limit ?? 50;\n const summaries = [...this.runs.values()]\n .filter((s) => (args?.workflowId ? s.workflowId === args.workflowId : true))\n .sort((a, b) => b.startedAt.localeCompare(a.startedAt))\n .slice(0, limit)\n .map((s) => RunSummaryMapper.fromPersistedState(s));\n return summaries;\n }\n\n async listRunsOlderThan(\n args: Readonly<{ nowIso: string; defaultRetentionSeconds: number; limit?: number }>,\n ): Promise<ReadonlyArray<RunPruneCandidate>> {\n const limit = args.limit ?? 100;\n const out: RunPruneCandidate[] = [];\n for (const s of this.runs.values()) {\n if (s.status !== \"completed\" && s.status !== \"failed\") continue;\n const finishedAt = RunFinishedAtFactory.resolveIso(s);\n const retentionSeconds = s.policySnapshot?.retentionSeconds ?? args.defaultRetentionSeconds;\n const cutoffIso = new Date(new Date(args.nowIso).getTime() - retentionSeconds * 1000).toISOString();\n if (!finishedAt || finishedAt >= cutoffIso) continue;\n out.push({\n runId: s.runId,\n workflowId: s.workflowId,\n startedAt: s.startedAt,\n finishedAt,\n });\n }\n out.sort((a, b) => a.finishedAt.localeCompare(b.finishedAt));\n return out.slice(0, limit);\n }\n}\n","/**\n * Mints fresh {@link AbortController}s. Injected (rather than direct `new`) to honor the\n * codebase's no-direct-construction rule and to give tests a seam for substituting a fake.\n */\nexport class AbortControllerFactory {\n create(): AbortController {\n return new AbortController();\n }\n}\n","import type { CredentialResolverFactory } from \"../execution/CredentialResolverFactory\";\nimport type { RunEventBus, TestCaseRunStatus, TestSuiteRunStatus } from \"../events/runEvents\";\nimport type {\n Item,\n Items,\n NodeId,\n ParentExecutionRef,\n RunExecutionOptions,\n RunId,\n RunResult,\n TestSuiteRunId,\n TestTriggerNodeConfig,\n TestTriggerSetupContext,\n TriggerNodeConfig,\n WorkflowDefinition,\n WorkflowId,\n} from \"../types\";\n\nimport type { AbortControllerFactory } from \"./AbortControllerFactory\";\nimport { TestSuiteRunIdFactory } from \"./TestSuiteRunIdFactory\";\n\nconst DEFAULT_CONCURRENCY = 4;\n\n/**\n * Engine-facade subset the orchestrator needs. Kept narrow on purpose so unit tests can\n * substitute a fake without depending on the full Engine wiring.\n */\nexport interface TestSuiteOrchestratorEngine {\n runWorkflow(\n wf: WorkflowDefinition,\n startAt: NodeId,\n items: Items,\n parent?: ParentExecutionRef,\n executionOptions?: RunExecutionOptions,\n ): Promise<RunResult>;\n waitForCompletion(runId: RunId): Promise<Extract<RunResult, { status: \"completed\" | \"failed\" }>>;\n}\n\nexport interface TestSuiteCaseOutcome {\n readonly testCaseIndex: number;\n readonly runId: RunId;\n readonly status: TestCaseRunStatus;\n}\n\nexport interface TestSuiteRunResult {\n readonly testSuiteRunId: TestSuiteRunId;\n readonly workflowId: WorkflowId;\n readonly triggerNodeId: NodeId;\n readonly status: TestSuiteRunStatus;\n readonly totalCases: number;\n readonly passedCases: number;\n readonly failedCases: number;\n readonly cases: ReadonlyArray<TestSuiteCaseOutcome>;\n}\n\nexport interface RunTestSuiteArgs {\n readonly workflow: WorkflowDefinition;\n readonly triggerNodeId: NodeId;\n readonly testSuiteRunId?: TestSuiteRunId;\n readonly concurrency?: number;\n readonly signal?: AbortSignal;\n}\n\n/**\n * Drives a {@link TestTriggerNodeConfig.generateItems} iterable into one workflow run per item,\n * with bounded concurrency. Pure engine logic — no persistence, no HTTP, no UI. Hosts adapt by\n * subscribing to {@link RunEventBus} and writing rows on `testSuite*` / `testCase*` / `nodeCompleted`.\n *\n * Cancellation: the supplied `AbortSignal` aborts the source iterable (so credentialed pulls bail)\n * and stops scheduling further cases. In-flight cases are awaited; engine-level cancellation of\n * an already-dispatched run is not yet wired (Phase 2).\n */\nexport class TestSuiteOrchestrator {\n constructor(\n private readonly engine: TestSuiteOrchestratorEngine,\n private readonly testSuiteRunIdFactory: TestSuiteRunIdFactory,\n private readonly credentialResolverFactory: CredentialResolverFactory,\n private readonly abortControllerFactory: AbortControllerFactory,\n private readonly eventBus: RunEventBus | undefined,\n private readonly currentDate: () => Date = () => new Date(),\n ) {}\n\n async runSuite(args: RunTestSuiteArgs): Promise<TestSuiteRunResult> {\n const triggerNodeId = args.triggerNodeId;\n const definition = args.workflow.nodes.find((n) => n.id === triggerNodeId);\n if (!definition) {\n throw new Error(`Unknown trigger nodeId: ${triggerNodeId}`);\n }\n if (definition.kind !== \"trigger\") {\n throw new Error(`Node ${triggerNodeId} is not a trigger`);\n }\n const triggerConfig = definition.config as TriggerNodeConfig;\n if (triggerConfig.triggerKind !== \"test\") {\n throw new Error(\n `Node ${triggerNodeId} is not a test trigger (triggerKind=\"${triggerConfig.triggerKind ?? \"live\"}\")`,\n );\n }\n const testTriggerConfig = triggerConfig as TestTriggerNodeConfig<unknown>;\n if (typeof testTriggerConfig.generateItems !== \"function\") {\n throw new Error(`Test trigger ${triggerNodeId} is missing a generateItems implementation`);\n }\n\n const testSuiteRunId = args.testSuiteRunId ?? this.testSuiteRunIdFactory.makeTestSuiteRunId();\n const concurrency = Math.max(1, args.concurrency ?? testTriggerConfig.concurrency ?? DEFAULT_CONCURRENCY);\n const externalSignal = args.signal;\n const internalAbort = this.abortControllerFactory.create();\n const onExternalAbort = () => internalAbort.abort(externalSignal?.reason);\n if (externalSignal) {\n if (externalSignal.aborted) {\n internalAbort.abort(externalSignal.reason);\n } else {\n externalSignal.addEventListener(\"abort\", onExternalAbort, { once: true });\n }\n }\n\n const triggerNodeName = definition.name ?? testTriggerConfig.name;\n\n await this.publish({\n kind: \"testSuiteStarted\",\n testSuiteRunId,\n workflowId: args.workflow.id,\n triggerNodeId,\n ...(triggerNodeName ? { triggerNodeName } : {}),\n concurrency,\n at: this.now(),\n });\n\n const setupContext: TestTriggerSetupContext = {\n workflowId: args.workflow.id,\n nodeId: triggerNodeId,\n config: testTriggerConfig,\n testSuiteRunId,\n getCredential: this.credentialResolverFactory.create(args.workflow.id, triggerNodeId, testTriggerConfig),\n signal: internalAbort.signal,\n };\n\n const cases: TestSuiteCaseOutcome[] = [];\n let nextIndex = 0;\n let inFlight = 0;\n let waitForSlot: Promise<void> | undefined;\n let releaseSlot: (() => void) | undefined;\n const queue: Array<Promise<void>> = [];\n let generationError: Error | undefined;\n\n const acquireSlot = async (): Promise<void> => {\n while (inFlight >= concurrency) {\n if (!waitForSlot) {\n waitForSlot = new Promise<void>((resolve) => {\n releaseSlot = resolve;\n });\n }\n await waitForSlot;\n }\n inFlight += 1;\n };\n\n const release = (): void => {\n inFlight -= 1;\n if (releaseSlot) {\n const fn = releaseSlot;\n releaseSlot = undefined;\n waitForSlot = undefined;\n fn();\n }\n };\n\n try {\n for await (const item of testTriggerConfig.generateItems(setupContext) as AsyncIterable<Item<unknown>>) {\n if (internalAbort.signal.aborted) {\n break;\n }\n await acquireSlot();\n if (internalAbort.signal.aborted) {\n release();\n break;\n }\n const testCaseIndex = nextIndex++;\n const testCaseLabel = this.resolveCaseLabel(testTriggerConfig, item);\n queue.push(\n this.runOneCase({\n workflow: args.workflow,\n triggerNodeId,\n testSuiteRunId,\n testCaseIndex,\n testCaseLabel,\n item,\n })\n .then((outcome) => {\n cases.push(outcome);\n })\n .finally(release),\n );\n }\n } catch (err) {\n generationError = err instanceof Error ? err : new Error(String(err));\n } finally {\n if (externalSignal) {\n externalSignal.removeEventListener(\"abort\", onExternalAbort);\n }\n }\n\n await Promise.all(queue);\n\n cases.sort((a, b) => a.testCaseIndex - b.testCaseIndex);\n const totalCases = cases.length;\n const passedCases = cases.filter((c) => c.status === \"succeeded\").length;\n const failedCases = cases.filter((c) => c.status === \"failed\").length;\n const status: TestSuiteRunStatus = this.deriveSuiteStatus({\n generationError,\n cancelled: internalAbort.signal.aborted,\n totalCases,\n passedCases,\n failedCases,\n });\n\n await this.publish({\n kind: \"testSuiteFinished\",\n testSuiteRunId,\n workflowId: args.workflow.id,\n status,\n totalCases,\n passedCases,\n failedCases,\n at: this.now(),\n });\n\n if (generationError && status === \"errored\") {\n throw generationError;\n }\n\n return {\n testSuiteRunId,\n workflowId: args.workflow.id,\n triggerNodeId,\n status,\n totalCases,\n passedCases,\n failedCases,\n cases,\n };\n }\n\n private async runOneCase(args: {\n workflow: WorkflowDefinition;\n triggerNodeId: NodeId;\n testSuiteRunId: TestSuiteRunId;\n testCaseIndex: number;\n testCaseLabel: string | undefined;\n item: Item<unknown>;\n }): Promise<TestSuiteCaseOutcome> {\n const executionOptions: RunExecutionOptions = {\n testContext: {\n testSuiteRunId: args.testSuiteRunId,\n testCaseIndex: args.testCaseIndex,\n ...(args.testCaseLabel !== undefined ? { testCaseLabel: args.testCaseLabel } : {}),\n },\n };\n\n const initial = await this.engine.runWorkflow(\n args.workflow,\n args.triggerNodeId,\n [args.item],\n undefined,\n executionOptions,\n );\n\n const runId = initial.runId;\n await this.publish({\n kind: \"testCaseStarted\",\n testSuiteRunId: args.testSuiteRunId,\n testCaseIndex: args.testCaseIndex,\n runId,\n workflowId: args.workflow.id,\n at: this.now(),\n ...(args.testCaseLabel !== undefined ? { testCaseLabel: args.testCaseLabel } : {}),\n });\n\n let terminal: Extract<RunResult, { status: \"completed\" | \"failed\" }>;\n if (initial.status === \"completed\" || initial.status === \"failed\") {\n terminal = initial;\n } else {\n terminal = await this.engine.waitForCompletion(runId);\n }\n\n // RunResult.status from the engine narrows to \"completed\" | \"failed\" here; widening to\n // \"errored\" / \"cancelled\" happens outside this code path (tracker downgrade for assertion\n // failures; outer abort handling for cancelled).\n const status: TestCaseRunStatus = terminal.status === \"completed\" ? \"succeeded\" : \"failed\";\n await this.publish({\n kind: \"testCaseCompleted\",\n testSuiteRunId: args.testSuiteRunId,\n testCaseIndex: args.testCaseIndex,\n runId,\n workflowId: args.workflow.id,\n status,\n at: this.now(),\n });\n return { testCaseIndex: args.testCaseIndex, runId, status };\n }\n\n private deriveSuiteStatus(args: {\n generationError: Error | undefined;\n cancelled: boolean;\n totalCases: number;\n passedCases: number;\n failedCases: number;\n }): TestSuiteRunStatus {\n if (args.generationError && args.totalCases === 0) {\n return \"errored\";\n }\n if (args.cancelled) {\n return \"cancelled\";\n }\n if (args.generationError) {\n return \"errored\";\n }\n if (args.totalCases === 0) {\n return \"succeeded\";\n }\n if (args.failedCases === 0) {\n return \"succeeded\";\n }\n if (args.passedCases === 0) {\n return \"failed\";\n }\n return \"partial\";\n }\n\n private now(): string {\n return this.currentDate().toISOString();\n }\n\n /** Defensive label resolver — author-supplied callbacks throw / return non-strings; we tolerate both. */\n private resolveCaseLabel(config: TestTriggerNodeConfig<unknown>, item: Item<unknown>): string | undefined {\n if (typeof config.caseLabel !== \"function\") return undefined;\n try {\n const result = config.caseLabel(item);\n if (typeof result !== \"string\") return undefined;\n const trimmed = result.trim();\n return trimmed.length === 0 ? undefined : trimmed;\n } catch {\n return undefined;\n }\n }\n\n private async publish(event: Parameters<RunEventBus[\"publish\"]>[0]): Promise<void> {\n if (!this.eventBus) return;\n await this.eventBus.publish(event);\n }\n}\n","import type { TestSuiteRunId } from \"../contracts/testTriggerTypes\";\n\n/**\n * Mints unique TestSuiteRun identifiers. Separated from {@link import(\"../types\").RunIdFactory}\n * so suite ids and per-case workflow run ids never alias.\n */\nexport class TestSuiteRunIdFactory {\n makeTestSuiteRunId(): TestSuiteRunId {\n return `tsr_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n }\n}\n","import { NodeExecutor } from \"../execution/NodeExecutor\";\n\nimport { InlineDrivingScheduler } from \"./InlineDrivingScheduler\";\n\nexport class InlineDrivingSchedulerFactory {\n create(nodeExecutor: NodeExecutor): InlineDrivingScheduler {\n return new InlineDrivingScheduler(nodeExecutor);\n }\n}\n","import { instanceCachingFactory, type DependencyContainer } from \"../../di\";\nimport { CoreTokens } from \"../../di\";\nimport { NoOpAgentMcpIntegration } from \"../../contracts/NoOpAgentMcpIntegration\";\nimport { EngineExecutionLimitsPolicyFactory } from \"../../policies/executionLimits/EngineExecutionLimitsPolicyFactory\";\nimport {\n ChildExecutionScopeFactory,\n DefaultAsyncSleeper,\n InProcessRetryRunnerFactory,\n ItemExprResolver,\n NodeExecutor,\n NodeExecutorFactory,\n NodeInstanceFactoryFactory,\n NodeOutputNormalizer,\n RunnableOutputBehaviorResolver,\n} from \"../../execution\";\nimport {\n EngineFactory,\n EngineWorkflowRunnerServiceFactory,\n RunIntentServiceFactory,\n RunIntentService,\n WorkflowRepositoryWebhookTriggerMatcherFactory,\n} from \"../../runtime\";\nimport { InlineDrivingScheduler } from \"../../scheduler/InlineDrivingScheduler\";\nimport { InlineDrivingSchedulerFactory } from \"../../scheduler/InlineDrivingSchedulerFactory\";\nimport { Engine } from \"../../orchestration/Engine\";\nimport type { EngineRuntimeRegistrationOptions } from \"./EngineRuntimeRegistration.types\";\nimport type { WebhookTriggerMatcherProvider } from \"./EngineRuntimeRegistration.types\";\n\n/**\n * Container-first entry: call on a host/test container **after** workflow, run, node, and credential\n * ports are registered. The registrar owns the default inline scheduler, engine binding,\n * and intent-surface wiring so hosts only override the seams they actually replace.\n */\nexport class EngineRuntimeRegistrar {\n register(container: DependencyContainer, options?: EngineRuntimeRegistrationOptions): void {\n this.registerSupportFactories(container);\n this.registerExecutionLimitsPolicy(container, options);\n this.ensureWorkflowNodeInstanceFactory(container);\n this.ensureNodeExecutor(container);\n this.registerDefaultActivationScheduler(container);\n this.registerEngine(container, options);\n this.registerIntentServices(container);\n this.registerAgentMcpIntegration(container);\n }\n\n private registerAgentMcpIntegration(container: DependencyContainer): void {\n if (container.isRegistered(CoreTokens.AgentMcpIntegration, true)) {\n return;\n }\n container.registerInstance(CoreTokens.AgentMcpIntegration, new NoOpAgentMcpIntegration());\n }\n\n private registerSupportFactories(container: DependencyContainer): void {\n if (!container.isRegistered(ItemExprResolver, true)) {\n container.registerSingleton(ItemExprResolver, ItemExprResolver);\n }\n if (!container.isRegistered(NodeOutputNormalizer, true)) {\n container.registerSingleton(NodeOutputNormalizer, NodeOutputNormalizer);\n }\n if (!container.isRegistered(RunnableOutputBehaviorResolver, true)) {\n container.registerSingleton(RunnableOutputBehaviorResolver, RunnableOutputBehaviorResolver);\n }\n if (!container.isRegistered(ChildExecutionScopeFactory, true)) {\n container.register(ChildExecutionScopeFactory, {\n useFactory: instanceCachingFactory((dependencyContainer) => {\n return new ChildExecutionScopeFactory(dependencyContainer.resolve(CoreTokens.ActivationIdFactory));\n }),\n });\n }\n container.registerSingleton(EngineExecutionLimitsPolicyFactory, EngineExecutionLimitsPolicyFactory);\n container.registerSingleton(NodeInstanceFactoryFactory, NodeInstanceFactoryFactory);\n container.registerSingleton(DefaultAsyncSleeper, DefaultAsyncSleeper);\n container.registerSingleton(InProcessRetryRunnerFactory, InProcessRetryRunnerFactory);\n container.registerSingleton(NodeExecutorFactory, NodeExecutorFactory);\n container.registerSingleton(InlineDrivingSchedulerFactory, InlineDrivingSchedulerFactory);\n container.registerSingleton(RunIntentServiceFactory, RunIntentServiceFactory);\n container.registerSingleton(EngineWorkflowRunnerServiceFactory, EngineWorkflowRunnerServiceFactory);\n container.registerSingleton(\n WorkflowRepositoryWebhookTriggerMatcherFactory,\n WorkflowRepositoryWebhookTriggerMatcherFactory,\n );\n }\n\n private registerExecutionLimitsPolicy(\n container: DependencyContainer,\n options: EngineRuntimeRegistrationOptions | undefined,\n ): void {\n if (container.isRegistered(CoreTokens.EngineExecutionLimitsPolicy, true)) {\n return;\n }\n container.register(CoreTokens.EngineExecutionLimitsPolicy, {\n useFactory: instanceCachingFactory((dependencyContainer) => {\n const fromResolver = options?.resolveEngineExecutionLimits?.();\n const merged = fromResolver ?? options?.engineExecutionLimits;\n return dependencyContainer.resolve(EngineExecutionLimitsPolicyFactory).create(merged);\n }),\n });\n }\n\n private ensureWorkflowNodeInstanceFactory(container: DependencyContainer): void {\n if (container.isRegistered(CoreTokens.WorkflowNodeInstanceFactory, true)) {\n return;\n }\n container.register(CoreTokens.WorkflowNodeInstanceFactory, {\n useFactory: instanceCachingFactory((dependencyContainer) => {\n return dependencyContainer\n .resolve(NodeInstanceFactoryFactory)\n .create(dependencyContainer.resolve(CoreTokens.NodeResolver));\n }),\n });\n }\n\n private ensureNodeExecutor(container: DependencyContainer): void {\n if (container.isRegistered(NodeExecutor, true)) {\n return;\n }\n container.register(NodeExecutor, {\n useFactory: instanceCachingFactory((dependencyContainer) => {\n const retryRunner = dependencyContainer\n .resolve(InProcessRetryRunnerFactory)\n .create(dependencyContainer.resolve(DefaultAsyncSleeper));\n return dependencyContainer\n .resolve(NodeExecutorFactory)\n .create(\n dependencyContainer.resolve(CoreTokens.WorkflowNodeInstanceFactory),\n retryRunner,\n dependencyContainer.resolve(RunnableOutputBehaviorResolver),\n );\n }),\n });\n }\n\n private registerDefaultActivationScheduler(container: DependencyContainer): void {\n if (container.isRegistered(CoreTokens.NodeActivationScheduler, true)) {\n return;\n }\n container.register(InlineDrivingScheduler, {\n useFactory: instanceCachingFactory((dependencyContainer) => {\n return dependencyContainer\n .resolve(InlineDrivingSchedulerFactory)\n .create(dependencyContainer.resolve(NodeExecutor));\n }),\n });\n container.register(CoreTokens.NodeActivationScheduler, {\n useFactory: instanceCachingFactory((dependencyContainer) => {\n return dependencyContainer.resolve(InlineDrivingScheduler);\n }),\n });\n }\n\n private registerEngine(container: DependencyContainer, options: EngineRuntimeRegistrationOptions | undefined): void {\n container.registerSingleton(EngineFactory, EngineFactory);\n const matcherProvider = this.resolveMatcherProvider(options);\n container.register(Engine, {\n useFactory: instanceCachingFactory((dependencyContainer) => {\n const liveWorkflowRepository = dependencyContainer.resolve(CoreTokens.LiveWorkflowRepository);\n const nodeResolver = dependencyContainer.resolve(CoreTokens.NodeResolver);\n const tokenRegistryLike = dependencyContainer.resolve(CoreTokens.PersistedWorkflowTokenRegistry);\n const workflowActivationPolicy = dependencyContainer.resolve(CoreTokens.WorkflowActivationPolicy);\n const webhookTriggerMatcher = matcherProvider.createMatcher(dependencyContainer);\n const workflowNodeInstanceFactory = dependencyContainer.resolve(CoreTokens.WorkflowNodeInstanceFactory);\n const triggerRuntimeDiagnostics = options?.triggerRuntimeDiagnosticsProvider?.create(dependencyContainer);\n return dependencyContainer.resolve(EngineFactory).create({\n credentialSessions: dependencyContainer.resolve(CoreTokens.CredentialSessionService),\n liveWorkflowRepository,\n workflowRepository: dependencyContainer.resolve(CoreTokens.WorkflowRepository),\n workflowActivationPolicy,\n nodeResolver,\n triggerSetupStateRepository: dependencyContainer.resolve(CoreTokens.TriggerSetupStateRepository),\n webhookTriggerMatcher,\n runIdFactory: dependencyContainer.resolve(CoreTokens.RunIdFactory),\n activationIdFactory: dependencyContainer.resolve(CoreTokens.ActivationIdFactory),\n workflowExecutionRepository: dependencyContainer.resolve(CoreTokens.WorkflowExecutionRepository),\n activationScheduler: dependencyContainer.resolve(CoreTokens.NodeActivationScheduler),\n runDataFactory: dependencyContainer.resolve(CoreTokens.RunDataFactory),\n executionContextFactory: dependencyContainer.resolve(CoreTokens.ExecutionContextFactory),\n nodeExecutor: dependencyContainer.resolve(NodeExecutor),\n eventBus: dependencyContainer.resolve(CoreTokens.RunEventBus),\n tokenRegistry: tokenRegistryLike,\n workflowNodeInstanceFactory,\n executionLimitsPolicy: dependencyContainer.resolve(CoreTokens.EngineExecutionLimitsPolicy),\n workflowPolicyRuntimeDefaults: options?.workflowPolicyRuntimeDefaults,\n triggerRuntimeDiagnostics,\n });\n }),\n });\n }\n\n private registerIntentServices(container: DependencyContainer): void {\n container.register(RunIntentService, {\n useFactory: instanceCachingFactory((dependencyContainer) => {\n return dependencyContainer\n .resolve(RunIntentServiceFactory)\n .create(dependencyContainer.resolve(Engine), dependencyContainer.resolve(CoreTokens.WorkflowRepository));\n }),\n });\n container.register(CoreTokens.WorkflowRunnerService, {\n useFactory: instanceCachingFactory((dependencyContainer) => {\n return dependencyContainer\n .resolve(EngineWorkflowRunnerServiceFactory)\n .create(dependencyContainer.resolve(Engine), dependencyContainer.resolve(CoreTokens.WorkflowRepository));\n }),\n });\n }\n\n private resolveMatcherProvider(options: EngineRuntimeRegistrationOptions | undefined): WebhookTriggerMatcherProvider {\n if (options?.webhookTriggerMatcherProvider) {\n return options.webhookTriggerMatcherProvider;\n }\n return {\n createMatcher: (container) =>\n container\n .resolve(WorkflowRepositoryWebhookTriggerMatcherFactory)\n .create(\n container.resolve(CoreTokens.WorkflowRepository),\n container.resolve(CoreTokens.WorkflowActivationPolicy),\n options?.webhookTriggerRoutingDiagnostics,\n ),\n };\n }\n}\n"],"mappings":"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"}
|