@codemation/core-nodes-ocr 0.2.2 → 0.2.3
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 +7 -0
- package/dist/codemation.plugin.cjs +252 -7
- package/dist/codemation.plugin.cjs.map +1 -1
- package/dist/codemation.plugin.d.cts +1 -1
- package/dist/codemation.plugin.d.ts +1 -1
- package/dist/codemation.plugin.js +253 -8
- package/dist/codemation.plugin.js.map +1 -1
- package/dist/{index-C2KJPzqN.d.ts → index-rc7dB1Ws.d.ts} +353 -281
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/metadata.json +1 -1
- package/dist/{runtimeTypes-ffl603pJ.d.cts → runtimeTypes-MQgcsey7.d.cts} +265 -193
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as Container, l as TypeToken, s as WorkflowDefinition, u as AnyCredentialType } from "./runtimeTypes-MQgcsey7.cjs";
|
|
2
2
|
import { BetterAuthOptions } from "better-auth";
|
|
3
3
|
|
|
4
4
|
//#region ../core/src/contracts/mcpTypes.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as TypeToken, c as
|
|
1
|
+
import { a as TypeToken, c as McpServerDeclaration, i as Container, l as AnyCredentialType, n as DefinedCollection, o as EngineExecutionLimitsPolicyConfig, r as WorkflowDefinition, t as CollectionDefinition } from "./index-rc7dB1Ws.js";
|
|
2
2
|
import { ZodType, z } from "zod";
|
|
3
3
|
import { BetterAuthOptions } from "better-auth";
|
|
4
4
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as __toDynamicImportESM, i as __commonJS, n as require_auth_errors, o as __toESM, r as require_token_error, t as require_token_util } from "./token-util-EUxa8JtH.js";
|
|
2
2
|
import { n as analyzeImageNode, o as azureContentUnderstandingCredentialType, r as analyzeDocumentNode, t as analyzeInvoiceNode } from "./analyzeInvoiceNode-uVwe3GHD.js";
|
|
3
|
-
import { AgentConfigInspector, AgentGuardrailDefaults, AgentMessageConfigNormalizer, CallableToolConfig, ChildExecutionScopeFactory, CodemationTelemetryAttributeNames, CodemationTelemetryMetricNames, ConnectionInvocationIdFactory, ConnectionNodeIdFactory, CoreTokens, GenAiTelemetryAttributeNames, ItemExprResolver, ItemsInputNormalizer, NodeBackedToolConfig, NodeOutputNormalizer, RunnableOutputBehaviorResolver, chatModel, defineCredential, defineNode, emitPorts, getOriginIndexFromItem, inject, injectable, isPortsEmission, node } from "@codemation/core";
|
|
3
|
+
import { AgentConfigInspector, AgentGuardrailDefaults, AgentMessageConfigNormalizer, CallableToolConfig, ChildExecutionScopeFactory, CodemationTelemetryAttributeNames, CodemationTelemetryMetricNames, ConnectionInvocationIdFactory, ConnectionNodeIdFactory, CoreTokens, GenAiTelemetryAttributeNames, InboxChannelResolverToken, ItemExprResolver, ItemsInputNormalizer, NodeBackedToolConfig, NodeOutputNormalizer, RunnableOutputBehaviorResolver, SuspensionRequest, chatModel, defineCredential, defineHumanApprovalNode, defineNode, emitPorts, getOriginIndexFromItem, inject, injectable, isPortsEmission, node } from "@codemation/core";
|
|
4
4
|
import dns from "node:dns/promises";
|
|
5
5
|
import * as z4 from "zod/v4";
|
|
6
6
|
import { z } from "zod/v4";
|
|
@@ -8730,12 +8730,22 @@ let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
|
|
|
8730
8730
|
this.repairPolicy = repairPolicy;
|
|
8731
8731
|
}
|
|
8732
8732
|
async execute(args) {
|
|
8733
|
+
if (args.plannedToolCalls.filter((c) => c.binding.humanApproval !== void 0).length > 0 && args.plannedToolCalls.length > 1) return args.plannedToolCalls.map((c) => ({
|
|
8734
|
+
toolName: c.binding.config.name,
|
|
8735
|
+
toolCallId: c.toolCall.id ?? c.binding.config.name,
|
|
8736
|
+
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.` },
|
|
8737
|
+
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.` })
|
|
8738
|
+
}));
|
|
8733
8739
|
const results = await Promise.allSettled(args.plannedToolCalls.map(async (plannedToolCall) => await this.executePlannedToolCall({
|
|
8734
8740
|
...args,
|
|
8735
8741
|
plannedToolCall
|
|
8736
8742
|
})));
|
|
8737
8743
|
const rejected = results.find((result) => result.status === "rejected");
|
|
8738
|
-
if (rejected?.status === "rejected")
|
|
8744
|
+
if (rejected?.status === "rejected") {
|
|
8745
|
+
const reason = rejected.reason;
|
|
8746
|
+
if (reason instanceof SuspensionRequest) throw reason;
|
|
8747
|
+
throw reason instanceof Error ? reason : new Error(String(reason));
|
|
8748
|
+
}
|
|
8739
8749
|
return results.filter((result) => result.status === "fulfilled").map((result) => result.value);
|
|
8740
8750
|
}
|
|
8741
8751
|
async executePlannedToolCall(args) {
|
|
@@ -8820,6 +8830,34 @@ let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
|
|
|
8820
8830
|
result
|
|
8821
8831
|
};
|
|
8822
8832
|
} catch (error) {
|
|
8833
|
+
if (error instanceof SuspensionRequest) {
|
|
8834
|
+
const pendingToolCallId = plannedToolCall.toolCall.id ?? plannedToolCall.binding.config.name;
|
|
8835
|
+
const checkpoint = {
|
|
8836
|
+
conversation: args.conversationSnapshot ? [...args.conversationSnapshot] : [],
|
|
8837
|
+
turnCount: args.turnCount ?? 0,
|
|
8838
|
+
toolCallCount: args.toolCallCount ?? 0,
|
|
8839
|
+
pendingToolCallId,
|
|
8840
|
+
agentName: args.agentName,
|
|
8841
|
+
modelId: args.modelId ?? ""
|
|
8842
|
+
};
|
|
8843
|
+
const agentReasoning = this.extractLastAssistantText(args.conversationSnapshot ?? []);
|
|
8844
|
+
const augmented = new SuspensionRequest({
|
|
8845
|
+
...error.request,
|
|
8846
|
+
metadata: {
|
|
8847
|
+
...error.request.metadata,
|
|
8848
|
+
agentCheckpoint: checkpoint,
|
|
8849
|
+
pendingToolCallId,
|
|
8850
|
+
agentReasoning,
|
|
8851
|
+
onRejected: plannedToolCall.binding.humanApproval?.onRejected ?? "return"
|
|
8852
|
+
}
|
|
8853
|
+
});
|
|
8854
|
+
await span.end({
|
|
8855
|
+
status: "error",
|
|
8856
|
+
statusMessage: "suspended",
|
|
8857
|
+
endedAt: /* @__PURE__ */ new Date()
|
|
8858
|
+
});
|
|
8859
|
+
throw augmented;
|
|
8860
|
+
}
|
|
8823
8861
|
const classification = this.errorClassifier.classify({
|
|
8824
8862
|
error,
|
|
8825
8863
|
toolName: plannedToolCall.binding.config.name,
|
|
@@ -8995,6 +9033,24 @@ let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
|
|
|
8995
9033
|
extractErrorDetails(error) {
|
|
8996
9034
|
return error.details;
|
|
8997
9035
|
}
|
|
9036
|
+
/**
|
|
9037
|
+
* Extracts the text content from the last assistant message in the conversation snapshot.
|
|
9038
|
+
* Used to populate `agentReasoning` in the HITL suspension metadata.
|
|
9039
|
+
*/
|
|
9040
|
+
extractLastAssistantText(conversation) {
|
|
9041
|
+
for (let i = conversation.length - 1; i >= 0; i--) {
|
|
9042
|
+
const msg = conversation[i];
|
|
9043
|
+
if (msg?.role !== "assistant") continue;
|
|
9044
|
+
const content = msg.content;
|
|
9045
|
+
if (typeof content === "string") return content;
|
|
9046
|
+
if (Array.isArray(content)) {
|
|
9047
|
+
const textParts = content.filter((part) => typeof part === "object" && part.type === "text").map((part) => part.text);
|
|
9048
|
+
if (textParts.length > 0) return textParts.join("");
|
|
9049
|
+
}
|
|
9050
|
+
break;
|
|
9051
|
+
}
|
|
9052
|
+
return "";
|
|
9053
|
+
}
|
|
8998
9054
|
serializeIssue(issue) {
|
|
8999
9055
|
const result = {
|
|
9000
9056
|
path: [...issue.path],
|
|
@@ -15325,6 +15381,7 @@ var AgentItemPortMap = class {
|
|
|
15325
15381
|
//#endregion
|
|
15326
15382
|
//#region ../core-nodes/src/nodes/AIAgentNode.ts
|
|
15327
15383
|
var _ref, _ref2, _ref3, _ref4, _ref5;
|
|
15384
|
+
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.";
|
|
15328
15385
|
let AIAgentNode = class AIAgentNode$1 {
|
|
15329
15386
|
kind = "node";
|
|
15330
15387
|
outputPorts = ["main"];
|
|
@@ -15342,13 +15399,90 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
15342
15399
|
this.connectionCredentialExecutionContextFactory = this.executionHelpers.createConnectionCredentialExecutionContextFactory(credentialSessions);
|
|
15343
15400
|
}
|
|
15344
15401
|
async execute(args) {
|
|
15345
|
-
const
|
|
15402
|
+
const { ctx } = args;
|
|
15403
|
+
if (ctx.resumeContext) return this.executeResumed(args, ctx.resumeContext);
|
|
15404
|
+
const prepared = await this.getOrPrepareExecution(ctx);
|
|
15346
15405
|
const itemWithMappedJson = {
|
|
15347
15406
|
...args.item,
|
|
15348
15407
|
json: args.input
|
|
15349
15408
|
};
|
|
15350
15409
|
return (await this.runAgentForItem(prepared, itemWithMappedJson, args.itemIndex, args.items)).json;
|
|
15351
15410
|
}
|
|
15411
|
+
/**
|
|
15412
|
+
* Resume path: re-enters the agent loop after a HITL suspension.
|
|
15413
|
+
* Reconstructs the conversation from the checkpoint, injects the human decision
|
|
15414
|
+
* as a tool_result, and continues the loop from where it suspended.
|
|
15415
|
+
*/
|
|
15416
|
+
async executeResumed(args, resumeContext) {
|
|
15417
|
+
const { ctx } = args;
|
|
15418
|
+
const taskMetadata = resumeContext.task.metadata ?? {};
|
|
15419
|
+
const checkpoint = taskMetadata["agentCheckpoint"];
|
|
15420
|
+
const onRejected = taskMetadata["onRejected"] ?? "return";
|
|
15421
|
+
if (!checkpoint) {
|
|
15422
|
+
const prepared$1 = await this.getOrPrepareExecution(ctx);
|
|
15423
|
+
const itemWithMappedJson = {
|
|
15424
|
+
...args.item,
|
|
15425
|
+
json: args.input
|
|
15426
|
+
};
|
|
15427
|
+
return (await this.runAgentForItem(prepared$1, itemWithMappedJson, args.itemIndex, args.items)).json;
|
|
15428
|
+
}
|
|
15429
|
+
if (resumeContext.decision.kind === "decided" && resumeContext.decision.value === null && onRejected === "halt") return;
|
|
15430
|
+
const decision = this.normalizeDecision(resumeContext);
|
|
15431
|
+
if (decision.status === "rejected" && onRejected === "halt") return;
|
|
15432
|
+
const prepared = await this.getOrPrepareExecution(ctx);
|
|
15433
|
+
const item = args.item;
|
|
15434
|
+
const itemInputsByPort = AgentItemPortMap.fromItem(item);
|
|
15435
|
+
const itemScopedTools = this.createItemScopedTools(prepared.resolvedTools, ctx, item, args.itemIndex, args.items);
|
|
15436
|
+
const toolResultEntry = {
|
|
15437
|
+
toolName: checkpoint.pendingToolCallId,
|
|
15438
|
+
toolCallId: checkpoint.pendingToolCallId,
|
|
15439
|
+
result: decision,
|
|
15440
|
+
serialized: JSON.stringify(decision)
|
|
15441
|
+
};
|
|
15442
|
+
const conversation = [...checkpoint.conversation, AgentMessageFactory.createToolResultsMessage([toolResultEntry])];
|
|
15443
|
+
const loopResult = await this.runTurnLoopUntilFinalAnswer({
|
|
15444
|
+
prepared,
|
|
15445
|
+
itemInputsByPort,
|
|
15446
|
+
itemScopedTools,
|
|
15447
|
+
conversation,
|
|
15448
|
+
resumedTurnCount: checkpoint.turnCount,
|
|
15449
|
+
resumedToolCallCount: checkpoint.toolCallCount
|
|
15450
|
+
});
|
|
15451
|
+
await ctx.telemetry.recordMetric({
|
|
15452
|
+
name: CodemationTelemetryMetricNames.agentTurns,
|
|
15453
|
+
value: loopResult.turnCount
|
|
15454
|
+
});
|
|
15455
|
+
await ctx.telemetry.recordMetric({
|
|
15456
|
+
name: CodemationTelemetryMetricNames.agentToolCalls,
|
|
15457
|
+
value: loopResult.toolCallCount
|
|
15458
|
+
});
|
|
15459
|
+
const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, loopResult.finalText, itemScopedTools.length > 0);
|
|
15460
|
+
return this.buildOutputItem(item, outputJson).json;
|
|
15461
|
+
}
|
|
15462
|
+
/**
|
|
15463
|
+
* Normalizes a {@link ResumeContext} decision into a flat JSON-serializable shape
|
|
15464
|
+
* suitable for injection as a tool_result content.
|
|
15465
|
+
*/
|
|
15466
|
+
normalizeDecision(resumeContext) {
|
|
15467
|
+
const { decision } = resumeContext;
|
|
15468
|
+
if (decision.kind === "decided") {
|
|
15469
|
+
const value = decision.value;
|
|
15470
|
+
return {
|
|
15471
|
+
status: (typeof value === "object" && value !== null && "approved" in value ? Boolean(value["approved"]) : true) ? "approved" : "rejected",
|
|
15472
|
+
value: decision.value,
|
|
15473
|
+
actor: decision.actor,
|
|
15474
|
+
decidedAt: decision.decidedAt.toISOString()
|
|
15475
|
+
};
|
|
15476
|
+
}
|
|
15477
|
+
if (decision.kind === "timed_out") return {
|
|
15478
|
+
status: "timed_out",
|
|
15479
|
+
at: decision.at.toISOString()
|
|
15480
|
+
};
|
|
15481
|
+
return {
|
|
15482
|
+
status: "auto_accepted",
|
|
15483
|
+
at: decision.at.toISOString()
|
|
15484
|
+
};
|
|
15485
|
+
}
|
|
15352
15486
|
async getOrPrepareExecution(ctx) {
|
|
15353
15487
|
let pending = this.preparedByExecutionContext.get(ctx);
|
|
15354
15488
|
if (!pending) {
|
|
@@ -15469,7 +15603,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
15469
15603
|
const { prepared, itemInputsByPort, itemScopedTools, conversation } = args;
|
|
15470
15604
|
const { ctx, guardrails, toolLoadingStrategy } = prepared;
|
|
15471
15605
|
let finalText = "";
|
|
15472
|
-
let toolCallCount = 0;
|
|
15606
|
+
let toolCallCount = args.resumedToolCallCount ?? 0;
|
|
15473
15607
|
let turnCount = 0;
|
|
15474
15608
|
const repairAttemptsByToolName = /* @__PURE__ */ new Map();
|
|
15475
15609
|
/** Tool IDs surfaced by find_tools across all prior turns in this item run. */
|
|
@@ -15510,11 +15644,17 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
15510
15644
|
const plannedToolCalls = this.planToolCalls(itemScopedTools, coordinatorCalls, ctx.nodeId);
|
|
15511
15645
|
toolCallCount += plannedToolCalls.length;
|
|
15512
15646
|
await this.markQueuedTools(plannedToolCalls, ctx);
|
|
15647
|
+
const assistantMsg = result.assistantMessage ?? AgentMessageFactory.createAssistantWithToolCalls(result.text, result.toolCalls);
|
|
15648
|
+
const conversationWithAssistant = [...conversation, assistantMsg];
|
|
15513
15649
|
const executed = await this.toolExecutionCoordinator.execute({
|
|
15514
15650
|
plannedToolCalls,
|
|
15515
15651
|
ctx,
|
|
15516
15652
|
agentName: this.getAgentDisplayName(ctx),
|
|
15517
|
-
repairAttemptsByToolName
|
|
15653
|
+
repairAttemptsByToolName,
|
|
15654
|
+
conversationSnapshot: conversationWithAssistant,
|
|
15655
|
+
turnCount,
|
|
15656
|
+
toolCallCount,
|
|
15657
|
+
modelId: this.resolveChatModelName(ctx.config.chatModel)
|
|
15518
15658
|
});
|
|
15519
15659
|
coordinatorExecutedCalls.push(...executed);
|
|
15520
15660
|
}
|
|
@@ -15576,6 +15716,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
15576
15716
|
connectionNodeId: ConnectionNodeIdFactory.toolConnectionNodeId(ctx.nodeId, entry.config.name),
|
|
15577
15717
|
getCredentialRequirements: () => entry.config.getCredentialRequirements?.() ?? []
|
|
15578
15718
|
});
|
|
15719
|
+
const hitlBehavior = this.resolveHumanApprovalBehavior(entry.config);
|
|
15579
15720
|
return {
|
|
15580
15721
|
config: entry.config,
|
|
15581
15722
|
inputSchema: entry.runtime.inputSchema,
|
|
@@ -15590,11 +15731,22 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
15590
15731
|
items,
|
|
15591
15732
|
hooks
|
|
15592
15733
|
});
|
|
15593
|
-
}
|
|
15734
|
+
},
|
|
15735
|
+
...hitlBehavior !== void 0 ? { humanApproval: hitlBehavior } : {}
|
|
15594
15736
|
};
|
|
15595
15737
|
});
|
|
15596
15738
|
}
|
|
15597
15739
|
/**
|
|
15740
|
+
* Detects whether a tool config is backed by a `defineHumanApprovalNode` marker
|
|
15741
|
+
* and returns the HITL behavior config, or `undefined` when not a HITL tool.
|
|
15742
|
+
*/
|
|
15743
|
+
resolveHumanApprovalBehavior(config) {
|
|
15744
|
+
if (!this.isNodeBackedToolConfig(config)) return void 0;
|
|
15745
|
+
const marker$3 = config.node.humanApprovalToolBehavior;
|
|
15746
|
+
if (marker$3 === void 0) return void 0;
|
|
15747
|
+
return { onRejected: marker$3.onRejected ?? "return" };
|
|
15748
|
+
}
|
|
15749
|
+
/**
|
|
15598
15750
|
* Invoke a text turn using the merged tool set from item-scoped tools (coordinator-managed)
|
|
15599
15751
|
* and strategy tools (find_tools + discovered MCP tools).
|
|
15600
15752
|
* Strategy tools take precedence for names that overlap.
|
|
@@ -15624,6 +15776,8 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
15624
15776
|
/**
|
|
15625
15777
|
* Builds a ToolSet from resolved tools for strategy initialization.
|
|
15626
15778
|
* The strategy uses this for its "always-included" node-backed tool descriptions.
|
|
15779
|
+
* HITL tools (detected via the `humanApprovalToolBehavior` field set by `defineHumanApprovalNode`) get the solo-constraint sentence
|
|
15780
|
+
* appended to their description.
|
|
15627
15781
|
*/
|
|
15628
15782
|
buildToolSetFromResolved(resolvedTools) {
|
|
15629
15783
|
if (resolvedTools.length === 0) return {};
|
|
@@ -15633,8 +15787,10 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
15633
15787
|
schemaName: entry.config.name,
|
|
15634
15788
|
requireObjectRoot: true
|
|
15635
15789
|
});
|
|
15790
|
+
const baseDescription = entry.config.description ?? entry.runtime.defaultDescription;
|
|
15791
|
+
const description = this.resolveHumanApprovalBehavior(entry.config) !== void 0 ? `${baseDescription} ${HITL_SOLO_CONSTRAINT_SENTENCE}` : baseDescription;
|
|
15636
15792
|
toolSet[entry.config.name] = {
|
|
15637
|
-
description
|
|
15793
|
+
description,
|
|
15638
15794
|
inputSchema: jsonSchema(schemaRecord)
|
|
15639
15795
|
};
|
|
15640
15796
|
}
|
|
@@ -15662,8 +15818,10 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
15662
15818
|
schemaName: entry.config.name,
|
|
15663
15819
|
requireObjectRoot: true
|
|
15664
15820
|
});
|
|
15821
|
+
const baseDescription = entry.config.description;
|
|
15822
|
+
const description = entry.humanApproval !== void 0 && baseDescription !== void 0 ? `${baseDescription} ${HITL_SOLO_CONSTRAINT_SENTENCE}` : entry.humanApproval !== void 0 ? HITL_SOLO_CONSTRAINT_SENTENCE : baseDescription;
|
|
15665
15823
|
toolSet[entry.config.name] = {
|
|
15666
|
-
description
|
|
15824
|
+
description,
|
|
15667
15825
|
inputSchema: jsonSchema(schemaRecord)
|
|
15668
15826
|
};
|
|
15669
15827
|
}
|
|
@@ -17755,6 +17913,93 @@ const collectionDeleteNode = defineNode({
|
|
|
17755
17913
|
}
|
|
17756
17914
|
});
|
|
17757
17915
|
|
|
17916
|
+
//#endregion
|
|
17917
|
+
//#region ../core-nodes/src/nodes/InboxApprovalNode.types.ts
|
|
17918
|
+
function resolveSubjectField(field, item) {
|
|
17919
|
+
return typeof field === "function" ? field({ item }) : field;
|
|
17920
|
+
}
|
|
17921
|
+
/**
|
|
17922
|
+
* Auto-detecting inbox approval node.
|
|
17923
|
+
*
|
|
17924
|
+
* Uses `ctx.resolve(InboxChannelResolverToken)` to pick the right inbox channel
|
|
17925
|
+
* at runtime:
|
|
17926
|
+
* - In managed mode (PairingConfig present): routes to the control-plane inbox.
|
|
17927
|
+
* - Otherwise: routes to the local inbox.
|
|
17928
|
+
*
|
|
17929
|
+
* Authors use this node directly; no extra wiring needed per deployment mode.
|
|
17930
|
+
*/
|
|
17931
|
+
const inboxApproval = defineHumanApprovalNode({
|
|
17932
|
+
key: "inbox.approval",
|
|
17933
|
+
title: "Inbox Approval",
|
|
17934
|
+
description: "Suspend and wait for a human reviewer to approve or reject.",
|
|
17935
|
+
icon: "lucide:inbox",
|
|
17936
|
+
channel: "inbox",
|
|
17937
|
+
configSchema: z$1.object({
|
|
17938
|
+
title: z$1.custom((v$1) => typeof v$1 === "string" || typeof v$1 === "function"),
|
|
17939
|
+
body: z$1.custom((v$1) => typeof v$1 === "string" || typeof v$1 === "function"),
|
|
17940
|
+
priority: z$1.enum([
|
|
17941
|
+
"low",
|
|
17942
|
+
"normal",
|
|
17943
|
+
"high"
|
|
17944
|
+
]).default("normal"),
|
|
17945
|
+
timeout: z$1.string().default("24h"),
|
|
17946
|
+
onTimeout: z$1.enum(["halt", "auto-accept"]).default("halt")
|
|
17947
|
+
}),
|
|
17948
|
+
decisionSchema: z$1.object({
|
|
17949
|
+
approved: z$1.boolean(),
|
|
17950
|
+
note: z$1.string().optional()
|
|
17951
|
+
}),
|
|
17952
|
+
defaultTimeout: "24h",
|
|
17953
|
+
defaultOnTimeout: "halt",
|
|
17954
|
+
async deliver({ task, config, item }, ctx) {
|
|
17955
|
+
const resolver = ctx.resolve(InboxChannelResolverToken);
|
|
17956
|
+
if (!resolver) throw new Error("inboxApproval: no InboxChannelResolver registered. Ensure the host DI container is wired.");
|
|
17957
|
+
const { channel, workspaceId } = resolver.resolve();
|
|
17958
|
+
const subject = {
|
|
17959
|
+
title: resolveSubjectField(config.title, item),
|
|
17960
|
+
summary: resolveSubjectField(config.body, item),
|
|
17961
|
+
attributes: {
|
|
17962
|
+
workflowId: ctx.workflowId,
|
|
17963
|
+
item: item.json
|
|
17964
|
+
}
|
|
17965
|
+
};
|
|
17966
|
+
const delivery = await channel.deliver({
|
|
17967
|
+
task,
|
|
17968
|
+
subject,
|
|
17969
|
+
priority: config.priority,
|
|
17970
|
+
item,
|
|
17971
|
+
workspaceId
|
|
17972
|
+
});
|
|
17973
|
+
ctx.telemetry.addSpanEvent({
|
|
17974
|
+
name: "hitl.task.delivered",
|
|
17975
|
+
attributes: {
|
|
17976
|
+
taskId: task.taskId,
|
|
17977
|
+
channel: channel.kind
|
|
17978
|
+
}
|
|
17979
|
+
});
|
|
17980
|
+
return delivery;
|
|
17981
|
+
},
|
|
17982
|
+
async onDecision({ decision, actor, delivery }, ctx) {
|
|
17983
|
+
const resolver = ctx.resolve(InboxChannelResolverToken);
|
|
17984
|
+
if (!resolver) return;
|
|
17985
|
+
const { channel } = resolver.resolve();
|
|
17986
|
+
await channel.updateOnDecision?.({
|
|
17987
|
+
delivery,
|
|
17988
|
+
decision,
|
|
17989
|
+
actor
|
|
17990
|
+
});
|
|
17991
|
+
},
|
|
17992
|
+
async onTimeout({ delivery, policy }, ctx) {
|
|
17993
|
+
const resolver = ctx.resolve(InboxChannelResolverToken);
|
|
17994
|
+
if (!resolver) return;
|
|
17995
|
+
const { channel } = resolver.resolve();
|
|
17996
|
+
await channel.updateOnTimeout?.({
|
|
17997
|
+
delivery,
|
|
17998
|
+
policy
|
|
17999
|
+
});
|
|
18000
|
+
}
|
|
18001
|
+
});
|
|
18002
|
+
|
|
17758
18003
|
//#endregion
|
|
17759
18004
|
//#region ../host/src/presentation/config/CodemationAuthoring.types.ts
|
|
17760
18005
|
var CodemationAuthoringConfigFactory = class {
|