【免费下载链接】mex
Team memory for engineers and their AI agents. Lives in your repo. Shared through Git.
MEX 是一款面向工程师及其 AI Agent 的团队记忆工具,其核心能力之一是"代码图谱"(Code Graph):它用Tree-sitter WASM解析源码、把符号与调用关系写入SQLite FTS5全文索引,构建出一张确定性、可复现、不依赖任何 LLM的代码图,让mex graph query、mex impact这类命令能像数据库查询一样精确回答"谁调用了我""这个函数定义在哪"。本文带你拆解这套架构的五个关键设计。
为什么需要"确定性"代码图
很多代码理解工具把仓库内容直接丢给大模型,输出随提示词和随机性漂移;而传统 grep 只能做文本匹配,无法区分"同名的方法"还是"重载的函数"。
MEX 的图谱引擎在接口层面就明确了这一原则:build 是tree-sitter → SQLite,读取是纯 SQL,全流程没有 LLM 参与(见 src/graph/engine.ts)。这意味着:
- 同一份代码,在任何机器上构建出的图字节级一致;
- 读取路径是同步 SQL 查询,毫秒级返回;
- 图谱本身成为一个可校验的数据契约,而不是"模型的印象"。
上图是 MEX Hub 中的 Graph 构建任务:从Discover → Stage → Parse → Resolve → Validate → Publish六个阶段逐段推进,任何一步失败都不会污染已发布的图谱——这是后文会讲的"候选进程 + 原子发布"机制的可视化体现。
第一步:Tree-sitter WASM 解析源码
解析层的核心是 src/graph/extraction/grammars.ts,它封装了web-tree-sitter——一个运行在WASM 上的 tree-sitter 运行时。选 WASM 而不是原生模块,有三个直接收益:
- 免编译安装:
.wasm文件随包分发(见 src/graph/wasm/ 下的 TypeScript、JavaScript、Python、Rust、C# 等语法文件),无需 node-gyp 构建; - 按需懒加载:只有项目中真实出现的语言才会加载对应 grammar,大型仓库不会白白占用 WASM 堆;
- 跨平台一致:同一份 WASM 字节在任何操作系统上产出同一棵语法树。
文件扩展名到语言的映射(.ts、.tsx、.py、.rs、.cs等)是唯一的事实来源,定义在 grammars.ts 第 56-72 行;parse()函数则是语法树进入提取器的唯一边界,提取器永远不直接触碰 web-tree-sitter。
一个容易忽视的细节在 第 164-166 行:解析出的树分配在 Emscripten 堆上,不会被 JavaScript GC 回收,因此每个文件解析完必须显式disposeTree()释放——这是图谱引擎能在巨型仓库上不泄漏内存的关键之一。
第二步:行无关节点 ID,确定性身份的基石
"确定性"最脆弱的地方是身份标识。如果节点 ID 里包含行号,那么上方任意一行代码的增删都会让 ID 变化,所有引用它的锚点(grounding)会静默失效。
MEX 的解法在 src/graph/extraction/node-id.ts:
节点 ID = `${kind}:` + sha256(`${file_path}:${kind}:${name}`…).前 32 位注意哈希输入里没有行号——注释、格式化、上方代码增删都不会改变 ID。这个"Tier-1 身份"故意保持粗粒度:重命名(name 变化)或移动文件(path 变化)仍会表现为"删除 + 新增",而这正是下一层指纹机制要接管的事。
两阶段管线:先单文件提取,再全局解析
图谱构建采用extract → resolve两阶段设计:
- 提取阶段:每个文件独立、纯函数式地解析,产出符号节点和"未解析引用"(
unresolved_refs)。提取器禁止跨文件查询、禁止读文件系统,保证单文件结果可缓存、可复用; - 解析阶段:全量索引完成后,统一把引用绑定成边(
edges)。框架级知识由可插拔的FrameworkResolver补齐——目前覆盖 Express、Next.js App Router、FastAPI、Flask、NestJS(见 docs/code-graph-support.md 的支持矩阵)。
绑定不上的引用不会被丢弃,而是诚实保留在unresolved_refs表中——图谱对自己的盲区是可见的,mex graph query who-calls会明确标注这类降级证据。
第三步:SQLite + FTS5 存储与全文检索
存储层直接复用 Node.js 内置的node:sqlite(要求 Node ≥ 22.5),它编译进了完整的WAL + FTS5 + mmap能力,无需任何原生依赖(见 src/graph/db/sqlite.ts)。MEX 甚至在启动时探测 FTS5 是否可用,缺失时给出可操作的报错而不是生硬的no such module: fts5。
数据契约是一份"冻结"的 schema(src/graph/schema.sql),核心表职责清晰:
| 表 | 职责 |
|---|---|
nodes | 代码符号(函数/类/方法…),带body_hash漂移检测列 |
edges | 符号关系:calls、imports、extends、references… |
files | 文件内容哈希与解析健康度,驱动增量筛选 |
unresolved_refs | 解析失败的引用(图谱的已知盲区) |
node_fingerprints/lsh_buckets | MinHash 指纹与 LSH 倒排(重命名对账) |
全文检索由两张FTS5 虚拟表承担:
nodes_fts(schema.sql 第 214-222 行):索引符号的 name、qualified_name、docstring、signature,通过触发器与nodes表自动同步;source_chunks_fts(第 202-209 行):contentless 模式索引源码分块的标识符与注释词,命中时源码永远从磁盘重读,索引只存坐标。
查询侧用BM25 加权排序(src/graph/db/store.ts 第 957-960 行:name 权重 20、docstring 权重 5、signature 权重 1),配合 src/graph/retrieval/query.ts 里的查询规划器——它会剥离停用词、把BudgetLedger拆成budget/ledger词元、对configuration做保守词干变体(→config),让"用自然语言问代码"也能命中结构化符号:
第四步:MinHash + LSH,让图谱在重命名后"认得人"
Tier-1 ID 能扛住行号漂移,但扛不住重命名。MEX 为此设计了Tier-2 指纹(src/graph/fingerprint.ts):
- 对节点归一化 AST 三元组(丢弃标识符拼写,只保留语法骨架)做MinHash,K=64;
- 指纹连同 caller/callee邻域签名一起存入
node_fingerprints; - 用LSH 分带索引(32 bands × 2 rows)加速候选查找:分带哈希存入
lsh_buckets,两指纹只要任一带哈希相同就进入候选集; - 对账器(src/graph/reconcile.ts)在 Tier-1 未命中时给出三选一裁决:MOVED(静默重绑)、GONE(报错)、AMBIGUOUS(交给人或 Agent 确认)。
这套机制让 Wiki 中"某段说明指向某函数"的锚点,在函数改名或挪文件后依然能自动找回——而不是静默断链。
第五步:增量更新与原子发布
日常开发中mex graph refresh不会全量重建:files表的内容哈希先筛出变更文件,file_extraction_cache复用过期的提取结果,file_row_digests记录每个文件的派生行摘要,只重写过掉文件的行。
更重的 rebuild 则在一次性候选进程中完成(Hub 侧见上文的 Jobs 管线):子进程崩溃、超时、取消都只影响临时工作区,父进程校验通过后才原子改名发布新库;读者永远只打开"最后一次成功发布"的不可变快照(升级规则见 docs/design/graph-v4-compatibility.md)。任何失败都不会让坏数据成为可信图谱。
最终效果:在 Code 页面查看任意符号,Callers/Callees/Impact 都是对 SQLite 索引的确定性查询结果。
上手:三条命令验证你的代码图
mex graph status # 图谱新鲜度与解析健康度 mex graph query who-calls requireSession # 精确的调用关系查询 mex graph scope "trace the authentication flow" # 按任务取有界证据集如果mex check提示某个 Wiki 断言的 grounding 漂移,说明对应节点的body_hash变了——这就是nodes表里那个"demo 没有、MEX 独有"的列在做的事(schema.sql 第 80-86 行):
核心文件索引
- 语法加载与语言检测:src/graph/extraction/grammars.ts
- 行无关节点 ID:src/graph/extraction/node-id.ts
- SQLite 数据契约(FTS5 虚拟表):src/graph/schema.sql
- node:sqlite 适配与 FTS5 探测:src/graph/db/sqlite.ts
- 存储与 BM25 查询:src/graph/db/store.ts
- MinHash 指纹与 LSH 分带:src/graph/fingerprint.ts
- 重命名/移动对账契约:src/graph/reconcile.ts
- 引擎接口(build/sync/search):src/graph/engine.ts
- 查询规划(停用词、词干、标识符拆分):src/graph/retrieval/query.ts
- 语言与框架支持矩阵:docs/code-graph-support.md
一句话总结:MEX 的代码图谱 = WASM 化的确定性解析(Tree-sitter)+ 冻结的 SQLite 契约(FTS5 + 指纹)+ 行无关 ID 与原子发布,三者共同把"问代码"从概率问题变成了数据库问题。
【免费下载链接】mex
Team memory for engineers and their AI agents. Lives in your repo. Shared through Git.
相关推荐
Tree-sitter代码导航与重构
Tree sitter代码导航与重构 Tree sitter 提供了强大的语法树遍历和节点定位功能,使开发者能够高效地分析和操作抽象语法树(AST)。通过树游标
开发工具Handsontable 仓库的 code-graph 技能:用预构建 Tree-sitter 知识图谱取代 Grep+Read 的跨文件代码查询
Handsontable 仓库的 code graph 技能:用预构建 Tree sitter 知识图谱取代 Grep+Read 的跨文件代码查询 本篇文章基于
前端UI组件揭秘Continue代码理解引擎:Tree-sitter如何让AI读懂你的代码
揭秘Continue代码理解引擎:Tree sitter如何让AI读懂你的代码 在AI辅助编程工具层出不穷的今天,开发者们常常面临一个痛点:为什么AI总是"答非
人工智能AI Agent代码智能体开发工具工具调用RAG
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考