fix(ai): preserve explicit tool errors

Promote resolved tool error flags through Pi's formal tool-result contract.
将工具返回的错误标记提升为 Pi 正式错误结果,避免错误被记为成功。
This commit is contained in:
Sanssssssssssssssss authored and digua committed 2026-08-28 22:33:10 +08:00
1 parent 90bf3b6400
commit e544392a83
2 files changed
+34

No files matched your search

@@ -282,6 +282,38 @@ describe('runAgentCore runtime contract', () => {
)
})
it('preserves explicit error flags returned by tools', async () => {
const events: AgentCoreEvent[] = []
const tool = createTool('failed_lookup', async () => ({
content: [{ type: 'text', text: 'lookup failed' }],
details: null,
isError: true,
}))
const result = await runAgentCore(
createOptions({
tools: [tool],
streamFn: createScriptedStream([
assistantMessage([{ type: 'toolCall', id: 'failed-lookup', name: 'failed_lookup', arguments: {} }], {
stopReason: 'toolUse',
}),
assistantMessage([{ type: 'text', text: 'Recovered' }]),
]),
onEvent: (event) => events.push(event),
})
)
const toolEnd = events.find((event) => event.type === 'tool_end')
const toolResult = result.finalMessages.find((message) => message.role === 'toolResult')
assert.deepEqual(
{
event: toolEnd?.type === 'tool_end' ? toolEnd.isError : undefined,
transcript: toolResult?.role === 'toolResult' ? toolResult.isError : undefined,
},
{ event: true, transcript: true }
)
})
it('disables tools and injects the final-answer steer message at the tool round limit', async () => {
let finalContext: Context | undefined
const tool = createTool('lookup', async () => ({
@@ -127,6 +127,8 @@ export async function runAgentCore(options: AgentCoreOptions): Promise<AgentCore
onConvertToLlm?.(filtered)
return filtered
},
afterToolCall: async ({ result }) =>
(result as { isError?: boolean }).isError === true ? { isError: true } : undefined,
prepareNextTurnWithContext: ({ context }) =>
hasReachedToolRoundLimit
? {