@codemation/core-nodes 0.10.2 → 0.13.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 +122 -0
- package/dist/index.cjs +427 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +205 -67
- package/dist/index.d.ts +206 -68
- package/dist/index.js +427 -99
- package/dist/index.js.map +1 -1
- package/dist/metadata.json +1 -1
- package/package.json +3 -2
- package/src/chatModels/CodemationChatModelConfig.ts +9 -21
- package/src/chatModels/CodemationChatModelFactory.ts +12 -9
- package/src/chatModels/OpenAIChatModelFactory.ts +3 -2
- package/src/index.ts +1 -1
- package/src/nodes/AIAgentConfig.ts +36 -0
- package/src/nodes/AIAgentNode.ts +81 -15
- package/src/nodes/AgentBinaryContentFactory.ts +74 -0
- package/src/nodes/AgentMessageFactory.ts +22 -6
- package/src/nodes/AgentToolResultContentFactory.ts +155 -0
- package/src/nodes/CallbackNodeFactory.ts +9 -6
- package/src/nodes/CronTriggerFactory.ts +6 -2
- package/src/nodes/DeferredMetaToolStrategy.ts +8 -2
- package/src/nodes/ManualTriggerFactory.ts +15 -11
- package/src/nodes/WebhookTriggerFactory.ts +9 -2
- package/src/nodes/aggregate.ts +9 -2
- package/src/nodes/assertion.ts +3 -0
- package/src/nodes/filter.ts +9 -2
- package/src/nodes/httpRequest.ts +6 -1
- package/src/nodes/if.ts +9 -2
- package/src/nodes/isTestRun.ts +6 -2
- package/src/nodes/mapData.ts +4 -2
- package/src/nodes/merge.ts +9 -2
- package/src/nodes/noOp.ts +9 -2
- package/src/nodes/nodeOptions.types.ts +12 -0
- package/src/nodes/split.ts +9 -2
- package/src/nodes/subWorkflow.ts +9 -2
- package/src/nodes/switch.ts +7 -1
- package/src/nodes/wait.ts +9 -2
- package/src/workflowAuthoring/WorkflowChatModelFactory.types.ts +8 -2
- package/src/chatModels/ManagedModelFetcher.ts +0 -23
package/dist/index.cjs
CHANGED
|
@@ -25,14 +25,10 @@ let __codemation_core = require("@codemation/core");
|
|
|
25
25
|
__codemation_core = __toESM(__codemation_core);
|
|
26
26
|
let node_dns_promises = require("node:dns/promises");
|
|
27
27
|
node_dns_promises = __toESM(node_dns_promises);
|
|
28
|
-
let __ai_sdk_openai = require("@ai-sdk/openai");
|
|
29
|
-
__ai_sdk_openai = __toESM(__ai_sdk_openai);
|
|
30
28
|
let __codemation_core_bootstrap = require("@codemation/core/bootstrap");
|
|
31
29
|
__codemation_core_bootstrap = __toESM(__codemation_core_bootstrap);
|
|
32
30
|
let node_crypto = require("node:crypto");
|
|
33
31
|
node_crypto = __toESM(node_crypto);
|
|
34
|
-
let ai = require("ai");
|
|
35
|
-
ai = __toESM(ai);
|
|
36
32
|
let croner = require("croner");
|
|
37
33
|
croner = __toESM(croner);
|
|
38
34
|
|
|
@@ -704,8 +700,9 @@ function __decorate(decorators, target, key, desc) {
|
|
|
704
700
|
let OpenAIChatModelFactory = class OpenAIChatModelFactory$1 {
|
|
705
701
|
async create(args) {
|
|
706
702
|
const session = await args.ctx.getCredential(args.config.credentialSlotKey);
|
|
703
|
+
const { createOpenAI } = await import("@ai-sdk/openai");
|
|
707
704
|
return {
|
|
708
|
-
languageModel:
|
|
705
|
+
languageModel: createOpenAI({
|
|
709
706
|
apiKey: session.apiKey,
|
|
710
707
|
baseURL: session.baseUrl
|
|
711
708
|
}).chat(args.config.model),
|
|
@@ -4448,27 +4445,24 @@ function buildHmacAuthHeader(workspaceId, pairingSecret, method, url, body, over
|
|
|
4448
4445
|
//#endregion
|
|
4449
4446
|
//#region src/chatModels/CodemationChatModelFactory.ts
|
|
4450
4447
|
let CodemationChatModelFactory = class CodemationChatModelFactory$1 {
|
|
4451
|
-
create(args) {
|
|
4448
|
+
async create(args) {
|
|
4452
4449
|
const gatewayUrl = process.env["LLM_GATEWAY_URL"];
|
|
4453
4450
|
if (!gatewayUrl) throw new Error("Codemation managed AI not available in this environment (LLM_GATEWAY_URL is not set).");
|
|
4454
4451
|
const workspaceId = process.env["WORKSPACE_ID"];
|
|
4455
4452
|
const pairingSecret = process.env["WORKSPACE_PAIRING_SECRET"];
|
|
4456
4453
|
if (!workspaceId || !pairingSecret) throw new Error("Codemation managed AI not available in this environment (workspace pairing is not configured).");
|
|
4457
4454
|
const hmacFetch = managedHmacFetchFactory(workspaceId, pairingSecret);
|
|
4458
|
-
const
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
modelName: args.config.
|
|
4455
|
+
const { createAnthropic } = await import("@ai-sdk/anthropic");
|
|
4456
|
+
return {
|
|
4457
|
+
languageModel: createAnthropic({
|
|
4458
|
+
baseURL: `${gatewayUrl}/v1`,
|
|
4459
|
+
apiKey: "codemation-managed",
|
|
4460
|
+
fetch: hmacFetch
|
|
4461
|
+
})(args.config.complexity),
|
|
4462
|
+
modelName: args.config.complexity,
|
|
4466
4463
|
provider: "codemation-managed",
|
|
4467
|
-
defaultCallOptions: {
|
|
4468
|
-
|
|
4469
|
-
temperature: args.config.options?.temperature
|
|
4470
|
-
}
|
|
4471
|
-
});
|
|
4464
|
+
defaultCallOptions: { maxOutputTokens: args.config.options?.maxTokens }
|
|
4465
|
+
};
|
|
4472
4466
|
}
|
|
4473
4467
|
};
|
|
4474
4468
|
CodemationChatModelFactory = __decorate([(0, __codemation_core.chatModel)({ packageName: "@codemation/core-nodes" })], CodemationChatModelFactory);
|
|
@@ -4480,11 +4474,11 @@ var CodemationChatModelConfig = class {
|
|
|
4480
4474
|
presentation;
|
|
4481
4475
|
provider = "codemation-managed";
|
|
4482
4476
|
modelName;
|
|
4483
|
-
constructor(name,
|
|
4477
|
+
constructor(name, complexity, presentationIn, options) {
|
|
4484
4478
|
this.name = name;
|
|
4485
|
-
this.
|
|
4479
|
+
this.complexity = complexity;
|
|
4486
4480
|
this.options = options;
|
|
4487
|
-
this.modelName =
|
|
4481
|
+
this.modelName = complexity;
|
|
4488
4482
|
this.presentation = presentationIn ?? {
|
|
4489
4483
|
icon: "lucide:bot",
|
|
4490
4484
|
label: name
|
|
@@ -4493,24 +4487,151 @@ var CodemationChatModelConfig = class {
|
|
|
4493
4487
|
};
|
|
4494
4488
|
|
|
4495
4489
|
//#endregion
|
|
4496
|
-
//#region src/
|
|
4490
|
+
//#region src/nodes/AgentToolResultContentFactory.ts
|
|
4497
4491
|
/**
|
|
4498
|
-
*
|
|
4499
|
-
*
|
|
4500
|
-
* Returns an empty array if the env var is absent or the fetch fails.
|
|
4501
|
-
* Cache the result per session — the allowlist changes infrequently.
|
|
4492
|
+
* Cap on raw (pre-base64) bytes inlined from a single tool result. Base64 inflates ~33% and every
|
|
4493
|
+
* inlined byte eats model context, so oversize binaries are replaced with a text placeholder.
|
|
4502
4494
|
*/
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4495
|
+
const MAX_INLINE_BYTES = 8 * 1024 * 1024;
|
|
4496
|
+
/** MCP content-block discriminators. At least one must appear for a result to be treated as MCP-shaped. */
|
|
4497
|
+
const KNOWN_MCP_BLOCK_TYPES = new Set([
|
|
4498
|
+
"text",
|
|
4499
|
+
"image",
|
|
4500
|
+
"audio",
|
|
4501
|
+
"resource",
|
|
4502
|
+
"resource_link"
|
|
4503
|
+
]);
|
|
4504
|
+
/**
|
|
4505
|
+
* Maps a tool result that is **content-block-shaped** (an MCP `CallToolResult` with a `content`
|
|
4506
|
+
* array) into AI SDK `{ type: "content" }` tool-result output, so binaries reach the chat model as
|
|
4507
|
+
* native multimodal tool-result blocks instead of being flattened to inert JSON text.
|
|
4508
|
+
*
|
|
4509
|
+
* The `@ai-sdk/anthropic` provider maps a `content`-output part as follows:
|
|
4510
|
+
* `text` → text block, `image-data` → image block, `file-data` (only `application/pdf`) → document
|
|
4511
|
+
* block. Non-PDF `file-data` is dropped by the provider, so this factory emits `image-data` for
|
|
4512
|
+
* images, `file-data` only for PDFs, and a text marker for every other binary type.
|
|
4513
|
+
*
|
|
4514
|
+
* Returns `undefined` when the result is not content-block-shaped — callers keep the existing
|
|
4515
|
+
* `{ type: "json" }` path, so plain string/object tool results are unaffected.
|
|
4516
|
+
*/
|
|
4517
|
+
var AgentToolResultContentFactory = class AgentToolResultContentFactory {
|
|
4518
|
+
static tryMapToContentOutput(result) {
|
|
4519
|
+
const blocks = AgentToolResultContentFactory.contentBlocks(result);
|
|
4520
|
+
if (blocks === void 0) return void 0;
|
|
4521
|
+
const parts = [];
|
|
4522
|
+
let inlinedBytes = 0;
|
|
4523
|
+
for (const block of blocks) {
|
|
4524
|
+
const mapped = AgentToolResultContentFactory.mapBlock(block, inlinedBytes);
|
|
4525
|
+
parts.push(mapped.part);
|
|
4526
|
+
inlinedBytes += mapped.bytes;
|
|
4513
4527
|
}
|
|
4528
|
+
return parts;
|
|
4529
|
+
}
|
|
4530
|
+
/**
|
|
4531
|
+
* Returns the `content` array iff `result` is an object whose `content` is an array of typed
|
|
4532
|
+
* blocks AND at least one block carries a known MCP discriminator. A plain JSON result that merely
|
|
4533
|
+
* has a `content` key of some other shape (e.g. Notion/Slack rich-text blocks) is rejected,
|
|
4534
|
+
* preserving the `{ type: "json" }` path so its payload is never lost.
|
|
4535
|
+
*/
|
|
4536
|
+
static contentBlocks(result) {
|
|
4537
|
+
if (result === null || typeof result !== "object") return void 0;
|
|
4538
|
+
const content = result.content;
|
|
4539
|
+
if (!Array.isArray(content) || content.length === 0) return void 0;
|
|
4540
|
+
if (!content.every((block) => block !== null && typeof block === "object" && typeof block.type === "string")) return void 0;
|
|
4541
|
+
return content.some((block) => KNOWN_MCP_BLOCK_TYPES.has(block.type)) ? content : void 0;
|
|
4542
|
+
}
|
|
4543
|
+
static mapBlock(block, inlinedBytesSoFar) {
|
|
4544
|
+
const type = block.type;
|
|
4545
|
+
if (type === "text" && typeof block.text === "string") return {
|
|
4546
|
+
part: {
|
|
4547
|
+
type: "text",
|
|
4548
|
+
text: block.text
|
|
4549
|
+
},
|
|
4550
|
+
bytes: 0
|
|
4551
|
+
};
|
|
4552
|
+
if (type === "image" && typeof block.data === "string" && typeof block.mimeType === "string") return AgentToolResultContentFactory.mapBinary({
|
|
4553
|
+
base64: block.data,
|
|
4554
|
+
mediaType: block.mimeType,
|
|
4555
|
+
inlinedBytesSoFar
|
|
4556
|
+
});
|
|
4557
|
+
if (type === "resource" && block.resource) return AgentToolResultContentFactory.mapEmbeddedResource(block.resource, inlinedBytesSoFar);
|
|
4558
|
+
if (type === "resource_link" && typeof block.uri === "string") {
|
|
4559
|
+
const mime = typeof block.mimeType === "string" ? ` (${block.mimeType})` : "";
|
|
4560
|
+
return {
|
|
4561
|
+
part: {
|
|
4562
|
+
type: "text",
|
|
4563
|
+
text: `[linked resource: ${block.uri}${mime}]`
|
|
4564
|
+
},
|
|
4565
|
+
bytes: 0
|
|
4566
|
+
};
|
|
4567
|
+
}
|
|
4568
|
+
return {
|
|
4569
|
+
part: {
|
|
4570
|
+
type: "text",
|
|
4571
|
+
text: `[unsupported tool content block: ${String(type)}]`
|
|
4572
|
+
},
|
|
4573
|
+
bytes: 0
|
|
4574
|
+
};
|
|
4575
|
+
}
|
|
4576
|
+
static mapEmbeddedResource(resource, inlinedBytesSoFar) {
|
|
4577
|
+
if (typeof resource.text === "string") return {
|
|
4578
|
+
part: {
|
|
4579
|
+
type: "text",
|
|
4580
|
+
text: resource.text
|
|
4581
|
+
},
|
|
4582
|
+
bytes: 0
|
|
4583
|
+
};
|
|
4584
|
+
if (typeof resource.blob === "string" && typeof resource.mimeType === "string") return AgentToolResultContentFactory.mapBinary({
|
|
4585
|
+
base64: resource.blob,
|
|
4586
|
+
mediaType: resource.mimeType,
|
|
4587
|
+
filename: typeof resource.name === "string" ? resource.name : void 0,
|
|
4588
|
+
inlinedBytesSoFar
|
|
4589
|
+
});
|
|
4590
|
+
return {
|
|
4591
|
+
part: {
|
|
4592
|
+
type: "text",
|
|
4593
|
+
text: `[embedded resource: ${typeof resource.uri === "string" ? resource.uri : "unknown"}]`
|
|
4594
|
+
},
|
|
4595
|
+
bytes: 0
|
|
4596
|
+
};
|
|
4597
|
+
}
|
|
4598
|
+
static mapBinary(args) {
|
|
4599
|
+
const rawBytes = Math.floor(args.base64.length * 3 / 4);
|
|
4600
|
+
if (args.inlinedBytesSoFar + rawBytes > MAX_INLINE_BYTES) {
|
|
4601
|
+
const name = args.filename ? ` "${args.filename}"` : "";
|
|
4602
|
+
const kb = Math.round(rawBytes / 1024);
|
|
4603
|
+
return {
|
|
4604
|
+
part: {
|
|
4605
|
+
type: "text",
|
|
4606
|
+
text: `[binary${name} (${args.mediaType}, ~${kb} KB) omitted: exceeds the per-tool-result inline limit]`
|
|
4607
|
+
},
|
|
4608
|
+
bytes: 0
|
|
4609
|
+
};
|
|
4610
|
+
}
|
|
4611
|
+
if (args.mediaType.startsWith("image/")) return {
|
|
4612
|
+
part: {
|
|
4613
|
+
type: "image-data",
|
|
4614
|
+
data: args.base64,
|
|
4615
|
+
mediaType: args.mediaType
|
|
4616
|
+
},
|
|
4617
|
+
bytes: rawBytes
|
|
4618
|
+
};
|
|
4619
|
+
if (args.mediaType === "application/pdf") return {
|
|
4620
|
+
part: {
|
|
4621
|
+
type: "file-data",
|
|
4622
|
+
data: args.base64,
|
|
4623
|
+
mediaType: args.mediaType,
|
|
4624
|
+
...args.filename ? { filename: args.filename } : {}
|
|
4625
|
+
},
|
|
4626
|
+
bytes: rawBytes
|
|
4627
|
+
};
|
|
4628
|
+
return {
|
|
4629
|
+
part: {
|
|
4630
|
+
type: "text",
|
|
4631
|
+
text: `[binary${args.filename ? ` "${args.filename}"` : ""} (${args.mediaType}) not inlined: unsupported by the model]`
|
|
4632
|
+
},
|
|
4633
|
+
bytes: 0
|
|
4634
|
+
};
|
|
4514
4635
|
}
|
|
4515
4636
|
};
|
|
4516
4637
|
|
|
@@ -4550,20 +4671,35 @@ var AgentMessageFactory = class AgentMessageFactory {
|
|
|
4550
4671
|
* Builds the `{ role: "tool", content: [{ type: "tool-result", ... }, ...] }` message returned
|
|
4551
4672
|
* to the model after each tool round.
|
|
4552
4673
|
*/
|
|
4553
|
-
static createToolResultsMessage(executedToolCalls) {
|
|
4674
|
+
static createToolResultsMessage(executedToolCalls, passToolBinariesToModel = true) {
|
|
4554
4675
|
return {
|
|
4555
4676
|
role: "tool",
|
|
4556
4677
|
content: executedToolCalls.map((executed) => ({
|
|
4557
4678
|
type: "tool-result",
|
|
4558
4679
|
toolCallId: executed.toolCallId,
|
|
4559
4680
|
toolName: executed.toolName,
|
|
4560
|
-
output:
|
|
4561
|
-
type: "json",
|
|
4562
|
-
value: AgentMessageFactory.toToolResultJson(executed.result)
|
|
4563
|
-
}
|
|
4681
|
+
output: AgentMessageFactory.toToolResultOutput(executed.result, passToolBinariesToModel)
|
|
4564
4682
|
}))
|
|
4565
4683
|
};
|
|
4566
4684
|
}
|
|
4685
|
+
/**
|
|
4686
|
+
* Routes a tool result to a native multimodal `{ type: "content" }` output when it is
|
|
4687
|
+
* content-block-shaped (an MCP `CallToolResult`) and binary passdown is enabled; otherwise keeps
|
|
4688
|
+
* the inert `{ type: "json" }` path.
|
|
4689
|
+
*/
|
|
4690
|
+
static toToolResultOutput(result, passToolBinariesToModel) {
|
|
4691
|
+
if (passToolBinariesToModel) {
|
|
4692
|
+
const content = AgentToolResultContentFactory.tryMapToContentOutput(result);
|
|
4693
|
+
if (content !== void 0) return {
|
|
4694
|
+
type: "content",
|
|
4695
|
+
value: content
|
|
4696
|
+
};
|
|
4697
|
+
}
|
|
4698
|
+
return {
|
|
4699
|
+
type: "json",
|
|
4700
|
+
value: AgentMessageFactory.toToolResultJson(result)
|
|
4701
|
+
};
|
|
4702
|
+
}
|
|
4567
4703
|
static toToolResultJson(value) {
|
|
4568
4704
|
if (value === void 0) return null;
|
|
4569
4705
|
try {
|
|
@@ -5882,6 +6018,63 @@ AgentToolExecutionCoordinator = __decorate([
|
|
|
5882
6018
|
__decorateMetadata("design:paramtypes", [typeof (_ref$2 = typeof AgentToolErrorClassifier !== "undefined" && AgentToolErrorClassifier) === "function" ? _ref$2 : Object, typeof (_ref2$2 = typeof AgentToolRepairPolicy !== "undefined" && AgentToolRepairPolicy) === "function" ? _ref2$2 : Object])
|
|
5883
6019
|
], AgentToolExecutionCoordinator);
|
|
5884
6020
|
|
|
6021
|
+
//#endregion
|
|
6022
|
+
//#region src/nodes/AgentBinaryContentFactory.ts
|
|
6023
|
+
/**
|
|
6024
|
+
* Turns resolved file binaries into native AI SDK multimodal content parts and merges them into the
|
|
6025
|
+
* agent prompt. Images (`image/*`) become {@link ImagePart}s; every other type (PDFs, office docs,
|
|
6026
|
+
* CSV, JSON, …) becomes a {@link FilePart}. The provider maps these to its wire-level `image` /
|
|
6027
|
+
* `document` blocks; an unsupported file type surfaces as a provider error at runtime.
|
|
6028
|
+
*
|
|
6029
|
+
* Parts are appended to the LAST user message so the binary travels alongside the author's prompt
|
|
6030
|
+
* text (preserving any untrusted-source preamble that already wrapped that text). When no user
|
|
6031
|
+
* message exists, a new user message carrying only the binaries is appended.
|
|
6032
|
+
*/
|
|
6033
|
+
var AgentBinaryContentFactory = class AgentBinaryContentFactory {
|
|
6034
|
+
static toContentPart(binary) {
|
|
6035
|
+
if (binary.mediaType.startsWith("image/")) return {
|
|
6036
|
+
type: "image",
|
|
6037
|
+
image: binary.base64,
|
|
6038
|
+
mediaType: binary.mediaType
|
|
6039
|
+
};
|
|
6040
|
+
return {
|
|
6041
|
+
type: "file",
|
|
6042
|
+
data: binary.base64,
|
|
6043
|
+
mediaType: binary.mediaType,
|
|
6044
|
+
...binary.filename ? { filename: binary.filename } : {}
|
|
6045
|
+
};
|
|
6046
|
+
}
|
|
6047
|
+
static withBinaries(messages, binaries) {
|
|
6048
|
+
if (binaries.length === 0) return messages;
|
|
6049
|
+
const parts = binaries.map((binary) => AgentBinaryContentFactory.toContentPart(binary));
|
|
6050
|
+
const lastUserIndex = AgentBinaryContentFactory.lastUserMessageIndex(messages);
|
|
6051
|
+
if (lastUserIndex === -1) {
|
|
6052
|
+
const appended = {
|
|
6053
|
+
role: "user",
|
|
6054
|
+
content: parts
|
|
6055
|
+
};
|
|
6056
|
+
return [...messages, appended];
|
|
6057
|
+
}
|
|
6058
|
+
const next = [...messages];
|
|
6059
|
+
next[lastUserIndex] = AgentBinaryContentFactory.appendPartsToUserMessage(messages[lastUserIndex], parts);
|
|
6060
|
+
return next;
|
|
6061
|
+
}
|
|
6062
|
+
static lastUserMessageIndex(messages) {
|
|
6063
|
+
for (let index = messages.length - 1; index >= 0; index--) if (messages[index]?.role === "user") return index;
|
|
6064
|
+
return -1;
|
|
6065
|
+
}
|
|
6066
|
+
static appendPartsToUserMessage(message, parts) {
|
|
6067
|
+
const existing = typeof message.content === "string" ? message.content.length > 0 ? [{
|
|
6068
|
+
type: "text",
|
|
6069
|
+
text: message.content
|
|
6070
|
+
}] : [] : message.content;
|
|
6071
|
+
return {
|
|
6072
|
+
...message,
|
|
6073
|
+
content: [...existing, ...parts]
|
|
6074
|
+
};
|
|
6075
|
+
}
|
|
6076
|
+
};
|
|
6077
|
+
|
|
5885
6078
|
//#endregion
|
|
5886
6079
|
//#region src/nodes/NodeBackedToolRuntime.ts
|
|
5887
6080
|
var _ref$1, _ref2$1, _ref3$1, _ref4$1;
|
|
@@ -6080,11 +6273,18 @@ var DeferredMetaToolStrategy = class {
|
|
|
6080
6273
|
mcpEntries = [];
|
|
6081
6274
|
toolsByServerId = /* @__PURE__ */ new Map();
|
|
6082
6275
|
foundToolIds = /* @__PURE__ */ new Set();
|
|
6276
|
+
/**
|
|
6277
|
+
* `jsonSchema` from the `ai` SDK, loaded lazily in {@link initialize} so the SDK
|
|
6278
|
+
* (~28MB RSS) stays off the boot path. `initialize` always runs before the sync
|
|
6279
|
+
* `getToolsForTurn` → `buildFindToolsDefinition` path, so this is set before use.
|
|
6280
|
+
*/
|
|
6281
|
+
jsonSchema;
|
|
6083
6282
|
constructor(bm25, warnFn) {
|
|
6084
6283
|
this.bm25 = bm25;
|
|
6085
6284
|
this.warnFn = warnFn;
|
|
6086
6285
|
}
|
|
6087
6286
|
async initialize(input) {
|
|
6287
|
+
this.jsonSchema = (await import("ai")).jsonSchema;
|
|
6088
6288
|
this.nodeBackedTools = { ...input.nodeBackedTools };
|
|
6089
6289
|
const pinnedIds = input.pinnedMcpTools ?? [];
|
|
6090
6290
|
if (pinnedIds.length > PINNED_TOOLS_HARD_LIMIT) throw new Error(`Agent config error: pinnedMcpTools count (${pinnedIds.length}) exceeds hard limit of ${PINNED_TOOLS_HARD_LIMIT}.`);
|
|
@@ -6172,25 +6372,26 @@ var DeferredMetaToolStrategy = class {
|
|
|
6172
6372
|
return [...this.foundToolIds];
|
|
6173
6373
|
}
|
|
6174
6374
|
buildFindToolsDefinition() {
|
|
6375
|
+
const inputSchemaRecord = {
|
|
6376
|
+
type: "object",
|
|
6377
|
+
properties: {
|
|
6378
|
+
query: {
|
|
6379
|
+
type: "string",
|
|
6380
|
+
description: "Natural language description of what you want to do."
|
|
6381
|
+
},
|
|
6382
|
+
limit: {
|
|
6383
|
+
type: "integer",
|
|
6384
|
+
minimum: 1,
|
|
6385
|
+
maximum: 10,
|
|
6386
|
+
description: `Maximum number of tools to return (default ${FIND_TOOLS_DEFAULT_LIMIT}).`
|
|
6387
|
+
}
|
|
6388
|
+
},
|
|
6389
|
+
required: ["query"],
|
|
6390
|
+
additionalProperties: false
|
|
6391
|
+
};
|
|
6175
6392
|
return {
|
|
6176
6393
|
description: "Search for tools available from connected MCP servers. After this call, the tools listed in the result will be callable on your very next turn. Use this when you need a capability not visible in your current tool list. Do not attempt to call a tool name you have not seen yet — use find_tools to discover it first.",
|
|
6177
|
-
inputSchema:
|
|
6178
|
-
type: "object",
|
|
6179
|
-
properties: {
|
|
6180
|
-
query: {
|
|
6181
|
-
type: "string",
|
|
6182
|
-
description: "Natural language description of what you want to do."
|
|
6183
|
-
},
|
|
6184
|
-
limit: {
|
|
6185
|
-
type: "integer",
|
|
6186
|
-
minimum: 1,
|
|
6187
|
-
maximum: 10,
|
|
6188
|
-
description: `Maximum number of tools to return (default ${FIND_TOOLS_DEFAULT_LIMIT}).`
|
|
6189
|
-
}
|
|
6190
|
-
},
|
|
6191
|
-
required: ["query"],
|
|
6192
|
-
additionalProperties: false
|
|
6193
|
-
})
|
|
6394
|
+
inputSchema: this.jsonSchema(inputSchemaRecord)
|
|
6194
6395
|
};
|
|
6195
6396
|
}
|
|
6196
6397
|
};
|
|
@@ -6224,6 +6425,13 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6224
6425
|
inputSchema = unknown();
|
|
6225
6426
|
connectionCredentialExecutionContextFactory;
|
|
6226
6427
|
preparedByExecutionContext = /* @__PURE__ */ new WeakMap();
|
|
6428
|
+
/**
|
|
6429
|
+
* The `ai` SDK, loaded lazily in {@link execute} so the SDK (~28MB RSS) stays
|
|
6430
|
+
* off the boot path — non-AI workflows never load it. Every path runs through
|
|
6431
|
+
* `execute` → `ensureAiSdk` before any sync helper touches `this.aiSdk`.
|
|
6432
|
+
*/
|
|
6433
|
+
aiSdk;
|
|
6434
|
+
aiSdkPromise = null;
|
|
6227
6435
|
constructor(nodeResolver, credentialSessions, nodeBackedToolRuntime, executionHelpers, structuredOutputRunner, toolExecutionCoordinator, toolLoadingStrategyFactory, agentMcpIntegration) {
|
|
6228
6436
|
this.nodeResolver = nodeResolver;
|
|
6229
6437
|
this.nodeBackedToolRuntime = nodeBackedToolRuntime;
|
|
@@ -6236,6 +6444,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6236
6444
|
}
|
|
6237
6445
|
async execute(args) {
|
|
6238
6446
|
const { ctx } = args;
|
|
6447
|
+
await this.ensureAiSdk();
|
|
6239
6448
|
if (ctx.resumeContext) return this.executeResumed(args, ctx.resumeContext);
|
|
6240
6449
|
const prepared = await this.getOrPrepareExecution(ctx);
|
|
6241
6450
|
const itemWithMappedJson = {
|
|
@@ -6244,6 +6453,10 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6244
6453
|
};
|
|
6245
6454
|
return (await this.runAgentForItem(prepared, itemWithMappedJson, args.itemIndex, args.items)).json;
|
|
6246
6455
|
}
|
|
6456
|
+
/** Load the `ai` SDK once per node instance (cached promise guards concurrent items). */
|
|
6457
|
+
async ensureAiSdk() {
|
|
6458
|
+
this.aiSdk = await (this.aiSdkPromise ??= import("ai"));
|
|
6459
|
+
}
|
|
6247
6460
|
/**
|
|
6248
6461
|
* Resume path: re-enters the agent loop after a HITL suspension.
|
|
6249
6462
|
* Reconstructs the conversation from the checkpoint, injects the human decision
|
|
@@ -6275,7 +6488,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6275
6488
|
result: decision,
|
|
6276
6489
|
serialized: JSON.stringify(decision)
|
|
6277
6490
|
};
|
|
6278
|
-
const conversation = [...checkpoint.conversation, AgentMessageFactory.createToolResultsMessage([toolResultEntry])];
|
|
6491
|
+
const conversation = [...checkpoint.conversation, AgentMessageFactory.createToolResultsMessage([toolResultEntry], ctx.config.passToolBinariesToModel !== false)];
|
|
6279
6492
|
const loopResult = await this.runTurnLoopUntilFinalAnswer({
|
|
6280
6493
|
prepared,
|
|
6281
6494
|
itemInputsByPort,
|
|
@@ -6386,7 +6599,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6386
6599
|
const { ctx } = prepared;
|
|
6387
6600
|
const itemInputsByPort = AgentItemPortMap.fromItem(item);
|
|
6388
6601
|
const itemScopedTools = this.createItemScopedTools(prepared.resolvedTools, ctx, item, itemIndex, items);
|
|
6389
|
-
const conversation = [...this.createPromptMessages(item, itemIndex, items, ctx)];
|
|
6602
|
+
const conversation = [...await this.createPromptMessages(item, itemIndex, items, ctx)];
|
|
6390
6603
|
if (ctx.config.outputSchema && itemScopedTools.length === 0) {
|
|
6391
6604
|
const structuredOutput = await this.structuredOutputRunner.resolve({
|
|
6392
6605
|
model: prepared.model,
|
|
@@ -6495,7 +6708,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6495
6708
|
coordinatorExecutedCalls.push(...executed);
|
|
6496
6709
|
}
|
|
6497
6710
|
const allExecutedCalls = [...strategyExecutedCalls, ...coordinatorExecutedCalls];
|
|
6498
|
-
this.appendAssistantAndToolMessages(conversation, result.assistantMessage, result.text, result.toolCalls, allExecutedCalls);
|
|
6711
|
+
this.appendAssistantAndToolMessages(conversation, result.assistantMessage, result.text, result.toolCalls, allExecutedCalls, ctx.config.passToolBinariesToModel !== false);
|
|
6499
6712
|
}
|
|
6500
6713
|
return {
|
|
6501
6714
|
finalText,
|
|
@@ -6510,8 +6723,8 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6510
6723
|
if (guardrails.onTurnLimitReached === "respondWithLastMessage") return;
|
|
6511
6724
|
throw new Error(`AIAgent "${ctx.config.name ?? ctx.nodeId}" reached maxTurns=${guardrails.maxTurns} before producing a final response.`);
|
|
6512
6725
|
}
|
|
6513
|
-
appendAssistantAndToolMessages(conversation, assistantMessage, text, toolCalls, executedToolCalls) {
|
|
6514
|
-
conversation.push(assistantMessage ?? AgentMessageFactory.createAssistantWithToolCalls(text, toolCalls), AgentMessageFactory.createToolResultsMessage(executedToolCalls));
|
|
6726
|
+
appendAssistantAndToolMessages(conversation, assistantMessage, text, toolCalls, executedToolCalls, passToolBinariesToModel) {
|
|
6727
|
+
conversation.push(assistantMessage ?? AgentMessageFactory.createAssistantWithToolCalls(text, toolCalls), AgentMessageFactory.createToolResultsMessage(executedToolCalls, passToolBinariesToModel));
|
|
6515
6728
|
}
|
|
6516
6729
|
async resolveFinalOutputJson(prepared, itemInputsByPort, conversation, finalText, wasToolEnabledRun) {
|
|
6517
6730
|
if (!prepared.ctx.config.outputSchema) return AgentOutputFactory.fromAgentContent(finalText);
|
|
@@ -6630,7 +6843,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6630
6843
|
const description = this.resolveHumanApprovalBehavior(entry.config) !== void 0 ? `${baseDescription} ${HITL_SOLO_CONSTRAINT_SENTENCE}` : baseDescription;
|
|
6631
6844
|
toolSet[entry.config.name] = {
|
|
6632
6845
|
description,
|
|
6633
|
-
inputSchema:
|
|
6846
|
+
inputSchema: this.aiSdk.jsonSchema(schemaRecord)
|
|
6634
6847
|
};
|
|
6635
6848
|
}
|
|
6636
6849
|
return toolSet;
|
|
@@ -6661,7 +6874,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6661
6874
|
const description = entry.humanApproval !== void 0 && baseDescription !== void 0 ? `${baseDescription} ${HITL_SOLO_CONSTRAINT_SENTENCE}` : entry.humanApproval !== void 0 ? HITL_SOLO_CONSTRAINT_SENTENCE : baseDescription;
|
|
6662
6875
|
toolSet[entry.config.name] = {
|
|
6663
6876
|
description,
|
|
6664
|
-
inputSchema:
|
|
6877
|
+
inputSchema: this.aiSdk.jsonSchema(schemaRecord)
|
|
6665
6878
|
};
|
|
6666
6879
|
}
|
|
6667
6880
|
return toolSet;
|
|
@@ -6713,7 +6926,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6713
6926
|
});
|
|
6714
6927
|
try {
|
|
6715
6928
|
const callOptions = this.resolveCallOptions(model, guardrails.modelInvocationOptions);
|
|
6716
|
-
const result = await
|
|
6929
|
+
const result = await this.aiSdk.generateText({
|
|
6717
6930
|
model: model.languageModel,
|
|
6718
6931
|
messages: [...messages],
|
|
6719
6932
|
tools,
|
|
@@ -6832,8 +7045,8 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6832
7045
|
schemaName: structuredOptions?.schemaName ?? "structured_output",
|
|
6833
7046
|
requireObjectRoot: true
|
|
6834
7047
|
}) : schema;
|
|
6835
|
-
const outputSchema =
|
|
6836
|
-
const result = await
|
|
7048
|
+
const outputSchema = this.aiSdk.Output.object({ schema: this.aiSdk.jsonSchema(schemaRecord) });
|
|
7049
|
+
const result = await this.aiSdk.generateText({
|
|
6837
7050
|
model: model.languageModel,
|
|
6838
7051
|
messages: [...messages],
|
|
6839
7052
|
experimental_output: outputSchema,
|
|
@@ -7104,7 +7317,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
7104
7317
|
const json = JSON.stringify(value);
|
|
7105
7318
|
return JSON.parse(json);
|
|
7106
7319
|
}
|
|
7107
|
-
createPromptMessages(item, itemIndex, items, ctx) {
|
|
7320
|
+
async createPromptMessages(item, itemIndex, items, ctx) {
|
|
7108
7321
|
const messages = __codemation_core.AgentMessageConfigNormalizer.resolveFromInputOrConfig(item.json, ctx.config, {
|
|
7109
7322
|
item,
|
|
7110
7323
|
itemIndex,
|
|
@@ -7112,7 +7325,47 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
7112
7325
|
ctx
|
|
7113
7326
|
});
|
|
7114
7327
|
const wrapped = this.wrapUntrustedSourceMessages(messages, item, ctx.config);
|
|
7115
|
-
|
|
7328
|
+
const promptMessages = AgentMessageFactory.createPromptMessages(wrapped);
|
|
7329
|
+
if (ctx.config.passBinariesToModel === false) return promptMessages;
|
|
7330
|
+
const attachments = this.selectBinaryAttachments(item, itemIndex, items, ctx);
|
|
7331
|
+
const binaries = await this.resolveInlineBinaries(attachments, ctx);
|
|
7332
|
+
return AgentBinaryContentFactory.withBinaries(promptMessages, binaries);
|
|
7333
|
+
}
|
|
7334
|
+
/**
|
|
7335
|
+
* Picks which attachments feed the passdown. When the author supplies `config.binaries`
|
|
7336
|
+
* (a static array or a per-item function — e.g. to forward binaries from an earlier node),
|
|
7337
|
+
* those replace the current item's attachments; otherwise the current item's `item.binary`
|
|
7338
|
+
* is used.
|
|
7339
|
+
*/
|
|
7340
|
+
selectBinaryAttachments(item, itemIndex, items, ctx) {
|
|
7341
|
+
const manual = ctx.config.binaries;
|
|
7342
|
+
if (manual !== void 0) return typeof manual === "function" ? manual({
|
|
7343
|
+
item,
|
|
7344
|
+
itemIndex,
|
|
7345
|
+
items,
|
|
7346
|
+
ctx
|
|
7347
|
+
}) : manual;
|
|
7348
|
+
return item.binary ? Object.values(item.binary) : [];
|
|
7349
|
+
}
|
|
7350
|
+
/**
|
|
7351
|
+
* Reads every attachment through `ctx.binary` (storage-backed, by reference — never base64 on
|
|
7352
|
+
* `item.json`) and resolves it to inline base64 so the agent can pass it to the chat model as a
|
|
7353
|
+
* native multimodal block. Images become image blocks; every other type (PDF, office docs, CSV,
|
|
7354
|
+
* JSON, …) becomes a file block — we don't filter by media type, so any binary can be fed to the
|
|
7355
|
+
* model. If the provider rejects an unsupported type the error surfaces at runtime, and the
|
|
7356
|
+
* workflow can filter the binary upstream.
|
|
7357
|
+
*/
|
|
7358
|
+
async resolveInlineBinaries(attachments, ctx) {
|
|
7359
|
+
const resolved = [];
|
|
7360
|
+
for (const attachment of attachments) {
|
|
7361
|
+
const bytes = await ctx.binary.getBytes(attachment);
|
|
7362
|
+
resolved.push({
|
|
7363
|
+
mediaType: attachment.mimeType,
|
|
7364
|
+
base64: Buffer.from(bytes).toString("base64"),
|
|
7365
|
+
...attachment.filename ? { filename: attachment.filename } : {}
|
|
7366
|
+
});
|
|
7367
|
+
}
|
|
7368
|
+
return resolved;
|
|
7116
7369
|
}
|
|
7117
7370
|
/**
|
|
7118
7371
|
* When `item.json.__source` matches an entry in `config.untrustedSources`
|
|
@@ -7226,6 +7479,7 @@ var AIAgent = class {
|
|
|
7226
7479
|
chatModel;
|
|
7227
7480
|
tools;
|
|
7228
7481
|
id;
|
|
7482
|
+
description;
|
|
7229
7483
|
retryPolicy;
|
|
7230
7484
|
guardrails;
|
|
7231
7485
|
inputSchema;
|
|
@@ -7233,12 +7487,16 @@ var AIAgent = class {
|
|
|
7233
7487
|
mcpServers;
|
|
7234
7488
|
pinnedMcpTools;
|
|
7235
7489
|
untrustedSources;
|
|
7490
|
+
passBinariesToModel;
|
|
7491
|
+
passToolBinariesToModel;
|
|
7492
|
+
binaries;
|
|
7236
7493
|
constructor(options) {
|
|
7237
7494
|
this.name = options.name;
|
|
7238
7495
|
this.messages = options.messages;
|
|
7239
7496
|
this.chatModel = options.chatModel;
|
|
7240
7497
|
this.tools = options.tools ?? [];
|
|
7241
7498
|
this.id = options.id;
|
|
7499
|
+
this.description = options.description;
|
|
7242
7500
|
this.retryPolicy = options.retryPolicy ?? __codemation_core.RetryPolicy.defaultForAiAgent;
|
|
7243
7501
|
this.guardrails = options.guardrails;
|
|
7244
7502
|
this.inputSchema = options.inputSchema;
|
|
@@ -7246,6 +7504,9 @@ var AIAgent = class {
|
|
|
7246
7504
|
this.mcpServers = options.mcpServers;
|
|
7247
7505
|
this.pinnedMcpTools = options.pinnedMcpTools;
|
|
7248
7506
|
this.untrustedSources = options.untrustedSources;
|
|
7507
|
+
this.passBinariesToModel = options.passBinariesToModel;
|
|
7508
|
+
this.passToolBinariesToModel = options.passToolBinariesToModel;
|
|
7509
|
+
this.binaries = options.binaries;
|
|
7249
7510
|
}
|
|
7250
7511
|
inspectorSummary() {
|
|
7251
7512
|
const rows = [];
|
|
@@ -7316,12 +7577,14 @@ var Assertion = class {
|
|
|
7316
7577
|
icon;
|
|
7317
7578
|
name;
|
|
7318
7579
|
id;
|
|
7580
|
+
description;
|
|
7319
7581
|
emitsAssertions = true;
|
|
7320
7582
|
assertions;
|
|
7321
7583
|
constructor(options) {
|
|
7322
7584
|
this.name = options.name ?? "Assertion";
|
|
7323
7585
|
this.id = options.id;
|
|
7324
7586
|
this.icon = options.icon ?? "lucide:check-circle";
|
|
7587
|
+
this.description = options.description;
|
|
7325
7588
|
this.assertions = options.assertions;
|
|
7326
7589
|
}
|
|
7327
7590
|
inspectorSummary() {
|
|
@@ -7373,6 +7636,7 @@ var Callback = class Callback {
|
|
|
7373
7636
|
icon = "lucide:braces";
|
|
7374
7637
|
emptyBatchExecution = "runOnce";
|
|
7375
7638
|
id;
|
|
7639
|
+
description;
|
|
7376
7640
|
retryPolicy;
|
|
7377
7641
|
nodeErrorHandler;
|
|
7378
7642
|
declaredOutputPorts;
|
|
@@ -7384,6 +7648,7 @@ var Callback = class Callback {
|
|
|
7384
7648
|
id: idOrOptions
|
|
7385
7649
|
} : idOrOptions;
|
|
7386
7650
|
this.id = resolvedOptions?.id;
|
|
7651
|
+
this.description = resolvedOptions?.description;
|
|
7387
7652
|
this.retryPolicy = resolvedOptions?.retryPolicy;
|
|
7388
7653
|
this.nodeErrorHandler = resolvedOptions?.nodeErrorHandler;
|
|
7389
7654
|
this.declaredOutputPorts = resolvedOptions?.declaredOutputPorts;
|
|
@@ -7585,10 +7850,12 @@ var HttpRequest = class {
|
|
|
7585
7850
|
type = HttpRequestNode;
|
|
7586
7851
|
execution = { hint: "local" };
|
|
7587
7852
|
icon = "lucide:globe";
|
|
7853
|
+
description;
|
|
7588
7854
|
constructor(name, args = {}, retryPolicy = __codemation_core.RetryPolicy.defaultForHttp) {
|
|
7589
7855
|
this.name = name;
|
|
7590
7856
|
this.args = args;
|
|
7591
7857
|
this.retryPolicy = retryPolicy;
|
|
7858
|
+
this.description = args.description;
|
|
7592
7859
|
}
|
|
7593
7860
|
get id() {
|
|
7594
7861
|
return this.args.id;
|
|
@@ -7683,10 +7950,14 @@ var Aggregate = class {
|
|
|
7683
7950
|
execution = { hint: "local" };
|
|
7684
7951
|
keepBinaries = true;
|
|
7685
7952
|
icon = "builtin:aggregate-rows";
|
|
7686
|
-
|
|
7953
|
+
id;
|
|
7954
|
+
description;
|
|
7955
|
+
constructor(name, aggregate, idOrOptions) {
|
|
7687
7956
|
this.name = name;
|
|
7688
7957
|
this.aggregate = aggregate;
|
|
7689
|
-
|
|
7958
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
7959
|
+
this.id = options?.id;
|
|
7960
|
+
this.description = options?.description;
|
|
7690
7961
|
}
|
|
7691
7962
|
inspectorSummary() {
|
|
7692
7963
|
const fnName = this.aggregate.name;
|
|
@@ -7717,10 +7988,14 @@ var Filter = class {
|
|
|
7717
7988
|
type = FilterNode;
|
|
7718
7989
|
execution = { hint: "local" };
|
|
7719
7990
|
icon = "lucide:filter";
|
|
7720
|
-
|
|
7991
|
+
id;
|
|
7992
|
+
description;
|
|
7993
|
+
constructor(name, predicate, idOrOptions) {
|
|
7721
7994
|
this.name = name;
|
|
7722
7995
|
this.predicate = predicate;
|
|
7723
|
-
|
|
7996
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
7997
|
+
this.id = options?.id;
|
|
7998
|
+
this.description = options?.description;
|
|
7724
7999
|
}
|
|
7725
8000
|
inspectorSummary() {
|
|
7726
8001
|
const fnName = this.predicate.name;
|
|
@@ -7795,10 +8070,14 @@ var If = class {
|
|
|
7795
8070
|
execution = { hint: "local" };
|
|
7796
8071
|
icon = "lucide:split@rot=90";
|
|
7797
8072
|
declaredOutputPorts = ["true", "false"];
|
|
7798
|
-
|
|
8073
|
+
id;
|
|
8074
|
+
description;
|
|
8075
|
+
constructor(name, predicate, idOrOptions) {
|
|
7799
8076
|
this.name = name;
|
|
7800
8077
|
this.predicate = predicate;
|
|
7801
|
-
|
|
8078
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8079
|
+
this.id = options?.id;
|
|
8080
|
+
this.description = options?.description;
|
|
7802
8081
|
}
|
|
7803
8082
|
inspectorSummary() {
|
|
7804
8083
|
const fnName = this.predicate.name;
|
|
@@ -7838,9 +8117,12 @@ var IsTestRun = class {
|
|
|
7838
8117
|
declaredOutputPorts = ["true", "false"];
|
|
7839
8118
|
name;
|
|
7840
8119
|
id;
|
|
7841
|
-
|
|
8120
|
+
description;
|
|
8121
|
+
constructor(name = "Is test run?", idOrOptions) {
|
|
7842
8122
|
this.name = name;
|
|
7843
|
-
|
|
8123
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8124
|
+
this.id = options?.id;
|
|
8125
|
+
this.description = options?.description;
|
|
7844
8126
|
}
|
|
7845
8127
|
};
|
|
7846
8128
|
|
|
@@ -7869,11 +8151,15 @@ var Switch = class {
|
|
|
7869
8151
|
execution = { hint: "local" };
|
|
7870
8152
|
icon = "lucide:git-branch-plus";
|
|
7871
8153
|
declaredOutputPorts;
|
|
7872
|
-
|
|
8154
|
+
id;
|
|
8155
|
+
description;
|
|
8156
|
+
constructor(name, cfg, idOrOptions) {
|
|
7873
8157
|
this.name = name;
|
|
7874
8158
|
this.cfg = cfg;
|
|
7875
|
-
this.id = id;
|
|
7876
8159
|
this.declaredOutputPorts = [...new Set([...cfg.cases, cfg.defaultCase])].sort();
|
|
8160
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8161
|
+
this.id = options?.id;
|
|
8162
|
+
this.description = options?.description;
|
|
7877
8163
|
}
|
|
7878
8164
|
inspectorSummary() {
|
|
7879
8165
|
const rows = [{
|
|
@@ -7912,10 +8198,14 @@ var Split = class {
|
|
|
7912
8198
|
*/
|
|
7913
8199
|
continueWhenEmptyOutput = true;
|
|
7914
8200
|
icon = "builtin:split-rows";
|
|
7915
|
-
|
|
8201
|
+
id;
|
|
8202
|
+
description;
|
|
8203
|
+
constructor(name, getElements, idOrOptions) {
|
|
7916
8204
|
this.name = name;
|
|
7917
8205
|
this.getElements = getElements;
|
|
7918
|
-
|
|
8206
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8207
|
+
this.id = options?.id;
|
|
8208
|
+
this.description = options?.description;
|
|
7919
8209
|
}
|
|
7920
8210
|
inspectorSummary() {
|
|
7921
8211
|
const fnName = this.getElements.name;
|
|
@@ -7973,14 +8263,17 @@ var CronTrigger = class {
|
|
|
7973
8263
|
type = CronTriggerNode;
|
|
7974
8264
|
icon = "lucide:clock";
|
|
7975
8265
|
id;
|
|
7976
|
-
|
|
8266
|
+
description;
|
|
8267
|
+
constructor(name, args, idOrOptions) {
|
|
7977
8268
|
this.name = name;
|
|
7978
8269
|
this.args = args;
|
|
7979
8270
|
new croner.Cron(args.schedule, {
|
|
7980
8271
|
paused: true,
|
|
7981
8272
|
timezone: args.timezone
|
|
7982
8273
|
});
|
|
7983
|
-
|
|
8274
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8275
|
+
this.id = options?.id;
|
|
8276
|
+
this.description = options?.description;
|
|
7984
8277
|
}
|
|
7985
8278
|
get schedule() {
|
|
7986
8279
|
return this.args.schedule;
|
|
@@ -8034,20 +8327,21 @@ var ManualTrigger = class ManualTrigger {
|
|
|
8034
8327
|
icon = "lucide:play";
|
|
8035
8328
|
defaultItems;
|
|
8036
8329
|
id;
|
|
8330
|
+
description;
|
|
8037
8331
|
/** Manual runs often emit an empty batch; still schedule downstream by default. */
|
|
8038
8332
|
continueWhenEmptyOutput = true;
|
|
8039
|
-
constructor(name = "Manual trigger", defaultItemsOrId,
|
|
8333
|
+
constructor(name = "Manual trigger", defaultItemsOrId, idOrOptions) {
|
|
8040
8334
|
this.name = name;
|
|
8041
8335
|
this.defaultItems = ManualTrigger.resolveDefaultItems(defaultItemsOrId);
|
|
8042
|
-
|
|
8336
|
+
const trailing = idOrOptions ?? (typeof defaultItemsOrId === "string" ? defaultItemsOrId : void 0);
|
|
8337
|
+
const options = typeof trailing === "string" ? { id: trailing } : trailing ?? {};
|
|
8338
|
+
this.id = options.id;
|
|
8339
|
+
this.description = options.description;
|
|
8043
8340
|
}
|
|
8044
8341
|
static resolveDefaultItems(value) {
|
|
8045
8342
|
if (typeof value === "string" || value === void 0) return;
|
|
8046
8343
|
return this.itemsInputNormalizer.normalize(value);
|
|
8047
8344
|
}
|
|
8048
|
-
static resolveId(value, id) {
|
|
8049
|
-
return typeof value === "string" ? value : id;
|
|
8050
|
-
}
|
|
8051
8345
|
inspectorSummary() {
|
|
8052
8346
|
const rows = [{
|
|
8053
8347
|
label: "Trigger",
|
|
@@ -8093,11 +8387,13 @@ var MapData = class {
|
|
|
8093
8387
|
continueWhenEmptyOutput = true;
|
|
8094
8388
|
icon = "lucide:square-pen";
|
|
8095
8389
|
keepBinaries;
|
|
8390
|
+
description;
|
|
8096
8391
|
constructor(name, map, options = {}) {
|
|
8097
8392
|
this.name = name;
|
|
8098
8393
|
this.map = map;
|
|
8099
8394
|
this.options = options;
|
|
8100
8395
|
this.keepBinaries = options.keepBinaries ?? true;
|
|
8396
|
+
this.description = options.description;
|
|
8101
8397
|
}
|
|
8102
8398
|
get id() {
|
|
8103
8399
|
return this.options.id;
|
|
@@ -8170,10 +8466,14 @@ var Merge = class {
|
|
|
8170
8466
|
kind = "node";
|
|
8171
8467
|
type = MergeNode;
|
|
8172
8468
|
icon = "lucide:merge@rot=90";
|
|
8173
|
-
|
|
8469
|
+
id;
|
|
8470
|
+
description;
|
|
8471
|
+
constructor(name, cfg = { mode: "passThrough" }, idOrOptions) {
|
|
8174
8472
|
this.name = name;
|
|
8175
8473
|
this.cfg = cfg;
|
|
8176
|
-
|
|
8474
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8475
|
+
this.id = options?.id;
|
|
8476
|
+
this.description = options?.description;
|
|
8177
8477
|
}
|
|
8178
8478
|
inspectorSummary() {
|
|
8179
8479
|
const rows = [{
|
|
@@ -8206,9 +8506,13 @@ var NoOp = class {
|
|
|
8206
8506
|
type = NoOpNode;
|
|
8207
8507
|
execution = { hint: "local" };
|
|
8208
8508
|
icon = "lucide:circle-dashed";
|
|
8209
|
-
|
|
8509
|
+
id;
|
|
8510
|
+
description;
|
|
8511
|
+
constructor(name = "NoOp", idOrOptions) {
|
|
8210
8512
|
this.name = name;
|
|
8211
|
-
|
|
8513
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8514
|
+
this.id = options?.id;
|
|
8515
|
+
this.description = options?.description;
|
|
8212
8516
|
}
|
|
8213
8517
|
};
|
|
8214
8518
|
|
|
@@ -8274,12 +8578,16 @@ var SubWorkflow = class {
|
|
|
8274
8578
|
kind = "node";
|
|
8275
8579
|
type = SubWorkflowNode;
|
|
8276
8580
|
icon = "lucide:workflow";
|
|
8277
|
-
|
|
8581
|
+
id;
|
|
8582
|
+
description;
|
|
8583
|
+
constructor(name, workflowId, upstreamRefs, startAt, idOrOptions) {
|
|
8278
8584
|
this.name = name;
|
|
8279
8585
|
this.workflowId = workflowId;
|
|
8280
8586
|
this.upstreamRefs = upstreamRefs;
|
|
8281
8587
|
this.startAt = startAt;
|
|
8282
|
-
|
|
8588
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8589
|
+
this.id = options?.id;
|
|
8590
|
+
this.description = options?.description;
|
|
8283
8591
|
}
|
|
8284
8592
|
inspectorSummary() {
|
|
8285
8593
|
const rows = [{
|
|
@@ -8389,10 +8697,14 @@ var Wait = class {
|
|
|
8389
8697
|
/** Pass-through empty batches should still advance to downstream nodes. */
|
|
8390
8698
|
continueWhenEmptyOutput = true;
|
|
8391
8699
|
icon = "lucide:hourglass";
|
|
8392
|
-
|
|
8700
|
+
id;
|
|
8701
|
+
description;
|
|
8702
|
+
constructor(name, milliseconds, idOrOptions) {
|
|
8393
8703
|
this.name = name;
|
|
8394
8704
|
this.milliseconds = milliseconds;
|
|
8395
|
-
|
|
8705
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8706
|
+
this.id = options?.id;
|
|
8707
|
+
this.description = options?.description;
|
|
8396
8708
|
}
|
|
8397
8709
|
inspectorSummary() {
|
|
8398
8710
|
const seconds = this.milliseconds / 1e3;
|
|
@@ -8447,11 +8759,15 @@ var WebhookTrigger = class WebhookTrigger {
|
|
|
8447
8759
|
kind = "trigger";
|
|
8448
8760
|
type = WebhookTriggerNode;
|
|
8449
8761
|
icon = "lucide:globe";
|
|
8450
|
-
|
|
8762
|
+
id;
|
|
8763
|
+
description;
|
|
8764
|
+
constructor(name, args, handler = WebhookTrigger.defaultHandler, idOrOptions) {
|
|
8451
8765
|
this.name = name;
|
|
8452
8766
|
this.args = args;
|
|
8453
8767
|
this.handler = handler;
|
|
8454
|
-
|
|
8768
|
+
const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
|
|
8769
|
+
this.id = options?.id;
|
|
8770
|
+
this.description = options?.description;
|
|
8455
8771
|
}
|
|
8456
8772
|
get endpointKey() {
|
|
8457
8773
|
return this.args.endpointKey;
|
|
@@ -8508,11 +8824,21 @@ function createWorkflowBuilder(meta$2) {
|
|
|
8508
8824
|
|
|
8509
8825
|
//#endregion
|
|
8510
8826
|
//#region src/workflowAuthoring/WorkflowChatModelFactory.types.ts
|
|
8827
|
+
const VALID_COMPLEXITY = new Set([
|
|
8828
|
+
"low",
|
|
8829
|
+
"medium",
|
|
8830
|
+
"high",
|
|
8831
|
+
"xhigh"
|
|
8832
|
+
]);
|
|
8511
8833
|
var WorkflowChatModelFactory = class {
|
|
8512
8834
|
static create(model) {
|
|
8513
8835
|
if (typeof model !== "string") return model;
|
|
8514
8836
|
const [provider, resolvedModel] = model.includes(":") ? model.split(":", 2) : ["openai", model];
|
|
8515
|
-
if (provider === "codemation-managed")
|
|
8837
|
+
if (provider === "codemation-managed") {
|
|
8838
|
+
const complexity = resolvedModel ?? "medium";
|
|
8839
|
+
if (!VALID_COMPLEXITY.has(complexity)) throw new Error(`Invalid managed complexity "${complexity}". Must be one of: low, medium, high, xhigh.`);
|
|
8840
|
+
return new CodemationChatModelConfig("Codemation Managed", complexity);
|
|
8841
|
+
}
|
|
8516
8842
|
if (provider !== "openai") throw new Error(`Unsupported workflow().agent() model provider "${provider}".`);
|
|
8517
8843
|
return new OpenAIChatModelConfig("OpenAI", resolvedModel);
|
|
8518
8844
|
}
|
|
@@ -9280,7 +9606,6 @@ Object.defineProperty(exports, 'IsTestRunNode', {
|
|
|
9280
9606
|
return IsTestRunNode;
|
|
9281
9607
|
}
|
|
9282
9608
|
});
|
|
9283
|
-
exports.ManagedModelFetcher = ManagedModelFetcher;
|
|
9284
9609
|
exports.ManualTrigger = ManualTrigger;
|
|
9285
9610
|
Object.defineProperty(exports, 'ManualTriggerNode', {
|
|
9286
9611
|
enumerable: true,
|