@codemation/core-nodes 0.4.0 → 0.4.2
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 +24 -0
- package/dist/index.cjs +667 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +196 -5
- package/dist/index.d.ts +196 -5
- package/dist/index.js +650 -87
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/chatModels/openAiChatModelConfig.ts +3 -0
- package/src/nodes/AIAgentNode.ts +294 -102
- package/src/nodes/AgentToolErrorClassifier.ts +106 -0
- package/src/nodes/AgentToolExecutionCoordinator.ts +364 -0
- package/src/nodes/AgentToolRepair.types.ts +26 -0
- package/src/nodes/AgentToolRepairExhaustedError.ts +51 -0
- package/src/nodes/AgentToolRepairPolicy.ts +21 -0
- package/src/nodes/aggregate.ts +1 -0
- package/src/nodes/aiAgent.ts +4 -0
- package/src/nodes/split.ts +1 -0
package/dist/index.cjs
CHANGED
|
@@ -101,11 +101,14 @@ OpenAIStructuredOutputMethodFactory = _OpenAIStructuredOutputMethodFactory = __d
|
|
|
101
101
|
var OpenAIChatModelConfig = class {
|
|
102
102
|
type = OpenAIChatModelFactory;
|
|
103
103
|
presentation;
|
|
104
|
+
provider = "openai";
|
|
105
|
+
modelName;
|
|
104
106
|
constructor(name, model, credentialSlotKey = "openai", presentationIn, options) {
|
|
105
107
|
this.name = name;
|
|
106
108
|
this.model = model;
|
|
107
109
|
this.credentialSlotKey = credentialSlotKey;
|
|
108
110
|
this.options = options;
|
|
111
|
+
this.modelName = model;
|
|
109
112
|
this.presentation = presentationIn ?? {
|
|
110
113
|
icon: "builtin:openai",
|
|
111
114
|
label: name
|
|
@@ -2222,7 +2225,7 @@ function __decorateParam(paramIndex, decorator) {
|
|
|
2222
2225
|
|
|
2223
2226
|
//#endregion
|
|
2224
2227
|
//#region src/nodes/AgentStructuredOutputRepairPromptFactory.ts
|
|
2225
|
-
var _ref$
|
|
2228
|
+
var _ref$4, _AgentStructuredOutputRepairPromptFactory;
|
|
2226
2229
|
let AgentStructuredOutputRepairPromptFactory = class AgentStructuredOutputRepairPromptFactory$1 {
|
|
2227
2230
|
static {
|
|
2228
2231
|
_AgentStructuredOutputRepairPromptFactory = this;
|
|
@@ -2257,7 +2260,7 @@ let AgentStructuredOutputRepairPromptFactory = class AgentStructuredOutputRepair
|
|
|
2257
2260
|
AgentStructuredOutputRepairPromptFactory = _AgentStructuredOutputRepairPromptFactory = __decorate([
|
|
2258
2261
|
(0, __codemation_core.injectable)(),
|
|
2259
2262
|
__decorateParam(0, (0, __codemation_core.inject)(AIAgentExecutionHelpersFactory)),
|
|
2260
|
-
__decorateMetadata("design:paramtypes", [typeof (_ref$
|
|
2263
|
+
__decorateMetadata("design:paramtypes", [typeof (_ref$4 = typeof AIAgentExecutionHelpersFactory !== "undefined" && AIAgentExecutionHelpersFactory) === "function" ? _ref$4 : Object])
|
|
2261
2264
|
], AgentStructuredOutputRepairPromptFactory);
|
|
2262
2265
|
|
|
2263
2266
|
//#endregion
|
|
@@ -2592,7 +2595,7 @@ const meta = meta$1;
|
|
|
2592
2595
|
|
|
2593
2596
|
//#endregion
|
|
2594
2597
|
//#region src/nodes/AgentStructuredOutputRunner.ts
|
|
2595
|
-
var _ref$
|
|
2598
|
+
var _ref$3, _ref2$3, _AgentStructuredOutputRunner;
|
|
2596
2599
|
let AgentStructuredOutputRunner = class AgentStructuredOutputRunner$1 {
|
|
2597
2600
|
static {
|
|
2598
2601
|
_AgentStructuredOutputRunner = this;
|
|
@@ -2705,7 +2708,7 @@ AgentStructuredOutputRunner = _AgentStructuredOutputRunner = __decorate([
|
|
|
2705
2708
|
(0, __codemation_core.injectable)(),
|
|
2706
2709
|
__decorateParam(0, (0, __codemation_core.inject)(AgentStructuredOutputRepairPromptFactory)),
|
|
2707
2710
|
__decorateParam(1, (0, __codemation_core.inject)(OpenAIStructuredOutputMethodFactory)),
|
|
2708
|
-
__decorateMetadata("design:paramtypes", [typeof (_ref$
|
|
2711
|
+
__decorateMetadata("design:paramtypes", [typeof (_ref$3 = typeof AgentStructuredOutputRepairPromptFactory !== "undefined" && AgentStructuredOutputRepairPromptFactory) === "function" ? _ref$3 : Object, typeof (_ref2$3 = typeof OpenAIStructuredOutputMethodFactory !== "undefined" && OpenAIStructuredOutputMethodFactory) === "function" ? _ref2$3 : Object])
|
|
2709
2712
|
], AgentStructuredOutputRunner);
|
|
2710
2713
|
|
|
2711
2714
|
//#endregion
|
|
@@ -2716,6 +2719,390 @@ var AgentToolCallPortMap = class {
|
|
|
2716
2719
|
}
|
|
2717
2720
|
};
|
|
2718
2721
|
|
|
2722
|
+
//#endregion
|
|
2723
|
+
//#region src/nodes/AgentToolErrorClassifier.ts
|
|
2724
|
+
let AgentToolErrorClassifier = class AgentToolErrorClassifier$1 {
|
|
2725
|
+
classify(args) {
|
|
2726
|
+
const effectiveError = this.toError(args.error);
|
|
2727
|
+
if (this.isRepairableValidationError(args.error, effectiveError)) return {
|
|
2728
|
+
kind: "repairable_validation_error",
|
|
2729
|
+
effectiveError,
|
|
2730
|
+
issues: this.extractIssues(args.error, effectiveError, args.toolName),
|
|
2731
|
+
requiredSchemaReminder: this.toJsonValue(args.schema)
|
|
2732
|
+
};
|
|
2733
|
+
if (this.isTransientExecutionError(effectiveError)) return {
|
|
2734
|
+
kind: "transient_execution_error",
|
|
2735
|
+
effectiveError
|
|
2736
|
+
};
|
|
2737
|
+
return {
|
|
2738
|
+
kind: "non_repairable_error",
|
|
2739
|
+
effectiveError
|
|
2740
|
+
};
|
|
2741
|
+
}
|
|
2742
|
+
isRepairableValidationError(rawError, effectiveError) {
|
|
2743
|
+
if (rawError instanceof ZodError) return rawError.codemationToolValidationStage !== "output";
|
|
2744
|
+
if (effectiveError.name === "ZodError") return true;
|
|
2745
|
+
return effectiveError.message.includes("Received tool input did not match expected schema");
|
|
2746
|
+
}
|
|
2747
|
+
extractIssues(rawError, effectiveError, toolName) {
|
|
2748
|
+
if (rawError instanceof ZodError) return rawError.issues.map((issue$1) => ({
|
|
2749
|
+
path: issue$1.path.map((segment) => typeof segment === "number" ? segment : String(segment)),
|
|
2750
|
+
code: issue$1.code,
|
|
2751
|
+
message: issue$1.message,
|
|
2752
|
+
expected: this.toOptionalString("expected" in issue$1 ? issue$1.expected : void 0),
|
|
2753
|
+
received: this.toOptionalString("received" in issue$1 ? issue$1.received : void 0)
|
|
2754
|
+
}));
|
|
2755
|
+
if (effectiveError.name !== "ZodError") return;
|
|
2756
|
+
return [{
|
|
2757
|
+
path: [],
|
|
2758
|
+
code: "invalid_tool_input",
|
|
2759
|
+
message: `Tool "${toolName}" input was invalid: ${effectiveError.message}`
|
|
2760
|
+
}];
|
|
2761
|
+
}
|
|
2762
|
+
isTransientExecutionError(error) {
|
|
2763
|
+
const summary = `${error.name} ${error.message}`.toLowerCase();
|
|
2764
|
+
return summary.includes("timeout") || summary.includes("timed out") || summary.includes("rate limit") || summary.includes("too many requests") || summary.includes("temporarily unavailable") || summary.includes("econnreset") || summary.includes("etimedout") || summary.includes("503");
|
|
2765
|
+
}
|
|
2766
|
+
toError(error) {
|
|
2767
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
2768
|
+
}
|
|
2769
|
+
toJsonValue(value) {
|
|
2770
|
+
if (value === void 0) return;
|
|
2771
|
+
return JSON.parse(JSON.stringify(value));
|
|
2772
|
+
}
|
|
2773
|
+
toOptionalString(value) {
|
|
2774
|
+
if (value === void 0) return;
|
|
2775
|
+
return String(value);
|
|
2776
|
+
}
|
|
2777
|
+
};
|
|
2778
|
+
AgentToolErrorClassifier = __decorate([(0, __codemation_core.injectable)()], AgentToolErrorClassifier);
|
|
2779
|
+
|
|
2780
|
+
//#endregion
|
|
2781
|
+
//#region src/nodes/AgentToolRepairExhaustedError.ts
|
|
2782
|
+
var AgentToolRepairExhaustedError = class extends Error {
|
|
2783
|
+
details;
|
|
2784
|
+
constructor(args) {
|
|
2785
|
+
super(`AIAgent "${args.agentName}" (${args.nodeId}) could not recover from invalid tool calls for "${args.toolName}" after ${args.maxAttempts} repair attempt(s).`);
|
|
2786
|
+
this.name = "AgentToolRepairExhaustedError";
|
|
2787
|
+
const details = {
|
|
2788
|
+
toolName: args.toolName,
|
|
2789
|
+
maxAttempts: args.maxAttempts,
|
|
2790
|
+
recommendation: "Check tool schema, tool description, or inject known values in code instead of asking the model to infer them."
|
|
2791
|
+
};
|
|
2792
|
+
if (args.lastManagedInput !== void 0) details["lastManagedInput"] = args.lastManagedInput;
|
|
2793
|
+
if (args.lastValidationIssues && args.lastValidationIssues.length > 0) details["lastValidationIssues"] = args.lastValidationIssues.map((issue$1) => this.serializeIssue(issue$1));
|
|
2794
|
+
this.details = details;
|
|
2795
|
+
}
|
|
2796
|
+
serializeIssue(issue$1) {
|
|
2797
|
+
const result = {
|
|
2798
|
+
path: [...issue$1.path],
|
|
2799
|
+
code: issue$1.code,
|
|
2800
|
+
message: issue$1.message
|
|
2801
|
+
};
|
|
2802
|
+
if (issue$1.expected !== void 0) result["expected"] = issue$1.expected;
|
|
2803
|
+
if (issue$1.received !== void 0) result["received"] = issue$1.received;
|
|
2804
|
+
return result;
|
|
2805
|
+
}
|
|
2806
|
+
};
|
|
2807
|
+
|
|
2808
|
+
//#endregion
|
|
2809
|
+
//#region src/nodes/AgentToolRepairPolicy.ts
|
|
2810
|
+
var _AgentToolRepairPolicy;
|
|
2811
|
+
let AgentToolRepairPolicy = class AgentToolRepairPolicy$1 {
|
|
2812
|
+
static {
|
|
2813
|
+
_AgentToolRepairPolicy = this;
|
|
2814
|
+
}
|
|
2815
|
+
static maxRepairAttemptsPerTool = 2;
|
|
2816
|
+
createDecision(toolName, attemptsByToolName) {
|
|
2817
|
+
const attempt = (attemptsByToolName.get(toolName) ?? 0) + 1;
|
|
2818
|
+
attemptsByToolName.set(toolName, attempt);
|
|
2819
|
+
return {
|
|
2820
|
+
attempt,
|
|
2821
|
+
maxAttempts: _AgentToolRepairPolicy.maxRepairAttemptsPerTool,
|
|
2822
|
+
nextAction: attempt < _AgentToolRepairPolicy.maxRepairAttemptsPerTool ? "model_retry_with_tool_error_message" : "fail_agent_run"
|
|
2823
|
+
};
|
|
2824
|
+
}
|
|
2825
|
+
};
|
|
2826
|
+
AgentToolRepairPolicy = _AgentToolRepairPolicy = __decorate([(0, __codemation_core.injectable)()], AgentToolRepairPolicy);
|
|
2827
|
+
|
|
2828
|
+
//#endregion
|
|
2829
|
+
//#region src/nodes/AgentToolExecutionCoordinator.ts
|
|
2830
|
+
var _ref$2, _ref2$2;
|
|
2831
|
+
let AgentToolExecutionCoordinator = class AgentToolExecutionCoordinator$1 {
|
|
2832
|
+
constructor(errorClassifier, repairPolicy) {
|
|
2833
|
+
this.errorClassifier = errorClassifier;
|
|
2834
|
+
this.repairPolicy = repairPolicy;
|
|
2835
|
+
}
|
|
2836
|
+
async execute(args) {
|
|
2837
|
+
const results = await Promise.allSettled(args.plannedToolCalls.map(async (plannedToolCall) => await this.executePlannedToolCall({
|
|
2838
|
+
...args,
|
|
2839
|
+
plannedToolCall
|
|
2840
|
+
})));
|
|
2841
|
+
const rejected = results.find((result) => result.status === "rejected");
|
|
2842
|
+
if (rejected?.status === "rejected") throw rejected.reason instanceof Error ? rejected.reason : new Error(String(rejected.reason));
|
|
2843
|
+
return results.filter((result) => result.status === "fulfilled").map((result) => result.value);
|
|
2844
|
+
}
|
|
2845
|
+
async executePlannedToolCall(args) {
|
|
2846
|
+
const { plannedToolCall, ctx } = args;
|
|
2847
|
+
const toolCallInputsByPort = AgentToolCallPortMap.fromInput(plannedToolCall.toolCall.input ?? {});
|
|
2848
|
+
const invocationId = __codemation_core.ConnectionInvocationIdFactory.create();
|
|
2849
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
2850
|
+
const span = ctx.telemetry.startChildSpan({
|
|
2851
|
+
name: "agent.tool.call",
|
|
2852
|
+
kind: "client",
|
|
2853
|
+
startedAt,
|
|
2854
|
+
attributes: {
|
|
2855
|
+
[__codemation_core.CodemationTelemetryAttributeNames.connectionInvocationId]: invocationId,
|
|
2856
|
+
[__codemation_core.CodemationTelemetryAttributeNames.toolName]: plannedToolCall.binding.config.name
|
|
2857
|
+
}
|
|
2858
|
+
});
|
|
2859
|
+
await ctx.nodeState?.markRunning({
|
|
2860
|
+
nodeId: plannedToolCall.nodeId,
|
|
2861
|
+
activationId: ctx.activationId,
|
|
2862
|
+
inputsByPort: toolCallInputsByPort
|
|
2863
|
+
});
|
|
2864
|
+
try {
|
|
2865
|
+
const serialized = await plannedToolCall.binding.langChainTool.invoke(plannedToolCall.toolCall.input ?? {});
|
|
2866
|
+
const result = this.parseToolOutput(serialized);
|
|
2867
|
+
const finishedAt = /* @__PURE__ */ new Date();
|
|
2868
|
+
await ctx.nodeState?.markCompleted({
|
|
2869
|
+
nodeId: plannedToolCall.nodeId,
|
|
2870
|
+
activationId: ctx.activationId,
|
|
2871
|
+
inputsByPort: toolCallInputsByPort,
|
|
2872
|
+
outputs: AgentOutputFactory.fromUnknown(result)
|
|
2873
|
+
});
|
|
2874
|
+
await span.attachArtifact({
|
|
2875
|
+
kind: "tool.input",
|
|
2876
|
+
contentType: "application/json",
|
|
2877
|
+
previewJson: this.toJsonValue(plannedToolCall.toolCall.input)
|
|
2878
|
+
});
|
|
2879
|
+
await span.attachArtifact({
|
|
2880
|
+
kind: "tool.output",
|
|
2881
|
+
contentType: "application/json",
|
|
2882
|
+
previewJson: this.toJsonValue(result)
|
|
2883
|
+
});
|
|
2884
|
+
await span.end({
|
|
2885
|
+
status: "ok",
|
|
2886
|
+
endedAt: finishedAt
|
|
2887
|
+
});
|
|
2888
|
+
await ctx.nodeState?.appendConnectionInvocation({
|
|
2889
|
+
invocationId,
|
|
2890
|
+
connectionNodeId: plannedToolCall.nodeId,
|
|
2891
|
+
parentAgentNodeId: ctx.nodeId,
|
|
2892
|
+
parentAgentActivationId: ctx.activationId,
|
|
2893
|
+
status: "completed",
|
|
2894
|
+
managedInput: this.toJsonValue(plannedToolCall.toolCall.input),
|
|
2895
|
+
managedOutput: this.toJsonValue(result),
|
|
2896
|
+
queuedAt: startedAt.toISOString(),
|
|
2897
|
+
startedAt: startedAt.toISOString(),
|
|
2898
|
+
finishedAt: finishedAt.toISOString()
|
|
2899
|
+
});
|
|
2900
|
+
return {
|
|
2901
|
+
toolName: plannedToolCall.binding.config.name,
|
|
2902
|
+
toolCallId: plannedToolCall.toolCall.id ?? plannedToolCall.binding.config.name,
|
|
2903
|
+
serialized: typeof serialized === "string" ? serialized : JSON.stringify(serialized),
|
|
2904
|
+
result
|
|
2905
|
+
};
|
|
2906
|
+
} catch (error) {
|
|
2907
|
+
const classification = this.errorClassifier.classify({
|
|
2908
|
+
error,
|
|
2909
|
+
toolName: plannedToolCall.binding.config.name,
|
|
2910
|
+
schema: plannedToolCall.binding.langChainTool.schema
|
|
2911
|
+
});
|
|
2912
|
+
if (classification.kind !== "repairable_validation_error") {
|
|
2913
|
+
const effectiveError = classification.effectiveError;
|
|
2914
|
+
await this.recordFailedInvocation({
|
|
2915
|
+
invocationId,
|
|
2916
|
+
plannedToolCall,
|
|
2917
|
+
ctx,
|
|
2918
|
+
startedAt,
|
|
2919
|
+
inputsByPort: toolCallInputsByPort,
|
|
2920
|
+
managedInput: this.toJsonValue(plannedToolCall.toolCall.input),
|
|
2921
|
+
error: effectiveError
|
|
2922
|
+
});
|
|
2923
|
+
await span.attachArtifact({
|
|
2924
|
+
kind: "tool.input",
|
|
2925
|
+
contentType: "application/json",
|
|
2926
|
+
previewJson: this.toJsonValue(plannedToolCall.toolCall.input)
|
|
2927
|
+
});
|
|
2928
|
+
await span.end({
|
|
2929
|
+
status: "error",
|
|
2930
|
+
statusMessage: effectiveError.message,
|
|
2931
|
+
endedAt: /* @__PURE__ */ new Date()
|
|
2932
|
+
});
|
|
2933
|
+
throw effectiveError;
|
|
2934
|
+
}
|
|
2935
|
+
const repairDecision = this.repairPolicy.createDecision(plannedToolCall.binding.config.name, args.repairAttemptsByToolName);
|
|
2936
|
+
if (repairDecision.nextAction === "fail_agent_run") {
|
|
2937
|
+
const exhaustedError = new AgentToolRepairExhaustedError({
|
|
2938
|
+
agentName: args.agentName,
|
|
2939
|
+
nodeId: ctx.nodeId,
|
|
2940
|
+
toolName: plannedToolCall.binding.config.name,
|
|
2941
|
+
maxAttempts: repairDecision.maxAttempts,
|
|
2942
|
+
lastManagedInput: this.toJsonValue(plannedToolCall.toolCall.input),
|
|
2943
|
+
lastValidationIssues: classification.issues
|
|
2944
|
+
});
|
|
2945
|
+
await this.recordFailedInvocation({
|
|
2946
|
+
invocationId,
|
|
2947
|
+
plannedToolCall,
|
|
2948
|
+
ctx,
|
|
2949
|
+
startedAt,
|
|
2950
|
+
inputsByPort: toolCallInputsByPort,
|
|
2951
|
+
managedInput: this.toJsonValue(plannedToolCall.toolCall.input),
|
|
2952
|
+
error: exhaustedError,
|
|
2953
|
+
errorDetails: exhaustedError.details
|
|
2954
|
+
});
|
|
2955
|
+
await span.attachArtifact({
|
|
2956
|
+
kind: "tool.input",
|
|
2957
|
+
contentType: "application/json",
|
|
2958
|
+
previewJson: this.toJsonValue(plannedToolCall.toolCall.input)
|
|
2959
|
+
});
|
|
2960
|
+
await span.attachArtifact({
|
|
2961
|
+
kind: "tool.error",
|
|
2962
|
+
contentType: "application/json",
|
|
2963
|
+
previewJson: exhaustedError.details
|
|
2964
|
+
});
|
|
2965
|
+
await span.end({
|
|
2966
|
+
status: "error",
|
|
2967
|
+
statusMessage: exhaustedError.message,
|
|
2968
|
+
endedAt: /* @__PURE__ */ new Date()
|
|
2969
|
+
});
|
|
2970
|
+
throw exhaustedError;
|
|
2971
|
+
}
|
|
2972
|
+
const repairPayload = this.createRepairPayload({
|
|
2973
|
+
toolName: plannedToolCall.binding.config.name,
|
|
2974
|
+
issues: classification.issues,
|
|
2975
|
+
requiredSchemaReminder: classification.requiredSchemaReminder
|
|
2976
|
+
});
|
|
2977
|
+
const repairDetails = this.createRepairDetails({
|
|
2978
|
+
toolName: plannedToolCall.binding.config.name,
|
|
2979
|
+
issues: classification.issues,
|
|
2980
|
+
requiredSchemaReminder: classification.requiredSchemaReminder,
|
|
2981
|
+
repairDecision
|
|
2982
|
+
});
|
|
2983
|
+
await this.recordFailedInvocation({
|
|
2984
|
+
invocationId,
|
|
2985
|
+
plannedToolCall,
|
|
2986
|
+
ctx,
|
|
2987
|
+
startedAt,
|
|
2988
|
+
inputsByPort: toolCallInputsByPort,
|
|
2989
|
+
managedInput: this.toJsonValue(plannedToolCall.toolCall.input),
|
|
2990
|
+
error: classification.effectiveError,
|
|
2991
|
+
errorDetails: repairDetails
|
|
2992
|
+
});
|
|
2993
|
+
await span.attachArtifact({
|
|
2994
|
+
kind: "tool.input",
|
|
2995
|
+
contentType: "application/json",
|
|
2996
|
+
previewJson: this.toJsonValue(plannedToolCall.toolCall.input)
|
|
2997
|
+
});
|
|
2998
|
+
await span.attachArtifact({
|
|
2999
|
+
kind: "tool.error",
|
|
3000
|
+
contentType: "application/json",
|
|
3001
|
+
previewJson: repairPayload
|
|
3002
|
+
});
|
|
3003
|
+
await span.end({
|
|
3004
|
+
status: "error",
|
|
3005
|
+
statusMessage: classification.effectiveError.message,
|
|
3006
|
+
endedAt: /* @__PURE__ */ new Date()
|
|
3007
|
+
});
|
|
3008
|
+
return {
|
|
3009
|
+
toolName: plannedToolCall.binding.config.name,
|
|
3010
|
+
toolCallId: plannedToolCall.toolCall.id ?? plannedToolCall.binding.config.name,
|
|
3011
|
+
serialized: JSON.stringify(repairPayload),
|
|
3012
|
+
result: repairPayload
|
|
3013
|
+
};
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
async recordFailedInvocation(args) {
|
|
3017
|
+
const finishedAt = /* @__PURE__ */ new Date();
|
|
3018
|
+
await args.ctx.nodeState?.markFailed({
|
|
3019
|
+
nodeId: args.plannedToolCall.nodeId,
|
|
3020
|
+
activationId: args.ctx.activationId,
|
|
3021
|
+
inputsByPort: args.inputsByPort,
|
|
3022
|
+
error: args.error
|
|
3023
|
+
});
|
|
3024
|
+
await args.ctx.nodeState?.appendConnectionInvocation({
|
|
3025
|
+
invocationId: args.invocationId,
|
|
3026
|
+
connectionNodeId: args.plannedToolCall.nodeId,
|
|
3027
|
+
parentAgentNodeId: args.ctx.nodeId,
|
|
3028
|
+
parentAgentActivationId: args.ctx.activationId,
|
|
3029
|
+
status: "failed",
|
|
3030
|
+
managedInput: args.managedInput,
|
|
3031
|
+
error: {
|
|
3032
|
+
message: args.error.message,
|
|
3033
|
+
name: args.error.name,
|
|
3034
|
+
stack: args.error.stack,
|
|
3035
|
+
details: args.errorDetails ?? this.extractErrorDetails(args.error)
|
|
3036
|
+
},
|
|
3037
|
+
queuedAt: args.startedAt.toISOString(),
|
|
3038
|
+
startedAt: args.startedAt.toISOString(),
|
|
3039
|
+
finishedAt: finishedAt.toISOString()
|
|
3040
|
+
});
|
|
3041
|
+
}
|
|
3042
|
+
createRepairPayload(args) {
|
|
3043
|
+
const payload = {
|
|
3044
|
+
status: "error",
|
|
3045
|
+
errorType: "validation",
|
|
3046
|
+
toolName: args.toolName,
|
|
3047
|
+
message: this.createValidationMessage(args.toolName, args.issues),
|
|
3048
|
+
instruction: "Call the tool again with all required fields present and correctly typed."
|
|
3049
|
+
};
|
|
3050
|
+
if (args.requiredSchemaReminder !== void 0) payload["requiredSchemaReminder"] = args.requiredSchemaReminder;
|
|
3051
|
+
return payload;
|
|
3052
|
+
}
|
|
3053
|
+
createRepairDetails(args) {
|
|
3054
|
+
const details = {
|
|
3055
|
+
errorType: "validation",
|
|
3056
|
+
toolName: args.toolName,
|
|
3057
|
+
recoveryHint: "Call the same tool again with every required field present and correctly typed.",
|
|
3058
|
+
repair: {
|
|
3059
|
+
attempt: args.repairDecision.attempt,
|
|
3060
|
+
maxAttempts: args.repairDecision.maxAttempts,
|
|
3061
|
+
nextAction: args.repairDecision.nextAction
|
|
3062
|
+
}
|
|
3063
|
+
};
|
|
3064
|
+
if (args.issues && args.issues.length > 0) details["issues"] = args.issues.map((issue$1) => this.serializeIssue(issue$1));
|
|
3065
|
+
if (args.requiredSchemaReminder !== void 0) details["requiredSchemaReminder"] = args.requiredSchemaReminder;
|
|
3066
|
+
return details;
|
|
3067
|
+
}
|
|
3068
|
+
createValidationMessage(toolName, issues) {
|
|
3069
|
+
const firstIssue = issues?.[0];
|
|
3070
|
+
if (!firstIssue) return `Your previous tool call for "${toolName}" was invalid and did not match the expected schema.`;
|
|
3071
|
+
return `Your previous tool call for "${toolName}" was invalid because field "${firstIssue.path.length > 0 ? firstIssue.path.join(".") : "<root>"}" failed validation: ${firstIssue.message}`;
|
|
3072
|
+
}
|
|
3073
|
+
parseToolOutput(serialized) {
|
|
3074
|
+
if (typeof serialized !== "string") return serialized;
|
|
3075
|
+
try {
|
|
3076
|
+
return JSON.parse(serialized);
|
|
3077
|
+
} catch {
|
|
3078
|
+
return serialized;
|
|
3079
|
+
}
|
|
3080
|
+
}
|
|
3081
|
+
toJsonValue(value) {
|
|
3082
|
+
if (value === void 0) return;
|
|
3083
|
+
return JSON.parse(JSON.stringify(value));
|
|
3084
|
+
}
|
|
3085
|
+
extractErrorDetails(error) {
|
|
3086
|
+
return error.details;
|
|
3087
|
+
}
|
|
3088
|
+
serializeIssue(issue$1) {
|
|
3089
|
+
const result = {
|
|
3090
|
+
path: [...issue$1.path],
|
|
3091
|
+
code: issue$1.code,
|
|
3092
|
+
message: issue$1.message
|
|
3093
|
+
};
|
|
3094
|
+
if (issue$1.expected !== void 0) result["expected"] = issue$1.expected;
|
|
3095
|
+
if (issue$1.received !== void 0) result["received"] = issue$1.received;
|
|
3096
|
+
return result;
|
|
3097
|
+
}
|
|
3098
|
+
};
|
|
3099
|
+
AgentToolExecutionCoordinator = __decorate([
|
|
3100
|
+
(0, __codemation_core.injectable)(),
|
|
3101
|
+
__decorateParam(0, (0, __codemation_core.inject)(AgentToolErrorClassifier)),
|
|
3102
|
+
__decorateParam(1, (0, __codemation_core.inject)(AgentToolRepairPolicy)),
|
|
3103
|
+
__decorateMetadata("design:paramtypes", [typeof (_ref$2 = typeof AgentToolErrorClassifier !== "undefined" && AgentToolErrorClassifier) === "function" ? _ref$2 : Object, typeof (_ref2$2 = typeof AgentToolRepairPolicy !== "undefined" && AgentToolRepairPolicy) === "function" ? _ref2$2 : Object])
|
|
3104
|
+
], AgentToolExecutionCoordinator);
|
|
3105
|
+
|
|
2719
3106
|
//#endregion
|
|
2720
3107
|
//#region src/nodes/NodeBackedToolRuntime.ts
|
|
2721
3108
|
var _ref$1, _ref2$1, _ref3$1;
|
|
@@ -2806,7 +3193,7 @@ var AgentItemPortMap = class {
|
|
|
2806
3193
|
|
|
2807
3194
|
//#endregion
|
|
2808
3195
|
//#region src/nodes/AIAgentNode.ts
|
|
2809
|
-
var _ref, _ref2, _ref3;
|
|
3196
|
+
var _ref, _ref2, _ref3, _ref4;
|
|
2810
3197
|
let AIAgentNode = class AIAgentNode$1 {
|
|
2811
3198
|
kind = "node";
|
|
2812
3199
|
outputPorts = ["main"];
|
|
@@ -2819,11 +3206,12 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
2819
3206
|
connectionCredentialExecutionContextFactory;
|
|
2820
3207
|
/** One resolved model/tools bundle per activation context (same ctx across items in a batch). */
|
|
2821
3208
|
preparedByExecutionContext = /* @__PURE__ */ new WeakMap();
|
|
2822
|
-
constructor(nodeResolver, credentialSessions, nodeBackedToolRuntime, executionHelpers, structuredOutputRunner) {
|
|
3209
|
+
constructor(nodeResolver, credentialSessions, nodeBackedToolRuntime, executionHelpers, structuredOutputRunner, toolExecutionCoordinator) {
|
|
2823
3210
|
this.nodeResolver = nodeResolver;
|
|
2824
3211
|
this.nodeBackedToolRuntime = nodeBackedToolRuntime;
|
|
2825
3212
|
this.executionHelpers = executionHelpers;
|
|
2826
3213
|
this.structuredOutputRunner = structuredOutputRunner;
|
|
3214
|
+
this.toolExecutionCoordinator = toolExecutionCoordinator;
|
|
2827
3215
|
this.connectionCredentialExecutionContextFactory = this.executionHelpers.createConnectionCredentialExecutionContextFactory(credentialSessions);
|
|
2828
3216
|
}
|
|
2829
3217
|
async execute(args) {
|
|
@@ -2886,17 +3274,33 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
2886
3274
|
invokeTextModel: async (messages) => await this.invokeModel(prepared.model, prepared.languageModelConnectionNodeId, messages, ctx, itemInputsByPort, prepared.guardrails.modelInvocationOptions),
|
|
2887
3275
|
invokeStructuredModel: async (structuredModel, messages) => await this.invokeStructuredModel(structuredModel, prepared.languageModelConnectionNodeId, messages, ctx, itemInputsByPort, prepared.guardrails.modelInvocationOptions)
|
|
2888
3276
|
});
|
|
3277
|
+
await ctx.telemetry.recordMetric({
|
|
3278
|
+
name: __codemation_core.CodemationTelemetryMetricNames.agentTurns,
|
|
3279
|
+
value: 1
|
|
3280
|
+
});
|
|
3281
|
+
await ctx.telemetry.recordMetric({
|
|
3282
|
+
name: __codemation_core.CodemationTelemetryMetricNames.agentToolCalls,
|
|
3283
|
+
value: 0
|
|
3284
|
+
});
|
|
2889
3285
|
return this.buildOutputItem(item, structuredOutput);
|
|
2890
3286
|
}
|
|
2891
3287
|
const modelWithTools = this.bindToolsToModel(prepared.model, itemScopedTools);
|
|
2892
|
-
const
|
|
3288
|
+
const loopResult = await this.runTurnLoopUntilFinalAnswer({
|
|
2893
3289
|
prepared,
|
|
2894
3290
|
itemInputsByPort,
|
|
2895
3291
|
itemScopedTools,
|
|
2896
3292
|
conversation,
|
|
2897
3293
|
modelWithTools
|
|
2898
3294
|
});
|
|
2899
|
-
|
|
3295
|
+
await ctx.telemetry.recordMetric({
|
|
3296
|
+
name: __codemation_core.CodemationTelemetryMetricNames.agentTurns,
|
|
3297
|
+
value: loopResult.turnCount
|
|
3298
|
+
});
|
|
3299
|
+
await ctx.telemetry.recordMetric({
|
|
3300
|
+
name: __codemation_core.CodemationTelemetryMetricNames.agentToolCalls,
|
|
3301
|
+
value: loopResult.toolCallCount
|
|
3302
|
+
});
|
|
3303
|
+
const outputJson = await this.resolveFinalOutputJson(prepared, itemInputsByPort, conversation, loopResult.finalResponse, itemScopedTools.length > 0);
|
|
2900
3304
|
return this.buildOutputItem(item, outputJson);
|
|
2901
3305
|
}
|
|
2902
3306
|
/**
|
|
@@ -2906,7 +3310,11 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
2906
3310
|
const { prepared, itemInputsByPort, itemScopedTools, conversation, modelWithTools } = args;
|
|
2907
3311
|
const { ctx, guardrails, languageModelConnectionNodeId } = prepared;
|
|
2908
3312
|
let finalResponse;
|
|
3313
|
+
let toolCallCount = 0;
|
|
3314
|
+
let turnCount = 0;
|
|
3315
|
+
const repairAttemptsByToolName = /* @__PURE__ */ new Map();
|
|
2909
3316
|
for (let turn = 1; turn <= guardrails.maxTurns; turn++) {
|
|
3317
|
+
turnCount = turn;
|
|
2910
3318
|
const response = await this.invokeModel(modelWithTools, languageModelConnectionNodeId, conversation, ctx, itemInputsByPort, guardrails.modelInvocationOptions);
|
|
2911
3319
|
finalResponse = response;
|
|
2912
3320
|
const toolCalls = AgentMessageFactory.extractToolCalls(response);
|
|
@@ -2916,12 +3324,22 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
2916
3324
|
break;
|
|
2917
3325
|
}
|
|
2918
3326
|
const plannedToolCalls = this.planToolCalls(itemScopedTools, toolCalls, ctx.nodeId);
|
|
3327
|
+
toolCallCount += plannedToolCalls.length;
|
|
2919
3328
|
await this.markQueuedTools(plannedToolCalls, ctx);
|
|
2920
|
-
const executedToolCalls = await this.
|
|
3329
|
+
const executedToolCalls = await this.toolExecutionCoordinator.execute({
|
|
3330
|
+
plannedToolCalls,
|
|
3331
|
+
ctx,
|
|
3332
|
+
agentName: this.getAgentDisplayName(ctx),
|
|
3333
|
+
repairAttemptsByToolName
|
|
3334
|
+
});
|
|
2921
3335
|
this.appendAssistantAndToolMessages(conversation, response, executedToolCalls);
|
|
2922
3336
|
}
|
|
2923
3337
|
if (!finalResponse) throw new Error(`AIAgent "${ctx.config.name ?? ctx.nodeId}" did not produce a model response.`);
|
|
2924
|
-
return
|
|
3338
|
+
return {
|
|
3339
|
+
finalResponse,
|
|
3340
|
+
turnCount,
|
|
3341
|
+
toolCallCount
|
|
3342
|
+
};
|
|
2925
3343
|
}
|
|
2926
3344
|
cannotExecuteAnotherToolRound(turn, guardrails) {
|
|
2927
3345
|
return turn >= guardrails.maxTurns;
|
|
@@ -2980,6 +3398,10 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
2980
3398
|
});
|
|
2981
3399
|
}
|
|
2982
3400
|
async invokeModel(model, nodeId, messages, ctx, inputsByPort, options) {
|
|
3401
|
+
const invocationId = __codemation_core.ConnectionInvocationIdFactory.create();
|
|
3402
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
3403
|
+
const summarizedInput = this.summarizeLlmMessages(messages);
|
|
3404
|
+
const span = this.createModelInvocationSpan(ctx, invocationId, startedAt);
|
|
2983
3405
|
await ctx.nodeState?.markQueued({
|
|
2984
3406
|
nodeId,
|
|
2985
3407
|
activationId: ctx.activationId,
|
|
@@ -2992,6 +3414,7 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
2992
3414
|
});
|
|
2993
3415
|
try {
|
|
2994
3416
|
const response = await model.invoke(messages, options);
|
|
3417
|
+
const finishedAt = /* @__PURE__ */ new Date();
|
|
2995
3418
|
await ctx.nodeState?.markCompleted({
|
|
2996
3419
|
nodeId,
|
|
2997
3420
|
activationId: ctx.activationId,
|
|
@@ -2999,22 +3422,56 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
2999
3422
|
outputs: AgentOutputFactory.fromUnknown({ content: AgentMessageFactory.extractContent(response) })
|
|
3000
3423
|
});
|
|
3001
3424
|
const content = AgentMessageFactory.extractContent(response);
|
|
3425
|
+
await span.attachArtifact({
|
|
3426
|
+
kind: "ai.messages",
|
|
3427
|
+
contentType: "application/json",
|
|
3428
|
+
previewJson: summarizedInput
|
|
3429
|
+
});
|
|
3430
|
+
await span.attachArtifact({
|
|
3431
|
+
kind: "ai.response",
|
|
3432
|
+
contentType: "application/json",
|
|
3433
|
+
previewJson: content
|
|
3434
|
+
});
|
|
3435
|
+
await this.recordModelUsageMetrics(span, response, ctx);
|
|
3436
|
+
await span.end({
|
|
3437
|
+
status: "ok",
|
|
3438
|
+
endedAt: finishedAt
|
|
3439
|
+
});
|
|
3002
3440
|
await ctx.nodeState?.appendConnectionInvocation({
|
|
3003
|
-
invocationId
|
|
3441
|
+
invocationId,
|
|
3004
3442
|
connectionNodeId: nodeId,
|
|
3005
3443
|
parentAgentNodeId: ctx.nodeId,
|
|
3006
3444
|
parentAgentActivationId: ctx.activationId,
|
|
3007
3445
|
status: "completed",
|
|
3008
|
-
managedInput:
|
|
3446
|
+
managedInput: summarizedInput,
|
|
3009
3447
|
managedOutput: content,
|
|
3010
|
-
|
|
3448
|
+
queuedAt: startedAt.toISOString(),
|
|
3449
|
+
startedAt: startedAt.toISOString(),
|
|
3450
|
+
finishedAt: finishedAt.toISOString()
|
|
3011
3451
|
});
|
|
3012
3452
|
return response;
|
|
3013
3453
|
} catch (error) {
|
|
3014
|
-
|
|
3454
|
+
await span.end({
|
|
3455
|
+
status: "error",
|
|
3456
|
+
statusMessage: error instanceof Error ? error.message : String(error),
|
|
3457
|
+
endedAt: /* @__PURE__ */ new Date()
|
|
3458
|
+
});
|
|
3459
|
+
throw await this.failTrackedNodeInvocation({
|
|
3460
|
+
error,
|
|
3461
|
+
invocationId,
|
|
3462
|
+
startedAt,
|
|
3463
|
+
nodeId,
|
|
3464
|
+
ctx,
|
|
3465
|
+
inputsByPort,
|
|
3466
|
+
managedInput: this.summarizeLlmMessages(messages)
|
|
3467
|
+
});
|
|
3015
3468
|
}
|
|
3016
3469
|
}
|
|
3017
3470
|
async invokeStructuredModel(model, nodeId, messages, ctx, inputsByPort, options) {
|
|
3471
|
+
const invocationId = __codemation_core.ConnectionInvocationIdFactory.create();
|
|
3472
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
3473
|
+
const summarizedInput = this.summarizeLlmMessages(messages);
|
|
3474
|
+
const span = this.createModelInvocationSpan(ctx, invocationId, startedAt);
|
|
3018
3475
|
await ctx.nodeState?.markQueued({
|
|
3019
3476
|
nodeId,
|
|
3020
3477
|
activationId: ctx.activationId,
|
|
@@ -3027,26 +3484,173 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
3027
3484
|
});
|
|
3028
3485
|
try {
|
|
3029
3486
|
const response = await model.invoke(messages, options);
|
|
3487
|
+
const finishedAt = /* @__PURE__ */ new Date();
|
|
3030
3488
|
await ctx.nodeState?.markCompleted({
|
|
3031
3489
|
nodeId,
|
|
3032
3490
|
activationId: ctx.activationId,
|
|
3033
3491
|
inputsByPort,
|
|
3034
3492
|
outputs: AgentOutputFactory.fromUnknown(response)
|
|
3035
3493
|
});
|
|
3494
|
+
await span.attachArtifact({
|
|
3495
|
+
kind: "ai.messages",
|
|
3496
|
+
contentType: "application/json",
|
|
3497
|
+
previewJson: summarizedInput
|
|
3498
|
+
});
|
|
3499
|
+
await span.attachArtifact({
|
|
3500
|
+
kind: "ai.response.structured",
|
|
3501
|
+
contentType: "application/json",
|
|
3502
|
+
previewJson: this.resultToJsonValue(response)
|
|
3503
|
+
});
|
|
3504
|
+
await this.recordModelUsageMetrics(span, response, ctx);
|
|
3505
|
+
await span.end({
|
|
3506
|
+
status: "ok",
|
|
3507
|
+
endedAt: finishedAt
|
|
3508
|
+
});
|
|
3036
3509
|
await ctx.nodeState?.appendConnectionInvocation({
|
|
3037
|
-
invocationId
|
|
3510
|
+
invocationId,
|
|
3038
3511
|
connectionNodeId: nodeId,
|
|
3039
3512
|
parentAgentNodeId: ctx.nodeId,
|
|
3040
3513
|
parentAgentActivationId: ctx.activationId,
|
|
3041
3514
|
status: "completed",
|
|
3042
|
-
managedInput:
|
|
3515
|
+
managedInput: summarizedInput,
|
|
3043
3516
|
managedOutput: this.resultToJsonValue(response),
|
|
3044
|
-
|
|
3517
|
+
queuedAt: startedAt.toISOString(),
|
|
3518
|
+
startedAt: startedAt.toISOString(),
|
|
3519
|
+
finishedAt: finishedAt.toISOString()
|
|
3045
3520
|
});
|
|
3046
3521
|
return response;
|
|
3047
3522
|
} catch (error) {
|
|
3048
|
-
|
|
3523
|
+
await span.end({
|
|
3524
|
+
status: "error",
|
|
3525
|
+
statusMessage: error instanceof Error ? error.message : String(error),
|
|
3526
|
+
endedAt: /* @__PURE__ */ new Date()
|
|
3527
|
+
});
|
|
3528
|
+
throw await this.failTrackedNodeInvocation({
|
|
3529
|
+
error,
|
|
3530
|
+
invocationId,
|
|
3531
|
+
startedAt,
|
|
3532
|
+
nodeId,
|
|
3533
|
+
ctx,
|
|
3534
|
+
inputsByPort,
|
|
3535
|
+
managedInput: this.summarizeLlmMessages(messages)
|
|
3536
|
+
});
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3539
|
+
createModelInvocationSpan(ctx, invocationId, startedAt) {
|
|
3540
|
+
return ctx.telemetry.startChildSpan({
|
|
3541
|
+
name: "gen_ai.chat.completion",
|
|
3542
|
+
kind: "client",
|
|
3543
|
+
startedAt,
|
|
3544
|
+
attributes: {
|
|
3545
|
+
[__codemation_core.CodemationTelemetryAttributeNames.connectionInvocationId]: invocationId,
|
|
3546
|
+
[__codemation_core.GenAiTelemetryAttributeNames.operationName]: "chat",
|
|
3547
|
+
[__codemation_core.GenAiTelemetryAttributeNames.requestModel]: this.resolveChatModelName(ctx.config.chatModel)
|
|
3548
|
+
}
|
|
3549
|
+
});
|
|
3550
|
+
}
|
|
3551
|
+
async recordModelUsageMetrics(span, response, ctx) {
|
|
3552
|
+
const usage = this.extractModelUsageMetrics(response);
|
|
3553
|
+
for (const [name, value] of Object.entries(usage)) {
|
|
3554
|
+
if (value === void 0) continue;
|
|
3555
|
+
await span.recordMetric({
|
|
3556
|
+
name,
|
|
3557
|
+
value
|
|
3558
|
+
});
|
|
3049
3559
|
}
|
|
3560
|
+
await this.captureCostTrackingUsage(span, ctx, usage);
|
|
3561
|
+
}
|
|
3562
|
+
async captureCostTrackingUsage(span, ctx, usage) {
|
|
3563
|
+
const costTracking = span.costTracking;
|
|
3564
|
+
if (!costTracking) return;
|
|
3565
|
+
const provider = ctx.config.chatModel.provider;
|
|
3566
|
+
const pricingKey = ctx.config.chatModel.modelName;
|
|
3567
|
+
if (!provider || !pricingKey) return;
|
|
3568
|
+
const inputTokens = usage[__codemation_core.GenAiTelemetryAttributeNames.usageInputTokens];
|
|
3569
|
+
const outputTokens = usage[__codemation_core.GenAiTelemetryAttributeNames.usageOutputTokens];
|
|
3570
|
+
if (inputTokens !== void 0) await costTracking.captureUsage({
|
|
3571
|
+
component: "chat",
|
|
3572
|
+
provider,
|
|
3573
|
+
operation: "completion.input",
|
|
3574
|
+
pricingKey,
|
|
3575
|
+
usageUnit: "input_tokens",
|
|
3576
|
+
quantity: inputTokens,
|
|
3577
|
+
modelName: pricingKey
|
|
3578
|
+
});
|
|
3579
|
+
if (outputTokens !== void 0) await costTracking.captureUsage({
|
|
3580
|
+
component: "chat",
|
|
3581
|
+
provider,
|
|
3582
|
+
operation: "completion.output",
|
|
3583
|
+
pricingKey,
|
|
3584
|
+
usageUnit: "output_tokens",
|
|
3585
|
+
quantity: outputTokens,
|
|
3586
|
+
modelName: pricingKey
|
|
3587
|
+
});
|
|
3588
|
+
}
|
|
3589
|
+
resolveChatModelName(chatModel$1) {
|
|
3590
|
+
return chatModel$1.modelName ?? chatModel$1.name;
|
|
3591
|
+
}
|
|
3592
|
+
extractModelUsageMetrics(response) {
|
|
3593
|
+
const usage = this.extractUsageObject(response);
|
|
3594
|
+
const inputTokens = this.readUsageNumber(usage, [
|
|
3595
|
+
"input_tokens",
|
|
3596
|
+
"inputTokens",
|
|
3597
|
+
"prompt_tokens",
|
|
3598
|
+
"promptTokens"
|
|
3599
|
+
]);
|
|
3600
|
+
const outputTokens = this.readUsageNumber(usage, [
|
|
3601
|
+
"output_tokens",
|
|
3602
|
+
"outputTokens",
|
|
3603
|
+
"completion_tokens",
|
|
3604
|
+
"completionTokens"
|
|
3605
|
+
]);
|
|
3606
|
+
const totalTokens = this.readUsageNumber(usage, ["total_tokens", "totalTokens"]) ?? (inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0);
|
|
3607
|
+
const cachedInputTokens = this.readUsageNumber(usage, [
|
|
3608
|
+
"cache_read_input_tokens",
|
|
3609
|
+
"cacheReadInputTokens",
|
|
3610
|
+
"input_token_details.cached_tokens"
|
|
3611
|
+
]);
|
|
3612
|
+
const reasoningTokens = this.readUsageNumber(usage, [
|
|
3613
|
+
"reasoning_tokens",
|
|
3614
|
+
"reasoningTokens",
|
|
3615
|
+
"output_token_details.reasoning_tokens"
|
|
3616
|
+
]);
|
|
3617
|
+
return {
|
|
3618
|
+
[__codemation_core.GenAiTelemetryAttributeNames.usageInputTokens]: inputTokens,
|
|
3619
|
+
[__codemation_core.GenAiTelemetryAttributeNames.usageOutputTokens]: outputTokens,
|
|
3620
|
+
[__codemation_core.GenAiTelemetryAttributeNames.usageTotalTokens]: totalTokens,
|
|
3621
|
+
[__codemation_core.GenAiTelemetryAttributeNames.usageCacheReadInputTokens]: cachedInputTokens,
|
|
3622
|
+
[__codemation_core.GenAiTelemetryAttributeNames.usageReasoningTokens]: reasoningTokens
|
|
3623
|
+
};
|
|
3624
|
+
}
|
|
3625
|
+
extractUsageObject(response) {
|
|
3626
|
+
if (!this.isRecord(response)) return;
|
|
3627
|
+
const usageMetadata = response["usage_metadata"];
|
|
3628
|
+
if (this.isRecord(usageMetadata)) return usageMetadata;
|
|
3629
|
+
const responseMetadata = response["response_metadata"];
|
|
3630
|
+
if (this.isRecord(responseMetadata)) {
|
|
3631
|
+
const tokenUsage = responseMetadata["tokenUsage"];
|
|
3632
|
+
if (this.isRecord(tokenUsage)) return tokenUsage;
|
|
3633
|
+
const usage = responseMetadata["usage"];
|
|
3634
|
+
if (this.isRecord(usage)) return usage;
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
readUsageNumber(source, keys) {
|
|
3638
|
+
for (const key of keys) {
|
|
3639
|
+
const value = this.readNestedUsageValue(source, key);
|
|
3640
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
readNestedUsageValue(source, dottedKey) {
|
|
3644
|
+
if (!source) return;
|
|
3645
|
+
let current = source;
|
|
3646
|
+
for (const segment of dottedKey.split(".")) {
|
|
3647
|
+
if (!this.isRecord(current)) return;
|
|
3648
|
+
current = current[segment];
|
|
3649
|
+
}
|
|
3650
|
+
return current;
|
|
3651
|
+
}
|
|
3652
|
+
isRecord(value) {
|
|
3653
|
+
return typeof value === "object" && value !== null;
|
|
3050
3654
|
}
|
|
3051
3655
|
async markQueuedTools(plannedToolCalls, ctx) {
|
|
3052
3656
|
for (const plannedToolCall of plannedToolCalls) await ctx.nodeState?.markQueued({
|
|
@@ -3055,47 +3659,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
3055
3659
|
inputsByPort: AgentToolCallPortMap.fromInput(plannedToolCall.toolCall.input ?? {})
|
|
3056
3660
|
});
|
|
3057
3661
|
}
|
|
3058
|
-
async executeToolCalls(plannedToolCalls, ctx) {
|
|
3059
|
-
const results = await Promise.allSettled(plannedToolCalls.map(async (plannedToolCall) => {
|
|
3060
|
-
const toolCallInputsByPort = AgentToolCallPortMap.fromInput(plannedToolCall.toolCall.input ?? {});
|
|
3061
|
-
await ctx.nodeState?.markRunning({
|
|
3062
|
-
nodeId: plannedToolCall.nodeId,
|
|
3063
|
-
activationId: ctx.activationId,
|
|
3064
|
-
inputsByPort: toolCallInputsByPort
|
|
3065
|
-
});
|
|
3066
|
-
try {
|
|
3067
|
-
const serialized = await plannedToolCall.binding.langChainTool.invoke(plannedToolCall.toolCall.input ?? {});
|
|
3068
|
-
const result = this.parseToolOutput(serialized);
|
|
3069
|
-
await ctx.nodeState?.markCompleted({
|
|
3070
|
-
nodeId: plannedToolCall.nodeId,
|
|
3071
|
-
activationId: ctx.activationId,
|
|
3072
|
-
inputsByPort: toolCallInputsByPort,
|
|
3073
|
-
outputs: AgentOutputFactory.fromUnknown(result)
|
|
3074
|
-
});
|
|
3075
|
-
await ctx.nodeState?.appendConnectionInvocation({
|
|
3076
|
-
invocationId: __codemation_core.ConnectionInvocationIdFactory.create(),
|
|
3077
|
-
connectionNodeId: plannedToolCall.nodeId,
|
|
3078
|
-
parentAgentNodeId: ctx.nodeId,
|
|
3079
|
-
parentAgentActivationId: ctx.activationId,
|
|
3080
|
-
status: "completed",
|
|
3081
|
-
managedInput: this.toolCallInputToJson(plannedToolCall.toolCall.input),
|
|
3082
|
-
managedOutput: this.resultToJsonValue(result),
|
|
3083
|
-
finishedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3084
|
-
});
|
|
3085
|
-
return {
|
|
3086
|
-
toolName: plannedToolCall.binding.config.name,
|
|
3087
|
-
toolCallId: plannedToolCall.toolCall.id ?? plannedToolCall.binding.config.name,
|
|
3088
|
-
serialized,
|
|
3089
|
-
result
|
|
3090
|
-
};
|
|
3091
|
-
} catch (error) {
|
|
3092
|
-
throw await this.failTrackedNodeInvocation(error, plannedToolCall.nodeId, ctx, toolCallInputsByPort, this.toolCallInputToJson(plannedToolCall.toolCall.input));
|
|
3093
|
-
}
|
|
3094
|
-
}));
|
|
3095
|
-
const rejected = results.find((result) => result.status === "rejected");
|
|
3096
|
-
if (rejected?.status === "rejected") throw rejected.reason instanceof Error ? rejected.reason : new Error(String(rejected.reason));
|
|
3097
|
-
return results.filter((result) => result.status === "fulfilled").map((result) => result.value);
|
|
3098
|
-
}
|
|
3099
3662
|
planToolCalls(bindings, toolCalls, parentNodeId) {
|
|
3100
3663
|
const invocationCountByToolName = /* @__PURE__ */ new Map();
|
|
3101
3664
|
return toolCalls.map((toolCall) => {
|
|
@@ -3111,35 +3674,31 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
3111
3674
|
};
|
|
3112
3675
|
});
|
|
3113
3676
|
}
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
}
|
|
3122
|
-
async failTrackedNodeInvocation(error, nodeId, ctx, inputsByPort, managedInput) {
|
|
3123
|
-
const effectiveError = error instanceof Error ? error : new Error(String(error));
|
|
3124
|
-
await ctx.nodeState?.markFailed({
|
|
3125
|
-
nodeId,
|
|
3126
|
-
activationId: ctx.activationId,
|
|
3127
|
-
inputsByPort,
|
|
3677
|
+
async failTrackedNodeInvocation(args) {
|
|
3678
|
+
const effectiveError = args.error instanceof Error ? args.error : new Error(String(args.error));
|
|
3679
|
+
const finishedAt = /* @__PURE__ */ new Date();
|
|
3680
|
+
await args.ctx.nodeState?.markFailed({
|
|
3681
|
+
nodeId: args.nodeId,
|
|
3682
|
+
activationId: args.ctx.activationId,
|
|
3683
|
+
inputsByPort: args.inputsByPort,
|
|
3128
3684
|
error: effectiveError
|
|
3129
3685
|
});
|
|
3130
|
-
await ctx.nodeState?.appendConnectionInvocation({
|
|
3131
|
-
invocationId:
|
|
3132
|
-
connectionNodeId: nodeId,
|
|
3133
|
-
parentAgentNodeId: ctx.nodeId,
|
|
3134
|
-
parentAgentActivationId: ctx.activationId,
|
|
3686
|
+
await args.ctx.nodeState?.appendConnectionInvocation({
|
|
3687
|
+
invocationId: args.invocationId,
|
|
3688
|
+
connectionNodeId: args.nodeId,
|
|
3689
|
+
parentAgentNodeId: args.ctx.nodeId,
|
|
3690
|
+
parentAgentActivationId: args.ctx.activationId,
|
|
3135
3691
|
status: "failed",
|
|
3136
|
-
managedInput,
|
|
3692
|
+
managedInput: args.managedInput,
|
|
3137
3693
|
error: {
|
|
3138
3694
|
message: effectiveError.message,
|
|
3139
3695
|
name: effectiveError.name,
|
|
3140
|
-
stack: effectiveError.stack
|
|
3696
|
+
stack: effectiveError.stack,
|
|
3697
|
+
details: this.extractErrorDetails(effectiveError)
|
|
3141
3698
|
},
|
|
3142
|
-
|
|
3699
|
+
queuedAt: args.startedAt.toISOString(),
|
|
3700
|
+
startedAt: args.startedAt.toISOString(),
|
|
3701
|
+
finishedAt: finishedAt.toISOString()
|
|
3143
3702
|
});
|
|
3144
3703
|
return effectiveError;
|
|
3145
3704
|
}
|
|
@@ -3151,9 +3710,6 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
3151
3710
|
lastMessagePreview: preview.slice(0, 4e3)
|
|
3152
3711
|
};
|
|
3153
3712
|
}
|
|
3154
|
-
toolCallInputToJson(input) {
|
|
3155
|
-
return this.resultToJsonValue(input);
|
|
3156
|
-
}
|
|
3157
3713
|
resultToJsonValue(value) {
|
|
3158
3714
|
if (value === void 0) return;
|
|
3159
3715
|
const json = JSON.stringify(value);
|
|
@@ -3223,6 +3779,9 @@ let AIAgentNode = class AIAgentNode$1 {
|
|
|
3223
3779
|
getAgentDisplayName(ctx) {
|
|
3224
3780
|
return ctx.config.name ?? ctx.nodeId;
|
|
3225
3781
|
}
|
|
3782
|
+
extractErrorDetails(error) {
|
|
3783
|
+
return error.details;
|
|
3784
|
+
}
|
|
3226
3785
|
};
|
|
3227
3786
|
AIAgentNode = __decorate([
|
|
3228
3787
|
(0, __codemation_core.node)({ packageName: "@codemation/core-nodes" }),
|
|
@@ -3231,12 +3790,14 @@ AIAgentNode = __decorate([
|
|
|
3231
3790
|
__decorateParam(2, (0, __codemation_core.inject)(NodeBackedToolRuntime)),
|
|
3232
3791
|
__decorateParam(3, (0, __codemation_core.inject)(AIAgentExecutionHelpersFactory)),
|
|
3233
3792
|
__decorateParam(4, (0, __codemation_core.inject)(AgentStructuredOutputRunner)),
|
|
3793
|
+
__decorateParam(5, (0, __codemation_core.inject)(AgentToolExecutionCoordinator)),
|
|
3234
3794
|
__decorateMetadata("design:paramtypes", [
|
|
3235
3795
|
Object,
|
|
3236
3796
|
Object,
|
|
3237
3797
|
typeof (_ref = typeof NodeBackedToolRuntime !== "undefined" && NodeBackedToolRuntime) === "function" ? _ref : Object,
|
|
3238
3798
|
typeof (_ref2 = typeof AIAgentExecutionHelpersFactory !== "undefined" && AIAgentExecutionHelpersFactory) === "function" ? _ref2 : Object,
|
|
3239
|
-
typeof (_ref3 = typeof AgentStructuredOutputRunner !== "undefined" && AgentStructuredOutputRunner) === "function" ? _ref3 : Object
|
|
3799
|
+
typeof (_ref3 = typeof AgentStructuredOutputRunner !== "undefined" && AgentStructuredOutputRunner) === "function" ? _ref3 : Object,
|
|
3800
|
+
typeof (_ref4 = typeof AgentToolExecutionCoordinator !== "undefined" && AgentToolExecutionCoordinator) === "function" ? _ref4 : Object
|
|
3240
3801
|
])
|
|
3241
3802
|
], AIAgentNode);
|
|
3242
3803
|
|
|
@@ -3458,6 +4019,7 @@ var Aggregate = class {
|
|
|
3458
4019
|
kind = "node";
|
|
3459
4020
|
type = AggregateNode;
|
|
3460
4021
|
execution = { hint: "local" };
|
|
4022
|
+
keepBinaries = true;
|
|
3461
4023
|
icon = "lucide:layers";
|
|
3462
4024
|
constructor(name, aggregate, id) {
|
|
3463
4025
|
this.name = name;
|
|
@@ -3612,6 +4174,7 @@ var Split = class {
|
|
|
3612
4174
|
kind = "node";
|
|
3613
4175
|
type = SplitNode;
|
|
3614
4176
|
execution = { hint: "local" };
|
|
4177
|
+
keepBinaries = true;
|
|
3615
4178
|
/**
|
|
3616
4179
|
* When splitting yields zero items for a batch, downstream single-input nodes still run once with an empty batch.
|
|
3617
4180
|
* Mirrors {@link MapData}'s empty-output behavior.
|
|
@@ -4321,6 +4884,25 @@ Object.defineProperty(exports, 'AgentStructuredOutputRunner', {
|
|
|
4321
4884
|
}
|
|
4322
4885
|
});
|
|
4323
4886
|
exports.AgentToolCallPortMap = AgentToolCallPortMap;
|
|
4887
|
+
Object.defineProperty(exports, 'AgentToolErrorClassifier', {
|
|
4888
|
+
enumerable: true,
|
|
4889
|
+
get: function () {
|
|
4890
|
+
return AgentToolErrorClassifier;
|
|
4891
|
+
}
|
|
4892
|
+
});
|
|
4893
|
+
Object.defineProperty(exports, 'AgentToolExecutionCoordinator', {
|
|
4894
|
+
enumerable: true,
|
|
4895
|
+
get: function () {
|
|
4896
|
+
return AgentToolExecutionCoordinator;
|
|
4897
|
+
}
|
|
4898
|
+
});
|
|
4899
|
+
exports.AgentToolRepairExhaustedError = AgentToolRepairExhaustedError;
|
|
4900
|
+
Object.defineProperty(exports, 'AgentToolRepairPolicy', {
|
|
4901
|
+
enumerable: true,
|
|
4902
|
+
get: function () {
|
|
4903
|
+
return AgentToolRepairPolicy;
|
|
4904
|
+
}
|
|
4905
|
+
});
|
|
4324
4906
|
exports.Aggregate = Aggregate;
|
|
4325
4907
|
Object.defineProperty(exports, 'AggregateNode', {
|
|
4326
4908
|
enumerable: true,
|