代码图谱子系统
packages/ttsc/internal/graph(~4.5k Go LOC)在一个 tsgo Program 上构建 checker 解析的代码引用图:符号是节点,类型解析的关系是边。packages/graph(@ttsc/graph)把这张图通过 MCP 暴露给编码代理,让代理"读零个文件"就回答"什么调用什么、改动波及哪里"。
本子系统页面:
核心理念:checker 解析而非语法猜测
graph 包的包注释(internal/graph/graph.go 与 resolve.go:1)点出关键差异:因为图骑在 ttsc 的 in-process Checker 上,每条边都由真实类型检查器解析,而非语法启发。所以一条边能标"checker-resolved"而不是"guessed"。
README(packages/graph/README.md)对比 codegraph:codegraph 解析代码形状并推断连接,而 @ttsc/graph 问真实 TypeScript 编译器(它已解析过每个 import 与引用),所以图是精确而非推断的。在公共基准上,代理读零文件回答、token 降 77%-86%、工具调用降 94%-95%。
数据模型
Node(graph.go:23)的关键设计是 位置无关 ID:path#name:kind(nodeID,graph.go:120)。从文件 realpath、声明名、kind 构建,所以在声明上方插一行不会re-key 它——这让未来的增量层不必每次编辑都churn 整张图(byte-offset key 会强制 churn)。
Edge(graph.go:83)的 Pos/End 是 evidence(产生边的源表达式范围)而非 identity;重复关系保留第一个源顺序 span。Origin 记录语法形式(value-call 的 call/new/jsx/tagged、heritage 的 extends/implements),让 JSON dump 把一种内部 kind 拆成更细的 schema kind 而 MCP 模型不丢区分。
barrel re-export:图谱的命门
resolve.go 持有图谱依赖的"承重原语":跟随一个引用到 checker 绑定的真实声明。最难的情形是 barrel re-export——pkg/index.ts re-export 兄弟的符号;这种形状承载了 monorepo 里几乎每条跨包边。
停在 GetSymbolAtLocation 会落到本地 import alias、在 index 文件处切断边,把输出塌回 tree-sitter 质量。解包 alias 链(Checker_getAliasedSymbol)落到真正声明符号的兄弟源(resolve.go:48)。Resolve 做这个解包,再分类声明住哪,让 node_modules / .d.ts 边界成为 external leaf 而非把依赖内部拉进图。
详见 构建与解析。
CLI 与 MCP 两个消费者
cmd/ttscgraph:把图 dump 成 JSON(ttscgraph dump)。@ttsc/graph:MCP 服务器(npx @ttsc/graph)+ 3D 查看器(npx @ttsc/graph view)。
@ttsc/graph 的 MCP 工具表面用 typia.llm.controller 从一个 TypeScript 接口反射生成 JSON schema 与参数校验器——没有手写 schema(见 MCP 服务器)。