@codemation/core-nodes 0.1.1 → 0.2.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.
@@ -10,7 +10,14 @@ import type {
10
10
  ToolExecuteArgs,
11
11
  ZodSchemaAny,
12
12
  } from "@codemation/core";
13
- import { CoreTokens, inject, injectable, ItemValueResolver, NodeOutputNormalizer } from "@codemation/core";
13
+ import {
14
+ CoreTokens,
15
+ inject,
16
+ injectable,
17
+ ItemValueResolver,
18
+ NodeOutputNormalizer,
19
+ RunnableOutputBehaviorResolver,
20
+ } from "@codemation/core";
14
21
  import { z } from "zod";
15
22
 
16
23
  @injectable()
@@ -22,6 +29,8 @@ export class NodeBackedToolRuntime {
22
29
  private readonly itemValueResolver: ItemValueResolver,
23
30
  @inject(NodeOutputNormalizer)
24
31
  private readonly outputNormalizer: NodeOutputNormalizer,
32
+ @inject(RunnableOutputBehaviorResolver)
33
+ private readonly outputBehaviorResolver: RunnableOutputBehaviorResolver,
25
34
  ) {}
26
35
 
27
36
  async execute(
@@ -64,7 +73,7 @@ export class NodeBackedToolRuntime {
64
73
  if (this.isRunnableNode(resolvedNode)) {
65
74
  const runnable = resolvedNode;
66
75
  const runnableConfig = ctx.config;
67
- const carry = runnableConfig.lineageCarry ?? "emitOnly";
76
+ const behavior = this.outputBehaviorResolver.resolve(runnableConfig);
68
77
  const inputSchema = runnable.inputSchema ?? runnableConfig.inputSchema ?? z.unknown();
69
78
  const parsed = inputSchema.parse(nodeInput.json);
70
79
  const items = [nodeInput];
@@ -80,7 +89,7 @@ export class NodeBackedToolRuntime {
80
89
  return this.outputNormalizer.normalizeExecuteResult({
81
90
  baseItem: nodeInput,
82
91
  raw,
83
- carry,
92
+ behavior,
84
93
  });
85
94
  }
86
95
  throw new Error(`Node-backed tool expected a runnable node instance for "${ctx.config.name ?? ctx.nodeId}".`);
@@ -1,5 +1,7 @@
1
1
  export { AgentMessageFactory } from "./AgentMessageFactory";
2
2
  export { AgentOutputFactory } from "./AgentOutputFactory";
3
+ export { AgentStructuredOutputRepairPromptFactory } from "./AgentStructuredOutputRepairPromptFactory";
4
+ export { AgentStructuredOutputRunner } from "./AgentStructuredOutputRunner";
3
5
  export { AgentToolCallPortMap } from "./AgentToolCallPortMapFactory";
4
6
  export { AIAgent } from "./AIAgentConfig";
5
7
  export { AIAgentExecutionHelpersFactory } from "./AIAgentExecutionHelpersFactory";
@@ -2,6 +2,11 @@ import type { Item, NodeExecutionContext, RunnableNodeConfig, TypeToken } from "
2
2
 
3
3
  import { MapDataNode } from "./MapDataNode";
4
4
 
5
+ export interface MapDataOptions {
6
+ readonly id?: string;
7
+ readonly keepBinaries?: boolean;
8
+ }
9
+
5
10
  export class MapData<TInputJson = unknown, TOutputJson = unknown> implements RunnableNodeConfig<
6
11
  TInputJson,
7
12
  TOutputJson
@@ -11,14 +16,22 @@ export class MapData<TInputJson = unknown, TOutputJson = unknown> implements Run
11
16
  readonly execution = { hint: "local" } as const;
12
17
  /** Zero mapped items should still allow downstream nodes to run. */
13
18
  readonly continueWhenEmptyOutput = true as const;
19
+ readonly keepBinaries: boolean;
20
+
14
21
  constructor(
15
22
  public readonly name: string,
16
23
  public readonly map: (
17
24
  item: Item<TInputJson>,
18
25
  ctx: NodeExecutionContext<MapData<TInputJson, TOutputJson>>,
19
26
  ) => TOutputJson,
20
- public readonly id?: string,
21
- ) {}
27
+ private readonly options: MapDataOptions = {},
28
+ ) {
29
+ this.keepBinaries = options.keepBinaries ?? true;
30
+ }
31
+
32
+ get id(): string | undefined {
33
+ return this.options.id;
34
+ }
22
35
  }
23
36
 
24
37
  export { MapDataNode } from "./MapDataNode";
@@ -14,7 +14,6 @@ export class Switch<TInputJson = unknown> implements RunnableNodeConfig<TInputJs
14
14
  readonly type: TypeToken<unknown> = SwitchNode;
15
15
  readonly execution = { hint: "local" } as const;
16
16
  readonly icon = "lucide:git-branch-plus" as const;
17
- readonly lineageCarry = "carryThrough" as const;
18
17
  readonly declaredOutputPorts: ReadonlyArray<string>;
19
18
 
20
19
  constructor(
@@ -10,22 +10,18 @@ export class WorkflowAgentNodeFactory {
10
10
  ): AIAgent<TCurrentJson, TOutputSchema extends z.ZodTypeAny ? z.output<TOutputSchema> : Record<string, unknown>> {
11
11
  const options = typeof nameOrOptions === "string" ? optionsOrUndefined! : nameOrOptions;
12
12
  const name = typeof nameOrOptions === "string" ? nameOrOptions : "AI agent";
13
- const prompt = options.prompt;
14
- const messages = [
15
- {
16
- role: "user" as const,
17
- content:
18
- typeof prompt === "function" ? ({ item }: { item: { json: TCurrentJson } }) => prompt(item.json) : prompt,
19
- },
20
- ] as const;
13
+ const outputSchema = options.outputSchema as
14
+ | z.ZodType<TOutputSchema extends z.ZodTypeAny ? z.output<TOutputSchema> : Record<string, unknown>>
15
+ | undefined;
21
16
  return new AIAgent<
22
17
  TCurrentJson,
23
18
  TOutputSchema extends z.ZodTypeAny ? z.output<TOutputSchema> : Record<string, unknown>
24
19
  >({
25
20
  name,
26
- messages,
21
+ messages: options.messages,
27
22
  chatModel: WorkflowChatModelFactory.create(options.model),
28
23
  tools: options.tools,
24
+ outputSchema,
29
25
  id: options.id,
30
26
  retryPolicy: options.retryPolicy,
31
27
  guardrails: options.guardrails,
@@ -1,10 +1,16 @@
1
- import type { AgentGuardrailConfig, ChatModelConfig, RunnableNodeConfig, ToolConfig } from "@codemation/core";
1
+ import type {
2
+ AgentGuardrailConfig,
3
+ AgentMessageConfig,
4
+ ChatModelConfig,
5
+ RunnableNodeConfig,
6
+ ToolConfig,
7
+ } from "@codemation/core";
2
8
  import { z } from "zod";
3
9
 
4
- export type WorkflowAgentPrompt<TCurrentJson> = string | ((item: TCurrentJson) => string);
10
+ export type WorkflowAgentMessages<TCurrentJson> = AgentMessageConfig<TCurrentJson>;
5
11
 
6
12
  export interface WorkflowAgentOptions<TCurrentJson, TOutputSchema extends z.ZodTypeAny | undefined = undefined> {
7
- readonly prompt: WorkflowAgentPrompt<TCurrentJson>;
13
+ readonly messages: WorkflowAgentMessages<TCurrentJson>;
8
14
  readonly model: string | ChatModelConfig;
9
15
  readonly tools?: ReadonlyArray<ToolConfig>;
10
16
  readonly outputSchema?: TOutputSchema;
@@ -10,6 +10,7 @@ import type {
10
10
  import { z } from "zod";
11
11
  import { Aggregate } from "../nodes/aggregate";
12
12
  import { Filter } from "../nodes/filter";
13
+ import type { MapDataOptions } from "../nodes/mapData";
13
14
  import { MapData } from "../nodes/mapData";
14
15
  import { Split } from "../nodes/split";
15
16
  import { Wait } from "../nodes/wait";
@@ -31,17 +32,17 @@ export class WorkflowBranchBuilder<TCurrentJson> {
31
32
  map<TNextJson>(
32
33
  name: string,
33
34
  mapper: (item: TCurrentJson) => TNextJson,
34
- id?: string,
35
+ options?: MapDataOptions,
35
36
  ): WorkflowBranchBuilder<TNextJson>;
36
37
  map<TNextJson>(
37
38
  nameOrMapper: string | ((item: TCurrentJson) => TNextJson),
38
39
  mapperOrUndefined?: (item: TCurrentJson) => TNextJson,
39
- id?: string,
40
+ options?: MapDataOptions,
40
41
  ): WorkflowBranchBuilder<TNextJson> {
41
42
  const name = typeof nameOrMapper === "string" ? nameOrMapper : "Map data";
42
43
  const mapper = typeof nameOrMapper === "string" ? mapperOrUndefined! : nameOrMapper;
43
44
  return this.then(
44
- new MapData<TCurrentJson, TNextJson>(name, (item) => mapper(item.json as TCurrentJson), id),
45
+ new MapData<TCurrentJson, TNextJson>(name, (item) => mapper(item.json as TCurrentJson), options),
45
46
  ) as WorkflowBranchBuilder<TNextJson>;
46
47
  }
47
48
 
@@ -12,6 +12,7 @@ import { z } from "zod";
12
12
  import { Aggregate } from "../nodes/aggregate";
13
13
  import { Filter } from "../nodes/filter";
14
14
  import { If } from "../nodes/if";
15
+ import type { MapDataOptions } from "../nodes/mapData";
15
16
  import { MapData } from "../nodes/mapData";
16
17
  import { Merge, type MergeMode } from "../nodes/merge";
17
18
  import { Split } from "../nodes/split";
@@ -39,16 +40,20 @@ export class WorkflowChain<TCurrentJson> {
39
40
  }
40
41
 
41
42
  map<TNextJson>(mapper: (item: TCurrentJson) => TNextJson): WorkflowChain<TNextJson>;
42
- map<TNextJson>(name: string, mapper: (item: TCurrentJson) => TNextJson, id?: string): WorkflowChain<TNextJson>;
43
+ map<TNextJson>(
44
+ name: string,
45
+ mapper: (item: TCurrentJson) => TNextJson,
46
+ options?: MapDataOptions,
47
+ ): WorkflowChain<TNextJson>;
43
48
  map<TNextJson>(
44
49
  nameOrMapper: string | ((item: TCurrentJson) => TNextJson),
45
50
  mapperOrUndefined?: (item: TCurrentJson) => TNextJson,
46
- id?: string,
51
+ options?: MapDataOptions,
47
52
  ): WorkflowChain<TNextJson> {
48
53
  const name = typeof nameOrMapper === "string" ? nameOrMapper : "Map data";
49
54
  const mapper = typeof nameOrMapper === "string" ? mapperOrUndefined! : nameOrMapper;
50
55
  return this.then(
51
- new MapData<TCurrentJson, TNextJson>(name, (item) => mapper(item.json as TCurrentJson), id),
56
+ new MapData<TCurrentJson, TNextJson>(name, (item) => mapper(item.json as TCurrentJson), options),
52
57
  ) as WorkflowChain<TNextJson>;
53
58
  }
54
59
 
@@ -1,4 +1,4 @@
1
- export type { WorkflowAgentOptions } from "./workflowAuthoring/WorkflowAuthoringOptions.types";
1
+ export type { WorkflowAgentMessages, WorkflowAgentOptions } from "./workflowAuthoring/WorkflowAuthoringOptions.types";
2
2
  export { WorkflowAuthoringBuilder } from "./workflowAuthoring/WorkflowAuthoringBuilder.types";
3
3
  export { WorkflowBranchBuilder } from "./workflowAuthoring/WorkflowBranchBuilder.types";
4
4
  export { WorkflowChain } from "./workflowAuthoring/WorkflowChain.types";