Files
ManuAgent/web-ui/packages/agent/src/eventUtils.ts

36 lines
1.8 KiB
TypeScript

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<string, unknown>
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 }
}