fix(tools): classify body snapshot failures

This commit is contained in:
Tianyi Cui
2026-07-22 02:02:46 +08:00
parent a6e4bc7bcb
commit fb5292cee5
2 changed files with 36 additions and 5 deletions

View File

@@ -405,6 +405,18 @@ function snapshotProjection<T>(toolName: string, projector: 'render' | 'presenta
}
}
/** Snapshot one body or policy value into the canonical invalid-output failure class. */
function snapshotToolValue(toolName: string, candidate: unknown): JsonValue {
try {
const detached = snapshotJsonValue(candidate)
if (detached === undefined) throw new ToolOutputError(toolName, ['value is not lossless JSON'])
return detached as JsonValue
} catch (error: unknown) {
if (error instanceof ToolOutputError) throw error
throw new ToolOutputError(toolName, [`value snapshot failed: ${errorMessage(error)}`])
}
}
/** Successful canonical tool execution, including its Native/model projection. */
export interface ToolExecutionSuccess {
readonly isError: false
@@ -1316,13 +1328,10 @@ export class ToolRegistry extends Service {
/** Snapshot, validate, render, and optionally project one successful body value. */
private createSuccessResult(exec: ToolExecution, tool: ToolDefinition, candidate: unknown): ToolExecutionSuccess {
const detached = snapshotJsonValue(candidate)
if (detached === undefined) {
throw new ToolOutputError(tool.name, ['value is not lossless JSON'])
}
const detached = snapshotToolValue(tool.name, candidate)
const violations = validateJsonSchemaValue(tool.output.schema, detached, 'value')
if (violations.length > 0) throw new ToolOutputError(tool.name, violations)
const value = deepFreeze(detached as JsonValue)
const value = deepFreeze(detached)
let rendered: ContentBlock[]
try {
rendered = tool.output.render(exec.arguments, value)