@codemation/core-nodes 0.10.2 → 0.12.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/dist/index.cjs +259 -100
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +191 -66
  5. package/dist/index.d.ts +192 -67
  6. package/dist/index.js +259 -97
  7. package/dist/index.js.map +1 -1
  8. package/dist/metadata.json +1 -1
  9. package/package.json +3 -2
  10. package/src/chatModels/CodemationChatModelConfig.ts +9 -21
  11. package/src/chatModels/CodemationChatModelFactory.ts +12 -9
  12. package/src/chatModels/OpenAIChatModelFactory.ts +3 -2
  13. package/src/index.ts +1 -1
  14. package/src/nodes/AIAgentConfig.ts +28 -0
  15. package/src/nodes/AIAgentNode.ts +77 -13
  16. package/src/nodes/AgentBinaryContentFactory.ts +74 -0
  17. package/src/nodes/CallbackNodeFactory.ts +9 -6
  18. package/src/nodes/CronTriggerFactory.ts +6 -2
  19. package/src/nodes/DeferredMetaToolStrategy.ts +8 -2
  20. package/src/nodes/ManualTriggerFactory.ts +15 -11
  21. package/src/nodes/WebhookTriggerFactory.ts +9 -2
  22. package/src/nodes/aggregate.ts +9 -2
  23. package/src/nodes/assertion.ts +3 -0
  24. package/src/nodes/filter.ts +9 -2
  25. package/src/nodes/httpRequest.ts +6 -1
  26. package/src/nodes/if.ts +9 -2
  27. package/src/nodes/isTestRun.ts +6 -2
  28. package/src/nodes/mapData.ts +4 -2
  29. package/src/nodes/merge.ts +9 -2
  30. package/src/nodes/noOp.ts +9 -2
  31. package/src/nodes/nodeOptions.types.ts +12 -0
  32. package/src/nodes/split.ts +9 -2
  33. package/src/nodes/subWorkflow.ts +9 -2
  34. package/src/nodes/switch.ts +7 -1
  35. package/src/nodes/wait.ts +9 -2
  36. package/src/workflowAuthoring/WorkflowChatModelFactory.types.ts +8 -2
  37. package/src/chatModels/ManagedModelFetcher.ts +0 -23
package/dist/index.js CHANGED
@@ -1,9 +1,7 @@
1
1
  import { AgentConfigInspector, AgentConnectionNodeCollector, AgentGuardrailDefaults, AgentMessageConfigNormalizer, CallableToolConfig, ChildExecutionScopeFactory, CodemationTelemetryAttributeNames, CodemationTelemetryMetricNames, ConnectionInvocationIdFactory, ConnectionNodeIdFactory, CoreTokens, DefinedNodeRegistry, GenAiTelemetryAttributeNames, InboxChannelResolverToken, ItemExprResolver, ItemsInputNormalizer, NodeBackedToolConfig, NodeOutputNormalizer, RetryPolicy, RunnableOutputBehaviorResolver, SuspensionRequest, WorkflowBuilder, chatModel, defineCredential, defineHumanApprovalNode, defineNode, emitPorts, getOriginIndexFromItem, inject, injectable, isPortsEmission, node } from "@codemation/core";
2
2
  import dns from "node:dns/promises";
3
- import { createOpenAI } from "@ai-sdk/openai";
4
3
  import { CredentialResolverFactory } from "@codemation/core/bootstrap";
5
4
  import { createHash, createHmac, randomBytes } from "node:crypto";
6
- import { Output, generateText, jsonSchema } from "ai";
7
5
  import { Cron } from "croner";
8
6
 
9
7
  //#region src/credentials/ApiKeyCredentialType.ts
