@codemation/core-nodes 0.0.24 → 0.1.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 CHANGED
@@ -1,5 +1,32 @@
1
1
  # @codemation/core-nodes
2
2
 
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#54](https://github.com/MadeRelevant/codemation/pull/54) [`35b78bb`](https://github.com/MadeRelevant/codemation/commit/35b78bb4d8c7ee2998a8b8e51e5ffc3fd901e4c7) Thanks [@cblokland90](https://github.com/cblokland90)! - **Breaking change:** `defineNode(...)` now follows the per-item pipeline: implement **`execute(args, context)`** (optional **`inputSchema`**, **`mapInput`**, and **`TWireJson`** on the generated runnable config). Add **`defineBatchNode(...)`** with **`run(items, context)`** for plugin nodes that still require batch **`run`** semantics.
8
+
9
+ Built-in nodes and workflow DSL (`split` / `filter` / `aggregate` on the fluent chain, Switch routing, execution normalization) align with the unified runnable model.
10
+
11
+ Align documentation (site guides, repo **`AGENTS.md`**, **`strict-oop-di`** skill, **`packages/core/docs/item-node-execution.md`**) and the **plugin** starter **`AGENTS.md`** with **config** for static wiring (credentials, retry, presentation) vs **inputs** / wire JSON for per-item behavior.
12
+
13
+ - [#56](https://github.com/MadeRelevant/codemation/pull/56) [`eb97e53`](https://github.com/MadeRelevant/codemation/commit/eb97e5376f4f620099c32c14d7797ed3039bf7bb) Thanks [@cblokland90](https://github.com/cblokland90)! - Add fluent workflow authoring support for port routing and core nodes.
14
+ - `workflow()` DSL: add `route(...)`, `merge(...)`, and `switch(...)` helpers so multi-port graphs can be expressed without manual `edges`.
15
+ - `Callback`: allow returning `emitPorts(...)` and configuring declared output ports and error handling options.
16
+ - Next host: fix execution inspector tree nesting by preferring `snapshot.parent.nodeId` when available (nested agent/tool invocations).
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies [[`35b78bb`](https://github.com/MadeRelevant/codemation/commit/35b78bb4d8c7ee2998a8b8e51e5ffc3fd901e4c7), [`eb97e53`](https://github.com/MadeRelevant/codemation/commit/eb97e5376f4f620099c32c14d7797ed3039bf7bb)]:
21
+ - @codemation/core@0.4.0
22
+
23
+ ## 0.0.25
24
+
25
+ ### Patch Changes
26
+
27
+ - Updated dependencies [[`bb2b3b8`](https://github.com/MadeRelevant/codemation/commit/bb2b3b89069697c6aa36aac1de7124c5eea65c3e)]:
28
+ - @codemation/core@0.3.0
29
+
3
30
  ## 0.0.24
4
31
 
5
32
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -2475,9 +2475,9 @@ let AIAgentExecutionHelpersFactory = class AIAgentExecutionHelpersFactory$1 {
2475
2475
  /**
2476
2476
  * `@cfworker/json-schema` iterates `schema.required` with `for...of`; it must be a string array or absent.
2477
2477
  */
2478
- sanitizeJsonSchemaRequiredKeywordsForCfworker(node$15) {
2479
- if (!node$15 || typeof node$15 !== "object" || Array.isArray(node$15)) return;
2480
- const o = node$15;
2478
+ sanitizeJsonSchemaRequiredKeywordsForCfworker(node$16) {
2479
+ if (!node$16 || typeof node$16 !== "object" || Array.isArray(node$16)) return;
2480
+ const o = node$16;
2481
2481
  const req = o.required;
2482
2482
  if (req !== void 0 && !Array.isArray(req)) delete o.required;
2483
2483
  else if (Array.isArray(req)) {
@@ -2521,9 +2521,12 @@ function __decorateParam(paramIndex, decorator) {
2521
2521
 
2522
2522
  //#endregion
2523
2523
  //#region src/nodes/NodeBackedToolRuntime.ts
2524
+ var _ref$1, _ref2$1;
2524
2525
  let NodeBackedToolRuntime = class NodeBackedToolRuntime$1 {
2525
- constructor(nodeResolver) {
2526
+ constructor(nodeResolver, itemValueResolver, outputNormalizer) {
2526
2527
  this.nodeResolver = nodeResolver;
2528
+ this.itemValueResolver = itemValueResolver;
2529
+ this.outputNormalizer = outputNormalizer;
2527
2530
  }
2528
2531
  async execute(config$1, args) {
2529
2532
  const nodeInput = config$1.toNodeItem({
@@ -2552,11 +2555,30 @@ let NodeBackedToolRuntime = class NodeBackedToolRuntime$1 {
2552
2555
  }
2553
2556
  async executeResolvedNode(resolvedNode, nodeInput, ctx) {
2554
2557
  if (this.isMultiInputNode(resolvedNode)) return await resolvedNode.executeMulti({ in: [nodeInput] }, ctx);
2555
- if (this.isNode(resolvedNode)) return await resolvedNode.execute([nodeInput], ctx);
2558
+ if (this.isRunnableNode(resolvedNode)) {
2559
+ const runnable = resolvedNode;
2560
+ const runnableConfig = ctx.config;
2561
+ const carry = runnableConfig.lineageCarry ?? "emitOnly";
2562
+ const parsed = (runnable.inputSchema ?? runnableConfig.inputSchema ?? unknown()).parse(nodeInput.json);
2563
+ const items = [nodeInput];
2564
+ const execArgs = {
2565
+ input: parsed,
2566
+ item: nodeInput,
2567
+ itemIndex: 0,
2568
+ items,
2569
+ ctx: await this.itemValueResolver.resolveConfigForItem(ctx, nodeInput, 0, items)
2570
+ };
2571
+ const raw = await Promise.resolve(runnable.execute(execArgs));
2572
+ return this.outputNormalizer.normalizeExecuteResult({
2573
+ baseItem: nodeInput,
2574
+ raw,
2575
+ carry
2576
+ });
2577
+ }
2556
2578
  throw new Error(`Node-backed tool expected a runnable node instance for "${ctx.config.name ?? ctx.nodeId}".`);
2557
2579
  }
2558
- isNode(value) {
2559
- return typeof value === "object" && value !== null && "execute" in value;
2580
+ isRunnableNode(value) {
2581
+ return typeof value === "object" && value !== null && value.kind === "node" && typeof value.execute === "function" && typeof value.executeMulti !== "function";
2560
2582
  }
2561
2583
  isMultiInputNode(value) {
2562
2584
  return typeof value === "object" && value !== null && "executeMulti" in value;
@@ -2565,7 +2587,13 @@ let NodeBackedToolRuntime = class NodeBackedToolRuntime$1 {
2565
2587
  NodeBackedToolRuntime = __decorate([
2566
2588
  (0, __codemation_core.injectable)(),
2567
2589
  __decorateParam(0, (0, __codemation_core.inject)(__codemation_core.CoreTokens.NodeResolver)),
2568
- __decorateMetadata("design:paramtypes", [Object])
2590
+ __decorateParam(1, (0, __codemation_core.inject)(__codemation_core.ItemValueResolver)),
2591
+ __decorateParam(2, (0, __codemation_core.inject)(__codemation_core.NodeOutputNormalizer)),
2592
+ __decorateMetadata("design:paramtypes", [
2593
+ Object,
2594
+ typeof (_ref$1 = typeof __codemation_core.ItemValueResolver !== "undefined" && __codemation_core.ItemValueResolver) === "function" ? _ref$1 : Object,
2595
+ typeof (_ref2$1 = typeof __codemation_core.NodeOutputNormalizer !== "undefined" && __codemation_core.NodeOutputNormalizer) === "function" ? _ref2$1 : Object
2596
+ ])
2569
2597
  ], NodeBackedToolRuntime);
2570
2598
 
2571
2599
  //#endregion
@@ -2583,8 +2611,9 @@ let AIAgentNode = class AIAgentNode$1 {
2583
2611
  kind = "node";
2584
2612
  outputPorts = ["main"];
2585
2613
  /**
2586
- * Engine applies {@link RunnableNodeConfig.mapInput} + parse before {@link #executeOne}. Prefer modeling
2587
- * prompts as {@code { messages: [{ role, content }, ...] }} so persisted inputs are visible in the UI.
2614
+ * Engine validates {@link RunnableNodeConfig.inputSchema} (Zod) on {@code item.json} before enqueue, then resolves
2615
+ * per-item **`itemValue`** leaves on config before {@link #execute}. Prefer modeling prompts as
2616
+ * {@code { messages: [{ role, content }, ...] }} (on input or config) so persisted inputs are visible in the UI.
2588
2617
  */
2589
2618
  inputSchema = unknown();
2590
2619
  connectionCredentialExecutionContextFactory;
@@ -2596,7 +2625,7 @@ let AIAgentNode = class AIAgentNode$1 {
2596
2625
  this.executionHelpers = executionHelpers;
2597
2626
  this.connectionCredentialExecutionContextFactory = this.executionHelpers.createConnectionCredentialExecutionContextFactory(credentialSessions);
2598
2627
  }
2599
- async executeOne(args) {
2628
+ async execute(args) {
2600
2629
  const prepared = await this.getOrPrepareExecution(args.ctx);
2601
2630
  const itemWithMappedJson = {
2602
2631
  ...args.item,
@@ -2944,7 +2973,6 @@ var AIAgent = class {
2944
2973
  retryPolicy;
2945
2974
  guardrails;
2946
2975
  inputSchema;
2947
- mapInput;
2948
2976
  constructor(options) {
2949
2977
  this.name = options.name;
2950
2978
  this.messages = options.messages;
@@ -2954,15 +2982,15 @@ var AIAgent = class {
2954
2982
  this.retryPolicy = options.retryPolicy ?? __codemation_core.RetryPolicy.defaultForAiAgent;
2955
2983
  this.guardrails = options.guardrails;
2956
2984
  this.inputSchema = options.inputSchema;
2957
- this.mapInput = options.mapInput;
2958
2985
  }
2959
2986
  };
2960
2987
 
2961
2988
  //#endregion
2962
2989
  //#region src/nodes/CallbackResultNormalizerFactory.ts
2963
2990
  var CallbackResultNormalizer = class {
2964
- static toNodeOutputs(result, items) {
2965
- return { main: result ?? items };
2991
+ static toPortsEmission(result, items) {
2992
+ if ((0, __codemation_core.isPortsEmission)(result)) return result;
2993
+ return (0, __codemation_core.emitPorts)({ main: result ?? items });
2966
2994
  }
2967
2995
  };
2968
2996
 
@@ -2971,9 +2999,18 @@ var CallbackResultNormalizer = class {
2971
2999
  let CallbackNode = class CallbackNode$1 {
2972
3000
  kind = "node";
2973
3001
  outputPorts = ["main"];
2974
- async execute(items, ctx) {
2975
- const result = await ctx.config.callback(items, ctx);
2976
- return CallbackResultNormalizer.toNodeOutputs(result, items);
3002
+ async execute(args) {
3003
+ const items = args.items ?? [];
3004
+ const ctx = args.ctx;
3005
+ const config$1 = ctx.config;
3006
+ if (config$1 == null) throw new Error("CallbackNode: missing ctx.config (engine should always pass runnable config)");
3007
+ if (items.length === 0) {
3008
+ const result$1 = await config$1.callback(items, ctx);
3009
+ return CallbackResultNormalizer.toPortsEmission(result$1, items);
3010
+ }
3011
+ if (args.itemIndex !== items.length - 1) return [];
3012
+ const result = await config$1.callback(items, ctx);
3013
+ return CallbackResultNormalizer.toPortsEmission(result, items);
2977
3014
  }
2978
3015
  };
2979
3016
  CallbackNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" })], CallbackNode);
@@ -2985,10 +3022,22 @@ var Callback = class Callback {
2985
3022
  type = CallbackNode;
2986
3023
  execution = { hint: "local" };
2987
3024
  icon = "lucide:braces";
2988
- constructor(name = "Callback", callback = Callback.defaultCallback, id) {
3025
+ emptyBatchExecution = "runOnce";
3026
+ id;
3027
+ retryPolicy;
3028
+ nodeErrorHandler;
3029
+ declaredOutputPorts;
3030
+ constructor(name = "Callback", callback = Callback.defaultCallback, idOrOptions, options) {
2989
3031
  this.name = name;
2990
3032
  this.callback = callback;
2991
- this.id = id;
3033
+ const resolvedOptions = typeof idOrOptions === "string" ? {
3034
+ ...options,
3035
+ id: idOrOptions
3036
+ } : idOrOptions;
3037
+ this.id = resolvedOptions?.id;
3038
+ this.retryPolicy = resolvedOptions?.retryPolicy;
3039
+ this.nodeErrorHandler = resolvedOptions?.nodeErrorHandler;
3040
+ this.declaredOutputPorts = resolvedOptions?.declaredOutputPorts;
2992
3041
  }
2993
3042
  static defaultCallback(items) {
2994
3043
  return items;
@@ -3000,10 +3049,8 @@ var Callback = class Callback {
3000
3049
  let HttpRequestNode = class HttpRequestNode$1 {
3001
3050
  kind = "node";
3002
3051
  outputPorts = ["main"];
3003
- async execute(items, ctx) {
3004
- const output = [];
3005
- for (const item of items) output.push(await this.executeItem(item, ctx));
3006
- return { main: output };
3052
+ async execute(args) {
3053
+ return await this.executeItem(args.item, args.ctx);
3007
3054
  }
3008
3055
  async executeItem(item, ctx) {
3009
3056
  const url = this.resolveUrl(item, ctx);
@@ -3110,9 +3157,9 @@ var HttpRequest = class {
3110
3157
  let AggregateNode = class AggregateNode$1 {
3111
3158
  kind = "node";
3112
3159
  outputPorts = ["main"];
3113
- async execute(items, ctx) {
3114
- if (items.length === 0) return { main: [] };
3115
- return { main: [{ json: await Promise.resolve(ctx.config.aggregate(items, ctx)) }] };
3160
+ async execute(args) {
3161
+ if (args.itemIndex !== args.items.length - 1) return [];
3162
+ return Promise.resolve(args.ctx.config.aggregate(args.items, args.ctx));
3116
3163
  }
3117
3164
  };
3118
3165
  AggregateNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" })], AggregateNode);
@@ -3136,13 +3183,9 @@ var Aggregate = class {
3136
3183
  let FilterNode = class FilterNode$1 {
3137
3184
  kind = "node";
3138
3185
  outputPorts = ["main"];
3139
- async execute(items, ctx) {
3140
- const out = [];
3141
- for (let i = 0; i < items.length; i++) {
3142
- const item = items[i];
3143
- if (ctx.config.predicate(item, i, items, ctx)) out.push(item);
3144
- }
3145
- return { main: out };
3186
+ execute(args) {
3187
+ if (args.ctx.config.predicate(args.item, args.itemIndex, args.items, args.ctx)) return args.item;
3188
+ return [];
3146
3189
  }
3147
3190
  };
3148
3191
  FilterNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" })], FilterNode);
@@ -3161,40 +3204,57 @@ var Filter = class {
3161
3204
  }
3162
3205
  };
3163
3206
 
3207
+ //#endregion
3208
+ //#region src/nodes/mergeExecutionUtils.types.ts
3209
+ function getOriginIndex(item) {
3210
+ return (0, __codemation_core.getOriginIndexFromItem)(item);
3211
+ }
3212
+ /**
3213
+ * Tags items routed to fan-in merge-by-origin (same contract as {@link IfNode} / {@link SwitchNode}).
3214
+ */
3215
+ function tagItemForRouterFanIn(args) {
3216
+ const { item, itemIndex, nodeId, inputPortLabel = "$in" } = args;
3217
+ const metaBase = item.meta && typeof item.meta === "object" ? item.meta : {};
3218
+ const cmBase = metaBase._cm && typeof metaBase._cm === "object" ? metaBase._cm : {};
3219
+ const originIndex = typeof cmBase.originIndex === "number" ? cmBase.originIndex : itemIndex;
3220
+ return {
3221
+ ...item,
3222
+ meta: {
3223
+ ...metaBase,
3224
+ _cm: {
3225
+ ...cmBase,
3226
+ originIndex
3227
+ }
3228
+ },
3229
+ paired: [{
3230
+ nodeId,
3231
+ output: inputPortLabel,
3232
+ itemIndex: originIndex
3233
+ }, ...item.paired ?? []]
3234
+ };
3235
+ }
3236
+ function orderedInputs(inputsByPort, prefer) {
3237
+ const keys = Object.keys(inputsByPort);
3238
+ const preferred = (prefer ?? []).filter((k) => keys.includes(k));
3239
+ const rest = keys.filter((k) => !preferred.includes(k)).sort();
3240
+ return [...preferred, ...rest];
3241
+ }
3242
+
3164
3243
  //#endregion
3165
3244
  //#region src/nodes/IfNode.ts
3166
3245
  let IfNode = class IfNode$1 {
3167
3246
  kind = "node";
3168
- outputPorts = ["true", "false"];
3169
- async execute(items, ctx) {
3170
- const t = [];
3171
- const f = [];
3172
- for (let i = 0; i < items.length; i++) {
3173
- const item = items[i];
3174
- const metaBase = item.meta && typeof item.meta === "object" ? item.meta : {};
3175
- const cmBase = metaBase._cm && typeof metaBase._cm === "object" ? metaBase._cm : {};
3176
- const originIndex = typeof cmBase.originIndex === "number" ? cmBase.originIndex : i;
3177
- const tagged = {
3178
- ...item,
3179
- meta: {
3180
- ...metaBase,
3181
- _cm: {
3182
- ...cmBase,
3183
- originIndex
3184
- }
3185
- },
3186
- paired: [{
3187
- nodeId: ctx.nodeId,
3188
- output: "$in",
3189
- itemIndex: originIndex
3190
- }, ...item.paired ?? []]
3191
- };
3192
- (ctx.config.predicate(item, i, items, ctx) ? t : f).push(tagged);
3193
- }
3194
- return {
3195
- true: t,
3196
- false: f
3197
- };
3247
+ execute(args) {
3248
+ const tagged = tagItemForRouterFanIn({
3249
+ item: args.item,
3250
+ itemIndex: args.itemIndex,
3251
+ nodeId: args.ctx.nodeId
3252
+ });
3253
+ const ok = args.ctx.config.predicate(args.item, args.itemIndex, args.items, args.ctx);
3254
+ return (0, __codemation_core.emitPorts)({
3255
+ true: ok ? [tagged] : [],
3256
+ false: ok ? [] : [tagged]
3257
+ });
3198
3258
  }
3199
3259
  };
3200
3260
  IfNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" })], IfNode);
@@ -3206,6 +3266,7 @@ var If = class {
3206
3266
  type = IfNode;
3207
3267
  execution = { hint: "local" };
3208
3268
  icon = "lucide:split";
3269
+ declaredOutputPorts = ["true", "false"];
3209
3270
  constructor(name, predicate, id) {
3210
3271
  this.name = name;
3211
3272
  this.predicate = predicate;
@@ -3213,22 +3274,47 @@ var If = class {
3213
3274
  }
3214
3275
  };
3215
3276
 
3277
+ //#endregion
3278
+ //#region src/nodes/SwitchNode.ts
3279
+ let SwitchNode = class SwitchNode$1 {
3280
+ kind = "node";
3281
+ async execute(args) {
3282
+ const tagged = tagItemForRouterFanIn({
3283
+ item: args.item,
3284
+ itemIndex: args.itemIndex,
3285
+ nodeId: args.ctx.nodeId
3286
+ });
3287
+ const key = await Promise.resolve(args.ctx.config.cfg.resolveCaseKey(args.item, args.itemIndex, args.items, args.ctx));
3288
+ const { cases, defaultCase } = args.ctx.config.cfg;
3289
+ return (0, __codemation_core.emitPorts)({ [cases.includes(key) ? key : defaultCase]: [tagged] });
3290
+ }
3291
+ };
3292
+ SwitchNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" })], SwitchNode);
3293
+
3294
+ //#endregion
3295
+ //#region src/nodes/switch.ts
3296
+ var Switch = class {
3297
+ kind = "node";
3298
+ type = SwitchNode;
3299
+ execution = { hint: "local" };
3300
+ icon = "lucide:git-branch-plus";
3301
+ lineageCarry = "carryThrough";
3302
+ declaredOutputPorts;
3303
+ constructor(name, cfg, id) {
3304
+ this.name = name;
3305
+ this.cfg = cfg;
3306
+ this.id = id;
3307
+ this.declaredOutputPorts = [...new Set([...cfg.cases, cfg.defaultCase])].sort();
3308
+ }
3309
+ };
3310
+
3216
3311
  //#endregion
3217
3312
  //#region src/nodes/SplitNode.ts
3218
3313
  let SplitNode = class SplitNode$1 {
3219
3314
  kind = "node";
3220
3315
  outputPorts = ["main"];
3221
- async execute(items, ctx) {
3222
- const out = [];
3223
- for (let i = 0; i < items.length; i++) {
3224
- const item = items[i];
3225
- const elements = ctx.config.getElements(item, ctx);
3226
- for (let j = 0; j < elements.length; j++) out.push({
3227
- ...item,
3228
- json: elements[j]
3229
- });
3230
- }
3231
- return { main: out };
3316
+ execute(args) {
3317
+ return args.ctx.config.getElements(args.item, args.ctx);
3232
3318
  }
3233
3319
  };
3234
3320
  SplitNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" })], SplitNode);
@@ -3301,7 +3387,7 @@ let MapDataNode = class MapDataNode$1 {
3301
3387
  kind = "node";
3302
3388
  outputPorts = ["main"];
3303
3389
  inputSchema = unknown();
3304
- async executeOne(args) {
3390
+ async execute(args) {
3305
3391
  return args.ctx.config.map(args.item, args.ctx);
3306
3392
  }
3307
3393
  };
@@ -3322,19 +3408,6 @@ var MapData = class {
3322
3408
  }
3323
3409
  };
3324
3410
 
3325
- //#endregion
3326
- //#region src/nodes/mergeExecutionUtils.types.ts
3327
- function getOriginIndex(item) {
3328
- const v = (item.meta?._cm)?.originIndex;
3329
- return typeof v === "number" && Number.isFinite(v) ? v : void 0;
3330
- }
3331
- function orderedInputs(inputsByPort, prefer) {
3332
- const keys = Object.keys(inputsByPort);
3333
- const preferred = (prefer ?? []).filter((k) => keys.includes(k));
3334
- const rest = keys.filter((k) => !preferred.includes(k)).sort();
3335
- return [...preferred, ...rest];
3336
- }
3337
-
3338
3411
  //#endregion
3339
3412
  //#region src/nodes/MergeNode.ts
3340
3413
  let MergeNode = class MergeNode$1 {
@@ -3405,8 +3478,8 @@ var Merge = class {
3405
3478
  let NoOpNode = class NoOpNode$1 {
3406
3479
  kind = "node";
3407
3480
  outputPorts = ["main"];
3408
- async execute(items, _ctx) {
3409
- return { main: items };
3481
+ execute(args) {
3482
+ return args.item;
3410
3483
  }
3411
3484
  };
3412
3485
  NoOpNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" })], NoOpNode);
@@ -3431,44 +3504,42 @@ let SubWorkflowNode = class SubWorkflowNode$1 {
3431
3504
  constructor(workflows) {
3432
3505
  this.workflows = workflows;
3433
3506
  }
3434
- async execute(items, ctx) {
3507
+ async execute(args) {
3508
+ const current = args.item;
3509
+ const metaBase = current.meta && typeof current.meta === "object" ? current.meta : {};
3510
+ const cmBase = metaBase._cm && typeof metaBase._cm === "object" ? metaBase._cm : {};
3511
+ const originIndex = typeof cmBase.originIndex === "number" ? cmBase.originIndex : void 0;
3512
+ const result = await this.workflows.runById({
3513
+ workflowId: args.ctx.config.workflowId,
3514
+ startAt: args.ctx.config.startAt,
3515
+ items: [current],
3516
+ parent: {
3517
+ runId: args.ctx.runId,
3518
+ workflowId: args.ctx.workflowId,
3519
+ nodeId: args.ctx.nodeId,
3520
+ subworkflowDepth: args.ctx.subworkflowDepth,
3521
+ engineMaxNodeActivations: args.ctx.engineMaxNodeActivations,
3522
+ engineMaxSubworkflowDepth: args.ctx.engineMaxSubworkflowDepth
3523
+ }
3524
+ });
3525
+ if (result.status !== "completed") throw new Error(`Subworkflow ${args.ctx.config.workflowId} did not complete (status=${result.status})`);
3435
3526
  const out = [];
3436
- for (let i = 0; i < items.length; i++) {
3437
- const current = items[i];
3438
- const metaBase = current.meta && typeof current.meta === "object" ? current.meta : {};
3439
- const cmBase = metaBase._cm && typeof metaBase._cm === "object" ? metaBase._cm : {};
3440
- const originIndex = typeof cmBase.originIndex === "number" ? cmBase.originIndex : void 0;
3441
- const result = await this.workflows.runById({
3442
- workflowId: ctx.config.workflowId,
3443
- startAt: ctx.config.startAt,
3444
- items: [current],
3445
- parent: {
3446
- runId: ctx.runId,
3447
- workflowId: ctx.workflowId,
3448
- nodeId: ctx.nodeId,
3449
- subworkflowDepth: ctx.subworkflowDepth,
3450
- engineMaxNodeActivations: ctx.engineMaxNodeActivations,
3451
- engineMaxSubworkflowDepth: ctx.engineMaxSubworkflowDepth
3452
- }
3527
+ for (const produced of result.outputs) {
3528
+ const childMetaBase = produced.meta && typeof produced.meta === "object" ? produced.meta : {};
3529
+ const childCmBase = childMetaBase._cm && typeof childMetaBase._cm === "object" ? childMetaBase._cm : {};
3530
+ out.push({
3531
+ ...produced,
3532
+ meta: originIndex === void 0 ? childMetaBase : {
3533
+ ...childMetaBase,
3534
+ _cm: {
3535
+ ...childCmBase,
3536
+ originIndex
3537
+ }
3538
+ },
3539
+ paired: current.paired ?? produced.paired
3453
3540
  });
3454
- if (result.status !== "completed") throw new Error(`Subworkflow ${ctx.config.workflowId} did not complete (status=${result.status})`);
3455
- for (const produced of result.outputs) {
3456
- const childMetaBase = produced.meta && typeof produced.meta === "object" ? produced.meta : {};
3457
- const childCmBase = childMetaBase._cm && typeof childMetaBase._cm === "object" ? childMetaBase._cm : {};
3458
- out.push({
3459
- ...produced,
3460
- meta: originIndex === void 0 ? childMetaBase : {
3461
- ...childMetaBase,
3462
- _cm: {
3463
- ...childCmBase,
3464
- originIndex
3465
- }
3466
- },
3467
- paired: current.paired ?? produced.paired
3468
- });
3469
- }
3470
3541
  }
3471
- return { main: out };
3542
+ return (0, __codemation_core.emitPorts)({ main: out });
3472
3543
  }
3473
3544
  };
3474
3545
  SubWorkflowNode = __decorate([
@@ -3504,12 +3575,14 @@ var WaitDuration = class {
3504
3575
  let WaitNode = class WaitNode$1 {
3505
3576
  kind = "node";
3506
3577
  outputPorts = ["main"];
3507
- async execute(items, ctx) {
3508
- const milliseconds = WaitDuration.normalize(ctx.config.milliseconds);
3509
- if (milliseconds > 0) await new Promise((resolve) => {
3510
- setTimeout(resolve, milliseconds);
3511
- });
3512
- return { main: items };
3578
+ async execute(args) {
3579
+ if (args.itemIndex === 0) {
3580
+ const milliseconds = WaitDuration.normalize(args.ctx.config.milliseconds);
3581
+ if (milliseconds > 0) await new Promise((resolve) => {
3582
+ setTimeout(resolve, milliseconds);
3583
+ });
3584
+ }
3585
+ return args.item;
3513
3586
  }
3514
3587
  };
3515
3588
  WaitNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" })], WaitNode);
@@ -3602,8 +3675,8 @@ var WebhookTrigger = class WebhookTrigger {
3602
3675
  let ConnectionCredentialNode = class ConnectionCredentialNode$1 {
3603
3676
  kind = "node";
3604
3677
  outputPorts = ["main"];
3605
- async execute(_items, _ctx) {
3606
- return { main: [] };
3678
+ execute(_args) {
3679
+ return [];
3607
3680
  }
3608
3681
  };
3609
3682
  ConnectionCredentialNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" })], ConnectionCredentialNode);
@@ -3620,10 +3693,7 @@ function registerCoreNodes(container) {}
3620
3693
  //#endregion
3621
3694
  //#region src/workflowBuilder.types.ts
3622
3695
  function createWorkflowBuilder(meta$2) {
3623
- return new __codemation_core.WorkflowBuilder(meta$2, { makeMergeNode: (name) => new Merge(name, {
3624
- mode: "passThrough",
3625
- prefer: ["true", "false"]
3626
- }) });
3696
+ return new __codemation_core.WorkflowBuilder(meta$2);
3627
3697
  }
3628
3698
 
3629
3699
  //#endregion
@@ -3705,6 +3775,21 @@ var WorkflowBranchBuilder = class WorkflowBranchBuilder {
3705
3775
  const duration = durationOrUndefined ?? nameOrDuration;
3706
3776
  return this.then(new Wait(name, WorkflowDurationParser.parse(duration), id));
3707
3777
  }
3778
+ split(nameOrGetter, getElementsOrUndefined, id) {
3779
+ const name = typeof nameOrGetter === "string" ? nameOrGetter : "Split";
3780
+ const getElements = typeof nameOrGetter === "string" ? getElementsOrUndefined : nameOrGetter;
3781
+ return this.then(new Split(name, getElements, id));
3782
+ }
3783
+ filter(nameOrPredicate, predicateOrUndefined, id) {
3784
+ const name = typeof nameOrPredicate === "string" ? nameOrPredicate : "Filter";
3785
+ const predicate = typeof nameOrPredicate === "string" ? predicateOrUndefined : nameOrPredicate;
3786
+ return this.then(new Filter(name, predicate, id));
3787
+ }
3788
+ aggregate(nameOrFn, aggregateFnOrUndefined, id) {
3789
+ const name = typeof nameOrFn === "string" ? nameOrFn : "Aggregate";
3790
+ const aggregateFn = typeof nameOrFn === "string" ? aggregateFnOrUndefined : nameOrFn;
3791
+ return this.then(new Aggregate(name, aggregateFn, id));
3792
+ }
3708
3793
  agent(nameOrOptions, optionsOrUndefined) {
3709
3794
  return this.then(WorkflowAgentNodeFactory.create(nameOrOptions, optionsOrUndefined));
3710
3795
  }
@@ -3736,6 +3821,27 @@ var WorkflowChain = class WorkflowChain {
3736
3821
  const duration = durationOrUndefined ?? nameOrDuration;
3737
3822
  return this.then(new Wait(name, WorkflowDurationParser.parse(duration), id));
3738
3823
  }
3824
+ split(nameOrGetter, getElementsOrUndefined, id) {
3825
+ const name = typeof nameOrGetter === "string" ? nameOrGetter : "Split";
3826
+ const getElements = typeof nameOrGetter === "string" ? getElementsOrUndefined : nameOrGetter;
3827
+ return this.then(new Split(name, getElements, id));
3828
+ }
3829
+ filter(nameOrPredicate, predicateOrUndefined, id) {
3830
+ const name = typeof nameOrPredicate === "string" ? nameOrPredicate : "Filter";
3831
+ const predicate = typeof nameOrPredicate === "string" ? predicateOrUndefined : nameOrPredicate;
3832
+ return this.then(new Filter(name, predicate, id));
3833
+ }
3834
+ aggregate(nameOrFn, aggregateFnOrUndefined, id) {
3835
+ const name = typeof nameOrFn === "string" ? nameOrFn : "Aggregate";
3836
+ const aggregateFn = typeof nameOrFn === "string" ? aggregateFnOrUndefined : nameOrFn;
3837
+ return this.then(new Aggregate(name, aggregateFn, id));
3838
+ }
3839
+ merge(nameOrCfg, cfgOrId, id) {
3840
+ const name = typeof nameOrCfg === "string" ? nameOrCfg : "Merge";
3841
+ const cfg = typeof nameOrCfg === "string" ? (typeof cfgOrId === "string" ? void 0 : cfgOrId) ?? { mode: "passThrough" } : nameOrCfg ?? { mode: "passThrough" };
3842
+ const mergeId = typeof cfgOrId === "string" ? cfgOrId : id;
3843
+ return new WorkflowChain(this.chain.thenIntoInputHints(new Merge(name, cfg, mergeId)));
3844
+ }
3739
3845
  if(nameOrPredicate, predicateOrBranches, branchesOrUndefined) {
3740
3846
  const name = typeof nameOrPredicate === "string" ? nameOrPredicate : "If";
3741
3847
  const predicate = typeof nameOrPredicate === "string" ? predicateOrBranches : nameOrPredicate;
@@ -3748,6 +3854,19 @@ var WorkflowChain = class WorkflowChain {
3748
3854
  false: falseSteps
3749
3855
  }));
3750
3856
  }
3857
+ route(branches) {
3858
+ const mappedBranches = Object.fromEntries(Object.entries(branches).map(([port, branchFactory]) => [port, branchFactory ? (branch) => branchFactory(new WorkflowChain(branch)).chain : void 0]));
3859
+ return new WorkflowChain(this.chain.route(mappedBranches));
3860
+ }
3861
+ switch(nameOrCfg, cfgOrUndefined, id) {
3862
+ const name = typeof nameOrCfg === "string" ? nameOrCfg : "Switch";
3863
+ const cfg = typeof nameOrCfg === "string" ? cfgOrUndefined : nameOrCfg;
3864
+ return this.then(new Switch(name, {
3865
+ cases: cfg.cases,
3866
+ defaultCase: cfg.defaultCase,
3867
+ resolveCaseKey: (item) => cfg.resolveCaseKey(item.json)
3868
+ }, id)).route(cfg.branches);
3869
+ }
3751
3870
  agent(nameOrOptions, optionsOrUndefined) {
3752
3871
  return this.then(WorkflowAgentNodeFactory.create(nameOrOptions, optionsOrUndefined));
3753
3872
  }
@@ -3800,9 +3919,9 @@ var AIAgentConnectionWorkflowExpander = class {
3800
3919
  const connectionsByParentAndName = this.createConnectionsByParentAndName(workflow$1);
3801
3920
  const extraNodes = [];
3802
3921
  let connectionsChanged = false;
3803
- for (const node$15 of workflow$1.nodes) {
3804
- if (node$15.type !== AIAgentNode || !__codemation_core.AgentConfigInspector.isAgentNodeConfig(node$15.config)) continue;
3805
- for (const connectionNode of __codemation_core.AgentConnectionNodeCollector.collect(node$15.id, node$15.config)) {
3922
+ for (const node$16 of workflow$1.nodes) {
3923
+ if (node$16.type !== AIAgentNode || !__codemation_core.AgentConfigInspector.isAgentNodeConfig(node$16.config)) continue;
3924
+ for (const connectionNode of __codemation_core.AgentConnectionNodeCollector.collect(node$16.id, node$16.config)) {
3806
3925
  if (!existingChildIds.has(connectionNode.nodeId)) {
3807
3926
  this.assertNoIdCollision(workflow$1, extraNodes, existingChildIds, connectionNode.nodeId);
3808
3927
  extraNodes.push({
@@ -3995,6 +4114,13 @@ Object.defineProperty(exports, 'SubWorkflowNode', {
3995
4114
  return SubWorkflowNode;
3996
4115
  }
3997
4116
  });
4117
+ exports.Switch = Switch;
4118
+ Object.defineProperty(exports, 'SwitchNode', {
4119
+ enumerable: true,
4120
+ get: function () {
4121
+ return SwitchNode;
4122
+ }
4123
+ });
3998
4124
  exports.Wait = Wait;
3999
4125
  exports.WaitDuration = WaitDuration;
4000
4126
  Object.defineProperty(exports, 'WaitNode', {