@codemation/core-nodes-ocr 0.2.7 → 0.2.8

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.
@@ -1,5 +1,5 @@
1
- import { n as analyzeImageNode, o as azureContentUnderstandingCredentialType, r as analyzeDocumentNode, t as analyzeInvoiceNode } from "./analyzeInvoiceNode-BqZsN8iL.js";
2
- import { AgentConfigInspector, AgentGuardrailDefaults, AgentMessageConfigNormalizer, CallableToolConfig, ChildExecutionScopeFactory, CodemationTelemetryAttributeNames, CodemationTelemetryMetricNames, ConnectionInvocationIdFactory, ConnectionNodeIdFactory, CoreTokens, GenAiTelemetryAttributeNames, InboxChannelResolverToken, ItemExprResolver, ItemsInputNormalizer, NodeBackedToolConfig, NodeOutputNormalizer, RunnableOutputBehaviorResolver, SuspensionRequest, chatModel, defineCredential, defineHumanApprovalNode, defineNode, emitPorts, getOriginIndexFromItem, inject, injectable, isPortsEmission, node } from "@codemation/core";
1
+ import { n as analyzeImageNode, o as azureContentUnderstandingCredentialType, r as analyzeDocumentNode, t as analyzeInvoiceNode } from "./analyzeInvoiceNode-BQzww-XC.js";
2
+ import { AgentConfigInspector, AgentGuardrailDefaults, AgentMessageConfigNormalizer, CallableToolConfig, ChildExecutionScopeFactory, CodemationTelemetryAttributeNames, CodemationTelemetryMetricNames, ConnectionInvocationIdFactory, ConnectionNodeIdFactory, CoreTokens, GenAiTelemetryAttributeNames, InboxChannelResolverToken, ItemExprResolver, ItemsInputNormalizer, NodeBackedToolConfig, NodeOutputNormalizer, RunnableOutputBehaviorResolver, SuspensionRequest, chatModel, defineCredential, defineHumanApprovalNode, defineNode, definePollingTrigger, emitPorts, getOriginIndexFromItem, inject, injectable, isPortsEmission, node } from "@codemation/core";
3
3
  import dns from "node:dns/promises";
4
4
  import { toJSONSchema } from "zod/v4/core";
5
5
  import { CredentialResolverFactory } from "@codemation/core/bootstrap";
@@ -7,9 +7,6 @@ import { createHash, createHmac, randomBytes } from "node:crypto";
7
7
  import { ZodError, z } from "zod";
8
8
 
9
9
  //#region ../core-nodes/src/credentials/ApiKeyCredentialType.ts
