@codemation/core-nodes 0.8.1 → 0.10.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 +49 -0
- package/dist/index.cjs +441 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +945 -694
- package/dist/index.d.ts +945 -694
- package/dist/index.js +441 -57
- package/dist/index.js.map +1 -1
- package/dist/metadata.json +13 -1
- package/package.json +2 -2
- package/src/chatModels/CodemationChatModelConfig.ts +1 -1
- package/src/chatModels/CodemationChatModelFactory.ts +2 -61
- package/src/chatModels/ManagedHmacSignerFactory.types.ts +88 -0
- package/src/index.ts +2 -0
- package/src/nodes/AIAgentNode.ts +173 -11
- package/src/nodes/AgentLoopCheckpoint.types.ts +23 -0
- package/src/nodes/AgentToolExecutionCoordinator.ts +91 -2
- package/src/nodes/InboxApprovalNode.types.ts +87 -0
- package/src/nodes/aiAgentSupport.types.ts +5 -0
- package/src/nodes/codemationDocumentScannerNode.ts +131 -0
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AgentConfigInspector, AgentConnectionNodeCollector, AgentGuardrailDefaults, AgentMessageConfigNormalizer, CallableToolConfig, ChildExecutionScopeFactory, CodemationTelemetryAttributeNames, CodemationTelemetryMetricNames, ConnectionInvocationIdFactory, ConnectionNodeIdFactory, CoreTokens, DefinedNodeRegistry, GenAiTelemetryAttributeNames, ItemExprResolver, ItemsInputNormalizer, NodeBackedToolConfig, NodeOutputNormalizer, RetryPolicy, RunnableOutputBehaviorResolver, WorkflowBuilder, chatModel, defineCredential, defineNode, emitPorts, getOriginIndexFromItem, inject, injectable, isPortsEmission, node } from "@codemation/core";
|
|
1
|
+
import { AgentConfigInspector, AgentConnectionNodeCollector, AgentGuardrailDefaults, AgentMessageConfigNormalizer, CallableToolConfig, ChildExecutionScopeFactory, CodemationTelemetryAttributeNames, CodemationTelemetryMetricNames, ConnectionInvocationIdFactory, ConnectionNodeIdFactory, CoreTokens, DefinedNodeRegistry, GenAiTelemetryAttributeNames, InboxChannelResolverToken, ItemExprResolver, ItemsInputNormalizer, NodeBackedToolConfig, NodeOutputNormalizer, RetryPolicy, RunnableOutputBehaviorResolver, SuspensionRequest, WorkflowBuilder, chatModel, defineCredential, defineHumanApprovalNode, defineNode, emitPorts, getOriginIndexFromItem, inject, injectable, isPortsEmission, node } from "@codemation/core";
|
|
2
2
|
import dns from "node:dns/promises";
|
|
3
3
|
import { createOpenAI } from "@ai-sdk/openai";
|
|
4
4
|
import { CredentialResolverFactory } from "@codemation/core/bootstrap";
|
|
@@ -1279,6 +1279,7 @@ const string$1 = (params) => {
|
|
|
1279
1279
|
};
|
|
1280
1280
|
const integer = /^-?\d+$/;
|
|
1281
1281
|
const number$1 = /^-?\d+(?:\.\d+)?$/;
|
|
1282
|
+
const boolean$1 = /^(?:true|false)$/i;
|
|
1282
1283
|
const lowercase = /^[^A-Z]*$/;
|
|
1283
1284
|
const uppercase = /^[^a-z]*$/;
|
|
1284
1285
|
|
|
@@ -2057,6 +2058,24 @@ const $ZodNumberFormat = /* @__PURE__ */ $constructor("$ZodNumberFormat", (inst,
|
|
|
2057
2058
|
$ZodCheckNumberFormat.init(inst, def);
|
|
2058
2059
|
$ZodNumber.init(inst, def);
|
|
2059
2060
|
});
|
|
2061
|
+
const $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
|
|
2062
|
+
$ZodType.init(inst, def);
|
|
2063
|
+
inst._zod.pattern = boolean$1;
|
|
2064
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
2065
|
+
if (def.coerce) try {
|
|
2066
|
+
payload.value = Boolean(payload.value);
|
|
2067
|
+
} catch (_) {}
|
|
2068
|
+
const input = payload.value;
|
|
2069
|
+
if (typeof input === "boolean") return payload;
|
|
2070
|
+
payload.issues.push({
|
|
2071
|
+
expected: "boolean",
|
|
2072
|
+
code: "invalid_type",
|
|
2073
|
+
input,
|
|
2074
|
+
inst
|
|
2075
|
+
});
|
|
2076
|
+
return payload;
|
|
2077
|
+
};
|
|
2078
|
+
});
|
|
2060
2079
|
const $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
2061
2080
|
$ZodType.init(inst, def);
|
|
2062
2081
|
inst._zod.parse = (payload) => payload;
|
|
@@ -3133,6 +3152,13 @@ function _int(Class, params) {
|
|
|
3133
3152
|
});
|
|
3134
3153
|
}
|
|
3135
3154
|
/* @__NO_SIDE_EFFECTS__ */
|
|
3155
|
+
function _boolean(Class, params) {
|
|
3156
|
+
return new Class({
|
|
3157
|
+
type: "boolean",
|
|
3158
|
+
...normalizeParams(params)
|
|
3159
|
+
});
|
|
3160
|
+
}
|
|
3161
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
3136
3162
|
function _unknown(Class) {
|
|
3137
3163
|
return new Class({ type: "unknown" });
|
|
3138
3164
|
}
|
|
@@ -3299,6 +3325,17 @@ function _array(Class, element, params) {
|
|
|
3299
3325
|
});
|
|
3300
3326
|
}
|
|
3301
3327
|
/* @__NO_SIDE_EFFECTS__ */
|
|
3328
|
+
function _custom(Class, fn, _params) {
|
|
3329
|
+
const norm = normalizeParams(_params);
|
|
3330
|
+
norm.abort ?? (norm.abort = true);
|
|
3331
|
+
return new Class({
|
|
3332
|
+
type: "custom",
|
|
3333
|
+
check: "custom",
|
|
3334
|
+
fn,
|
|
3335
|
+
...norm
|
|
3336
|
+
});
|
|
3337
|
+
}
|
|
3338
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
3302
3339
|
function _refine(Class, fn, _params) {
|
|
3303
3340
|
return new Class({
|
|
3304
3341
|
type: "custom",
|
|
@@ -4322,6 +4359,59 @@ var OpenAiChatModelPresets = class {
|
|
|
4322
4359
|
};
|
|
4323
4360
|
const openAiChatModelPresets = new OpenAiChatModelPresets();
|
|
4324
4361
|
|
|
4362
|
+
//#endregion
|
|
4363
|
+
//#region src/chatModels/ManagedHmacSignerFactory.types.ts
|
|
4364
|
+
/**
|
|
4365
|
+
* Creates an HMAC-signing fetch wrapper that authenticates requests to
|
|
4366
|
+
* Codemation managed services (LLM broker, doc-scanner) with the
|
|
4367
|
+
* Codemation-Hmac v=1 scheme.
|
|
4368
|
+
*
|
|
4369
|
+
* Mirrors HmacRequestSigner from @codemation/host/pairing without importing
|
|
4370
|
+
* that package (which would create a circular dependency since @codemation/host
|
|
4371
|
+
* depends on @codemation/core-nodes).
|
|
4372
|
+
*
|
|
4373
|
+
* @param workspaceId - Workspace identifier injected by the CP provisioner.
|
|
4374
|
+
* @param pairingSecret - Base64-encoded 32-byte HMAC key injected by the provisioner.
|
|
4375
|
+
* @param options - Optional behaviour flags and test seams.
|
|
4376
|
+
*/
|
|
4377
|
+
function managedHmacFetchFactory(workspaceId, pairingSecret, options) {
|
|
4378
|
+
const signBody = options?.signBody ?? true;
|
|
4379
|
+
return async (input, init) => {
|
|
4380
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
4381
|
+
const method = init?.method ?? "POST";
|
|
4382
|
+
let bodyForSigning = "";
|
|
4383
|
+
if (signBody && init?.body !== void 0 && init.body !== null) bodyForSigning = typeof init.body === "string" ? init.body : await new Response(init.body).text();
|
|
4384
|
+
const authHeader = buildHmacAuthHeader(workspaceId, pairingSecret, method, url, bodyForSigning, options);
|
|
4385
|
+
const headers = new Headers(init?.headers);
|
|
4386
|
+
headers.set("Authorization", authHeader);
|
|
4387
|
+
const outgoingBody = signBody ? bodyForSigning || init?.body : init?.body;
|
|
4388
|
+
return fetch(input, {
|
|
4389
|
+
...init,
|
|
4390
|
+
body: outgoingBody,
|
|
4391
|
+
headers
|
|
4392
|
+
});
|
|
4393
|
+
};
|
|
4394
|
+
}
|
|
4395
|
+
/**
|
|
4396
|
+
* Produces a Codemation-Hmac v=1 Authorization header value.
|
|
4397
|
+
* Algorithm must match HmacVerifier.computeSignature() in the control-plane.
|
|
4398
|
+
*/
|
|
4399
|
+
function buildHmacAuthHeader(workspaceId, pairingSecret, method, url, body, overrides) {
|
|
4400
|
+
const ts = overrides?.now ? overrides.now() : Math.floor(Date.now() / 1e3);
|
|
4401
|
+
const nonce = overrides?.nonce ? overrides.nonce() : randomBytes(16).toString("base64");
|
|
4402
|
+
const parsed = new URL(url);
|
|
4403
|
+
const path = (parsed.pathname + parsed.search).toLowerCase();
|
|
4404
|
+
const bodyHash = createHash("sha256").update(body, "utf8").digest("hex");
|
|
4405
|
+
const baseString = [
|
|
4406
|
+
method.toUpperCase(),
|
|
4407
|
+
path,
|
|
4408
|
+
ts,
|
|
4409
|
+
nonce,
|
|
4410
|
+
bodyHash
|
|
4411
|
+
].join("\n");
|
|
4412
|
+
return `Codemation-Hmac v=1,workspaceId=${workspaceId},ts=${ts},nonce=${nonce},sig=${createHmac("sha256", Buffer.from(pairingSecret, "base64")).update(baseString, "utf8").digest("base64")}`;
|
|
4413
|
+
}
|
|
4414
|
+
|
|
4325
4415
|
//#endregion
|
|
4326
4416
|
//#region src/chatModels/CodemationChatModelFactory.ts
|
|
4327
4417
|
let CodemationChatModelFactory = class CodemationChatModelFactory$1 {
|
|
@@ -4331,7 +4421,7 @@ let CodemationChatModelFactory = class CodemationChatModelFactory$1 {
|
|
|
4331
4421
|
const workspaceId = process.env["WORKSPACE_ID"];
|
|
4332
4422
|
const pairingSecret = process.env["WORKSPACE_PAIRING_SECRET"];
|
|
4333
4423
|
if (!workspaceId || !pairingSecret) throw new Error("Codemation managed AI not available in this environment (workspace pairing is not configured).");
|
|
4334
|
-
const hmacFetch =
|
|
4424
|
+
const hmacFetch = managedHmacFetchFactory(workspaceId, pairingSecret);
|
|
4335
4425
|
const languageModel = createOpenAI({
|
|
4336
4426
|
baseURL: `${gatewayUrl}/v1`,
|
|
4337
4427
|
apiKey: "codemation-managed",
|
|
@@ -4347,52 +4437,6 @@ let CodemationChatModelFactory = class CodemationChatModelFactory$1 {
|
|
|
4347
4437
|
}
|
|
4348
4438
|
});
|
|
4349
4439
|
}
|
|
4350
|
-
/**
|
|
4351
|
-
* Creates an HMAC-signed fetch wrapper for use with AI SDK's createOpenAI.
|
|
4352
|
-
* Each call signs the request body with the workspace pairing secret so the
|
|
4353
|
-
* LLM broker can authenticate the workspace without a user-managed API key.
|
|
4354
|
-
*
|
|
4355
|
-
* Mirrors HmacRequestSigner from @codemation/host/pairing without importing
|
|
4356
|
-
* that package (which would create a circular dependency since @codemation/host
|
|
4357
|
-
* depends on @codemation/core-nodes).
|
|
4358
|
-
*/
|
|
4359
|
-
buildHmacSignedFetch(workspaceId, pairingSecret) {
|
|
4360
|
-
return async (input, init) => {
|
|
4361
|
-
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
4362
|
-
const method = init?.method ?? "POST";
|
|
4363
|
-
let bodyString = "";
|
|
4364
|
-
if (init?.body !== void 0 && init.body !== null) if (typeof init.body === "string") bodyString = init.body;
|
|
4365
|
-
else bodyString = await new Response(init.body).text();
|
|
4366
|
-
const authHeader = this.buildHmacAuthHeader(workspaceId, pairingSecret, method, url, bodyString);
|
|
4367
|
-
const headers = new Headers(init?.headers);
|
|
4368
|
-
headers.set("Authorization", authHeader);
|
|
4369
|
-
const effectiveBody = bodyString || init?.body;
|
|
4370
|
-
return fetch(input, {
|
|
4371
|
-
...init,
|
|
4372
|
-
body: effectiveBody,
|
|
4373
|
-
headers
|
|
4374
|
-
});
|
|
4375
|
-
};
|
|
4376
|
-
}
|
|
4377
|
-
/**
|
|
4378
|
-
* Produces a Codemation-Hmac v1 Authorization header value.
|
|
4379
|
-
* The algorithm must match HmacVerifier.computeSignature() in the control-plane.
|
|
4380
|
-
*/
|
|
4381
|
-
buildHmacAuthHeader(workspaceId, pairingSecret, method, url, body) {
|
|
4382
|
-
const ts = Math.floor(Date.now() / 1e3);
|
|
4383
|
-
const nonce = randomBytes(16).toString("base64");
|
|
4384
|
-
const parsed = new URL(url);
|
|
4385
|
-
const path = (parsed.pathname + parsed.search).toLowerCase();
|
|
4386
|
-
const bodyHash = createHash("sha256").update(body, "utf8").digest("hex");
|
|
4387
|
-
const baseString = [
|
|
4388
|
-
method.toUpperCase(),
|
|
4389
|
-
path,
|
|
4390
|
-
ts,
|
|
4391
|
-
nonce,
|
|
4392
|
-
bodyHash
|
|
4393
|
-
].join("\n");
|
|
4394
|
-
return `Codemation-Hmac v=1,workspaceId=${workspaceId},ts=${ts},nonce=${nonce},sig=${createHmac("sha256", Buffer.from(pairingSecret, "base64")).update(baseString, "utf8").digest("base64")}`;
|
|
4395
|
-
}
|
|
4396
4440
|
};
|
|
4397
4441
|
CodemationChatModelFactory = __decorate([chatModel({ packageName: "@codemation/core-nodes" })], CodemationChatModelFactory);
|
|
4398
4442
|
|
|
@@ -4895,6 +4939,14 @@ const ZodNumberFormat = /* @__PURE__ */ $constructor("ZodNumberFormat", (inst, d
|
|
|
4895
4939
|
function int(params) {
|
|
4896
4940
|
return _int(ZodNumberFormat, params);
|
|
4897
4941
|
}
|
|
4942
|
+
const ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
|
|
4943
|
+
$ZodBoolean.init(inst, def);
|
|
4944
|
+
ZodType.init(inst, def);
|
|
4945
|
+
inst._zod.processJSONSchema = (ctx, json, params) => booleanProcessor(inst, ctx, json, params);
|
|
4946
|
+
});
|
|
4947
|
+
function boolean(params) {
|
|
4948
|
+
return _boolean(ZodBoolean, params);
|
|
4949
|
+
}
|
|
4898
4950
|
const ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
4899
4951
|
$ZodUnknown.init(inst, def);
|
|
4900
4952
|
ZodType.init(inst, def);
|
|
@@ -5206,6 +5258,9 @@ const ZodCustom = /* @__PURE__ */ $constructor("ZodCustom", (inst, def) => {
|
|
|
5206
5258
|
ZodType.init(inst, def);
|
|
5207
5259
|
inst._zod.processJSONSchema = (ctx, json, params) => customProcessor(inst, ctx, json, params);
|
|
5208
5260
|
});
|
|
5261
|
+
function custom(fn, _params) {
|
|
5262
|
+
return _custom(ZodCustom, fn ?? (() => true), _params);
|
|
5263
|
+
}
|
|
5209
5264
|
function refine(fn, _params = {}) {
|
|
5210
5265
|
return _refine(ZodCustom, fn, _params);
|
|
5211
5266
|
}
|
|
@@ -5455,12 +5510,22 @@ let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
|
|
|
5455
5510
|
this.repairPolicy = repairPolicy;
|
|
5456
5511
|
}
|
|
5457
5512
|
async execute(args) {
|
|
5513
|
+
if (args.plannedToolCalls.filter((c) => c.binding.humanApproval !== void 0).length > 0 && args.plannedToolCalls.length > 1) return args.plannedToolCalls.map((c) => ({
|
|
5514
|
+
toolName: c.binding.config.name,
|
|
5515
|
+
toolCallId: c.toolCall.id ?? c.binding.config.name,
|
|
5516
|
+
result: { error: c.binding.humanApproval !== void 0 ? `HITL tool '${c.binding.config.name}' cannot be called alongside other tools in the same turn; call it alone.` : `deferred: a HITL tool in the same turn blocked execution. Retry this tool alone in the next turn.` },
|
|
5517
|
+
serialized: JSON.stringify({ error: c.binding.humanApproval !== void 0 ? `HITL tool '${c.binding.config.name}' cannot be called alongside other tools in the same turn; call it alone.` : `deferred: a HITL tool in the same turn blocked execution. Retry this tool alone in the next turn.` })
|
|
5518
|
+
}));
|
|
5458
5519
|
const results = await Promise.allSettled(args.plannedToolCalls.map(async (plannedToolCall) => await this.executePlannedToolCall({
|
|
5459
5520
|
...args,
|
|
5460
5521
|
plannedToolCall
|
|
5461
5522
|
})));
|
|
5462
5523
|
const rejected = results.find((result) => result.status === "rejected");
|
|
5463
|
-
if (rejected?.status === "rejected")
|
|
5524
|
+
if (rejected?.status === "rejected") {
|
|
5525
|
+
const reason = rejected.reason;
|
|
5526
|
+
if (reason instanceof SuspensionRequest) throw reason;
|
|
5527
|
+
throw reason instanceof Error ? reason : new Error(String(reason));
|
|
5528
|
+
}
|
|
5464
5529
|
return results.filter((result) => result.status === "fulfilled").map((result) => result.value);
|
|
5465
5530
|
}
|
|
5466
5531
|
async executePlannedToolCall(args) {
|
|
@@ -5545,6 +5610,34 @@ let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
|
|
|
5545
5610
|
result
|
|
5546
5611
|
};
|
|
5547
5612
|
} catch (error) {
|
|
5613
|
+
if (error instanceof SuspensionRequest) {
|
|
5614
|
+
const pendingToolCallId = plannedToolCall.toolCall.id ?? plannedToolCall.binding.config.name;
|
|
5615
|
+
const checkpoint = {
|
|
5616
|
+
conversation: args.conversationSnapshot ? [...args.conversationSnapshot] : [],
|
|
5617
|
+
turnCount: args.turnCount ?? 0,
|
|
5618
|
+
toolCallCount: args.toolCallCount ?? 0,
|
|
5619
|
+
pendingToolCallId,
|
|
5620
|
+
agentName: args.agentName,
|
|
5621
|
+
modelId: args.modelId ?? ""
|
|
5622
|
+
};
|
|
5623
|
+
const agentReasoning = this.extractLastAssistantText(args.conversationSnapshot ?? []);
|
|
5624
|
+
const augmented = new SuspensionRequest({
|
|
5625
|
+
...error.request,
|
|
5626
|
+
metadata: {
|
|
5627
|
+
...error.request.metadata,
|
|
5628
|
+
agentCheckpoint: checkpoint,
|
|
5629
|
+
pendingToolCallId,
|
|
5630
|
+
agentReasoning,
|
|
5631
|
+
onRejected: plannedToolCall.binding.humanApproval?.onRejected ?? "return"
|
|
5632
|
+
}
|
|
5633
|
+
});
|
|
5634
|
+
await span.end({
|
|
5635
|
+
status: "error",
|
|
5636
|
+
statusMessage: "suspended",
|
|
5637
|
+
endedAt: /* @__PURE__ */ new Date()
|
|
5638
|
+
});
|
|
5639
|
+
throw augmented;
|
|
5640
|
+
}
|
|
5548
5641
|
const classification = this.errorClassifier.classify({
|
|
5549
5642
|
error,
|
|
5550
5643
|
toolName: plannedToolCall.binding.config.name,
|
|
@@ -5720,6 +5813,24 @@ let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
|
|
|
5720
5813
|
extractErrorDetails(error) {
|
|
5721
5814
|
return error.details;
|
|
5722
5815
|
}
|
|
5816
|
+
/**
|
|
5817
|
+
* Extracts the text content from the last assistant message in the conversation snapshot.
|
|
5818
|
+
* Used to populate `agentReasoning` in the HITL suspension metadata.
|
|
5819
|
+
*/
|
|
5820
|
+
extractLastAssistantText(conversation) {
|
|
5821
|
+
for (let i = conversation.length - 1; i >= 0; i--) {
|
|
5822
|
+
const msg = conversation[i];
|
|
5823
|
+
if (msg?.role !== "assistant") continue;
|
|
5824
|
+
const content = msg.content;
|
|
5825
|
+
if (typeof content === "string") return content;
|
|
5826
|
+
if (Array.isArray(content)) {
|
|
5827
|
+
const textParts = content.filter((part) => typeof part === "object" && part.type === "text").map((part) => part.text);
|
|
5828
|
+
if (textParts.length > 0) return textParts.join("");
|
|
5829
|
+
}
|
|
5830
|
+
break;
|
|
5831
|
+
}
|
|
5832
|
+
return "";
|
|
5833
|
+
}
|
|
5723
5834
|
serializeIssue(issue$1) {
|
|
5724
5835
|
const result = {
|
|
5725
5836
|
path: [...issue$1.path],
|
|
@@ -6073,6 +6184,7 @@ var AgentItemPortMap = class {
|
|
|
6073
6184
|
//#endregion
|
|
6074
6185
|
//#region src/nodes/AIAgentNode.ts
|
|
6075
6186
|
var _ref, _ref2, _ref3, _ref4, _ref5;
|
|
6187
|
+
const HITL_SOLO_CONSTRAINT_SENTENCE = "This tool requires human approval and may take time. Call it alone — do not invoke other tools in the same turn. Your turn will be paused until a decision is made.";
|
|
6076
6188
|
let AIAgentNode = class AIAgentNode$1 {
|
|
6077
6189
|
kind = "node";
|
|
6078
6190
|
outputPorts = ["main"];
|
|
@@ -6090,13 +6202,90 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6090
6202
|
this.connectionCredentialExecutionContextFactory = this.executionHelpers.createConnectionCredentialExecutionContextFactory(credentialSessions);
|
|
6091
6203
|
}
|
|
6092
6204
|
async execute(args) {
|
|
6093
|
-
const
|
|
6205
|
+
const { ctx } = args;
|
|
6206
|
+
if (ctx.resumeContext) return this.executeResumed(args, ctx.resumeContext);
|
|
6207
|
+
const prepared = await this.getOrPrepareExecution(ctx);
|
|
6094
6208
|
const itemWithMappedJson = {
|
|
6095
6209
|
...args.item,
|
|
6096
6210
|
json: args.input
|
|
6097
6211
|
};
|
|
6098
6212
|
return (await this.runAgentForItem(prepared, itemWithMappedJson, args.itemIndex, args.items)).json;
|
|
6099
6213
|
}
|
|
6214
|
+
/**
|
|
6215
|
+
* Resume path: re-enters the agent loop after a HITL suspension.
|
|
6216
|
+
* Reconstructs the conversation from the checkpoint, injects the human decision
|
|
6217
|
+
* as a tool_result, and continues the loop from where it suspended.
|
|
6218
|
+
*/
|
|
6219
|
+
async executeResumed(args, resumeContext) {
|
|
6220
|
+
const { ctx } = args;
|
|
6221
|
+
const taskMetadata = resumeContext.task.metadata ?? {};
|
|
6222
|
+
const checkpoint = taskMetadata["agentCheckpoint"];
|
|
6223
|
+
const onRejected = taskMetadata["onRejected"] ?? "return";
|
|
6224
|
+
if (!checkpoint) {
|
|
6225
|
+
const prepared$1 = await this.getOrPrepareExecution(ctx);
|
|
6226
|
+
const itemWithMappedJson = {
|
|
6227
|
+
...args.item,
|
|
6228
|
+
json: args.input
|
|
6229
|
+
};
|
|
6230
|
+
return (await this.runAgentForItem(prepared$1, itemWithMappedJson, args.itemIndex, args.items)).json;
|
|
6231
|
+
}
|
|
6232
|
+
if (resumeContext.decision.kind === "decided" && resumeContext.decision.value === null && onRejected === "halt") return;
|
|
6233
|
+
const decision = this.normalizeDecision(resumeContext);
|
|
6234
|
+
if (decision.status === "rejected" && onRejected === "halt") return;
|
|
6235
|
+
const prepared = await this.getOrPrepareExecution(ctx);
|
|
6236
|
+
const item = args.item;
|
|
6237
|
+
const itemInputsByPort = AgentItemPortMap.fromItem(item);
|
|
6238
|
+
const itemScopedTools = this.createItemScopedTools(prepared.resolvedTools, ctx, item, args.itemIndex, args.items);
|
|
6239
|
+
const toolResultEntry = {
|
|
6240
|
+
toolName: checkpoint.pendingToolCallId,
|
|
6241
|
+
toolCallId: checkpoint.pendingToolCallId,
|
|
6242
|
+
result: decision,
|
|
6243
|
+
serialized: JSON.stringify(decision)
|
|
6244
|
+
};
|
|
6245
|
+
const conversation = [...checkpoint.conversation, AgentMessageFactory.createToolResultsMessage([toolResultEntry])];
|
|
6246
|
+
const loopResult = await this.runTurnLoopUntilFinalAnswer({
|
|
6247
|
+
prepared,
|
|
6248
|
+
itemInputsByPort,
|
|
6249
|
+
itemScopedTools,
|
|
6250
|
+
conversation,
|
|
6251
|
+
resumedTurnCount: checkpoint.turnCount,
|
|
6252
|
+
resumedToolCallCount: checkpoint.toolCallCount
|
|
6253
|
+
});
|
|
6254
|
+
await ctx.telemetry.recordMetric({
|
|
6255
|
+
name: CodemationTelemetryMetricNames.agentTurns,
|
|
6256
|
+
value: loopResult.turnCount
|
|
6257
|
+
});
|
|
6258
|
+
await ctx.telemetry.recordMetric({
|
|
6259
|
+
name: CodemationTelemetryMetricNames.agentToolCalls,
|
|
6260
|
+
value: loopResult.toolCallCount
|
|
6261
|
+
});
|
|
6262
|
+
const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, loopResult.finalText, itemScopedTools.length > 0);
|
|
6263
|
+
return this.buildOutputItem(item, outputJson).json;
|
|
6264
|
+
}
|
|
6265
|
+
/**
|
|
6266
|
+
* Normalizes a {@link ResumeContext} decision into a flat JSON-serializable shape
|
|
6267
|
+
* suitable for injection as a tool_result content.
|
|
6268
|
+
*/
|
|
6269
|
+
normalizeDecision(resumeContext) {
|
|
6270
|
+
const { decision } = resumeContext;
|
|
6271
|
+
if (decision.kind === "decided") {
|
|
6272
|
+
const value = decision.value;
|
|
6273
|
+
return {
|
|
6274
|
+
status: (typeof value === "object" && value !== null && "approved" in value ? Boolean(value["approved"]) : true) ? "approved" : "rejected",
|
|
6275
|
+
value: decision.value,
|
|
6276
|
+
actor: decision.actor,
|
|
6277
|
+
decidedAt: decision.decidedAt.toISOString()
|
|
6278
|
+
};
|
|
6279
|
+
}
|
|
6280
|
+
if (decision.kind === "timed_out") return {
|
|
6281
|
+
status: "timed_out",
|
|
6282
|
+
at: decision.at.toISOString()
|
|
6283
|
+
};
|
|
6284
|
+
return {
|
|
6285
|
+
status: "auto_accepted",
|
|
6286
|
+
at: decision.at.toISOString()
|
|
6287
|
+
};
|
|
6288
|
+
}
|
|
6100
6289
|
async getOrPrepareExecution(ctx) {
|
|
6101
6290
|
let pending = this.preparedByExecutionContext.get(ctx);
|
|
6102
6291
|
if (!pending) {
|
|
@@ -6217,7 +6406,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6217
6406
|
const { prepared, itemInputsByPort, itemScopedTools, conversation } = args;
|
|
6218
6407
|
const { ctx, guardrails, toolLoadingStrategy } = prepared;
|
|
6219
6408
|
let finalText = "";
|
|
6220
|
-
let toolCallCount = 0;
|
|
6409
|
+
let toolCallCount = args.resumedToolCallCount ?? 0;
|
|
6221
6410
|
let turnCount = 0;
|
|
6222
6411
|
const repairAttemptsByToolName = /* @__PURE__ */ new Map();
|
|
6223
6412
|
/** Tool IDs surfaced by find_tools across all prior turns in this item run. */
|
|
@@ -6258,11 +6447,17 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6258
6447
|
const plannedToolCalls = this.planToolCalls(itemScopedTools, coordinatorCalls, ctx.nodeId);
|
|
6259
6448
|
toolCallCount += plannedToolCalls.length;
|
|
6260
6449
|
await this.markQueuedTools(plannedToolCalls, ctx);
|
|
6450
|
+
const assistantMsg = result.assistantMessage ?? AgentMessageFactory.createAssistantWithToolCalls(result.text, result.toolCalls);
|
|
6451
|
+
const conversationWithAssistant = [...conversation, assistantMsg];
|
|
6261
6452
|
const executed = await this.toolExecutionCoordinator.execute({
|
|
6262
6453
|
plannedToolCalls,
|
|
6263
6454
|
ctx,
|
|
6264
6455
|
agentName: this.getAgentDisplayName(ctx),
|
|
6265
|
-
repairAttemptsByToolName
|
|
6456
|
+
repairAttemptsByToolName,
|
|
6457
|
+
conversationSnapshot: conversationWithAssistant,
|
|
6458
|
+
turnCount,
|
|
6459
|
+
toolCallCount,
|
|
6460
|
+
modelId: this.resolveChatModelName(ctx.config.chatModel)
|
|
6266
6461
|
});
|
|
6267
6462
|
coordinatorExecutedCalls.push(...executed);
|
|
6268
6463
|
}
|
|
@@ -6324,6 +6519,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6324
6519
|
connectionNodeId: ConnectionNodeIdFactory.toolConnectionNodeId(ctx.nodeId, entry.config.name),
|
|
6325
6520
|
getCredentialRequirements: () => entry.config.getCredentialRequirements?.() ?? []
|
|
6326
6521
|
});
|
|
6522
|
+
const hitlBehavior = this.resolveHumanApprovalBehavior(entry.config);
|
|
6327
6523
|
return {
|
|
6328
6524
|
config: entry.config,
|
|
6329
6525
|
inputSchema: entry.runtime.inputSchema,
|
|
@@ -6338,11 +6534,22 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6338
6534
|
items,
|
|
6339
6535
|
hooks
|
|
6340
6536
|
});
|
|
6341
|
-
}
|
|
6537
|
+
},
|
|
6538
|
+
...hitlBehavior !== void 0 ? { humanApproval: hitlBehavior } : {}
|
|
6342
6539
|
};
|
|
6343
6540
|
});
|
|
6344
6541
|
}
|
|
6345
6542
|
/**
|
|
6543
|
+
* Detects whether a tool config is backed by a `defineHumanApprovalNode` marker
|
|
6544
|
+
* and returns the HITL behavior config, or `undefined` when not a HITL tool.
|
|
6545
|
+
*/
|
|
6546
|
+
resolveHumanApprovalBehavior(config$1) {
|
|
6547
|
+
if (!this.isNodeBackedToolConfig(config$1)) return void 0;
|
|
6548
|
+
const marker = config$1.node.humanApprovalToolBehavior;
|
|
6549
|
+
if (marker === void 0) return void 0;
|
|
6550
|
+
return { onRejected: marker.onRejected ?? "return" };
|
|
6551
|
+
}
|
|
6552
|
+
/**
|
|
6346
6553
|
* Invoke a text turn using the merged tool set from item-scoped tools (coordinator-managed)
|
|
6347
6554
|
* and strategy tools (find_tools + discovered MCP tools).
|
|
6348
6555
|
* Strategy tools take precedence for names that overlap.
|
|
@@ -6372,6 +6579,8 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6372
6579
|
/**
|
|
6373
6580
|
* Builds a ToolSet from resolved tools for strategy initialization.
|
|
6374
6581
|
* The strategy uses this for its "always-included" node-backed tool descriptions.
|
|
6582
|
+
* HITL tools (detected via the `humanApprovalToolBehavior` field set by `defineHumanApprovalNode`) get the solo-constraint sentence
|
|
6583
|
+
* appended to their description.
|
|
6375
6584
|
*/
|
|
6376
6585
|
buildToolSetFromResolved(resolvedTools) {
|
|
6377
6586
|
if (resolvedTools.length === 0) return {};
|
|
@@ -6381,8 +6590,10 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6381
6590
|
schemaName: entry.config.name,
|
|
6382
6591
|
requireObjectRoot: true
|
|
6383
6592
|
});
|
|
6593
|
+
const baseDescription = entry.config.description ?? entry.runtime.defaultDescription;
|
|
6594
|
+
const description = this.resolveHumanApprovalBehavior(entry.config) !== void 0 ? `${baseDescription} ${HITL_SOLO_CONSTRAINT_SENTENCE}` : baseDescription;
|
|
6384
6595
|
toolSet[entry.config.name] = {
|
|
6385
|
-
description
|
|
6596
|
+
description,
|
|
6386
6597
|
inputSchema: jsonSchema(schemaRecord)
|
|
6387
6598
|
};
|
|
6388
6599
|
}
|
|
@@ -6410,8 +6621,10 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6410
6621
|
schemaName: entry.config.name,
|
|
6411
6622
|
requireObjectRoot: true
|
|
6412
6623
|
});
|
|
6624
|
+
const baseDescription = entry.config.description;
|
|
6625
|
+
const description = entry.humanApproval !== void 0 && baseDescription !== void 0 ? `${baseDescription} ${HITL_SOLO_CONSTRAINT_SENTENCE}` : entry.humanApproval !== void 0 ? HITL_SOLO_CONSTRAINT_SENTENCE : baseDescription;
|
|
6413
6626
|
toolSet[entry.config.name] = {
|
|
6414
|
-
description
|
|
6627
|
+
description,
|
|
6415
6628
|
inputSchema: jsonSchema(schemaRecord)
|
|
6416
6629
|
};
|
|
6417
6630
|
}
|
|
@@ -6579,7 +6792,11 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
6579
6792
|
});
|
|
6580
6793
|
try {
|
|
6581
6794
|
const callOptions = this.resolveCallOptions(model, guardrails.modelInvocationOptions);
|
|
6582
|
-
const
|
|
6795
|
+
const schemaRecord = this.isZodSchema(schema) ? this.executionHelpers.createJsonSchemaRecord(schema, {
|
|
6796
|
+
schemaName: structuredOptions?.schemaName ?? "structured_output",
|
|
6797
|
+
requireObjectRoot: true
|
|
6798
|
+
}) : schema;
|
|
6799
|
+
const outputSchema = Output.object({ schema: jsonSchema(schemaRecord) });
|
|
6583
6800
|
const result = await generateText({
|
|
6584
6801
|
model: model.languageModel,
|
|
6585
6802
|
messages: [...messages],
|
|
@@ -8729,5 +8946,172 @@ const collectionDeleteNode = defineNode({
|
|
|
8729
8946
|
});
|
|
8730
8947
|
|
|
8731
8948
|
//#endregion
|
|
8732
|
-
|
|
8949
|
+
//#region src/nodes/InboxApprovalNode.types.ts
|
|
8950
|
+
function resolveSubjectField(field, item) {
|
|
8951
|
+
return typeof field === "function" ? field({ item }) : field;
|
|
8952
|
+
}
|
|
8953
|
+
/**
|
|
8954
|
+
* Auto-detecting inbox approval node.
|
|
8955
|
+
*
|
|
8956
|
+
* Uses `ctx.resolve(InboxChannelResolverToken)` to pick the right inbox channel
|
|
8957
|
+
* at runtime:
|
|
8958
|
+
* - In managed mode (PairingConfig present): routes to the control-plane inbox.
|
|
8959
|
+
* - Otherwise: routes to the local inbox.
|
|
8960
|
+
*
|
|
8961
|
+
* Authors use this node directly; no extra wiring needed per deployment mode.
|
|
8962
|
+
*/
|
|
8963
|
+
const inboxApproval = defineHumanApprovalNode({
|
|
8964
|
+
key: "inbox.approval",
|
|
8965
|
+
title: "Inbox Approval",
|
|
8966
|
+
description: "Suspend and wait for a human reviewer to approve or reject.",
|
|
8967
|
+
icon: "lucide:inbox",
|
|
8968
|
+
channel: "inbox",
|
|
8969
|
+
configSchema: object({
|
|
8970
|
+
title: custom((v) => typeof v === "string" || typeof v === "function"),
|
|
8971
|
+
body: custom((v) => typeof v === "string" || typeof v === "function"),
|
|
8972
|
+
priority: _enum([
|
|
8973
|
+
"low",
|
|
8974
|
+
"normal",
|
|
8975
|
+
"high"
|
|
8976
|
+
]).default("normal"),
|
|
8977
|
+
timeout: string().default("24h"),
|
|
8978
|
+
onTimeout: _enum(["halt", "auto-accept"]).default("halt")
|
|
8979
|
+
}),
|
|
8980
|
+
decisionSchema: object({
|
|
8981
|
+
approved: boolean(),
|
|
8982
|
+
note: string().optional()
|
|
8983
|
+
}),
|
|
8984
|
+
defaultTimeout: "24h",
|
|
8985
|
+
defaultOnTimeout: "halt",
|
|
8986
|
+
async deliver({ task, config: config$1, item }, ctx) {
|
|
8987
|
+
const resolver = ctx.resolve(InboxChannelResolverToken);
|
|
8988
|
+
if (!resolver) throw new Error("inboxApproval: no InboxChannelResolver registered. Ensure the host DI container is wired.");
|
|
8989
|
+
const { channel, workspaceId } = resolver.resolve();
|
|
8990
|
+
const subject = {
|
|
8991
|
+
title: resolveSubjectField(config$1.title, item),
|
|
8992
|
+
summary: resolveSubjectField(config$1.body, item),
|
|
8993
|
+
attributes: {
|
|
8994
|
+
workflowId: ctx.workflowId,
|
|
8995
|
+
item: item.json
|
|
8996
|
+
}
|
|
8997
|
+
};
|
|
8998
|
+
const delivery = await channel.deliver({
|
|
8999
|
+
task,
|
|
9000
|
+
subject,
|
|
9001
|
+
priority: config$1.priority,
|
|
9002
|
+
item,
|
|
9003
|
+
workspaceId
|
|
9004
|
+
});
|
|
9005
|
+
ctx.telemetry.addSpanEvent({
|
|
9006
|
+
name: "hitl.task.delivered",
|
|
9007
|
+
attributes: {
|
|
9008
|
+
taskId: task.taskId,
|
|
9009
|
+
channel: channel.kind
|
|
9010
|
+
}
|
|
9011
|
+
});
|
|
9012
|
+
return delivery;
|
|
9013
|
+
},
|
|
9014
|
+
async onDecision({ decision, actor, delivery }, ctx) {
|
|
9015
|
+
const resolver = ctx.resolve(InboxChannelResolverToken);
|
|
9016
|
+
if (!resolver) return;
|
|
9017
|
+
const { channel } = resolver.resolve();
|
|
9018
|
+
await channel.updateOnDecision?.({
|
|
9019
|
+
delivery,
|
|
9020
|
+
decision,
|
|
9021
|
+
actor
|
|
9022
|
+
});
|
|
9023
|
+
},
|
|
9024
|
+
async onTimeout({ delivery, policy }, ctx) {
|
|
9025
|
+
const resolver = ctx.resolve(InboxChannelResolverToken);
|
|
9026
|
+
if (!resolver) return;
|
|
9027
|
+
const { channel } = resolver.resolve();
|
|
9028
|
+
await channel.updateOnTimeout?.({
|
|
9029
|
+
delivery,
|
|
9030
|
+
policy
|
|
9031
|
+
});
|
|
9032
|
+
}
|
|
9033
|
+
});
|
|
9034
|
+
|
|
9035
|
+
//#endregion
|
|
9036
|
+
//#region src/nodes/codemationDocumentScannerNode.ts
|
|
9037
|
+
const ANALYZER_TYPES = [
|
|
9038
|
+
"document",
|
|
9039
|
+
"invoice",
|
|
9040
|
+
"image",
|
|
9041
|
+
"auto"
|
|
9042
|
+
];
|
|
9043
|
+
const codemationDocumentScannerNode = defineNode({
|
|
9044
|
+
key: "codemation.document-scanner",
|
|
9045
|
+
title: "Codemation Document Scanner",
|
|
9046
|
+
description: "Analyzes a binary attachment (document or image) via the managed Codemation document-scanning service and returns markdown text plus structured fields. No Azure credential required — auth uses the workspace pairing secret. Enable includeConfidence to get per-field confidence scores (0–1).",
|
|
9047
|
+
icon: "lucide:scan-text",
|
|
9048
|
+
input: {
|
|
9049
|
+
binaryField: "data",
|
|
9050
|
+
analyzerType: "auto",
|
|
9051
|
+
contentType: void 0,
|
|
9052
|
+
includeConfidence: false,
|
|
9053
|
+
maxBytes: void 0
|
|
9054
|
+
},
|
|
9055
|
+
configSchema: object({
|
|
9056
|
+
binaryField: string().optional(),
|
|
9057
|
+
analyzerType: _enum(ANALYZER_TYPES).optional(),
|
|
9058
|
+
contentType: string().optional(),
|
|
9059
|
+
includeConfidence: boolean().optional(),
|
|
9060
|
+
maxBytes: number().int().positive().optional()
|
|
9061
|
+
}),
|
|
9062
|
+
inspectorSummary({ config: config$1 }) {
|
|
9063
|
+
const cfg = config$1;
|
|
9064
|
+
const rows = [{
|
|
9065
|
+
label: "Analyzer type",
|
|
9066
|
+
value: cfg.analyzerType ?? "auto"
|
|
9067
|
+
}];
|
|
9068
|
+
const binaryField = cfg.binaryField ?? "data";
|
|
9069
|
+
if (binaryField !== "data") rows.push({
|
|
9070
|
+
label: "Binary field",
|
|
9071
|
+
value: binaryField
|
|
9072
|
+
});
|
|
9073
|
+
if (cfg.includeConfidence) rows.push({
|
|
9074
|
+
label: "Confidence",
|
|
9075
|
+
value: "enabled"
|
|
9076
|
+
});
|
|
9077
|
+
if (cfg.contentType) rows.push({
|
|
9078
|
+
label: "Content type",
|
|
9079
|
+
value: cfg.contentType
|
|
9080
|
+
});
|
|
9081
|
+
return rows;
|
|
9082
|
+
},
|
|
9083
|
+
async execute({ item, ctx }, { config: rawConfig }) {
|
|
9084
|
+
const config$1 = rawConfig;
|
|
9085
|
+
const gatewayUrl = process.env["DOC_SCANNER_GATEWAY_URL"];
|
|
9086
|
+
if (!gatewayUrl) throw new Error("Codemation Document Scanner not available in this environment (DOC_SCANNER_GATEWAY_URL is not set).");
|
|
9087
|
+
const workspaceId = process.env["WORKSPACE_ID"];
|
|
9088
|
+
const pairingSecret = process.env["WORKSPACE_PAIRING_SECRET"];
|
|
9089
|
+
if (!workspaceId || !pairingSecret) throw new Error("Codemation Document Scanner not available (workspace pairing is not configured).");
|
|
9090
|
+
const binaryField = config$1.binaryField ?? "data";
|
|
9091
|
+
const attachment = item.binary?.[binaryField];
|
|
9092
|
+
if (!attachment) throw new Error(`Codemation Document Scanner: no binary attachment at key "${binaryField}".`);
|
|
9093
|
+
const body = await ctx.binary.getBytes(attachment, config$1.maxBytes);
|
|
9094
|
+
const contentType = config$1.contentType ?? attachment.mimeType ?? "application/octet-stream";
|
|
9095
|
+
const analyzerType = config$1.analyzerType ?? "auto";
|
|
9096
|
+
const confidenceSuffix = config$1.includeConfidence ?? false ? "&confidence=true" : "";
|
|
9097
|
+
const url = `${gatewayUrl}/analyze?type=${encodeURIComponent(analyzerType)}${confidenceSuffix}`;
|
|
9098
|
+
const response = await managedHmacFetchFactory(workspaceId, pairingSecret, { signBody: false })(url, {
|
|
9099
|
+
method: "POST",
|
|
9100
|
+
body: body.buffer,
|
|
9101
|
+
headers: {
|
|
9102
|
+
"Content-Type": contentType,
|
|
9103
|
+
"Content-Length": String(body.byteLength),
|
|
9104
|
+
"X-Codemation-Caller": "workflow-node"
|
|
9105
|
+
}
|
|
9106
|
+
});
|
|
9107
|
+
if (!response.ok) {
|
|
9108
|
+
const text = await response.text().catch(() => "(unreadable)");
|
|
9109
|
+
throw new Error(`Codemation Document Scanner: service responded ${response.status} ${response.statusText} — ${text}`);
|
|
9110
|
+
}
|
|
9111
|
+
return await response.json();
|
|
9112
|
+
}
|
|
9113
|
+
});
|
|
9114
|
+
|
|
9115
|
+
//#endregion
|
|
9116
|
+
export { AIAgent, AIAgentConnectionWorkflowExpander, AIAgentExecutionHelpersFactory, AIAgentNode, AgentItemPortMap, AgentMessageFactory, AgentOutputFactory, AgentStructuredOutputRepairPromptFactory, AgentStructuredOutputRunner, AgentToolCallPortMap, AgentToolErrorClassifier, AgentToolExecutionCoordinator, AgentToolRepairExhaustedError, AgentToolRepairPolicy, Aggregate, AggregateNode, Assertion, AssertionNode, BM25Index, Callback, CallbackNode, CallbackResultNormalizer, CodemationChatModelConfig, CodemationChatModelFactory, ConnectionCredentialExecutionContextFactory, ConnectionCredentialNode, ConnectionCredentialNodeConfig, ConnectionCredentialNodeConfigFactory, CronTrigger, CronTriggerNode, DeferredMetaToolStrategy, DeferredMetaToolStrategyFactory, Filter, FilterNode, HTTP_REQUEST_ACCEPTED_CREDENTIAL_TYPES, HttpRequest, HttpRequestNode, If, IfNode, IsTestRun, IsTestRunNode, ManagedModelFetcher, ManualTrigger, ManualTriggerNode, MapData, MapDataNode, Merge, MergeNode, NoOp, NoOpNode, OpenAIChatModelConfig, OpenAIChatModelFactory, OpenAiChatModelPresets, OpenAiStrictJsonSchemaFactory, SSRFBlockedError, Split, SplitNode, SsrfGuard, SubWorkflow, SubWorkflowNode, Switch, SwitchNode, TestTrigger, TestTriggerNode, Wait, WaitDuration, WaitNode, WebhookRespondNowAndContinueError, WebhookRespondNowError, WebhookTrigger, WebhookTriggerNode, WorkflowAuthoringBuilder, WorkflowBranchBuilder, WorkflowChain, apiKeyCredentialType, basicAuthCredentialType, bearerTokenCredentialType, codemationDocumentScannerNode, collectionDeleteNode, collectionFindOneNode, collectionGetNode, collectionInsertNode, collectionListNode, collectionUpdateNode, createWorkflowBuilder, defineRestNode, inboxApproval, oauth2ClientCredentialsType, openAiChatModelPresets, registerCoreNodes, workflow };
|
|
8733
9117
|
//# sourceMappingURL=index.js.map
|