主题
ReAct 推理循环消息流
本文引用的源码文件
本文引用的文件
- src/background/react-loop.js
- src/background/completion-verifier.js
- src/background/loop-detector.js
- src/background/subagent-depth.js
- src/background/token-recorder.js
- src/background/stream-controller.js
- src/background/tool-executor.js
- src/background/constants.js
- src/background/context-summarizer.js
- src/background/state.js
- src/storage/db.js
目录
引言
本文聚焦扩展端 background 中的 ReAct 推理循环消息流,围绕“思考-行动-观察”(Thought-Action-Observation)序列展开,解释 LLM 生成的 thought 文本如何被解析、action 工具调用如何分发、observation 结果如何聚合,以及循环何时终止。同时深入说明完成度校验器(completion-verifier)的任务完成评估、子任务深度控制与循环检测机制,并给出状态机图、时序图、错误传播路径、并行执行优化、超时控制策略、上下文压缩时机与 Token 使用监控等实践要点。
项目结构
ReAct 推理循环位于 Chrome 扩展的 background 脚本中,核心由以下模块协作:
- react-loop.js:ReAct 主循环、LLM 调用、工具分发、checkpoint 恢复、反思与子任务编排。
- completion-verifier.js:完成度校验编排层,负责客观断言取证、判据归一化、重跑指令构造与子任务标注。
- loop-detector.js:多模式循环检测器,识别重复、振荡、ref 枚举、失败作用域、无进展滚动等异常模式。
- subagent-depth.js:统一的子代理/子任务嵌套深度计数器,防止递归爆炸。
- token-recorder.js / stream-controller.js / tool-executor.js / constants.js / context-summarizer.js / state.js / db.js:Token 记录、SSE 流控、工具执行、常量、上下文摘要、会话状态与 checkpoint 持久化。
graph TB RL["react-loop.js<br/>ReAct 主循环"] --> TE["tool-executor.js<br/>工具获取与执行"] RL --> SC["stream-controller.js<br/>SSE 流式读取"] RL --> TR["token-recorder.js<br/>Token 使用记录"] RL --> LD["loop-detector.js<br/>循环检测"] RL --> CV["completion-verifier.js<br/>完成度校验"] RL --> SD["subagent-depth.js<br/>子代理深度"] RL --> CS["context-summarizer.js<br/>上下文摘要"] RL --> ST["state.js<br/>会话/保活/取消"] RL --> DB["db.js<br/>checkpoint 持久化"]
图表来源
- src/background/react-loop.js#L1-L21
- src/background/tool-executor.js
- src/background/stream-controller.js
- src/background/token-recorder.js
- src/background/loop-detector.js#L1-L21
- src/background/completion-verifier.js#L1-L19
- src/background/subagent-depth.js#L1-L20
- src/background/context-summarizer.js
- src/background/state.js
- src/storage/db.js
章节来源
- src/background/react-loop.js#L1-L21
- src/background/completion-verifier.js#L1-L19
- src/background/loop-detector.js#L1-L21
- src/background/subagent-depth.js#L1-L20
核心组件
- ReAct 主循环(reactLoop/reactLoopImpl):封装 SW 心跳与自动恢复,驱动迭代;维护消息窗口、工具结果缓存、轮末循环检测注入、checkpoint 持久化与恢复。
- 完成度校验器(verifySubtaskCompletion / annotateOneSubtaskCompletion):将模型给出的 doneCriteria 归一化,异步取证(DOM/命令),纯判定 classifyVerdict,必要时生成纠正指令驱动回炉。
- 循环检测器(createLoopDetector):按 tab 桶维护最近调用轨迹,识别重复、ABAB 振荡、ref 枚举、失败作用域、无进展滚动,输出软提醒或硬停。
- 子代理深度(getSubagentDepth/setSubagentDepth/clearSubagentDepth):统一登记 plan_task 子任务与 dispatch_task 子代理的深度,限制最大嵌套层级。
- Token 与流控:estimateMessagesTokens/trimMessagesByBudget 控制上下文预算;StreamController 管理 SSE 空闲超时;recordTokenUsage 汇总用量。
章节来源
- src/background/react-loop.js#L734-L746
- src/background/react-loop.js#L752-L800
- src/background/completion-verifier.js#L84-L147
- src/background/completion-verifier.js#L454-L518
- src/background/loop-detector.js#L266-L440
- src/background/subagent-depth.js#L20-L52
- src/background/token-recorder.js
- src/background/stream-controller.js
架构总览
下图展示一次 ReAct 迭代的端到端流程:从 LLM 返回 assistant(tool_calls) 到工具执行、observation 聚合、循环检测与完成度校验,再到下一轮或终止。
sequenceDiagram participant UI as "侧边栏/调用方" participant RL as "react-loop.js" participant LLM as "LLM API" participant TE as "tool-executor.js" participant LD as "loop-detector.js" participant CV as "completion-verifier.js" participant DB as "db.js" UI->>RL : 启动 reactLoop(messages, model, tools, ...) RL->>LLM : 发送当前消息序列含 system/user/assistant/tool LLM-->>RL : assistant(tool_calls) + thought RL->>TE : 分发 action工具名+参数 TE-->>RL : observation成功/失败/用户拒绝/超时 RL->>LD : 轮末喂入本轮调用记录 LD-->>RL : none/nudge/stop alt 检测到循环 RL->>DB : 保存 checkpoint(错误原因) RL-->>UI : 抛出带 executionLog 的错误 else 未达终止 RL->>CV : 对已完成的子任务即时取证Phase 2b CV-->>RL : verification/completionNote/directive RL->>DB : 保存 checkpoint(进度/消息) RL->>LLM : 继续下一轮 end
图表来源
- src/background/react-loop.js#L734-L800
- src/background/loop-detector.js#L304-L436
- src/background/completion-verifier.js#L454-L518
- src/storage/db.js
详细组件分析
ReAct 主循环(react-loop.js)
- 入口包装:reactLoop 开启 SW 心跳与自动恢复,finally 清理;内部实现为 reactLoopImpl。
- 迭代状态:iteration、totalReflectionRounds、currentMessages、toolResultCache、loopRecords、loopDetector。
- 工具调用分发:基于 LLM 返回的 tool_calls,解析 arguments(兼容字符串/对象),走 tool-executor.executeTool;支持可并行工具集 PARALLELIZABLE_TOOLS 与需确认工具 CONFIRMATION_REQUIRED_TOOLS。
- 观察聚合:将 observation 追加到 currentMessages,供下一轮 LLM 决策。
- 循环检测:每轮末 flushLoopRecords 喂入 loop-detector,若 stop 则抛错并保存 checkpoint(error)。
- 反思与子任务:结合 react-reflection.js 进行反思;plan_task 拆分子任务,executeSubtasks 支持 sequential/parallel/dependency 三种策略。
- 完成度校验:在子任务 onDone 钩子中调用 completion-verifier.annotateOneSubtaskCompletion,即时取证并可选回灌 directive 再跑一轮。
- 上下文压缩:通过 context-summarizer.summarizeRoundsBatch 与 token-counter.trimMessagesByBudget 控制消息窗口大小与 Token 预算。
- 检查点:persistCheckpoint/clearCheckpoint 与 resumeReactLoopFromCheckpoint 支持中断恢复,恢复时清理不完整消息对并注入恢复提示。
flowchart TD
Start(["进入 reactLoopImpl"]) --> Init["初始化迭代变量/检测器/缓存"]
Init --> CallLLM["调用 LLM 获取 assistant(tool_calls)"]
CallLLM --> ParseArgs["解析 tool_call.arguments"]
ParseArgs --> Dispatch["分发工具执行串行/并行/依赖"]
Dispatch --> Observe["聚合 observation 到消息"]
Observe --> LoopCheck{"循环检测器是否停止?"}
LoopCheck --> |是| SaveErr["保存 checkpoint(错误) 并抛错"]
LoopCheck --> |否| Verify["完成度校验子任务 onDone"]
Verify --> Budget{"Token/时间预算是否充足?"}
Budget --> |否| Summarize["上下文摘要/截断"]
Budget --> |是| NextIter["迭代计数+1"]
Summarize --> NextIter
NextIter --> More{"达到终止条件?"}
More --> |否| CallLLM
More --> |是| Done(["返回最终结果"])
图表来源
- src/background/react-loop.js#L752-L800
- src/background/constants.js
- src/background/context-summarizer.js
章节来源
- src/background/react-loop.js#L734-L800
- src/background/react-loop.js#L547-L583
- src/background/react-loop.js#L645-L726
- src/background/react-loop.js#L490-L501
完成度校验器(completion-verifier.js)
- 目标:把模型给出的 doneCriteria 转化为可机检的断言,独立取证后判定是否达成,必要时生成纠正指令驱动回炉。
- 关键函数:
- verifySubtaskCompletion:归一化断言 → 异步取证(DOM/命令)→ classifyVerdict → 决定是否 rerun 与构建 missing 指令。
- createContentEvidenceCollector:向内容脚本发送 EVALUATE_DONE_CRITERIA,取 DOM 证据,返回 {available, pass, reason}。
- createCommandEvidenceCollector:编译只读 shell 命令,经 agent execWait 执行,按 exitCode/stdout 判定。
- createRoutingEvidenceCollector:按 check 类型路由到 DOM 或命令取证器,支持动态 resolveTabId 与超时配置。
- annotateOneSubtaskCompletion:在子任务成功时即时取证;Phase A 仅标注不重跑;Phase B 支持四闸门(可重试∧有进展∧有预算∧未超次)闭环回炉。
- 四闸门与严格真子集:isStrictSubset 保证缺项集合单调收缩,避免振荡;budgetLeft 由调用方注入(时间+Token)。
classDiagram
class CompletionVerifier {
+verifySubtaskCompletion(params)
+annotateOneSubtaskCompletion(r, subtasks, deps)
+buildMissingCriteriaDirective(criteria, checkResults)
+buildCompletionNote(verdict)
}
class EvidenceCollectors {
+createContentEvidenceCollector(tabId, sendMessage, timeoutMs)
+createCommandEvidenceCollector(deps)
+createRoutingEvidenceCollector(deps)
}
class VerdictClassifier {
+classifyVerdict(input)
}
CompletionVerifier --> EvidenceCollectors : "组装取证器"
CompletionVerifier --> VerdictClassifier : "调用分类器"
图表来源
- src/background/completion-verifier.js#L84-L147
- src/background/completion-verifier.js#L163-L200
- src/background/completion-verifier.js#L260-L312
- src/background/completion-verifier.js#L322-L344
- src/background/completion-verifier.js#L454-L518
章节来源
- src/background/completion-verifier.js#L84-L147
- src/background/completion-verifier.js#L163-L200
- src/background/completion-verifier.js#L260-L312
- src/background/completion-verifier.js#L322-L344
- src/background/completion-verifier.js#L454-L518
循环检测器(loop-detector.js)
- 设计原则:纯逻辑、browser-free,按 tab 桶维护最近调用轨迹,支持六类模式:重复、ref 枚举、ABAB 振荡、失败作用域、导航重置、无进展滚动。
- 输入:record(tabId, toolName, args, result)
- 输出:
- 关键特性:
- 稳定序列化+FNV-1a 哈希用于 args/result 键计算。
- ref 枚举针对 query_elements,跟踪 page/hasMore/totalPages,区分顺序翻页与可疑重读。
- ABAB 振荡检测尾迹,支持软提醒与硬停阈值。
- 失败作用域白名单工具(interact_element/fill_form/select_dropdown/keyboard_input/file_upload),同目标多次失败即告警/停止。
- 无进展滚动针对 scroll_to(moved:false),按坐标网格归一化 key。
- 健康迟滞与重武装:连续健康调用后可清除警告标记。
flowchart TD
R["record(tabId, toolName, args, result)"] --> Nav{"是否导航重置信号?"}
Nav --> |是| Reset["重置页面级状态"]
Nav --> |否| Window["加入滑动窗口/ABAB尾迹"]
Window --> Repeat["重复检测窗口制"]
Window --> RefEnum["ref 枚举检测query_elements"]
Window --> FailScope["失败作用域白名单工具"]
Window --> Scroll["无进展滚动scroll_to"]
Window --> ABAB["ABAB 振荡检测"]
Repeat --> Decide{"触发 nudge/stop?"}
RefEnum --> Decide
FailScope --> Decide
Scroll --> Decide
ABAB --> Decide
Decide --> Nudge["返回 nudge合并去重"]
Decide --> Stop["返回 stop立即终止"]
Decide --> None["返回 none"]
图表来源
章节来源
子代理深度控制(subagent-depth.js)
- 目的:统一 plan_task 子任务与 dispatch_task 子代理的嵌套深度,防止递归爆炸。
- 接口:getSubagentDepth(sessionId)、setSubagentDepth(sessionId, depth)、clearSubagentDepth(sessionId)。
- 默认上限:MAX_SUBAGENT_DEPTH=2,达到上限不再允许继续下钻。
章节来源
工具调用与确认门控
- 敏感工具需用户确认:requestToolConfirmation 通过 keepalive port 定向或广播下发 SHOW_CONFIRM_DIALOG,等待 INTERACTION_DISPLAYED 后开始倒计时;支持“当前任务放行”(loop-level approval)一次性放行同任务内挂起确认。
- 关联键唯一性:buildConfirmKey 确保 correlationId 缺失或冲突时生成唯一键,避免并发同名工具串扰。
- fail-closed:超时、面板不可达、广播失败均视为拒绝。
章节来源
- src/background/react-loop.js#L125-L141
- src/background/react-loop.js#L171-L210
- src/background/react-loop.js#L285-L450
依赖关系分析
- react-loop.js 依赖:
- tool-executor.js:getTools/executeTool、PARALLELIZABLE_TOOLS、CONFIRMATION_REQUIRED_TOOLS、TOOL_TIMEOUT_MS。
- stream-controller.js:StreamController/readSSEStream/STREAM_IDLE_TIMEOUT_MS。
- token-counter.js:estimateMessagesTokens/trimMessagesByBudget 等。
- loop-detector.js:createLoopDetector。
- completion-verifier.js:createRoutingEvidenceCollector/annotateOneSubtaskCompletion。
- subagent-depth.js:getSubagentDepth/setSubagentDepth/clearSubagentDepth。
- context-summarizer.js:summarizeRoundsBatch/extractAllRounds。
- state.js:cancelReactLoop/resetReactCancel/isCancelled/getOrCreateAbortController 等。
- db.js:saveReactCheckpoint/getReactCheckpoint/deleteReactCheckpoint。
graph LR RL["react-loop.js"] --> TE["tool-executor.js"] RL --> SC["stream-controller.js"] RL --> TC["token-counter.js"] RL --> LD["loop-detector.js"] RL --> CV["completion-verifier.js"] RL --> SD["subagent-depth.js"] RL --> CS["context-summarizer.js"] RL --> ST["state.js"] RL --> DB["db.js"]
图表来源
章节来源
性能与 Token 监控
- Token 预算控制:
- estimateMessagesTokens/estimateTokens 估算消息与单条 Token 数。
- trimMessagesByBudget 根据上下文窗口与校准值裁剪消息历史。
- recordTokenUsage 汇总本次运行 Token 用量。
- 上下文压缩时机:
- 在长对话或多轮 ReAct 迭代中,通过 summarizeRoundsBatch 对历史轮次做摘要,减少后续 LLM 输入规模。
- 当 assessContextPressure 指示压力过大时,优先压缩旧轮次而非删除近期关键交互。
- 流式响应空闲超时:
- StreamController 的 STREAM_IDLE_TIMEOUT_MS 在无数据接收时主动中断,避免网络或服务提供商不稳定导致的悬挂。
- 工具执行超时:
- runWithTimeout 以 Promise.race 包裹工具执行,超时后抛错并附带 executionLog。
- 并行执行优化:
- 对 PARALLELIZABLE_TOOLS 采用并行执行,提升吞吐;但需注意结果聚合顺序与循环检测器的 order 字段稳定排序。
章节来源
- src/background/react-loop.js#L6
- src/background/react-loop.js#L490-L501
- src/background/stream-controller.js
- src/background/token-recorder.js
- src/background/context-summarizer.js
故障排查指南
- 循环检测导致的中断:
- 查看 loop-detector 输出的 reason(repeat/refEnum/oscillation/failureScope/noProgressScroll/budget),对应 react-loop 的 i18n 文案定位问题。
- 常见原因:重复无效操作、元素枚举循环、ABAB 振荡、同一目标反复失败、无进展滚动、累计提醒过多。
- 工具确认失败:
- requestToolConfirmation 的 fail-closed 语义:超时、面板不可达、广播失败均视为拒绝;检查 keepalive port 是否存在、INTERACTION_DISPLAYED 回执是否到达。
- 工具执行超时:
- TOOL_TIMEOUT_MS 或 runWithTimeout 触发;检查工具耗时、网络延迟、Agent 进程状态。
- 流式响应空闲超时:
- STREAM_IDLE_TIMEOUT_MS 触发;检查网络与服务提供商稳定性。
- 上下文内存泄漏:
- EXECUTION_LOG_MEMORY_LIMIT 与 trimExecutionLogMemory 会裁剪终态日志;检查 snapshotMap 同步清理。
- checkpoint 恢复失败:
- resumeReactLoopFromCheckpoint 会列出 IndexedDB 中所有 checkpoint 辅助诊断;检查 sessionId 是否匹配、DB 升级是否阻塞。
章节来源
- src/background/loop-detector.js#L304-L436
- src/background/react-loop.js#L285-L450
- src/background/react-loop.js#L490-L501
- src/background/react-loop.js#L525-L541
- src/background/react-loop.js#L645-L726
结论
ReAct 推理循环在本项目中通过 react-loop.js 实现了完整的 Thought-Action-Observation 序列,结合 completion-verifier.js 的完成度校验与 loop-detector.js 的多模式循环检测,形成稳健的自驱执行框架。配合 subagent-depth.js 的深度控制、token-counter 的 Token 预算、stream-controller 的流控与 context-summarizer 的上下文压缩,系统在复杂任务场景下具备高鲁棒性与可扩展性。生产部署时应重点关注工具确认通道、Agent 在线状态、流式响应稳定性与 checkpoint 持久化可靠性。
附录:关键实现片段路径
- ReAct 主循环入口与实现体:src/background/react-loop.js#L734-L746, src/background/react-loop.js#L752-L800
- 工具调用参数解析与确认门控:src/background/react-loop.js#L243-L250, src/background/react-loop.js#L285-L450
- 循环检测器接入与轮末注入:src/background/react-loop.js#L768-L800, src/background/loop-detector.js#L304-L436
- 完成度校验编排与子任务标注:src/background/completion-verifier.js#L84-L147, src/background/completion-verifier.js#L454-L518
- 子代理深度控制:src/background/subagent-depth.js#L20-L52
- Token 估算与预算裁剪:src/background/react-loop.js#L6
- 流式响应空闲超时:src/background/stream-controller.js
- 上下文摘要与压缩:src/background/context-summarizer.js
- checkpoint 持久化与恢复:src/background/react-loop.js#L547-L583, src/background/react-loop.js#L645-L726, src/storage/db.js