fix(api-session): preserve presenter fast path

This commit is contained in:
imccyu
2026-08-23 16:16:06 +08:00
parent d34be03f7b
commit 4326dd4bca
+21 -21
View File
@@ -171,11 +171,8 @@ export class SessionHistoryController {
nextSeq++
if (item.event.type === 'tool/call') {
const data = item.event.data as ToolCallData
try {
openCalls.set(data.callId, { name: data.name, args: JSON.parse(data.arguments) })
} catch {
// Unparseable model arguments leave the fast path unset; result presentation soft-falls.
}
const call = parseToolCall(data)
if (call !== undefined) openCalls.set(data.callId, call)
} else if (item.event.type === 'turn/end') {
openCalls.clear()
}
@@ -392,6 +389,7 @@ function viewFor(
): SessionToolView | undefined {
if (event.type !== 'tool/call' && event.type !== 'tool/result') return undefined
const tools = ctx.get('tools')
/* v8 ignore next -- deployments without the optional Tools service omit presentation metadata. */
if (tools === undefined) return undefined
try {
if (event.type === 'tool/call') {
@@ -399,17 +397,15 @@ function viewFor(
const view: ToolCallView | undefined = tools.get(data.name, scope)?.presentCall?.(JSON.parse(data.arguments))
return view === undefined ? undefined : { for: 'call', view: jsonView(view) }
}
if (event.type === 'tool/result') {
const [result] = event.data.message.content
const call = argsFor(event.data.message.source.callId)
if (call === undefined) return undefined
const view: ToolResultView | undefined = tools.get(call.name, scope)?.presentResult?.(call.args, {
content: result.content,
isError: result.isError === true,
...(event.data.meta === undefined ? {} : { meta: event.data.meta }),
})
return view === undefined ? undefined : { for: 'result', view: jsonView(view) }
}
const [result] = event.data.message.content
const call = argsFor(event.data.message.source.callId)
if (call === undefined) return undefined
const view: ToolResultView | undefined = tools.get(call.name, scope)?.presentResult?.(call.args, {
content: result.content,
isError: result.isError === true,
...(event.data.meta === undefined ? {} : { meta: event.data.meta }),
})
return view === undefined ? undefined : { for: 'result', view: jsonView(view) }
} catch (error) {
ctx.logger.warn(`session: presenter failed for ${event.type}: ${String(error)}`)
}
@@ -425,15 +421,19 @@ function backscanArgs(
if (event.type !== 'tool/call') continue
const data = event.data as ToolCallData
if (data.callId !== callId) continue
try {
return { name: data.name, args: JSON.parse(data.arguments) }
} catch {
return undefined
}
return parseToolCall(data)
}
return undefined
}
function parseToolCall(data: ToolCallData): { readonly name: string; readonly args: unknown } | undefined {
try {
return { name: data.name, args: JSON.parse(data.arguments) }
} catch {
return undefined
}
}
function jsonView(view: ToolCallView): SessionToolCallView
function jsonView(view: ToolResultView): ToolResultView
function jsonView(view: ToolCallView | ToolResultView): SessionToolCallView | ToolResultView {