@@ -674,6 +672,7 @@ function __decorate(decorators, target, key, desc) {
674
672
  let OpenAIChatModelFactory = class OpenAIChatModelFactory$1 {
675
673
  async create(args) {
676
674
  const session = await args.ctx.getCredential(args.config.credentialSlotKey);
675
+ const { createOpenAI } = await import("@ai-sdk/openai");
677
676
  return {
678
677
  languageModel: createOpenAI({
679
678
  apiKey: session.apiKey,
@@ -4418,27 +4417,24 @@ function buildHmacAuthHeader(workspaceId, pairingSecret, method, url, body, over
4418
4417
  //#endregion
4419
4418
  //#region src/chatModels/CodemationChatModelFactory.ts
4420
4419
  let CodemationChatModelFactory = class CodemationChatModelFactory$1 {
4421
- create(args) {
4420
+ async create(args) {
4422
4421
  const gatewayUrl = process.env["LLM_GATEWAY_URL"];
4423
4422
  if (!gatewayUrl) throw new Error("Codemation managed AI not available in this environment (LLM_GATEWAY_URL is not set).");
4424
4423
  const workspaceId = process.env["WORKSPACE_ID"];
4425
4424
  const pairingSecret = process.env["WORKSPACE_PAIRING_SECRET"];
4426
4425
  if (!workspaceId || !pairingSecret) throw new Error("Codemation managed AI not available in this environment (workspace pairing is not configured).");
4427
4426
  const hmacFetch = managedHmacFetchFactory(workspaceId, pairingSecret);
4428
- const languageModel = createOpenAI({
4429
- baseURL: `${gatewayUrl}/v1`,
4430
- apiKey: "codemation-managed",
4431
- fetch: hmacFetch
4432
- }).chat(args.config.model);
4433
- return Promise.resolve({
4434
- languageModel,
4435
- modelName: args.config.model,
4427
+ const { createAnthropic } = await import("@ai-sdk/anthropic");
4428
+ return {
4429
+ languageModel: createAnthropic({
4430
+ baseURL: `${gatewayUrl}/v1`,
4431
+ apiKey: "codemation-managed",
4432
+ fetch: hmacFetch
4433
+ })(args.config.complexity),
4434
+ modelName: args.config.complexity,
4436
4435
  provider: "codemation-managed",
4437
- defaultCallOptions: {
4438
- maxOutputTokens: args.config.options?.maxTokens,
4439
- temperature: args.config.options?.temperature
4440
- }
4441
- });
4436
+ defaultCallOptions: { maxOutputTokens: args.config.options?.maxTokens }
4437
+ };
4442
4438
  }
4443
4439
  };
4444
4440
  CodemationChatModelFactory = __decorate([chatModel({ packageName: "@codemation/core-nodes" })], CodemationChatModelFactory);
@@ -4450,11 +4446,11 @@ var CodemationChatModelConfig = class {
4450
4446
  presentation;
4451
4447
  provider = "codemation-managed";
4452
4448
  modelName;
4453
- constructor(name, model, presentationIn, options) {
4449
+ constructor(name, complexity, presentationIn, options) {
4454
4450
  this.name = name;
4455
- this.model = model;
4451
+ this.complexity = complexity;
4456
4452
  this.options = options;
4457
- this.modelName = model;
4453
+ this.modelName = complexity;
4458
4454
  this.presentation = presentationIn ?? {
4459
4455
  icon: "lucide:bot",
4460
4456
  label: name
@@ -4462,28 +4458,6 @@ var CodemationChatModelConfig = class {
4462
4458
  }
4463
4459
  };
4464
4460
 
4465
- //#endregion
4466
- //#region src/chatModels/ManagedModelFetcher.ts
4467
- /**
4468
- * Fetches the active platform-managed model allowlist from the CP.
4469
- * Reads CONTROL_PLANE_URL from the workspace process env.
4470
- * Returns an empty array if the env var is absent or the fetch fails.
4471
- * Cache the result per session — the allowlist changes infrequently.
4472
- */
4473
- var ManagedModelFetcher = class {
4474
- async fetch() {
4475
- const cpUrl = process.env["CONTROL_PLANE_URL"];
4476
- if (!cpUrl) return [];
4477
- try {
4478
- const res = await globalThis.fetch(`${cpUrl}/api/llm/managed-models`);
4479
- if (!res.ok) return [];
4480
- return await res.json();
4481
- } catch {
4482
- return [];
4483
- }
4484
- }
4485
- };
4486
-
4487
4461
  //#endregion
4488
4462
  //#region src/nodes/AgentMessageFactory.ts
4489
4463
  /**
@@ -5852,6 +5826,63 @@ AgentToolExecutionCoordinator = __decorate([
5852
5826
  __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])
5853
5827
  ], AgentToolExecutionCoordinator);
5854
5828
 
5829
+ //#endregion
5830
+ //#region src/nodes/AgentBinaryContentFactory.ts
5831
+ /**
5832
+ * Turns resolved file binaries into native AI SDK multimodal content parts and merges them into the
5833
+ * agent prompt. Images (`image/*`) become {@link ImagePart}s; every other type (PDFs, office docs,
5834
+ * CSV, JSON, …) becomes a {@link FilePart}. The provider maps these to its wire-level `image` /
5835
+ * `document` blocks; an unsupported file type surfaces as a provider error at runtime.
5836
+ *
5837
+ * Parts are appended to the LAST user message so the binary travels alongside the author's prompt
5838
+ * text (preserving any untrusted-source preamble that already wrapped that text). When no user
5839
+ * message exists, a new user message carrying only the binaries is appended.
5840
+ */
5841
+ var AgentBinaryContentFactory = class AgentBinaryContentFactory {
5842
+ static toContentPart(binary) {
5843
+ if (binary.mediaType.startsWith("image/")) return {
5844
+ type: "image",
5845
+ image: binary.base64,
5846
+ mediaType: binary.mediaType
5847
+ };
5848
+ return {
5849
+ type: "file",
5850
+ data: binary.base64,
5851
+ mediaType: binary.mediaType,
5852
+ ...binary.filename ? { filename: binary.filename } : {}
5853
+ };
5854
+ }
5855
+ static withBinaries(messages, binaries) {
5856
+ if (binaries.length === 0) return messages;
5857
+ const parts = binaries.map((binary) => AgentBinaryContentFactory.toContentPart(binary));
5858
+ const lastUserIndex = AgentBinaryContentFactory.lastUserMessageIndex(messages);
5859
+ if (lastUserIndex === -1) {
5860
+ const appended = {
5861
+ role: "user",
5862
+ content: parts
5863
+ };
5864
+ return [...messages, appended];
5865
+ }
5866
+ const next = [...messages];
5867
+ next[lastUserIndex] = AgentBinaryContentFactory.appendPartsToUserMessage(messages[lastUserIndex], parts);
5868
+ return next;
5869
+ }
5870
+ static lastUserMessageIndex(messages) {
5871
+ for (let index = messages.length - 1; index >= 0; index--) if (messages[index]?.role === "user") return index;
5872
+ return -1;
5873
+ }
5874
+ static appendPartsToUserMessage(message, parts) {
5875
+ const existing = typeof message.content === "string" ? message.content.length > 0 ? [{
5876
+ type: "text",
5877
+ text: message.content
5878
+ }] : [] : message.content;
5879
+ return {
5880
+ ...message,
5881
+ content: [...existing, ...parts]
5882
+ };
5883
+ }
5884
+ };
5885
+
5855
5886
  //#endregion
5856
5887
  //#region src/nodes/NodeBackedToolRuntime.ts
5857
5888
  var _ref$1, _ref2$1, _ref3$1, _ref4$1;
@@ -6050,11 +6081,18 @@ var DeferredMetaToolStrategy = class {
6050
6081
  mcpEntries = [];
6051
6082
  toolsByServerId = /* @__PURE__ */ new Map();
6052
6083
  foundToolIds = /* @__PURE__ */ new Set();
6084
+ /**
6085
+ * `jsonSchema` from the `ai` SDK, loaded lazily in {@link initialize} so the SDK
6086
+ * (~28MB RSS) stays off the boot path. `initialize` always runs before the sync
6087
+ * `getToolsForTurn` → `buildFindToolsDefinition` path, so this is set before use.
6088
+ */
6089
+ jsonSchema;
6053
6090
  constructor(bm25, warnFn) {
6054
6091
  this.bm25 = bm25;
6055
6092
  this.warnFn = warnFn;
6056
6093
  }
6057
6094
  async initialize(input) {
6095
+ this.jsonSchema = (await import("ai")).jsonSchema;
6058
6096
  this.nodeBackedTools = { ...input.nodeBackedTools };
6059
6097
  const pinnedIds = input.pinnedMcpTools ?? [];
6060
6098
  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}.`);
@@ -6142,25 +6180,26 @@ var DeferredMetaToolStrategy = class {
6142
6180
  return [...this.foundToolIds];
6143
6181
  }
6144
6182
  buildFindToolsDefinition() {
6183
+ const inputSchemaRecord = {
6184
+ type: "object",
6185
+ properties: {
6186
+ query: {
6187
+ type: "string",
6188
+ description: "Natural language description of what you want to do."
6189
+ },
6190
+ limit: {
6191
+ type: "integer",
6192
+ minimum: 1,
6193
+ maximum: 10,
6194
+ description: `Maximum number of tools to return (default ${FIND_TOOLS_DEFAULT_LIMIT}).`
6195
+ }
6196
+ },
6197
+ required: ["query"],
6198
+ additionalProperties: false
6199
+ };
6145
6200
  return {
6146
6201
  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.",
6147
- inputSchema: jsonSchema({
6148
- type: "object",
6149
- properties: {
6150
- query: {
6151
- type: "string",
6152
- description: "Natural language description of what you want to do."
6153
- },
6154
- limit: {
6155
- type: "integer",
6156
- minimum: 1,
6157
- maximum: 10,
6158
- description: `Maximum number of tools to return (default ${FIND_TOOLS_DEFAULT_LIMIT}).`
6159
- }
6160
- },
6161
- required: ["query"],
6162
- additionalProperties: false
6163
- })
6202
+ inputSchema: this.jsonSchema(inputSchemaRecord)
6164
6203
  };
6165
6204
  }
6166
6205
  };
@@ -6194,6 +6233,13 @@ let AIAgentNode = class AIAgentNode$1 {
6194
6233
  inputSchema = unknown();
6195
6234
  connectionCredentialExecutionContextFactory;
6196
6235
  preparedByExecutionContext = /* @__PURE__ */ new WeakMap();
6236
+ /**
6237
+ * The `ai` SDK, loaded lazily in {@link execute} so the SDK (~28MB RSS) stays
6238
+ * off the boot path — non-AI workflows never load it. Every path runs through
6239
+ * `execute` → `ensureAiSdk` before any sync helper touches `this.aiSdk`.
6240
+ */
6241
+ aiSdk;
6242
+ aiSdkPromise = null;
6197
6243
  constructor(nodeResolver, credentialSessions, nodeBackedToolRuntime, executionHelpers, structuredOutputRunner, toolExecutionCoordinator, toolLoadingStrategyFactory, agentMcpIntegration) {
6198
6244
  this.nodeResolver = nodeResolver;
6199
6245
  this.nodeBackedToolRuntime = nodeBackedToolRuntime;
@@ -6206,6 +6252,7 @@ let AIAgentNode = class AIAgentNode$1 {
6206
6252
  }
6207
6253
  async execute(args) {
6208
6254
  const { ctx } = args;
6255
+ await this.ensureAiSdk();
6209
6256
  if (ctx.resumeContext) return this.executeResumed(args, ctx.resumeContext);
6210
6257
  const prepared = await this.getOrPrepareExecution(ctx);
6211
6258
  const itemWithMappedJson = {
@@ -6214,6 +6261,10 @@ let AIAgentNode = class AIAgentNode$1 {
6214
6261
  };
6215
6262
  return (await this.runAgentForItem(prepared, itemWithMappedJson, args.itemIndex, args.items)).json;
6216
6263
  }
6264
+ /** Load the `ai` SDK once per node instance (cached promise guards concurrent items). */
6265
+ async ensureAiSdk() {
6266
+ this.aiSdk = await (this.aiSdkPromise ??= import("ai"));
6267
+ }
6217
6268
  /**
6218
6269
  * Resume path: re-enters the agent loop after a HITL suspension.
6219
6270
  * Reconstructs the conversation from the checkpoint, injects the human decision
@@ -6356,7 +6407,7 @@ let AIAgentNode = class AIAgentNode$1 {
6356
6407
  const { ctx } = prepared;
6357
6408
  const itemInputsByPort = AgentItemPortMap.fromItem(item);
6358
6409
  const itemScopedTools = this.createItemScopedTools(prepared.resolvedTools, ctx, item, itemIndex, items);
6359
- const conversation = [...this.createPromptMessages(item, itemIndex, items, ctx)];
6410
+ const conversation = [...await this.createPromptMessages(item, itemIndex, items, ctx)];
6360
6411
  if (ctx.config.outputSchema && itemScopedTools.length === 0) {
6361
6412
  const structuredOutput = await this.structuredOutputRunner.resolve({
6362
6413
  model: prepared.model,
@@ -6600,7 +6651,7 @@ let AIAgentNode = class AIAgentNode$1 {
6600
6651
  const description = this.resolveHumanApprovalBehavior(entry.config) !== void 0 ? `${baseDescription} ${HITL_SOLO_CONSTRAINT_SENTENCE}` : baseDescription;
6601
6652
  toolSet[entry.config.name] = {
6602
6653
  description,
6603
- inputSchema: jsonSchema(schemaRecord)
6654
+ inputSchema: this.aiSdk.jsonSchema(schemaRecord)
6604
6655
  };
6605
6656
  }
6606
6657
  return toolSet;
@@ -6631,7 +6682,7 @@ let AIAgentNode = class AIAgentNode$1 {
6631
6682
  const description = entry.humanApproval !== void 0 && baseDescription !== void 0 ? `${baseDescription} ${HITL_SOLO_CONSTRAINT_SENTENCE}` : entry.humanApproval !== void 0 ? HITL_SOLO_CONSTRAINT_SENTENCE : baseDescription;
6632
6683
  toolSet[entry.config.name] = {
6633
6684
  description,
6634
- inputSchema: jsonSchema(schemaRecord)
6685
+ inputSchema: this.aiSdk.jsonSchema(schemaRecord)
6635
6686
  };
6636
6687
  }
6637
6688
  return toolSet;
@@ -6683,7 +6734,7 @@ let AIAgentNode = class AIAgentNode$1 {
6683
6734
  });
6684
6735
  try {
6685
6736
  const callOptions = this.resolveCallOptions(model, guardrails.modelInvocationOptions);
6686
- const result = await generateText({
6737
+ const result = await this.aiSdk.generateText({
6687
6738
  model: model.languageModel,
6688
6739
  messages: [...messages],
6689
6740
  tools,
@@ -6802,8 +6853,8 @@ let AIAgentNode = class AIAgentNode$1 {
6802
6853
  schemaName: structuredOptions?.schemaName ?? "structured_output",
6803
6854
  requireObjectRoot: true
6804
6855
  }) : schema;
6805
- const outputSchema = Output.object({ schema: jsonSchema(schemaRecord) });
6806
- const result = await generateText({
6856
+ const outputSchema = this.aiSdk.Output.object({ schema: this.aiSdk.jsonSchema(schemaRecord) });
6857
+ const result = await this.aiSdk.generateText({
6807
6858
  model: model.languageModel,
6808
6859
  messages: [...messages],
6809
6860
  experimental_output: outputSchema,
@@ -7074,7 +7125,7 @@ let AIAgentNode = class AIAgentNode$1 {
7074
7125
  const json = JSON.stringify(value);
7075
7126
  return JSON.parse(json);
7076
7127
  }
7077
- createPromptMessages(item, itemIndex, items, ctx) {
7128
+ async createPromptMessages(item, itemIndex, items, ctx) {
7078
7129
  const messages = AgentMessageConfigNormalizer.resolveFromInputOrConfig(item.json, ctx.config, {
7079
7130
  item,
7080
7131
  itemIndex,
@@ -7082,7 +7133,47 @@ let AIAgentNode = class AIAgentNode$1 {
7082
7133
  ctx
7083
7134
  });
7084
7135
  const wrapped = this.wrapUntrustedSourceMessages(messages, item, ctx.config);
7085
- return AgentMessageFactory.createPromptMessages(wrapped);
7136
+ const promptMessages = AgentMessageFactory.createPromptMessages(wrapped);
7137
+ if (ctx.config.passBinariesToModel === false) return promptMessages;
7138
+ const attachments = this.selectBinaryAttachments(item, itemIndex, items, ctx);
7139
+ const binaries = await this.resolveInlineBinaries(attachments, ctx);
7140
+ return AgentBinaryContentFactory.withBinaries(promptMessages, binaries);
7141
+ }
7142
+ /**
7143
+ * Picks which attachments feed the passdown. When the author supplies `config.binaries`
7144
+ * (a static array or a per-item function — e.g. to forward binaries from an earlier node),
7145
+ * those replace the current item's attachments; otherwise the current item's `item.binary`
7146
+ * is used.
7147
+ */
7148
+ selectBinaryAttachments(item, itemIndex, items, ctx) {
7149
+ const manual = ctx.config.binaries;
7150
+ if (manual !== void 0) return typeof manual === "function" ? manual({
7151
+ item,
7152
+ itemIndex,
7153
+ items,
7154
+ ctx
7155
+ }) : manual;
7156
+ return item.binary ? Object.values(item.binary) : [];
7157
+ }
7158
+ /**
7159
+ * Reads every attachment through `ctx.binary` (storage-backed, by reference — never base64 on
7160
+ * `item.json`) and resolves it to inline base64 so the agent can pass it to the chat model as a
7161
+ * native multimodal block. Images become image blocks; every other type (PDF, office docs, CSV,
7162
+ * JSON, …) becomes a file block — we don't filter by media type, so any binary can be fed to the
7163
+ * model. If the provider rejects an unsupported type the error surfaces at runtime, and the
7164
+ * workflow can filter the binary upstream.
7165
+ */
7166
+ async resolveInlineBinaries(attachments, ctx) {
7167
+ const resolved = [];
7168
+ for (const attachment of attachments) {
7169
+ const bytes = await ctx.binary.getBytes(attachment);
7170
+ resolved.push({
7171
+ mediaType: attachment.mimeType,
7172
+ base64: Buffer.from(bytes).toString("base64"),
7173
+ ...attachment.filename ? { filename: attachment.filename } : {}
7174
+ });
7175
+ }
7176
+ return resolved;
7086
7177
  }
7087
7178
  /**
7088
7179
  * When `item.json.__source` matches an entry in `config.untrustedSources`
@@ -7196,6 +7287,7 @@ var AIAgent = class {
7196
7287
  chatModel;
7197
7288
  tools;
7198
7289
  id;
7290
+ description;
7199
7291
  retryPolicy;
7200
7292
  guardrails;
7201
7293
  inputSchema;
@@ -7203,12 +7295,15 @@ var AIAgent = class {
7203
7295
  mcpServers;
7204
7296
  pinnedMcpTools;
7205
7297
  untrustedSources;
7298
+ passBinariesToModel;
7299
+ binaries;
7206
7300
  constructor(options) {
7207
7301
  this.name = options.name;
7208
7302
  this.messages = options.messages;
7209
7303
  this.chatModel = options.chatModel;
7210
7304
  this.tools = options.tools ?? [];
7211
7305
  this.id = options.id;
7306
+ this.description = options.description;
7212
7307
  this.retryPolicy = options.retryPolicy ?? RetryPolicy.defaultForAiAgent;
7213
7308
  this.guardrails = options.guardrails;
7214
7309
  this.inputSchema = options.inputSchema;
@@ -7216,6 +7311,8 @@ var AIAgent = class {
7216
7311
  this.mcpServers = options.mcpServers;
7217
7312
  this.pinnedMcpTools = options.pinnedMcpTools;
7218
7313
  this.untrustedSources = options.untrustedSources;
7314
+ this.passBinariesToModel = options.passBinariesToModel;
7315
+ this.binaries = options.binaries;
7219
7316
  }
7220
7317
  inspectorSummary() {
7221
7318
  const rows = [];
@@ -7286,12 +7383,14 @@ var Assertion = class {
7286
7383
  icon;
7287
7384
  name;
7288
7385
  id;
7386
+ description;
7289
7387
  emitsAssertions = true;
7290
7388
  assertions;
7291
7389
  constructor(options) {
7292
7390
  this.name = options.name ?? "Assertion";
7293
7391
  this.id = options.id;
7294
7392
  this.icon = options.icon ?? "lucide:check-circle";
7393
+ this.description = options.description;
7295
7394
  this.assertions = options.assertions;
7296
7395
  }
7297
7396
  inspectorSummary() {
@@ -7343,6 +7442,7 @@ var Callback = class Callback {
7343
7442
  icon = "lucide:braces";
7344
7443
  emptyBatchExecution = "runOnce";
7345
7444
  id;
7445
+ description;
7346
7446
  retryPolicy;
7347
7447
  nodeErrorHandler;
7348
7448
  declaredOutputPorts;
@@ -7354,6 +7454,7 @@ var Callback = class Callback {
7354
7454
  id: idOrOptions
7355
7455
  } : idOrOptions;
7356
7456
  this.id = resolvedOptions?.id;
7457
+ this.description = resolvedOptions?.description;
7357
7458
  this.retryPolicy = resolvedOptions?.retryPolicy;
7358
7459
  this.nodeErrorHandler = resolvedOptions?.nodeErrorHandler;
7359
7460
  this.declaredOutputPorts = resolvedOptions?.declaredOutputPorts;
@@ -7555,10 +7656,12 @@ var HttpRequest = class {
7555
7656
  type = HttpRequestNode;
7556
7657
  execution = { hint: "local" };
7557
7658
  icon = "lucide:globe";
7659
+ description;
7558
7660
  constructor(name, args = {}, retryPolicy = RetryPolicy.defaultForHttp) {
7559
7661
  this.name = name;
7560
7662
  this.args = args;
7561
7663
  this.retryPolicy = retryPolicy;
7664
+ this.description = args.description;
7562
7665
  }
7563
7666
  get id() {
7564
7667
  return this.args.id;
@@ -7653,10 +7756,14 @@ var Aggregate = class {
7653
7756
  execution = { hint: "local" };
7654
7757
  keepBinaries = true;
7655
7758
  icon = "builtin:aggregate-rows";
7656
- constructor(name, aggregate, id) {
7759
+ id;
7760
+ description;
7761
+ constructor(name, aggregate, idOrOptions) {
7657
7762
  this.name = name;
7658
7763
  this.aggregate = aggregate;
7659
- this.id = id;
7764
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
7765
+ this.id = options?.id;
7766
+ this.description = options?.description;
7660
7767
  }
7661
7768
  inspectorSummary() {
7662
7769
  const fnName = this.aggregate.name;
@@ -7687,10 +7794,14 @@ var Filter = class {
7687
7794
  type = FilterNode;
7688
7795
  execution = { hint: "local" };
7689
7796
  icon = "lucide:filter";
7690
- constructor(name, predicate, id) {
7797
+ id;
7798
+ description;
7799
+ constructor(name, predicate, idOrOptions) {
7691
7800
  this.name = name;
7692
7801
  this.predicate = predicate;
7693
- this.id = id;
7802
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
7803
+ this.id = options?.id;
7804
+ this.description = options?.description;
7694
7805
  }
7695
7806
  inspectorSummary() {
7696
7807
  const fnName = this.predicate.name;
@@ -7765,10 +7876,14 @@ var If = class {
7765
7876
  execution = { hint: "local" };
7766
7877
  icon = "lucide:split@rot=90";
7767
7878
  declaredOutputPorts = ["true", "false"];
7768
- constructor(name, predicate, id) {
7879
+ id;
7880
+ description;
7881
+ constructor(name, predicate, idOrOptions) {
7769
7882
  this.name = name;
7770
7883
  this.predicate = predicate;
7771
- this.id = id;
7884
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
7885
+ this.id = options?.id;
7886
+ this.description = options?.description;
7772
7887
  }
7773
7888
  inspectorSummary() {
7774
7889
  const fnName = this.predicate.name;
@@ -7808,9 +7923,12 @@ var IsTestRun = class {
7808
7923
  declaredOutputPorts = ["true", "false"];
7809
7924
  name;
7810
7925
  id;
7811
- constructor(name = "Is test run?", id) {
7926
+ description;
7927
+ constructor(name = "Is test run?", idOrOptions) {
7812
7928
  this.name = name;
7813
- this.id = id;
7929
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
7930
+ this.id = options?.id;
7931
+ this.description = options?.description;
7814
7932
  }
7815
7933
  };
7816
7934
 
@@ -7839,11 +7957,15 @@ var Switch = class {
7839
7957
  execution = { hint: "local" };
7840
7958
  icon = "lucide:git-branch-plus";
7841
7959
  declaredOutputPorts;
7842
- constructor(name, cfg, id) {
7960
+ id;
7961
+ description;
7962
+ constructor(name, cfg, idOrOptions) {
7843
7963
  this.name = name;
7844
7964
  this.cfg = cfg;
7845
- this.id = id;
7846
7965
  this.declaredOutputPorts = [...new Set([...cfg.cases, cfg.defaultCase])].sort();
7966
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
7967
+ this.id = options?.id;
7968
+ this.description = options?.description;
7847
7969
  }
7848
7970
  inspectorSummary() {
7849
7971
  const rows = [{
@@ -7882,10 +8004,14 @@ var Split = class {
7882
8004
  */
7883
8005
  continueWhenEmptyOutput = true;
7884
8006
  icon = "builtin:split-rows";
7885
- constructor(name, getElements, id) {
8007
+ id;
8008
+ description;
8009
+ constructor(name, getElements, idOrOptions) {
7886
8010
  this.name = name;
7887
8011
  this.getElements = getElements;
7888
- this.id = id;
8012
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
8013
+ this.id = options?.id;
8014
+ this.description = options?.description;
7889
8015
  }
7890
8016
  inspectorSummary() {
7891
8017
  const fnName = this.getElements.name;
@@ -7943,14 +8069,17 @@ var CronTrigger = class {
7943
8069
  type = CronTriggerNode;
7944
8070
  icon = "lucide:clock";
7945
8071
  id;
7946
- constructor(name, args, id) {
8072
+ description;
8073
+ constructor(name, args, idOrOptions) {
7947
8074
  this.name = name;
7948
8075
  this.args = args;
7949
8076
  new Cron(args.schedule, {
7950
8077
  paused: true,
7951
8078
  timezone: args.timezone
7952
8079
  });
7953
- this.id = id;
8080
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
8081
+ this.id = options?.id;
8082
+ this.description = options?.description;
7954
8083
  }
7955
8084
  get schedule() {
7956
8085
  return this.args.schedule;
@@ -8004,20 +8133,21 @@ var ManualTrigger = class ManualTrigger {
8004
8133
  icon = "lucide:play";
8005
8134
  defaultItems;
8006
8135
  id;
8136
+ description;
8007
8137
  /** Manual runs often emit an empty batch; still schedule downstream by default. */
8008
8138
  continueWhenEmptyOutput = true;
8009
- constructor(name = "Manual trigger", defaultItemsOrId, id) {
8139
+ constructor(name = "Manual trigger", defaultItemsOrId, idOrOptions) {
8010
8140
  this.name = name;
8011
8141
  this.defaultItems = ManualTrigger.resolveDefaultItems(defaultItemsOrId);
8012
- this.id = ManualTrigger.resolveId(defaultItemsOrId, id);
8142
+ const trailing = idOrOptions ?? (typeof defaultItemsOrId === "string" ? defaultItemsOrId : void 0);
8143
+ const options = typeof trailing === "string" ? { id: trailing } : trailing ?? {};
8144
+ this.id = options.id;
8145
+ this.description = options.description;
8013
8146
  }
8014
8147
  static resolveDefaultItems(value) {
8015
8148
  if (typeof value === "string" || value === void 0) return;
8016
8149
  return this.itemsInputNormalizer.normalize(value);
8017
8150
  }
8018
- static resolveId(value, id) {
8019
- return typeof value === "string" ? value : id;
8020
- }
8021
8151
  inspectorSummary() {
8022
8152
  const rows = [{
8023
8153
  label: "Trigger",
@@ -8063,11 +8193,13 @@ var MapData = class {
8063
8193
  continueWhenEmptyOutput = true;
8064
8194
  icon = "lucide:square-pen";
8065
8195
  keepBinaries;
8196
+ description;
8066
8197
  constructor(name, map, options = {}) {
8067
8198
  this.name = name;
8068
8199
  this.map = map;
8069
8200
  this.options = options;
8070
8201
  this.keepBinaries = options.keepBinaries ?? true;
8202
+ this.description = options.description;
8071
8203
  }
8072
8204
  get id() {
8073
8205
  return this.options.id;
@@ -8140,10 +8272,14 @@ var Merge = class {
8140
8272
  kind = "node";
8141
8273
  type = MergeNode;
8142
8274
  icon = "lucide:merge@rot=90";
8143
- constructor(name, cfg = { mode: "passThrough" }, id) {
8275
+ id;
8276
+ description;
8277
+ constructor(name, cfg = { mode: "passThrough" }, idOrOptions) {
8144
8278
  this.name = name;
8145
8279
  this.cfg = cfg;
8146
- this.id = id;
8280
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
8281
+ this.id = options?.id;
8282
+ this.description = options?.description;
8147
8283
  }
8148
8284
  inspectorSummary() {
8149
8285
  const rows = [{
@@ -8176,9 +8312,13 @@ var NoOp = class {
8176
8312
  type = NoOpNode;
8177
8313
  execution = { hint: "local" };
8178
8314
  icon = "lucide:circle-dashed";
8179
- constructor(name = "NoOp", id) {
8315
+ id;
8316
+ description;
8317
+ constructor(name = "NoOp", idOrOptions) {
8180
8318
  this.name = name;
8181
- this.id = id;
8319
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
8320
+ this.id = options?.id;
8321
+ this.description = options?.description;
8182
8322
  }
8183
8323
  };
8184
8324
 
@@ -8244,12 +8384,16 @@ var SubWorkflow = class {
8244
8384
  kind = "node";
8245
8385
  type = SubWorkflowNode;
8246
8386
  icon = "lucide:workflow";
8247
- constructor(name, workflowId, upstreamRefs, startAt, id) {
8387
+ id;
8388
+ description;
8389
+ constructor(name, workflowId, upstreamRefs, startAt, idOrOptions) {
8248
8390
  this.name = name;
8249
8391
  this.workflowId = workflowId;
8250
8392
  this.upstreamRefs = upstreamRefs;
8251
8393
  this.startAt = startAt;
8252
- this.id = id;
8394
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
8395
+ this.id = options?.id;
8396
+ this.description = options?.description;
8253
8397
  }
8254
8398
  inspectorSummary() {
8255
8399
  const rows = [{
@@ -8359,10 +8503,14 @@ var Wait = class {
8359
8503
  /** Pass-through empty batches should still advance to downstream nodes. */
8360
8504
  continueWhenEmptyOutput = true;
8361
8505
  icon = "lucide:hourglass";
8362
- constructor(name, milliseconds, id) {
8506
+ id;
8507
+ description;
8508
+ constructor(name, milliseconds, idOrOptions) {
8363
8509
  this.name = name;
8364
8510
  this.milliseconds = milliseconds;
8365
- this.id = id;
8511
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
8512
+ this.id = options?.id;
8513
+ this.description = options?.description;
8366
8514
  }
8367
8515
  inspectorSummary() {
8368
8516
  const seconds = this.milliseconds / 1e3;
@@ -8417,11 +8565,15 @@ var WebhookTrigger = class WebhookTrigger {
8417
8565
  kind = "trigger";
8418
8566
  type = WebhookTriggerNode;
8419
8567
  icon = "lucide:globe";
8420
- constructor(name, args, handler = WebhookTrigger.defaultHandler, id) {
8568
+ id;
8569
+ description;
8570
+ constructor(name, args, handler = WebhookTrigger.defaultHandler, idOrOptions) {
8421
8571
  this.name = name;
8422
8572
  this.args = args;
8423
8573
  this.handler = handler;
8424
- this.id = id;
8574
+ const options = typeof idOrOptions === "string" ? { id: idOrOptions } : idOrOptions;
8575
+ this.id = options?.id;
8576
+ this.description = options?.description;
8425
8577
  }
8426
8578
  get endpointKey() {
8427
8579
  return this.args.endpointKey;
@@ -8478,11 +8630,21 @@ function createWorkflowBuilder(meta$2) {
8478
8630
 
8479
8631
  //#endregion
8480
8632
  //#region src/workflowAuthoring/WorkflowChatModelFactory.types.ts
8633
+ const VALID_COMPLEXITY = new Set([
8634
+ "low",
8635
+ "medium",
8636
+ "high",
8637
+ "xhigh"
8638
+ ]);
8481
8639
  var WorkflowChatModelFactory = class {
8482
8640
  static create(model) {
8483
8641
  if (typeof model !== "string") return model;
8484
8642
  const [provider, resolvedModel] = model.includes(":") ? model.split(":", 2) : ["openai", model];
8485
- if (provider === "codemation-managed") return new CodemationChatModelConfig("Codemation Managed", resolvedModel ?? "");
8643
+ if (provider === "codemation-managed") {
8644
+ const complexity = resolvedModel ?? "medium";
8645
+ if (!VALID_COMPLEXITY.has(complexity)) throw new Error(`Invalid managed complexity "${complexity}". Must be one of: low, medium, high, xhigh.`);
8646
+ return new CodemationChatModelConfig("Codemation Managed", complexity);
8647
+ }
8486
8648
  if (provider !== "openai") throw new Error(`Unsupported workflow().agent() model provider "${provider}".`);
8487
8649
  return new OpenAIChatModelConfig("OpenAI", resolvedModel);
8488
8650
  }
@@ -9119,5 +9281,5 @@ const codemationDocumentScannerNode = defineNode({
9119
9281
  });
9120
9282
 
9121
9283
  //#endregion
9122
- export { AIAgent, AIAgentConnectionWorkflowExpander, AIAgentExecutionHelpersFactory, AIAgentNode, AgentItemPortMap, AgentMessageFactory, AgentOutputFactory, AgentStructuredOutputRepairPromptFactory, AgentStructuredOutputRunner, AgentToolCallPortMap, AgentToolErrorClassifier, AgentToolExecutionCoordinator, AgentToolRepairExhaustedError, AgentToolRepairPolicy, Aggregate, AggregateNode, Assertion, AssertionNode, BM25Index, Callback, CallbackNode, CallbackResultNormalizer, CodemationChatModelConfig, CodemationChatModelFactory, ConnectionCredentialExecutionContextFactory, ConnectionCredentialNode, ConnectionCredentialNodeConfig, ConnectionCredentialNodeConfigFactory, CronTrigger, CronTriggerNode, DeferredMetaToolStrategy, DeferredMetaToolStrategyFactory, Filter, FilterNode, HTTP_REQUEST_ACCEPTED_CREDENTIAL_TYPES, HttpRequest, HttpRequestNode, If, IfNode, IsTestRun, IsTestRunNode, ManagedModelFetcher, ManualTrigger, ManualTriggerNode, MapData, MapDataNode, Merge, MergeNode, NoOp, NoOpNode, OpenAIChatModelConfig, OpenAIChatModelFactory, OpenAiChatModelPresets, OpenAiStrictJsonSchemaFactory, SSRFBlockedError, Split, SplitNode, SsrfGuard, SubWorkflow, SubWorkflowNode, Switch, SwitchNode, TestTrigger, TestTriggerNode, Wait, WaitDuration, WaitNode, WebhookRespondNowAndContinueError, WebhookRespondNowError, WebhookTrigger, WebhookTriggerNode, WorkflowAuthoringBuilder, WorkflowBranchBuilder, WorkflowChain, apiKeyCredentialType, basicAuthCredentialType, bearerTokenCredentialType, codemationDocumentScannerNode, collectionDeleteNode, collectionFindOneNode, collectionGetNode, collectionInsertNode, collectionListNode, collectionUpdateNode, createWorkflowBuilder, defineRestNode, inboxApproval, oauth2ClientCredentialsType, openAiChatModelPresets, registerCoreNodes, workflow };
9284
+ export { AIAgent, AIAgentConnectionWorkflowExpander, AIAgentExecutionHelpersFactory, AIAgentNode, AgentItemPortMap, AgentMessageFactory, AgentOutputFactory, AgentStructuredOutputRepairPromptFactory, AgentStructuredOutputRunner, AgentToolCallPortMap, AgentToolErrorClassifier, AgentToolExecutionCoordinator, AgentToolRepairExhaustedError, AgentToolRepairPolicy, Aggregate, AggregateNode, Assertion, AssertionNode, BM25Index, Callback, CallbackNode, CallbackResultNormalizer, CodemationChatModelConfig, CodemationChatModelFactory, ConnectionCredentialExecutionContextFactory, ConnectionCredentialNode, ConnectionCredentialNodeConfig, ConnectionCredentialNodeConfigFactory, CronTrigger, CronTriggerNode, DeferredMetaToolStrategy, DeferredMetaToolStrategyFactory, Filter, FilterNode, HTTP_REQUEST_ACCEPTED_CREDENTIAL_TYPES, HttpRequest, HttpRequestNode, If, IfNode, IsTestRun, IsTestRunNode, ManualTrigger, ManualTriggerNode, MapData, MapDataNode, Merge, MergeNode, NoOp, NoOpNode, OpenAIChatModelConfig, OpenAIChatModelFactory, OpenAiChatModelPresets, OpenAiStrictJsonSchemaFactory, SSRFBlockedError, Split, SplitNode, SsrfGuard, SubWorkflow, SubWorkflowNode, Switch, SwitchNode, TestTrigger, TestTriggerNode, Wait, WaitDuration, WaitNode, WebhookRespondNowAndContinueError, WebhookRespondNowError, WebhookTrigger, WebhookTriggerNode, WorkflowAuthoringBuilder, WorkflowBranchBuilder, WorkflowChain, apiKeyCredentialType, basicAuthCredentialType, bearerTokenCredentialType, codemationDocumentScannerNode, collectionDeleteNode, collectionFindOneNode, collectionGetNode, collectionInsertNode, collectionListNode, collectionUpdateNode, createWorkflowBuilder, defineRestNode, inboxApproval, oauth2ClientCredentialsType, openAiChatModelPresets, registerCoreNodes, workflow };
9123
9285
  //# sourceMappingURL=index.js.map