Files
zclaw_openfang/wiki/chat.md
iven c12b64150b
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
fix(runtime): 工具调用 P0 修复 — after_tool_call 接入 + stream_errored 工具抢救
P0-1: after_tool_call 中间件从未被调用
- 流式模式(run_streaming)和非流式模式(run)均添加 middleware_chain.run_after_tool_call()
- ToolErrorMiddleware 错误计数恢复逻辑现在生效
- ToolOutputGuardMiddleware 敏感信息检测现在生效

P0-2: stream_errored 跳过所有工具执行
- 新增 completed_tool_ids 跟踪哪些工具已收到完整 ToolUseEnd
- 流式错误时区分完整工具和不完整工具
- 完整工具照常执行(产物创建等不受影响)
- 不完整工具发送取消 ToolEnd 事件(前端不再卡"执行中")
- 工具执行后若 stream_errored,break outer 阻止无效 LLM 循环

参考文档:
- docs/references/zclaw-toolcall-issues.md (10项问题分析)
- docs/references/deerflow-toolcall-reference.md (DeerFlow工具调用完整参考)
2026-04-24 12:20:14 +08:00

7.1 KiB
Raw Blame History

title, updated, status, tags
title updated status tags
聊天系统 2026-04-23 active
module
chat
stream

聊天系统

index 导航。关联模块: routing saas butler

1. 设计决策

决策 原因
3 种 ChatStream 实现 覆盖 3 种运行环境: KernelClient(Tauri) / SaaSRelay(浏览器) / GatewayClient(外部进程)
5 Store 拆分 原 908 行 ChatStore → stream/conversation/message/chat/artifact单一职责
5 分钟超时守护 防止流挂起: kernel-chat.ts:76超时自动 cancelStream
统一回调接口 3 种实现共享 { onDelta, onThinkingDelta, onTool, onHand, onComplete, onError }
LLM 动态建议 替换硬编码关键词匹配,用 LLM 生成个性化建议1深入追问+1实用行动+1管家关怀4路并行预取智能上下文

ChatStream 实现

环境 实现 传输
Tauri + SaaS (主路径) KernelClient + relay Tauri Event → SaaS Token Pool → LLM
Tauri 本地 KernelClient Tauri Event → Kernel → LLM 直连
浏览器端 SaaSRelayGatewayClient HTTP SSE → SaaS → LLM
外部 Gateway GatewayClient WebSocket

2. 关键文件 + 数据流

核心文件

文件 职责
desktop/src/store/chat/streamStore.ts 流式消息编排、发送、取消、LLM 动态建议生成
desktop/src/store/chat/conversationStore.ts 会话管理、当前模型、sessionKey
desktop/src/store/chat/messageStore.ts 消息持久化 (IndexedDB)
desktop/src/lib/kernel-chat.ts KernelClient ChatStream (Tauri)
desktop/src/lib/suggestion-context.ts 4路并行智能上下文拉取 (用户画像/痛点/经验/技能匹配)
desktop/src/lib/cold-start-mapper.ts 冷启动配置映射 (行业检测/命名/个性/技能)
desktop/src/components/ChatArea.tsx 聊天区域 UI
desktop/src/components/ai/SuggestionChips.tsx 动态建议芯片展示
crates/zclaw-runtime/src/loop_runner.rs Rust 主聊天循环 + 中间件链

发送消息流

用户输入 → ChatPanel.tsx
  → streamStore.sendMessage(content)
    → effectiveSessionKey = conversationStore.sessionKey || uuid()
    → effectiveAgentId = resolveGatewayAgentId(currentAgent)
    → getClient().chatStream(content, callbacks, { sessionKey, agentId, chatMode })
      → [KernelClient] Tauri invoke('agent_chat_stream')
        → Kernel → loop_runner → 14层中间件 → LLM Driver
          → Tauri Event emit('chat-response-delta')
            → onDelta → streamStore 追加 delta → UI 渲染
            → onComplete → conversationStore 持久化 → messageStore 写 IndexedDB
      → [SaaSRelay] POST /api/v1/relay/chat/completions → SSE
      → [GatewayClient] WebSocket send → onmessage
    → 5 分钟超时守护 (kernel-chat.ts:76)

集成契约

