@codemation/core-nodes 0.13.0 → 0.14.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 (73) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/index.cjs +34 -433
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +95 -1312
  5. package/dist/index.d.ts +95 -1312
  6. package/dist/index.js +35 -435
  7. package/dist/index.js.map +1 -1
  8. package/dist/metadata.json +1 -1
  9. package/package.json +2 -2
  10. package/src/authoring/defineRestNode.types.ts +0 -84
  11. package/src/canvasIconName.ts +0 -7
  12. package/src/chatModels/CodemationChatModelConfig.ts +0 -10
  13. package/src/chatModels/CodemationChatModelFactory.ts +0 -7
  14. package/src/chatModels/ManagedHmacSignerFactory.types.ts +0 -35
  15. package/src/chatModels/OpenAIChatModelFactory.ts +0 -2
  16. package/src/chatModels/OpenAiChatModelPresetsFactory.ts +0 -5
  17. package/src/chatModels/OpenAiCredentialSession.ts +0 -1
  18. package/src/chatModels/OpenAiStrictJsonSchemaFactory.ts +0 -21
  19. package/src/credentials/ApiKeyCredentialType.ts +0 -3
  20. package/src/credentials/BasicAuthCredentialType.ts +0 -4
  21. package/src/credentials/BearerTokenCredentialType.ts +0 -4
  22. package/src/credentials/OAuth2ClientCredentialsTypeFactory.ts +0 -19
  23. package/src/credentials/OAuth2TokenExchangeFactory.ts +0 -7
  24. package/src/http/HttpBodyBuilder.ts +0 -16
  25. package/src/http/HttpRequestExecutor.ts +0 -35
  26. package/src/http/HttpUrlBuilder.ts +0 -4
  27. package/src/http/SSRFBlockedError.ts +0 -4
  28. package/src/http/SsrfGuard.ts +10 -50
  29. package/src/http/httpRequest.types.ts +0 -49
  30. package/src/index.ts +1 -0
  31. package/src/nodes/AIAgentConfig.ts +0 -44
  32. package/src/nodes/AIAgentExecutionHelpersFactory.ts +0 -37
  33. package/src/nodes/AIAgentNode.ts +0 -132
  34. package/src/nodes/AgentBinaryContentFactory.ts +0 -12
  35. package/src/nodes/AgentLoopCheckpoint.types.ts +0 -13
  36. package/src/nodes/AgentMessageFactory.ts +0 -18
  37. package/src/nodes/AgentStructuredOutputRunner.ts +0 -17
  38. package/src/nodes/AgentToolExecutionCoordinator.ts +0 -12
  39. package/src/nodes/AgentToolResultContentFactory.ts +0 -29
  40. package/src/nodes/AssertionNode.ts +0 -14
  41. package/src/nodes/BM25Index.ts +0 -14
  42. package/src/nodes/ConnectionCredentialExecutionContextFactory.ts +0 -5
  43. package/src/nodes/ConnectionCredentialNode.ts +0 -4
  44. package/src/nodes/CronTriggerFactory.ts +0 -9
  45. package/src/nodes/DeferredMetaToolStrategy.ts +0 -18
  46. package/src/nodes/DeferredMetaToolStrategyFactory.ts +0 -5
  47. package/src/nodes/HttpRequestNodeFactory.ts +0 -14
  48. package/src/nodes/InboxApprovalNode.types.ts +0 -16
  49. package/src/nodes/IsTestRunNode.ts +0 -8
  50. package/src/nodes/ManualTriggerFactory.ts +0 -3
  51. package/src/nodes/ManualTriggerNode.ts +0 -4
  52. package/src/nodes/MergeNode.ts +0 -1
  53. package/src/nodes/NodeBackedToolRuntime.ts +0 -14
  54. package/src/nodes/SubWorkflowNode.ts +0 -3
  55. package/src/nodes/SwitchNode.ts +0 -3
  56. package/src/nodes/TestTriggerNode.ts +0 -9
  57. package/src/nodes/aiAgentSupport.types.ts +0 -16
  58. package/src/nodes/assertion.ts +0 -10
  59. package/src/nodes/codemationDocumentScannerNode.ts +0 -18
  60. package/src/nodes/collections/collectionListNode.types.ts +0 -1
  61. package/src/nodes/httpRequest.ts +0 -68
  62. package/src/nodes/isTestRun.ts +0 -4
  63. package/src/nodes/mapData.ts +0 -1
  64. package/src/nodes/merge.ts +0 -4
  65. package/src/nodes/mergeExecutionUtils.types.ts +0 -3
  66. package/src/nodes/nodeOptions.types.ts +0 -8
  67. package/src/nodes/schedulePollingTrigger.ts +37 -0
  68. package/src/nodes/split.ts +0 -4
  69. package/src/nodes/testTrigger.ts +0 -21
  70. package/src/nodes/wait.ts +0 -1
  71. package/src/nodes/webhookTriggerNode.ts +0 -5
  72. package/src/register.types.ts +0 -10
  73. package/src/workflows/AIAgentConnectionWorkflowExpander.ts +0 -3
package/dist/index.cjs CHANGED
@@ -33,9 +33,6 @@ let croner = require("croner");
33
33
  croner = __toESM(croner);
34
34
 
35
35
  //#region src/credentials/ApiKeyCredentialType.ts
