@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.
package/dist/index.cjs CHANGED
@@ -60,6 +60,42 @@ let OpenAIChatModelFactory = class OpenAIChatModelFactory$1 {
60
60
  };
61
61
  OpenAIChatModelFactory = __decorate([(0, __codemation_core.chatModel)({ packageName: "@codemation/core-nodes" })], OpenAIChatModelFactory);
62
62
 
63
+ //#endregion
64
+ //#region src/chatModels/OpenAIStructuredOutputMethodFactory.ts
65
+ var _OpenAIStructuredOutputMethodFactory;
66
+ let OpenAIStructuredOutputMethodFactory = class OpenAIStructuredOutputMethodFactory$1 {
67
+ static {
68
+ _OpenAIStructuredOutputMethodFactory = this;
69
+ }
70
+ static isoDatePattern = /^\d{4}-\d{2}-\d{2}$/;
71
+ create(chatModelConfig) {
72
+ if (chatModelConfig.type !== OpenAIChatModelFactory) return;
73
+ const model = this.readModelName(chatModelConfig);
74
+ if (!model) return {
75
+ method: "functionCalling",
76
+ strict: true
77
+ };
78
+ return {
79
+ method: this.supportsJsonSchema(model) ? "jsonSchema" : "functionCalling",
80
+ strict: true
81
+ };
82
+ }
83
+ readModelName(chatModelConfig) {
84
+ const candidate = chatModelConfig;
85
+ return typeof candidate.model === "string" ? candidate.model : void 0;
86
+ }
87
+ supportsJsonSchema(model) {
88
+ if (model === "gpt-4o" || model === "gpt-4o-mini") return true;
89
+ return this.supportsSnapshotAtOrAfter(model, "gpt-4o-", "2024-08-06") || this.supportsSnapshotAtOrAfter(model, "gpt-4o-mini-", "2024-07-18");
90
+ }
91
+ supportsSnapshotAtOrAfter(model, prefix, minimumSnapshotDate) {
92
+ if (!model.startsWith(prefix)) return false;
93
+ const snapshotDate = model.slice(prefix.length);
94
+ return _OpenAIStructuredOutputMethodFactory.isoDatePattern.test(snapshotDate) && snapshotDate >= minimumSnapshotDate;
95
+ }
96
+ };
97
+ OpenAIStructuredOutputMethodFactory = _OpenAIStructuredOutputMethodFactory = __decorate([(0, __codemation_core.injectable)()], OpenAIStructuredOutputMethodFactory);
98
+
63
99
  //#endregion
64
100
  //#region src/chatModels/openAiChatModelConfig.ts
65
101
  var OpenAIChatModelConfig = class {
@@ -171,14 +207,6 @@ var AgentOutputFactory = class {
171
207
  }
172
208
  };
173
209
 
174
- //#endregion
175
- //#region src/nodes/AgentToolCallPortMapFactory.ts
176
- var AgentToolCallPortMap = class {
177
- static fromInput(input) {
178
- return { in: [{ json: input }] };
179
- }
180
- };
181
-
182
210
  //#endregion
183
211
  //#region ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/core.js
184
212
  /** A special constant with type `never` */
@@ -2070,6 +2098,168 @@ function toJSONSchema(input, params) {
2070
2098
  return finalize(ctx, input);
2071
2099
  }
2072
2100
 
