@codemation/core-nodes 0.0.22 → 0.0.24
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 +18 -0
- package/dist/index.cjs +1606 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +189 -27
- package/dist/index.d.ts +189 -27
- package/dist/index.js +1580 -60
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +3 -0
- package/src/nodes/AIAgentConfig.ts +14 -4
- package/src/nodes/AIAgentNode.ts +40 -12
- package/src/nodes/AggregateNode.ts +19 -0
- package/src/nodes/FilterNode.ts +22 -0
- package/src/nodes/MapDataNode.ts +12 -9
- package/src/nodes/SplitNode.ts +26 -0
- package/src/nodes/aggregate.ts +21 -0
- package/src/nodes/filter.ts +23 -0
- package/src/nodes/split.ts +23 -0
- package/src/register.types.ts +6 -0
- package/src/workflowAuthoring/WorkflowBranchBuilder.types.ts +1 -1
- package/src/workflowAuthoring/WorkflowChain.types.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemation/core-nodes",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@langchain/core": "^1.1.31",
|
|
32
32
|
"@langchain/openai": "^1.2.12",
|
|
33
33
|
"lucide-react": "^0.577.0",
|
|
34
|
-
"@codemation/core": "0.2.
|
|
34
|
+
"@codemation/core": "0.2.3"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "^25.3.5",
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,10 @@ export * from "./chatModels/OpenAiChatModelPresetsFactory";
|
|
|
6
6
|
export * from "./nodes/aiAgent";
|
|
7
7
|
export * from "./nodes/CallbackNodeFactory";
|
|
8
8
|
export * from "./nodes/httpRequest";
|
|
9
|
+
export * from "./nodes/aggregate";
|
|
10
|
+
export * from "./nodes/filter";
|
|
9
11
|
export * from "./nodes/if";
|
|
12
|
+
export * from "./nodes/split";
|
|
10
13
|
export * from "./nodes/ManualTriggerFactory";
|
|
11
14
|
export * from "./nodes/mapData";
|
|
12
15
|
export * from "./nodes/merge";
|
|
@@ -4,15 +4,17 @@ import {
|
|
|
4
4
|
type AgentMessageConfig,
|
|
5
5
|
type AgentNodeConfig,
|
|
6
6
|
type ChatModelConfig,
|
|
7
|
+
type ItemInputMapper,
|
|
7
8
|
type RetryPolicySpec,
|
|
8
9
|
type RunnableNodeConfig,
|
|
9
10
|
type ToolConfig,
|
|
10
11
|
type TypeToken,
|
|
11
12
|
} from "@codemation/core";
|
|
13
|
+
import type { ZodType } from "zod";
|
|
12
14
|
|
|
13
15
|
import { AIAgentNode } from "./AIAgentNode";
|
|
14
16
|
|
|
15
|
-
export interface AIAgentOptions<TInputJson = unknown, _TOutputJson = unknown> {
|
|
17
|
+
export interface AIAgentOptions<TInputJson = unknown, _TOutputJson = unknown, TWireJson = TInputJson> {
|
|
16
18
|
readonly name: string;
|
|
17
19
|
readonly messages: AgentMessageConfig<TInputJson>;
|
|
18
20
|
readonly chatModel: ChatModelConfig;
|
|
@@ -20,14 +22,18 @@ export interface AIAgentOptions<TInputJson = unknown, _TOutputJson = unknown> {
|
|
|
20
22
|
readonly id?: string;
|
|
21
23
|
readonly retryPolicy?: RetryPolicySpec;
|
|
22
24
|
readonly guardrails?: AgentGuardrailConfig;
|
|
25
|
+
/** Engine applies with {@link RunnableNodeConfig.inputSchema} before {@link AIAgentNode.executeOne}. */
|
|
26
|
+
readonly inputSchema?: ZodType<TInputJson>;
|
|
27
|
+
/** Per-item mapper before validation; use with {@link inputSchema} so persisted run inputs show the prompt payload. */
|
|
28
|
+
readonly mapInput?: ItemInputMapper<TWireJson, TInputJson>;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
/**
|
|
26
32
|
* AI agent: credential bindings are keyed to connection-owned LLM/tool node ids (ConnectionNodeIdFactory),
|
|
27
33
|
* not to the agent workflow node id.
|
|
28
34
|
*/
|
|
29
|
-
export class AIAgent<TInputJson = unknown, TOutputJson = unknown>
|
|
30
|
-
implements RunnableNodeConfig<TInputJson, TOutputJson>, AgentNodeConfig<TInputJson, TOutputJson>
|
|
35
|
+
export class AIAgent<TInputJson = unknown, TOutputJson = unknown, TWireJson = TInputJson>
|
|
36
|
+
implements RunnableNodeConfig<TInputJson, TOutputJson, TWireJson>, AgentNodeConfig<TInputJson, TOutputJson, TWireJson>
|
|
31
37
|
{
|
|
32
38
|
readonly kind = "node" as const;
|
|
33
39
|
readonly type: TypeToken<unknown> = AIAgentNode;
|
|
@@ -40,8 +46,10 @@ export class AIAgent<TInputJson = unknown, TOutputJson = unknown>
|
|
|
40
46
|
readonly id?: string;
|
|
41
47
|
readonly retryPolicy: RetryPolicySpec;
|
|
42
48
|
readonly guardrails?: AgentGuardrailConfig;
|
|
49
|
+
readonly inputSchema?: ZodType<TInputJson>;
|
|
50
|
+
readonly mapInput?: ItemInputMapper<TWireJson, TInputJson>;
|
|
43
51
|
|
|
44
|
-
constructor(options: AIAgentOptions<TInputJson, TOutputJson>) {
|
|
52
|
+
constructor(options: AIAgentOptions<TInputJson, TOutputJson, TWireJson>) {
|
|
45
53
|
this.name = options.name;
|
|
46
54
|
this.messages = options.messages;
|
|
47
55
|
this.chatModel = options.chatModel;
|
|
@@ -49,5 +57,7 @@ export class AIAgent<TInputJson = unknown, TOutputJson = unknown>
|
|
|
49
57
|
this.id = options.id;
|
|
50
58
|
this.retryPolicy = options.retryPolicy ?? RetryPolicy.defaultForAiAgent;
|
|
51
59
|
this.guardrails = options.guardrails;
|
|
60
|
+
this.inputSchema = options.inputSchema;
|
|
61
|
+
this.mapInput = options.mapInput;
|
|
52
62
|
}
|
|
53
63
|
}
|
package/src/nodes/AIAgentNode.ts
CHANGED
|
@@ -4,13 +4,12 @@ import type {
|
|
|
4
4
|
ChatModelConfig,
|
|
5
5
|
ChatModelFactory,
|
|
6
6
|
Item,
|
|
7
|
+
ItemNode,
|
|
7
8
|
Items,
|
|
8
9
|
JsonValue,
|
|
9
10
|
LangChainChatModelLike,
|
|
10
|
-
Node,
|
|
11
11
|
NodeExecutionContext,
|
|
12
12
|
NodeInputsByPort,
|
|
13
|
-
NodeOutputs,
|
|
14
13
|
Tool,
|
|
15
14
|
ToolConfig,
|
|
16
15
|
ZodSchemaAny,
|
|
@@ -30,6 +29,7 @@ import {
|
|
|
30
29
|
} from "@codemation/core";
|
|
31
30
|
|
|
32
31
|
import { AIMessage, type BaseMessage } from "@langchain/core/messages";
|
|
32
|
+
import { z } from "zod";
|
|
33
33
|
|
|
34
34
|
import type { AIAgent } from "./AIAgentConfig";
|
|
35
35
|
import { AIAgentExecutionHelpersFactory } from "./AIAgentExecutionHelpersFactory";
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
type ResolvedGuardrails = Required<Pick<AgentGuardrailConfig, "maxTurns" | "onTurnLimitReached">> &
|
|
50
50
|
Pick<AgentGuardrailConfig, "modelInvocationOptions">;
|
|
51
51
|
|
|
52
|
-
/** Everything needed to run the agent loop for
|
|
52
|
+
/** Everything needed to run the agent loop for one item (shared across items in the same activation). */
|
|
53
53
|
interface PreparedAgentExecution {
|
|
54
54
|
readonly ctx: NodeExecutionContext<AIAgent<any, any>>;
|
|
55
55
|
readonly model: LangChainChatModelLike;
|
|
@@ -59,11 +59,21 @@ interface PreparedAgentExecution {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
@node({ packageName: "@codemation/core-nodes" })
|
|
62
|
-
export class AIAgentNode implements
|
|
62
|
+
export class AIAgentNode implements ItemNode<AIAgent<any, any>, unknown, unknown> {
|
|
63
63
|
kind = "node" as const;
|
|
64
64
|
outputPorts = ["main"] as const;
|
|
65
|
+
/**
|
|
66
|
+
* Engine applies {@link RunnableNodeConfig.mapInput} + parse before {@link #executeOne}. Prefer modeling
|
|
67
|
+
* prompts as {@code { messages: [{ role, content }, ...] }} so persisted inputs are visible in the UI.
|
|
68
|
+
*/
|
|
69
|
+
readonly inputSchema = z.unknown();
|
|
65
70
|
|
|
66
71
|
private readonly connectionCredentialExecutionContextFactory: ConnectionCredentialExecutionContextFactory;
|
|
72
|
+
/** One resolved model/tools bundle per activation context (same ctx across items in a batch). */
|
|
73
|
+
private readonly preparedByExecutionContext = new WeakMap<
|
|
74
|
+
NodeExecutionContext<AIAgent<any, any>>,
|
|
75
|
+
Promise<PreparedAgentExecution>
|
|
76
|
+
>();
|
|
67
77
|
|
|
68
78
|
constructor(
|
|
69
79
|
@inject(CoreTokens.NodeResolver)
|
|
@@ -79,17 +89,35 @@ export class AIAgentNode implements Node<AIAgent<any, any>> {
|
|
|
79
89
|
this.executionHelpers.createConnectionCredentialExecutionContextFactory(credentialSessions);
|
|
80
90
|
}
|
|
81
91
|
|
|
82
|
-
async
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
92
|
+
async executeOne(args: {
|
|
93
|
+
input: unknown;
|
|
94
|
+
item: Item;
|
|
95
|
+
itemIndex: number;
|
|
96
|
+
items: Items;
|
|
97
|
+
ctx: NodeExecutionContext<AIAgent<any, any>>;
|
|
98
|
+
}): Promise<unknown> {
|
|
99
|
+
const prepared = await this.getOrPrepareExecution(args.ctx);
|
|
100
|
+
const itemWithMappedJson = { ...args.item, json: args.input };
|
|
101
|
+
const resultItem = await this.runAgentForItem(prepared, itemWithMappedJson, args.itemIndex, args.items);
|
|
102
|
+
return resultItem.json;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private async getOrPrepareExecution(ctx: NodeExecutionContext<AIAgent<any, any>>): Promise<PreparedAgentExecution> {
|
|
106
|
+
let pending = this.preparedByExecutionContext.get(ctx);
|
|
107
|
+
if (!pending) {
|
|
108
|
+
pending = this.prepareExecution(ctx);
|
|
109
|
+
this.preparedByExecutionContext.set(ctx, pending);
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
return await pending;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
this.preparedByExecutionContext.delete(ctx);
|
|
115
|
+
throw error;
|
|
87
116
|
}
|
|
88
|
-
return { main: out };
|
|
89
117
|
}
|
|
90
118
|
|
|
91
119
|
/**
|
|
92
|
-
* Resolves the chat model and tools once, then
|
|
120
|
+
* Resolves the chat model and tools once per activation, then reuses for every item in the batch.
|
|
93
121
|
*/
|
|
94
122
|
private async prepareExecution(ctx: NodeExecutionContext<AIAgent<any, any>>): Promise<PreparedAgentExecution> {
|
|
95
123
|
const chatModelFactory = this.nodeResolver.resolve(ctx.config.chatModel.type) as ChatModelFactory<ChatModelConfig>;
|
|
@@ -467,7 +495,7 @@ export class AIAgentNode implements Node<AIAgent<any, any>> {
|
|
|
467
495
|
ctx: NodeExecutionContext<AIAgent<any, any>>,
|
|
468
496
|
): ReadonlyArray<BaseMessage> {
|
|
469
497
|
return AgentMessageFactory.createPromptMessages(
|
|
470
|
-
AgentMessageConfigNormalizer.
|
|
498
|
+
AgentMessageConfigNormalizer.resolveFromInputOrConfig(item.json, ctx.config, {
|
|
471
499
|
item,
|
|
472
500
|
itemIndex,
|
|
473
501
|
items,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Items, Node, NodeExecutionContext, NodeOutputs } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
import { node } from "@codemation/core";
|
|
4
|
+
|
|
5
|
+
import type { Aggregate } from "./aggregate";
|
|
6
|
+
|
|
7
|
+
@node({ packageName: "@codemation/core-nodes" })
|
|
8
|
+
export class AggregateNode implements Node<Aggregate<any, any>> {
|
|
9
|
+
kind = "node" as const;
|
|
10
|
+
outputPorts = ["main"] as const;
|
|
11
|
+
|
|
12
|
+
async execute(items: Items, ctx: NodeExecutionContext<Aggregate<any, any>>): Promise<NodeOutputs> {
|
|
13
|
+
if (items.length === 0) {
|
|
14
|
+
return { main: [] };
|
|
15
|
+
}
|
|
16
|
+
const json = await Promise.resolve(ctx.config.aggregate(items as Items, ctx));
|
|
17
|
+
return { main: [{ json }] };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Item, Items, Node, NodeExecutionContext, NodeOutputs } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
import { node } from "@codemation/core";
|
|
4
|
+
|
|
5
|
+
import type { Filter } from "./filter";
|
|
6
|
+
|
|
7
|
+
@node({ packageName: "@codemation/core-nodes" })
|
|
8
|
+
export class FilterNode implements Node<Filter<any>> {
|
|
9
|
+
kind = "node" as const;
|
|
10
|
+
outputPorts = ["main"] as const;
|
|
11
|
+
|
|
12
|
+
async execute(items: Items, ctx: NodeExecutionContext<Filter<any>>): Promise<NodeOutputs> {
|
|
13
|
+
const out: Item[] = [];
|
|
14
|
+
for (let i = 0; i < items.length; i++) {
|
|
15
|
+
const item = items[i] as Item;
|
|
16
|
+
if (ctx.config.predicate(item as Item, i, items as Items, ctx)) {
|
|
17
|
+
out.push(item);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return { main: out };
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/nodes/MapDataNode.ts
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import type { Item,
|
|
1
|
+
import type { Item, ItemNode, Items, NodeExecutionContext } from "@codemation/core";
|
|
2
2
|
|
|
3
3
|
import { node } from "@codemation/core";
|
|
4
|
+
import { z } from "zod";
|
|
4
5
|
|
|
5
6
|
import { MapData } from "./mapData";
|
|
6
7
|
|
|
7
8
|
@node({ packageName: "@codemation/core-nodes" })
|
|
8
|
-
export class MapDataNode implements
|
|
9
|
+
export class MapDataNode implements ItemNode<MapData<any, any>, unknown, unknown> {
|
|
9
10
|
kind = "node" as const;
|
|
10
11
|
outputPorts = ["main"] as const;
|
|
12
|
+
readonly inputSchema = z.unknown();
|
|
11
13
|
|
|
12
|
-
async
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
async executeOne(args: {
|
|
15
|
+
input: unknown;
|
|
16
|
+
item: Item;
|
|
17
|
+
itemIndex: number;
|
|
18
|
+
items: Items;
|
|
19
|
+
ctx: NodeExecutionContext<MapData<any, any>>;
|
|
20
|
+
}): Promise<unknown> {
|
|
21
|
+
return args.ctx.config.map(args.item, args.ctx);
|
|
19
22
|
}
|
|
20
23
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Item, Items, Node, NodeExecutionContext, NodeOutputs } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
import { node } from "@codemation/core";
|
|
4
|
+
|
|
5
|
+
import type { Split } from "./split";
|
|
6
|
+
|
|
7
|
+
@node({ packageName: "@codemation/core-nodes" })
|
|
8
|
+
export class SplitNode implements Node<Split<any, any>> {
|
|
9
|
+
kind = "node" as const;
|
|
10
|
+
outputPorts = ["main"] as const;
|
|
11
|
+
|
|
12
|
+
async execute(items: Items, ctx: NodeExecutionContext<Split<any, any>>): Promise<NodeOutputs> {
|
|
13
|
+
const out: Item[] = [];
|
|
14
|
+
for (let i = 0; i < items.length; i++) {
|
|
15
|
+
const item = items[i] as Item;
|
|
16
|
+
const elements = ctx.config.getElements(item, ctx);
|
|
17
|
+
for (let j = 0; j < elements.length; j++) {
|
|
18
|
+
out.push({
|
|
19
|
+
...item,
|
|
20
|
+
json: elements[j],
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return { main: out };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Items, NodeExecutionContext, RunnableNodeConfig, TypeToken } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
import { AggregateNode } from "./AggregateNode";
|
|
4
|
+
|
|
5
|
+
export class Aggregate<TIn = unknown, TOut = unknown> implements RunnableNodeConfig<TIn, TOut> {
|
|
6
|
+
readonly kind = "node" as const;
|
|
7
|
+
readonly type: TypeToken<unknown> = AggregateNode;
|
|
8
|
+
readonly execution = { hint: "local" } as const;
|
|
9
|
+
readonly icon = "lucide:layers" as const;
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
public readonly name: string,
|
|
13
|
+
public readonly aggregate: (
|
|
14
|
+
items: Items<TIn>,
|
|
15
|
+
ctx: NodeExecutionContext<Aggregate<TIn, TOut>>,
|
|
16
|
+
) => TOut | Promise<TOut>,
|
|
17
|
+
public readonly id?: string,
|
|
18
|
+
) {}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { AggregateNode } from "./AggregateNode";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Item, Items, NodeExecutionContext, RunnableNodeConfig, TypeToken } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
import { FilterNode } from "./FilterNode";
|
|
4
|
+
|
|
5
|
+
export class Filter<TIn = unknown> implements RunnableNodeConfig<TIn, TIn> {
|
|
6
|
+
readonly kind = "node" as const;
|
|
7
|
+
readonly type: TypeToken<unknown> = FilterNode;
|
|
8
|
+
readonly execution = { hint: "local" } as const;
|
|
9
|
+
readonly icon = "lucide:filter" as const;
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
public readonly name: string,
|
|
13
|
+
public readonly predicate: (
|
|
14
|
+
item: Item<TIn>,
|
|
15
|
+
index: number,
|
|
16
|
+
items: Items<TIn>,
|
|
17
|
+
ctx: NodeExecutionContext<Filter<TIn>>,
|
|
18
|
+
) => boolean,
|
|
19
|
+
public readonly id?: string,
|
|
20
|
+
) {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { FilterNode } from "./FilterNode";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Item, NodeExecutionContext, RunnableNodeConfig, TypeToken } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
import { SplitNode } from "./SplitNode";
|
|
4
|
+
|
|
5
|
+
export class Split<TIn = unknown, TElem = unknown> implements RunnableNodeConfig<TIn, TElem> {
|
|
6
|
+
readonly kind = "node" as const;
|
|
7
|
+
readonly type: TypeToken<unknown> = SplitNode;
|
|
8
|
+
readonly execution = { hint: "local" } as const;
|
|
9
|
+
/**
|
|
10
|
+
* When splitting yields zero items for a batch, downstream single-input nodes still run once with an empty batch.
|
|
11
|
+
* Mirrors {@link MapData}'s empty-output behavior.
|
|
12
|
+
*/
|
|
13
|
+
readonly continueWhenEmptyOutput = true as const;
|
|
14
|
+
readonly icon = "lucide:ungroup" as const;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
public readonly name: string,
|
|
18
|
+
public readonly getElements: (item: Item<TIn>, ctx: NodeExecutionContext<Split<TIn, TElem>>) => readonly TElem[],
|
|
19
|
+
public readonly id?: string,
|
|
20
|
+
) {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { SplitNode } from "./SplitNode";
|
package/src/register.types.ts
CHANGED
|
@@ -9,6 +9,9 @@ import { NoOpNode } from "./nodes/noOp";
|
|
|
9
9
|
import { SubWorkflowNode } from "./nodes/subWorkflow";
|
|
10
10
|
import { WaitNode } from "./nodes/wait";
|
|
11
11
|
import { ConnectionCredentialNode } from "./nodes/ConnectionCredentialNode";
|
|
12
|
+
import { AggregateNode } from "./nodes/aggregate";
|
|
13
|
+
import { FilterNode } from "./nodes/filter";
|
|
14
|
+
import { SplitNode } from "./nodes/split";
|
|
12
15
|
|
|
13
16
|
/**
|
|
14
17
|
* Registrar for built-in nodes. In a real project, this would use tsyringe's
|
|
@@ -34,4 +37,7 @@ export function registerCoreNodes(container: Container): void {
|
|
|
34
37
|
void AIAgentExecutionHelpersFactory;
|
|
35
38
|
void WaitNode;
|
|
36
39
|
void ConnectionCredentialNode;
|
|
40
|
+
void SplitNode;
|
|
41
|
+
void FilterNode;
|
|
42
|
+
void AggregateNode;
|
|
37
43
|
}
|
|
@@ -10,7 +10,7 @@ import { WorkflowDurationParser } from "./WorkflowDurationParser.types";
|
|
|
10
10
|
export class WorkflowBranchBuilder<TCurrentJson> {
|
|
11
11
|
constructor(private readonly steps: ReadonlyArray<AnyRunnableNodeConfig> = []) {}
|
|
12
12
|
|
|
13
|
-
then<TConfig extends RunnableNodeConfig<
|
|
13
|
+
then<TInputJson, TOutputJson, TConfig extends RunnableNodeConfig<TInputJson, TOutputJson, TCurrentJson>>(
|
|
14
14
|
config: TConfig,
|
|
15
15
|
): WorkflowBranchBuilder<RunnableNodeOutputJson<TConfig>> {
|
|
16
16
|
return new WorkflowBranchBuilder<RunnableNodeOutputJson<TConfig>>([...this.steps, config]);
|
|
@@ -18,7 +18,7 @@ type BranchOutputMatch<TLeft, TRight> = [TLeft] extends [TRight] ? ([TRight] ext
|
|
|
18
18
|
export class WorkflowChain<TCurrentJson> {
|
|
19
19
|
constructor(private readonly chain: ChainCursor<TCurrentJson>) {}
|
|
20
20
|
|
|
21
|
-
then<TConfig extends RunnableNodeConfig<
|
|
21
|
+
then<TInputJson, TOutputJson, TConfig extends RunnableNodeConfig<TInputJson, TOutputJson, TCurrentJson>>(
|
|
22
22
|
config: TConfig,
|
|
23
23
|
): WorkflowChain<RunnableNodeOutputJson<TConfig>> {
|
|
24
24
|
return new WorkflowChain(this.chain.then(config));
|