fix(growth,kernel,runtime,desktop): 50 轮功能链路审计 7 项断链修复
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

P0 修复:
- B-MEM-2: 跨会话记忆丢失 — 添加 IdentityRecall 查询意图检测,
  身份类查询绕过 FTS5/LIKE 文本搜索,直接按 scope 检索全部偏好+知识记忆;
  缓存 GrowthIntegration 到 Kernel 避免每次请求重建空 scorer
- B-HAND-1: Hands 未触发 — 创建 HandTool wrapper 实现 Tool trait,
  在 create_tool_registry() 中注册所有已启用 Hands 为 LLM 可调用工具

P1 修复:
- B-SCHED-4: 一次性定时未拦截 — 添加 RE_ONE_SHOT_TODAY 正则匹配
  "下午3点半提醒我..."类无日期前缀的同日触发模式
- B-CHAT-2: 工具调用循环 — ToolErrorMiddleware 添加连续失败计数器,
  3 次连续失败后自动 AbortLoop 防止无限重试
- B-CHAT-5: Stream 竞态 — cancelStream 后添加 500ms cancelCooldown,
  防止后端 active-stream 检查竞态
This commit is contained in:
iven
2026-04-20 09:43:38 +08:00
parent 24b866fc28
commit f2917366a8
10 changed files with 746 additions and 49 deletions

View File

@@ -113,6 +113,8 @@ interface ChatStoreAccess {
export interface StreamState {
isStreaming: boolean;
/** Brief cooldown after cancelStream — prevents race with backend active-stream check */
cancelCooldown: boolean;
isLoading: boolean;
chatMode: ChatModeType;
suggestions: string[];
@@ -201,6 +203,7 @@ export const useStreamStore = create<StreamState>()(
persist(
(set, get) => ({
isStreaming: false,
cancelCooldown: false,
isLoading: false,
chatMode: 'thinking' as ChatModeType,
suggestions: [],
@@ -230,7 +233,7 @@ export const useStreamStore = create<StreamState>()(
// ── Core: sendMessage ──
sendMessage: async (content: string) => {
if (get().isStreaming) return;
if (get().isStreaming || get().cancelCooldown) return;
if (!_chat) {
log.warn('sendMessage called before chatStore injection');
return;
@@ -678,9 +681,12 @@ export const useStreamStore = create<StreamState>()(
}
// 4. Reset streaming state and clear sessionKey so next send gets a fresh session
set({ isStreaming: false, activeRunId: null });
set({ isStreaming: false, activeRunId: null, cancelCooldown: true });
useConversationStore.setState({ sessionKey: null });
log.info('Stream cancelled by user');
// 5. Brief cooldown to prevent race with backend active-stream check
setTimeout(() => set({ cancelCooldown: false }), 500);
},
// ── Agent Stream Listener ──