2101
+ //#endregion
2102
+ //#region src/nodes/ConnectionCredentialExecutionContextFactory.ts
2103
+ /**
2104
+ * Builds a {@link NodeExecutionContext} whose identity for credential binding and `getCredential`
2105
+ * is a **connection-owned** workflow node id (`ConnectionNodeIdFactory` in `@codemation/core`),
2106
+ * not the executing parent node. Use for LLM slots, tool slots, or any connection-scoped owner.
2107
+ */
2108
+ var ConnectionCredentialExecutionContextFactory = class {
2109
+ credentialResolverFactory;
2110
+ constructor(credentialSessions) {
2111
+ this.credentialResolverFactory = new __codemation_core_bootstrap.CredentialResolverFactory(credentialSessions);
2112
+ }
2113
+ forConnectionNode(ctx, args) {
2114
+ const stubConfig = { getCredentialRequirements: args.getCredentialRequirements };
2115
+ const getCredential = this.credentialResolverFactory.create(ctx.workflowId, args.connectionNodeId, stubConfig);
2116
+ return {
2117
+ ...ctx,
2118
+ nodeId: args.connectionNodeId,
2119
+ getCredential
2120
+ };
2121
+ }
2122
+ };
2123
+
2124
+ //#endregion
2125
+ //#region src/nodes/AIAgentExecutionHelpersFactory.ts
2126
+ let AIAgentExecutionHelpersFactory = class AIAgentExecutionHelpersFactory$1 {
2127
+ createConnectionCredentialExecutionContextFactory(credentialSessions) {
2128
+ return new ConnectionCredentialExecutionContextFactory(credentialSessions);
2129
+ }
2130
+ createDynamicStructuredTool(entry, toolCredentialContext, item, itemIndex, items) {
2131
+ if (entry.runtime.inputSchema == null) throw new Error(`Cannot create LangChain tool "${entry.config.name}": missing inputSchema (broken tool runtime resolution).`);
2132
+ const schemaForOpenAi = this.createJsonSchemaRecord(entry.runtime.inputSchema, {
2133
+ schemaName: entry.config.name,
2134
+ requireObjectRoot: true
2135
+ });
2136
+ return new __langchain_core_tools.DynamicStructuredTool({
2137
+ name: entry.config.name,
2138
+ description: entry.config.description ?? entry.runtime.defaultDescription,
2139
+ schema: schemaForOpenAi,
2140
+ func: async (input) => {
2141
+ const result = await entry.runtime.execute({
2142
+ config: entry.config,
2143
+ input,
2144
+ ctx: toolCredentialContext,
2145
+ item,
2146
+ itemIndex,
2147
+ items
2148
+ });
2149
+ return JSON.stringify(result);
2150
+ }
2151
+ });
2152
+ }
2153
+ /**
2154
+ * Produces a plain JSON Schema object for OpenAI tool parameters and LangChain tool invocation:
2155
+ * - **Zod** → `toJSONSchema(..., { target: "draft-07" })` so shapes match what `@cfworker/json-schema`
2156
+ * expects (`required` must be an array; draft 2020-12 output can break validation).
2157
+ * - Otherwise LangChain `toJsonSchema` (Standard Schema + JSON passthrough); if the result is still Zod
2158
+ * (duplicate `zod` copies), fall back to Zod `toJSONSchema` with draft-07.
2159
+ * - Strip root `$schema` for OpenAI; normalize invalid `required` keywords for cfworker; ensure `properties`.
2160
+ */
2161
+ createJsonSchemaRecord(inputSchema, options) {
2162
+ const draft07Params = { target: "draft-07" };
2163
+ let converted;
2164
+ if ((0, __langchain_core_utils_types.isInteropZodSchema)(inputSchema)) converted = toJSONSchema(inputSchema, draft07Params);
2165
+ else {
2166
+ converted = (0, __langchain_core_utils_json_schema.toJsonSchema)(inputSchema);
2167
+ if ((0, __langchain_core_utils_types.isInteropZodSchema)(converted)) converted = toJSONSchema(inputSchema, draft07Params);
2168
+ }
2169
+ const { $schema: _draftSchemaOmitted,...rest } = converted;
2170
+ if (options.requireObjectRoot && rest.type !== "object") throw new Error(`Cannot create LangChain tool "${options.schemaName}": tool input schema must be a JSON Schema object type (got type=${String(rest.type)}).`);
2171
+ if (options.requireObjectRoot && rest.properties !== void 0 && (typeof rest.properties !== "object" || Array.isArray(rest.properties))) throw new Error(`Cannot create LangChain tool "${options.schemaName}": tool input schema "properties" must be an object (got ${JSON.stringify(rest.properties)}).`);
2172
+ if (options.requireObjectRoot && rest.properties === void 0) rest.properties = {};
2173
+ this.sanitizeJsonSchemaRequiredKeywordsForCfworker(rest);
2174
+ return rest;
2175
+ }
2176
+ /**
2177
+ * `@cfworker/json-schema` iterates `schema.required` with `for...of`; it must be a string array or absent.
2178
+ */
2179
+ sanitizeJsonSchemaRequiredKeywordsForCfworker(node$16) {
2180
+ if (!node$16 || typeof node$16 !== "object" || Array.isArray(node$16)) return;
2181
+ const o = node$16;
2182
+ const req = o.required;
2183
+ if (req !== void 0 && !Array.isArray(req)) delete o.required;
2184
+ else if (Array.isArray(req)) {
2185
+ const strings = req.filter((x) => typeof x === "string");
2186
+ if (strings.length === 0) delete o.required;
2187
+ else if (strings.length !== req.length) o.required = strings;
2188
+ }
2189
+ const props = o.properties;
2190
+ if (props && typeof props === "object" && !Array.isArray(props)) for (const v of Object.values(props)) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(v);
2191
+ for (const key of [
2192
+ "allOf",
2193
+ "anyOf",
2194
+ "oneOf"
2195
+ ]) {
2196
+ const branch = o[key];
2197
+ if (Array.isArray(branch)) for (const sub of branch) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(sub);
2198
+ }
2199
+ if (o.if) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.if);
2200
+ if (o.then) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.then);
2201
+ if (o.else) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.else);
2202
+ if (o.not) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.not);
2203
+ if (o.items) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.items);
2204
+ if (Array.isArray(o.prefixItems)) for (const sub of o.prefixItems) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(sub);
2205
+ }
2206
+ };
2207
+ AIAgentExecutionHelpersFactory = __decorate([(0, __codemation_core.injectable)()], AIAgentExecutionHelpersFactory);
2208
+
2209
+ //#endregion
2210
+ //#region \0@oxc-project+runtime@0.95.0/helpers/decorateMetadata.js
2211
+ function __decorateMetadata(k, v) {
2212
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2213
+ }
2214
+
2215
+ //#endregion
2216
+ //#region \0@oxc-project+runtime@0.95.0/helpers/decorateParam.js
2217
+ function __decorateParam(paramIndex, decorator) {
2218
+ return function(target, key) {
2219
+ decorator(target, key, paramIndex);
2220
+ };
2221
+ }
2222
+
2223
+ //#endregion
2224
+ //#region src/nodes/AgentStructuredOutputRepairPromptFactory.ts
2225
+ var _ref$3, _AgentStructuredOutputRepairPromptFactory;
2226
+ let AgentStructuredOutputRepairPromptFactory = class AgentStructuredOutputRepairPromptFactory$1 {
2227
+ static {
2228
+ _AgentStructuredOutputRepairPromptFactory = this;
2229
+ }
2230
+ static maxSchemaLength = 8e3;
2231
+ static maxInvalidContentLength = 4e3;
2232
+ static maxValidationErrorLength = 4e3;
2233
+ constructor(executionHelpers) {
2234
+ this.executionHelpers = executionHelpers;
2235
+ }
2236
+ create(args) {
2237
+ return [{
2238
+ role: "system",
2239
+ content: "Return only JSON that matches the required schema exactly. Do not include markdown fences, commentary, or prose."
2240
+ }, {
2241
+ role: "user",
2242
+ content: JSON.stringify({
2243
+ requiredSchema: this.truncate(JSON.stringify(this.executionHelpers.createJsonSchemaRecord(args.schema, {
2244
+ schemaName: "agent_output",
2245
+ requireObjectRoot: false
2246
+ })), _AgentStructuredOutputRepairPromptFactory.maxSchemaLength),
2247
+ invalidModelOutput: this.truncate(args.invalidContent, _AgentStructuredOutputRepairPromptFactory.maxInvalidContentLength),
2248
+ validationError: this.truncate(args.validationError, _AgentStructuredOutputRepairPromptFactory.maxValidationErrorLength)
2249
+ })
2250
+ }];
2251
+ }
2252
+ truncate(value, maxLength) {
2253
+ if (value.length <= maxLength) return value;
2254
+ return `${value.slice(0, maxLength)}...(truncated)`;
2255
+ }
2256
+ };
2257
+ AgentStructuredOutputRepairPromptFactory = _AgentStructuredOutputRepairPromptFactory = __decorate([
2258
+ (0, __codemation_core.injectable)(),
2259
+ __decorateParam(0, (0, __codemation_core.inject)(AIAgentExecutionHelpersFactory)),
2260
+ __decorateMetadata("design:paramtypes", [typeof (_ref$3 = typeof AIAgentExecutionHelpersFactory !== "undefined" && AIAgentExecutionHelpersFactory) === "function" ? _ref$3 : Object])
2261
+ ], AgentStructuredOutputRepairPromptFactory);
2262
+
2073
2263
  //#endregion
