30 lines
1.5 KiB
TypeScript
30 lines
1.5 KiB
TypeScript
import type { ChatMessage, ToolCallRecord } from '@shared/types'
|
|
import { getMessageParts } from '@shared/message-parts'
|
|
import type { WireMessage } from '../gateway'
|
|
|
|
/** Preserve ordered assistant/tool exchanges when using a stateless compatible gateway. */
|
|
export function assistantWireHistory(message: ChatMessage): WireMessage[] {
|
|
const messages: WireMessage[] = []
|
|
const parts = getMessageParts(message)
|
|
let text = ''
|
|
for (let index = 0; index < parts.length; index++) {
|
|
const part = parts[index]
|
|
if (part.type === 'text') { text += part.text; continue }
|
|
if (part.type !== 'tool') continue
|
|
const tools: ToolCallRecord[] = []
|
|
while (index < parts.length && parts[index].type === 'tool') {
|
|
const candidate = parts[index] as { type: 'tool'; toolId: string }
|
|
const tool = message.tools?.find((tool) => tool.id === candidate.toolId)
|
|
if (tool) tools.push(tool)
|
|
index++
|
|
}
|
|
index--
|
|
if (!tools.length) continue
|
|
messages.push({ role: 'assistant', content: text || null, tool_calls: tools.map((tool) => ({ id: tool.id, type: 'function', function: { name: tool.name, arguments: tool.argsRaw || '{}' } })) })
|
|
text = ''
|
|
for (const tool of tools) messages.push({ role: 'tool', tool_call_id: tool.id, content: tool.status === 'ok' ? tool.output ?? tool.summary ?? JSON.stringify(tool.result ?? '') : `ERROR (${tool.status}): ${tool.output ?? tool.summary ?? '工具未完成'}` })
|
|
}
|
|
if (text) messages.push({ role: 'assistant', content: text })
|
|
return messages
|
|
}
|