@codemation/core-nodes 0.2.0 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemation/core-nodes",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
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.6.0"
34
+ "@codemation/core": "0.7.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "^25.3.5",
@@ -68,7 +68,7 @@ export class AIAgentNode implements RunnableNode<AIAgent<any, any>> {
68
68
  outputPorts = ["main"] as const;
69
69
  /**
70
70
  * Engine validates {@link RunnableNodeConfig.inputSchema} (Zod) on {@code item.json} before enqueue, then resolves
71
- * per-item **`itemValue`** leaves on config before {@link #execute}. Prefer modeling prompts as
71
+ * per-item **`itemExpr`** leaves on config before {@link #execute}. Prefer modeling prompts as
72
72
  * {@code { messages: [{ role, content }, ...] }} (on input or config) so persisted inputs are visible in the UI.
73
73
  */
74
74
  readonly inputSchema = z.unknown();
@@ -14,7 +14,7 @@ import {
14
14
  CoreTokens,
15
15
  inject,
16
16
  injectable,
17
- ItemValueResolver,
17
+ ItemExprResolver,
18
18
  NodeOutputNormalizer,
19
19
  RunnableOutputBehaviorResolver,
20
20
  } from "@codemation/core";
@@ -25,8 +25,8 @@ export class NodeBackedToolRuntime {
25
25
  constructor(
26
26
  @inject(CoreTokens.NodeResolver)
27
27
  private readonly nodeResolver: NodeResolver,
28
- @inject(ItemValueResolver)
29
- private readonly itemValueResolver: ItemValueResolver,
28
+ @inject(ItemExprResolver)
29
+ private readonly itemExprResolver: ItemExprResolver,
30
30
  @inject(NodeOutputNormalizer)
31
31
  private readonly outputNormalizer: NodeOutputNormalizer,
32
32
  @inject(RunnableOutputBehaviorResolver)
@@ -77,7 +77,7 @@ export class NodeBackedToolRuntime {
77
77
  const inputSchema = runnable.inputSchema ?? runnableConfig.inputSchema ?? z.unknown();
78
78
  const parsed = inputSchema.parse(nodeInput.json);
79
79
  const items = [nodeInput];
80
- const resolvedCtx = await this.itemValueResolver.resolveConfigForItem(ctx, nodeInput, 0, items);
80
+ const resolvedCtx = await this.itemExprResolver.resolveConfigForItem(ctx, nodeInput, 0, items);
81
81
  const execArgs: RunnableNodeExecuteArgs = {
82
82
  input: parsed,
83
83
  item: nodeInput,
@@ -1,6 +1,8 @@
1
1
  import type {
2
2
  AnyRunnableNodeConfig,
3
+ CredentialJsonRecord,
3
4
  DefinedNode,
5
+ DefinedNodeConfigInput,
4
6
  Item,
5
7
  Items,
6
8
  NodeExecutionContext,
@@ -19,6 +21,11 @@ import { WorkflowAgentNodeFactory } from "./WorkflowAgentNodeFactory.types";
19
21
  import { WorkflowDefinedNodeResolver } from "./WorkflowDefinedNodeResolver.types";
20
22
  import { WorkflowDurationParser } from "./WorkflowDurationParser.types";
21
23
 
24
+ type WorkflowMapCallback<TCurrentJson, TNextJson> = (
25
+ item: Item<TCurrentJson>,
26
+ ctx: NodeExecutionContext<MapData<TCurrentJson, TNextJson>>,
27
+ ) => TNextJson;
28
+
22
29
  export class WorkflowBranchBuilder<TCurrentJson> {
23
30
  constructor(private readonly steps: ReadonlyArray<AnyRunnableNodeConfig> = []) {}
24
31
 
@@ -28,22 +35,20 @@ export class WorkflowBranchBuilder<TCurrentJson> {
28
35
  return new WorkflowBranchBuilder<RunnableNodeOutputJson<TConfig>>([...this.steps, config]);
29
36
  }
30
37
 
31
- map<TNextJson>(mapper: (item: TCurrentJson) => TNextJson): WorkflowBranchBuilder<TNextJson>;
38
+ map<TNextJson>(mapper: WorkflowMapCallback<TCurrentJson, TNextJson>): WorkflowBranchBuilder<TNextJson>;
32
39
  map<TNextJson>(
33
40
  name: string,
34
- mapper: (item: TCurrentJson) => TNextJson,
41
+ mapper: WorkflowMapCallback<TCurrentJson, TNextJson>,
35
42
  options?: MapDataOptions,
36
43
  ): WorkflowBranchBuilder<TNextJson>;
37
44
  map<TNextJson>(
38
- nameOrMapper: string | ((item: TCurrentJson) => TNextJson),
39
- mapperOrUndefined?: (item: TCurrentJson) => TNextJson,
45
+ nameOrMapper: string | WorkflowMapCallback<TCurrentJson, TNextJson>,
46
+ mapperOrUndefined?: WorkflowMapCallback<TCurrentJson, TNextJson>,
40
47
  options?: MapDataOptions,
41
48
  ): WorkflowBranchBuilder<TNextJson> {
42
49
  const name = typeof nameOrMapper === "string" ? nameOrMapper : "Map data";
43
50
  const mapper = typeof nameOrMapper === "string" ? mapperOrUndefined! : nameOrMapper;
44
- return this.then(
45
- new MapData<TCurrentJson, TNextJson>(name, (item) => mapper(item.json as TCurrentJson), options),
46
- ) as WorkflowBranchBuilder<TNextJson>;
51
+ return this.then(new MapData<TCurrentJson, TNextJson>(name, mapper, options)) as WorkflowBranchBuilder<TNextJson>;
47
52
  }
48
53
 
49
54
  wait(duration: number | string): WorkflowBranchBuilder<TCurrentJson>;
@@ -172,18 +177,18 @@ export class WorkflowBranchBuilder<TCurrentJson> {
172
177
  >;
173
178
  }
174
179
 
175
- node<TConfig extends Record<string, unknown>, TOutputJson>(
176
- definitionOrKey: DefinedNode<string, TConfig, TCurrentJson, TOutputJson> | string,
177
- config: TConfig,
180
+ node<TConfig extends CredentialJsonRecord, TInputJson, TOutputJson>(
181
+ definitionOrKey: DefinedNode<string, TConfig, TInputJson, TOutputJson> | string,
182
+ config: DefinedNodeConfigInput<TConfig, TCurrentJson>,
178
183
  name?: string,
179
184
  id?: string,
180
- ): WorkflowBranchBuilder<TOutputJson> {
185
+ ): TCurrentJson extends TInputJson ? WorkflowBranchBuilder<TOutputJson> : never {
181
186
  const definition = WorkflowDefinedNodeResolver.resolve(
182
187
  definitionOrKey as DefinedNode<string, Record<string, unknown>, unknown, unknown> | string,
183
- ) as DefinedNode<string, TConfig, TCurrentJson, TOutputJson>;
188
+ ) as DefinedNode<string, TConfig, TInputJson, TOutputJson>;
184
189
  return this.then(
185
- definition.create(config, name, id) as RunnableNodeConfig<TCurrentJson, TOutputJson>,
186
- ) as WorkflowBranchBuilder<TOutputJson>;
190
+ definition.create(config, name, id) as unknown as RunnableNodeConfig<TCurrentJson, TOutputJson>,
191
+ ) as TCurrentJson extends TInputJson ? WorkflowBranchBuilder<TOutputJson> : never;
187
192
  }
188
193
 
189
194
  getSteps(): ReadonlyArray<AnyRunnableNodeConfig> {
@@ -1,5 +1,7 @@
1
1
  import type {
2
+ CredentialJsonRecord,
2
3
  DefinedNode,
4
+ DefinedNodeConfigInput,
3
5
  Item,
4
6
  Items,
5
7
  NodeExecutionContext,
@@ -29,6 +31,18 @@ type BranchCallback<TCurrentJson, TNextJson> = (
29
31
  ) => WorkflowBranchBuilder<TNextJson>;
30
32
  type RouteBranchCallback<TCurrentJson, TNextJson> = (branch: WorkflowChain<TCurrentJson>) => WorkflowChain<TNextJson>;
31
33
  type BranchOutputMatch<TLeft, TRight> = [TLeft] extends [TRight] ? ([TRight] extends [TLeft] ? true : false) : false;
34
+ type WorkflowMapCallback<TCurrentJson, TNextJson> = (
35
+ item: Item<TCurrentJson>,
36
+ ctx: NodeExecutionContext<MapData<TCurrentJson, TNextJson>>,
37
+ ) => TNextJson;
38
+ type WorkflowIfPredicate<TCurrentJson> = (
39
+ item: Item<TCurrentJson>,
40
+ ctx: NodeExecutionContext<If<TCurrentJson>>,
41
+ ) => boolean;
42
+ type WorkflowSwitchCaseKeyResolver<TCurrentJson> = (
43
+ item: Item<TCurrentJson>,
44
+ ctx: NodeExecutionContext<Switch<TCurrentJson>>,
45
+ ) => string | Promise<string>;
32
46
 
33
47
  export class WorkflowChain<TCurrentJson> {
34
48
  constructor(private readonly chain: ChainCursor<TCurrentJson>) {}
@@ -39,22 +53,20 @@ export class WorkflowChain<TCurrentJson> {
39
53
  return new WorkflowChain(this.chain.then(config));
40
54
  }
41
55
 
42
- map<TNextJson>(mapper: (item: TCurrentJson) => TNextJson): WorkflowChain<TNextJson>;
56
+ map<TNextJson>(mapper: WorkflowMapCallback<TCurrentJson, TNextJson>): WorkflowChain<TNextJson>;
43
57
  map<TNextJson>(
44
58
  name: string,
45
- mapper: (item: TCurrentJson) => TNextJson,
59
+ mapper: WorkflowMapCallback<TCurrentJson, TNextJson>,
46
60
  options?: MapDataOptions,
47
61
  ): WorkflowChain<TNextJson>;
48
62
  map<TNextJson>(
49
- nameOrMapper: string | ((item: TCurrentJson) => TNextJson),
50
- mapperOrUndefined?: (item: TCurrentJson) => TNextJson,
63
+ nameOrMapper: string | WorkflowMapCallback<TCurrentJson, TNextJson>,
64
+ mapperOrUndefined?: WorkflowMapCallback<TCurrentJson, TNextJson>,
51
65
  options?: MapDataOptions,
52
66
  ): WorkflowChain<TNextJson> {
53
67
  const name = typeof nameOrMapper === "string" ? nameOrMapper : "Map data";
54
68
  const mapper = typeof nameOrMapper === "string" ? mapperOrUndefined! : nameOrMapper;
55
- return this.then(
56
- new MapData<TCurrentJson, TNextJson>(name, (item) => mapper(item.json as TCurrentJson), options),
57
- ) as WorkflowChain<TNextJson>;
69
+ return this.then(new MapData<TCurrentJson, TNextJson>(name, mapper, options)) as WorkflowChain<TNextJson>;
58
70
  }
59
71
 
60
72
  wait(duration: number | string): WorkflowChain<TCurrentJson>;
@@ -190,7 +202,7 @@ export class WorkflowChain<TCurrentJson> {
190
202
  }
191
203
 
192
204
  if<TBranchJson>(
193
- predicate: (item: TCurrentJson) => boolean,
205
+ predicate: WorkflowIfPredicate<TCurrentJson>,
194
206
  branches: Readonly<{
195
207
  true?: BranchCallback<TCurrentJson, TBranchJson>;
196
208
  false?: BranchCallback<TCurrentJson, TBranchJson>;
@@ -198,16 +210,16 @@ export class WorkflowChain<TCurrentJson> {
198
210
  ): WorkflowChain<TBranchJson>;
199
211
  if<TBranchJson>(
200
212
  name: string,
201
- predicate: (item: TCurrentJson) => boolean,
213
+ predicate: WorkflowIfPredicate<TCurrentJson>,
202
214
  branches: Readonly<{
203
215
  true?: BranchCallback<TCurrentJson, TBranchJson>;
204
216
  false?: BranchCallback<TCurrentJson, TBranchJson>;
205
217
  }>,
206
218
  ): WorkflowChain<TBranchJson>;
207
219
  if<TTrueJson, TFalseJson>(
208
- nameOrPredicate: string | ((item: TCurrentJson) => boolean),
220
+ nameOrPredicate: string | WorkflowIfPredicate<TCurrentJson>,
209
221
  predicateOrBranches:
210
- | ((item: TCurrentJson) => boolean)
222
+ | WorkflowIfPredicate<TCurrentJson>
211
223
  | Readonly<{ true?: BranchCallback<TCurrentJson, TTrueJson>; false?: BranchCallback<TCurrentJson, TFalseJson> }>,
212
224
  branchesOrUndefined?: Readonly<{
213
225
  true?: BranchCallback<TCurrentJson, TTrueJson>;
@@ -216,12 +228,14 @@ export class WorkflowChain<TCurrentJson> {
216
228
  ): WorkflowChain<BranchOutputMatch<TTrueJson, TFalseJson> extends true ? TTrueJson : never> {
217
229
  const name = typeof nameOrPredicate === "string" ? nameOrPredicate : "If";
218
230
  const predicate =
219
- typeof nameOrPredicate === "string" ? (predicateOrBranches as (item: TCurrentJson) => boolean) : nameOrPredicate;
231
+ typeof nameOrPredicate === "string"
232
+ ? (predicateOrBranches as WorkflowIfPredicate<TCurrentJson>)
233
+ : nameOrPredicate;
220
234
  const branches = (typeof nameOrPredicate === "string" ? branchesOrUndefined : predicateOrBranches) as Readonly<{
221
235
  true?: BranchCallback<TCurrentJson, TTrueJson>;
222
236
  false?: BranchCallback<TCurrentJson, TFalseJson>;
223
237
  }>;
224
- const cursor = this.chain.then(new If<TCurrentJson>(name, (item) => predicate(item.json as TCurrentJson)));
238
+ const cursor = this.chain.then(new If<TCurrentJson>(name, (item, _index, _items, ctx) => predicate(item, ctx)));
225
239
  const trueSteps = branches.true?.(new WorkflowBranchBuilder<TCurrentJson>()).getSteps();
226
240
  const falseSteps = branches.false?.(new WorkflowBranchBuilder<TCurrentJson>()).getSteps();
227
241
  return new WorkflowChain(
@@ -258,7 +272,7 @@ export class WorkflowChain<TCurrentJson> {
258
272
  cfg: Readonly<{
259
273
  cases: readonly string[];
260
274
  defaultCase: string;
261
- resolveCaseKey: (item: TCurrentJson) => string | Promise<string>;
275
+ resolveCaseKey: WorkflowSwitchCaseKeyResolver<TCurrentJson>;
262
276
  branches: Readonly<Record<string, RouteBranchCallback<TCurrentJson, TBranchJson> | undefined>>;
263
277
  }>,
264
278
  ): WorkflowChain<TBranchJson>;
@@ -267,7 +281,7 @@ export class WorkflowChain<TCurrentJson> {
267
281
  cfg: Readonly<{
268
282
  cases: readonly string[];
269
283
  defaultCase: string;
270
- resolveCaseKey: (item: TCurrentJson) => string | Promise<string>;
284
+ resolveCaseKey: WorkflowSwitchCaseKeyResolver<TCurrentJson>;
271
285
  branches: Readonly<Record<string, RouteBranchCallback<TCurrentJson, TBranchJson> | undefined>>;
272
286
  }>,
273
287
  id?: string,
@@ -278,13 +292,13 @@ export class WorkflowChain<TCurrentJson> {
278
292
  | Readonly<{
279
293
  cases: readonly string[];
280
294
  defaultCase: string;
281
- resolveCaseKey: (item: TCurrentJson) => string | Promise<string>;
295
+ resolveCaseKey: WorkflowSwitchCaseKeyResolver<TCurrentJson>;
282
296
  branches: Readonly<Record<string, RouteBranchCallback<TCurrentJson, TBranchJson> | undefined>>;
283
297
  }>,
284
298
  cfgOrUndefined?: Readonly<{
285
299
  cases: readonly string[];
286
300
  defaultCase: string;
287
- resolveCaseKey: (item: TCurrentJson) => string | Promise<string>;
301
+ resolveCaseKey: WorkflowSwitchCaseKeyResolver<TCurrentJson>;
288
302
  branches: Readonly<Record<string, RouteBranchCallback<TCurrentJson, TBranchJson> | undefined>>;
289
303
  }>,
290
304
  id?: string,
@@ -297,7 +311,7 @@ export class WorkflowChain<TCurrentJson> {
297
311
  {
298
312
  cases: cfg.cases,
299
313
  defaultCase: cfg.defaultCase,
300
- resolveCaseKey: (item) => cfg.resolveCaseKey(item.json as TCurrentJson),
314
+ resolveCaseKey: (item, _index, _items, ctx) => cfg.resolveCaseKey(item, ctx),
301
315
  },
302
316
  id,
303
317
  ),
@@ -322,18 +336,18 @@ export class WorkflowChain<TCurrentJson> {
322
336
  >;
323
337
  }
324
338
 
325
- node<TConfig extends Record<string, unknown>, TOutputJson>(
326
- definitionOrKey: DefinedNode<string, TConfig, TCurrentJson, TOutputJson> | string,
327
- config: TConfig,
339
+ node<TConfig extends CredentialJsonRecord, TInputJson, TOutputJson>(
340
+ definitionOrKey: DefinedNode<string, TConfig, TInputJson, TOutputJson> | string,
341
+ config: DefinedNodeConfigInput<TConfig, TCurrentJson>,
328
342
  name?: string,
329
343
  id?: string,
330
- ): WorkflowChain<TOutputJson> {
344
+ ): TCurrentJson extends TInputJson ? WorkflowChain<TOutputJson> : never {
331
345
  const definition = WorkflowDefinedNodeResolver.resolve(
332
346
  definitionOrKey as DefinedNode<string, Record<string, unknown>, unknown, unknown> | string,
333
- ) as DefinedNode<string, TConfig, TCurrentJson, TOutputJson>;
347
+ ) as DefinedNode<string, TConfig, TInputJson, TOutputJson>;
334
348
  return this.then(
335
- definition.create(config, name, id) as RunnableNodeConfig<TCurrentJson, TOutputJson>,
336
- ) as WorkflowChain<TOutputJson>;
349
+ definition.create(config, name, id) as unknown as RunnableNodeConfig<TCurrentJson, TOutputJson>,
350
+ ) as TCurrentJson extends TInputJson ? WorkflowChain<TOutputJson> : never;
337
351
  }
338
352
 
339
353
  build(): WorkflowDefinition {