36
- /**
37
- * API key credential that injects a key either as an HTTP header or a query parameter.
38
- */
39
36
  const apiKeyCredentialType = (0, __codemation_core.defineCredential)({
40
37
  key: "core-nodes.api-key",
41
38
  label: "API Key",
@@ -83,10 +80,6 @@ const apiKeyCredentialType = (0, __codemation_core.defineCredential)({
83
80
 
84
81
  //#endregion
85
82
  //#region src/credentials/BasicAuthCredentialType.ts
86
- /**
87
- * HTTP Basic authentication credential.
88
- * Session sets `Authorization: Basic <base64(username:password)>`.
89
- */
90
83
  const basicAuthCredentialType = (0, __codemation_core.defineCredential)({
91
84
  key: "core-nodes.basic-auth",
92
85
  label: "Basic Auth",
@@ -124,10 +117,6 @@ const basicAuthCredentialType = (0, __codemation_core.defineCredential)({
124
117
 
125
118
  //#endregion
126
119
  //#region src/credentials/BearerTokenCredentialType.ts
127
- /**
128
- * Simple Bearer token credential.
129
- * Session sets `Authorization: Bearer <token>` on every request.
130
- */
131
120
  const bearerTokenCredentialType = (0, __codemation_core.defineCredential)({
132
121
  key: "core-nodes.bearer-token",
133
122
  label: "Bearer Token",
@@ -186,24 +175,6 @@ var OAuth2TokenExchangeFactory = class {
186
175
 
187
176
  //#endregion
188
177
  //#region src/credentials/OAuth2ClientCredentialsTypeFactory.ts
189
- /**
190
- * OAuth2 client-credentials flow credential.
191
- *
192
- * This is a machine-to-machine flow: no user redirect occurs. The session
193
- * POSTs to the configured `tokenUrl` with `client_credentials` grant, caches
194
- * the resulting access token for the duration of the session, and injects it
195
- * as `Authorization: Bearer <token>` on each request.
196
- *
197
- * Token caching is per-session only (one createSession call = one token fetch
198
- * at most). Cross-session caching would require host-level state and is out of
199
- * scope here. Because the engine creates a fresh session per execution, a new
200
- * token is fetched once per node activation.
201
- *
202
- * NOTE: `auth` is intentionally omitted from the definition. The OAuth2
203
- * `auth: { kind: "oauth2" }` shape signals an authorization-code / user-redirect
204
- * flow; using it here would cause the host UI to render an OAuth consent button
205
- * that goes nowhere. Client-credentials is a purely server-side flow.
206
- */
207
178
  const oauth2ClientCredentialsType = (0, __codemation_core.defineCredential)({
208
179
  key: "core-nodes.oauth2-client-credentials",
209
180
  label: "OAuth2 Client Credentials",
@@ -287,10 +258,6 @@ const oauth2ClientCredentialsType = (0, __codemation_core.defineCredential)({
287
258
 
288
259
  //#endregion
289
260
  //#region src/http/SSRFBlockedError.ts
290
- /**
291
- * Thrown when an HTTP request target resolves to a private, link-local, or
292
- * loopback address and `allowPrivateNetworkTargets` is not set.
293
- */
294
261
  var SSRFBlockedError = class extends Error {
295
262
  resolvedIp;
296
263
  constructor(host, resolvedIp) {
@@ -302,26 +269,7 @@ var SSRFBlockedError = class extends Error {
302
269
 
303
270
  //#endregion
304
271
  //#region src/http/SsrfGuard.ts
305
- /** Emitted once per process when NODE_ENV=production and no allowedOutboundHosts is set. */
306
272
  let _productionNoAllowlistWarned = false;
307
- /**
308
- * Guards HTTP requests against Server-Side Request Forgery (SSRF) by
309
- * DNS-resolving the target host and rejecting private/link-local/loopback
310
- * addresses.
311
- *
312
- * Blocked ranges:
313
- * - RFC-1918: 10/8, 172.16/12, 192.168/16
314
- * - Link-local: 169.254/16
315
- * - Loopback: 127/8, ::1
316
- *
317
- * When `allowedOutboundHosts` is set, every resolved DNS target must match
318
- * at least one entry in the list (exact hostname or `*.example.com` wildcard).
319
- * When unset, existing behaviour applies: private ranges blocked, public allowed.
320
- *
321
- * Call {@link check} before making any outbound HTTP request.
322
- * Pass `allowPrivate: true` to bypass the private-network guard for trusted workflows
323
- * (allowedOutboundHosts allowlist is still applied when set).
324
- */
325
273
  var SsrfGuard = class {
326
274
  constructor(allowedOutboundHosts) {
327
275
  this.allowedOutboundHosts = allowedOutboundHosts;
@@ -330,15 +278,6 @@ var SsrfGuard = class {
330
278
  console.warn("[SsrfGuard] WARNING: NODE_ENV=production but no allowedOutboundHosts is configured for HttpRequest. All public destinations are permitted. Set allowedOutboundHosts to restrict outbound traffic.");
331
279
  }
332
280
  }
333
- /**
334
- * Resolves the host of `url` via DNS and throws {@link SSRFBlockedError}
335
- * if any resolved address falls in a blocked range, or if the host does not
336
- * match the operator-configured allowlist (when set).
337
- *
338
- * @param url - Fully-qualified URL of the intended request target.
339
- * @param allowPrivate - When `true`, the private-network check is skipped.
340
- * The allowedOutboundHosts check is still applied when set.
341
- */
342
281
  async check(url, allowPrivate) {
343
282
  if (allowPrivate && !this.allowedOutboundHosts?.length) return;
344
283
  let host;
@@ -362,10 +301,6 @@ var SsrfGuard = class {
362
301
  }
363
302
  for (const { address } of addresses) if (this.isPrivateAddress(address)) throw new SSRFBlockedError(host, address);
364
303
  }
365
- /**
366
- * Returns true when `host` matches at least one entry in `allowedOutboundHosts`.
367
- * Supports exact hostnames (`api.example.com`) and wildcard prefixes (`*.example.com`).
368
- */
369
304
  isHostAllowed(host) {
370
305
  for (const allowed of this.allowedOutboundHosts ?? []) if (allowed.startsWith("*.")) {
371
306
  const suffix = allowed.slice(1);
@@ -399,21 +334,6 @@ var SsrfGuard = class {
399
334
 
400
335
  //#endregion
401
336
  //#region src/http/HttpRequestExecutor.ts
402
- /**
403
- * Executes a single HTTP request described by {@link HttpRequestSpec}.
404
- *
405
- * - Credential sessions provide header/query deltas via `applyToRequest`.
406
- * - Body encoding is delegated to {@link HttpBodyBuilder}.
407
- * - URL query merging is delegated to {@link HttpUrlBuilder}.
408
- * - SSRF protection is delegated to {@link SsrfGuard} (injected).
409
- * - Binary response bodies: when `download.mode` triggers binary attach, the
410
- * `bodyBinaryName` field is set in the result but the body is NOT read here.
411
- * Callers that need binary attachment should use `buildRequest` to get the
412
- * resolved URL + init and make the fetch + binary attach themselves.
413
- *
414
- * Collaborators (`fetch`, body builder, url builder, ssrfGuard) are injected so
415
- * callers own construction at composition roots and tests can supply deterministic stubs.
416
- */
417
337
  var HttpRequestExecutor = class {
418
338
  constructor(fetchFn, bodyBuilder, urlBuilder, ssrfGuard) {
419
339
  this.fetchFn = fetchFn;
@@ -421,14 +341,6 @@ var HttpRequestExecutor = class {
421
341
  this.urlBuilder = urlBuilder;
422
342
  this.ssrfGuard = ssrfGuard;
423
343
  }
424
- /**
425
- * Builds the fetch init (headers, query, body) from the spec + credential delta,
426
- * returning both the resolved URL and the RequestInit so callers can make the
427
- * actual fetch call themselves (useful for streaming / binary attach).
428
- *
429
- * Also performs SSRF protection via the injected {@link SsrfGuard} before
430
- * returning — throws {@link SSRFBlockedError} if the target is a private address.
431
- */
432
344
  async buildRequest(spec, item) {
433
345
  await this.ssrfGuard.check(spec.url, spec.allowPrivateNetworkTargets ?? false);
434
346
  const credentialDelta = spec.credential?.applyToRequest(spec) ?? {};
@@ -452,12 +364,6 @@ var HttpRequestExecutor = class {
452
364
  }
453
365
  };
454
366
  }
455
- /**
456
- * Executes an HTTP request and returns parsed result.
457
- * For binary downloads (when `shouldAttachBody` is true), the body is NOT consumed
458
- * and callers must call `ctx.binary.attach` directly using the resolved URL + init
459
- * (available via `buildRequest`).
460
- */
461
367
  async execute(spec, item) {
462
368
  const { url: resolvedUrl, init } = await this.buildRequest(spec, item);
463
369
  const response = await this.fetchFn(resolvedUrl, init);
@@ -514,10 +420,6 @@ var HttpRequestExecutor = class {
514
420
 
515
421
  //#endregion
516
422
  //#region src/http/HttpBodyBuilder.ts
517
- /**
518
- * Builds a fetch-compatible `BodyInit` + Content-Type pair from an {@link HttpBodySpec}.
519
- * Multipart binaries are read from `item.binary` via `ctx.binary.openReadStream`.
520
- */
521
423
  var HttpBodyBuilder = class {
522
424
  async build(spec, item, ctx) {
523
425
  if (!spec || spec.kind === "none") return;
@@ -588,10 +490,6 @@ var HttpBodyBuilder = class {
588
490
 
589
491
  //#endregion
590
492
  //#region src/http/HttpUrlBuilder.ts
591
- /**
592
- * Merges query parameters into a base URL.
593
- * Handles both scalar and array values, and preserves any existing params.
594
- */
595
493
  var HttpUrlBuilder = class {
596
494
  build(baseUrl, query) {
597
495
  if (!query || Object.keys(query).length === 0) return baseUrl;
@@ -604,39 +502,12 @@ var HttpUrlBuilder = class {
604
502
 
605
503
  //#endregion
606
504
  //#region src/authoring/defineRestNode.types.ts
607
- /**
608
- * Substitutes `{name}` placeholders in a path template using values from `params`.
609
- */
610
505
  function substitutePath(template, params) {
611
506
  return template.replace(/\{([^}]+)}/g, (_match, key) => {
612
507
  const value = params[key];
613
508
  return value !== void 0 ? String(value) : `{${key}}`;
614
509
  });
615
510
  }
616
- /**
617
- * Declarative helper for creating thin API-wrapper nodes.
618
- *
619
- * Usage:
620
- * ```ts
621
- * export const postMessage = defineRestNode({
622
- * key: "slack.post-message",
623
- * title: "Send Slack message",
624
- * icon: "si:slack",
625
- * api: { baseUrl: "https://slack.com/api", path: "/chat.postMessage", method: "POST" },
626
- * credentials: { auth: bearerTokenCredentialType },
627
- * inputSchema: z.object({ channel: z.string(), text: z.string() }),
628
- * request: ({ input }) => ({
629
- * body: { kind: "json", data: { channel: input.channel, text: input.text } },
630
- * }),
631
- * response: ({ json }) => ({ messageTs: (json as any).ts }),
632
- * });
633
- * ```
634
- *
635
- * - `defineRestNode` is a thin wrapper over `defineNode`; it does not introduce a new runtime kind.
636
- * - Credential sessions are resolved via the `credentials` binding map (same as `defineNode`).
637
- * - Path `{placeholder}` substitution is applied from `input` keys before the request is made.
638
- * - Non-2xx responses throw an `Error` by default (`errorPolicy: "throw"`).
639
- */
640
511
  function defineRestNode(options) {
641
512
  const errorPolicy = options.errorPolicy ?? "throw";
642
513
  return (0, __codemation_core.defineNode)({
@@ -4174,11 +4045,6 @@ function toJSONSchema(input, params) {
4174
4045
 
4175
4046
  //#endregion
4176
4047
  //#region src/nodes/ConnectionCredentialExecutionContextFactory.ts
4177
- /**
4178
- * Builds a {@link NodeExecutionContext} whose identity for credential binding and `getCredential`
4179
- * is a **connection-owned** workflow node id (`ConnectionNodeIdFactory` in `@codemation/core`),
4180
- * not the executing parent node. Use for LLM slots, tool slots, or any connection-scoped owner.
4181
- */
4182
4048
  var ConnectionCredentialExecutionContextFactory = class {
4183
4049
  credentialResolverFactory;
4184
4050
  constructor(credentialSessions) {
@@ -4201,15 +4067,6 @@ let AIAgentExecutionHelpersFactory = class AIAgentExecutionHelpersFactory$1 {
4201
4067
  createConnectionCredentialExecutionContextFactory(credentialSessions) {
4202
4068
  return new ConnectionCredentialExecutionContextFactory(credentialSessions);
4203
4069
  }
4204
- /**
4205
- * Produces a plain JSON Schema object (`draft-07`) from a Zod schema, as needed by
4206
- * OpenAI tool-parameter schemas and the structured-output repair prompt.
4207
- * - Prefers the schema's **instance** `toJSONSchema(...)` method so we stay inside the Zod
4208
- * instance that created the schema (works across consumer/framework tsx namespaces — see
4209
- * {@link ZodInstanceToJsonSchema}). Falls back to the framework-imported module function.
4210
- * - Strips root `$schema` (OpenAI ignores it).
4211
- * - Sanitizes `required` for cfworker json-schema compatibility (must be a string array or absent).
4212
- */
4213
4070
  createJsonSchemaRecord(inputSchema, options) {
4214
4071
  const { $schema: _draftSchemaOmitted,...rest } = this.convertZodSchemaToJsonSchema(inputSchema, { target: "draft-07" });
4215
4072
  if (options.requireObjectRoot && rest.type !== "object") throw new Error(`Cannot create tool "${options.schemaName}": tool input schema must be a JSON Schema object type (got type=${String(rest.type)}).`);
@@ -4218,20 +4075,11 @@ let AIAgentExecutionHelpersFactory = class AIAgentExecutionHelpersFactory$1 {
4218
4075
  this.sanitizeJsonSchemaRequiredKeywordsForCfworker(rest);
4219
4076
  return rest;
4220
4077
  }
4221
- /**
4222
- * Runs Zod's `toJSONSchema` via the schema's own instance method when available, so consumer
4223
- * schemas loaded under a different tsx namespace still convert correctly. If the caller handed us
4224
- * a payload that lacks that method (e.g. a plain JSON Schema record or a Zod instance whose
4225
- * prototype was stripped), we fall back to the framework-bundled module function.
4226
- */
4227
4078
  convertZodSchemaToJsonSchema(inputSchema, params) {
4228
4079
  const candidate = inputSchema.toJSONSchema;
4229
4080
  if (typeof candidate === "function") return candidate.call(inputSchema, params);
4230
4081
  return toJSONSchema(inputSchema, params);
4231
4082
  }
4232
- /**
4233
- * `@cfworker/json-schema` iterates `schema.required` with `for...of`; it must be a string array or absent.
4234
- */
4235
4083
  sanitizeJsonSchemaRequiredKeywordsForCfworker(node$20) {
4236
4084
  if (!node$20 || typeof node$20 !== "object" || Array.isArray(node$20)) return;
4237
4085
  const o = node$20;
@@ -4378,11 +4226,6 @@ var OpenAIChatModelConfig = class {
4378
4226
 
4379
4227
  //#endregion
4380
4228
  //#region src/chatModels/OpenAiChatModelPresetsFactory.ts
4381
- /**
4382
- * Default OpenAI chat model configs for scaffolds and demos (icon + label match {@link OpenAIChatModelConfig} defaults).
4383
- * Prefer importing {@link openAiChatModelPresets} from here or from the consumer template re-export
4384
- * instead of repeating {@link OpenAIChatModelConfig} construction in app workflows.
4385
- */
4386
4229
  var OpenAiChatModelPresets = class {
4387
4230
  demoGpt4oMini = new OpenAIChatModelConfig("OpenAI", "gpt-4o-mini");
4388
4231
  demoGpt41 = new OpenAIChatModelConfig("OpenAI", "gpt-4.1");
@@ -4391,19 +4234,6 @@ const openAiChatModelPresets = new OpenAiChatModelPresets();
4391
4234
 
4392
4235
  //#endregion
4393
4236
  //#region src/chatModels/ManagedHmacSignerFactory.types.ts
4394
- /**
4395
- * Creates an HMAC-signing fetch wrapper that authenticates requests to
4396
- * Codemation managed services (LLM broker, doc-scanner) with the
4397
- * Codemation-Hmac v=1 scheme.
4398
- *
4399
- * Mirrors HmacRequestSigner from @codemation/host/pairing without importing
4400
- * that package (which would create a circular dependency since @codemation/host
4401
- * depends on @codemation/core-nodes).
4402
- *
4403
- * @param workspaceId - Workspace identifier injected by the CP provisioner.
4404
- * @param pairingSecret - Base64-encoded 32-byte HMAC key injected by the provisioner.
4405
- * @param options - Optional behaviour flags and test seams.
4406
- */
4407
4237
  function managedHmacFetchFactory(workspaceId, pairingSecret, options) {
4408
4238
  const signBody = options?.signBody ?? true;
4409
4239
  return async (input, init) => {
@@ -4422,10 +4252,6 @@ function managedHmacFetchFactory(workspaceId, pairingSecret, options) {
4422
4252
  });
4423
4253
  };
4424
4254
  }
4425
- /**
4426
- * Produces a Codemation-Hmac v=1 Authorization header value.
4427
- * Algorithm must match HmacVerifier.computeSignature() in the control-plane.
4428
- */
4429
4255
  function buildHmacAuthHeader(workspaceId, pairingSecret, method, url, body, overrides) {
4430
4256
  const ts = overrides?.now ? overrides.now() : Math.floor(Date.now() / 1e3);
4431
4257
  const nonce = overrides?.nonce ? overrides.nonce() : (0, node_crypto.randomBytes)(16).toString("base64");
@@ -4488,12 +4314,7 @@ var CodemationChatModelConfig = class {
4488
4314
 
4489
4315
  //#endregion
4490
4316
  //#region src/nodes/AgentToolResultContentFactory.ts
4491
- /**
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.
4494
- */
4495
4317
  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
4318
  const KNOWN_MCP_BLOCK_TYPES = new Set([
4498
4319
  "text",
4499
4320
  "image",
@@ -4501,19 +4322,6 @@ const KNOWN_MCP_BLOCK_TYPES = new Set([
4501
4322
  "resource",
4502
4323
  "resource_link"
4503
4324
  ]);
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
4325
  var AgentToolResultContentFactory = class AgentToolResultContentFactory {
4518
4326
  static tryMapToContentOutput(result) {
4519
4327
  const blocks = AgentToolResultContentFactory.contentBlocks(result);
@@ -4527,12 +4335,6 @@ var AgentToolResultContentFactory = class AgentToolResultContentFactory {
4527
4335
  }
4528
4336
  return parts;
4529
4337
  }
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
4338
  static contentBlocks(result) {
4537
4339
  if (result === null || typeof result !== "object") return void 0;
4538
4340
  const content = result.content;
@@ -4637,19 +4439,10 @@ var AgentToolResultContentFactory = class AgentToolResultContentFactory {
4637
4439
 
4638
4440
  //#endregion
4639
4441
  //#region src/nodes/AgentMessageFactory.ts
4640
- /**
4641
- * AI-SDK-shaped message construction for the AIAgent stack. Emits plain `ModelMessage[]`
4642
- * ( `{ role: 'system' | 'user' | 'assistant' | 'tool', content: ... }` ) as consumed by
4643
- * `generateText({ messages })` from the `ai` package.
4644
- */
4645
4442
  var AgentMessageFactory = class AgentMessageFactory {
4646
4443
  static createPromptMessages(messages) {
4647
4444
  return messages.map((message) => this.createPromptMessage(message));
4648
4445
  }
4649
- /**
4650
- * Builds the assistant message that contains optional text plus one or more tool-call parts,
4651
- * matching the shape AI SDK emits between steps.
4652
- */
4653
4446
  static createAssistantWithToolCalls(text, toolCalls) {
4654
4447
  const content = [];
4655
4448
  if (text && text.length > 0) content.push({
@@ -4667,10 +4460,6 @@ var AgentMessageFactory = class AgentMessageFactory {
4667
4460
  content
4668
4461
  };
4669
4462
  }
4670
- /**
4671
- * Builds the `{ role: "tool", content: [{ type: "tool-result", ... }, ...] }` message returned
4672
- * to the model after each tool round.
4673
- */
4674
4463
  static createToolResultsMessage(executedToolCalls, passToolBinariesToModel = true) {
4675
4464
  return {
4676
4465
  role: "tool",
@@ -4682,11 +4471,6 @@ var AgentMessageFactory = class AgentMessageFactory {
4682
4471
  }))
4683
4472
  };
4684
4473
  }
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
4474
  static toToolResultOutput(result, passToolBinariesToModel) {
4691
4475
  if (passToolBinariesToModel) {
4692
4476
  const content = AgentToolResultContentFactory.tryMapToContentOutput(result);
@@ -5496,10 +5280,6 @@ let AgentStructuredOutputRunner = class AgentStructuredOutputRunner$1 {
5496
5280
  }
5497
5281
  throw new Error(`Structured output required for AIAgent "${args.agentName}" (${args.nodeId}) but validation still failed after ${_AgentStructuredOutputRunner.repairAttemptCount} repair attempts: ${failure.validationError}`);
5498
5282
  }
5499
- /**
5500
- * Chooses strict mode for OpenAI chat-model configs, off otherwise. Extendable in future for
5501
- * other providers that adopt the same "supply a JSON Schema record directly" contract.
5502
- */
5503
5283
  resolveStructuredOutputOptions(chatModelConfig) {
5504
5284
  if (chatModelConfig.type !== OpenAIChatModelFactory) return;
5505
5285
  return {
@@ -5982,10 +5762,6 @@ let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
5982
5762
  extractErrorDetails(error) {
5983
5763
  return error.details;
5984
5764
  }
5985
- /**
5986
- * Extracts the text content from the last assistant message in the conversation snapshot.
5987
- * Used to populate `agentReasoning` in the HITL suspension metadata.
5988
- */
5989
5765
  extractLastAssistantText(conversation) {
5990
5766
  for (let i = conversation.length - 1; i >= 0; i--) {
5991
5767
  const msg = conversation[i];
@@ -6020,16 +5796,6 @@ AgentToolExecutionCoordinator = __decorate([
6020
5796
 
6021
5797
  //#endregion
6022
5798
  //#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
5799
  var AgentBinaryContentFactory = class AgentBinaryContentFactory {
6034
5800
  static toContentPart(binary) {
6035
5801
  if (binary.mediaType.startsWith("image/")) return {
@@ -6108,20 +5874,6 @@ let NodeBackedToolRuntime = class NodeBackedToolRuntime$1 {
6108
5874
  outputs
6109
5875
  });
6110
5876
  }
6111
- /**
6112
- * Returns a re-rooted child ctx for nested-agent tools (so their LLM/tool connection ids derive
6113
- * from the tool connection node, telemetry parents under the tool-call span, and connection
6114
- * invocations carry `parentInvocationId`). Plain runnable tools (non-agent) keep the orchestrator
6115
- * ctx with only `config` swapped — no nesting concern.
6116
- *
6117
- * The caller (`AIAgentNode.createItemScopedTools`) already wraps the orchestrator ctx via
6118
- * `ConnectionCredentialExecutionContextFactory.forConnectionNode`, so `args.ctx.nodeId` is the
6119
- * tool's own connection node id (e.g. `AIAgentNode:2__conn__tool__searchInMail`). We pass that
6120
- * through as the sub-agent's `nodeId`; deriving another `toolConnectionNodeId(args.ctx.nodeId,
6121
- * config.name)` here would prepend a duplicate `__conn__tool__<name>` segment and exponentially
6122
- * deepen ids on each invocation, which also breaks credential resolution because user-provided
6123
- * bindings sit on the single-level connection node id.
6124
- */
6125
5877
  resolveNodeCtx(config$1, args) {
6126
5878
  const isNestedAgent = __codemation_core.AgentConfigInspector.isAgentNodeConfig(config$1.node);
6127
5879
  const hooks = args.hooks;
@@ -6186,22 +5938,12 @@ NodeBackedToolRuntime = __decorate([
6186
5938
 
6187
5939
  //#endregion
6188
5940
  //#region src/nodes/BM25Index.ts
6189
- /**
6190
- * Minimal BM25 (Okapi BM25) implementation for indexing MCP tool descriptions.
6191
- *
6192
- * Parameters: k1=1.5, b=0.75 (standard defaults).
6193
- * Tokenisation: lowercase, split on non-alphanumerics, filter empties.
6194
- */
6195
5941
  var BM25Index = class {
6196
5942
  k1 = 1.5;
6197
5943
  b = .75;
6198
5944
  tf = [];
6199
5945
  df = /* @__PURE__ */ new Map();
6200
5946
  avgDocLen = 0;
6201
- /**
6202
- * Add all documents at once. After calling this, search is available.
6203
- * Documents are indexed in insertion order; search returns their indices.
6204
- */
6205
5947
  add(docs) {
6206
5948
  const docTerms = docs.map((d) => this.tokenize(d));
6207
5949
  let totalLen = 0;
@@ -6214,10 +5956,6 @@ var BM25Index = class {
6214
5956
  }
6215
5957
  this.avgDocLen = docTerms.length > 0 ? totalLen / docTerms.length : 0;
6216
5958
  }
6217
- /**
6218
- * Returns up to `limit` document indices ranked by BM25 score (highest first).
6219
- * Returns an empty array if the index is empty or the query matches nothing.
6220
- */
6221
5959
  search(query, limit) {
6222
5960
  const n = this.tf.length;
6223
5961
  if (n === 0) return [];
@@ -6258,26 +5996,12 @@ const PINNED_TOOLS_SOFT_LIMIT = 8;
6258
5996
  const PINNED_TOOLS_HARD_LIMIT = 16;
6259
5997
  const FIND_TOOLS_NAME = "find_tools";
6260
5998
  const FIND_TOOLS_DEFAULT_LIMIT = 5;
6261
- /**
6262
- * Default tool-loading strategy: BM25-indexed MCP tool deferral via a `find_tools` meta-tool.
6263
- *
6264
- * - Node-backed tools and pinned MCP tools are always included in every turn.
6265
- * - `find_tools(query, limit?)` is added to the tool set when MCP tools are indexed.
6266
- * - Tools surfaced by `find_tools` are included in subsequent turns.
6267
- *
6268
- * Not DI-managed; instantiated per agent execution by DeferredMetaToolStrategyFactory.
6269
- */
6270
5999
  var DeferredMetaToolStrategy = class {
6271
6000
  nodeBackedTools = {};
6272
6001
  pinnedTools = {};
6273
6002
  mcpEntries = [];
6274
6003
  toolsByServerId = /* @__PURE__ */ new Map();
6275
6004
  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
6005
  jsonSchema;
6282
6006
  constructor(bm25, warnFn) {
6283
6007
  this.bm25 = bm25;
@@ -6425,11 +6149,6 @@ let AIAgentNode = class AIAgentNode$1 {
6425
6149
  inputSchema = unknown();
6426
6150
  connectionCredentialExecutionContextFactory;
6427
6151
  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
6152
  aiSdk;
6434
6153
  aiSdkPromise = null;
6435
6154
  constructor(nodeResolver, credentialSessions, nodeBackedToolRuntime, executionHelpers, structuredOutputRunner, toolExecutionCoordinator, toolLoadingStrategyFactory, agentMcpIntegration) {
@@ -6453,15 +6172,9 @@ let AIAgentNode = class AIAgentNode$1 {
6453
6172
  };
6454
6173
  return (await this.runAgentForItem(prepared, itemWithMappedJson, args.itemIndex, args.items)).json;
6455
6174
  }
6456
- /** Load the `ai` SDK once per node instance (cached promise guards concurrent items). */
6457
6175
  async ensureAiSdk() {
6458
6176
  this.aiSdk = await (this.aiSdkPromise ??= import("ai"));
6459
6177
  }
6460
- /**
6461
- * Resume path: re-enters the agent loop after a HITL suspension.
6462
- * Reconstructs the conversation from the checkpoint, injects the human decision
6463
- * as a tool_result, and continues the loop from where it suspended.
6464
- */
6465
6178
  async executeResumed(args, resumeContext) {
6466
6179
  const { ctx } = args;
6467
6180
  const taskMetadata = resumeContext.task.metadata ?? {};
@@ -6508,10 +6221,6 @@ let AIAgentNode = class AIAgentNode$1 {
6508
6221
  const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, loopResult.finalText, itemScopedTools.length > 0);
6509
6222
  return this.buildOutputItem(item, outputJson).json;
6510
6223
  }
6511
- /**
6512
- * Normalizes a {@link ResumeContext} decision into a flat JSON-serializable shape
6513
- * suitable for injection as a tool_result content.
6514
- */
6515
6224
  normalizeDecision(resumeContext) {
6516
6225
  const { decision } = resumeContext;
6517
6226
  if (decision.kind === "decided") {
@@ -6638,16 +6347,6 @@ let AIAgentNode = class AIAgentNode$1 {
6638
6347
  const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, loopResult.finalText, itemScopedTools.length > 0);
6639
6348
  return this.buildOutputItem(item, outputJson);
6640
6349
  }
6641
- /**
6642
- * Multi-turn loop:
6643
- * - Each turn is a single `generateText` call with tools exposed but **not auto-executed**
6644
- * (we control tool dispatch so that {@link AgentToolExecutionCoordinator} drives repair /
6645
- * connection-invocation recording / transient-error handling exactly like before).
6646
- * - When the model returns no tool calls the loop ends with the model's text as the final answer.
6647
- * - Respects `guardrails.maxTurns` and `guardrails.onTurnLimitReached`.
6648
- * - Strategy-owned tool calls (e.g. `find_tools`) are dispatched via the strategy, not the
6649
- * coordinator; their results are tracked so subsequent turns receive the discovered tools.
6650
- */
6651
6350
  async runTurnLoopUntilFinalAnswer(args) {
6652
6351
  const { prepared, itemInputsByPort, itemScopedTools, conversation } = args;
6653
6352
  const { ctx, guardrails, toolLoadingStrategy } = prepared;
@@ -6655,7 +6354,6 @@ let AIAgentNode = class AIAgentNode$1 {
6655
6354
  let toolCallCount = args.resumedToolCallCount ?? 0;
6656
6355
  let turnCount = 0;
6657
6356
  const repairAttemptsByToolName = /* @__PURE__ */ new Map();
6658
- /** Tool IDs surfaced by find_tools across all prior turns in this item run. */
6659
6357
  let previousFoundToolIds = [];
6660
6358
  for (let turn = 1; turn <= guardrails.maxTurns; turn++) {
6661
6359
  turnCount = turn;
@@ -6785,12 +6483,6 @@ let AIAgentNode = class AIAgentNode$1 {
6785
6483
  };
6786
6484
  });
6787
6485
  }
6788
- /**
6789
- * Resolves the HITL behavior for a tool binding, or `undefined` when it is not a HITL tool.
6790
- * A binding is HITL if either the backing node carries a `defineHumanApprovalNode` marker or the
6791
- * binding sets a per-binding `onRejected` via `asTool(..., { onRejected })`. The per-binding value
6792
- * wins over the node marker, so two tools backed by the same node can reject differently.
6793
- */
6794
6486
  resolveHumanApprovalBehavior(config$1) {
6795
6487
  if (!this.isNodeBackedToolConfig(config$1)) return void 0;
6796
6488
  const marker = config$1.node.humanApprovalToolBehavior;
@@ -6798,11 +6490,6 @@ let AIAgentNode = class AIAgentNode$1 {
6798
6490
  if (marker === void 0 && perBinding === void 0) return void 0;
6799
6491
  return { onRejected: perBinding ?? marker?.onRejected ?? "return" };
6800
6492
  }
6801
- /**
6802
- * Invoke a text turn using the merged tool set from item-scoped tools (coordinator-managed)
6803
- * and strategy tools (find_tools + discovered MCP tools).
6804
- * Strategy tools take precedence for names that overlap.
6805
- */
6806
6493
  async invokeTextTurnWithStrategyTools(prepared, itemInputsByPort, messages, itemScopedTools, strategyTools) {
6807
6494
  const itemToolSet = this.buildToolSet(itemScopedTools);
6808
6495
  const strategyHasTools = Object.keys(strategyTools).length > 0;
@@ -6813,10 +6500,6 @@ let AIAgentNode = class AIAgentNode$1 {
6813
6500
  } : void 0;
6814
6501
  return this.invokeTextTurnWithToolSet(prepared, itemInputsByPort, messages, mergedTools);
6815
6502
  }
6816
- /**
6817
- * Removes `execute` properties from ToolSet entries so the AI SDK does not
6818
- * auto-execute them within `generateText`. Codemation owns all tool dispatch.
6819
- */
6820
6503
  stripExecuteCallbacks(tools) {
6821
6504
  const stripped = {};
6822
6505
  for (const [name, def] of Object.entries(tools)) {
@@ -6825,12 +6508,6 @@ let AIAgentNode = class AIAgentNode$1 {
6825
6508
  }
6826
6509
  return stripped;
6827
6510
  }
6828
- /**
6829
- * Builds a ToolSet from resolved tools for strategy initialization.
6830
- * The strategy uses this for its "always-included" node-backed tool descriptions.
6831
- * HITL tools (detected via the `humanApprovalToolBehavior` field set by `defineHumanApprovalNode`) get the solo-constraint sentence
6832
- * appended to their description.
6833
- */
6834
6511
  buildToolSetFromResolved(resolvedTools) {
6835
6512
  if (resolvedTools.length === 0) return {};
6836
6513
  const toolSet = {};
@@ -6848,20 +6525,6 @@ let AIAgentNode = class AIAgentNode$1 {
6848
6525
  }
6849
6526
  return toolSet;
6850
6527
  }
6851
- /**
6852
- * Builds an AI SDK {@link ToolSet} where every tool ships a pre-converted JSON Schema (via
6853
- * {@link jsonSchema}) — not the raw Zod schema — and carries **no** `execute`. Two reasons:
6854
- *
6855
- * 1. Codemation owns tool dispatch + the per-tool repair loop (see {@link AgentToolExecutionCoordinator}),
6856
- * so the AI SDK must surface tool calls back to us instead of auto-running them.
6857
- * 2. The AI SDK's `asSchema` helper discriminates between Zod v3 / Zod v4 / Standard Schema via
6858
- * runtime feature-detection (`~standard`, `_zod`, etc.). Handing it a pre-built
6859
- * {@link jsonSchema} record — which is tagged with `Symbol.for('vercel.ai.schema')` — skips all
6860
- * of that detection and guarantees the provider receives a draft-07 JSON Schema with
6861
- * `additionalProperties: false` at every object depth (see {@link OpenAiStrictJsonSchemaFactory}
6862
- * for the same logic applied to structured-output schemas). Codemation still runs its own Zod
6863
- * validation on tool inputs before execute — the schema handed to the model is advisory.
6864
- */
6865
6528
  buildToolSet(itemScopedTools) {
6866
6529
  if (itemScopedTools.length === 0) return void 0;
6867
6530
  const toolSet = {};
@@ -6879,10 +6542,6 @@ let AIAgentNode = class AIAgentNode$1 {
6879
6542
  }
6880
6543
  return toolSet;
6881
6544
  }
6882
- /**
6883
- * One `generateText` turn (no auto tool execution) with Codemation-owned child-span telemetry
6884
- * and connection-invocation state recording. Accepts a pre-built ToolSet.
6885
- */
6886
6545
  async invokeTextTurnWithToolSet(prepared, itemInputsByPort, messages, tools) {
6887
6546
  const invocationId = __codemation_core.ConnectionInvocationIdFactory.create();
6888
6547
  const startedAt = /* @__PURE__ */ new Date();
@@ -6993,11 +6652,6 @@ let AIAgentNode = class AIAgentNode$1 {
6993
6652
  });
6994
6653
  }
6995
6654
  }
6996
- /**
6997
- * Structured-output turn: runs `generateText({ output: Output.object({ schema }) })` via the
6998
- * structured-output runner. We keep this as a separate helper because the runner needs the raw
6999
- * validated value (not just text) back, and must be able to retry on Zod failures.
7000
- */
7001
6655
  async invokeStructuredTurn(prepared, itemInputsByPort, schema, messages, structuredOptions) {
7002
6656
  const invocationId = __codemation_core.ConnectionInvocationIdFactory.create();
7003
6657
  const startedAt = /* @__PURE__ */ new Date();
@@ -7122,13 +6776,6 @@ let AIAgentNode = class AIAgentNode$1 {
7122
6776
  providerOptions: overrides?.providerOptions ?? defaults.providerOptions
7123
6777
  };
7124
6778
  }
7125
- /**
7126
- * Build a no-code-friendly output payload for an LLM round.
7127
- *
7128
- * Always includes `content` (matching the canvas snapshot shape used elsewhere) and adds a
7129
- * `toolCalls` array when the round produced tool calls so the execution inspector surfaces the
7130
- * planned calls instead of just an empty `""` for tool-only rounds.
7131
- */
7132
6779
  summarizeTurnOutput(turnResult) {
7133
6780
  if (turnResult.toolCalls.length === 0) return { content: turnResult.text };
7134
6781
  const toolCalls = turnResult.toolCalls.map((toolCall) => ({
@@ -7331,12 +6978,6 @@ let AIAgentNode = class AIAgentNode$1 {
7331
6978
  const binaries = await this.resolveInlineBinaries(attachments, ctx);
7332
6979
  return AgentBinaryContentFactory.withBinaries(promptMessages, binaries);
7333
6980
  }
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
6981
  selectBinaryAttachments(item, itemIndex, items, ctx) {
7341
6982
  const manual = ctx.config.binaries;
7342
6983
  if (manual !== void 0) return typeof manual === "function" ? manual({
@@ -7347,14 +6988,6 @@ let AIAgentNode = class AIAgentNode$1 {
7347
6988
  }) : manual;
7348
6989
  return item.binary ? Object.values(item.binary) : [];
7349
6990
  }
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
6991
  async resolveInlineBinaries(attachments, ctx) {
7359
6992
  const resolved = [];
7360
6993
  for (const attachment of attachments) {
@@ -7367,12 +7000,6 @@ let AIAgentNode = class AIAgentNode$1 {
7367
7000
  }
7368
7001
  return resolved;
7369
7002
  }
7370
- /**
7371
- * When `item.json.__source` matches an entry in `config.untrustedSources`
7372
- * (default: `["gmail", "ocr", "webhook"]`), wraps every user-role message
7373
- * content with an untrusted-external-source preamble so the LLM treats the
7374
- * content as data, not instructions.
7375
- */
7376
7003
  wrapUntrustedSourceMessages(messages, item, config$1) {
7377
7004
  const source = item.json !== null && typeof item.json === "object" ? item.json.__source : void 0;
7378
7005
  if (typeof source !== "string") return messages;
@@ -7465,10 +7092,6 @@ AIAgentNode = __decorate([
7465
7092
 
7466
7093
  //#endregion
7467
7094
  //#region src/nodes/AIAgentConfig.ts
7468
- /**
7469
- * AI agent: credential bindings are keyed to connection-owned LLM/tool node ids (ConnectionNodeIdFactory),
7470
- * not to the agent workflow node id.
7471
- */
7472
7095
  var AIAgent = class {
7473
7096
  kind = "node";
7474
7097
  type = AIAgentNode;
@@ -7566,11 +7189,6 @@ AssertionNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemat
7566
7189
 
7567
7190
  //#endregion
7568
7191
  //#region src/nodes/assertion.ts
7569
- /**
7570
- * Generic assertion node — the "callback" form. For declarative shorthands (StringEquals,
7571
- * JudgeByAgent) compose this with helpers added in later phases. Sets `emitsAssertions: true`
7572
- * so host-side persisters know to record its outputs as `TestAssertion` rows.
7573
- */
7574
7192
  var Assertion = class {
7575
7193
  kind = "node";
7576
7194
  type = AssertionNode;
@@ -7833,17 +7451,12 @@ HttpRequestNode = __decorate([(0, __codemation_core.node)({ packageName: "@codem
7833
7451
 
7834
7452
  //#endregion
7835
7453
  //#region src/nodes/httpRequest.ts
7836
- /**
7837
- * The built-in HTTP request credential type IDs accepted by the `HttpRequest` node.
7838
- * These match the four generic credential types shipped with `@codemation/core-nodes`.
7839
- */
7840
7454
  const HTTP_REQUEST_ACCEPTED_CREDENTIAL_TYPES = [
7841
7455
  bearerTokenCredentialType.definition.typeId,
7842
7456
  apiKeyCredentialType.definition.typeId,
7843
7457
  basicAuthCredentialType.definition.typeId,
7844
7458
  oauth2ClientCredentialsType.definition.typeId
7845
7459
  ];
7846
- /** Default maximum response size for binary mode: 100 MiB. */
7847
7460
  const DEFAULT_RESPONSE_SIZE_CAP_BYTES = 100 * 1024 * 1024;
7848
7461
  var HttpRequest = class {
7849
7462
  kind = "node";
@@ -8012,9 +7625,6 @@ var Filter = class {
8012
7625
  function getOriginIndex(item) {
8013
7626
  return (0, __codemation_core.getOriginIndexFromItem)(item);
8014
7627
  }
8015
- /**
8016
- * Tags items routed to fan-in merge-by-origin (same contract as {@link IfNode} / {@link SwitchNode}).
8017
- */
8018
7628
  function tagItemForRouterFanIn(args) {
8019
7629
  const { item, itemIndex, nodeId, inputPortLabel = "$in" } = args;
8020
7630
  const metaBase = item.meta && typeof item.meta === "object" ? item.meta : {};
@@ -8105,10 +7715,6 @@ IsTestRunNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemat
8105
7715
 
8106
7716
  //#endregion
8107
7717
  //#region src/nodes/isTestRun.ts
8108
- /**
8109
- * Branches per-item on whether the current run is a test run. Output ports: `true`, `false`.
8110
- * The wire payload is unchanged — this is a router, not a transform.
8111
- */
8112
7718
  var IsTestRun = class {
8113
7719
  kind = "node";
8114
7720
  type = IsTestRunNode;
@@ -8192,10 +7798,6 @@ var Split = class {
8192
7798
  type = SplitNode;
8193
7799
  execution = { hint: "local" };
8194
7800
  keepBinaries = true;
8195
- /**
8196
- * When splitting yields zero items for a batch, downstream single-input nodes still run once with an empty batch.
8197
- * Mirrors {@link MapData}'s empty-output behavior.
8198
- */
8199
7801
  continueWhenEmptyOutput = true;
8200
7802
  icon = "builtin:split-rows";
8201
7803
  id;
@@ -8249,15 +7851,6 @@ CronTriggerNode = __decorate([(0, __codemation_core.node)({ packageName: "@codem
8249
7851
 
8250
7852
  //#endregion
8251
7853
  //#region src/nodes/CronTriggerFactory.ts
8252
- /**
8253
- * Schedules a workflow on a standard cron expression.
8254
- *
8255
- * Each tick emits one item: `{ firedAt: string, scheduledFor: string }` — both ISO-8601 timestamps.
8256
- * `firedAt` is the wall-clock moment the callback ran; `scheduledFor` is the cron-computed
8257
- * firing instant (these differ when the job was delayed).
8258
- *
8259
- * Timezone defaults to UTC when omitted — cron without an explicit TZ is a DST footgun.
8260
- */
8261
7854
  var CronTrigger = class {
8262
7855
  kind = "trigger";
8263
7856
  type = CronTriggerNode;
@@ -8328,7 +7921,6 @@ var ManualTrigger = class ManualTrigger {
8328
7921
  defaultItems;
8329
7922
  id;
8330
7923
  description;
8331
- /** Manual runs often emit an empty batch; still schedule downstream by default. */
8332
7924
  continueWhenEmptyOutput = true;
8333
7925
  constructor(name = "Manual trigger", defaultItemsOrId, idOrOptions) {
8334
7926
  this.name = name;
@@ -8383,7 +7975,6 @@ var MapData = class {
8383
7975
  kind = "node";
8384
7976
  type = MapDataNode;
8385
7977
  execution = { hint: "local" };
8386
- /** Zero mapped items should still allow downstream nodes to run. */
8387
7978
  continueWhenEmptyOutput = true;
8388
7979
  icon = "lucide:square-pen";
8389
7980
  keepBinaries;
@@ -8616,11 +8207,6 @@ TestTriggerNode = __decorate([(0, __codemation_core.node)({ packageName: "@codem
8616
8207
 
8617
8208
  //#endregion
8618
8209
  //#region src/nodes/testTrigger.ts
8619
- /**
8620
- * Trigger config for a test fixture source. Drop one (or more) of these on the canvas alongside
8621
- * a workflow's live triggers; clicking "Run tests" on the Tests tab invokes
8622
- * {@link TestTriggerOptions.generateItems} via the TestSuiteOrchestrator.
8623
- */
8624
8210
  var TestTrigger = class {
8625
8211
  kind = "trigger";
8626
8212
  triggerKind = "test";
@@ -8694,7 +8280,6 @@ var Wait = class {
8694
8280
  kind = "node";
8695
8281
  type = WaitNode;
8696
8282
  execution = { hint: "local" };
8697
- /** Pass-through empty batches should still advance to downstream nodes. */
8698
8283
  continueWhenEmptyOutput = true;
8699
8284
  icon = "lucide:hourglass";
8700
8285
  id;
@@ -8796,6 +8381,39 @@ var WebhookTrigger = class WebhookTrigger {
8796
8381
  }
8797
8382
  };
8798
8383
 
8384
+ //#endregion
8385
+ //#region src/nodes/schedulePollingTrigger.ts
8386
+ const schedulePollingTrigger = (0, __codemation_core.definePollingTrigger)({
8387
+ key: "schedule.interval",
8388
+ packageName: "@codemation/core-nodes",
8389
+ title: "Run on schedule",
8390
+ description: "Emit one tick item on every poll cycle.",
8391
+ icon: "lucide:clock",
8392
+ pollIntervalMs: 6e4,
8393
+ initialState() {
8394
+ return { tick: 0 };
8395
+ },
8396
+ poll({ state }) {
8397
+ const tick = (state ?? { tick: 0 }).tick + 1;
8398
+ return {
8399
+ items: [{ json: {
8400
+ firedAt: (/* @__PURE__ */ new Date()).toISOString(),
8401
+ tick
8402
+ } }],
8403
+ nextState: { tick }
8404
+ };
8405
+ },
8406
+ execute(items) {
8407
+ return { main: items };
8408
+ },
8409
+ testItems() {
8410
+ return [{ json: {
8411
+ firedAt: (/* @__PURE__ */ new Date()).toISOString(),
8412
+ tick: 0
8413
+ } }];
8414
+ }
8415
+ });
8416
+
8799
8417
  //#endregion
8800
8418
  //#region src/nodes/ConnectionCredentialNode.ts
8801
8419
  let ConnectionCredentialNode = class ConnectionCredentialNode$1 {
@@ -8809,11 +8427,6 @@ ConnectionCredentialNode = __decorate([(0, __codemation_core.node)({ packageName
8809
8427
 
8810
8428
  //#endregion
8811
8429
  //#region src/register.types.ts
8812
- /**
8813
- * Registrar for built-in nodes. In a real project, this would use tsyringe's
8814
- * container.registerSingleton(...). For the skeleton we keep it token-based:
8815
- * the engine resolves node implementations by class token.
8816
- */
8817
8430
  function registerCoreNodes(container) {}
8818
8431
 
8819
8432
  //#endregion
@@ -9042,9 +8655,6 @@ function workflow(id) {
9042
8655
 
9043
8656
  //#endregion
9044
8657
  //#region src/workflows/AIAgentConnectionWorkflowExpander.ts
9045
- /**
9046
- * Materializes connection-owned child nodes and {@link WorkflowDefinition.connections} for AI agent nodes.
9047
- */
9048
8658
  var AIAgentConnectionWorkflowExpander = class {
9049
8659
  constructor(connectionCredentialNodeConfigFactory, mcpServerResolver) {
9050
8660
  this.connectionCredentialNodeConfigFactory = connectionCredentialNodeConfigFactory;
@@ -9312,16 +8922,6 @@ const collectionDeleteNode = (0, __codemation_core.defineNode)({
9312
8922
  function resolveSubjectField(field, item) {
9313
8923
  return typeof field === "function" ? field({ item }) : field;
9314
8924
  }
9315
- /**
9316
- * Auto-detecting inbox approval node.
9317
- *
9318
- * Uses `ctx.resolve(InboxChannelResolverToken)` to pick the right inbox channel
9319
- * at runtime:
9320
- * - In managed mode (PairingConfig present): routes to the control-plane inbox.
9321
- * - Otherwise: routes to the local inbox.
9322
- *
9323
- * Authors use this node directly; no extra wiring needed per deployment mode.
9324
- */
9325
8925
  const inboxApproval = (0, __codemation_core.defineHumanApprovalNode)({
9326
8926
  key: "inbox.approval",
9327
8927
  title: "Inbox Approval",
@@ -9714,5 +9314,6 @@ exports.inboxApproval = inboxApproval;
9714
9314
  exports.oauth2ClientCredentialsType = oauth2ClientCredentialsType;
9715
9315
  exports.openAiChatModelPresets = openAiChatModelPresets;
9716
9316
  exports.registerCoreNodes = registerCoreNodes;
9317
+ exports.schedulePollingTrigger = schedulePollingTrigger;
9717
9318
  exports.workflow = workflow;
9718
9319
  //# sourceMappingURL=index.cjs.map