@codemation/core-nodes 0.12.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.
- package/CHANGELOG.md +30 -0
- package/dist/index.cjs +180 -413
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -1303
- package/dist/index.d.ts +99 -1303
- package/dist/index.js +181 -415
- package/dist/index.js.map +1 -1
- package/dist/metadata.json +1 -1
- package/package.json +2 -2
- package/src/authoring/defineRestNode.types.ts +0 -84
- package/src/canvasIconName.ts +0 -7
- package/src/chatModels/CodemationChatModelConfig.ts +0 -10
- package/src/chatModels/CodemationChatModelFactory.ts +0 -7
- package/src/chatModels/ManagedHmacSignerFactory.types.ts +0 -35
- package/src/chatModels/OpenAIChatModelFactory.ts +0 -2
- package/src/chatModels/OpenAiChatModelPresetsFactory.ts +0 -5
- package/src/chatModels/OpenAiCredentialSession.ts +0 -1
- package/src/chatModels/OpenAiStrictJsonSchemaFactory.ts +0 -21
- package/src/credentials/ApiKeyCredentialType.ts +0 -3
- package/src/credentials/BasicAuthCredentialType.ts +0 -4
- package/src/credentials/BearerTokenCredentialType.ts +0 -4
- package/src/credentials/OAuth2ClientCredentialsTypeFactory.ts +0 -19
- package/src/credentials/OAuth2TokenExchangeFactory.ts +0 -7
- package/src/http/HttpBodyBuilder.ts +0 -16
- package/src/http/HttpRequestExecutor.ts +0 -35
- package/src/http/HttpUrlBuilder.ts +0 -4
- package/src/http/SSRFBlockedError.ts +0 -4
- package/src/http/SsrfGuard.ts +10 -50
- package/src/http/httpRequest.types.ts +0 -49
- package/src/index.ts +1 -0
- package/src/nodes/AIAgentConfig.ts +3 -39
- package/src/nodes/AIAgentExecutionHelpersFactory.ts +0 -37
- package/src/nodes/AIAgentNode.ts +4 -134
- package/src/nodes/AgentBinaryContentFactory.ts +0 -12
- package/src/nodes/AgentLoopCheckpoint.types.ts +0 -13
- package/src/nodes/AgentMessageFactory.ts +17 -19
- package/src/nodes/AgentStructuredOutputRunner.ts +0 -17
- package/src/nodes/AgentToolExecutionCoordinator.ts +0 -12
- package/src/nodes/AgentToolResultContentFactory.ts +126 -0
- package/src/nodes/AssertionNode.ts +0 -14
- package/src/nodes/BM25Index.ts +0 -14
- package/src/nodes/ConnectionCredentialExecutionContextFactory.ts +0 -5
- package/src/nodes/ConnectionCredentialNode.ts +0 -4
- package/src/nodes/CronTriggerFactory.ts +0 -9
- package/src/nodes/DeferredMetaToolStrategy.ts +0 -18
- package/src/nodes/DeferredMetaToolStrategyFactory.ts +0 -5
- package/src/nodes/HttpRequestNodeFactory.ts +0 -14
- package/src/nodes/InboxApprovalNode.types.ts +0 -16
- package/src/nodes/IsTestRunNode.ts +0 -8
- package/src/nodes/ManualTriggerFactory.ts +0 -3
- package/src/nodes/ManualTriggerNode.ts +0 -4
- package/src/nodes/MergeNode.ts +0 -1
- package/src/nodes/NodeBackedToolRuntime.ts +0 -14
- package/src/nodes/SubWorkflowNode.ts +0 -3
- package/src/nodes/SwitchNode.ts +0 -3
- package/src/nodes/TestTriggerNode.ts +0 -9
- package/src/nodes/aiAgentSupport.types.ts +0 -16
- package/src/nodes/assertion.ts +0 -10
- package/src/nodes/codemationDocumentScannerNode.ts +0 -18
- package/src/nodes/collections/collectionListNode.types.ts +0 -1
- package/src/nodes/httpRequest.ts +0 -68
- package/src/nodes/isTestRun.ts +0 -4
- package/src/nodes/mapData.ts +0 -1
- package/src/nodes/merge.ts +0 -4
- package/src/nodes/mergeExecutionUtils.types.ts +0 -3
- package/src/nodes/nodeOptions.types.ts +0 -8
- package/src/nodes/schedulePollingTrigger.ts +37 -0
- package/src/nodes/split.ts +0 -4
- package/src/nodes/testTrigger.ts +0 -21
- package/src/nodes/wait.ts +0 -1
- package/src/nodes/webhookTriggerNode.ts +0 -5
- package/src/register.types.ts +0 -10
- 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");
|
|
@@ -4486,21 +4312,137 @@ var CodemationChatModelConfig = class {
|
|
|
4486
4312
|
}
|
|
4487
4313
|
};
|
|
4488
4314
|
|
|
4315
|
+
//#endregion
|
|
4316
|
+
//#region src/nodes/AgentToolResultContentFactory.ts
|
|
4317
|
+
const MAX_INLINE_BYTES = 8 * 1024 * 1024;
|
|
4318
|
+
const KNOWN_MCP_BLOCK_TYPES = new Set([
|
|
4319
|
+
"text",
|
|
4320
|
+
"image",
|
|
4321
|
+
"audio",
|
|
4322
|
+
"resource",
|
|
4323
|
+
"resource_link"
|
|
4324
|
+
]);
|
|
4325
|
+
var AgentToolResultContentFactory = class AgentToolResultContentFactory {
|
|
4326
|
+
static tryMapToContentOutput(result) {
|
|
4327
|
+
const blocks = AgentToolResultContentFactory.contentBlocks(result);
|
|
4328
|
+
if (blocks === void 0) return void 0;
|
|
4329
|
+
const parts = [];
|
|
4330
|
+
let inlinedBytes = 0;
|
|
4331
|
+
for (const block of blocks) {
|
|
4332
|
+
const mapped = AgentToolResultContentFactory.mapBlock(block, inlinedBytes);
|
|
4333
|
+
parts.push(mapped.part);
|
|
4334
|
+
inlinedBytes += mapped.bytes;
|
|
4335
|
+
}
|
|
4336
|
+
return parts;
|
|
4337
|
+
}
|
|
4338
|
+
static contentBlocks(result) {
|
|
4339
|
+
if (result === null || typeof result !== "object") return void 0;
|
|
4340
|
+
const content = result.content;
|
|
4341
|
+
if (!Array.isArray(content) || content.length === 0) return void 0;
|
|
4342
|
+
if (!content.every((block) => block !== null && typeof block === "object" && typeof block.type === "string")) return void 0;
|
|
4343
|
+
return content.some((block) => KNOWN_MCP_BLOCK_TYPES.has(block.type)) ? content : void 0;
|
|
4344
|
+
}
|
|
4345
|
+
static mapBlock(block, inlinedBytesSoFar) {
|
|
4346
|
+
const type = block.type;
|
|
4347
|
+
if (type === "text" && typeof block.text === "string") return {
|
|
4348
|
+
part: {
|
|
4349
|
+
type: "text",
|
|
4350
|
+
text: block.text
|
|
4351
|
+
},
|
|
4352
|
+
bytes: 0
|
|
4353
|
+
};
|
|
4354
|
+
if (type === "image" && typeof block.data === "string" && typeof block.mimeType === "string") return AgentToolResultContentFactory.mapBinary({
|
|
4355
|
+
base64: block.data,
|
|
4356
|
+
mediaType: block.mimeType,
|
|
4357
|
+
inlinedBytesSoFar
|
|
4358
|
+
});
|
|
4359
|
+
if (type === "resource" && block.resource) return AgentToolResultContentFactory.mapEmbeddedResource(block.resource, inlinedBytesSoFar);
|
|
4360
|
+
if (type === "resource_link" && typeof block.uri === "string") {
|
|
4361
|
+
const mime = typeof block.mimeType === "string" ? ` (${block.mimeType})` : "";
|
|
4362
|
+
return {
|
|
4363
|
+
part: {
|
|
4364
|
+
type: "text",
|
|
4365
|
+
text: `[linked resource: ${block.uri}${mime}]`
|
|
4366
|
+
},
|
|
4367
|
+
bytes: 0
|
|
4368
|
+
};
|
|
4369
|
+
}
|
|
4370
|
+
return {
|
|
4371
|
+
part: {
|
|
4372
|
+
type: "text",
|
|
4373
|
+
text: `[unsupported tool content block: ${String(type)}]`
|
|
4374
|
+
},
|
|
4375
|
+
bytes: 0
|
|
4376
|
+
};
|
|
4377
|
+
}
|
|
4378
|
+
static mapEmbeddedResource(resource, inlinedBytesSoFar) {
|
|
4379
|
+
if (typeof resource.text === "string") return {
|
|
4380
|
+
part: {
|
|
4381
|
+
type: "text",
|
|
4382
|
+
text: resource.text
|
|
4383
|
+
},
|
|
4384
|
+
bytes: 0
|
|
4385
|
+
};
|
|
4386
|
+
if (typeof resource.blob === "string" && typeof resource.mimeType === "string") return AgentToolResultContentFactory.mapBinary({
|
|
4387
|
+
base64: resource.blob,
|
|
4388
|
+
mediaType: resource.mimeType,
|
|
4389
|
+
filename: typeof resource.name === "string" ? resource.name : void 0,
|
|
4390
|
+
inlinedBytesSoFar
|
|
4391
|
+
});
|
|
4392
|
+
return {
|
|
4393
|
+
part: {
|
|
4394
|
+
type: "text",
|
|
4395
|
+
text: `[embedded resource: ${typeof resource.uri === "string" ? resource.uri : "unknown"}]`
|
|
4396
|
+
},
|
|
4397
|
+
bytes: 0
|
|
4398
|
+
};
|
|
4399
|
+
}
|
|
4400
|
+
static mapBinary(args) {
|
|
4401
|
+
const rawBytes = Math.floor(args.base64.length * 3 / 4);
|
|
4402
|
+
if (args.inlinedBytesSoFar + rawBytes > MAX_INLINE_BYTES) {
|
|
4403
|
+
const name = args.filename ? ` "${args.filename}"` : "";
|
|
4404
|
+
const kb = Math.round(rawBytes / 1024);
|
|
4405
|
+
return {
|
|
4406
|
+
part: {
|
|
4407
|
+
type: "text",
|
|
4408
|
+
text: `[binary${name} (${args.mediaType}, ~${kb} KB) omitted: exceeds the per-tool-result inline limit]`
|
|
4409
|
+
},
|
|
4410
|
+
bytes: 0
|
|
4411
|
+
};
|
|
4412
|
+
}
|
|
4413
|
+
if (args.mediaType.startsWith("image/")) return {
|
|
4414
|
+
part: {
|
|
4415
|
+
type: "image-data",
|
|
4416
|
+
data: args.base64,
|
|
4417
|
+
mediaType: args.mediaType
|
|
4418
|
+
},
|
|
4419
|
+
bytes: rawBytes
|
|
4420
|
+
};
|
|
4421
|
+
if (args.mediaType === "application/pdf") return {
|
|
4422
|
+
part: {
|
|
4423
|
+
type: "file-data",
|
|
4424
|
+
data: args.base64,
|
|
4425
|
+
mediaType: args.mediaType,
|
|
4426
|
+
...args.filename ? { filename: args.filename } : {}
|
|
4427
|
+
},
|
|
4428
|
+
bytes: rawBytes
|
|
4429
|
+
};
|
|
4430
|
+
return {
|
|
4431
|
+
part: {
|
|
4432
|
+
type: "text",
|
|
4433
|
+
text: `[binary${args.filename ? ` "${args.filename}"` : ""} (${args.mediaType}) not inlined: unsupported by the model]`
|
|
4434
|
+
},
|
|
4435
|
+
bytes: 0
|
|
4436
|
+
};
|
|
4437
|
+
}
|
|
4438
|
+
};
|
|
4439
|
+
|
|
4489
4440
|
//#endregion
|
|
4490
4441
|
//#region src/nodes/AgentMessageFactory.ts
|
|
4491
|
-
/**
|
|
4492
|
-
* AI-SDK-shaped message construction for the AIAgent stack. Emits plain `ModelMessage[]`
|
|
4493
|
-
* ( `{ role: 'system' | 'user' | 'assistant' | 'tool', content: ... }` ) as consumed by
|
|
4494
|
-
* `generateText({ messages })` from the `ai` package.
|
|
4495
|
-
*/
|
|
4496
4442
|
var AgentMessageFactory = class AgentMessageFactory {
|
|
4497
4443
|
static createPromptMessages(messages) {
|
|
4498
4444
|
return messages.map((message) => this.createPromptMessage(message));
|
|
4499
4445
|
}
|
|
4500
|
-
/**
|
|
4501
|
-
* Builds the assistant message that contains optional text plus one or more tool-call parts,
|
|
4502
|
-
* matching the shape AI SDK emits between steps.
|
|
4503
|
-
*/
|
|
4504
4446
|
static createAssistantWithToolCalls(text, toolCalls) {
|
|
4505
4447
|
const content = [];
|
|
4506
4448
|
if (text && text.length > 0) content.push({
|
|
@@ -4518,24 +4460,30 @@ var AgentMessageFactory = class AgentMessageFactory {
|
|
|
4518
4460
|
content
|
|
4519
4461
|
};
|
|
4520
4462
|
}
|
|
4521
|
-
|
|
4522
|
-
* Builds the `{ role: "tool", content: [{ type: "tool-result", ... }, ...] }` message returned
|
|
4523
|
-
* to the model after each tool round.
|
|
4524
|
-
*/
|
|
4525
|
-
static createToolResultsMessage(executedToolCalls) {
|
|
4463
|
+
static createToolResultsMessage(executedToolCalls, passToolBinariesToModel = true) {
|
|
4526
4464
|
return {
|
|
4527
4465
|
role: "tool",
|
|
4528
4466
|
content: executedToolCalls.map((executed) => ({
|
|
4529
4467
|
type: "tool-result",
|
|
4530
4468
|
toolCallId: executed.toolCallId,
|
|
4531
4469
|
toolName: executed.toolName,
|
|
4532
|
-
output:
|
|
4533
|
-
type: "json",
|
|
4534
|
-
value: AgentMessageFactory.toToolResultJson(executed.result)
|
|
4535
|
-
}
|
|
4470
|
+
output: AgentMessageFactory.toToolResultOutput(executed.result, passToolBinariesToModel)
|
|
4536
4471
|
}))
|
|
4537
4472
|
};
|
|
4538
4473
|
}
|
|
4474
|
+
static toToolResultOutput(result, passToolBinariesToModel) {
|
|
4475
|
+
if (passToolBinariesToModel) {
|
|
4476
|
+
const content = AgentToolResultContentFactory.tryMapToContentOutput(result);
|
|
4477
|
+
if (content !== void 0) return {
|
|
4478
|
+
type: "content",
|
|
4479
|
+
value: content
|
|
4480
|
+
};
|
|
4481
|
+
}
|
|
4482
|
+
return {
|
|
4483
|
+
type: "json",
|
|
4484
|
+
value: AgentMessageFactory.toToolResultJson(result)
|
|
4485
|
+
};
|
|
4486
|
+
}
|
|
4539
4487
|
static toToolResultJson(value) {
|
|
4540
4488
|
if (value === void 0) return null;
|
|
4541
4489
|
try {
|
|
@@ -5332,10 +5280,6 @@ let AgentStructuredOutputRunner = class AgentStructuredOutputRunner$1 {
|
|
|
5332
5280
|
}
|
|
5333
5281
|
throw new Error(`Structured output required for AIAgent "${args.agentName}" (${args.nodeId}) but validation still failed after ${_AgentStructuredOutputRunner.repairAttemptCount} repair attempts: ${failure.validationError}`);
|
|
5334
5282
|
}
|
|
5335
|
-
/**
|
|
5336
|
-
* Chooses strict mode for OpenAI chat-model configs, off otherwise. Extendable in future for
|
|
5337
|
-
* other providers that adopt the same "supply a JSON Schema record directly" contract.
|
|
5338
|
-
*/
|
|
5339
5283
|
resolveStructuredOutputOptions(chatModelConfig) {
|
|
5340
5284
|
if (chatModelConfig.type !== OpenAIChatModelFactory) return;
|
|
5341
5285
|
return {
|
|
@@ -5818,10 +5762,6 @@ let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
|
|
|
5818
5762
|
extractErrorDetails(error) {
|
|
5819
5763
|
return error.details;
|
|
5820
5764
|
}
|
|
5821
|
-
/**
|
|
5822
|
-
* Extracts the text content from the last assistant message in the conversation snapshot.
|
|
5823
|
-
* Used to populate `agentReasoning` in the HITL suspension metadata.
|
|
5824
|
-
*/
|
|
5825
5765
|
extractLastAssistantText(conversation) {
|
|
5826
5766
|
for (let i = conversation.length - 1; i >= 0; i--) {
|
|
5827
5767
|
const msg = conversation[i];
|
|
@@ -5856,16 +5796,6 @@ AgentToolExecutionCoordinator = __decorate([
|
|
|
5856
5796
|
|
|
5857
5797
|
//#endregion
|
|
5858
5798
|
//#region src/nodes/AgentBinaryContentFactory.ts
|
|
5859
|
-
/**
|
|
5860
|
-
* Turns resolved file binaries into native AI SDK multimodal content parts and merges them into the
|
|
5861
|
-
* agent prompt. Images (`image/*`) become {@link ImagePart}s; every other type (PDFs, office docs,
|
|
5862
|
-
* CSV, JSON, …) becomes a {@link FilePart}. The provider maps these to its wire-level `image` /
|
|
5863
|
-
* `document` blocks; an unsupported file type surfaces as a provider error at runtime.
|
|
5864
|
-
*
|
|
5865
|
-
* Parts are appended to the LAST user message so the binary travels alongside the author's prompt
|
|
5866
|
-
* text (preserving any untrusted-source preamble that already wrapped that text). When no user
|
|
5867
|
-
* message exists, a new user message carrying only the binaries is appended.
|
|
5868
|
-
*/
|
|
5869
5799
|
var AgentBinaryContentFactory = class AgentBinaryContentFactory {
|
|
5870
5800
|
static toContentPart(binary) {
|
|
5871
5801
|
if (binary.mediaType.startsWith("image/")) return {
|
|
@@ -5944,20 +5874,6 @@ let NodeBackedToolRuntime = class NodeBackedToolRuntime$1 {
|
|
|
5944
5874
|
outputs
|
|
5945
5875
|
});
|
|
5946
5876
|
}
|
|
5947
|
-
/**
|
|
5948
|
-
* Returns a re-rooted child ctx for nested-agent tools (so their LLM/tool connection ids derive
|
|
5949
|
-
* from the tool connection node, telemetry parents under the tool-call span, and connection
|
|
5950
|
-
* invocations carry `parentInvocationId`). Plain runnable tools (non-agent) keep the orchestrator
|
|
5951
|
-
* ctx with only `config` swapped — no nesting concern.
|
|
5952
|
-
*
|
|
5953
|
-
* The caller (`AIAgentNode.createItemScopedTools`) already wraps the orchestrator ctx via
|
|
5954
|
-
* `ConnectionCredentialExecutionContextFactory.forConnectionNode`, so `args.ctx.nodeId` is the
|
|
5955
|
-
* tool's own connection node id (e.g. `AIAgentNode:2__conn__tool__searchInMail`). We pass that
|
|
5956
|
-
* through as the sub-agent's `nodeId`; deriving another `toolConnectionNodeId(args.ctx.nodeId,
|
|
5957
|
-
* config.name)` here would prepend a duplicate `__conn__tool__<name>` segment and exponentially
|
|
5958
|
-
* deepen ids on each invocation, which also breaks credential resolution because user-provided
|
|
5959
|
-
* bindings sit on the single-level connection node id.
|
|
5960
|
-
*/
|
|
5961
5877
|
resolveNodeCtx(config$1, args) {
|
|
5962
5878
|
const isNestedAgent = __codemation_core.AgentConfigInspector.isAgentNodeConfig(config$1.node);
|
|
5963
5879
|
const hooks = args.hooks;
|
|
@@ -6022,22 +5938,12 @@ NodeBackedToolRuntime = __decorate([
|
|
|
6022
5938
|
|
|
6023
5939
|
//#endregion
|
|
6024
5940
|
//#region src/nodes/BM25Index.ts
|
|
6025
|
-
/**
|
|
6026
|
-
* Minimal BM25 (Okapi BM25) implementation for indexing MCP tool descriptions.
|
|
6027
|
-
*
|
|
6028
|
-
* Parameters: k1=1.5, b=0.75 (standard defaults).
|
|
6029
|
-
* Tokenisation: lowercase, split on non-alphanumerics, filter empties.
|
|
6030
|
-
*/
|
|
6031
5941
|
var BM25Index = class {
|
|
6032
5942
|
k1 = 1.5;
|
|
6033
5943
|
b = .75;
|
|
6034
5944
|
tf = [];
|
|
6035
5945
|
df = /* @__PURE__ */ new Map();
|
|
6036
5946
|
avgDocLen = 0;
|
|
6037
|
-
/**
|
|
6038
|
-
* Add all documents at once. After calling this, search is available.
|
|
6039
|
-
* Documents are indexed in insertion order; search returns their indices.
|
|
6040
|
-
*/
|
|
6041
5947
|
add(docs) {
|
|
6042
5948
|
const docTerms = docs.map((d) => this.tokenize(d));
|
|
6043
5949
|
let totalLen = 0;
|
|
@@ -6050,10 +5956,6 @@ var BM25Index = class {
|
|
|
6050
5956
|
}
|
|
6051
5957
|
this.avgDocLen = docTerms.length > 0 ? totalLen / docTerms.length : 0;
|
|
6052
5958
|
}
|
|
6053
|
-
/**
|
|
6054
|
-
* Returns up to `limit` document indices ranked by BM25 score (highest first).
|
|
6055
|
-
* Returns an empty array if the index is empty or the query matches nothing.
|
|
6056
|
-
*/
|
|
6057
5959
|
search(query, limit) {
|
|
6058
5960
|
const n = this.tf.length;
|
|
6059
5961
|
if (n === 0) return [];
|
|
@@ -6094,26 +5996,12 @@ const PINNED_TOOLS_SOFT_LIMIT = 8;
|
|
|
6094
5996
|
const PINNED_TOOLS_HARD_LIMIT = 16;
|
|
6095
5997
|
const FIND_TOOLS_NAME = "find_tools";
|
|
6096
5998
|
const FIND_TOOLS_DEFAULT_LIMIT = 5;
|
|
6097
|
-
/**
|
|
6098
|
-
* Default tool-loading strategy: BM25-indexed MCP tool deferral via a `find_tools` meta-tool.
|
|
6099
|
-
*
|
|
6100
|
-
* - Node-backed tools and pinned MCP tools are always included in every turn.
|
|
6101
|
-
* - `find_tools(query, limit?)` is added to the tool set when MCP tools are indexed.
|
|
6102
|
-
* - Tools surfaced by `find_tools` are included in subsequent turns.
|
|
6103
|
-
*
|
|
6104
|
-
* Not DI-managed; instantiated per agent execution by DeferredMetaToolStrategyFactory.
|
|
6105
|
-
*/
|
|
6106
5999
|
var DeferredMetaToolStrategy = class {
|
|
6107
6000
|
nodeBackedTools = {};
|
|
6108
6001
|
pinnedTools = {};
|
|
6109
6002
|
mcpEntries = [];
|
|
6110
6003
|
toolsByServerId = /* @__PURE__ */ new Map();
|
|
6111
6004
|
foundToolIds = /* @__PURE__ */ new Set();
|
|
6112
|
-
/**
|
|
6113
|
-
* `jsonSchema` from the `ai` SDK, loaded lazily in {@link initialize} so the SDK
|
|
6114
|
-
* (~28MB RSS) stays off the boot path. `initialize` always runs before the sync
|
|
6115
|
-
* `getToolsForTurn` → `buildFindToolsDefinition` path, so this is set before use.
|
|
6116
|
-
*/
|
|
6117
6005
|
jsonSchema;
|
|
6118
6006
|
constructor(bm25, warnFn) {
|
|
6119
6007
|
this.bm25 = bm25;
|
|
@@ -6261,11 +6149,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6261
6149
|
inputSchema = unknown();
|
|
6262
6150
|
connectionCredentialExecutionContextFactory;
|
|
6263
6151
|
preparedByExecutionContext = /* @__PURE__ */ new WeakMap();
|
|
6264
|
-
/**
|
|
6265
|
-
* The `ai` SDK, loaded lazily in {@link execute} so the SDK (~28MB RSS) stays
|
|
6266
|
-
* off the boot path — non-AI workflows never load it. Every path runs through
|
|
6267
|
-
* `execute` → `ensureAiSdk` before any sync helper touches `this.aiSdk`.
|
|
6268
|
-
*/
|
|
6269
6152
|
aiSdk;
|
|
6270
6153
|
aiSdkPromise = null;
|
|
6271
6154
|
constructor(nodeResolver, credentialSessions, nodeBackedToolRuntime, executionHelpers, structuredOutputRunner, toolExecutionCoordinator, toolLoadingStrategyFactory, agentMcpIntegration) {
|
|
@@ -6289,15 +6172,9 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6289
6172
|
};
|
|
6290
6173
|
return (await this.runAgentForItem(prepared, itemWithMappedJson, args.itemIndex, args.items)).json;
|
|
6291
6174
|
}
|
|
6292
|
-
/** Load the `ai` SDK once per node instance (cached promise guards concurrent items). */
|
|
6293
6175
|
async ensureAiSdk() {
|
|
6294
6176
|
this.aiSdk = await (this.aiSdkPromise ??= import("ai"));
|
|
6295
6177
|
}
|
|
6296
|
-
/**
|
|
6297
|
-
* Resume path: re-enters the agent loop after a HITL suspension.
|
|
6298
|
-
* Reconstructs the conversation from the checkpoint, injects the human decision
|
|
6299
|
-
* as a tool_result, and continues the loop from where it suspended.
|
|
6300
|
-
*/
|
|
6301
6178
|
async executeResumed(args, resumeContext) {
|
|
6302
6179
|
const { ctx } = args;
|
|
6303
6180
|
const taskMetadata = resumeContext.task.metadata ?? {};
|
|
@@ -6324,7 +6201,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6324
6201
|
result: decision,
|
|
6325
6202
|
serialized: JSON.stringify(decision)
|
|
6326
6203
|
};
|
|
6327
|
-
const conversation = [...checkpoint.conversation, AgentMessageFactory.createToolResultsMessage([toolResultEntry])];
|
|
6204
|
+
const conversation = [...checkpoint.conversation, AgentMessageFactory.createToolResultsMessage([toolResultEntry], ctx.config.passToolBinariesToModel !== false)];
|
|
6328
6205
|
const loopResult = await this.runTurnLoopUntilFinalAnswer({
|
|
6329
6206
|
prepared,
|
|
6330
6207
|
itemInputsByPort,
|
|
@@ -6344,10 +6221,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6344
6221
|
const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, loopResult.finalText, itemScopedTools.length > 0);
|
|
6345
6222
|
return this.buildOutputItem(item, outputJson).json;
|
|
6346
6223
|
}
|
|
6347
|
-
/**
|
|
6348
|
-
* Normalizes a {@link ResumeContext} decision into a flat JSON-serializable shape
|
|
6349
|
-
* suitable for injection as a tool_result content.
|
|
6350
|
-
*/
|
|
6351
6224
|
normalizeDecision(resumeContext) {
|
|
6352
6225
|
const { decision } = resumeContext;
|
|
6353
6226
|
if (decision.kind === "decided") {
|
|
@@ -6474,16 +6347,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6474
6347
|
const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, loopResult.finalText, itemScopedTools.length > 0);
|
|
6475
6348
|
return this.buildOutputItem(item, outputJson);
|
|
6476
6349
|
}
|
|
6477
|
-
/**
|
|
6478
|
-
* Multi-turn loop:
|
|
6479
|
-
* - Each turn is a single `generateText` call with tools exposed but **not auto-executed**
|
|
6480
|
-
* (we control tool dispatch so that {@link AgentToolExecutionCoordinator} drives repair /
|
|
6481
|
-
* connection-invocation recording / transient-error handling exactly like before).
|
|
6482
|
-
* - When the model returns no tool calls the loop ends with the model's text as the final answer.
|
|
6483
|
-
* - Respects `guardrails.maxTurns` and `guardrails.onTurnLimitReached`.
|
|
6484
|
-
* - Strategy-owned tool calls (e.g. `find_tools`) are dispatched via the strategy, not the
|
|
6485
|
-
* coordinator; their results are tracked so subsequent turns receive the discovered tools.
|
|
6486
|
-
*/
|
|
6487
6350
|
async runTurnLoopUntilFinalAnswer(args) {
|
|
6488
6351
|
const { prepared, itemInputsByPort, itemScopedTools, conversation } = args;
|
|
6489
6352
|
const { ctx, guardrails, toolLoadingStrategy } = prepared;
|
|
@@ -6491,7 +6354,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6491
6354
|
let toolCallCount = args.resumedToolCallCount ?? 0;
|
|
6492
6355
|
let turnCount = 0;
|
|
6493
6356
|
const repairAttemptsByToolName = /* @__PURE__ */ new Map();
|
|
6494
|
-
/** Tool IDs surfaced by find_tools across all prior turns in this item run. */
|
|
6495
6357
|
let previousFoundToolIds = [];
|
|
6496
6358
|
for (let turn = 1; turn <= guardrails.maxTurns; turn++) {
|
|
6497
6359
|
turnCount = turn;
|
|
@@ -6544,7 +6406,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6544
6406
|
coordinatorExecutedCalls.push(...executed);
|
|
6545
6407
|
}
|
|
6546
6408
|
const allExecutedCalls = [...strategyExecutedCalls, ...coordinatorExecutedCalls];
|
|
6547
|
-
this.appendAssistantAndToolMessages(conversation, result.assistantMessage, result.text, result.toolCalls, allExecutedCalls);
|
|
6409
|
+
this.appendAssistantAndToolMessages(conversation, result.assistantMessage, result.text, result.toolCalls, allExecutedCalls, ctx.config.passToolBinariesToModel !== false);
|
|
6548
6410
|
}
|
|
6549
6411
|
return {
|
|
6550
6412
|
finalText,
|
|
@@ -6559,8 +6421,8 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6559
6421
|
if (guardrails.onTurnLimitReached === "respondWithLastMessage") return;
|
|
6560
6422
|
throw new Error(`AIAgent "${ctx.config.name ?? ctx.nodeId}" reached maxTurns=${guardrails.maxTurns} before producing a final response.`);
|
|
6561
6423
|
}
|
|
6562
|
-
appendAssistantAndToolMessages(conversation, assistantMessage, text, toolCalls, executedToolCalls) {
|
|
6563
|
-
conversation.push(assistantMessage ?? AgentMessageFactory.createAssistantWithToolCalls(text, toolCalls), AgentMessageFactory.createToolResultsMessage(executedToolCalls));
|
|
6424
|
+
appendAssistantAndToolMessages(conversation, assistantMessage, text, toolCalls, executedToolCalls, passToolBinariesToModel) {
|
|
6425
|
+
conversation.push(assistantMessage ?? AgentMessageFactory.createAssistantWithToolCalls(text, toolCalls), AgentMessageFactory.createToolResultsMessage(executedToolCalls, passToolBinariesToModel));
|
|
6564
6426
|
}
|
|
6565
6427
|
async resolveFinalOutputJson(prepared, itemInputsByPort, conversation, finalText, wasToolEnabledRun) {
|
|
6566
6428
|
if (!prepared.ctx.config.outputSchema) return AgentOutputFactory.fromAgentContent(finalText);
|
|
@@ -6621,12 +6483,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6621
6483
|
};
|
|
6622
6484
|
});
|
|
6623
6485
|
}
|
|
6624
|
-
/**
|
|
6625
|
-
* Resolves the HITL behavior for a tool binding, or `undefined` when it is not a HITL tool.
|
|
6626
|
-
* A binding is HITL if either the backing node carries a `defineHumanApprovalNode` marker or the
|
|
6627
|
-
* binding sets a per-binding `onRejected` via `asTool(..., { onRejected })`. The per-binding value
|
|
6628
|
-
* wins over the node marker, so two tools backed by the same node can reject differently.
|
|
6629
|
-
*/
|
|
6630
6486
|
resolveHumanApprovalBehavior(config$1) {
|
|
6631
6487
|
if (!this.isNodeBackedToolConfig(config$1)) return void 0;
|
|
6632
6488
|
const marker = config$1.node.humanApprovalToolBehavior;
|
|
@@ -6634,11 +6490,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6634
6490
|
if (marker === void 0 && perBinding === void 0) return void 0;
|
|
6635
6491
|
return { onRejected: perBinding ?? marker?.onRejected ?? "return" };
|
|
6636
6492
|
}
|
|
6637
|
-
/**
|
|
6638
|
-
* Invoke a text turn using the merged tool set from item-scoped tools (coordinator-managed)
|
|
6639
|
-
* and strategy tools (find_tools + discovered MCP tools).
|
|
6640
|
-
* Strategy tools take precedence for names that overlap.
|
|
6641
|
-
*/
|
|
6642
6493
|
async invokeTextTurnWithStrategyTools(prepared, itemInputsByPort, messages, itemScopedTools, strategyTools) {
|
|
6643
6494
|
const itemToolSet = this.buildToolSet(itemScopedTools);
|
|
6644
6495
|
const strategyHasTools = Object.keys(strategyTools).length > 0;
|
|
@@ -6649,10 +6500,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6649
6500
|
} : void 0;
|
|
6650
6501
|
return this.invokeTextTurnWithToolSet(prepared, itemInputsByPort, messages, mergedTools);
|
|
6651
6502
|
}
|
|
6652
|
-
/**
|
|
6653
|
-
* Removes `execute` properties from ToolSet entries so the AI SDK does not
|
|
6654
|
-
* auto-execute them within `generateText`. Codemation owns all tool dispatch.
|
|
6655
|
-
*/
|
|
6656
6503
|
stripExecuteCallbacks(tools) {
|
|
6657
6504
|
const stripped = {};
|
|
6658
6505
|
for (const [name, def] of Object.entries(tools)) {
|
|
@@ -6661,12 +6508,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6661
6508
|
}
|
|
6662
6509
|
return stripped;
|
|
6663
6510
|
}
|
|
6664
|
-
/**
|
|
6665
|
-
* Builds a ToolSet from resolved tools for strategy initialization.
|
|
6666
|
-
* The strategy uses this for its "always-included" node-backed tool descriptions.
|
|
6667
|
-
* HITL tools (detected via the `humanApprovalToolBehavior` field set by `defineHumanApprovalNode`) get the solo-constraint sentence
|
|
6668
|
-
* appended to their description.
|
|
6669
|
-
*/
|
|
6670
6511
|
buildToolSetFromResolved(resolvedTools) {
|
|
6671
6512
|
if (resolvedTools.length === 0) return {};
|
|
6672
6513
|
const toolSet = {};
|
|
@@ -6684,20 +6525,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6684
6525
|
}
|
|
6685
6526
|
return toolSet;
|
|
6686
6527
|
}
|
|
6687
|
-
/**
|
|
6688
|
-
* Builds an AI SDK {@link ToolSet} where every tool ships a pre-converted JSON Schema (via
|
|
6689
|
-
* {@link jsonSchema}) — not the raw Zod schema — and carries **no** `execute`. Two reasons:
|
|
6690
|
-
*
|
|
6691
|
-
* 1. Codemation owns tool dispatch + the per-tool repair loop (see {@link AgentToolExecutionCoordinator}),
|
|
6692
|
-
* so the AI SDK must surface tool calls back to us instead of auto-running them.
|
|
6693
|
-
* 2. The AI SDK's `asSchema` helper discriminates between Zod v3 / Zod v4 / Standard Schema via
|
|
6694
|
-
* runtime feature-detection (`~standard`, `_zod`, etc.). Handing it a pre-built
|
|
6695
|
-
* {@link jsonSchema} record — which is tagged with `Symbol.for('vercel.ai.schema')` — skips all
|
|
6696
|
-
* of that detection and guarantees the provider receives a draft-07 JSON Schema with
|
|
6697
|
-
* `additionalProperties: false` at every object depth (see {@link OpenAiStrictJsonSchemaFactory}
|
|
6698
|
-
* for the same logic applied to structured-output schemas). Codemation still runs its own Zod
|
|
6699
|
-
* validation on tool inputs before execute — the schema handed to the model is advisory.
|
|
6700
|
-
*/
|
|
6701
6528
|
buildToolSet(itemScopedTools) {
|
|
6702
6529
|
if (itemScopedTools.length === 0) return void 0;
|
|
6703
6530
|
const toolSet = {};
|
|
@@ -6715,10 +6542,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6715
6542
|
}
|
|
6716
6543
|
return toolSet;
|
|
6717
6544
|
}
|
|
6718
|
-
/**
|
|
6719
|
-
* One `generateText` turn (no auto tool execution) with Codemation-owned child-span telemetry
|
|
6720
|
-
* and connection-invocation state recording. Accepts a pre-built ToolSet.
|
|
6721
|
-
*/
|
|
6722
6545
|
async invokeTextTurnWithToolSet(prepared, itemInputsByPort, messages, tools) {
|
|
6723
6546
|
const invocationId = __codemation_core.ConnectionInvocationIdFactory.create();
|
|
6724
6547
|
const startedAt = /* @__PURE__ */ new Date();
|
|
@@ -6829,11 +6652,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6829
6652
|
});
|
|
6830
6653
|
}
|
|
6831
6654
|
}
|
|
6832
|
-
/**
|
|
6833
|
-
* Structured-output turn: runs `generateText({ output: Output.object({ schema }) })` via the
|
|
6834
|
-
* structured-output runner. We keep this as a separate helper because the runner needs the raw
|
|
6835
|
-
* validated value (not just text) back, and must be able to retry on Zod failures.
|
|
6836
|
-
*/
|
|
6837
6655
|
async invokeStructuredTurn(prepared, itemInputsByPort, schema, messages, structuredOptions) {
|
|
6838
6656
|
const invocationId = __codemation_core.ConnectionInvocationIdFactory.create();
|
|
6839
6657
|
const startedAt = /* @__PURE__ */ new Date();
|
|
@@ -6958,13 +6776,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6958
6776
|
providerOptions: overrides?.providerOptions ?? defaults.providerOptions
|
|
6959
6777
|
};
|
|
6960
6778
|
}
|
|
6961
|
-
/**
|
|
6962
|
-
* Build a no-code-friendly output payload for an LLM round.
|
|
6963
|
-
*
|
|
6964
|
-
* Always includes `content` (matching the canvas snapshot shape used elsewhere) and adds a
|
|
6965
|
-
* `toolCalls` array when the round produced tool calls so the execution inspector surfaces the
|
|
6966
|
-
* planned calls instead of just an empty `""` for tool-only rounds.
|
|
6967
|
-
*/
|
|
6968
6779
|
summarizeTurnOutput(turnResult) {
|
|
6969
6780
|
if (turnResult.toolCalls.length === 0) return { content: turnResult.text };
|
|
6970
6781
|
const toolCalls = turnResult.toolCalls.map((toolCall) => ({
|
|
@@ -7167,12 +6978,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
7167
6978
|
const binaries = await this.resolveInlineBinaries(attachments, ctx);
|
|
7168
6979
|
return AgentBinaryContentFactory.withBinaries(promptMessages, binaries);
|
|
7169
6980
|
}
|
|
7170
|
-
/**
|
|
7171
|
-
* Picks which attachments feed the passdown. When the author supplies `config.binaries`
|
|
7172
|
-
* (a static array or a per-item function — e.g. to forward binaries from an earlier node),
|
|
7173
|
-
* those replace the current item's attachments; otherwise the current item's `item.binary`
|
|
7174
|
-
* is used.
|
|
7175
|
-
*/
|
|
7176
6981
|
selectBinaryAttachments(item, itemIndex, items, ctx) {
|
|
7177
6982
|
const manual = ctx.config.binaries;
|
|
7178
6983
|
if (manual !== void 0) return typeof manual === "function" ? manual({
|
|
@@ -7183,14 +6988,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
7183
6988
|
}) : manual;
|
|
7184
6989
|
return item.binary ? Object.values(item.binary) : [];
|
|
7185
6990
|
}
|
|
7186
|
-
/**
|
|
7187
|
-
* Reads every attachment through `ctx.binary` (storage-backed, by reference — never base64 on
|
|
7188
|
-
* `item.json`) and resolves it to inline base64 so the agent can pass it to the chat model as a
|
|
7189
|
-
* native multimodal block. Images become image blocks; every other type (PDF, office docs, CSV,
|
|
7190
|
-
* JSON, …) becomes a file block — we don't filter by media type, so any binary can be fed to the
|
|
7191
|
-
* model. If the provider rejects an unsupported type the error surfaces at runtime, and the
|
|
7192
|
-
* workflow can filter the binary upstream.
|
|
7193
|
-
*/
|
|
7194
6991
|
async resolveInlineBinaries(attachments, ctx) {
|
|
7195
6992
|
const resolved = [];
|
|
7196
6993
|
for (const attachment of attachments) {
|
|
@@ -7203,12 +7000,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
7203
7000
|
}
|
|
7204
7001
|
return resolved;
|
|
7205
7002
|
}
|
|
7206
|
-
/**
|
|
7207
|
-
* When `item.json.__source` matches an entry in `config.untrustedSources`
|
|
7208
|
-
* (default: `["gmail", "ocr", "webhook"]`), wraps every user-role message
|
|
7209
|
-
* content with an untrusted-external-source preamble so the LLM treats the
|
|
7210
|
-
* content as data, not instructions.
|
|
7211
|
-
*/
|
|
7212
7003
|
wrapUntrustedSourceMessages(messages, item, config$1) {
|
|
7213
7004
|
const source = item.json !== null && typeof item.json === "object" ? item.json.__source : void 0;
|
|
7214
7005
|
if (typeof source !== "string") return messages;
|
|
@@ -7301,10 +7092,6 @@ AIAgentNode = __decorate([
|
|
|
7301
7092
|
|
|
7302
7093
|
//#endregion
|
|
7303
7094
|
//#region src/nodes/AIAgentConfig.ts
|
|
7304
|
-
/**
|
|
7305
|
-
* AI agent: credential bindings are keyed to connection-owned LLM/tool node ids (ConnectionNodeIdFactory),
|
|
7306
|
-
* not to the agent workflow node id.
|
|
7307
|
-
*/
|
|
7308
7095
|
var AIAgent = class {
|
|
7309
7096
|
kind = "node";
|
|
7310
7097
|
type = AIAgentNode;
|
|
@@ -7324,6 +7111,7 @@ var AIAgent = class {
|
|
|
7324
7111
|
pinnedMcpTools;
|
|
7325
7112
|
untrustedSources;
|
|
7326
7113
|
passBinariesToModel;
|
|
7114
|
+
passToolBinariesToModel;
|
|
7327
7115
|
binaries;
|
|
7328
7116
|
constructor(options) {
|
|
7329
7117
|
this.name = options.name;
|
|
@@ -7340,6 +7128,7 @@ var AIAgent = class {
|
|
|
7340
7128
|
this.pinnedMcpTools = options.pinnedMcpTools;
|
|
7341
7129
|
this.untrustedSources = options.untrustedSources;
|
|
7342
7130
|
this.passBinariesToModel = options.passBinariesToModel;
|
|
7131
|
+
this.passToolBinariesToModel = options.passToolBinariesToModel;
|
|
7343
7132
|
this.binaries = options.binaries;
|
|
7344
7133
|
}
|
|
7345
7134
|
inspectorSummary() {
|
|
@@ -7400,11 +7189,6 @@ AssertionNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemat
|
|
|
7400
7189
|
|
|
7401
7190
|
//#endregion
|
|
7402
7191
|
//#region src/nodes/assertion.ts
|
|
7403
|
-
/**
|
|
7404
|
-
* Generic assertion node — the "callback" form. For declarative shorthands (StringEquals,
|
|
7405
|
-
* JudgeByAgent) compose this with helpers added in later phases. Sets `emitsAssertions: true`
|
|
7406
|
-
* so host-side persisters know to record its outputs as `TestAssertion` rows.
|
|
7407
|
-
*/
|
|
7408
7192
|
var Assertion = class {
|
|
7409
7193
|
kind = "node";
|
|
7410
7194
|
type = AssertionNode;
|
|
@@ -7667,17 +7451,12 @@ HttpRequestNode = __decorate([(0, __codemation_core.node)({ packageName: "@codem
|
|
|
7667
7451
|
|
|
7668
7452
|
//#endregion
|
|
7669
7453
|
//#region src/nodes/httpRequest.ts
|
|
7670
|
-
/**
|
|
7671
|
-
* The built-in HTTP request credential type IDs accepted by the `HttpRequest` node.
|
|
7672
|
-
* These match the four generic credential types shipped with `@codemation/core-nodes`.
|
|
7673
|
-
*/
|
|
7674
7454
|
const HTTP_REQUEST_ACCEPTED_CREDENTIAL_TYPES = [
|
|
7675
7455
|
bearerTokenCredentialType.definition.typeId,
|
|
7676
7456
|
apiKeyCredentialType.definition.typeId,
|
|
7677
7457
|
basicAuthCredentialType.definition.typeId,
|
|
7678
7458
|
oauth2ClientCredentialsType.definition.typeId
|
|
7679
7459
|
];
|
|
7680
|
-
/** Default maximum response size for binary mode: 100 MiB. */
|
|
7681
7460
|
const DEFAULT_RESPONSE_SIZE_CAP_BYTES = 100 * 1024 * 1024;
|
|
7682
7461
|
var HttpRequest = class {
|
|
7683
7462
|
kind = "node";
|
|
@@ -7846,9 +7625,6 @@ var Filter = class {
|
|
|
7846
7625
|
function getOriginIndex(item) {
|
|
7847
7626
|
return (0, __codemation_core.getOriginIndexFromItem)(item);
|
|
7848
7627
|
}
|
|
7849
|
-
/**
|
|
7850
|
-
* Tags items routed to fan-in merge-by-origin (same contract as {@link IfNode} / {@link SwitchNode}).
|
|
7851
|
-
*/
|
|
7852
7628
|
function tagItemForRouterFanIn(args) {
|
|
7853
7629
|
const { item, itemIndex, nodeId, inputPortLabel = "$in" } = args;
|
|
7854
7630
|
const metaBase = item.meta && typeof item.meta === "object" ? item.meta : {};
|
|
@@ -7939,10 +7715,6 @@ IsTestRunNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemat
|
|
|
7939
7715
|
|
|
7940
7716
|
//#endregion
|
|
7941
7717
|
//#region src/nodes/isTestRun.ts
|
|
7942
|
-
/**
|
|
7943
|
-
* Branches per-item on whether the current run is a test run. Output ports: `true`, `false`.
|
|
7944
|
-
* The wire payload is unchanged — this is a router, not a transform.
|
|
7945
|
-
*/
|
|
7946
7718
|
var IsTestRun = class {
|
|
7947
7719
|
kind = "node";
|
|
7948
7720
|
type = IsTestRunNode;
|
|
@@ -8026,10 +7798,6 @@ var Split = class {
|
|
|
8026
7798
|
type = SplitNode;
|
|
8027
7799
|
execution = { hint: "local" };
|
|
8028
7800
|
keepBinaries = true;
|
|
8029
|
-
/**
|
|
8030
|
-
* When splitting yields zero items for a batch, downstream single-input nodes still run once with an empty batch.
|
|
8031
|
-
* Mirrors {@link MapData}'s empty-output behavior.
|
|
8032
|
-
*/
|
|
8033
7801
|
continueWhenEmptyOutput = true;
|
|
8034
7802
|
icon = "builtin:split-rows";
|
|
8035
7803
|
id;
|
|
@@ -8083,15 +7851,6 @@ CronTriggerNode = __decorate([(0, __codemation_core.node)({ packageName: "@codem
|
|
|
8083
7851
|
|
|
8084
7852
|
//#endregion
|
|
8085
7853
|
//#region src/nodes/CronTriggerFactory.ts
|
|
8086
|
-
/**
|
|
8087
|
-
* Schedules a workflow on a standard cron expression.
|
|
8088
|
-
*
|
|
8089
|
-
* Each tick emits one item: `{ firedAt: string, scheduledFor: string }` — both ISO-8601 timestamps.
|
|
8090
|
-
* `firedAt` is the wall-clock moment the callback ran; `scheduledFor` is the cron-computed
|
|
8091
|
-
* firing instant (these differ when the job was delayed).
|
|
8092
|
-
*
|
|
8093
|
-
* Timezone defaults to UTC when omitted — cron without an explicit TZ is a DST footgun.
|
|
8094
|
-
*/
|
|
8095
7854
|
var CronTrigger = class {
|
|
8096
7855
|
kind = "trigger";
|
|
8097
7856
|
type = CronTriggerNode;
|
|
@@ -8162,7 +7921,6 @@ var ManualTrigger = class ManualTrigger {
|
|
|
8162
7921
|
defaultItems;
|
|
8163
7922
|
id;
|
|
8164
7923
|
description;
|
|
8165
|
-
/** Manual runs often emit an empty batch; still schedule downstream by default. */
|
|
8166
7924
|
continueWhenEmptyOutput = true;
|
|
8167
7925
|
constructor(name = "Manual trigger", defaultItemsOrId, idOrOptions) {
|
|
8168
7926
|
this.name = name;
|
|
@@ -8217,7 +7975,6 @@ var MapData = class {
|
|
|
8217
7975
|
kind = "node";
|
|
8218
7976
|
type = MapDataNode;
|
|
8219
7977
|
execution = { hint: "local" };
|
|
8220
|
-
/** Zero mapped items should still allow downstream nodes to run. */
|
|
8221
7978
|
continueWhenEmptyOutput = true;
|
|
8222
7979
|
icon = "lucide:square-pen";
|
|
8223
7980
|
keepBinaries;
|
|
@@ -8450,11 +8207,6 @@ TestTriggerNode = __decorate([(0, __codemation_core.node)({ packageName: "@codem
|
|
|
8450
8207
|
|
|
8451
8208
|
//#endregion
|
|
8452
8209
|
//#region src/nodes/testTrigger.ts
|
|
8453
|
-
/**
|
|
8454
|
-
* Trigger config for a test fixture source. Drop one (or more) of these on the canvas alongside
|
|
8455
|
-
* a workflow's live triggers; clicking "Run tests" on the Tests tab invokes
|
|
8456
|
-
* {@link TestTriggerOptions.generateItems} via the TestSuiteOrchestrator.
|
|
8457
|
-
*/
|
|
8458
8210
|
var TestTrigger = class {
|
|
8459
8211
|
kind = "trigger";
|
|
8460
8212
|
triggerKind = "test";
|
|
@@ -8528,7 +8280,6 @@ var Wait = class {
|
|
|
8528
8280
|
kind = "node";
|
|
8529
8281
|
type = WaitNode;
|
|
8530
8282
|
execution = { hint: "local" };
|
|
8531
|
-
/** Pass-through empty batches should still advance to downstream nodes. */
|
|
8532
8283
|
continueWhenEmptyOutput = true;
|
|
8533
8284
|
icon = "lucide:hourglass";
|
|
8534
8285
|
id;
|
|
@@ -8630,6 +8381,39 @@ var WebhookTrigger = class WebhookTrigger {
|
|
|
8630
8381
|
}
|
|
8631
8382
|
};
|
|
8632
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
|
+
|
|
8633
8417
|
//#endregion
|
|
8634
8418
|
//#region src/nodes/ConnectionCredentialNode.ts
|
|
8635
8419
|
let ConnectionCredentialNode = class ConnectionCredentialNode$1 {
|
|
@@ -8643,11 +8427,6 @@ ConnectionCredentialNode = __decorate([(0, __codemation_core.node)({ packageName
|
|
|
8643
8427
|
|
|
8644
8428
|
//#endregion
|
|
8645
8429
|
//#region src/register.types.ts
|
|
8646
|
-
/**
|
|
8647
|
-
* Registrar for built-in nodes. In a real project, this would use tsyringe's
|
|
8648
|
-
* container.registerSingleton(...). For the skeleton we keep it token-based:
|
|
8649
|
-
* the engine resolves node implementations by class token.
|
|
8650
|
-
*/
|
|
8651
8430
|
function registerCoreNodes(container) {}
|
|
8652
8431
|
|
|
8653
8432
|
//#endregion
|
|
@@ -8876,9 +8655,6 @@ function workflow(id) {
|
|
|
8876
8655
|
|
|
8877
8656
|
//#endregion
|
|
8878
8657
|
//#region src/workflows/AIAgentConnectionWorkflowExpander.ts
|
|
8879
|
-
/**
|
|
8880
|
-
* Materializes connection-owned child nodes and {@link WorkflowDefinition.connections} for AI agent nodes.
|
|
8881
|
-
*/
|
|
8882
8658
|
var AIAgentConnectionWorkflowExpander = class {
|
|
8883
8659
|
constructor(connectionCredentialNodeConfigFactory, mcpServerResolver) {
|
|
8884
8660
|
this.connectionCredentialNodeConfigFactory = connectionCredentialNodeConfigFactory;
|
|
@@ -9146,16 +8922,6 @@ const collectionDeleteNode = (0, __codemation_core.defineNode)({
|
|
|
9146
8922
|
function resolveSubjectField(field, item) {
|
|
9147
8923
|
return typeof field === "function" ? field({ item }) : field;
|
|
9148
8924
|
}
|
|
9149
|
-
/**
|
|
9150
|
-
* Auto-detecting inbox approval node.
|
|
9151
|
-
*
|
|
9152
|
-
* Uses `ctx.resolve(InboxChannelResolverToken)` to pick the right inbox channel
|
|
9153
|
-
* at runtime:
|
|
9154
|
-
* - In managed mode (PairingConfig present): routes to the control-plane inbox.
|
|
9155
|
-
* - Otherwise: routes to the local inbox.
|
|
9156
|
-
*
|
|
9157
|
-
* Authors use this node directly; no extra wiring needed per deployment mode.
|
|
9158
|
-
*/
|
|
9159
8925
|
const inboxApproval = (0, __codemation_core.defineHumanApprovalNode)({
|
|
9160
8926
|
key: "inbox.approval",
|
|
9161
8927
|
title: "Inbox Approval",
|
|
@@ -9548,5 +9314,6 @@ exports.inboxApproval = inboxApproval;
|
|
|
9548
9314
|
exports.oauth2ClientCredentialsType = oauth2ClientCredentialsType;
|
|
9549
9315
|
exports.openAiChatModelPresets = openAiChatModelPresets;
|
|
9550
9316
|
exports.registerCoreNodes = registerCoreNodes;
|
|
9317
|
+
exports.schedulePollingTrigger = schedulePollingTrigger;
|
|
9551
9318
|
exports.workflow = workflow;
|
|
9552
9319
|
//# sourceMappingURL=index.cjs.map
|