@codemation/core 0.8.1 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +386 -0
- package/dist/{EngineRuntimeRegistration.types-BP6tsaNP.d.ts → EngineRuntimeRegistration.types-D1fyApMI.d.ts} +2 -2
- package/dist/{EngineWorkflowRunnerService-DzOCa1BW.d.cts → EngineRuntimeRegistration.types-pB3FnzqR.d.cts} +17 -17
- package/dist/{InMemoryRunDataFactory-1iz7_SnO.d.cts → InMemoryRunDataFactory-Xw7v4-sj.d.cts} +31 -29
- package/dist/InMemoryRunEventBusRegistry-VM3OWnHo.cjs +47 -0
- package/dist/InMemoryRunEventBusRegistry-VM3OWnHo.cjs.map +1 -0
- package/dist/InMemoryRunEventBusRegistry-sM4z4n_i.js +41 -0
- package/dist/InMemoryRunEventBusRegistry-sM4z4n_i.js.map +1 -0
- package/dist/{RunIntentService-BqhmdoA1.d.ts → RunIntentService-BE9CAkbf.d.ts} +966 -471
- package/dist/{RunIntentService-S-1lW-gS.d.cts → RunIntentService-siBSjaaY.d.cts} +859 -493
- package/dist/bootstrap/index.cjs +5 -2
- package/dist/bootstrap/index.d.cts +212 -135
- package/dist/bootstrap/index.d.ts +4 -4
- package/dist/bootstrap/index.js +3 -3
- package/dist/{bootstrap-Bx1u4cbS.cjs → bootstrap-Cm5ruQxx.cjs} +253 -2
- package/dist/bootstrap-Cm5ruQxx.cjs.map +1 -0
- package/dist/{bootstrap-BoknFKnw.js → bootstrap-D3r505ko.js} +236 -3
- package/dist/bootstrap-D3r505ko.js.map +1 -0
- package/dist/{index-CVs9rVhl.d.ts → index-DeLl1Tne.d.ts} +632 -230
- package/dist/index.cjs +323 -176
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +544 -91
- package/dist/index.d.ts +3 -3
- package/dist/index.js +299 -166
- package/dist/index.js.map +1 -1
- package/dist/{runtime-DUW6tIJ1.js → runtime-BGNbRnqs.js} +934 -75
- package/dist/runtime-BGNbRnqs.js.map +1 -0
- package/dist/{runtime-Dvo2ru5A.cjs → runtime-DKXJwTNv.cjs} +1028 -73
- package/dist/runtime-DKXJwTNv.cjs.map +1 -0
- package/dist/testing.cjs +4 -4
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +3 -3
- package/package.json +7 -2
- package/src/ai/AiHost.ts +42 -14
- package/src/authoring/DefinedCollectionRegistry.ts +17 -0
- package/src/authoring/defineCollection.types.ts +181 -0
- package/src/authoring/definePollingTrigger.types.ts +396 -0
- package/src/authoring/definePollingTriggerInternals.ts +74 -0
- package/src/authoring/index.ts +19 -0
- package/src/bootstrap/index.ts +9 -0
- package/src/bootstrap/runtime/EngineRuntimeRegistrar.ts +8 -0
- package/src/browser.ts +1 -0
- package/src/contracts/CodemationTelemetryAttributeNames.ts +6 -0
- package/src/contracts/NoOpNodeExecutionTelemetry.ts +2 -11
- package/src/contracts/NoOpTelemetrySpanScope.ts +46 -10
- package/src/contracts/assertionTypes.ts +63 -0
- package/src/contracts/baseTypes.ts +12 -0
- package/src/contracts/collectionTypes.ts +44 -0
- package/src/contracts/credentialTypes.ts +23 -1
- package/src/contracts/executionPersistenceContracts.ts +30 -0
- package/src/contracts/index.ts +4 -0
- package/src/contracts/runTypes.ts +37 -1
- package/src/contracts/runtimeTypes.ts +42 -0
- package/src/contracts/telemetryTypes.ts +8 -0
- package/src/contracts/testTriggerTypes.ts +66 -0
- package/src/contracts/workflowTypes.ts +36 -7
- package/src/contracts.ts +59 -0
- package/src/events/ConnectionInvocationEventPublisher.ts +46 -0
- package/src/events/index.ts +1 -0
- package/src/events/runEvents.ts +74 -0
- package/src/execution/ChildExecutionScopeFactory.ts +55 -0
- package/src/execution/DefaultExecutionContextFactory.ts +6 -0
- package/src/execution/ExecutionTelemetryCostTrackingDecoratorFactory.ts +18 -0
- package/src/execution/NodeExecutor.ts +10 -2
- package/src/execution/NodeInstanceFactory.ts +13 -1
- package/src/execution/NodeInstantiationError.ts +16 -0
- package/src/execution/NodeRunStateWriter.ts +7 -0
- package/src/execution/NodeRunStateWriterFactory.ts +7 -0
- package/src/execution/WorkflowRunExecutionContextFactory.ts +3 -0
- package/src/execution/index.ts +2 -0
- package/src/index.ts +8 -0
- package/src/orchestration/AbortControllerFactory.ts +9 -0
- package/src/orchestration/NodeExecutionRequestHandlerService.ts +1 -0
- package/src/orchestration/RunContinuationService.ts +3 -0
- package/src/orchestration/RunStartService.ts +122 -3
- package/src/orchestration/TestSuiteOrchestrator.ts +350 -0
- package/src/orchestration/TestSuiteRunIdFactory.ts +11 -0
- package/src/orchestration/TriggerRuntimeService.ts +34 -7
- package/src/orchestration/index.ts +9 -0
- package/src/runtime/EngineFactory.ts +12 -0
- package/src/triggers/polling/PollingTriggerDedupWindow.ts +23 -0
- package/src/triggers/polling/PollingTriggerLogger.ts +18 -0
- package/src/triggers/polling/PollingTriggerRuntime.ts +122 -0
- package/src/triggers/polling/index.ts +5 -0
- package/src/types/index.ts +12 -9
- package/src/workflow/definition/NodeIterationIdFactory.ts +26 -0
- package/src/workflow/dsl/NodeIdSlugifier.ts +18 -0
- package/src/workflow/dsl/WorkflowBuilder.ts +71 -3
- package/src/workflow/dsl/WorkflowDefinitionError.ts +15 -0
- package/src/workflow/index.ts +3 -0
- package/dist/InMemoryRunEventBusRegistry-B0_C4OnP.cjs +0 -262
- package/dist/InMemoryRunEventBusRegistry-B0_C4OnP.cjs.map +0 -1
- package/dist/InMemoryRunEventBusRegistry-C2U83Hmv.js +0 -238
- package/dist/InMemoryRunEventBusRegistry-C2U83Hmv.js.map +0 -1
- package/dist/bootstrap-BoknFKnw.js.map +0 -1
- package/dist/bootstrap-Bx1u4cbS.cjs.map +0 -1
- package/dist/runtime-DUW6tIJ1.js.map +0 -1
- package/dist/runtime-Dvo2ru5A.cjs.map +0 -1
package/src/types/index.ts
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
|
+
// Re-export pure-type contracts first (available via @codemation/core/contracts subpath)
|
|
2
|
+
export * from "../contracts";
|
|
3
|
+
export type { CollectionStore, CollectionsContext } from "../contracts/collectionTypes";
|
|
4
|
+
|
|
5
|
+
// Additional runtime exports not included in contracts (factory classes, DSL builders, etc.)
|
|
1
6
|
export * from "../contracts/emitPorts";
|
|
2
7
|
export * from "../contracts/itemMeta";
|
|
3
|
-
export * from "../contracts/params";
|
|
4
8
|
export * from "../contracts/itemExpr";
|
|
5
|
-
export * from "../contracts/retryPolicySpec.types";
|
|
6
9
|
export * from "../contracts/NoRetryPolicy";
|
|
7
10
|
export * from "../contracts/RetryPolicy";
|
|
8
11
|
export * from "../contracts/ExpRetryPolicy";
|
|
9
12
|
export * from "../contracts/credentialTypes";
|
|
10
|
-
export * from "../contracts/CostCatalogContract";
|
|
11
13
|
export * from "../contracts/CostTrackingTelemetryContract";
|
|
12
14
|
export * from "../contracts/NoOpCostTrackingTelemetry";
|
|
13
15
|
export * from "../contracts/NoOpCostTrackingTelemetryFactory";
|
|
14
|
-
export * from "../contracts/
|
|
15
|
-
export * from "../contracts/runtimeTypes";
|
|
16
|
-
export * from "../contracts/telemetryTypes";
|
|
16
|
+
export * from "../contracts/NoOpExecutionTelemetryFactory";
|
|
17
17
|
export * from "../contracts/runFinishedAtFactory";
|
|
18
|
-
export * from "../contracts/runTypes";
|
|
19
|
-
export * from "../contracts/webhookTypes";
|
|
20
|
-
export * from "../contracts/workflowTypes";
|
|
21
18
|
export * from "../contracts/workflowActivationPolicy";
|
|
19
|
+
// telemetryTypes and workflowTypes also have runtime exports (No-Op telemetry classes,
|
|
20
|
+
// attribute-name registries, `nodeRef` factory, unique-symbol type tags) — `contracts.ts`
|
|
21
|
+
// already re-exports them with `export type *` for the slim subpath; re-export with the
|
|
22
|
+
// full `export *` here so back-compat for `@codemation/core` (root) consumers is preserved.
|
|
23
|
+
export * from "../contracts/telemetryTypes";
|
|
24
|
+
export * from "../contracts/workflowTypes";
|
|
22
25
|
export * from "../workflow";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import type { NodeId } from "../../types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Unique ids for one per-item iteration of a runnable node's execute loop.
|
|
7
|
+
*
|
|
8
|
+
* Activations are per-batch (one scheduled execution of a node, possibly with N items).
|
|
9
|
+
* Iterations refine that to one identifier per item-index inside the batch loop, so per-item
|
|
10
|
+
* connection invocations and telemetry can be grouped without time-window heuristics.
|
|
11
|
+
*/
|
|
12
|
+
export class NodeIterationIdFactory {
|
|
13
|
+
static create(): string {
|
|
14
|
+
return `iter_${randomUUID()}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Deterministic id for tests when a stable sequence is needed. */
|
|
18
|
+
static createForTest(seed: string, sequence: number): string {
|
|
19
|
+
return `iter_${seed}_${sequence}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Deterministic id derived from a connection node id (for sub-agent / tool-call scopes). */
|
|
23
|
+
static createForConnection(connectionNodeId: NodeId, sequence: number): string {
|
|
24
|
+
return `iter_${connectionNodeId}_${sequence}`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a human-readable node label into a stable, URL-safe identifier segment.
|
|
3
|
+
*
|
|
4
|
+
* Rules:
|
|
5
|
+
* - Lowercase the entire string.
|
|
6
|
+
* - Replace every run of characters outside `[a-z0-9]` with a single `-`.
|
|
7
|
+
* - Strip any leading or trailing `-` characters.
|
|
8
|
+
* - Return `""` for blank/empty input.
|
|
9
|
+
*/
|
|
10
|
+
export const NodeIdSlugifier = {
|
|
11
|
+
slugify(label: string): string {
|
|
12
|
+
if (!label) return "";
|
|
13
|
+
return label
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
16
|
+
.replace(/^-+|-+$/g, "");
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -10,13 +10,22 @@ import type {
|
|
|
10
10
|
WorkflowId,
|
|
11
11
|
} from "../../types";
|
|
12
12
|
|
|
13
|
+
import { AgentConfigInspector } from "../../ai/AgentConfigInspectorFactory";
|
|
14
|
+
import { AgentConnectionNodeCollector } from "../../ai/AgentConnectionNodeCollector";
|
|
13
15
|
import { ChainCursor } from "./ChainCursorResolver";
|
|
16
|
+
import { NodeIdSlugifier } from "./NodeIdSlugifier";
|
|
17
|
+
import { WorkflowDefinitionError } from "./WorkflowDefinitionError";
|
|
14
18
|
import type { AnyRunnableNodeConfig, AnyTriggerNodeConfig } from "./workflowBuilderTypes";
|
|
15
19
|
|
|
20
|
+
type NodeIdEntry = Readonly<{
|
|
21
|
+
nodeId: string;
|
|
22
|
+
tokenName: string;
|
|
23
|
+
label: string;
|
|
24
|
+
}>;
|
|
25
|
+
|
|
16
26
|
export class WorkflowBuilder {
|
|
17
27
|
private readonly nodes: NodeDefinition[] = [];
|
|
18
28
|
private readonly edges: WorkflowDefinition["edges"] = [];
|
|
19
|
-
private seq = 0;
|
|
20
29
|
|
|
21
30
|
constructor(
|
|
22
31
|
private readonly meta: { id: WorkflowId; name: string },
|
|
@@ -24,8 +33,7 @@ export class WorkflowBuilder {
|
|
|
24
33
|
) {}
|
|
25
34
|
|
|
26
35
|
private add(config: NodeConfigBase): NodeRef {
|
|
27
|
-
const
|
|
28
|
-
const id = config.id ?? `${tokenName}:${++this.seq}`;
|
|
36
|
+
const id = config.id ?? NodeIdSlugifier.slugify(config.name ?? "");
|
|
29
37
|
this.nodes.push({ id, kind: config.kind, type: config.type, name: config.name, config });
|
|
30
38
|
return { id, kind: config.kind, name: config.name };
|
|
31
39
|
}
|
|
@@ -45,8 +53,68 @@ export class WorkflowBuilder {
|
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
build(): WorkflowDefinition {
|
|
56
|
+
this.validateNodeIds();
|
|
48
57
|
return { ...this.meta, nodes: this.nodes, edges: this.edges };
|
|
49
58
|
}
|
|
59
|
+
|
|
60
|
+
private validateNodeIds(): void {
|
|
61
|
+
const entries: NodeIdEntry[] = [];
|
|
62
|
+
|
|
63
|
+
for (const node of this.nodes) {
|
|
64
|
+
const tokenName = typeof node.type === "function" ? node.type.name : String(node.type);
|
|
65
|
+
entries.push({ nodeId: node.id, tokenName, label: node.name ?? "" });
|
|
66
|
+
|
|
67
|
+
if (AgentConfigInspector.isAgentNodeConfig(node.config)) {
|
|
68
|
+
for (const child of AgentConnectionNodeCollector.collect(node.id, node.config)) {
|
|
69
|
+
entries.push({ nodeId: child.nodeId, tokenName: child.typeName, label: child.name });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const emptyIds: NodeIdEntry[] = [];
|
|
75
|
+
const seenIds = new Map<string, NodeIdEntry>();
|
|
76
|
+
const duplicateIds: NodeIdEntry[] = [];
|
|
77
|
+
|
|
78
|
+
for (const entry of entries) {
|
|
79
|
+
if (!entry.nodeId) {
|
|
80
|
+
emptyIds.push(entry);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const existing = seenIds.get(entry.nodeId);
|
|
84
|
+
if (existing) {
|
|
85
|
+
if (!duplicateIds.includes(existing)) {
|
|
86
|
+
duplicateIds.push(existing);
|
|
87
|
+
}
|
|
88
|
+
duplicateIds.push(entry);
|
|
89
|
+
} else {
|
|
90
|
+
seenIds.set(entry.nodeId, entry);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (emptyIds.length === 0 && duplicateIds.length === 0) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const lines: string[] = ["WorkflowBuilder.build() found invalid node ids:"];
|
|
99
|
+
|
|
100
|
+
if (emptyIds.length > 0) {
|
|
101
|
+
lines.push(" Empty ids (label is blank and no explicit id was given):");
|
|
102
|
+
for (const e of emptyIds) {
|
|
103
|
+
lines.push(` - type "${e.tokenName}" label "${e.label}"`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (duplicateIds.length > 0) {
|
|
108
|
+
lines.push(" Duplicate ids:");
|
|
109
|
+
for (const e of duplicateIds) {
|
|
110
|
+
lines.push(` - id "${e.nodeId}" type "${e.tokenName}" label "${e.label}"`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
lines.push(" Fix: set an explicit `id:` on each offending node config.");
|
|
115
|
+
|
|
116
|
+
throw new WorkflowDefinitionError(lines.join("\n"));
|
|
117
|
+
}
|
|
50
118
|
}
|
|
51
119
|
|
|
52
120
|
export { ChainCursor } from "./ChainCursorResolver";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by {@link WorkflowBuilder.build} when the workflow definition is structurally invalid.
|
|
3
|
+
*
|
|
4
|
+
* Common causes:
|
|
5
|
+
* - A node has an empty effective id (label is blank and no explicit `id` was given).
|
|
6
|
+
* - Two or more nodes share the same effective id (label slugs collide or explicit ids clash).
|
|
7
|
+
*
|
|
8
|
+
* Fix: provide an explicit `id:` on the offending node configs.
|
|
9
|
+
*/
|
|
10
|
+
export class WorkflowDefinitionError extends Error {
|
|
11
|
+
constructor(message: string) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "WorkflowDefinitionError";
|
|
14
|
+
}
|
|
15
|
+
}
|
package/src/workflow/index.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
export { WorkflowBuilder } from "./dsl/WorkflowBuilder";
|
|
2
|
+
export { WorkflowDefinitionError } from "./dsl/WorkflowDefinitionError";
|
|
3
|
+
export { NodeIdSlugifier } from "./dsl/NodeIdSlugifier";
|
|
2
4
|
export { ChainCursor } from "./dsl/ChainCursorResolver";
|
|
3
5
|
export { WhenBuilder } from "./dsl/WhenBuilder";
|
|
4
6
|
export * from "./dsl/workflowBuilderTypes";
|
|
5
7
|
|
|
6
8
|
export { ConnectionInvocationIdFactory } from "./definition/ConnectionInvocationIdFactory";
|
|
7
9
|
export { ConnectionNodeIdFactory } from "./definition/ConnectionNodeIdFactory";
|
|
10
|
+
export { NodeIterationIdFactory } from "./definition/NodeIterationIdFactory";
|
|
8
11
|
export { WorkflowExecutableNodeClassifier } from "./definition/WorkflowExecutableNodeClassifier";
|
|
9
12
|
export * from "./definition/WorkflowExecutableNodeClassifierFactory";
|
|
10
13
|
|
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
//#region src/workflow/dsl/WhenBuilder.ts
|
|
3
|
-
var WhenBuilder = class WhenBuilder {
|
|
4
|
-
constructor(wf, from, branchPort) {
|
|
5
|
-
this.wf = wf;
|
|
6
|
-
this.from = from;
|
|
7
|
-
this.branchPort = branchPort;
|
|
8
|
-
}
|
|
9
|
-
addBranch(steps) {
|
|
10
|
-
const created = [];
|
|
11
|
-
let prev = null;
|
|
12
|
-
for (const cfg of steps) {
|
|
13
|
-
const ref = this.wf.add(cfg);
|
|
14
|
-
created.push(ref);
|
|
15
|
-
if (!prev) this.wf.connect(this.from, ref, this.branchPort, "in");
|
|
16
|
-
else this.wf.connect(prev, ref, "main", "in");
|
|
17
|
-
prev = ref;
|
|
18
|
-
}
|
|
19
|
-
for (const cfg of steps) {
|
|
20
|
-
const maybe = cfg;
|
|
21
|
-
if (!Array.isArray(maybe.upstreamRefs) || maybe.upstreamRefs.length === 0) continue;
|
|
22
|
-
maybe.upstreamRefs = maybe.upstreamRefs.map((r) => {
|
|
23
|
-
if (typeof r !== "string") return r;
|
|
24
|
-
const nodeId = created[parseInt(r.slice(1), 10)]?.id;
|
|
25
|
-
return nodeId ? { nodeId } : { nodeId: r };
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
return this;
|
|
29
|
-
}
|
|
30
|
-
when = (branch, steps, ...more) => {
|
|
31
|
-
const list = Array.isArray(steps) ? steps : [steps, ...more];
|
|
32
|
-
const port = branch ? "true" : "false";
|
|
33
|
-
const b = new WhenBuilder(this.wf, this.from, port);
|
|
34
|
-
b.addBranch(list);
|
|
35
|
-
return b;
|
|
36
|
-
};
|
|
37
|
-
build() {
|
|
38
|
-
return this.wf.build();
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
//#endregion
|
|
43
|
-
//#region src/workflow/dsl/ChainCursorResolver.ts
|
|
44
|
-
var ChainCursor = class ChainCursor {
|
|
45
|
-
constructor(wf, endpoints) {
|
|
46
|
-
this.wf = wf;
|
|
47
|
-
this.endpoints = endpoints;
|
|
48
|
-
}
|
|
49
|
-
then(config) {
|
|
50
|
-
const next = this.wf.add(config);
|
|
51
|
-
const inputPortHint = this.resolveSharedInputPortHint();
|
|
52
|
-
for (const e of this.endpoints) this.wf.connect(e.node, next, e.output);
|
|
53
|
-
return new ChainCursor(this.wf, [{
|
|
54
|
-
node: next,
|
|
55
|
-
output: "main",
|
|
56
|
-
...inputPortHint ? { inputPortHint } : {}
|
|
57
|
-
}]);
|
|
58
|
-
}
|
|
59
|
-
thenIntoInputHints(config) {
|
|
60
|
-
const next = this.wf.add(config);
|
|
61
|
-
for (const e of this.endpoints) this.wf.connect(e.node, next, e.output, e.inputPortHint ?? "in");
|
|
62
|
-
return new ChainCursor(this.wf, [{
|
|
63
|
-
node: next,
|
|
64
|
-
output: "main"
|
|
65
|
-
}]);
|
|
66
|
-
}
|
|
67
|
-
when = ((arg1, steps, ...more) => {
|
|
68
|
-
if (this.endpoints.length !== 1) throw new Error("ChainCursor.when(...) is only supported from a single cursor endpoint");
|
|
69
|
-
const cursor = this.endpoints[0].node;
|
|
70
|
-
if (typeof arg1 === "boolean") {
|
|
71
|
-
const list = Array.isArray(steps) ? steps : steps ? [steps, ...more] : more;
|
|
72
|
-
const port = arg1 ? "true" : "false";
|
|
73
|
-
const b = new WhenBuilder(this.wf, cursor, port);
|
|
74
|
-
b.addBranch(list);
|
|
75
|
-
return b;
|
|
76
|
-
}
|
|
77
|
-
const branches = arg1;
|
|
78
|
-
const wfAny = this.wf;
|
|
79
|
-
const buildBranch = (port, branchSteps) => {
|
|
80
|
-
const list = branchSteps ?? [];
|
|
81
|
-
let prev = null;
|
|
82
|
-
for (const cfg of list) {
|
|
83
|
-
const ref = wfAny.add(cfg);
|
|
84
|
-
if (!prev) wfAny.connect(cursor, ref, port, "in");
|
|
85
|
-
else wfAny.connect(prev, ref, "main", "in");
|
|
86
|
-
prev = ref;
|
|
87
|
-
}
|
|
88
|
-
if (!prev) return {
|
|
89
|
-
end: cursor,
|
|
90
|
-
endOutput: port,
|
|
91
|
-
inputPortHint: port
|
|
92
|
-
};
|
|
93
|
-
return {
|
|
94
|
-
end: prev,
|
|
95
|
-
endOutput: "main",
|
|
96
|
-
inputPortHint: port
|
|
97
|
-
};
|
|
98
|
-
};
|
|
99
|
-
const t = buildBranch("true", branches.true);
|
|
100
|
-
const f = buildBranch("false", branches.false);
|
|
101
|
-
return new ChainCursor(this.wf, [{
|
|
102
|
-
node: t.end,
|
|
103
|
-
output: t.endOutput,
|
|
104
|
-
inputPortHint: t.inputPortHint
|
|
105
|
-
}, {
|
|
106
|
-
node: f.end,
|
|
107
|
-
output: f.endOutput,
|
|
108
|
-
inputPortHint: f.inputPortHint
|
|
109
|
-
}]);
|
|
110
|
-
});
|
|
111
|
-
route(branches) {
|
|
112
|
-
if (this.endpoints.length !== 1) throw new Error("ChainCursor.route(...) is only supported from a single cursor endpoint");
|
|
113
|
-
const cursor = this.endpoints[0];
|
|
114
|
-
const nextEndpoints = [];
|
|
115
|
-
for (const [port, branchFactory] of Object.entries(branches)) {
|
|
116
|
-
if (!branchFactory) continue;
|
|
117
|
-
const builtBranch = branchFactory(new ChainCursor(this.wf, [{
|
|
118
|
-
node: cursor.node,
|
|
119
|
-
output: port,
|
|
120
|
-
inputPortHint: port
|
|
121
|
-
}]));
|
|
122
|
-
if (!builtBranch) continue;
|
|
123
|
-
nextEndpoints.push(...builtBranch.endpoints);
|
|
124
|
-
}
|
|
125
|
-
return new ChainCursor(this.wf, nextEndpoints);
|
|
126
|
-
}
|
|
127
|
-
build() {
|
|
128
|
-
return this.wf.build();
|
|
129
|
-
}
|
|
130
|
-
resolveSharedInputPortHint() {
|
|
131
|
-
const first = this.endpoints[0]?.inputPortHint;
|
|
132
|
-
if (!first) return;
|
|
133
|
-
return this.endpoints.every((endpoint) => endpoint.inputPortHint === first) ? first : void 0;
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
//#endregion
|
|
138
|
-
//#region src/workflow/dsl/WorkflowBuilder.ts
|
|
139
|
-
var WorkflowBuilder = class {
|
|
140
|
-
nodes = [];
|
|
141
|
-
edges = [];
|
|
142
|
-
seq = 0;
|
|
143
|
-
constructor(meta, options) {
|
|
144
|
-
this.meta = meta;
|
|
145
|
-
this.options = options;
|
|
146
|
-
}
|
|
147
|
-
add(config) {
|
|
148
|
-
const tokenName = typeof config.type === "function" ? config.type.name : String(config.type);
|
|
149
|
-
const id = config.id ?? `${tokenName}:${++this.seq}`;
|
|
150
|
-
this.nodes.push({
|
|
151
|
-
id,
|
|
152
|
-
kind: config.kind,
|
|
153
|
-
type: config.type,
|
|
154
|
-
name: config.name,
|
|
155
|
-
config
|
|
156
|
-
});
|
|
157
|
-
return {
|
|
158
|
-
id,
|
|
159
|
-
kind: config.kind,
|
|
160
|
-
name: config.name
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
connect(from, to, fromOutput = "main", toInput = "in") {
|
|
164
|
-
this.edges.push({
|
|
165
|
-
from: {
|
|
166
|
-
nodeId: from.id,
|
|
167
|
-
output: fromOutput
|
|
168
|
-
},
|
|
169
|
-
to: {
|
|
170
|
-
nodeId: to.id,
|
|
171
|
-
input: toInput
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
trigger(config) {
|
|
176
|
-
const ref = this.add(config);
|
|
177
|
-
return new ChainCursor(this, [{
|
|
178
|
-
node: ref,
|
|
179
|
-
output: "main"
|
|
180
|
-
}]);
|
|
181
|
-
}
|
|
182
|
-
start(config) {
|
|
183
|
-
const ref = this.add(config);
|
|
184
|
-
return new ChainCursor(this, [{
|
|
185
|
-
node: ref,
|
|
186
|
-
output: "main"
|
|
187
|
-
}]);
|
|
188
|
-
}
|
|
189
|
-
build() {
|
|
190
|
-
return {
|
|
191
|
-
...this.meta,
|
|
192
|
-
nodes: this.nodes,
|
|
193
|
-
edges: this.edges
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
//#endregion
|
|
199
|
-
//#region src/events/InMemoryRunEventSubscription.ts
|
|
200
|
-
var InMemoryRunEventSubscription = class {
|
|
201
|
-
constructor(onClose) {
|
|
202
|
-
this.onClose = onClose;
|
|
203
|
-
}
|
|
204
|
-
async close() {
|
|
205
|
-
this.onClose();
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
//#endregion
|
|
210
|
-
//#region src/events/InMemoryRunEventBusRegistry.ts
|
|
211
|
-
var InMemoryRunEventBus = class {
|
|
212
|
-
globalListeners = /* @__PURE__ */ new Set();
|
|
213
|
-
listenersByWorkflowId = /* @__PURE__ */ new Map();
|
|
214
|
-
async publish(event) {
|
|
215
|
-
for (const listener of this.globalListeners) listener(event);
|
|
216
|
-
for (const listener of this.listenersByWorkflowId.get(event.workflowId) ?? []) listener(event);
|
|
217
|
-
}
|
|
218
|
-
async subscribe(onEvent) {
|
|
219
|
-
this.globalListeners.add(onEvent);
|
|
220
|
-
return new InMemoryRunEventSubscription(() => {
|
|
221
|
-
this.globalListeners.delete(onEvent);
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
async subscribeToWorkflow(workflowId, onEvent) {
|
|
225
|
-
const existing = this.listenersByWorkflowId.get(workflowId) ?? /* @__PURE__ */ new Set();
|
|
226
|
-
existing.add(onEvent);
|
|
227
|
-
this.listenersByWorkflowId.set(workflowId, existing);
|
|
228
|
-
return new InMemoryRunEventSubscription(() => {
|
|
229
|
-
const listeners = this.listenersByWorkflowId.get(workflowId);
|
|
230
|
-
if (!listeners) return;
|
|
231
|
-
listeners.delete(onEvent);
|
|
232
|
-
if (listeners.size === 0) this.listenersByWorkflowId.delete(workflowId);
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
//#endregion
|
|
238
|
-
Object.defineProperty(exports, 'ChainCursor', {
|
|
239
|
-
enumerable: true,
|
|
240
|
-
get: function () {
|
|
241
|
-
return ChainCursor;
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
Object.defineProperty(exports, 'InMemoryRunEventBus', {
|
|
245
|
-
enumerable: true,
|
|
246
|
-
get: function () {
|
|
247
|
-
return InMemoryRunEventBus;
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
Object.defineProperty(exports, 'WhenBuilder', {
|
|
251
|
-
enumerable: true,
|
|
252
|
-
get: function () {
|
|
253
|
-
return WhenBuilder;
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
Object.defineProperty(exports, 'WorkflowBuilder', {
|
|
257
|
-
enumerable: true,
|
|
258
|
-
get: function () {
|
|
259
|
-
return WorkflowBuilder;
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
//# sourceMappingURL=InMemoryRunEventBusRegistry-B0_C4OnP.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryRunEventBusRegistry-B0_C4OnP.cjs","names":["wf: WorkflowBuilder","from: NodeRef","branchPort: OutputPortKey","created: NodeRef[]","prev: NodeRef | null","port: OutputPortKey","wf: WorkflowBuilder","endpoints: ReadonlyArray<ChainCursorEndpoint>","port: OutputPortKey","prev: NodeRef | null","nextEndpoints: ChainCursorEndpoint[]","meta: { id: WorkflowId; name: string }","options?: Readonly<Record<string, never>>","onClose: () => void"],"sources":["../src/workflow/dsl/WhenBuilder.ts","../src/workflow/dsl/ChainCursorResolver.ts","../src/workflow/dsl/WorkflowBuilder.ts","../src/events/InMemoryRunEventSubscription.ts","../src/events/InMemoryRunEventBusRegistry.ts"],"sourcesContent":["import type { NodeId, NodeRef, OutputPortKey, UpstreamRefPlaceholder, WorkflowDefinition } from \"../../types\";\n\nimport { WorkflowBuilder } from \"./WorkflowBuilder\";\nimport type { AnyRunnableNodeConfig, BooleanWhenOverloads, ValidStepSequence } from \"./workflowBuilderTypes\";\n\nexport class WhenBuilder<TCurrentJson> {\n constructor(\n private readonly wf: WorkflowBuilder,\n private readonly from: NodeRef,\n private readonly branchPort: OutputPortKey,\n ) {}\n\n addBranch<TSteps extends ReadonlyArray<AnyRunnableNodeConfig>>(\n steps: TSteps & ValidStepSequence<TCurrentJson, TSteps>,\n ): this {\n const created: NodeRef[] = [];\n\n let prev: NodeRef | null = null;\n for (const cfg of steps) {\n const ref = (this.wf as any).add(cfg) as NodeRef;\n created.push(ref);\n if (!prev) (this.wf as any).connect(this.from, ref, this.branchPort, \"in\");\n else (this.wf as any).connect(prev, ref, \"main\", \"in\");\n prev = ref;\n }\n\n for (const cfg of steps) {\n const maybe = cfg as unknown as { upstreamRefs?: Array<{ nodeId: NodeId } | UpstreamRefPlaceholder> };\n if (!Array.isArray(maybe.upstreamRefs) || maybe.upstreamRefs.length === 0) continue;\n\n maybe.upstreamRefs = maybe.upstreamRefs.map((r) => {\n if (typeof r !== \"string\") return r;\n const idx = parseInt(r.slice(1), 10);\n const nodeId = created[idx]?.id;\n return nodeId ? { nodeId } : { nodeId: r };\n });\n }\n\n return this;\n }\n\n readonly when: BooleanWhenOverloads<TCurrentJson, WhenBuilder<TCurrentJson>> = (\n branch: boolean,\n steps: ReadonlyArray<AnyRunnableNodeConfig> | AnyRunnableNodeConfig,\n ...more: AnyRunnableNodeConfig[]\n ): WhenBuilder<TCurrentJson> => {\n const list = Array.isArray(steps) ? steps : [steps, ...more];\n const port: OutputPortKey = branch ? \"true\" : \"false\";\n const b = new WhenBuilder<TCurrentJson>(this.wf, this.from, port);\n b.addBranch(list);\n return b;\n };\n\n build(): WorkflowDefinition {\n return this.wf.build();\n }\n}\n","import type {\n InputPortKey,\n NodeRef,\n OutputPortKey,\n RunnableNodeConfig,\n RunnableNodeOutputJson,\n WorkflowDefinition,\n} from \"../../types\";\n\nimport { WorkflowBuilder } from \"./WorkflowBuilder\";\nimport { WhenBuilder } from \"./WhenBuilder\";\nimport type {\n AnyRunnableNodeConfig,\n BooleanWhenOverloads,\n BranchOutputGuard,\n BranchStepsArg,\n StepSequenceOutput,\n} from \"./workflowBuilderTypes\";\n\ntype ChainCursorEndpoint = Readonly<{ node: NodeRef; output: OutputPortKey; inputPortHint?: InputPortKey }>;\n\ntype ChainCursorWhenOverloads<TCurrentJson> = BooleanWhenOverloads<TCurrentJson, WhenBuilder<TCurrentJson>> & {\n <\n TTrueSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined,\n TFalseSteps extends ReadonlyArray<AnyRunnableNodeConfig> | undefined,\n >(\n branches: Readonly<{\n true?: TTrueSteps extends ReadonlyArray<AnyRunnableNodeConfig> ? BranchStepsArg<TCurrentJson, TTrueSteps> : never;\n false?: TFalseSteps extends ReadonlyArray<AnyRunnableNodeConfig>\n ? BranchStepsArg<TCurrentJson, TFalseSteps>\n : never;\n }> &\n BranchOutputGuard<TCurrentJson, TTrueSteps, TFalseSteps>,\n ): ChainCursor<StepSequenceOutput<TCurrentJson, TTrueSteps>>;\n};\n\nexport class ChainCursor<TCurrentJson> {\n constructor(\n private readonly wf: WorkflowBuilder,\n private readonly endpoints: ReadonlyArray<ChainCursorEndpoint>,\n ) {}\n\n then<TOutputJson, TConfig extends RunnableNodeConfig<TCurrentJson, TOutputJson>>(\n config: TConfig,\n ): ChainCursor<RunnableNodeOutputJson<TConfig>> {\n const next = (this.wf as any).add(config) as NodeRef;\n const inputPortHint = this.resolveSharedInputPortHint();\n for (const e of this.endpoints) {\n (this.wf as any).connect(e.node, next, e.output);\n }\n return new ChainCursor<RunnableNodeOutputJson<TConfig>>(this.wf, [\n { node: next, output: \"main\", ...(inputPortHint ? { inputPortHint } : {}) },\n ]);\n }\n\n thenIntoInputHints<TOutputJson, TConfig extends RunnableNodeConfig<any, TOutputJson>>(\n config: TConfig,\n ): ChainCursor<RunnableNodeOutputJson<TConfig>> {\n const next = (this.wf as any).add(config) as NodeRef;\n for (const e of this.endpoints) {\n (this.wf as any).connect(e.node, next, e.output, e.inputPortHint ?? \"in\");\n }\n return new ChainCursor<RunnableNodeOutputJson<TConfig>>(this.wf, [{ node: next, output: \"main\" }]);\n }\n\n readonly when: ChainCursorWhenOverloads<TCurrentJson> = ((\n arg1:\n | boolean\n | Readonly<{ true?: ReadonlyArray<AnyRunnableNodeConfig>; false?: ReadonlyArray<AnyRunnableNodeConfig> }>,\n steps?: ReadonlyArray<AnyRunnableNodeConfig> | AnyRunnableNodeConfig,\n ...more: AnyRunnableNodeConfig[]\n ): WhenBuilder<TCurrentJson> | ChainCursor<TCurrentJson> => {\n if (this.endpoints.length !== 1) {\n throw new Error(\"ChainCursor.when(...) is only supported from a single cursor endpoint\");\n }\n const cursor = this.endpoints[0]!.node;\n\n if (typeof arg1 === \"boolean\") {\n const list = Array.isArray(steps) ? steps : steps ? [steps, ...more] : more;\n const port: OutputPortKey = arg1 ? \"true\" : \"false\";\n const b = new WhenBuilder<TCurrentJson>(this.wf, cursor, port);\n b.addBranch(list);\n return b;\n }\n\n const branches = arg1;\n const wfAny = this.wf as any;\n\n const buildBranch = (\n port: OutputPortKey,\n branchSteps: ReadonlyArray<AnyRunnableNodeConfig> | undefined,\n ): Readonly<{ end: NodeRef; endOutput: OutputPortKey; inputPortHint: InputPortKey }> => {\n const list = branchSteps ?? [];\n let prev: NodeRef | null = null;\n for (const cfg of list) {\n const ref = wfAny.add(cfg) as NodeRef;\n if (!prev) wfAny.connect(cursor, ref, port, \"in\");\n else wfAny.connect(prev, ref, \"main\", \"in\");\n prev = ref;\n }\n if (!prev) return { end: cursor, endOutput: port, inputPortHint: port };\n return { end: prev, endOutput: \"main\", inputPortHint: port };\n };\n\n const t = buildBranch(\"true\", branches.true);\n const f = buildBranch(\"false\", branches.false);\n return new ChainCursor<TCurrentJson>(this.wf, [\n { node: t.end, output: t.endOutput, inputPortHint: t.inputPortHint },\n { node: f.end, output: f.endOutput, inputPortHint: f.inputPortHint },\n ]);\n }) as ChainCursorWhenOverloads<TCurrentJson>;\n\n route<TNextJson>(\n branches: Readonly<\n Record<OutputPortKey, (branch: ChainCursor<TCurrentJson>) => ChainCursor<TNextJson> | undefined>\n >,\n ): ChainCursor<TNextJson> {\n if (this.endpoints.length !== 1) {\n throw new Error(\"ChainCursor.route(...) is only supported from a single cursor endpoint\");\n }\n const cursor = this.endpoints[0]!;\n const nextEndpoints: ChainCursorEndpoint[] = [];\n for (const [port, branchFactory] of Object.entries(branches)) {\n if (!branchFactory) {\n continue;\n }\n const branch = new ChainCursor<TCurrentJson>(this.wf, [{ node: cursor.node, output: port, inputPortHint: port }]);\n const builtBranch = branchFactory(branch);\n if (!builtBranch) {\n continue;\n }\n nextEndpoints.push(...builtBranch.endpoints);\n }\n return new ChainCursor<TNextJson>(this.wf, nextEndpoints);\n }\n\n build(): WorkflowDefinition {\n return this.wf.build();\n }\n\n private resolveSharedInputPortHint(): InputPortKey | undefined {\n const first = this.endpoints[0]?.inputPortHint;\n if (!first) {\n return undefined;\n }\n return this.endpoints.every((endpoint) => endpoint.inputPortHint === first) ? first : undefined;\n }\n}\n","import type {\n InputPortKey,\n NodeConfigBase,\n NodeDefinition,\n NodeRef,\n OutputPortKey,\n RunnableNodeOutputJson,\n TriggerNodeOutputJson,\n WorkflowDefinition,\n WorkflowId,\n} from \"../../types\";\n\nimport { ChainCursor } from \"./ChainCursorResolver\";\nimport type { AnyRunnableNodeConfig, AnyTriggerNodeConfig } from \"./workflowBuilderTypes\";\n\nexport class WorkflowBuilder {\n private readonly nodes: NodeDefinition[] = [];\n private readonly edges: WorkflowDefinition[\"edges\"] = [];\n private seq = 0;\n\n constructor(\n private readonly meta: { id: WorkflowId; name: string },\n private readonly options?: Readonly<Record<string, never>>,\n ) {}\n\n private add(config: NodeConfigBase): NodeRef {\n const tokenName = typeof config.type === \"function\" ? config.type.name : String(config.type);\n const id = config.id ?? `${tokenName}:${++this.seq}`;\n this.nodes.push({ id, kind: config.kind, type: config.type, name: config.name, config });\n return { id, kind: config.kind, name: config.name };\n }\n\n private connect(from: NodeRef, to: NodeRef, fromOutput: OutputPortKey = \"main\", toInput: InputPortKey = \"in\"): void {\n this.edges.push({ from: { nodeId: from.id, output: fromOutput }, to: { nodeId: to.id, input: toInput } });\n }\n\n trigger<TConfig extends AnyTriggerNodeConfig>(config: TConfig): ChainCursor<TriggerNodeOutputJson<TConfig>> {\n const ref = this.add(config);\n return new ChainCursor<TriggerNodeOutputJson<TConfig>>(this, [{ node: ref, output: \"main\" }]);\n }\n\n start<TConfig extends AnyRunnableNodeConfig>(config: TConfig): ChainCursor<RunnableNodeOutputJson<TConfig>> {\n const ref = this.add(config);\n return new ChainCursor<RunnableNodeOutputJson<TConfig>>(this, [{ node: ref, output: \"main\" }]);\n }\n\n build(): WorkflowDefinition {\n return { ...this.meta, nodes: this.nodes, edges: this.edges };\n }\n}\n\nexport { ChainCursor } from \"./ChainCursorResolver\";\nexport { WhenBuilder } from \"./WhenBuilder\";\n","import type { RunEventSubscription } from \"./runEvents\";\n\nexport class InMemoryRunEventSubscription implements RunEventSubscription {\n constructor(private readonly onClose: () => void) {}\n\n async close(): Promise<void> {\n this.onClose();\n }\n}\n","import type { WorkflowId } from \"../types\";\n\nimport type { RunEvent, RunEventBus, RunEventSubscription } from \"./runEvents\";\n\nimport { InMemoryRunEventSubscription } from \"./InMemoryRunEventSubscription\";\n\nexport class InMemoryRunEventBus implements RunEventBus {\n private readonly globalListeners = new Set<(event: RunEvent) => void>();\n private readonly listenersByWorkflowId = new Map<WorkflowId, Set<(event: RunEvent) => void>>();\n\n async publish(event: RunEvent): Promise<void> {\n for (const listener of this.globalListeners) listener(event);\n for (const listener of this.listenersByWorkflowId.get(event.workflowId) ?? []) listener(event);\n }\n\n async subscribe(onEvent: (event: RunEvent) => void): Promise<RunEventSubscription> {\n this.globalListeners.add(onEvent);\n return new InMemoryRunEventSubscription(() => {\n this.globalListeners.delete(onEvent);\n });\n }\n\n async subscribeToWorkflow(workflowId: WorkflowId, onEvent: (event: RunEvent) => void): Promise<RunEventSubscription> {\n const existing = this.listenersByWorkflowId.get(workflowId) ?? new Set<(event: RunEvent) => void>();\n existing.add(onEvent);\n this.listenersByWorkflowId.set(workflowId, existing);\n\n return new InMemoryRunEventSubscription(() => {\n const listeners = this.listenersByWorkflowId.get(workflowId);\n if (!listeners) return;\n listeners.delete(onEvent);\n if (listeners.size === 0) this.listenersByWorkflowId.delete(workflowId);\n });\n }\n}\n\nexport { InMemoryRunEventSubscription } from \"./InMemoryRunEventSubscription\";\n"],"mappings":"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"}
|