show chat run errors as agent messages (#887)

This commit is contained in:
ekko
2026-05-21 09:05:17 +08:00
committed by GitHub
parent 40109e9c42
commit 3612a76735
6 changed files with 157 additions and 46 deletions
@@ -264,6 +264,13 @@ class AgentClient {
onStatus?: (status: 'compressing' | 'replying' | 'ready') => void,
): Promise<void> {
logger.debug(`[AgentClients] ${this.name} mentioned by ${msg.senderName}: "${msg.content.slice(0, 50)}"`)
const runMessageId = groupMessageId(roomId, this.profile, this.name)
let partIndex = 0
let streamMessageId = groupMessagePartId(runMessageId, partIndex)
let currentContent = ''
let totalContent = ''
let reasoningContent = ''
let streamStarted = false
try {
// Notify room that agent is typing
this.startTyping(roomId)
@@ -335,12 +342,6 @@ class AgentClient {
const bridge = new AgentBridgeClient()
const sessionSeed = String(this.storage?.getRoom?.(roomId)?.sessionSeed || '0')
const sessionId = groupBridgeSessionId(roomId, this.profile, this.name, sessionSeed)
const runMessageId = groupMessageId(roomId, this.profile, this.name)
let partIndex = 0
let streamMessageId = groupMessagePartId(runMessageId, partIndex)
let currentContent = ''
let totalContent = ''
let reasoningContent = ''
const flushedAssistantParts = new Set<string>()
let lastChunk: AgentBridgeOutput | null = null
const started = await bridge.chat(
@@ -355,6 +356,7 @@ class AgentClient {
)
this.emitMessageStreamStart(roomId, streamMessageId)
streamStarted = true
for await (const chunk of bridge.streamOutput(started.run_id, { timeoutMs: 120000 })) {
lastChunk = chunk
reasoningContent += await this.recordBridgeEvents(roomId, chunk, () => streamMessageId, async () => {
@@ -373,6 +375,7 @@ class AgentClient {
partIndex += 1
streamMessageId = groupMessagePartId(runMessageId, partIndex)
this.emitMessageStreamStart(roomId, streamMessageId)
streamStarted = true
return toolBaseId
})
if (chunk.delta) {
@@ -384,6 +387,7 @@ class AgentClient {
if (lastChunk?.status === 'error') {
logger.error(`[AgentClients] ${this.name}: bridge response failed: ${lastChunk.error || 'unknown error'}`)
await this.sendAgentErrorMessage(roomId, streamMessageId, lastChunk.error || 'Run failed', msg, reasoningContent)
this.emitMessageStreamEnd(roomId, streamMessageId)
this.stopTyping(roomId)
onStatus?.('ready')
@@ -414,11 +418,35 @@ class AgentClient {
onStatus?.('ready')
} catch (err: any) {
logger.error(`[AgentClients] ${this.name}: error handling message: ${err.message}`)
try {
await this.sendAgentErrorMessage(roomId, streamMessageId, err, msg, reasoningContent)
if (streamStarted) this.emitMessageStreamEnd(roomId, streamMessageId)
} catch (sendErr: any) {
logger.warn(`[AgentClients] ${this.name}: failed to send error message: ${sendErr.message}`)
}
this.stopTyping(roomId)
onStatus?.('ready')
}
}
private async sendAgentErrorMessage(
roomId: string,
messageId: string,
error: unknown,
sourceMsg: MentionMessage,
reasoningContent = '',
): Promise<void> {
const detail = error instanceof Error ? error.message : String(error || 'Run failed')
const content = detail.startsWith('Error:') ? detail : `Error: ${detail}`
await this.sendMessage(roomId, content, messageId, {
role: 'assistant',
mentionDepth: nextMentionDepth(sourceMsg),
finish_reason: 'error',
reasoning: reasoningContent || null,
reasoning_content: reasoningContent || null,
})
}
private async recordBridgeEvents(
roomId: string,
chunk: AgentBridgeOutput,