优化: 对话执行轨迹聚合与工具卡交互

前端聚合当前轮次工具调用数,替代每轮清零的完成计数,进度文案改轮次+累计口径
完成聚合语义由执行轨迹卡承接,工具卡复读修复与默认折叠收敛
流式与工具事件配套调整,新增轮次轨迹收集 composable
This commit is contained in:
lxy
2026-10-01 02:41:05 +08:00
parent e7cd035c62
commit 04acc4297d
15 changed files with 482 additions and 95 deletions
+5 -4
View File
@@ -283,16 +283,17 @@ async function onDrop(e: DragEvent): Promise<void> {
/** 发送可用:有文本或图片或已选技能(纯技能调用允许空文本) */
const canSend = computed(() => inputText.value.trim().length > 0 || pendingImages.value.length > 0 || !!pendingSkill.value)
// 按钮状态:streaming=true 且 textIdle=false(最近 300ms 有新 delta) → 'stop'(红);
// 按钮状态:streaming=true 且(本会话 conv_state='generating' 或最近 300ms 有文本 delta)→ 'stop'(红);
// 否则 → 'idle'(白)。textIdle 是 reactive ref,在 AiTextDelta 中每 delta 复位 false,
// 300ms 无新 delta 后 setTimeout 置 true。不与 streaming 绑定——文本显示完后 300ms 按钮白,
// 不等 AiCompleted,streaming 持续 true 也不影响。
// 300ms 无新 delta 后 setTimeout 置 true。仅靠 textIdle 会漏掉工具执行/轮间 LLM 等待期
// (30s heartbeat 无 delta,按钮回落发送图标,生成失控不可干预),故补 conv_state 判定;
// textIdle 兜底保留,防 conv_state 尚未追踪(null)瞬间按钮闪断。
const stopBtnState = computed<'idle' | 'stop' | 'stopping' | 'retry'>(() => {
const convId = store.state.activeConversationId
const cs = getConvState(convId)
if (cs === 'stopping') return 'stopping'
if (cs === 'error') return 'retry'
const textActive = store.state.streaming && !textIdle.value
const textActive = store.state.streaming && (cs === 'generating' || !textIdle.value)
return textActive ? 'stop' : 'idle'
})