fix(cli): persist tool history for continuation / 保存工具历史供续聊

CLI dropped completed tool results from replay. Persist bounded results by call ID with error state.
CLI 续聊遗漏已完成的工具结果;按调用 ID 保存限长结果和错误状态。

Add SQLite reload regression for concurrent calls and truncated answers.
新增 SQLite 重载回归,覆盖并行调用与回答截断。
This commit is contained in:
Sanssssssssssssssss authored and digua committed 2026-09-21 11:19:53 +08:00
1 parent c48d2837f1
commit f72198f2c5
2 files changed
+121

No files matched your search

+27
View File
@@ -10,6 +10,7 @@ import type {
TokenUsageData,
} from '@openchatlab/node-runtime'
import type { ChartPayload, PathProvider } from '@openchatlab/core'
import { extractToolResultText, truncateToolResultText } from '@openchatlab/core'
import { getDefaultGeneralAssistantId } from '@openchatlab/shared-types'
import { createCliRunAgentStream } from './agent-stream-runner'
@@ -166,6 +167,7 @@ export async function runChatTurn(
const streamState: { error: Error | null } = { error: null }
const events: AgentStreamChunk[] = []
const contentBlocks: ContentBlock[] = []
const toolBlocks = new Map<string, Extract<ContentBlock, { type: 'tool' }>>()
let hasReplayContentBlocks = false
const runAgentStream = (deps.createRunAgentStream ?? createCliRunAgentStream)(deps.dbManager, deps.aiChatManager)
@@ -294,6 +296,31 @@ export async function runChatTurn(
appendChartBlocks(extractChartPayloads(chunk.toolResult))
return
}
if (chunk.type === 'tool_start' && chunk.toolName && chunk.toolName !== 'render_chart' && chunk.toolCallId) {
const block: Extract<ContentBlock, { type: 'tool' }> = {
type: 'tool',
tool: {
name: chunk.toolName,
displayName: chunk.toolName,
status: 'running',
toolCallId: chunk.toolCallId,
params: chunk.toolParams,
},
}
toolBlocks.set(chunk.toolCallId, block)
contentBlocks.push(block)
hasReplayContentBlocks = true
return
}
if (chunk.type === 'tool_result' && chunk.toolCallId) {
const block = toolBlocks.get(chunk.toolCallId)
if (block) {
block.tool.status = chunk.toolIsError ? 'error' : 'done'
block.tool.isError = chunk.toolIsError === true
block.tool.result = truncateToolResultText(extractToolResultText(chunk.toolResult))
}
return
}
if (chunk.type === 'content' && chunk.content) {
answer += chunk.content
appendTextBlock(chunk.content)