2074
2264
  //#region ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/errors.js
2075
2265
  const initializer = (inst, issues) => {
@@ -2401,132 +2591,140 @@ const describe = describe$1;
2401
2591
  const meta = meta$1;
2402
2592
 
2403
2593
  //#endregion
2404
- //#region src/nodes/ConnectionCredentialExecutionContextFactory.ts
2405
- /**
2406
- * Builds a {@link NodeExecutionContext} whose identity for credential binding and `getCredential`
2407
- * is a **connection-owned** workflow node id (`ConnectionNodeIdFactory` in `@codemation/core`),
2408
- * not the executing parent node. Use for LLM slots, tool slots, or any connection-scoped owner.
2409
- */
2410
- var ConnectionCredentialExecutionContextFactory = class {
2411
- credentialResolverFactory;
2412
- constructor(credentialSessions) {
2413
- this.credentialResolverFactory = new __codemation_core_bootstrap.CredentialResolverFactory(credentialSessions);
2594
+ //#region src/nodes/AgentStructuredOutputRunner.ts
2595
+ var _ref$2, _ref2$2, _AgentStructuredOutputRunner;
2596
+ let AgentStructuredOutputRunner = class AgentStructuredOutputRunner$1 {
2597
+ static {
2598
+ _AgentStructuredOutputRunner = this;
2599
+ }
2600
+ static repairAttemptCount = 2;
2601
+ constructor(repairPromptFactory, openAiStructuredOutputMethodFactory) {
2602
+ this.repairPromptFactory = repairPromptFactory;
2603
+ this.openAiStructuredOutputMethodFactory = openAiStructuredOutputMethodFactory;
2604
+ }
2605
+ async resolve(args) {
2606
+ let lastFailure;
2607
+ if (args.rawFinalResponse) {
2608
+ const directResult = this.tryParseAndValidate(AgentMessageFactory.extractContent(args.rawFinalResponse), args.schema);
2609
+ if (directResult.ok) return directResult.value;
2610
+ lastFailure = directResult;
2611
+ } else if (!this.supportsNativeStructuredOutput(args.model)) {
2612
+ const rawResponse = await args.invokeTextModel(args.conversation);
2613
+ const directResult = this.tryParseAndValidate(AgentMessageFactory.extractContent(rawResponse), args.schema);
2614
+ if (directResult.ok) return directResult.value;
2615
+ lastFailure = directResult;
2616
+ }
2617
+ try {
2618
+ const nativeStructuredModel = this.createStructuredOutputModel(args.model, args.chatModelConfig, args.schema);
2619
+ if (nativeStructuredModel) {
2620
+ const nativeResult = this.tryValidateStructuredValue(await args.invokeStructuredModel(nativeStructuredModel, args.conversation), args.schema);
2621
+ if (nativeResult.ok) return nativeResult.value;
2622
+ lastFailure = nativeResult;
2623
+ }
2624
+ } catch (error) {
2625
+ lastFailure = {
2626
+ ok: false,
2627
+ invalidContent: "",
2628
+ validationError: `Native structured output failed: ${this.summarizeError(error)}`
2629
+ };
2630
+ }
2631
+ return await this.retryWithRepairPrompt({
2632
+ ...args,
2633
+ lastFailure: lastFailure ?? {
2634
+ ok: false,
2635
+ invalidContent: "",
2636
+ validationError: "Structured output was required but no valid structured response was produced."
2637
+ }
2638
+ });
2414
2639
  }
2415
- forConnectionNode(ctx, args) {
2416
- const stubConfig = { getCredentialRequirements: args.getCredentialRequirements };
2417
- const getCredential = this.credentialResolverFactory.create(ctx.workflowId, args.connectionNodeId, stubConfig);
2418
- return {
2419
- ...ctx,
2420
- nodeId: args.connectionNodeId,
2421
- getCredential
2422
- };
2640
+ async retryWithRepairPrompt(args) {
2641
+ let failure = args.lastFailure;
2642
+ for (let attempt = 1; attempt <= _AgentStructuredOutputRunner.repairAttemptCount; attempt++) {
2643
+ const repairMessages = [...args.conversation, ...AgentMessageFactory.createPromptMessages(this.repairPromptFactory.create({
2644
+ schema: args.schema,
2645
+ invalidContent: failure.invalidContent,
2646
+ validationError: failure.validationError
2647
+ }))];
2648
+ const repairResponse = await args.invokeTextModel(repairMessages);
2649
+ const repairResult = this.tryParseAndValidate(AgentMessageFactory.extractContent(repairResponse), args.schema);
2650
+ if (repairResult.ok) return repairResult.value;
2651
+ failure = repairResult;
2652
+ }
2653
+ throw new Error(`Structured output required for AIAgent "${args.agentName}" (${args.nodeId}) but validation still failed after ${_AgentStructuredOutputRunner.repairAttemptCount} repair attempts: ${failure.validationError}`);
2423
2654
  }
2424
- };
2425
-
2426
- //#endregion
2427
- //#region src/nodes/AIAgentExecutionHelpersFactory.ts
2428
- let AIAgentExecutionHelpersFactory = class AIAgentExecutionHelpersFactory$1 {
2429
- createConnectionCredentialExecutionContextFactory(credentialSessions) {
2430
- return new ConnectionCredentialExecutionContextFactory(credentialSessions);
2655
+ createStructuredOutputModel(model, chatModelConfig, schema) {
2656
+ if (!this.supportsNativeStructuredOutput(model)) return;
2657
+ const options = this.getStructuredOutputOptions(chatModelConfig);
2658
+ return model.withStructuredOutput(schema, options);
2431
2659
  }
2432
- createDynamicStructuredTool(entry, toolCredentialContext, item, itemIndex, items) {
2433
- if (entry.runtime.inputSchema == null) throw new Error(`Cannot create LangChain tool "${entry.config.name}": missing inputSchema (broken tool runtime resolution).`);
2434
- const schemaForOpenAi = this.normalizeToolInputSchemaForOpenAiDynamicStructuredTool(entry.config.name, entry.runtime.inputSchema);
2435
- return new __langchain_core_tools.DynamicStructuredTool({
2436
- name: entry.config.name,
2437
- description: entry.config.description ?? entry.runtime.defaultDescription,
2438
- schema: schemaForOpenAi,
2439
- func: async (input) => {
2440
- const result = await entry.runtime.execute({
2441
- config: entry.config,
2442
- input,
2443
- ctx: toolCredentialContext,
2444
- item,
2445
- itemIndex,
2446
- items
2447
- });
2448
- return JSON.stringify(result);
2449
- }
2450
- });
2660
+ getStructuredOutputOptions(chatModelConfig) {
2661
+ return this.openAiStructuredOutputMethodFactory.create(chatModelConfig) ?? { strict: true };
2451
2662
  }
2452
- /**
2453
- * Produces a plain JSON Schema object for OpenAI tool parameters and LangChain tool invocation:
2454
- * - **Zod** → `toJSONSchema(..., { target: "draft-07" })` so shapes match what `@cfworker/json-schema`
2455
- * expects (`required` must be an array; draft 2020-12 output can break validation).
2456
- * - Otherwise LangChain `toJsonSchema` (Standard Schema + JSON passthrough); if the result is still Zod
2457
- * (duplicate `zod` copies), fall back to Zod `toJSONSchema` with draft-07.
2458
- * - Strip root `$schema` for OpenAI; normalize invalid `required` keywords for cfworker; ensure `properties`.
2459
- */
2460
- normalizeToolInputSchemaForOpenAiDynamicStructuredTool(toolName, inputSchema) {
2461
- const draft07Params = { target: "draft-07" };
2462
- let converted;
2463
- if ((0, __langchain_core_utils_types.isInteropZodSchema)(inputSchema)) converted = toJSONSchema(inputSchema, draft07Params);
2464
- else {
2465
- converted = (0, __langchain_core_utils_json_schema.toJsonSchema)(inputSchema);
2466
- if ((0, __langchain_core_utils_types.isInteropZodSchema)(converted)) converted = toJSONSchema(inputSchema, draft07Params);
2663
+ supportsNativeStructuredOutput(model) {
2664
+ return typeof model.withStructuredOutput === "function";
2665
+ }
2666
+ tryParseAndValidate(content, schema) {
2667
+ try {
2668
+ return this.tryValidateStructuredValue(JSON.parse(content), schema, content);
2669
+ } catch (error) {
2670
+ return {
2671
+ ok: false,
2672
+ invalidContent: content,
2673
+ validationError: `Response was not valid JSON: ${this.summarizeError(error)}`
2674
+ };
2467
2675
  }
2468
- const { $schema: _draftSchemaOmitted,...rest } = converted;
2469
- if (rest.type !== "object") throw new Error(`Cannot create LangChain tool "${toolName}": tool input schema must be a JSON Schema object type (got type=${String(rest.type)}).`);
2470
- if (rest.properties !== void 0 && (typeof rest.properties !== "object" || Array.isArray(rest.properties))) throw new Error(`Cannot create LangChain tool "${toolName}": tool input schema "properties" must be an object (got ${JSON.stringify(rest.properties)}).`);
2471
- if (rest.properties === void 0) rest.properties = {};
2472
- this.sanitizeJsonSchemaRequiredKeywordsForCfworker(rest);
2473
- return rest;
2474
2676
  }
2475
- /**
2476
- * `@cfworker/json-schema` iterates `schema.required` with `for...of`; it must be a string array or absent.
2477
- */
2478
- sanitizeJsonSchemaRequiredKeywordsForCfworker(node$16) {
2479
- if (!node$16 || typeof node$16 !== "object" || Array.isArray(node$16)) return;
2480
- const o = node$16;
2481
- const req = o.required;
2482
- if (req !== void 0 && !Array.isArray(req)) delete o.required;
2483
- else if (Array.isArray(req)) {
2484
- const strings = req.filter((x) => typeof x === "string");
2485
- if (strings.length === 0) delete o.required;
2486
- else if (strings.length !== req.length) o.required = strings;
2677
+ tryValidateStructuredValue(value, schema, invalidContent) {
2678
+ try {
2679
+ return {
2680
+ ok: true,
2681
+ value: schema.parse(value)
2682
+ };
2683
+ } catch (error) {
2684
+ return {
2685
+ ok: false,
2686
+ invalidContent: invalidContent ?? this.toJson(value),
2687
+ validationError: this.summarizeError(error)
2688
+ };
2487
2689
  }
2488
- const props = o.properties;
2489
- if (props && typeof props === "object" && !Array.isArray(props)) for (const v of Object.values(props)) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(v);
2490
- for (const key of [
2491
- "allOf",
2492
- "anyOf",
2493
- "oneOf"
2494
- ]) {
2495
- const branch = o[key];
2496
- if (Array.isArray(branch)) for (const sub of branch) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(sub);
2690
+ }
2691
+ summarizeError(error) {
2692
+ if (error instanceof ZodError) return error.issues.map((issue$1) => `${issue$1.path.join(".") || "<root>"}: ${issue$1.message}`).join("; ");
2693
+ if (error instanceof Error) return error.message;
2694
+ return String(error);
2695
+ }
2696
+ toJson(value) {
2697
+ try {
2698
+ return JSON.stringify(value);
2699
+ } catch (error) {
2700
+ return `<<unserializable: ${this.summarizeError(error)}>>`;
2497
2701
  }
2498
- if (o.if) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.if);
2499
- if (o.then) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.then);
2500
- if (o.else) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.else);
2501
- if (o.not) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.not);
2502
- if (o.items) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(o.items);
2503
- if (Array.isArray(o.prefixItems)) for (const sub of o.prefixItems) this.sanitizeJsonSchemaRequiredKeywordsForCfworker(sub);
2504
2702
  }
2505
2703
  };
2506
- AIAgentExecutionHelpersFactory = __decorate([(0, __codemation_core.injectable)()], AIAgentExecutionHelpersFactory);
2507
-
2508
- //#endregion
2509
- //#region \0@oxc-project+runtime@0.95.0/helpers/decorateMetadata.js
2510
- function __decorateMetadata(k, v) {
2511
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2512
- }
2704
+ AgentStructuredOutputRunner = _AgentStructuredOutputRunner = __decorate([
2705
+ (0, __codemation_core.injectable)(),
2706
+ __decorateParam(0, (0, __codemation_core.inject)(AgentStructuredOutputRepairPromptFactory)),
2707
+ __decorateParam(1, (0, __codemation_core.inject)(OpenAIStructuredOutputMethodFactory)),
2708
+ __decorateMetadata("design:paramtypes", [typeof (_ref$2 = typeof AgentStructuredOutputRepairPromptFactory !== "undefined" && AgentStructuredOutputRepairPromptFactory) === "function" ? _ref$2 : Object, typeof (_ref2$2 = typeof OpenAIStructuredOutputMethodFactory !== "undefined" && OpenAIStructuredOutputMethodFactory) === "function" ? _ref2$2 : Object])
2709
+ ], AgentStructuredOutputRunner);
2513
2710
 
2514
2711
  //#endregion
2515
- //#region \0@oxc-project+runtime@0.95.0/helpers/decorateParam.js
2516
- function __decorateParam(paramIndex, decorator) {
2517
- return function(target, key) {
2518
- decorator(target, key, paramIndex);
2519
- };
2520
- }
2712
+ //#region src/nodes/AgentToolCallPortMapFactory.ts
2713
+ var AgentToolCallPortMap = class {
2714
+ static fromInput(input) {
2715
+ return { in: [{ json: input }] };
2716
+ }
2717
+ };
2521
2718
 
2522
2719
  //#endregion
2523
2720
  //#region src/nodes/NodeBackedToolRuntime.ts
2524
- var _ref$1, _ref2$1;
2721
+ var _ref$1, _ref2$1, _ref3$1;
2525
2722
  let NodeBackedToolRuntime = class NodeBackedToolRuntime$1 {
2526
- constructor(nodeResolver, itemValueResolver, outputNormalizer) {
2723
+ constructor(nodeResolver, itemValueResolver, outputNormalizer, outputBehaviorResolver) {
2527
2724
  this.nodeResolver = nodeResolver;
2528
2725
  this.itemValueResolver = itemValueResolver;
2529
2726
  this.outputNormalizer = outputNormalizer;
2727
+ this.outputBehaviorResolver = outputBehaviorResolver;
2530
2728
  }
2531
2729
  async execute(config$1, args) {
2532
2730
  const nodeInput = config$1.toNodeItem({
@@ -2558,7 +2756,7 @@ let NodeBackedToolRuntime = class NodeBackedToolRuntime$1 {
2558
2756
  if (this.isRunnableNode(resolvedNode)) {
2559
2757
  const runnable = resolvedNode;
2560
2758
  const runnableConfig = ctx.config;
2561
- const carry = runnableConfig.lineageCarry ?? "emitOnly";
2759
+ const behavior = this.outputBehaviorResolver.resolve(runnableConfig);
2562
2760
  const parsed = (runnable.inputSchema ?? runnableConfig.inputSchema ?? unknown()).parse(nodeInput.json);
2563
2761
  const items = [nodeInput];
2564
2762
  const execArgs = {
@@ -2572,7 +2770,7 @@ let NodeBackedToolRuntime = class NodeBackedToolRuntime$1 {
2572
2770
  return this.outputNormalizer.normalizeExecuteResult({
2573
2771
  baseItem: nodeInput,
2574
2772
  raw,
2575
- carry
2773
+ behavior
2576
2774
  });
2577
2775
  }
2578
2776
  throw new Error(`Node-backed tool expected a runnable node instance for "${ctx.config.name ?? ctx.nodeId}".`);
@@ -2589,10 +2787,12 @@ NodeBackedToolRuntime = __decorate([
2589
2787
  __decorateParam(0, (0, __codemation_core.inject)(__codemation_core.CoreTokens.NodeResolver)),
2590
2788
  __decorateParam(1, (0, __codemation_core.inject)(__codemation_core.ItemValueResolver)),
2591
2789
  __decorateParam(2, (0, __codemation_core.inject)(__codemation_core.NodeOutputNormalizer)),
2790
+ __decorateParam(3, (0, __codemation_core.inject)(__codemation_core.RunnableOutputBehaviorResolver)),
2592
2791
  __decorateMetadata("design:paramtypes", [
2593
2792
  Object,
2594
2793
  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
2794
+ typeof (_ref2$1 = typeof __codemation_core.NodeOutputNormalizer !== "undefined" && __codemation_core.NodeOutputNormalizer) === "function" ? _ref2$1 : Object,
2795
+ typeof (_ref3$1 = typeof __codemation_core.RunnableOutputBehaviorResolver !== "undefined" && __codemation_core.RunnableOutputBehaviorResolver) === "function" ? _ref3$1 : Object
2596
2796
  ])
2597
2797
  ], NodeBackedToolRuntime);
2598
2798
 
@@ -2606,7 +2806,7 @@ var AgentItemPortMap = class {
2606
2806
 
2607
2807
  //#endregion
2608
2808
  //#region src/nodes/AIAgentNode.ts
2609
- var _ref, _ref2;
2809
+ var _ref, _ref2, _ref3;
2610
2810
  let AIAgentNode = class AIAgentNode$1 {
2611
2811
  kind = "node";
2612
2812
  outputPorts = ["main"];
@@ -2619,10 +2819,11 @@ let AIAgentNode = class AIAgentNode$1 {
2619
2819
  connectionCredentialExecutionContextFactory;
2620
2820
  /** One resolved model/tools bundle per activation context (same ctx across items in a batch). */
2621
2821
  preparedByExecutionContext = /* @__PURE__ */ new WeakMap();
2622
- constructor(nodeResolver, credentialSessions, nodeBackedToolRuntime, executionHelpers) {
2822
+ constructor(nodeResolver, credentialSessions, nodeBackedToolRuntime, executionHelpers, structuredOutputRunner) {
2623
2823
  this.nodeResolver = nodeResolver;
2624
2824
  this.nodeBackedToolRuntime = nodeBackedToolRuntime;
2625
2825
  this.executionHelpers = executionHelpers;
2826
+ this.structuredOutputRunner = structuredOutputRunner;
2626
2827
  this.connectionCredentialExecutionContextFactory = this.executionHelpers.createConnectionCredentialExecutionContextFactory(credentialSessions);
2627
2828
  }
2628
2829
  async execute(args) {
@@ -2674,6 +2875,19 @@ let AIAgentNode = class AIAgentNode$1 {
2674
2875
  const itemInputsByPort = AgentItemPortMap.fromItem(item);
2675
2876
  const itemScopedTools = this.createItemScopedTools(prepared.resolvedTools, ctx, item, itemIndex, items);
2676
2877
  const conversation = [...this.createPromptMessages(item, itemIndex, items, ctx)];
2878
+ if (ctx.config.outputSchema && itemScopedTools.length === 0) {
2879
+ const structuredOutput = await this.structuredOutputRunner.resolve({
2880
+ model: prepared.model,
2881
+ chatModelConfig: ctx.config.chatModel,
2882
+ schema: ctx.config.outputSchema,
2883
+ conversation,
2884
+ agentName: this.getAgentDisplayName(ctx),
2885
+ nodeId: ctx.nodeId,
2886
+ invokeTextModel: async (messages) => await this.invokeModel(prepared.model, prepared.languageModelConnectionNodeId, messages, ctx, itemInputsByPort, prepared.guardrails.modelInvocationOptions),
2887
+ invokeStructuredModel: async (structuredModel, messages) => await this.invokeStructuredModel(structuredModel, prepared.languageModelConnectionNodeId, messages, ctx, itemInputsByPort, prepared.guardrails.modelInvocationOptions)
2888
+ });
2889
+ return this.buildOutputItem(item, structuredOutput);
2890
+ }
2677
2891
  const modelWithTools = this.bindToolsToModel(prepared.model, itemScopedTools);
2678
2892
  const finalResponse = await this.runTurnLoopUntilFinalAnswer({
2679
2893
  prepared,
@@ -2682,7 +2896,8 @@ let AIAgentNode = class AIAgentNode$1 {
2682
2896
  conversation,
2683
2897
  modelWithTools
2684
2898
  });
2685
- return this.buildOutputItem(item, finalResponse);
2899
+ const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, finalResponse, itemScopedTools.length > 0);
2900
+ return this.buildOutputItem(item, outputJson);
2686
2901
  }
2687
2902
  /**
2688
2903
  * Repeatedly invokes the model until it returns without tool calls, or guardrails end the loop.
@@ -2718,8 +2933,22 @@ let AIAgentNode = class AIAgentNode$1 {
2718
2933
  appendAssistantAndToolMessages(conversation, assistantMessage, executedToolCalls) {
2719
2934
  conversation.push(assistantMessage, ...executedToolCalls.map((toolCall) => AgentMessageFactory.createToolMessage(toolCall.toolCallId, toolCall.serialized)));
2720
2935
  }
2721
- buildOutputItem(item, finalResponse) {
2722
- return AgentOutputFactory.replaceJson(item, AgentOutputFactory.fromAgentContent(AgentMessageFactory.extractContent(finalResponse)));
2936
+ async resolveFinalOutputJson(prepared, itemInputsByPort, conversation, finalResponse, wasToolEnabledRun) {
2937
+ if (!prepared.ctx.config.outputSchema) return AgentOutputFactory.fromAgentContent(AgentMessageFactory.extractContent(finalResponse));
2938
+ return await this.structuredOutputRunner.resolve({
2939
+ model: prepared.model,
2940
+ chatModelConfig: prepared.ctx.config.chatModel,
2941
+ schema: prepared.ctx.config.outputSchema,
2942
+ conversation: wasToolEnabledRun ? [...conversation, finalResponse] : conversation,
2943
+ rawFinalResponse: finalResponse,
2944
+ agentName: this.getAgentDisplayName(prepared.ctx),
2945
+ nodeId: prepared.ctx.nodeId,
2946
+ invokeTextModel: async (messages) => await this.invokeModel(prepared.model, prepared.languageModelConnectionNodeId, messages, prepared.ctx, itemInputsByPort, prepared.guardrails.modelInvocationOptions),
2947
+ invokeStructuredModel: async (structuredModel, messages) => await this.invokeStructuredModel(structuredModel, prepared.languageModelConnectionNodeId, messages, prepared.ctx, itemInputsByPort, prepared.guardrails.modelInvocationOptions)
2948
+ });
2949
+ }
2950
+ buildOutputItem(item, outputJson) {
2951
+ return AgentOutputFactory.replaceJson(item, outputJson);
2723
2952
  }
2724
2953
  bindToolsToModel(model, itemScopedTools) {
2725
2954
  if (itemScopedTools.length === 0 || !model.bindTools) return model;
@@ -2785,6 +3014,40 @@ let AIAgentNode = class AIAgentNode$1 {
2785
3014
  throw await this.failTrackedNodeInvocation(error, nodeId, ctx, inputsByPort, this.summarizeLlmMessages(messages));
2786
3015
  }
2787
3016
  }
3017
+ async invokeStructuredModel(model, nodeId, messages, ctx, inputsByPort, options) {
3018
+ await ctx.nodeState?.markQueued({
3019
+ nodeId,
3020
+ activationId: ctx.activationId,
3021
+ inputsByPort
3022
+ });
3023
+ await ctx.nodeState?.markRunning({
3024
+ nodeId,
3025
+ activationId: ctx.activationId,
3026
+ inputsByPort
3027
+ });
3028
+ try {
3029
+ const response = await model.invoke(messages, options);
3030
+ await ctx.nodeState?.markCompleted({
3031
+ nodeId,
3032
+ activationId: ctx.activationId,
3033
+ inputsByPort,
3034
+ outputs: AgentOutputFactory.fromUnknown(response)
3035
+ });
3036
+ await ctx.nodeState?.appendConnectionInvocation({
3037
+ invocationId: __codemation_core.ConnectionInvocationIdFactory.create(),
3038
+ connectionNodeId: nodeId,
3039
+ parentAgentNodeId: ctx.nodeId,
3040
+ parentAgentActivationId: ctx.activationId,
3041
+ status: "completed",
3042
+ managedInput: this.summarizeLlmMessages(messages),
3043
+ managedOutput: this.resultToJsonValue(response),
3044
+ finishedAt: (/* @__PURE__ */ new Date()).toISOString()
3045
+ });
3046
+ return response;
3047
+ } catch (error) {
3048
+ throw await this.failTrackedNodeInvocation(error, nodeId, ctx, inputsByPort, this.summarizeLlmMessages(messages));
3049
+ }
3050
+ }
2788
3051
  async markQueuedTools(plannedToolCalls, ctx) {
2789
3052
  for (const plannedToolCall of plannedToolCalls) await ctx.nodeState?.markQueued({
2790
3053
  nodeId: plannedToolCall.nodeId,
@@ -2914,6 +3177,18 @@ let AIAgentNode = class AIAgentNode$1 {
2914
3177
  execute: async (args) => await this.nodeBackedToolRuntime.execute(config$1, args)
2915
3178
  };
2916
3179
  }
3180
+ if (this.isCallableToolConfig(config$1)) {
3181
+ const inputSchema = config$1.getInputSchema();
3182
+ if (inputSchema == null) throw new Error(`AIAgent tool "${config$1.name}": callable tool is missing inputSchema (cannot build LangChain tool).`);
3183
+ return {
3184
+ defaultDescription: config$1.description ?? `Callable tool "${config$1.name}".`,
3185
+ inputSchema,
3186
+ execute: async (args) => await config$1.executeTool({
3187
+ ...args,
3188
+ config: config$1
3189
+ })
3190
+ };
3191
+ }
2917
3192
  const tool = this.nodeResolver.resolve(config$1.type);
2918
3193
  if (tool.inputSchema == null) throw new Error(`AIAgent tool "${config$1.name}": plugin tool "${String(config$1.type)}" is missing inputSchema.`);
2919
3194
  return {
@@ -2930,6 +3205,12 @@ let AIAgentNode = class AIAgentNode$1 {
2930
3205
  isNodeBackedToolConfig(config$1) {
2931
3206
  return config$1 instanceof __codemation_core.NodeBackedToolConfig || typeof config$1 === "object" && config$1 !== null && config$1.toolKind === "nodeBacked";
2932
3207
  }
3208
+ /**
3209
+ * Callable tools use {@link CallableToolConfig#toolKind} for cross-package / JSON round-trip safety.
3210
+ */
3211
+ isCallableToolConfig(config$1) {
3212
+ return config$1 instanceof __codemation_core.CallableToolConfig || typeof config$1 === "object" && config$1 !== null && config$1.toolKind === "callable";
3213
+ }
2933
3214
  resolveGuardrails(guardrails) {
2934
3215
  const maxTurns = guardrails?.maxTurns ?? __codemation_core.AgentGuardrailDefaults.maxTurns;
2935
3216
  if (!Number.isInteger(maxTurns) || maxTurns < 1) throw new Error(`AIAgent maxTurns must be a positive integer. Received: ${String(maxTurns)}`);
@@ -2939,6 +3220,9 @@ let AIAgentNode = class AIAgentNode$1 {
2939
3220
  modelInvocationOptions: guardrails?.modelInvocationOptions
2940
3221
  };
2941
3222
  }
3223
+ getAgentDisplayName(ctx) {
3224
+ return ctx.config.name ?? ctx.nodeId;
3225
+ }
2942
3226
  };
2943
3227
  AIAgentNode = __decorate([
2944
3228
  (0, __codemation_core.node)({ packageName: "@codemation/core-nodes" }),
@@ -2946,11 +3230,13 @@ AIAgentNode = __decorate([
2946
3230
  __decorateParam(1, (0, __codemation_core.inject)(__codemation_core.CoreTokens.CredentialSessionService)),
2947
3231
  __decorateParam(2, (0, __codemation_core.inject)(NodeBackedToolRuntime)),
2948
3232
  __decorateParam(3, (0, __codemation_core.inject)(AIAgentExecutionHelpersFactory)),
3233
+ __decorateParam(4, (0, __codemation_core.inject)(AgentStructuredOutputRunner)),
2949
3234
  __decorateMetadata("design:paramtypes", [
2950
3235
  Object,
2951
3236
  Object,
2952
3237
  typeof (_ref = typeof NodeBackedToolRuntime !== "undefined" && NodeBackedToolRuntime) === "function" ? _ref : Object,
2953
- typeof (_ref2 = typeof AIAgentExecutionHelpersFactory !== "undefined" && AIAgentExecutionHelpersFactory) === "function" ? _ref2 : Object
3238
+ typeof (_ref2 = typeof AIAgentExecutionHelpersFactory !== "undefined" && AIAgentExecutionHelpersFactory) === "function" ? _ref2 : Object,
3239
+ typeof (_ref3 = typeof AgentStructuredOutputRunner !== "undefined" && AgentStructuredOutputRunner) === "function" ? _ref3 : Object
2954
3240
  ])
2955
3241
  ], AIAgentNode);
2956
3242
 
@@ -2973,6 +3259,7 @@ var AIAgent = class {
2973
3259
  retryPolicy;
2974
3260
  guardrails;
2975
3261
  inputSchema;
3262
+ outputSchema;
2976
3263
  constructor(options) {
2977
3264
  this.name = options.name;
2978
3265
  this.messages = options.messages;
@@ -2982,6 +3269,7 @@ var AIAgent = class {
2982
3269
  this.retryPolicy = options.retryPolicy ?? __codemation_core.RetryPolicy.defaultForAiAgent;
2983
3270
  this.guardrails = options.guardrails;
2984
3271
  this.inputSchema = options.inputSchema;
3272
+ this.outputSchema = options.outputSchema;
2985
3273
  }
2986
3274
  };
2987
3275
 
@@ -3298,7 +3586,6 @@ var Switch = class {
3298
3586
  type = SwitchNode;
3299
3587
  execution = { hint: "local" };
3300
3588
  icon = "lucide:git-branch-plus";
3301
- lineageCarry = "carryThrough";
3302
3589
  declaredOutputPorts;
3303
3590
  constructor(name, cfg, id) {
3304
3591
  this.name = name;
@@ -3401,10 +3688,15 @@ var MapData = class {
3401
3688
  execution = { hint: "local" };
3402
3689
  /** Zero mapped items should still allow downstream nodes to run. */
3403
3690
  continueWhenEmptyOutput = true;
3404
- constructor(name, map, id) {
3691
+ keepBinaries;
3692
+ constructor(name, map, options = {}) {
3405
3693
  this.name = name;
3406
3694
  this.map = map;
3407
- this.id = id;
3695
+ this.options = options;
3696
+ this.keepBinaries = options.keepBinaries ?? true;
3697
+ }
3698
+ get id() {
3699
+ return this.options.id;
3408
3700
  }
3409
3701
  };
3410
3702
 
@@ -3713,15 +4005,13 @@ var WorkflowAgentNodeFactory = class {
3713
4005
  static create(nameOrOptions, optionsOrUndefined) {
3714
4006
  const options = typeof nameOrOptions === "string" ? optionsOrUndefined : nameOrOptions;
3715
4007
  const name = typeof nameOrOptions === "string" ? nameOrOptions : "AI agent";
3716
- const prompt = options.prompt;
4008
+ const outputSchema = options.outputSchema;
3717
4009
  return new AIAgent({
3718
4010
  name,
3719
- messages: [{
3720
- role: "user",
3721
- content: typeof prompt === "function" ? ({ item }) => prompt(item.json) : prompt
3722
- }],
4011
+ messages: options.messages,
3723
4012
  chatModel: WorkflowChatModelFactory.create(options.model),
3724
4013
  tools: options.tools,
4014
+ outputSchema,
3725
4015
  id: options.id,
3726
4016
  retryPolicy: options.retryPolicy,
3727
4017
  guardrails: options.guardrails
@@ -3765,10 +4055,10 @@ var WorkflowBranchBuilder = class WorkflowBranchBuilder {
3765
4055
  then(config$1) {
3766
4056
  return new WorkflowBranchBuilder([...this.steps, config$1]);
3767
4057
  }
3768
- map(nameOrMapper, mapperOrUndefined, id) {
4058
+ map(nameOrMapper, mapperOrUndefined, options) {
3769
4059
  const name = typeof nameOrMapper === "string" ? nameOrMapper : "Map data";
3770
4060
  const mapper = typeof nameOrMapper === "string" ? mapperOrUndefined : nameOrMapper;
3771
- return this.then(new MapData(name, (item) => mapper(item.json), id));
4061
+ return this.then(new MapData(name, (item) => mapper(item.json), options));
3772
4062
  }
3773
4063
  wait(nameOrDuration, durationOrUndefined, id) {
3774
4064
  const name = typeof nameOrDuration === "string" && durationOrUndefined !== void 0 ? nameOrDuration : "Wait";
@@ -3811,10 +4101,10 @@ var WorkflowChain = class WorkflowChain {
3811
4101
  then(config$1) {
3812
4102
  return new WorkflowChain(this.chain.then(config$1));
3813
4103
  }
3814
- map(nameOrMapper, mapperOrUndefined, id) {
4104
+ map(nameOrMapper, mapperOrUndefined, options) {
3815
4105
  const name = typeof nameOrMapper === "string" ? nameOrMapper : "Map data";
3816
4106
  const mapper = typeof nameOrMapper === "string" ? mapperOrUndefined : nameOrMapper;
3817
- return this.then(new MapData(name, (item) => mapper(item.json), id));
4107
+ return this.then(new MapData(name, (item) => mapper(item.json), options));
3818
4108
  }
3819
4109
  wait(nameOrDuration, durationOrUndefined, id) {
3820
4110
  const name = typeof nameOrDuration === "string" && durationOrUndefined !== void 0 ? nameOrDuration : "Wait";
@@ -4018,6 +4308,18 @@ Object.defineProperty(exports, 'AIAgentNode', {
4018
4308
  exports.AgentItemPortMap = AgentItemPortMap;
4019
4309
  exports.AgentMessageFactory = AgentMessageFactory;
4020
4310
  exports.AgentOutputFactory = AgentOutputFactory;
4311
+ Object.defineProperty(exports, 'AgentStructuredOutputRepairPromptFactory', {
4312
+ enumerable: true,
4313
+ get: function () {
4314
+ return AgentStructuredOutputRepairPromptFactory;
4315
+ }
4316
+ });
4317
+ Object.defineProperty(exports, 'AgentStructuredOutputRunner', {
4318
+ enumerable: true,
4319
+ get: function () {
4320
+ return AgentStructuredOutputRunner;
4321
+ }
4322
+ });
4021
4323
  exports.AgentToolCallPortMap = AgentToolCallPortMap;
4022
4324
  exports.Aggregate = Aggregate;
4023
4325
  Object.defineProperty(exports, 'AggregateNode', {
@@ -4099,6 +4401,12 @@ Object.defineProperty(exports, 'OpenAIChatModelFactory', {
4099
4401
  return OpenAIChatModelFactory;
4100
4402
  }
4101
4403
  });
4404
+ Object.defineProperty(exports, 'OpenAIStructuredOutputMethodFactory', {
4405
+ enumerable: true,
4406
+ get: function () {
4407
+ return OpenAIStructuredOutputMethodFactory;
4408
+ }
4409
+ });
4102
4410
  exports.OpenAiChatModelPresets = OpenAiChatModelPresets;
4103
4411
  exports.Split = Split;
4104
4412
  Object.defineProperty(exports, 'SplitNode', {