【免费下载链接】mex
Team memory for engineers and their AI agents. Lives in your repo. Shared through Git.
MEX 是一款面向工程师与 AI 代理的开源团队记忆工具,知识存放在仓库里、通过 Git 共享。它的代码图谱内置了一组框架路由解析器,能自动读懂 Express、Next.js、FastAPI、Flask、NestJS 五大框架的路由代码,把「GET /users→ 哪个处理函数」这条线索变成代码图谱中的真实连接。本文带你一次看懂它背后的实现思路 🧭。
MEX 代码图谱与路由解析器是什么
MEX 的代码图谱会扫描整个仓库,把函数、类、方法等提取为图谱节点,再把文件间的调用、导入关系连成边。但普通语法扫描有一个盲区:路由注册大多是框架行为——app.get("/x", handler)里,路由字符串和处理函数之间并没有显式的函数调用,纯 AST 遍历看不到这层关系。
于是 MEX 在解析管线中预留了一个专门的扩展点 FrameworkResolver:每种框架实现一个解析器,负责补上「路由节点 → 处理函数」这一类只有框架知识才能推导出的关系。解析器注册表在 src/graph/resolution/frameworks/index.ts,当前收录 5 位「选手」。
一次完整的解析:五步工作流程
无论哪个框架,解析流程都遵循同一套骨架(见 src/graph/resolution/resolver.ts):
| 步骤 | 做什么 | 关键点 |
|---|---|---|
1️⃣ 框架检测detect | 判断项目是否使用了该框架 | 只依据项目内的真实证据,检测不到就整体跳过 |
2️⃣ 路由提取extract | 逐文件扫描,生成route节点(如GET /users) | 节点名 = 方法 + 路径,签名携带处理函数名 |
| 3️⃣ 发出引用 | 每个路由节点挂一条指向处理函数名的function_ref未决引用 | 此时只记录名字,不急着绑定 |
4️⃣ 跨文件绑定resolve | 把引用绑定到具体的函数/方法节点 | 只在「同文件且唯一」时才出手,置信度 0.8 |
| 5️⃣ 持久化 | 绑定成功落成一条references边 | 失败则留在「未决引用」记录里,宁缺毋滥 |
这套「先提取、后解析」的两阶段设计,保证构建与增量同步走完全相同的确定性逻辑。
Express:正则匹配app.get("/path", handler)
检测方式:读取package.json,express出现在dependencies或devDependencies中即激活。
Express 解析器(express.ts)用一个正则扫描app或router上的get / post / put / patch / delete / options / head / all注册,且路径必须是字符串字面量:
import express from "express"; const app = express(); export function healthHandler(): void {} app.get("/health", healthHandler);命中后生成GET /health路由节点,并绑定healthHandler。绑定非常克制:只接受同文件内唯一声明的处理函数;若同名函数在别的文件里「恰好唯一」,解析器会拒绝猜测——这个设计有专门的测试用例守护(resolver-express.test.ts)。
FastAPI:装饰器 + 前缀合成,方法列表自动展开
FastAPI 解析器(fastapi.ts)的看点最多:
- 检测:扫描
.py源码里的import fastapi(用词边界排除fastapi_utils等近似包)。 - 路由接收者识别:
app = FastAPI()、router = APIRouter(prefix="/users")都会登记进本文件的「接收者表」,跨模块from .routers import users导入的名字同样认账——这解决了路由声明和 app 创建分文件摆放的常见布局。 - 装饰器解析:
@app.get("/{user_id}")直接成路由;@app.api_route("/x", methods=["GET", "POST"])会展开成两条路由。 - 前缀合成:
APIRouter(prefix="/users")的静态前缀会拼到装饰器路径前面,/users+/{id}→/users/{id}。 - 主动弃权:f-string 动态路径、
%格式化、写在 docstring 里的示例装饰器,一律跳过而不是照抄输出。
一段真实的集成测试(resolver-fastapi-integration.test.ts)构造了两个模块:routers.py声明users = APIRouter(prefix='/users'),app.py导入后注册@users.get('/{user_id}')——最终图谱里出现GET /users/{user_id}节点,完整链路走通。
Flask:与 FastAPI 同源的「装饰器配对」思路
Flask 解析器(flask.ts)与 FastAPI 共享同一套 Python 源文本工具(python-source.ts:先注释/docstring 置空,再做括号配平的逻辑行合并),区别在于框架细节:
- 检测:识别
import flask/from flask import ...,flask_restful不命中。 @app.route("/x")默认 GET;methods=["POST", "PUT"]展开为多条路由;若methods=的值不是字面量列表,则整条路由跳过,绝不猜测成 GET。- Blueprint 前缀:
Blueprint(url_prefix="/admin")的静态前缀同样参与合成。 - 路径转换器保留原样:
/users/<int:user_id>尖括号语法是 Flask 自己的路由语言,原样写入节点名。
NestJS:Controller 前缀 × HTTP 方法装饰器
NestJS 解析器(nestjs.ts)处理装饰器套装饰器的场景:
- 检测:
@nestjs/core或@nestjs/common出现在依赖中。 - 前缀来源:
@Controller("users")或@Controller({ path: "users" })读取静态前缀;前缀不可静态读取(常量、模板插值)时,整个控制器的路由被跳过。 - 状态机:
@Controller绑定到「下一个 class 声明」,一个文件里多个控制器各持前缀、互不串线;@Get(":id")等 HTTP 装饰器再往前扫描,跳过中间夹着的@ApiOperation(...)等其他装饰器(字符串感知的括号配平,引号里的右括号不会误伤)。 - 同名路由消歧:NestJS 版本化路由允许同一文件里出现多个
GET /users,节点 id 通过「序号 + 处理函数名」区分;绑定阶段再用「所属控制器类名」在两个同名方法间精准二选一(测试见 resolver-nestjs.test.ts)。 - 注释免疫:扫描前把注释整体置空,被注释掉的
// @Get('legacy')不会变成幽灵路由。
Next.js App Router:路径就藏在文件名里
Next.js 解析器(nextjs.ts)的思路与众不同——App Router 的路由由文件位置决定:
- 检测:
package.json含next依赖,或仓库里存在route.ts这类文件(后者让 monorepo 子包里的应用也能被识别)。 - 路由路径由目录推导:
app/api/users/route.ts服务于/api/users;src/app根目录会剥掉src前缀;(marketing)路由组不出现在 URL 中;[id]、[...slug]动态段原样保留;_开头的私有文件夹整体退出路由。 - 处理器 = 导出的 HTTP 方法:文件里
export function GET(request) {}或export const GET = ...即处理器;每个方法每个文件最多产出一个路由节点,TypeScript 重载声明不会引发 id 冲突。
路径推导函数deriveRoutePath有大量单元测试守护,包括apps/web/src/app/api/orders/route.ts → /api/orders这类 monorepo 边界场景(resolver-nextjs.test.ts)。
五大框架解析要点速查
| 框架 | 检测依据 | 路由节点来源 | 前缀合成 | 典型弃权场景 |
|---|---|---|---|---|
| Express | package.json依赖 | app/router.方法(路径, 函数) | — | 计算路径、内联回调、中间件链 |
| FastAPI | Python 源码 import | @x.get/post/...与api_route | APIRouter(prefix=...) | f-string 路径、非字面量methods= |
| Flask | Python 源码 import | @x.route与快捷方法装饰器 | Blueprint(url_prefix=...) | 计算路径、非字面量methods= |
| NestJS | @nestjs/core/common依赖 | @Controller+@Get/@Post/... | 控制器静态前缀 | 常量前缀、模板插值路径 |
| Next.js | next依赖或route.*文件 | app/**/route.ts(x)导出的 HTTP 方法 | 目录结构即路径 | _私有目录、非七种 HTTP 方法导出 |
五者共享同一条铁律:绑定只认「同文件且唯一」,置信度统一 0.8;无法确信时输出null而不是猜一条边。动态路由、依赖注入、运行时分发不在承诺范围内——文档对此有明确声明。
在 MEX Hub 中验证解析结果
解析出的路由节点不是孤本:它们进入图谱后即可查询。在 Hub 的 Code 页面可以查看任意函数节点的 Callers / Callees / Impact 视图;图谱健康状态、解析成功率(如179/183 complete)和刷新建议则在 Health 页面实时呈现,截图即上文两张实拍。命令行侧,mex graph的--json输出会列出被跳过的文件与弃权输入,方便你核对语料策略。
源码导读:想深挖从这里入手
| 文件 | 说明 |
|---|---|
| src/graph/resolution/types.ts | FrameworkResolver冻结接口与ResolutionContext定义 |
| src/graph/resolution/resolver.ts | 通用解析管线:导入解析、符号绑定、歧义弃权 |
| src/graph/resolution/context.ts | 解析上下文实现:节点索引快照与按需文件读取 |
| src/graph/resolution/frameworks/index.ts | 五大解析器注册表(社区扩展入口) |
| src/graph/resolution/frameworks/express.ts | Express 参考实现(官方模板解析器) |
| src/graph/resolution/frameworks/fastapi.ts | FastAPI 装饰器、前缀与方法展开 |
| src/graph/resolution/frameworks/flask.ts | Flask 装饰器与 Blueprint 前缀 |
| src/graph/resolution/frameworks/nestjs.ts | NestJS 控制器状态机与注释置空 |
| src/graph/resolution/frameworks/nextjs.ts | Next.js App Router 路径推导 |
| docs/code-graph-support.md | 官方支持矩阵与已知限制 |
| docs/extractors.md | 解析器贡献指南(如何为新框架写解析器) |
如果你想为团队常用的框架补一个解析器,docs/extractors.md 给出了完整路线图:以 Express 实现为模板,补齐「检测 / 提取 / 绑定」三个环节和对应测试,即可接入注册表 🛠️。
【免费下载链接】mex
Team memory for engineers and their AI agents. Lives in your repo. Shared through Git.
相关推荐
WinUtil 使用指南:1 条命令完成 Windows 软件安装、系统优化与故障修复
WinUtil 使用指南:1 条命令完成 Windows 软件安装、系统优化与故障修复 WinUtil(Chris Titus Tech's Windows U
桌面应用运维Understand-Anything 中的 Flask 框架知识库:从提示注入到架构分层,看懂知识图谱如何"读懂" Flask 项目
Understand Anything 中的 Flask 框架知识库:从提示注入到架构分层,看懂知识图谱如何"读懂" Flask 项目 Understand A
AI 技能AI 插件开发工具知识图谱Node-Casbin 集成指南:如何在 Express、NestJS 等框架中使用
Node Casbin 集成指南:如何在 Express、NestJS 等框架中使用 Node Casbin 是一个强大且高效的 Node.js 访问控制库,支
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考