方向 模块 接口 说明
Calls -> routing getClient() 确定走哪条 ChatStream
Calls -> middleware Through loop_runner 14 层 runtime 中间件链
Called by <- UI ChatPanel.tsx 用户发送消息、取消流式
Emits -> streamStore Tauri Event chat-response-delta 流式增量更新

3. 代码逻辑

Store 拆分 (5 Store)

Store 文件 职责
streamStore store/chat/streamStore.ts 流式编排、发送、取消
conversationStore store/chat/conversationStore.ts 会话管理、当前模型
messageStore store/chat/messageStore.ts 消息持久化 (IndexedDB)
chatStore store/chat/chatStore.ts 聊天通用状态
artifactStore store/chat/artifactStore.ts 聊天产物/附件

流式事件类型

agent_chat_stream Tauri Event emit 的 tagged union:

Delta / ThinkingDelta / ToolStart / ToolEnd / HandStart / HandEnd / SubtaskStatus / IterationStart / Complete / Error

模型切换

UI 选择模型 → conversationStore.currentModel = newModel
  → 下次 sendMessage → getClient() 读取 currentModel
  → SaaS 模式: relay 白名单验证 → 可用则切换
  → 本地模式: 直接使用用户配置的模型

不变量

  • sessionKey 在会话内必须一致 (UUID 生成一次,持久化 IndexedDB)
  • cancelStream 设置原子标志位,与 onDelta 回调无竞态
  • 3 种 ChatStream 共享同一套回调接口,上层代码无需感知实现差异
  • 消息持久化走 messageStore → IndexedDB与流式渲染解耦
  • 动态建议 4 路并行预取 (userProfile/painPoints/experiences/skillMatch)500ms 超时降级为空串
  • 建议生成与 memory extraction 解耦 — 不等 memory LLM 调用完成即启动建议

LLM 动态建议

sendMessage → isStreaming=true + _activeSuggestionContextPrefetch = fetchSuggestionContext(...)
  → 流式响应中 prefetch 在后台执行
onComplete → createCompleteHandler
  → generateLLMSuggestions(prefetchedContext) — 立即启动不等 memory
    → prompt: 1 深入追问 + 1 实用行动 + 1 管家关怀
  → memory/reflection 后台独立运行 (Promise.all)
  → SuggestionChips 渲染

Tauri 命令

命令 说明
agent_chat_stream 流式聊天 (主路径)
agent_chat 非流式聊天
cancel_stream 取消当前流式响应
classroom_chat 课堂场景对话

4. 活跃问题 + 注意事项

问题 状态 说明
after_tool_call 中间件未调用 已修复 (04-24) 流式+非流式均添加调用ToolErrorMiddleware/ToolOutputGuard 现在生效
stream_errored 跳过所有工具 已修复 (04-24) 完整工具照常执行,不完整工具发送取消事件
B-CHAT-07 混合域截断 P2 Open 跨域消息时可能截断上下文
SSE Token 统计为 0 已修复 SseUsageCapture stream_done flag
Tauri invoke 参数名 已修复 (f6c5dd2) camelCase 格式
Provider Key 解密 已修复 (b69dc61) warn+skip + heal

注意事项:

  • 辅助 LLM 调用 (记忆摘要/提取、管家路由) 复用 kernel_init 的 model+base_url与聊天同链路
  • 课堂聊天是独立 Tauri 命令 (classroom_chat),不走 agent_chat_stream
  • Agent tab 已移除 — 跨会话身份由 soul.md 接管,不再通过 RightPanel 管理

5. 变更日志

日期 变更
04-24 工具调用 P0 修复: after_tool_call 中间件接入(流式+非流式) + stream_errored 工具抢救(完整工具执行+不完整工具取消)
04-24 产物系统优化: MarkdownRenderer 提取共享 + ArtifactPanel react-markdown 渲染 + 文件选择器下拉 + 数据源扩展(file_write/str_replace 两路径) + artifactStore IndexedDB 持久化
04-23 建议 prefetch: sendMessage 时启动 context 预取,流结束后立即消费,不等 memory extraction
04-23 建议 prompt 重写: 1深入追问+1实用行动+1管家关怀上下文窗口 6→20 条
04-23 身份信号: detectAgentNameSuggestion 前端即时检测 + RightPanel 监听 Tauri 事件刷新名称
04-23 Agent tab 移除: RightPanel 清理 ~280 行 dead code身份由 soul.md 接管