AI 参与说明(Agent:Codex):本文由 Codex 根据 REA 官方资料、Context7 检索材料与固定提交源码协助调研、撰写和校验,整理日期为 2026-10-10。源码基线为
33b9b31,该提交的 package 版本为6.3.0;本文的架构评价属于对源码的工程分析。运行记录:模型gpt-6.1-sol,reasoning effortultra,执行入口 Codex Desktop,提供方openai;运行记录中的 CLI 版本0.162.0-alpha.17.2(不代表桌面 App 版本)。
REA(Reverse Engineer Anything)最值得研究的是:它把多种逆向分析能力组织成外部 Agent 可以调用、组合和核对的本地工具系统。原生机器码的反编译交给 Hopper、Ghidra、IDA;JavaScript/Electron 的静态解析、关系图与部分工作流由 REA 自己实现;运行观察则接到 CDP、Playwright、V8 Inspector 和受控进程等后端。
REA supplies analysis tools and Evidence; the external Agent owns the investigation loop. 在本次固定版本的入口、应用工作流、依赖与相关调用检索中,没有发现内置模型调用或自主 Agent Loop。MCP Prompt 返回文本模板,复合工具执行确定性代码;决定查哪个函数、如何解释结果、怎样重建功能,仍是外部 Agent 的工作。MCP Prompt 实现,复合工具分发
先认识几个术语
| 英文术语 | 中文名称 | 简要解释 |
|---|---|---|
| MCP | 模型上下文协议 | 让 Agent 客户端发现和调用外部工具的协议 |
| Agent Loop | 智能体循环 | 请求模型、执行工具,再把结果交给模型决定下一步 |
| Provider | 提供方 | 在 REA 中表示某一种分析后端,不是模型服务商 |
| Analysis Profile | 分析配置档案 | 固定引擎身份、版本及影响结果的配置 |
| Evidence | 证据记录 | 带来源、目标身份、结果、位置和限制的结构化记录 |
| Artifact | 制品 | 已提供给分析器的文件、目录、安装包或归档成员 |
| AST | 抽象语法树 | 将源代码解析成语法结构,便于查找调用和定义 |
| IPC | 进程间通信 | Electron 等应用中跨进程交换消息的机制 |
| CDP | Chrome 开发者工具协议 | 读取浏览器页面、脚本和运行状态的调试协议 |
| Snapshot | 快照 | 保存特定目标与分析配置下可以重放的查询结果 |
分析基线与项目范围
本文锁定完整 commit 33b9b31a6fb50cc3e6f4591d0395dbba15b51f13,避免移动的 main 与文档检索缓存混用。package.json 声明包名 rea-agents,同时提供 rea 与 rea-agents 两个命令;Node.js 要求是 ^22.19.0 || ^24.11.0 || >=26.0.0。6.3.0 是该提交声明的版本,不代表 npm 当前 latest 的独立核验结果。package.json
项目的能力跨越多个后端,但适用条件不同:
| 分析对象 | 主要实现 | 能得到什么,以及边界 |
|---|---|---|
| 原生二进制 | Hopper / Ghidra / IDA 适配器 | 伪代码、汇编、函数、引用;依赖已有引擎、宿主和目标支持 |
| JavaScript / Electron | 文件清单、Babel AST、静态语义与图构建 | 模块、入口、IPC、接口和语义候选;静态路径不执行目标代码 |
| 网站与运行中的 JavaScript | CDP / Playwright / V8 Inspector | 页面、脚本与有限运行观察;不同工具具有不同副作用 |
| .NET | 内置 TypeScript PE/CLI reader | Metadata、签名和 CIL;不会据此执行 CLR 或恢复 C# 源码 |
| Android APK | REA Java bridge + 已配置的 JADX 后端 | Manifest、类、方法反编译与引用;不运行 APK |
| Firmware | 已配置的 Binwalk / Unblob | 区域识别、提取与后续分析入口;不能从签名推断运行映射 |
后三类可对照 .NET 边界、JADX 配置与限制、Firmware Provider。下面重点拆解共享内核、原生后端和 JavaScript/Electron 主线。
总体架构:两个入口,共用应用内核
从依赖方向看,REA 采用入口、协议适配、应用工作流、领域合同和后端适配的分层。CLI 与 MCP 共用应用服务和 Provider,但 CLI 不需要把每条命令转成 MCP 请求。官方架构图源码
flowchart TB
Agent[外部 Agent<br/>持有 Agent Loop] --> MCP[MCP Adapter<br/>长期 stdio 进程]
Terminal[终端用户] --> CLI[CLI Adapter<br/>单次命令]
MCP --> App[Application Services<br/>共同工作流]
CLI --> App
App --> Session[BinarySession<br/>目标与 Provider 路由]
App --> JS[JavaScript / Electron<br/>静态解析与图构建]
App --> Runtime[Browser / Process<br/>运行观察]
Session --> Deep[选定的深度 Provider<br/>Hopper / Ghidra / IDA]
Session --> Auxiliary[辅助 Provider<br/>Artifact / Native 等]
Deep --> Evidence[Evidence<br/>来源、结果与限制]
Auxiliary --> Evidence
JS --> Evidence
Runtime --> Evidence
图中 Evidence 是共同结果合同;各工具可在对应流程中记录和交付结果,并非把所有输出广播给所有后端。
| 源码位置 | 阅读时关注的问题 |
|---|---|
scripts/rea.mjs | 如何把 mcp / --mcp 分发到生产 MCP 入口,其余命令进入 CLI |
src/main.ts、src/cli.ts | 长期进程与单次执行如何初始化和清理 |
src/composition/ | CLI/MCP 如何装配同一套真实 Provider |
src/server/、src/contracts/ | 工具注册、Schema、进度、取消和结果投递 |
src/application/ | Session、Provider 选择和复合工作流 |
src/domain/ | Evidence、图、比较和快照的校验与纯转换 |
src/hopper/、src/ghidra/、src/ida/、bridge/ | 如何进入引擎,如何收回自己拥有的资源 |
src/artifacts/、src/browser/、src/process/ | 文件读取、运行观察和进程边界 |
src/composition/binary.ts 将 Hopper、Ghidra、IDA 放进同一个 AnalysisProviderRegistry,辅助能力通过相应 Provider 装配;MCP 的 main.ts 创建长期 BinarySession,CLI 的 DirectAnalysis 则为单次分析建立并清理 Session。共同装配点,MCP 生命周期,CLI 分析实现
这条分层的收益是:同一个分析算法可以被终端、MCP 和测试调用,协议层负责参数、输出和连接生命周期,应用层不用依赖某个 Agent 产品。
MCP 合同:工具目录稳定,可用性单独查询
REA 有两种容易混淆的目录:ToolContract 定义面向调用者的工具名称、输入输出 Schema、副作用和示例;AnalysisProviderRegistry 负责选择能分析某个目标的深度后端。前者回答“有哪些工具”,后者回答“这次由谁执行”。工具合同集合
tools/list 包含暂时不可用的工具。打开目标、关闭目标或后端健康状态改变,并不改变整个工具目录。Agent 应读取 binary_session 的 result.tool_availability,查看当前目标、宿主、Provider 和客户端协议能力是否满足条件,以及原因与修复建议。MCP runtime contracts
Schema 也分两层:Canonical Zod Schema 执行严格运行时验证;广告给客户端的 JSON Schema 为兼容模型接口做展示投影,例如把根对象 union 展示成一个对象。投影可能无法表达全部排斥关系,最终仍由 Canonical Schema 拒绝非法组合。源码保留原始验证器,只替换展示部分。Schema 投影,保留 Canonical 验证器
因此,工具在目录中出现、参数通过广告 Schema、目标已经打开,是三个不同条件;不能把其中一个当作分析可以成功的保证。
原生分析:选择引擎、固定来源、接入 Bridge
Provider 选择是确定性的
显式请求的 Provider 优先于环境默认值。auto 会评估目标支持与配置:恰好一个可用候选才绑定;多个候选返回 ambiguous;没有深度候选时可保留未绑定状态,让适用的辅助能力继续工作。候选按 ID 排序,注册先后不是隐含优先级。选择算法
A successful deep-analysis selection binds the target to one Provider and one committed Analysis Profile. SessionProviderRouter 把这个绑定与互不重叠的辅助操作家族组合起来。运行失败不会悄悄切换另一家反编译器,避免同一调查中的结果来源无声变化。目标路由
“发现配置”“支持这个目标”“引擎实际就绪”分别建模。生产路由的 CompositeProvider 对打开目标时的 health 本地返回,子客户端在首次实际操作时创建;Ghidra 的首次后端查询才触发启动和导入。open_binary 成功不能单独证明 JVM 已完成分析。CompositeProvider,Ghidra 首次查询
三家引擎的集成方式不同
| 后端 | REA 如何接入 | 真正完成反编译的位置 |
|---|---|---|
| Hopper | 在应用内运行 Python Bridge,经本地 Unix socket 交换请求 | procedure.decompile() |
| Ghidra | Headless 导入目标,执行 Java Bridge;POSIX 使用 Unix socket,Windows 使用经认证的本地 TCP | DecompInterface.decompileFunction() 与 getC() |
| IDA | 适配用户已配置的上游 MCP,支持已连接 GUI 或受控 Headless 数据库 | 上游 decompile_function / decompile 工具 |
依据分别见 Hopper Bridge、Ghidra Bridge、IDA 操作映射。输出是引擎生成的伪代码,不是原始源码;符号、类型、间接调用和运行路径仍可能不完整。
以 Ghidra 为例,REA 不只是调用一次命令:它准备私有目标副本、临时项目与运行目录,生成 token 和 run ID,启动自己拥有的进程,再核对握手中的目标 hash、Analysis Profile、语言配置、Provider 版本和能力。停止未确认时保留运行目录以便重试清理,避免仍在运行的 JVM 继续写入已删除的位置。Ghidra 启动,握手校验
这些机制约束通信、来源和资源归属;私有目录与 token 不等于容器隔离,也不使引擎解析器自动成为处理任意目标的安全沙箱。
取消请求不等于停止底层引擎
三家适配器都为目标内的请求安排串行执行,避免文档、数据库和单个 Program 状态相互干扰,但取消方式不同:
- Hopper:已经发送的请求被取消时,可以结束调用者的等待,仍保留在途请求占用,直到真实响应到达;不会假装队列已经空闲。
- Ghidra:取消正在执行的请求会终止临时 Session 并清理受控进程,后续重新导入需要付出启动成本,Session 注释也会丢失。
- IDA:取消后仍需等待上游在途请求收束,再清理拥有的资源;不能据此声称上游反编译立刻停止。
对应实现见 HopperRequestQueue、GhidraRequestQueue、IdaSessionClient。MCP 能接受多个请求,不表示一个原生引擎能并行分析多个请求。
JavaScript/Electron:从文件到两张关系图
这条路线最能体现 REA 自身的分析逻辑。analyze_javascript_application 的专用输入是目录或 ASAR,先建立 Canonical Artifact Inventory,再读取已编目的文件、核对字节与 SHA-256、解析文本,最后建立图并生成 Evidence。.node 文件可以作为原生边界被识别,但不会被静态路径加载执行。重建入口,字节复核
flowchart TB
Input[目录 / ASAR] --> Inventory[Artifact Inventory<br/>身份与文件清单]
Inventory --> Bytes[读取文件<br/>复核字节与 SHA-256]
Bytes --> Parse[AST / package.json / HTML / Source Map]
Parse --> Structure[模块、入口与边界 findings]
Parse --> Semantics[词法 binding 与静态语义 IR]
Structure --> Application[JavaScript Application Graph]
Semantics --> Semantic[JavaScript Semantic Relation Graph]
Application --> Validate[结果校验、封存与 Evidence]
Semantic --> Validate
两张图回答不同问题:
| 图 | 主要内容 | 适合问的问题 |
|---|---|---|
| JavaScript Application Graph | 文件、Package、模块、Chunk、入口、Source Map、Electron 边界 | 哪些组件存在,如何组织和连接? |
| JavaScript Semantic Relation Graph | Binding、Callable、Call Site、Argument、Return、Closure 等 | 某个调用或值在允许的静态范围内可能关联到哪里? |
AST 使用 Babel Parser,静态语义分析进一步建立词法 Scope、Binding、模块关系和有限的值、参数与返回关系。它超过单纯的字符串搜索,但没有执行 JavaScript,也不是完整解释器或完整的控制流敏感分析。Parser,静态语义算法
Bundle 恢复靠识别结构
REA 对特定 Webpack/Rspack Chunk 结构读取字面量 Module Table 和 Factory;当前源码也识别 esbuild 的 __commonJS / __esm 字面量 Wrapper。它保留源码切片摘要与结构指纹,不通过执行 Bootstrap 来枚举模块。Chunk 识别,esbuild Wrapper
这仍有格式假设。动态计算的模块表、自定义加载器和混淆可能无法恢复;某些 Runtime 名称、Framework Marker 或路由字段识别只是候选,不能从一个 path 字段就断言应用一定使用了某个路由框架。
Semantic Relation Graph 在本版本还有明确资源上限:全树最多保留 100,000 个节点,每文件最多 20,000 个节点,并在 Coverage 中记录截断与遗漏信息。未截断的语义 Coverage 仍可为 unknown;解析成功不等于完整恢复行为。资源上限及 Coverage,语义限制
Electron IPC 配对是一个清楚的算法例子
REA 收集 BrowserWindow、Preload、contextBridge 暴露成员、IPC 注册和发送位置,再按以下条件配对 Renderer Transmission 与 Main Handler:
- Channel 必须是精确相同的字面量。
- IPC Mode 必须兼容,例如
invoke与handle。 - 只有一个候选 Handler 才是
paired;多个为ambiguous,没有为unpaired。
动态 Channel 不猜测配对,只有唯一配对才生成对应的静态推断边。配对算法,图边与限制
A unique static IPC pairing does not prove runtime registration or reachability. 两段代码使用相同 Channel,并不证明用户点击后一定走到该 Handler。类似地,发现 event.sender 检查只是权限验证候选;发现 JavaScript 请求 .node 成员也不证明该原生导出存在。Sender Validation Candidate,原生成员边界
Browser:运行观察需要区分模式
| 模式 | 实际机制 | 关键边界 |
|---|---|---|
| 普通页面采集 | Attach 已有 CDP Target,启用相关 Domain,观察一段窗口,读取 DOM、Accessibility、Resource Tree 等 | 看不到连接前全部活动;连接与 Instrumentation 本身有影响 |
observe_web_execution | V8 Precise Coverage,取得范围与执行计数 | 重置计数、影响优化执行;不是完整时间线或 UI 因果链 |
| 主动 Scenario | Playwright 执行声明式 goto、click、fill 等步骤,再采集 | 会实际操作页面;有目标应用本身的副作用 |
普通采集只有明确要求才读取 Script Source;分析 Source Map 时也可能发出额外 HTTP 请求。Script Source 开关,Source Map 请求
V8 Coverage 明确报告 resets_execution_counters 和 disables_optimized_execution,缺失 Coverage 不能当成零执行。不能把所有 Browser 工具归为“无影响的被动读取”。普通采集,Coverage 副作用,Scenario 动作
REA 还支持静态与运行时图的 Reconciliation:优先按捕获源代码的 SHA-256 匹配,结合授权的位置映射;多候选保留歧义,内容摘要冲突时不会仅因路径一致就算匹配。无摘要时可在条件满足时采用唯一授权位置,但匹配依据较弱。匹配实现
Bundle 被加载时,内部 Module 可以只是 resident-in-loaded-asset,不能直接写成 Factory 已执行。只有在限定捕获范围与完整性条件满足时,才报告 not-observed-in-capture;这仍不等于应用永远不会使用它。Load State
Evidence:统一结果,但不替代事实判断
Evidence 是项目把多个后端组织起来的关键。主要字段如下:Schema
| 字段 | 作用 |
|---|---|
subject | 目标 SHA-256、格式、架构和显示路径 |
provider、analysis_profile | 记录来源与影响结果的配置 |
operation、parameters | 记录执行了什么操作 |
raw_result、normalized_result | 适用时保留不同于标准结果的原始表示,以及统一结果 |
confidence | observed / derived / inferred 分类,并非数值概率 |
authority | 区分制品、受控运行、历史资料、外部服务或分析者推断 |
limitations、locations、evidence_links | 限制、位置及关联 Evidence |
evidence_id | 对语义内容规范化后计算的 ev_ 摘要 |
结果、参数、来源、配置、限制和关联记录参与 Evidence 摘要。导入时重新检查摘要,可拒绝保留旧 ID 却改动语义字段的记录;目标显示名称与 local_path 不属于目标的语义身份,但其他结果字段仍可能含路径,不能推导成任何搬移都保持相同 ID。摘要与导入检查
An Evidence hash checks content consistency, not the truth of an analysis claim. 这里没有第三方签名或独立可信时间戳。能构造记录的人也能计算新的摘要,因此 Schema 与 Hash 正确,只说明结构和引用一致,不能单独证明引擎真的执行过、推断正确或输入者可信。这是从摘要实现得出的工程判断。Canonical Digest
项目另有 Unknown 记录,维护尚未解决的问题、修订关系、支持与反驳 Evidence。这样,“未观察到”“能力不足”“已有矛盾”可以保留为可追踪状态,不必被压成一个空数组或含糊的成功结果。
完整分析与适合阅读的 View 分开
MCP 成功回复同时提供文本与结构化内容,仍受响应预算和 Node 单字符串上限约束。若已经完成的结果超过投递预算,REA 可以先保留完整 Evidence,再返回 Transport Constraint 与恢复引用,让调用者读取合适的 View、导出 Bundle 或改用完整 CLI JSON;不会截断后假装结果完整。结果投递
这里的“不截断”只针对已完成结果的 MCP 投递。采集窗口、图资源预算和 Provider 能力仍可能使分析本身不完整,必须继续读取 Coverage 与 Limitations。
Session、Snapshot 与 Ledger 是三种状态
| 状态 | 用途 | 生命周期 |
|---|---|---|
| Active Binding | 当前目标、客户端、Provider 和 Analysis Profile | 一个 BinarySession 有一个活跃目标;切换时排队并等待在途调用 |
| Snapshot Cache | 重放允许缓存的精确查询 | 绑定目标内容与分析配置;可显式导入、导出文件 |
| Investigation Ledger | 保存 Evidence 与 Unknown | 正常切换目标时保留,调用 close_binary 时清除,MCP 连接仍可继续使用 |
Snapshot Key 对规范化的 {target, binding, operation, parameters} 计算摘要。结果必须满足能力与副作用条件才能缓存;依赖 GUI 当前位置、修改 Artifact、明确标记 live 等操作不能简单重放。换目标或 Analysis Profile 也不能冒用旧条目。缓存准入,Query Identity
本版本的 10,000 条上限属于 Snapshot Cache 的结果绑定,不是全部 Evidence 的存储上限。IDA 的活跃数据库采用 live 语义,因为外部 GUI 可能改变数据库,前后身份检查也不构成数据库锁。IDA Profile
内存 Snapshot 重放会追加本次没有重跑 Provider 的 Limitation;CLI 的持久 Snapshot 快速路径可以直接返回原有 Evidence。因此,本文建议消费结果时一并记录本次是重放还是新查询,不能仅凭 Evidence 仍然有效就称它为新观察。长期 MCP 连接可以引用同一 Ledger 的 Evidence ID;单次 CLI 进程不能拿另一个连接的 ID 直接查结果,需要完整 Inline Evidence 或导出的文件。REA 也不会因此自动获得跨重启的 Agent 任务恢复能力。内存重放,CLI 快速路径
Skill、Prompt 和算法工具各做什么
REA 的 Skill 是给外部 Agent 的调查方法:选择目标、先读摘要、关注限制、避免重复调用、维护 Unknown、引用 Evidence,并分解复杂问题。MCP Prompt 提供调查文本模板。Enhanced Tool 则将多个操作写成可执行工作流。三者都不在 REA 服务端发起模型循环。
例如原生 trace_feature 实际执行 search_strings、search_procedures 的 Literal Search,然后查询 Xrefs、定位包含该地址的 Procedure。它没有用 Embedding 或模型自动理解一句自然语言对应哪些函数;合理的 Seed、后续调用链和最终解释仍需外部调查过程完成。trace_feature 的实现
项目自身的 Skill 也明确:已有完整源码仓库的普通架构分析应使用常规仓库工具;REA 更适合结论依赖已发布 Binary、Package、反编译或源码无法证明的运行行为时使用。本次研究项目本身,因此直接读源码,不需要先配置反编译器。项目 Skill 的适用范围
可复现实验:验证 IPC 配对,而不运行 Electron
下面的输入只是静态分析 Fixture,没有安装或启动 Electron 的前提。它故意包含顶层 throw;静态读取应成功,执行目标则会失败。运行环境要求与上文相同。
先锁定源码并编译。本例禁用依赖安装脚本,只用于静态路径;不调用 setup,不修改 Agent 配置。
git clone https://github.com/morluto/rea.git rea-source
cd rea-source
git checkout 33b9b31a6fb50cc3e6f4591d0395dbba15b51f13
npm ci --ignore-scripts --no-audit --no-fund
npm run compile
在这个源码目录中创建临时输入,并取得完整 JSON:
rea_sample=$(mktemp -d)
cat > "$rea_sample/package.json" <<'JSON'
{"name":"rea-static-demo","version":"1.0.0","main":"main.js"}
JSON
cat > "$rea_sample/main.js" <<'JS'
const { BrowserWindow, ipcMain } = require("electron");
new BrowserWindow({
webPreferences: { preload: require.resolve("./preload.js") }
});
ipcMain.handle("notes:get", () => ["demo"]);
throw new Error("Static fixture must never execute");
JS
cat > "$rea_sample/preload.js" <<'JS'
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("notes", {
get: () => ipcRenderer.invoke("notes:get")
});
JS
node scripts/rea.mjs analyze-javascript-application "$rea_sample" --json > evidence.json
node --input-type=module -e '
import { readFileSync } from "node:fs";
const e = JSON.parse(readFileSync("evidence.json", "utf8"));
console.log(JSON.stringify({
operation: e.operation,
confidence: e.confidence,
ipc: e.normalized_result.summary.ipc
}, null, 2));
'
进度信息写到 stderr,重定向的文件保存完整 Evidence。验收重点是唯一配对,而不是节点数量。接着做两个输入变更:
- 在 Main 文件再加一个
ipcMain.handle("notes:get", () => ["second"]),静态候选变成两个。这是用于观察歧义的 Fixture,不是正确的 Electron 运行程序。 - 恢复原 Main,将 Preload 成员改成
get: (channel) => ipcRenderer.invoke(channel),Channel 成为无法确定的动态输入。
在 Node.js 26.0.0 中,以固定提交编译出的 CLI 运行上述静态路径,三组结果如下:
| 输入 | Main Handler 数 | paired_renderer_transmissions | ambiguous_renderer_transmissions | dynamic_channel_operations |
|---|---|---|---|---|
| 唯一字面量 Channel | 1 | 1 | 0 | 0 |
| 同 Channel 两个 Handler | 2 | 0 | 1 | 0 |
| 动态 Channel 参数 | 1 | 0 | 0 | 1 |
三组 Evidence 的 confidence 都为 derived。同输入重复分析得到相同 Evidence ID;改变输入后 ID 改变。另在 Fixture 中加入写文件哨兵,分析后文件没有出现;修改 Evidence 的 confidence 却保留原 ID,parseEvidence 拒绝导入。
本次还运行了项目已有的 evidence.test.ts、AnalysisProviderRegistry.test.ts 和 AnalysisSnapshotCache.test.ts,共 40 项通过,覆盖记录一致性、Provider 选择与快照规则。实验没有启动真实 Hopper、Ghidra、IDA 或 Electron;它核验的是该版本对自造静态输入和合同边界的行为。
架构评价与适用边界
从源码看,最值得复用的是四个设计:业务工作流同时供 CLI 与 MCP 使用;目标和 Provider 配置被固定并纳入结果来源;完整结果与供 Agent 阅读的 View 分开;Unknown、Coverage 和副作用成为合同的一部分。这些机制帮助调查过程积累可追踪结果,也减少静默切换后端或把缺口写成结论的机会。
代价是明显的边界复杂度:同一个操作可能涉及 Schema 投影、可用性、目标身份、Profile、缓存策略、Evidence 校验、传输预算和资源清理。只看工具名字或 README,很容易把它理解得比实际实现更强;阅读时应沿一条完整数据流走到后端与结果合同。
使用场景也应明确:分析已发布的原生或 Electron 应用、追踪 Package 的模块与接口、比较版本、把运行观察与静态制品对齐,都与项目主线吻合。完整源码已有答案时,先读源码通常更直接。需要证明重建代码与原行为一致时,仍需针对目标设计输入、输出和失败路径的实际验证;伪代码、静态边或匹配指纹都不能单独替代它。
本地分析只说明 REA 的工具执行位置。外部 Agent 会接收结果,并按自己的模型服务链路处理;Evidence 还可能包含本地路径与目标细节,公开引用时应选取必要字段并脱敏。本文实验输出只展示自造 Fixture 的聚合信息。项目的数据流说明
建议源码阅读顺序与关联阅读
先看 scripts/rea.mjs 和 src/composition/binary.ts,建立入口与依赖关系;再看 src/contracts/toolContracts.ts、src/application/binary/ 和 src/domain/evidence.ts,理解调用与结果合同。随后选一条后端深入:原生分析追到 Bridge 和 Request Queue;JavaScript 则从 JavaScriptApplicationService 追到 Artifact Reconstruction、Electron Pairing 和 Graph Builder。最后用已有测试核对失败、歧义和取消路径。
- Agents Overview:本栏目导航。
- Pi Agent 框架架构:包边界、Agent Loop 与接入选择:对照理解真正管理模型循环的 Runtime 与 REA 工具系统的分工。
- Context7 源码分析:技术架构、MCP 运行原理与检索链路:另一类 MCP 接入层及其后端边界。