@axlsdk/axl 0.19.0 → 0.19.1
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/README.md +5 -0
- package/dist/index.cjs +287 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +286 -54
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -162,9 +162,14 @@ const calculator = tool({
|
|
|
162
162
|
// handler also accepts (input, ctx) for nested agent invocations — see below
|
|
163
163
|
retry: { attempts: 3, backoff: 'exponential' },
|
|
164
164
|
sensitive: false,
|
|
165
|
+
// Keep the complete handler result for the host while sending only this
|
|
166
|
+
// allowlisted projection back to the model:
|
|
167
|
+
toModelOutput: (result) => ({ answer: result.result }),
|
|
165
168
|
});
|
|
166
169
|
```
|
|
167
170
|
|
|
171
|
+
`toModelOutput` is an opt-in, synchronous mapper for successful agent-invoked local tools. Strings are sent verbatim; JSON-compatible values are strictly validated and serialized once. The full post-hook result stays on `tool_call_end.data.result` for host rendering (subject to `trace.redact`). `sensitive: true` and thrown handler/hook/mock failures skip projection, and projection errors fail closed with `ToolModelOutputError`—there is no raw fallback. Direct `tool.run()`/`_execute()`, MCP tools, and handoffs are unchanged. See the [API reference](../../docs/api-reference.md#model-facing-tool-output) for the exact type, validation, mock, and delivery contract.
|
|
172
|
+
|
|
168
173
|
Tool handlers receive a second parameter `ctx: WorkflowContext` (a child context), enabling the "agent-as-tool" composition pattern:
|
|
169
174
|
|
|
170
175
|
```typescript
|
package/dist/index.cjs
CHANGED
|
@@ -159,6 +159,7 @@ __export(index_exports, {
|
|
|
159
159
|
ThinkTagScanner: () => ThinkTagScanner,
|
|
160
160
|
TimeoutError: () => TimeoutError,
|
|
161
161
|
ToolDenied: () => ToolDenied,
|
|
162
|
+
ToolModelOutputError: () => ToolModelOutputError,
|
|
162
163
|
VLLM_PROFILE: () => VLLM_PROFILE,
|
|
163
164
|
ValidationError: () => ValidationError,
|
|
164
165
|
VerifyError: () => VerifyError,
|
|
@@ -272,6 +273,7 @@ function tool(config) {
|
|
|
272
273
|
retry: retryPolicy,
|
|
273
274
|
requireApproval: config.requireApproval ?? false,
|
|
274
275
|
hooks: config.hooks,
|
|
276
|
+
...config.toModelOutput !== void 0 ? { toModelOutput: config.toModelOutput } : {},
|
|
275
277
|
async run(ctx, input) {
|
|
276
278
|
const startTime = Date.now();
|
|
277
279
|
try {
|
|
@@ -333,6 +335,17 @@ var AxlError = class extends Error {
|
|
|
333
335
|
this.code = code;
|
|
334
336
|
}
|
|
335
337
|
};
|
|
338
|
+
var ToolModelOutputError = class extends AxlError {
|
|
339
|
+
toolName;
|
|
340
|
+
cause;
|
|
341
|
+
constructor(toolName, cause) {
|
|
342
|
+
super("TOOL_MODEL_OUTPUT_ERROR", `Failed to prepare model output for tool "${toolName}"`);
|
|
343
|
+
this.name = "ToolModelOutputError";
|
|
344
|
+
this.toolName = toolName;
|
|
345
|
+
this.cause = cause;
|
|
346
|
+
Object.defineProperty(this, "cause", { enumerable: false });
|
|
347
|
+
}
|
|
348
|
+
};
|
|
336
349
|
var VerifyError = class extends AxlError {
|
|
337
350
|
lastOutput;
|
|
338
351
|
zodError;
|
|
@@ -2353,6 +2366,15 @@ function sanitizeSchemaForGemini(schema) {
|
|
|
2353
2366
|
}
|
|
2354
2367
|
return out;
|
|
2355
2368
|
}
|
|
2369
|
+
function parseGeminiFunctionResponse(content) {
|
|
2370
|
+
let parsed;
|
|
2371
|
+
try {
|
|
2372
|
+
parsed = JSON.parse(content);
|
|
2373
|
+
} catch {
|
|
2374
|
+
return { result: content };
|
|
2375
|
+
}
|
|
2376
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : { result: parsed };
|
|
2377
|
+
}
|
|
2356
2378
|
var GEMINI_PRICING = {
|
|
2357
2379
|
"gemini-2.5-pro": [125e-8, 1e-5],
|
|
2358
2380
|
"gemini-2.5-flash": [3e-7, 25e-7],
|
|
@@ -2688,15 +2710,9 @@ var GeminiProvider = class {
|
|
|
2688
2710
|
}
|
|
2689
2711
|
} else if (msg.role === "tool") {
|
|
2690
2712
|
const functionName = toolCallIdToName.get(msg.tool_call_id) ?? "unknown";
|
|
2691
|
-
let responseData;
|
|
2692
|
-
try {
|
|
2693
|
-
responseData = JSON.parse(msg.content);
|
|
2694
|
-
} catch {
|
|
2695
|
-
responseData = { result: msg.content };
|
|
2696
|
-
}
|
|
2697
2713
|
const functionResponse = {
|
|
2698
2714
|
name: functionName,
|
|
2699
|
-
response:
|
|
2715
|
+
response: parseGeminiFunctionResponse(msg.content)
|
|
2700
2716
|
};
|
|
2701
2717
|
if (msg.tool_call_id && geminiNativeIds.has(msg.tool_call_id)) {
|
|
2702
2718
|
functionResponse.id = msg.tool_call_id;
|
|
@@ -4926,8 +4942,191 @@ function resolveConfig(config) {
|
|
|
4926
4942
|
return resolved;
|
|
4927
4943
|
}
|
|
4928
4944
|
|
|
4945
|
+
// src/tool-model-output.ts
|
|
4946
|
+
var import_node_util = require("util");
|
|
4947
|
+
function invalid(path, reason) {
|
|
4948
|
+
return new Error(`Invalid tool model output at ${path}: ${reason}`);
|
|
4949
|
+
}
|
|
4950
|
+
function propertyPath(parent, key) {
|
|
4951
|
+
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) return `${parent}.${key}`;
|
|
4952
|
+
let escaped = "";
|
|
4953
|
+
for (const character of key) {
|
|
4954
|
+
const code = character.charCodeAt(0);
|
|
4955
|
+
if (character === "\\" || character === '"') escaped += `\\${character}`;
|
|
4956
|
+
else if (code <= 31 || code === 8232 || code === 8233) {
|
|
4957
|
+
escaped += `\\u${code.toString(16).padStart(4, "0")}`;
|
|
4958
|
+
} else escaped += character;
|
|
4959
|
+
}
|
|
4960
|
+
return `${parent}["${escaped}"]`;
|
|
4961
|
+
}
|
|
4962
|
+
function normalize(value, path, stack) {
|
|
4963
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
4964
|
+
if (typeof value === "number") {
|
|
4965
|
+
if (!Number.isFinite(value)) throw invalid(path, "number must be finite");
|
|
4966
|
+
return value;
|
|
4967
|
+
}
|
|
4968
|
+
if (value === void 0) throw invalid(path, "undefined is only allowed on object properties");
|
|
4969
|
+
if (typeof value === "bigint" || typeof value === "function" || typeof value === "symbol") {
|
|
4970
|
+
throw invalid(path, `unsupported ${typeof value}`);
|
|
4971
|
+
}
|
|
4972
|
+
if (typeof value !== "object") throw invalid(path, `unsupported ${typeof value}`);
|
|
4973
|
+
let prototype;
|
|
4974
|
+
let descriptors;
|
|
4975
|
+
try {
|
|
4976
|
+
prototype = Object.getPrototypeOf(value);
|
|
4977
|
+
descriptors = Object.getOwnPropertyDescriptors(value);
|
|
4978
|
+
Object.setPrototypeOf(descriptors, null);
|
|
4979
|
+
} catch (cause) {
|
|
4980
|
+
throw invalid(
|
|
4981
|
+
path,
|
|
4982
|
+
`object inspection failed (${cause instanceof Error ? cause.name : "error"})`
|
|
4983
|
+
);
|
|
4984
|
+
}
|
|
4985
|
+
if (stack.has(value)) throw invalid(path, "cyclic reference");
|
|
4986
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
4987
|
+
const descriptor = descriptors[key];
|
|
4988
|
+
if (descriptor && !("value" in descriptor)) {
|
|
4989
|
+
throw invalid(
|
|
4990
|
+
typeof key === "string" ? propertyPath(path, key) : `${path}[symbol]`,
|
|
4991
|
+
"accessor properties are not supported"
|
|
4992
|
+
);
|
|
4993
|
+
}
|
|
4994
|
+
if (typeof key === "symbol" && descriptor?.enumerable) {
|
|
4995
|
+
throw invalid(`${path}[symbol]`, "enumerable symbol keys are not supported");
|
|
4996
|
+
}
|
|
4997
|
+
}
|
|
4998
|
+
if (typeof descriptors.toJSON?.value === "function") {
|
|
4999
|
+
throw invalid(propertyPath(path, "toJSON"), "custom toJSON is not supported");
|
|
5000
|
+
}
|
|
5001
|
+
const array = Array.isArray(value);
|
|
5002
|
+
if (array && prototype !== Array.prototype && prototype !== null) {
|
|
5003
|
+
throw invalid(path, "array subclasses are not supported");
|
|
5004
|
+
}
|
|
5005
|
+
const inheritedToJSON = prototype === Array.prototype || prototype === Object.prototype ? Object.getOwnPropertyDescriptor(prototype, "toJSON") : void 0;
|
|
5006
|
+
if (typeof inheritedToJSON?.value === "function") {
|
|
5007
|
+
throw invalid(propertyPath(path, "toJSON"), "inherited custom toJSON is not supported");
|
|
5008
|
+
}
|
|
5009
|
+
const inheritedThen = prototype === Array.prototype || prototype === Object.prototype ? Object.getOwnPropertyDescriptor(prototype, "then") : void 0;
|
|
5010
|
+
if (typeof descriptors.then?.value === "function" || inheritedThen !== void 0 && (!("value" in inheritedThen) || typeof inheritedThen.value === "function")) {
|
|
5011
|
+
throw invalid(path, "thenable output is not supported");
|
|
5012
|
+
}
|
|
5013
|
+
stack.add(value);
|
|
5014
|
+
try {
|
|
5015
|
+
if (array) {
|
|
5016
|
+
const normalized2 = [];
|
|
5017
|
+
const length = descriptors.length?.value;
|
|
5018
|
+
if (!Number.isSafeInteger(length) || length < 0) {
|
|
5019
|
+
throw invalid(propertyPath(path, "length"), "array length is invalid");
|
|
5020
|
+
}
|
|
5021
|
+
for (let index = 0; index < length; index++) {
|
|
5022
|
+
const descriptor = descriptors[String(index)];
|
|
5023
|
+
if (!descriptor || !("value" in descriptor)) {
|
|
5024
|
+
throw invalid(`${path}[${index}]`, "arrays must be dense data properties");
|
|
5025
|
+
}
|
|
5026
|
+
if (descriptor.value === void 0) {
|
|
5027
|
+
throw invalid(`${path}[${index}]`, "array values cannot be undefined");
|
|
5028
|
+
}
|
|
5029
|
+
normalized2.push(normalize(descriptor.value, `${path}[${index}]`, stack));
|
|
5030
|
+
}
|
|
5031
|
+
for (const key of Object.keys(descriptors)) {
|
|
5032
|
+
const descriptor = descriptors[key];
|
|
5033
|
+
if (!descriptor?.enumerable) continue;
|
|
5034
|
+
const index = Number(key);
|
|
5035
|
+
if (!Number.isInteger(index) || index < 0 || index >= length || String(index) !== key) {
|
|
5036
|
+
throw invalid(propertyPath(path, key), "non-index array properties are not supported");
|
|
5037
|
+
}
|
|
5038
|
+
}
|
|
5039
|
+
Object.setPrototypeOf(normalized2, null);
|
|
5040
|
+
return normalized2;
|
|
5041
|
+
}
|
|
5042
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
5043
|
+
throw invalid(path, "only plain objects and null-prototype records are supported");
|
|
5044
|
+
}
|
|
5045
|
+
const normalized = /* @__PURE__ */ Object.create(null);
|
|
5046
|
+
for (const key of Object.keys(descriptors)) {
|
|
5047
|
+
const descriptor = descriptors[key];
|
|
5048
|
+
if (!descriptor?.enumerable) continue;
|
|
5049
|
+
if (!("value" in descriptor)) {
|
|
5050
|
+
throw invalid(propertyPath(path, key), "accessor properties are not supported");
|
|
5051
|
+
}
|
|
5052
|
+
if (descriptor.value === void 0) continue;
|
|
5053
|
+
normalized[key] = normalize(descriptor.value, propertyPath(path, key), stack);
|
|
5054
|
+
}
|
|
5055
|
+
return normalized;
|
|
5056
|
+
} finally {
|
|
5057
|
+
stack.delete(value);
|
|
5058
|
+
}
|
|
5059
|
+
}
|
|
5060
|
+
function serializeToolModelOutput(toolName, output) {
|
|
5061
|
+
try {
|
|
5062
|
+
if (import_node_util.types.isPromise(output)) {
|
|
5063
|
+
void Promise.prototype.then.call(output, void 0, () => void 0);
|
|
5064
|
+
}
|
|
5065
|
+
if (typeof output === "string") return output;
|
|
5066
|
+
return JSON.stringify(normalize(output, "$", /* @__PURE__ */ new WeakSet()));
|
|
5067
|
+
} catch (cause) {
|
|
5068
|
+
throw new ToolModelOutputError(toolName, cause);
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
|
|
4929
5072
|
// src/context.ts
|
|
4930
5073
|
var signalStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
5074
|
+
function isErrorShaped(value) {
|
|
5075
|
+
return value !== null && typeof value === "object" && "error" in value;
|
|
5076
|
+
}
|
|
5077
|
+
function isErrorShapedSafely(value) {
|
|
5078
|
+
try {
|
|
5079
|
+
return isErrorShaped(value);
|
|
5080
|
+
} catch {
|
|
5081
|
+
return false;
|
|
5082
|
+
}
|
|
5083
|
+
}
|
|
5084
|
+
function recordToolSpanResult(span, value, suppressInspectionErrors) {
|
|
5085
|
+
let isError = false;
|
|
5086
|
+
let errorMessage;
|
|
5087
|
+
const inspect = () => {
|
|
5088
|
+
if (isErrorShaped(value)) {
|
|
5089
|
+
isError = true;
|
|
5090
|
+
errorMessage = value.error;
|
|
5091
|
+
} else {
|
|
5092
|
+
isError = false;
|
|
5093
|
+
}
|
|
5094
|
+
};
|
|
5095
|
+
if (suppressInspectionErrors) {
|
|
5096
|
+
try {
|
|
5097
|
+
inspect();
|
|
5098
|
+
} catch {
|
|
5099
|
+
isError = false;
|
|
5100
|
+
errorMessage = void 0;
|
|
5101
|
+
}
|
|
5102
|
+
} else {
|
|
5103
|
+
inspect();
|
|
5104
|
+
}
|
|
5105
|
+
span.setAttribute("axl.tool.success", !isError);
|
|
5106
|
+
if (isError) span.setStatus("error", errorMessage);
|
|
5107
|
+
}
|
|
5108
|
+
function prepareToolModelOutput(toolName, project) {
|
|
5109
|
+
let output;
|
|
5110
|
+
try {
|
|
5111
|
+
output = project();
|
|
5112
|
+
} catch (cause) {
|
|
5113
|
+
throw new ToolModelOutputError(toolName, cause);
|
|
5114
|
+
}
|
|
5115
|
+
return serializeToolModelOutput(toolName, output);
|
|
5116
|
+
}
|
|
5117
|
+
function finalizeToolResult(options) {
|
|
5118
|
+
const { toolName, configuredTool, outcome, legacyContent, emitEnd, beforeProjection } = options;
|
|
5119
|
+
const projectionEligible = configuredTool !== void 0 && !configuredTool.sensitive && outcome.kind === "returned" && configuredTool.toModelOutput !== void 0;
|
|
5120
|
+
if (projectionEligible) {
|
|
5121
|
+
emitEnd();
|
|
5122
|
+
beforeProjection();
|
|
5123
|
+
const project = configuredTool.toModelOutput;
|
|
5124
|
+
return prepareToolModelOutput(toolName, () => project(outcome.value));
|
|
5125
|
+
}
|
|
5126
|
+
const content = legacyContent();
|
|
5127
|
+
emitEnd();
|
|
5128
|
+
return content;
|
|
5129
|
+
}
|
|
4931
5130
|
var askStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
4932
5131
|
var inlineSchemaCache = /* @__PURE__ */ new WeakMap();
|
|
4933
5132
|
function zodToJsonSchema(schema) {
|
|
@@ -5622,6 +5821,7 @@ ${appendedSchemaText}`;
|
|
|
5622
5821
|
let lastStartAttempt = 1;
|
|
5623
5822
|
let lastStartMaxAttempts = 1;
|
|
5624
5823
|
while (turns < maxTurns) {
|
|
5824
|
+
this.currentSignal?.throwIfAborted();
|
|
5625
5825
|
if (Date.now() - startTime > timeoutMs) {
|
|
5626
5826
|
throw new TimeoutError("ctx.ask()", timeoutMs);
|
|
5627
5827
|
}
|
|
@@ -5723,6 +5923,7 @@ ${appendedSchemaText}`;
|
|
|
5723
5923
|
this.onAgentStart?.({ agent: agent2._name, model: modelUri }, callbackMeta);
|
|
5724
5924
|
let response;
|
|
5725
5925
|
try {
|
|
5926
|
+
this.currentSignal?.throwIfAborted();
|
|
5726
5927
|
if (this._streamingEnabled) {
|
|
5727
5928
|
let content2 = "";
|
|
5728
5929
|
const toolCalls = [];
|
|
@@ -6024,6 +6225,8 @@ ${appendedSchemaText}`;
|
|
|
6024
6225
|
return await handoffFn();
|
|
6025
6226
|
}
|
|
6026
6227
|
}
|
|
6228
|
+
const tool2 = agent2._config.tools?.find((candidate) => candidate.name === toolName);
|
|
6229
|
+
const isMcpTool = !tool2 && this.mcpManager?.isMcpTool(toolName);
|
|
6027
6230
|
const toolOverride = this.toolOverrides?.get(toolName);
|
|
6028
6231
|
if (toolOverride) {
|
|
6029
6232
|
let toolArgs2;
|
|
@@ -6048,38 +6251,47 @@ ${appendedSchemaText}`;
|
|
|
6048
6251
|
callbackMeta
|
|
6049
6252
|
);
|
|
6050
6253
|
const toolStart2 = Date.now();
|
|
6254
|
+
const suppressErrorShapeInspection2 = tool2?.sensitive === true || tool2?.toModelOutput !== void 0;
|
|
6051
6255
|
const executeOverride = async () => {
|
|
6052
|
-
let toolResult3;
|
|
6053
6256
|
try {
|
|
6054
|
-
|
|
6257
|
+
return { kind: "returned", value: await toolOverride(toolArgs2) };
|
|
6055
6258
|
} catch (err) {
|
|
6056
|
-
|
|
6259
|
+
return {
|
|
6260
|
+
kind: "thrown",
|
|
6261
|
+
value: { error: err instanceof Error ? err.message : String(err) }
|
|
6262
|
+
};
|
|
6057
6263
|
}
|
|
6058
|
-
return toolResult3;
|
|
6059
6264
|
};
|
|
6060
|
-
const
|
|
6265
|
+
const outcome = this.spanManager ? await this.spanManager.withSpanAsync(
|
|
6061
6266
|
"axl.tool.call",
|
|
6062
6267
|
{
|
|
6063
6268
|
"axl.tool.name": toolName,
|
|
6064
6269
|
"axl.agent.name": agent2._name
|
|
6065
6270
|
},
|
|
6066
6271
|
async (span) => {
|
|
6067
|
-
const
|
|
6272
|
+
const result = await executeOverride();
|
|
6068
6273
|
span.setAttribute("axl.tool.duration", Date.now() - toolStart2);
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
if (isError)
|
|
6072
|
-
span.setStatus("error", r.error);
|
|
6073
|
-
return r;
|
|
6274
|
+
recordToolSpanResult(span, result.value, suppressErrorShapeInspection2);
|
|
6275
|
+
return result;
|
|
6074
6276
|
}
|
|
6075
6277
|
) : await executeOverride();
|
|
6076
|
-
const
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6278
|
+
const toolResult2 = outcome.value;
|
|
6279
|
+
const resultContent2 = finalizeToolResult({
|
|
6280
|
+
toolName,
|
|
6281
|
+
configuredTool: tool2,
|
|
6282
|
+
outcome,
|
|
6283
|
+
legacyContent: () => tool2?.sensitive ? "[REDACTED - sensitive tool output]" : JSON.stringify(toolResult2),
|
|
6284
|
+
emitEnd: () => {
|
|
6285
|
+
const toolDuration2 = Date.now() - toolStart2;
|
|
6286
|
+
this.emitEvent({
|
|
6287
|
+
type: "tool_call_end",
|
|
6288
|
+
agent: agent2._name,
|
|
6289
|
+
tool: toolName,
|
|
6290
|
+
duration: toolDuration2,
|
|
6291
|
+
data: { args: toolArgs2, result: toolResult2, callId: toolCall.id }
|
|
6292
|
+
});
|
|
6293
|
+
},
|
|
6294
|
+
beforeProjection: () => this.currentSignal?.throwIfAborted()
|
|
6083
6295
|
});
|
|
6084
6296
|
currentMessages.push({
|
|
6085
6297
|
role: "tool",
|
|
@@ -6088,8 +6300,6 @@ ${appendedSchemaText}`;
|
|
|
6088
6300
|
});
|
|
6089
6301
|
continue;
|
|
6090
6302
|
}
|
|
6091
|
-
const tool2 = agent2._config.tools?.find((t) => t.name === toolName);
|
|
6092
|
-
const isMcpTool = !tool2 && this.mcpManager?.isMcpTool(toolName);
|
|
6093
6303
|
if (!tool2 && !isMcpTool) {
|
|
6094
6304
|
this.emitEvent({ type: "tool_denied", agent: agent2._name, tool: toolName });
|
|
6095
6305
|
currentMessages.push({
|
|
@@ -6118,6 +6328,7 @@ ${appendedSchemaText}`;
|
|
|
6118
6328
|
});
|
|
6119
6329
|
this.onToolCall?.({ name: toolName, args: toolArgs, callId: toolCall.id }, callbackMeta);
|
|
6120
6330
|
const toolStart = Date.now();
|
|
6331
|
+
const suppressErrorShapeInspection = tool2?.sensitive === true || tool2?.toModelOutput !== void 0;
|
|
6121
6332
|
if (tool2 && tool2.requireApproval) {
|
|
6122
6333
|
const approvalFn = async () => {
|
|
6123
6334
|
const decision = await this.awaitHuman({
|
|
@@ -6179,12 +6390,12 @@ ${appendedSchemaText}`;
|
|
|
6179
6390
|
}
|
|
6180
6391
|
}
|
|
6181
6392
|
const executeTool = async () => {
|
|
6182
|
-
let
|
|
6393
|
+
let outcome;
|
|
6183
6394
|
let resultContent2;
|
|
6184
6395
|
if (isMcpTool && this.mcpManager) {
|
|
6185
6396
|
try {
|
|
6186
6397
|
const mcpResult = await this.mcpManager.callTool(toolName, toolArgs);
|
|
6187
|
-
|
|
6398
|
+
outcome = { kind: "returned", value: mcpResult };
|
|
6188
6399
|
resultContent2 = mcpResult.content.map(
|
|
6189
6400
|
(c) => c.type === "text" ? c.text : `[${c.type}]`
|
|
6190
6401
|
).join("\n");
|
|
@@ -6192,34 +6403,50 @@ ${appendedSchemaText}`;
|
|
|
6192
6403
|
resultContent2 = `Error: ${resultContent2}`;
|
|
6193
6404
|
}
|
|
6194
6405
|
} catch (err) {
|
|
6195
|
-
|
|
6196
|
-
|
|
6406
|
+
outcome = {
|
|
6407
|
+
kind: "thrown",
|
|
6408
|
+
value: { error: err instanceof Error ? err.message : String(err) }
|
|
6409
|
+
};
|
|
6410
|
+
resultContent2 = JSON.stringify(outcome.value);
|
|
6197
6411
|
}
|
|
6198
6412
|
} else if (tool2) {
|
|
6199
6413
|
const childCtx = this.createChildContext();
|
|
6200
6414
|
try {
|
|
6201
|
-
|
|
6415
|
+
outcome = { kind: "returned", value: await tool2._execute(toolArgs, childCtx) };
|
|
6202
6416
|
} catch (err) {
|
|
6203
|
-
|
|
6417
|
+
outcome = {
|
|
6418
|
+
kind: "thrown",
|
|
6419
|
+
value: { error: err instanceof Error ? err.message : String(err) }
|
|
6420
|
+
};
|
|
6204
6421
|
}
|
|
6205
|
-
if (tool2.hooks?.after && !(
|
|
6422
|
+
if (outcome.kind === "returned" && tool2.hooks?.after && !(suppressErrorShapeInspection ? isErrorShapedSafely(outcome.value) : isErrorShaped(outcome.value))) {
|
|
6206
6423
|
try {
|
|
6207
|
-
|
|
6424
|
+
outcome = {
|
|
6425
|
+
kind: "returned",
|
|
6426
|
+
value: await tool2.hooks.after(outcome.value, this)
|
|
6427
|
+
};
|
|
6208
6428
|
} catch (err) {
|
|
6209
|
-
|
|
6210
|
-
|
|
6429
|
+
outcome = {
|
|
6430
|
+
kind: "thrown",
|
|
6431
|
+
value: {
|
|
6432
|
+
error: `After hook error: ${err instanceof Error ? err.message : String(err)}`
|
|
6433
|
+
}
|
|
6211
6434
|
};
|
|
6212
6435
|
}
|
|
6213
6436
|
}
|
|
6214
|
-
|
|
6437
|
+
if (tool2.sensitive) {
|
|
6438
|
+
resultContent2 = "[REDACTED - sensitive tool output]";
|
|
6439
|
+
} else if (outcome.kind === "thrown" || tool2.toModelOutput === void 0) {
|
|
6440
|
+
resultContent2 = JSON.stringify(outcome.value);
|
|
6441
|
+
}
|
|
6215
6442
|
} else {
|
|
6216
|
-
|
|
6443
|
+
outcome = { kind: "returned", value: void 0 };
|
|
6217
6444
|
resultContent2 = "Tool execution error";
|
|
6218
6445
|
}
|
|
6219
|
-
return {
|
|
6446
|
+
return { outcome, resultContent: resultContent2 };
|
|
6220
6447
|
};
|
|
6221
6448
|
const traceName = isMcpTool && this.mcpManager ? this.mcpManager.getQualifiedName(toolName) ?? toolName : toolName;
|
|
6222
|
-
const
|
|
6449
|
+
const execution = this.spanManager ? await this.spanManager.withSpanAsync(
|
|
6223
6450
|
"axl.tool.call",
|
|
6224
6451
|
{
|
|
6225
6452
|
"axl.tool.name": traceName,
|
|
@@ -6228,22 +6455,27 @@ ${appendedSchemaText}`;
|
|
|
6228
6455
|
async (span) => {
|
|
6229
6456
|
const r = await executeTool();
|
|
6230
6457
|
span.setAttribute("axl.tool.duration", Date.now() - toolStart);
|
|
6231
|
-
|
|
6232
|
-
span.setAttribute("axl.tool.success", !isError);
|
|
6233
|
-
if (isError)
|
|
6234
|
-
span.setStatus(
|
|
6235
|
-
"error",
|
|
6236
|
-
r.toolResult.error
|
|
6237
|
-
);
|
|
6458
|
+
recordToolSpanResult(span, r.outcome.value, suppressErrorShapeInspection);
|
|
6238
6459
|
return r;
|
|
6239
6460
|
}
|
|
6240
6461
|
) : await executeTool();
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6462
|
+
const toolResult = execution.outcome.value;
|
|
6463
|
+
const toolDuration = Date.now() - toolStart;
|
|
6464
|
+
const resultContent = finalizeToolResult({
|
|
6465
|
+
toolName,
|
|
6466
|
+
configuredTool: tool2,
|
|
6467
|
+
outcome: execution.outcome,
|
|
6468
|
+
legacyContent: () => execution.resultContent,
|
|
6469
|
+
emitEnd: () => {
|
|
6470
|
+
this.emitEvent({
|
|
6471
|
+
type: "tool_call_end",
|
|
6472
|
+
agent: agent2._name,
|
|
6473
|
+
tool: traceName,
|
|
6474
|
+
duration: toolDuration,
|
|
6475
|
+
data: { args: toolArgs, result: toolResult, callId: toolCall.id }
|
|
6476
|
+
});
|
|
6477
|
+
},
|
|
6478
|
+
beforeProjection: () => this.currentSignal?.throwIfAborted()
|
|
6247
6479
|
});
|
|
6248
6480
|
currentMessages.push({
|
|
6249
6481
|
role: "tool",
|
|
@@ -12108,6 +12340,7 @@ function cosineSimilarity2(a, b) {
|
|
|
12108
12340
|
ThinkTagScanner,
|
|
12109
12341
|
TimeoutError,
|
|
12110
12342
|
ToolDenied,
|
|
12343
|
+
ToolModelOutputError,
|
|
12111
12344
|
VLLM_PROFILE,
|
|
12112
12345
|
ValidationError,
|
|
12113
12346
|
VerifyError,
|