10
- /**
11
- * API key credential that injects a key either as an HTTP header or a query parameter.
12
- */
13
10
  const apiKeyCredentialType = defineCredential({
14
11
  key: "core-nodes.api-key",
15
12
  label: "API Key",
@@ -57,10 +54,6 @@ const apiKeyCredentialType = defineCredential({
57
54
 
58
55
  //#endregion
59
56
  //#region ../core-nodes/src/credentials/BasicAuthCredentialType.ts
60
- /**
61
- * HTTP Basic authentication credential.
62
- * Session sets `Authorization: Basic <base64(username:password)>`.
63
- */
64
57
  const basicAuthCredentialType = defineCredential({
65
58
  key: "core-nodes.basic-auth",
66
59
  label: "Basic Auth",
@@ -98,10 +91,6 @@ const basicAuthCredentialType = defineCredential({
98
91
 
99
92
  //#endregion
100
93
  //#region ../core-nodes/src/credentials/BearerTokenCredentialType.ts
101
- /**
102
- * Simple Bearer token credential.
103
- * Session sets `Authorization: Bearer <token>` on every request.
104
- */
105
94
  const bearerTokenCredentialType = defineCredential({
106
95
  key: "core-nodes.bearer-token",
107
96
  label: "Bearer Token",
@@ -160,24 +149,6 @@ var OAuth2TokenExchangeFactory = class {
160
149
 
161
150
  //#endregion
162
151
  //#region ../core-nodes/src/credentials/OAuth2ClientCredentialsTypeFactory.ts
163
- /**
164
- * OAuth2 client-credentials flow credential.
165
- *
166
- * This is a machine-to-machine flow: no user redirect occurs. The session
167
- * POSTs to the configured `tokenUrl` with `client_credentials` grant, caches
168
- * the resulting access token for the duration of the session, and injects it
169
- * as `Authorization: Bearer <token>` on each request.
170
- *
171
- * Token caching is per-session only (one createSession call = one token fetch
172
- * at most). Cross-session caching would require host-level state and is out of
173
- * scope here. Because the engine creates a fresh session per execution, a new
174
- * token is fetched once per node activation.
175
- *
176
- * NOTE: `auth` is intentionally omitted from the definition. The OAuth2
177
- * `auth: { kind: "oauth2" }` shape signals an authorization-code / user-redirect
178
- * flow; using it here would cause the host UI to render an OAuth consent button
179
- * that goes nowhere. Client-credentials is a purely server-side flow.
180
- */
181
152
  const oauth2ClientCredentialsType = defineCredential({
182
153
  key: "core-nodes.oauth2-client-credentials",
183
154
  label: "OAuth2 Client Credentials",
@@ -261,10 +232,6 @@ const oauth2ClientCredentialsType = defineCredential({
261
232
 
262
233
  //#endregion
263
234
  //#region ../core-nodes/src/http/SSRFBlockedError.ts
264
- /**
265
- * Thrown when an HTTP request target resolves to a private, link-local, or
266
- * loopback address and `allowPrivateNetworkTargets` is not set.
267
- */
268
235
  var SSRFBlockedError = class extends Error {
269
236
  resolvedIp;
270
237
  constructor(host, resolvedIp) {
@@ -276,26 +243,7 @@ var SSRFBlockedError = class extends Error {
276
243
 
277
244
  //#endregion
278
245
  //#region ../core-nodes/src/http/SsrfGuard.ts
279
- /** Emitted once per process when NODE_ENV=production and no allowedOutboundHosts is set. */
280
246
  let _productionNoAllowlistWarned = false;
281
- /**
282
- * Guards HTTP requests against Server-Side Request Forgery (SSRF) by
283
- * DNS-resolving the target host and rejecting private/link-local/loopback
284
- * addresses.
285
- *
286
- * Blocked ranges:
287
- * - RFC-1918: 10/8, 172.16/12, 192.168/16
288
- * - Link-local: 169.254/16
289
- * - Loopback: 127/8, ::1
290
- *
291
- * When `allowedOutboundHosts` is set, every resolved DNS target must match
292
- * at least one entry in the list (exact hostname or `*.example.com` wildcard).
293
- * When unset, existing behaviour applies: private ranges blocked, public allowed.
294
- *
295
- * Call {@link check} before making any outbound HTTP request.
296
- * Pass `allowPrivate: true` to bypass the private-network guard for trusted workflows
297
- * (allowedOutboundHosts allowlist is still applied when set).
298
- */
299
247
  var SsrfGuard = class {
300
248
  constructor(allowedOutboundHosts) {
301
249
  this.allowedOutboundHosts = allowedOutboundHosts;
@@ -304,15 +252,6 @@ var SsrfGuard = class {
304
252
  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.");
305
253
  }
306
254
  }
307
- /**
308
- * Resolves the host of `url` via DNS and throws {@link SSRFBlockedError}
309
- * if any resolved address falls in a blocked range, or if the host does not
310
- * match the operator-configured allowlist (when set).
311
- *
312
- * @param url - Fully-qualified URL of the intended request target.
313
- * @param allowPrivate - When `true`, the private-network check is skipped.
314
- * The allowedOutboundHosts check is still applied when set.
315
- */
316
255
  async check(url, allowPrivate) {
317
256
  if (allowPrivate && !this.allowedOutboundHosts?.length) return;
318
257
  let host;
@@ -336,10 +275,6 @@ var SsrfGuard = class {
336
275
  }
337
276
  for (const { address } of addresses) if (this.isPrivateAddress(address)) throw new SSRFBlockedError(host, address);
338
277
  }
339
- /**
340
- * Returns true when `host` matches at least one entry in `allowedOutboundHosts`.
341
- * Supports exact hostnames (`api.example.com`) and wildcard prefixes (`*.example.com`).
342
- */
343
278
  isHostAllowed(host) {
344
279
  for (const allowed of this.allowedOutboundHosts ?? []) if (allowed.startsWith("*.")) {
345
280
  const suffix = allowed.slice(1);
@@ -373,21 +308,6 @@ var SsrfGuard = class {
373
308
 
374
309
  //#endregion
375
310
  //#region ../core-nodes/src/http/HttpRequestExecutor.ts
376
- /**
377
- * Executes a single HTTP request described by {@link HttpRequestSpec}.
378
- *
379
- * - Credential sessions provide header/query deltas via `applyToRequest`.
380
- * - Body encoding is delegated to {@link HttpBodyBuilder}.
381
- * - URL query merging is delegated to {@link HttpUrlBuilder}.
382
- * - SSRF protection is delegated to {@link SsrfGuard} (injected).
383
- * - Binary response bodies: when `download.mode` triggers binary attach, the
384
- * `bodyBinaryName` field is set in the result but the body is NOT read here.
385
- * Callers that need binary attachment should use `buildRequest` to get the
386
- * resolved URL + init and make the fetch + binary attach themselves.
387
- *
388
- * Collaborators (`fetch`, body builder, url builder, ssrfGuard) are injected so
389
- * callers own construction at composition roots and tests can supply deterministic stubs.
390
- */
391
311
  var HttpRequestExecutor = class {
392
312
  constructor(fetchFn, bodyBuilder, urlBuilder, ssrfGuard) {
393
313
  this.fetchFn = fetchFn;
@@ -395,14 +315,6 @@ var HttpRequestExecutor = class {
395
315
  this.urlBuilder = urlBuilder;
396
316
  this.ssrfGuard = ssrfGuard;
397
317
  }
398
- /**
399
- * Builds the fetch init (headers, query, body) from the spec + credential delta,
400
- * returning both the resolved URL and the RequestInit so callers can make the
401
- * actual fetch call themselves (useful for streaming / binary attach).
402
- *
403
- * Also performs SSRF protection via the injected {@link SsrfGuard} before
404
- * returning — throws {@link SSRFBlockedError} if the target is a private address.
405
- */
406
318
  async buildRequest(spec, item) {
407
319
  await this.ssrfGuard.check(spec.url, spec.allowPrivateNetworkTargets ?? false);
408
320
  const credentialDelta = spec.credential?.applyToRequest(spec) ?? {};
@@ -426,12 +338,6 @@ var HttpRequestExecutor = class {
426
338
  }
427
339
  };
428
340
  }
429
- /**
430
- * Executes an HTTP request and returns parsed result.
431
- * For binary downloads (when `shouldAttachBody` is true), the body is NOT consumed
432
- * and callers must call `ctx.binary.attach` directly using the resolved URL + init
433
- * (available via `buildRequest`).
434
- */
435
341
  async execute(spec, item) {
436
342
  const { url: resolvedUrl, init } = await this.buildRequest(spec, item);
437
343
  const response = await this.fetchFn(resolvedUrl, init);
@@ -488,10 +394,6 @@ var HttpRequestExecutor = class {
488
394
 
489
395
  //#endregion
490
396
  //#region ../core-nodes/src/http/HttpBodyBuilder.ts
491
- /**
492
- * Builds a fetch-compatible `BodyInit` + Content-Type pair from an {@link HttpBodySpec}.
493
- * Multipart binaries are read from `item.binary` via `ctx.binary.openReadStream`.
494
- */
495
397
  var HttpBodyBuilder = class {
496
398
  async build(spec, item, ctx) {
497
399
  if (!spec || spec.kind === "none") return;
@@ -562,10 +464,6 @@ var HttpBodyBuilder = class {
562
464
 
563
465
  //#endregion
564
466
  //#region ../core-nodes/src/http/HttpUrlBuilder.ts
565
- /**
566
- * Merges query parameters into a base URL.
567
- * Handles both scalar and array values, and preserves any existing params.
568
- */
569
467
  var HttpUrlBuilder = class {
570
468
  build(baseUrl, query) {
571
469
  if (!query || Object.keys(query).length === 0) return baseUrl;
@@ -609,11 +507,6 @@ OpenAIChatModelFactory = __decorate([chatModel({ packageName: "@codemation/core-
609
507
 
610
508
  //#endregion
611
509
  //#region ../core-nodes/src/nodes/ConnectionCredentialExecutionContextFactory.ts
612
- /**
613
- * Builds a {@link NodeExecutionContext} whose identity for credential binding and `getCredential`
614
- * is a **connection-owned** workflow node id (`ConnectionNodeIdFactory` in `@codemation/core`),
615
- * not the executing parent node. Use for LLM slots, tool slots, or any connection-scoped owner.
616
- */
617
510
  var ConnectionCredentialExecutionContextFactory = class {
618
511
  credentialResolverFactory;
619
512
  constructor(credentialSessions) {
@@ -636,15 +529,6 @@ let AIAgentExecutionHelpersFactory = class AIAgentExecutionHelpersFactory$1 {
636
529
  createConnectionCredentialExecutionContextFactory(credentialSessions) {
637
530
  return new ConnectionCredentialExecutionContextFactory(credentialSessions);
638
531
  }
639
- /**
640
- * Produces a plain JSON Schema object (`draft-07`) from a Zod schema, as needed by
641
- * OpenAI tool-parameter schemas and the structured-output repair prompt.
642
- * - Prefers the schema's **instance** `toJSONSchema(...)` method so we stay inside the Zod
643
- * instance that created the schema (works across consumer/framework tsx namespaces — see
644
- * {@link ZodInstanceToJsonSchema}). Falls back to the framework-imported module function.
645
- * - Strips root `$schema` (OpenAI ignores it).
646
- * - Sanitizes `required` for cfworker json-schema compatibility (must be a string array or absent).
647
- */
648
532
  createJsonSchemaRecord(inputSchema, options) {
649
533
  const { $schema: _draftSchemaOmitted,...rest } = this.convertZodSchemaToJsonSchema(inputSchema, { target: "draft-07" });
650
534
  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)}).`);
@@ -653,20 +537,11 @@ let AIAgentExecutionHelpersFactory = class AIAgentExecutionHelpersFactory$1 {
653
537
  this.sanitizeJsonSchemaRequiredKeywordsForCfworker(rest);
654
538
  return rest;
655
539
  }
656
- /**
657
- * Runs Zod's `toJSONSchema` via the schema's own instance method when available, so consumer
658
- * schemas loaded under a different tsx namespace still convert correctly. If the caller handed us
659
- * a payload that lacks that method (e.g. a plain JSON Schema record or a Zod instance whose
660
- * prototype was stripped), we fall back to the framework-bundled module function.
661
- */
662
540
  convertZodSchemaToJsonSchema(inputSchema, params) {
663
541
  const candidate = inputSchema.toJSONSchema;
664
542
  if (typeof candidate === "function") return candidate.call(inputSchema, params);
665
543
  return toJSONSchema(inputSchema, params);
666
544
  }
667
- /**
668
- * `@cfworker/json-schema` iterates `schema.required` with `for...of`; it must be a string array or absent.
669
- */
670
545
  sanitizeJsonSchemaRequiredKeywordsForCfworker(node$1) {
671
546
  if (!node$1 || typeof node$1 !== "object" || Array.isArray(node$1)) return;
672
547
  const o = node$1;
@@ -813,11 +688,6 @@ var OpenAIChatModelConfig = class {
813
688
 
814
689
  //#endregion
815
690
  //#region ../core-nodes/src/chatModels/OpenAiChatModelPresetsFactory.ts
816
- /**
817
- * Default OpenAI chat model configs for scaffolds and demos (icon + label match {@link OpenAIChatModelConfig} defaults).
818
- * Prefer importing {@link openAiChatModelPresets} from here or from the consumer template re-export
819
- * instead of repeating {@link OpenAIChatModelConfig} construction in app workflows.
820
- */
821
691
  var OpenAiChatModelPresets = class {
822
692
  demoGpt4oMini = new OpenAIChatModelConfig("OpenAI", "gpt-4o-mini");
823
693
  demoGpt41 = new OpenAIChatModelConfig("OpenAI", "gpt-4.1");
@@ -826,19 +696,6 @@ const openAiChatModelPresets = new OpenAiChatModelPresets();
826
696
 
827
697
  //#endregion
828
698
  //#region ../core-nodes/src/chatModels/ManagedHmacSignerFactory.types.ts
829
- /**
830
- * Creates an HMAC-signing fetch wrapper that authenticates requests to
831
- * Codemation managed services (LLM broker, doc-scanner) with the
832
- * Codemation-Hmac v=1 scheme.
833
- *
834
- * Mirrors HmacRequestSigner from @codemation/host/pairing without importing
835
- * that package (which would create a circular dependency since @codemation/host
836
- * depends on @codemation/core-nodes).
837
- *
838
- * @param workspaceId - Workspace identifier injected by the CP provisioner.
839
- * @param pairingSecret - Base64-encoded 32-byte HMAC key injected by the provisioner.
840
- * @param options - Optional behaviour flags and test seams.
841
- */
842
699
  function managedHmacFetchFactory(workspaceId, pairingSecret, options) {
843
700
  const signBody = options?.signBody ?? true;
844
701
  return async (input, init) => {
@@ -857,10 +714,6 @@ function managedHmacFetchFactory(workspaceId, pairingSecret, options) {
857
714
  });
858
715
  };
859
716
  }
860
- /**
861
- * Produces a Codemation-Hmac v=1 Authorization header value.
862
- * Algorithm must match HmacVerifier.computeSignature() in the control-plane.
863
- */
864
717
  function buildHmacAuthHeader(workspaceId, pairingSecret, method, url, body, overrides) {
865
718
  const ts = overrides?.now ? overrides.now() : Math.floor(Date.now() / 1e3);
866
719
  const nonce = overrides?.nonce ? overrides.nonce() : randomBytes(16).toString("base64");
@@ -902,21 +755,137 @@ let CodemationChatModelFactory = class CodemationChatModelFactory$1 {
902
755
  };
903
756
  CodemationChatModelFactory = __decorate([chatModel({ packageName: "@codemation/core-nodes" })], CodemationChatModelFactory);
904
757
 
758
+ //#endregion
759
+ //#region ../core-nodes/src/nodes/AgentToolResultContentFactory.ts
760
+ const MAX_INLINE_BYTES = 8 * 1024 * 1024;
761
+ const KNOWN_MCP_BLOCK_TYPES = new Set([
762
+ "text",
763
+ "image",
764
+ "audio",
765
+ "resource",
766
+ "resource_link"
767
+ ]);
768
+ var AgentToolResultContentFactory = class AgentToolResultContentFactory {
769
+ static tryMapToContentOutput(result) {
770
+ const blocks = AgentToolResultContentFactory.contentBlocks(result);
771
+ if (blocks === void 0) return void 0;
772
+ const parts = [];
773
+ let inlinedBytes = 0;
774
+ for (const block of blocks) {
775
+ const mapped = AgentToolResultContentFactory.mapBlock(block, inlinedBytes);
776
+ parts.push(mapped.part);
777
+ inlinedBytes += mapped.bytes;
778
+ }
779
+ return parts;
780
+ }
781
+ static contentBlocks(result) {
782
+ if (result === null || typeof result !== "object") return void 0;
783
+ const content = result.content;
784
+ if (!Array.isArray(content) || content.length === 0) return void 0;
785
+ if (!content.every((block) => block !== null && typeof block === "object" && typeof block.type === "string")) return void 0;
786
+ return content.some((block) => KNOWN_MCP_BLOCK_TYPES.has(block.type)) ? content : void 0;
787
+ }
788
+ static mapBlock(block, inlinedBytesSoFar) {
789
+ const type = block.type;
790
+ if (type === "text" && typeof block.text === "string") return {
791
+ part: {
792
+ type: "text",
793
+ text: block.text
794
+ },
795
+ bytes: 0
796
+ };
797
+ if (type === "image" && typeof block.data === "string" && typeof block.mimeType === "string") return AgentToolResultContentFactory.mapBinary({
798
+ base64: block.data,
799
+ mediaType: block.mimeType,
800
+ inlinedBytesSoFar
801
+ });
802
+ if (type === "resource" && block.resource) return AgentToolResultContentFactory.mapEmbeddedResource(block.resource, inlinedBytesSoFar);
803
+ if (type === "resource_link" && typeof block.uri === "string") {
804
+ const mime = typeof block.mimeType === "string" ? ` (${block.mimeType})` : "";
805
+ return {
806
+ part: {
807
+ type: "text",
808
+ text: `[linked resource: ${block.uri}${mime}]`
809
+ },
810
+ bytes: 0
811
+ };
812
+ }
813
+ return {
814
+ part: {
815
+ type: "text",
816
+ text: `[unsupported tool content block: ${String(type)}]`
817
+ },
818
+ bytes: 0
819
+ };
820
+ }
821
+ static mapEmbeddedResource(resource, inlinedBytesSoFar) {
822
+ if (typeof resource.text === "string") return {
823
+ part: {
824
+ type: "text",
825
+ text: resource.text
826
+ },
827
+ bytes: 0
828
+ };
829
+ if (typeof resource.blob === "string" && typeof resource.mimeType === "string") return AgentToolResultContentFactory.mapBinary({
830
+ base64: resource.blob,
831
+ mediaType: resource.mimeType,
832
+ filename: typeof resource.name === "string" ? resource.name : void 0,
833
+ inlinedBytesSoFar
834
+ });
835
+ return {
836
+ part: {
837
+ type: "text",
838
+ text: `[embedded resource: ${typeof resource.uri === "string" ? resource.uri : "unknown"}]`
839
+ },
840
+ bytes: 0
841
+ };
842
+ }
843
+ static mapBinary(args) {
844
+ const rawBytes = Math.floor(args.base64.length * 3 / 4);
845
+ if (args.inlinedBytesSoFar + rawBytes > MAX_INLINE_BYTES) {
846
+ const name = args.filename ? ` "${args.filename}"` : "";
847
+ const kb = Math.round(rawBytes / 1024);
848
+ return {
849
+ part: {
850
+ type: "text",
851
+ text: `[binary${name} (${args.mediaType}, ~${kb} KB) omitted: exceeds the per-tool-result inline limit]`
852
+ },
853
+ bytes: 0
854
+ };
855
+ }
856
+ if (args.mediaType.startsWith("image/")) return {
857
+ part: {
858
+ type: "image-data",
859
+ data: args.base64,
860
+ mediaType: args.mediaType
861
+ },
862
+ bytes: rawBytes
863
+ };
864
+ if (args.mediaType === "application/pdf") return {
865
+ part: {
866
+ type: "file-data",
867
+ data: args.base64,
868
+ mediaType: args.mediaType,
869
+ ...args.filename ? { filename: args.filename } : {}
870
+ },
871
+ bytes: rawBytes
872
+ };
873
+ return {
874
+ part: {
875
+ type: "text",
876
+ text: `[binary${args.filename ? ` "${args.filename}"` : ""} (${args.mediaType}) not inlined: unsupported by the model]`
877
+ },
878
+ bytes: 0
879
+ };
880
+ }
881
+ };
882
+
905
883
  //#endregion
906
884
  //#region ../core-nodes/src/nodes/AgentMessageFactory.ts
907
- /**
908
- * AI-SDK-shaped message construction for the AIAgent stack. Emits plain `ModelMessage[]`
909
- * ( `{ role: 'system' | 'user' | 'assistant' | 'tool', content: ... }` ) as consumed by
910
- * `generateText({ messages })` from the `ai` package.
911
- */
912
885
  var AgentMessageFactory = class AgentMessageFactory {
913
886
  static createPromptMessages(messages) {
914
887
  return messages.map((message) => this.createPromptMessage(message));
915
888
  }
916
- /**
917
- * Builds the assistant message that contains optional text plus one or more tool-call parts,
918
- * matching the shape AI SDK emits between steps.
919
- */
920
889
  static createAssistantWithToolCalls(text, toolCalls) {
921
890
  const content = [];
922
891
  if (text && text.length > 0) content.push({
@@ -934,24 +903,30 @@ var AgentMessageFactory = class AgentMessageFactory {
934
903
  content
935
904
  };
936
905
  }
937
- /**
938
- * Builds the `{ role: "tool", content: [{ type: "tool-result", ... }, ...] }` message returned
939
- * to the model after each tool round.
940
- */
941
- static createToolResultsMessage(executedToolCalls) {
906
+ static createToolResultsMessage(executedToolCalls, passToolBinariesToModel = true) {
942
907
  return {
943
908
  role: "tool",
944
909
  content: executedToolCalls.map((executed) => ({
945
910
  type: "tool-result",
946
911
  toolCallId: executed.toolCallId,
947
912
  toolName: executed.toolName,
948
- output: {
949
- type: "json",
950
- value: AgentMessageFactory.toToolResultJson(executed.result)
951
- }
913
+ output: AgentMessageFactory.toToolResultOutput(executed.result, passToolBinariesToModel)
952
914
  }))
953
915
  };
954
916
  }
917
+ static toToolResultOutput(result, passToolBinariesToModel) {
918
+ if (passToolBinariesToModel) {
919
+ const content = AgentToolResultContentFactory.tryMapToContentOutput(result);
920
+ if (content !== void 0) return {
921
+ type: "content",
922
+ value: content
923
+ };
924
+ }
925
+ return {
926
+ type: "json",
927
+ value: AgentMessageFactory.toToolResultJson(result)
928
+ };
929
+ }
955
930
  static toToolResultJson(value) {
956
931
  if (value === void 0) return null;
957
932
  try {
@@ -1094,10 +1069,6 @@ let AgentStructuredOutputRunner = class AgentStructuredOutputRunner$1 {
1094
1069
  }
1095
1070
  throw new Error(`Structured output required for AIAgent "${args.agentName}" (${args.nodeId}) but validation still failed after ${_AgentStructuredOutputRunner.repairAttemptCount} repair attempts: ${failure.validationError}`);
1096
1071
  }
1097
- /**
1098
- * Chooses strict mode for OpenAI chat-model configs, off otherwise. Extendable in future for
1099
- * other providers that adopt the same "supply a JSON Schema record directly" contract.
1100
- */
1101
1072
  resolveStructuredOutputOptions(chatModelConfig) {
1102
1073
  if (chatModelConfig.type !== OpenAIChatModelFactory) return;
1103
1074
  return {
@@ -1580,10 +1551,6 @@ let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
1580
1551
  extractErrorDetails(error) {
1581
1552
  return error.details;
1582
1553
  }
1583
- /**
1584
- * Extracts the text content from the last assistant message in the conversation snapshot.
1585
- * Used to populate `agentReasoning` in the HITL suspension metadata.
1586
- */
1587
1554
  extractLastAssistantText(conversation) {
1588
1555
  for (let i = conversation.length - 1; i >= 0; i--) {
1589
1556
  const msg = conversation[i];
@@ -1618,16 +1585,6 @@ AgentToolExecutionCoordinator = __decorate([
1618
1585
 
1619
1586
  //#endregion
1620
1587
  //#region ../core-nodes/src/nodes/AgentBinaryContentFactory.ts
1621
- /**
1622
- * Turns resolved file binaries into native AI SDK multimodal content parts and merges them into the
1623
- * agent prompt. Images (`image/*`) become {@link ImagePart}s; every other type (PDFs, office docs,
1624
- * CSV, JSON, …) becomes a {@link FilePart}. The provider maps these to its wire-level `image` /
1625
- * `document` blocks; an unsupported file type surfaces as a provider error at runtime.
1626
- *
1627
- * Parts are appended to the LAST user message so the binary travels alongside the author's prompt
1628
- * text (preserving any untrusted-source preamble that already wrapped that text). When no user
1629
- * message exists, a new user message carrying only the binaries is appended.
1630
- */
1631
1588
  var AgentBinaryContentFactory = class AgentBinaryContentFactory {
1632
1589
  static toContentPart(binary) {
1633
1590
  if (binary.mediaType.startsWith("image/")) return {
@@ -1706,20 +1663,6 @@ let NodeBackedToolRuntime = class NodeBackedToolRuntime$1 {
1706
1663
  outputs
1707
1664
  });
1708
1665
  }
1709
- /**
1710
- * Returns a re-rooted child ctx for nested-agent tools (so their LLM/tool connection ids derive
1711
- * from the tool connection node, telemetry parents under the tool-call span, and connection
1712
- * invocations carry `parentInvocationId`). Plain runnable tools (non-agent) keep the orchestrator
1713
- * ctx with only `config` swapped — no nesting concern.
1714
- *
1715
- * The caller (`AIAgentNode.createItemScopedTools`) already wraps the orchestrator ctx via
1716
- * `ConnectionCredentialExecutionContextFactory.forConnectionNode`, so `args.ctx.nodeId` is the
1717
- * tool's own connection node id (e.g. `AIAgentNode:2__conn__tool__searchInMail`). We pass that
1718
- * through as the sub-agent's `nodeId`; deriving another `toolConnectionNodeId(args.ctx.nodeId,
1719
- * config.name)` here would prepend a duplicate `__conn__tool__<name>` segment and exponentially
1720
- * deepen ids on each invocation, which also breaks credential resolution because user-provided
1721
- * bindings sit on the single-level connection node id.
1722
- */
1723
1666
  resolveNodeCtx(config, args) {
1724
1667
  const isNestedAgent = AgentConfigInspector.isAgentNodeConfig(config.node);
1725
1668
  const hooks = args.hooks;
@@ -1784,22 +1727,12 @@ NodeBackedToolRuntime = __decorate([
1784
1727
 
1785
1728
  //#endregion
1786
1729
  //#region ../core-nodes/src/nodes/BM25Index.ts
1787
- /**
1788
- * Minimal BM25 (Okapi BM25) implementation for indexing MCP tool descriptions.
1789
- *
1790
- * Parameters: k1=1.5, b=0.75 (standard defaults).
1791
- * Tokenisation: lowercase, split on non-alphanumerics, filter empties.
1792
- */
1793
1730
  var BM25Index = class {
1794
1731
  k1 = 1.5;
1795
1732
  b = .75;
1796
1733
  tf = [];
1797
1734
  df = /* @__PURE__ */ new Map();
1798
1735
  avgDocLen = 0;
1799
- /**
1800
- * Add all documents at once. After calling this, search is available.
1801
- * Documents are indexed in insertion order; search returns their indices.
1802
- */
1803
1736
  add(docs) {
1804
1737
  const docTerms = docs.map((d) => this.tokenize(d));
1805
1738
  let totalLen = 0;
@@ -1812,10 +1745,6 @@ var BM25Index = class {
1812
1745
  }
1813
1746
  this.avgDocLen = docTerms.length > 0 ? totalLen / docTerms.length : 0;
1814
1747
  }
1815
- /**
1816
- * Returns up to `limit` document indices ranked by BM25 score (highest first).
1817
- * Returns an empty array if the index is empty or the query matches nothing.
1818
- */
1819
1748
  search(query, limit) {
1820
1749
  const n = this.tf.length;
1821
1750
  if (n === 0) return [];
@@ -1856,26 +1785,12 @@ const PINNED_TOOLS_SOFT_LIMIT = 8;
1856
1785
  const PINNED_TOOLS_HARD_LIMIT = 16;
1857
1786
  const FIND_TOOLS_NAME = "find_tools";
1858
1787
  const FIND_TOOLS_DEFAULT_LIMIT = 5;
1859
- /**
1860
- * Default tool-loading strategy: BM25-indexed MCP tool deferral via a `find_tools` meta-tool.
1861
- *
1862
- * - Node-backed tools and pinned MCP tools are always included in every turn.
1863
- * - `find_tools(query, limit?)` is added to the tool set when MCP tools are indexed.
1864
- * - Tools surfaced by `find_tools` are included in subsequent turns.
1865
- *
1866
- * Not DI-managed; instantiated per agent execution by DeferredMetaToolStrategyFactory.
1867
- */
1868
1788
  var DeferredMetaToolStrategy = class {
1869
1789
  nodeBackedTools = {};
1870
1790
  pinnedTools = {};
1871
1791
  mcpEntries = [];
1872
1792
  toolsByServerId = /* @__PURE__ */ new Map();
1873
1793
  foundToolIds = /* @__PURE__ */ new Set();
1874
- /**
1875
- * `jsonSchema` from the `ai` SDK, loaded lazily in {@link initialize} so the SDK
1876
- * (~28MB RSS) stays off the boot path. `initialize` always runs before the sync
1877
- * `getToolsForTurn` → `buildFindToolsDefinition` path, so this is set before use.
1878
- */
1879
1794
  jsonSchema;
1880
1795
  constructor(bm25, warnFn) {
1881
1796
  this.bm25 = bm25;
@@ -2023,11 +1938,6 @@ let AIAgentNode = class AIAgentNode$1 {
2023
1938
  inputSchema = z.unknown();
2024
1939
  connectionCredentialExecutionContextFactory;
2025
1940
  preparedByExecutionContext = /* @__PURE__ */ new WeakMap();
2026
- /**
2027
- * The `ai` SDK, loaded lazily in {@link execute} so the SDK (~28MB RSS) stays
2028
- * off the boot path — non-AI workflows never load it. Every path runs through
2029
- * `execute` → `ensureAiSdk` before any sync helper touches `this.aiSdk`.
2030
- */
2031
1941
  aiSdk;
2032
1942
  aiSdkPromise = null;
2033
1943
  constructor(nodeResolver, credentialSessions, nodeBackedToolRuntime, executionHelpers, structuredOutputRunner, toolExecutionCoordinator, toolLoadingStrategyFactory, agentMcpIntegration) {
@@ -2051,15 +1961,9 @@ let AIAgentNode = class AIAgentNode$1 {
2051
1961
  };
2052
1962
  return (await this.runAgentForItem(prepared, itemWithMappedJson, args.itemIndex, args.items)).json;
2053
1963
  }
2054
- /** Load the `ai` SDK once per node instance (cached promise guards concurrent items). */
2055
1964
  async ensureAiSdk() {
2056
1965
  this.aiSdk = await (this.aiSdkPromise ??= import("./dist-DBYFkhSG.js"));
2057
1966
  }
2058
- /**
2059
- * Resume path: re-enters the agent loop after a HITL suspension.
2060
- * Reconstructs the conversation from the checkpoint, injects the human decision
2061
- * as a tool_result, and continues the loop from where it suspended.
2062
- */
2063
1967
  async executeResumed(args, resumeContext) {
2064
1968
  const { ctx } = args;
2065
1969
  const taskMetadata = resumeContext.task.metadata ?? {};
@@ -2086,7 +1990,7 @@ let AIAgentNode = class AIAgentNode$1 {
2086
1990
  result: decision,
2087
1991
  serialized: JSON.stringify(decision)
2088
1992
  };
2089
- const conversation = [...checkpoint.conversation, AgentMessageFactory.createToolResultsMessage([toolResultEntry])];
1993
+ const conversation = [...checkpoint.conversation, AgentMessageFactory.createToolResultsMessage([toolResultEntry], ctx.config.passToolBinariesToModel !== false)];
2090
1994
  const loopResult = await this.runTurnLoopUntilFinalAnswer({
2091
1995
  prepared,
2092
1996
  itemInputsByPort,
@@ -2106,10 +2010,6 @@ let AIAgentNode = class AIAgentNode$1 {
2106
2010
  const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, loopResult.finalText, itemScopedTools.length > 0);
2107
2011
  return this.buildOutputItem(item, outputJson).json;
2108
2012
  }
2109
- /**
2110
- * Normalizes a {@link ResumeContext} decision into a flat JSON-serializable shape
2111
- * suitable for injection as a tool_result content.
2112
- */
2113
2013
  normalizeDecision(resumeContext) {
2114
2014
  const { decision } = resumeContext;
2115
2015
  if (decision.kind === "decided") {
@@ -2236,16 +2136,6 @@ let AIAgentNode = class AIAgentNode$1 {
2236
2136
  const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, loopResult.finalText, itemScopedTools.length > 0);
2237
2137
  return this.buildOutputItem(item, outputJson);
2238
2138
  }
2239
- /**
2240
- * Multi-turn loop:
2241
- * - Each turn is a single `generateText` call with tools exposed but **not auto-executed**
2242
- * (we control tool dispatch so that {@link AgentToolExecutionCoordinator} drives repair /
2243
- * connection-invocation recording / transient-error handling exactly like before).
2244
- * - When the model returns no tool calls the loop ends with the model's text as the final answer.
2245
- * - Respects `guardrails.maxTurns` and `guardrails.onTurnLimitReached`.
2246
- * - Strategy-owned tool calls (e.g. `find_tools`) are dispatched via the strategy, not the
2247
- * coordinator; their results are tracked so subsequent turns receive the discovered tools.
2248
- */
2249
2139
  async runTurnLoopUntilFinalAnswer(args) {
2250
2140
  const { prepared, itemInputsByPort, itemScopedTools, conversation } = args;
2251
2141
  const { ctx, guardrails, toolLoadingStrategy } = prepared;
@@ -2253,7 +2143,6 @@ let AIAgentNode = class AIAgentNode$1 {
2253
2143
  let toolCallCount = args.resumedToolCallCount ?? 0;
2254
2144
  let turnCount = 0;
2255
2145
  const repairAttemptsByToolName = /* @__PURE__ */ new Map();
2256
- /** Tool IDs surfaced by find_tools across all prior turns in this item run. */
2257
2146
  let previousFoundToolIds = [];
2258
2147
  for (let turn = 1; turn <= guardrails.maxTurns; turn++) {
2259
2148
  turnCount = turn;
@@ -2306,7 +2195,7 @@ let AIAgentNode = class AIAgentNode$1 {
2306
2195
  coordinatorExecutedCalls.push(...executed);
2307
2196
  }
2308
2197
  const allExecutedCalls = [...strategyExecutedCalls, ...coordinatorExecutedCalls];
2309
- this.appendAssistantAndToolMessages(conversation, result.assistantMessage, result.text, result.toolCalls, allExecutedCalls);
2198
+ this.appendAssistantAndToolMessages(conversation, result.assistantMessage, result.text, result.toolCalls, allExecutedCalls, ctx.config.passToolBinariesToModel !== false);
2310
2199
  }
2311
2200
  return {
2312
2201
  finalText,
@@ -2321,8 +2210,8 @@ let AIAgentNode = class AIAgentNode$1 {
2321
2210
  if (guardrails.onTurnLimitReached === "respondWithLastMessage") return;
2322
2211
  throw new Error(`AIAgent "${ctx.config.name ?? ctx.nodeId}" reached maxTurns=${guardrails.maxTurns} before producing a final response.`);
2323
2212
  }
2324
- appendAssistantAndToolMessages(conversation, assistantMessage, text, toolCalls, executedToolCalls) {
2325
- conversation.push(assistantMessage ?? AgentMessageFactory.createAssistantWithToolCalls(text, toolCalls), AgentMessageFactory.createToolResultsMessage(executedToolCalls));
2213
+ appendAssistantAndToolMessages(conversation, assistantMessage, text, toolCalls, executedToolCalls, passToolBinariesToModel) {
2214
+ conversation.push(assistantMessage ?? AgentMessageFactory.createAssistantWithToolCalls(text, toolCalls), AgentMessageFactory.createToolResultsMessage(executedToolCalls, passToolBinariesToModel));
2326
2215
  }
2327
2216
  async resolveFinalOutputJson(prepared, itemInputsByPort, conversation, finalText, wasToolEnabledRun) {
2328
2217
  if (!prepared.ctx.config.outputSchema) return AgentOutputFactory.fromAgentContent(finalText);
@@ -2383,12 +2272,6 @@ let AIAgentNode = class AIAgentNode$1 {
2383
2272
  };
2384
2273
  });
2385
2274
  }
2386
- /**
2387
- * Resolves the HITL behavior for a tool binding, or `undefined` when it is not a HITL tool.
2388
- * A binding is HITL if either the backing node carries a `defineHumanApprovalNode` marker or the
2389
- * binding sets a per-binding `onRejected` via `asTool(..., { onRejected })`. The per-binding value
2390
- * wins over the node marker, so two tools backed by the same node can reject differently.
2391
- */
2392
2275
  resolveHumanApprovalBehavior(config) {
2393
2276
  if (!this.isNodeBackedToolConfig(config)) return void 0;
2394
2277
  const marker = config.node.humanApprovalToolBehavior;
@@ -2396,11 +2279,6 @@ let AIAgentNode = class AIAgentNode$1 {
2396
2279
  if (marker === void 0 && perBinding === void 0) return void 0;
2397
2280
  return { onRejected: perBinding ?? marker?.onRejected ?? "return" };
2398
2281
  }
2399
- /**
2400
- * Invoke a text turn using the merged tool set from item-scoped tools (coordinator-managed)
2401
- * and strategy tools (find_tools + discovered MCP tools).
2402
- * Strategy tools take precedence for names that overlap.
2403
- */
2404
2282
  async invokeTextTurnWithStrategyTools(prepared, itemInputsByPort, messages, itemScopedTools, strategyTools) {
2405
2283
  const itemToolSet = this.buildToolSet(itemScopedTools);
2406
2284
  const strategyHasTools = Object.keys(strategyTools).length > 0;
@@ -2411,10 +2289,6 @@ let AIAgentNode = class AIAgentNode$1 {
2411
2289
  } : void 0;
2412
2290
  return this.invokeTextTurnWithToolSet(prepared, itemInputsByPort, messages, mergedTools);
2413
2291
  }
2414
- /**
2415
- * Removes `execute` properties from ToolSet entries so the AI SDK does not
2416
- * auto-execute them within `generateText`. Codemation owns all tool dispatch.
2417
- */
2418
2292
  stripExecuteCallbacks(tools) {
2419
2293
  const stripped = {};
2420
2294
  for (const [name, def] of Object.entries(tools)) {
@@ -2423,12 +2297,6 @@ let AIAgentNode = class AIAgentNode$1 {
2423
2297
  }
2424
2298
  return stripped;
2425
2299
  }
2426
- /**
2427
- * Builds a ToolSet from resolved tools for strategy initialization.
2428
- * The strategy uses this for its "always-included" node-backed tool descriptions.
2429
- * HITL tools (detected via the `humanApprovalToolBehavior` field set by `defineHumanApprovalNode`) get the solo-constraint sentence
2430
- * appended to their description.
2431
- */
2432
2300
  buildToolSetFromResolved(resolvedTools) {
2433
2301
  if (resolvedTools.length === 0) return {};
2434
2302
  const toolSet = {};
@@ -2446,20 +2314,6 @@ let AIAgentNode = class AIAgentNode$1 {
2446
2314
  }
2447
2315
  return toolSet;
2448
2316
  }
2449
- /**
2450
- * Builds an AI SDK {@link ToolSet} where every tool ships a pre-converted JSON Schema (via
2451
- * {@link jsonSchema}) — not the raw Zod schema — and carries **no** `execute`. Two reasons:
2452
- *
2453
- * 1. Codemation owns tool dispatch + the per-tool repair loop (see {@link AgentToolExecutionCoordinator}),
2454
- * so the AI SDK must surface tool calls back to us instead of auto-running them.
2455
- * 2. The AI SDK's `asSchema` helper discriminates between Zod v3 / Zod v4 / Standard Schema via
2456
- * runtime feature-detection (`~standard`, `_zod`, etc.). Handing it a pre-built
2457
- * {@link jsonSchema} record — which is tagged with `Symbol.for('vercel.ai.schema')` — skips all
2458
- * of that detection and guarantees the provider receives a draft-07 JSON Schema with
2459
- * `additionalProperties: false` at every object depth (see {@link OpenAiStrictJsonSchemaFactory}
2460
- * for the same logic applied to structured-output schemas). Codemation still runs its own Zod
2461
- * validation on tool inputs before execute — the schema handed to the model is advisory.
2462
- */
2463
2317
  buildToolSet(itemScopedTools) {
2464
2318
  if (itemScopedTools.length === 0) return void 0;
2465
2319
  const toolSet = {};
@@ -2477,10 +2331,6 @@ let AIAgentNode = class AIAgentNode$1 {
2477
2331
  }
2478
2332
  return toolSet;
2479
2333
  }
2480
- /**
2481
- * One `generateText` turn (no auto tool execution) with Codemation-owned child-span telemetry
2482
- * and connection-invocation state recording. Accepts a pre-built ToolSet.
2483
- */
2484
2334
  async invokeTextTurnWithToolSet(prepared, itemInputsByPort, messages, tools) {
2485
2335
  const invocationId = ConnectionInvocationIdFactory.create();
2486
2336
  const startedAt = /* @__PURE__ */ new Date();
@@ -2591,11 +2441,6 @@ let AIAgentNode = class AIAgentNode$1 {
2591
2441
  });
2592
2442
  }
2593
2443
  }
2594
- /**
2595
- * Structured-output turn: runs `generateText({ output: Output.object({ schema }) })` via the
2596
- * structured-output runner. We keep this as a separate helper because the runner needs the raw
2597
- * validated value (not just text) back, and must be able to retry on Zod failures.
2598
- */
2599
2444
  async invokeStructuredTurn(prepared, itemInputsByPort, schema, messages, structuredOptions) {
2600
2445
  const invocationId = ConnectionInvocationIdFactory.create();
2601
2446
  const startedAt = /* @__PURE__ */ new Date();
@@ -2720,13 +2565,6 @@ let AIAgentNode = class AIAgentNode$1 {
2720
2565
  providerOptions: overrides?.providerOptions ?? defaults.providerOptions
2721
2566
  };
2722
2567
  }
2723
- /**
2724
- * Build a no-code-friendly output payload for an LLM round.
2725
- *
2726
- * Always includes `content` (matching the canvas snapshot shape used elsewhere) and adds a
2727
- * `toolCalls` array when the round produced tool calls so the execution inspector surfaces the
2728
- * planned calls instead of just an empty `""` for tool-only rounds.
2729
- */
2730
2568
  summarizeTurnOutput(turnResult) {
2731
2569
  if (turnResult.toolCalls.length === 0) return { content: turnResult.text };
2732
2570
  const toolCalls = turnResult.toolCalls.map((toolCall) => ({
@@ -2929,12 +2767,6 @@ let AIAgentNode = class AIAgentNode$1 {
2929
2767
  const binaries = await this.resolveInlineBinaries(attachments, ctx);
2930
2768
  return AgentBinaryContentFactory.withBinaries(promptMessages, binaries);
2931
2769
  }
2932
- /**
2933
- * Picks which attachments feed the passdown. When the author supplies `config.binaries`
2934
- * (a static array or a per-item function — e.g. to forward binaries from an earlier node),
2935
- * those replace the current item's attachments; otherwise the current item's `item.binary`
2936
- * is used.
2937
- */
2938
2770
  selectBinaryAttachments(item, itemIndex, items, ctx) {
2939
2771
  const manual = ctx.config.binaries;
2940
2772
  if (manual !== void 0) return typeof manual === "function" ? manual({
@@ -2945,14 +2777,6 @@ let AIAgentNode = class AIAgentNode$1 {
2945
2777
  }) : manual;
2946
2778
  return item.binary ? Object.values(item.binary) : [];
2947
2779
  }
2948
- /**
2949
- * Reads every attachment through `ctx.binary` (storage-backed, by reference — never base64 on
2950
- * `item.json`) and resolves it to inline base64 so the agent can pass it to the chat model as a
2951
- * native multimodal block. Images become image blocks; every other type (PDF, office docs, CSV,
2952
- * JSON, …) becomes a file block — we don't filter by media type, so any binary can be fed to the
2953
- * model. If the provider rejects an unsupported type the error surfaces at runtime, and the
2954
- * workflow can filter the binary upstream.
2955
- */
2956
2780
  async resolveInlineBinaries(attachments, ctx) {
2957
2781
  const resolved = [];
2958
2782
  for (const attachment of attachments) {
@@ -2965,12 +2789,6 @@ let AIAgentNode = class AIAgentNode$1 {
2965
2789
  }
2966
2790
  return resolved;
2967
2791
  }
2968
- /**
2969
- * When `item.json.__source` matches an entry in `config.untrustedSources`
2970
- * (default: `["gmail", "ocr", "webhook"]`), wraps every user-role message
2971
- * content with an untrusted-external-source preamble so the LLM treats the
2972
- * content as data, not instructions.
2973
- */
2974
2792
  wrapUntrustedSourceMessages(messages, item, config) {
2975
2793
  const source = item.json !== null && typeof item.json === "object" ? item.json.__source : void 0;
2976
2794
  if (typeof source !== "string") return messages;
@@ -3281,17 +3099,12 @@ HttpRequestNode = __decorate([node({ packageName: "@codemation/core-nodes" })],
3281
3099
 
3282
3100
  //#endregion
3283
3101
  //#region ../core-nodes/src/nodes/httpRequest.ts
3284
- /**
3285
- * The built-in HTTP request credential type IDs accepted by the `HttpRequest` node.
3286
- * These match the four generic credential types shipped with `@codemation/core-nodes`.
3287
- */
3288
3102
  const HTTP_REQUEST_ACCEPTED_CREDENTIAL_TYPES = [
3289
3103
  bearerTokenCredentialType.definition.typeId,
3290
3104
  apiKeyCredentialType.definition.typeId,
3291
3105
  basicAuthCredentialType.definition.typeId,
3292
3106
  oauth2ClientCredentialsType.definition.typeId
3293
3107
  ];
3294
- /** Default maximum response size for binary mode: 100 MiB. */
3295
3108
  const DEFAULT_RESPONSE_SIZE_CAP_BYTES = 100 * 1024 * 1024;
3296
3109
 
3297
3110
  //#endregion
@@ -3323,9 +3136,6 @@ FilterNode = __decorate([node({ packageName: "@codemation/core-nodes" })], Filte
3323
3136
  function getOriginIndex(item) {
3324
3137
  return getOriginIndexFromItem(item);
3325
3138
  }
3326
- /**
3327
- * Tags items routed to fan-in merge-by-origin (same contract as {@link IfNode} / {@link SwitchNode}).
3328
- */
3329
3139
  function tagItemForRouterFanIn(args) {
3330
3140
  const { item, itemIndex, nodeId, inputPortLabel = "$in" } = args;
3331
3141
  const metaBase = item.meta && typeof item.meta === "object" ? item.meta : {};
@@ -4208,7 +4018,6 @@ var ManualTrigger = class ManualTrigger {
4208
4018
  defaultItems;
4209
4019
  id;
4210
4020
  description;
4211
- /** Manual runs often emit an empty batch; still schedule downstream by default. */
4212
4021
  continueWhenEmptyOutput = true;
4213
4022
  constructor(name = "Manual trigger", defaultItemsOrId, idOrOptions) {
4214
4023
  this.name = name;
@@ -4426,6 +4235,39 @@ let WebhookTriggerNode = class WebhookTriggerNode$1 {
4426
4235
  };
4427
4236
  WebhookTriggerNode = __decorate([node({ packageName: "@codemation/core-nodes" })], WebhookTriggerNode);
4428
4237
 
4238
+ //#endregion
4239
+ //#region ../core-nodes/src/nodes/schedulePollingTrigger.ts
4240
+ const schedulePollingTrigger = definePollingTrigger({
4241
+ key: "schedule.interval",
4242
+ packageName: "@codemation/core-nodes",
4243
+ title: "Run on schedule",
4244
+ description: "Emit one tick item on every poll cycle.",
4245
+ icon: "lucide:clock",
4246
+ pollIntervalMs: 6e4,
4247
+ initialState() {
4248
+ return { tick: 0 };
4249
+ },
4250
+ poll({ state }) {
4251
+ const tick = (state ?? { tick: 0 }).tick + 1;
4252
+ return {
4253
+ items: [{ json: {
4254
+ firedAt: (/* @__PURE__ */ new Date()).toISOString(),
4255
+ tick
4256
+ } }],
4257
+ nextState: { tick }
4258
+ };
4259
+ },
4260
+ execute(items) {
4261
+ return { main: items };
4262
+ },
4263
+ testItems() {
4264
+ return [{ json: {
4265
+ firedAt: (/* @__PURE__ */ new Date()).toISOString(),
4266
+ tick: 0
4267
+ } }];
4268
+ }
4269
+ });
4270
+
4429
4271
  //#endregion
4430
4272
  //#region ../core-nodes/src/nodes/ConnectionCredentialNode.ts
4431
4273
  let ConnectionCredentialNode = class ConnectionCredentialNode$1 {
@@ -4613,16 +4455,6 @@ const collectionDeleteNode = defineNode({
4613
4455
  function resolveSubjectField(field, item) {
4614
4456
  return typeof field === "function" ? field({ item }) : field;
4615
4457
  }
4616
- /**
4617
- * Auto-detecting inbox approval node.
4618
- *
4619
- * Uses `ctx.resolve(InboxChannelResolverToken)` to pick the right inbox channel
4620
- * at runtime:
4621
- * - In managed mode (PairingConfig present): routes to the control-plane inbox.
4622
- * - Otherwise: routes to the local inbox.
4623
- *
4624
- * Authors use this node directly; no extra wiring needed per deployment mode.
4625
- */
4626
4458
  const inboxApproval = defineHumanApprovalNode({
4627
4459
  key: "inbox.approval",
4628
4460
  title: "Inbox Approval",