import type { AgentEvent } from './api' /** 合并重连批次并按事件主键去重。 */ export function appendUniqueEvents(current: AgentEvent[], incoming: AgentEvent[]) { if (!incoming.length) return current const lastId = current.at(-1)?.id if (lastId == null || incoming[0].id > lastId) return current.concat(incoming) const ids = new Set(current.map(event => event.id)) return current.concat(incoming.filter(event => !ids.has(event.id))) } /** 新工具使用结构化状态;解码 SDK 包装后兼容已保存的旧事件。 */ export function parseToolResult(content: unknown, toolName: string) { let value = content for (let i = 0; i < 2 && typeof value === 'string'; i++) { try { value = JSON.parse(value) } catch { break } } const text = typeof value === 'string' ? value : JSON.stringify(value) ?? '' if ((toolName === 'execute' || toolName === 'edit_file') && value && typeof value === 'object') { const result = value as Record if (typeof result.success === 'boolean') return { text, failed: !result.success } if (typeof result.exitCode === 'number') return { text, failed: result.exitCode !== 0 } if (result.isError === true || result.error) return { text, failed: true } } if (toolName === 'document_view' && text.includes('document_view_result=')) { try { const metadata = JSON.parse(text.split('document_view_result=')[1]!.split('\n')[0]!) if (Array.isArray(metadata.errors) && metadata.errors.length) return { text, failed: true } } catch { return { text, failed: true } } } const error = /(?:执行失败|(?:^|\n)\s*(?:error:|failed\b|exit code:\s*-?[1-9]))/i.test(text.trim()) const legacyShellError = toolName === 'execute' && /(?:^|\n)(?:\w*Error:|Traceback \(most recent call last\):)/.test(text) return { text, failed: error || legacyShellError } }