主题
智能对话系统
本文引用的源码文件
本文引用的文件
目录
引言
本文件面向“智能对话系统”的 ReAct 推理循环、工具执行框架、上下文管理、完成度校验等核心能力,提供从架构到实现细节的系统化说明。系统采用双进程架构:Chrome 扩展端(Manifest V3)负责 UI、消息路由与 ReAct 主循环;独立本地 Agent 端提供文件读写、命令执行、长期记忆与 RAG 能力。两端通过本地 HTTP/WebSocket 通信,Agent 源码修改后需重启进程才生效。
项目结构
围绕本次文档目标,关键代码集中在 background 层与 shared 工具库:
- ReAct 主循环与状态恢复:background/react-loop.js
- 工具定义、动态注册与执行调度:background/tool-executor.js
- 多模式循环检测器:background/loop-detector.js
- 完成度校验编排:background/completion-verifier.js
- Token 估算与上下文预算:shared/token-counter.js
- 批量上下文摘要:background/context-summarizer.js
- 流式输出控制器:background/stream-controller.js
- 手动压缩摘要:background/context-compactor.js
- 工具参数解析与结果规范化:background/tool-helpers.js
graph TB RL["ReAct 主循环<br/>react-loop.js"] --> TE["工具执行框架<br/>tool-executor.js"] RL --> LC["循环检测器<br/>loop-detector.js"] RL --> CV["完成度校验编排<br/>completion-verifier.js"] RL --> TC["Token 估算与预算<br/>token-counter.js"] RL --> CS["批量上下文摘要<br/>context-summarizer.js"] RL --> SC["流式输出控制器<br/>stream-controller.js"] RL --> CC["手动压缩摘要<br/>context-compactor.js"] TE --> TH["工具辅助函数<br/>tool-helpers.js"]
图示来源
- src/background/react-loop.js#L734-L746
- src/background/tool-executor.js#L1110-L1307
- src/background/loop-detector.js#L266-L439
- src/background/completion-verifier.js#L84-L147
- src/shared/token-counter.js#L432-L505
- src/background/context-summarizer.js#L181-L245
- src/background/stream-controller.js#L36-L281
- src/background/context-compactor.js#L32-L80
- src/background/tool-helpers.js#L222-L361
章节来源
核心组件
- ReAct 推理循环:封装 SW 保活、超时控制、API 调用、工具执行、日志与 checkpoint 持久化、子任务计划锚点与便签回注、上下文压力评估与裁剪、反思注入。
- 工具执行框架:统一获取可用工具、动态注册 MCP/RAG 工具、参数解析与结果规范化、并行执行策略、敏感操作确认、网络与安全门控。
- 循环检测器:六模式检测(重复、ref 枚举、ABAB 振荡、失败作用域、导航重置、无进展滚动),软提醒与硬停结合,按 tab 隔离状态。
- 完成度校验:客观断言取证(DOM/命令)、开放任务 critic 评审、四闸门回炉控制、缺项纠正指令生成。
- 上下文管理:Token 估算校准、批量结构化摘要、权重兜底裁剪、图片剥离与引用压缩。
- 流式输出:SSE 解析、节流发送、usage 提取、tool_calls 检测与 ID 规范化。
章节来源
- src/background/react-loop.js#L752-L1599
- src/background/tool-executor.js#L448-L684
- src/background/loop-detector.js#L11-L21
- src/background/completion-verifier.js#L84-L147
- src/shared/token-counter.js#L97-L127
- src/background/stream-controller.js#L287-L409
架构总览
下图展示一次 ReAct 迭代中,模型响应、工具执行、循环检测与上下文管理的交互路径。
sequenceDiagram
participant User as "用户"
participant RL as "ReAct 主循环<br/>react-loop.js"
participant API as "LLM API"
participant SC as "流式控制器<br/>stream-controller.js"
participant TE as "工具执行框架<br/>tool-executor.js"
participant LD as "循环检测器<br/>loop-detector.js"
participant CV as "完成度校验<br/>completion-verifier.js"
User->>RL : 发起任务
RL->>API : 构建请求含 tools/messages
API-->>SC : SSE 流
SC-->>RL : content/tool_calls/usage
RL->>TE : 执行工具可并行/确认/超时
TE-->>RL : 标准化结果 {success,content,...}
RL->>LD : 记录本轮工具调用
LD-->>RL : nudge/stop/none
RL->>CV : 子任务完成度校验可选
CV-->>RL : verdict/directive/rerun
RL->>RL : 上下文压力评估与裁剪/摘要
RL-->>User : 最终结果或继续下一轮
图示来源
- src/background/react-loop.js#L1256-L1599
- src/background/stream-controller.js#L287-L409
- src/background/tool-executor.js#L1110-L1307
- src/background/loop-detector.js#L304-L439
- src/background/completion-verifier.js#L454-L518
详细组件分析
ReAct 推理循环
- 思考-行动-观察循环:每轮构造 messages/tools 调用 LLM;若返回 tool_calls,则进入工具执行阶段;否则视为文本回复并推进。
- 工具调用协调:支持并行执行(PARALLELIZABLE_TOOLS)、敏感操作确认(CONFIRMATION_REQUIRED_TOOLS)、超时控制(runWithTimeout)、执行日志增量发送与内存窗口裁剪。
- 循环检测:每轮末将工具调用记录喂入 loopDetector;根据 kind 决定注入提醒或抛出硬停错误。
- 上下文管理:每次 API 前评估上下文压力,触发批量摘要或权重裁剪;保留 system 与 assistant(tool_calls)+tool 配对;历史图片剥离;Token 预算动态计算。
- 完成度校验:在子任务成功时即时取证并标注 completionNote/verification;Phase B 支持基于四闸门的回炉重跑。
- 恢复机制:checkpoint 持久化 IndexedDB,支持中断恢复、清理不完整消息对、注入恢复提示。
flowchart TD
Start(["开始一轮"]) --> BuildReq["构建请求<br/>messages + tools"]
BuildReq --> CallAPI["调用 LLM API"]
CallAPI --> HasTools{"是否 tool_calls?"}
HasTools -- 否 --> TextReply["文本回复处理"]
HasTools -- 是 --> ExecTools["执行工具并行/确认/超时"]
ExecTools --> RecordLoop["记录工具调用"]
RecordLoop --> DetectLoop{"循环检测"}
DetectLoop -- stop --> StopLoop["抛出硬停错误"]
DetectLoop -- nudge --> InjectNudge["注入提醒"]
DetectLoop -- none --> NextStep["继续"]
InjectNudge --> NextStep
TextReply --> CheckContext["上下文压力评估"]
NextStep --> CheckContext
CheckContext --> TrimOrSum["裁剪/摘要"]
TrimOrSum --> VerifySubtask["完成度校验可选"]
VerifySubtask --> End(["结束/下一轮"])
图示来源
- src/background/react-loop.js#L752-L1599
- src/background/loop-detector.js#L304-L439
- src/background/completion-verifier.js#L454-L518
章节来源
工具执行框架
- 工具定义与注册:BUILTIN_TOOLS、RAW_TOOLS、TOOL_HANDLERS、TOOL_EXECUTION_MAP;动态加载 MCP/RAG 工具,重建 BG_HANDLERS 与并行/确认集合。
- 参数验证与结果规范化:tryParseToolArgs 两阶段修复 JSON;normalizeToolResult 统一 {success, content, tool_call_id}。
- 并行执行策略:依据 PARALLELIZABLE_TOOLS 并发执行;执行日志增量发送,避免 64MiB 限制。
- 超时控制:runWithTimeout 包装 Promise.race;工具级超时与整体循环超时分离。
- 安全与确认:敏感工具弹出确认对话框,支持“当前任务放行”;agent_exec 灰名单命令走相同确认通道。
- 会话强制下发 MCP 服务:绕过关闭/排除列表,保证预筛选不丢弃。
classDiagram
class ToolExecutor {
+getTools()
+executeTool()
+loadMcpTools()
+unloadMcpTools()
+loadRagTools()
+unloadRagTools()
}
class Helpers {
+tryParseToolArgs()
+normalizeToolResult()
+makeResult()
}
ToolExecutor --> Helpers : "使用"
图示来源
章节来源
循环检测算法
- 六模式:重复(窗口制)、ref 枚举(query_elements)、ABAB 振荡、失败作用域(白名单工具)、导航重置(back/forward/reload/wait_navigation)、无进展滚动(scroll_to)。
- 状态桶:按 tabId 隔离,维护 window、ababTail、repeatCounts、refEnum、failureScopes、scroll、warned/flowWarned、healthyStreak。
- 输出:kind=none/nudge/stop;nudge 合并为一条 user 提醒注入;stop 抛错并带 loopStop reason。
flowchart TD
A["record(tabId, name, args, result)"] --> NavCheck{"是否导航重置信号?"}
NavCheck -- 是 --> ResetState["重置页面级状态"]
NavCheck -- 否 --> WindowPush["入窗/尾迹"]
WindowPush --> Repeat["重复检测"]
WindowPush --> RefEnum["ref 枚举检测"]
WindowPush --> FailScope["失败作用域检测"]
WindowPush --> Scroll["无进展滚动检测"]
Repeat --> ABAB["ABAB 振荡检测"]
RefEnum --> ABAB
FailScope --> ABAB
Scroll --> ABAB
ABAB --> Healthy["健康迟滞/重武装"]
Healthy --> Decide{"stop? nudge? none?"}
图示来源
章节来源
完成度验证器
- 断言归一化:normalizeDoneCriteria 过滤非法/不受支持的 check。
- 异步取证:createContentEvidenceCollector(DOM)、createCommandEvidenceCollector(命令/文件)、createRoutingEvidenceCollector(路由 DOM/命令)。
- 判定内核:classifyVerdict 输出 SATISFIED/UNMET_RETRYABLE/UNMET_PERMANENT/INDETERMINATE。
- 回炉控制:四闸门(可重试∧有进展∧有预算∧未超次)+ 严格真子集进度判定;directive 仅点名可取证且未通过的缺项。
- 注解写入:annotateOneSubtaskCompletion 在子任务 onDone 即时写回 verification/completionNote;Phase B 支持 rerun 回调驱动再跑一轮。
flowchart TD
Start(["子任务完成"]) --> Normalize["归一化断言"]
Normalize --> Gather["逐条异步取证"]
Gather --> Classify["纯判定 classifyVerdict"]
Classify --> Verdict{"verdict 类型"}
Verdict -- SATISFIED --> Done["达标"]
Verdict -- UNMET_RETRYABLE --> Gates["四闸门检查"]
Gates -- 全过 --> Rerun["生成 directive 并 rerun"]
Gates -- 任一不过 --> Permanent["永久未达标"]
Verdict -- INDETERMINATE --> Indet["证据不可用/部分不可用"]
Verdict -- UNMET_PERMANENT --> Permanent
Rerun --> Annotate["写回 verification/completionNote"]
Indet --> Annotate
Permanent --> Annotate
Done --> End(["结束"])
图示来源
章节来源
上下文管理与 Token 优化
- Token 估算与校准:estimateMessagesTokens 支持多模态内容;EWMA 校准因子更新 getCalibratedTokens。
- 上下文预算:getMessageBudget 与 assessContextPressure;按 80% 阈值触发批量摘要,仍超标则权重裁剪。
- 批量摘要:summarizeRoundsBatch 一次 LLM 压缩多轮旧对话,注入结构化摘要(任务目标/已完成/关键事实/未决问题)。
- 手动压缩:generateCompactionSummary 用户显式触发,快速失败明确报错。
- 图片处理:stripImagesFromContent 剥离历史图片;sanitizeImageUrlsForApi 仅传 url 字段。
flowchart TD
Est["估算消息 tokens"] --> Calib["应用校准因子"]
Calib --> Pressure["评估上下文压力"]
Pressure --> |warning/critical| Sum["批量摘要"]
Sum --> StillOver{"仍超预算?"}
StillOver -- 是 --> Trim["权重裁剪"]
StillOver -- 否 --> Keep["保持"]
Pressure --> |safe| Keep
Trim --> Final["最终消息集"]
Keep --> Final
图示来源
- src/shared/token-counter.js#L97-L127
- src/shared/token-counter.js#L432-L505
- src/background/context-summarizer.js#L181-L245
- src/background/context-compactor.js#L32-L80
章节来源
流式输出控制器
- SSE 解析:feedLine 处理 data:[DONE]/choices.delta,累积 content/reasoning_content/tool_calls。
- 节流发送:sendChunk 合并 chunk,按 streamChunkDelay 节流;sendStart/finish 控制生命周期。
- usage 提取:stream_options.include_usage 的最终 chunk 单独提取 usage。
- tool_calls 检测:finish_reason=tool_calls 时立即通知前端,ID 规范化。
classDiagram
class StreamController {
+feedLine(line)
+sendChunk(content)
+sendStart()
+finish()
+sendToolCallNotification()
+reset()
+getResult()
}
图示来源
章节来源
依赖关系分析
- react-loop.js 依赖 tool-executor.js(工具获取与执行)、loop-detector.js(循环检测)、completion-verifier.js(完成度校验)、token-counter.js(估算与裁剪)、context-summarizer.js(批量摘要)、stream-controller.js(SSE 解析)。
- tool-executor.js 依赖 tool-helpers.js(参数解析与结果规范化),并通过 local-agent-client 与 Agent 端交互。
- completion-verifier.js 依赖 shared/completion-verdict.js(判定内核)与 verify-command-safety.js(命令安全)。
graph LR RL["react-loop.js"] --> TE["tool-executor.js"] RL --> LD["loop-detector.js"] RL --> CV["completion-verifier.js"] RL --> TC["token-counter.js"] RL --> CS["context-summarizer.js"] RL --> SC["stream-controller.js"] TE --> TH["tool-helpers.js"]
图示来源
章节来源
性能与优化
- Token 估算校准:EWMA 平滑实际 prompt_tokens,减少估算偏差导致的过度裁剪或超限。
- 批量摘要替代串行摘要:一次 LLM 调用压缩多轮旧对话,降低调用次数与延迟。
- 权重裁剪 O(n):贡献预估算一次,增量扣减,避免 O(n²)。
- 执行日志内存窗口:EXECUTION_LOG_MEMORY_LIMIT 限制日志规模,防止 SW 内存失控。
- 流式空闲超时:STREAM_IDLE_TIMEOUT_MS 保护长连接卡死。
- 大工具结果卸载:offloadLargeToolResult 将全文写入 workspace,对话内仅保留预览与路径,按需回读。
[本节为通用指导,无需特定文件来源]
故障排查指南
- API 400 上下文超限自愈:检测到 context/token/too long 特征时,按 CONTEXT_HEAL_RATIOS 逐档裁剪并重试本轮,至多 CONTEXT_HEAL_MAX_ATTEMPTS 次。
- 流式空闲超时:readSSEStream 抛出 StreamIdleTimeout,区分 AbortError 与空闲超时,分别给出用户可见文案。
- 工具参数解析失败:tryParseToolArgs 两阶段修复(位置引导修复、尾随逗号、未加引号字符串、嵌套对象、自动补全括号/引号、数组混入 KV 对)。
- 工具结果格式异常:normalizeToolResult 兜底填充 content 与 tool_call_id,失败返回标准错误对象。
- 侧边栏确认弹窗无法送达:默认拒绝 fail-closed,撤销陈旧弹窗,避免串扰与悬挂。
章节来源
结论
本系统以 ReAct 主循环为核心,串联工具执行、循环检测、完成度校验与上下文管理,形成稳健的智能对话闭环。通过 Token 校准、批量摘要与权重裁剪保障上下文稳定;通过多模式循环检测与四闸门回炉控制抑制无效振荡;通过流式控制器与执行日志增量发送提升用户体验与可观测性。
[本节为总结,无需特定文件来源]
附录:扩展实践
扩展新工具类型
- 在 tool-executor.js 中新增 handler 并注册到 TOOL_HANDLERS,必要时加入 RAW_TOOLS/BUILTIN_TOOLS,并调用 rebuildBgHandlers 同步并行/确认集合。
- 参考 MCP/RAG 动态注册流程,确保工具元数据与开关逻辑一致。
- 参考路径:src/background/tool-executor.js#L448-L684、src/background/tool-executor.js#L944-L1001
自定义 ReAct 行为
- 调整循环检测阈值:通过 createLoopDetector(config) 覆盖 LOOP_DETECTOR_CONFIG。
- 调整上下文预算与摘要策略:修改 getReactTokenBudget 与 trimMessages 中的阈值与比例。
- 参考路径:src/background/loop-detector.js#L11-L21、src/background/react-loop.js#L824-L846、src/background/react-loop.js#L898-L977
优化对话性能
- 启用流式输出与节流:配置 streamEnabled 与 streamChunkDelay。
- 使用批量摘要与权重裁剪组合:优先批量摘要,失败降级权重裁剪。
- 参考路径:src/background/stream-controller.js#L36-L281、src/background/context-summarizer.js#L181-L245
[本节为实践指导,无需特定文件来源]