nice-aos — 通用前端代码本体 / 数据库脚本 / 部署配置分析 CLI(React / Vue 2+3 / Flutter / Go / 油猴脚本 / MySQL 迁移脚本 / Docker+K8s+nginx 部署配置)
把任意 React、Vue 2 / Vue 3、Flutter(Dart)前端仓库、Go(CLI / agent 代理 / Gin 后端)仓库或 Tampermonkey 油猴脚本仓库预先分析为结构化本体快照(语义架构分层/功能域/模块/文件/组件/Hook/Composable/Zustand/Pinia/Vuex/Riverpod Store/Service/接口/类/方法/路由/依赖 + import/render/props 传递链/导航/implements/extends/renders/overrides/方法调用链 关系图谱;油猴脚本额外产出 GM API 使用/DOM 注入点/网络端点/脚本函数 + 调用图;Go 项目额外产出 CLI 命令树 / HTTP 路由 / 前后端调用映射),供 AI agent 与开发者通过 CLI 毫秒级查询,替代逐文件 grep。 参考 asdm-aos(Java 代码本体分析)的架构,针对前端生态重新建模:React(React 19 + TypeScript + Vite + Zustand + overlay 路由 / react-router)、Vue 2(Options API + Vuex + element-ui,RuoYi 类中后台)/ Vue 3(SFC + vue-router + Pinia)、Flutter(Dart Widget + GoRouter + Riverpod,轻量语法级解析)、Go(cobra CLI 命令树 + Gin/标准库 HTTP 路由 + 包级调用链 + 前后端融合仓库映射,轻量语法级解析)与油猴脚本(UserScript 元数据 + GM API + 注入/请求审计)。 语义本体引擎:对象按概念范畴与抽象层级(L3 架构 / L2 结构 / L1 单元 / L0 事实)组织;架构分层按内容信号推断(非目录名直译);Module/Domain/Project 自动生成职责画像与自然语言总结。 本体查看器(viewer):
export --format html一键生成自包含蓝图 HTML(零依赖可离线打开,宽屏分档适配),含领域蓝图 / 业务数据图 / 业务逻辑流向 / 脚本蓝图(油猴函数调用图 + DOM 注入锚点 + 网络端点一图呈现)五个视图;纯脚本仓库三视图自动按函数意图分析重建(意图功能域 / 存储枢纽 / 意图流转矩阵),分析不出业务结构时自动隐藏;--format viewmodel输出聚合视图模型 JSON 供 agent 直接消费。
在 1000+ 源文件的前端项目中,让 AI agent 直接 grep 全量源码,响应慢且结构理解易出错。nice-aos 将"文件"升维为"关系图谱":
| 传统方式 | nice-aos |
|---|---|
| grep 谁导入了 ai.ts(遍历全部文件) | link importedBy --src file:src/services/ai.ts(毫秒) |
| 人工追页面跳转关系 | link navigatesTo --src route:dietary_health |
| 不知道哪些文件是死代码 | 快照内置四级死代码(文件/导出/类型/函数级) |
| 单个独立脚本/文件想快速体检(不建快照) | action analyzeFile 不落盘直接输出本体 JSON |
| 循环依赖靠运气发现 | 快照内置 Tarjan SCC(_meta.cycles) |
| 不知道 store 被谁用了 | link usesStore --src store:useThemeStore |
| 接口方法有哪些实现类(实现关系记录在实现类里,正向查不到) | link implementedBy --src "iface:src/types/storage.ts#IStorage" |
| 找某个方法的所有声明与实现 | query Method --where "name~createinterface"(一次命中签名+实现) |
| 审计油猴脚本是否越权调 GM API | query GmApiUsage --where "declared=false" |
| 不知道油猴脚本往页面哪里注入了 DOM | link injectsInto --src us:demo.user.js |
| 说不清项目架构和功能划分 | query Project 看 summary/architecture(分层画像 + 功能域清单 + 健康度) |
| 不知道某目录的职责 | query Module --where "archLayer=state" 看职责画像 |
| 想按功能域浏览代码 | link belongsTo --src dom:health 列出该域全部成员 |
| 想要一张可交互的项目蓝图给人看 | export --format html --output blueprint.html(浏览器直接打开,无需服务) |
| 想给 AI agent / 油猴脚本一个 HTTP 数据源 | nice-aos serve(一行启动,CORS 就绪,暴露快照与蓝图) |
npm install -g nice-aos # 全局安装(需要 Node.js >= 18)
# 或不安装,直接使用:
npx nice-aos query --helpcd /path/to/your-frontend-project
# 1. 构建本体快照(约 3.5 秒 / 1000+ 文件,快照默认写入 ./.nice-aos/data/snapshot.json)
nice-aos action refreshRepo --params '{"repoPath":"."}'
# 2. 查询对象
nice-aos query Project
nice-aos query Component --where "name~steam" # ~ 模糊匹配(子串包含,忽略大小写)
nice-aos query Route --where "domain=health"
# 3. 遍历关系
nice-aos link importedBy --src "file:src/services/ai.ts" # 谁导入了这个文件
nice-aos link renders --src "comp:HealthStatsPage" # 组件渲染了什么
nice-aos link usesStore --src "store:useThemeStore" # store 被谁用了
# 4. 导出全景报告(路由地图 / 导航图 / 循环依赖 / 死代码候选 / Store 一览)
nice-aos export --format markdown --output report.md
# 5. 生成可交互蓝图 HTML(浏览器直接打开,离线可用;--theme 可选 deep-blue / fresh-green)
nice-aos export --format html --output blueprint.html
# 6. 单文件分析(不建快照,stdout 直接输出本体 JSON,可与 jq/findstr 管道组合)
nice-aos action analyzeFile --params '{"file":"Steam-License-Classifier.js"}' | jq '.ScriptFunction[] | select(.deadCandidate)'
# 7. 升级到最新版(全局安装时一键升级;--check 仅检测)
nice-aos update
# 8. 启动本地数据源服务(供 AI agent / 油猴脚本跨源拉取快照与蓝图)
nice-aos serve快照目录解析优先级:
--snapshot-dir参数 >NICE_AOS_SNAPSHOT_DIR环境变量 >cwd/.nice-aos/data>~/.nice-aos/data。
默认扫描 src/(不存在则扫描项目根)。多根目录通过 roots 参数显式指定:
nice-aos action refreshRepo --params '{"repoPath":".","roots":["src","packages/ui/src","packages/core/src"]}'CLI 对项目根的识别是多向的——用户定位到代码子目录、子项目目录或融合仓库根,周边的项目信息都会被识别并处理:
- 上级宿主:定位
src/等代码子目录时向上定位宿主项目根(package.json / pubspec.yaml / go.mod,上限 4 层),读取宿主依赖清单、tsconfig 路径别名与构建配置(hostRoot/hostConfigs字段) - 子项目(subProjects):定位仓库根时发现一级子目录中的子项目(如 gin-vue-admin 的
server/+web/),npm 子项目依赖并入画像辅助框架判定;防误吸附——无.git、无根清单且子项目超过 4 个的「代码集合目录」只报告不并入 - 兄弟项目(siblingProjects):定位子项目目录(
web/)或代码子目录(web/src)时,向上定位仓库根(.git/go.work/pnpm-workspace.yaml/lerna.json/nx.json)后识别同级项目;只报告不并入扫描范围与依赖(显式定位仍是用户意图边界) - Go module 上级发现:定位 Go module 子目录(如
server/api)时向上发现 go.mod(goModule.dir以..相对形态表达),import 路径经折叠解析仍能正确建立 internal 文件边、路由 handler 关联与跨包调用链 - 子目录 go.mod:融合仓库(
server/go.mod+ 前端web/)从.go文件所在目录逐级向上发现全部 go.mod,多模块并存时全部依赖并入、主模块取源码最多者
纯油猴脚本仓库(如 steam-tampermonkey-scripts)直接扫描即可,.user.js 与头部含 ==UserScript== 元数据块的 .js 均自动识别:
nice-aos action refreshRepo --params '{"repoPath":"/path/to/steam-tampermonkey-scripts"}'
# 审计示例
nice-aos query UserScript --where "riskLevel=high" # 高风险脚本
nice-aos query GmApiUsage --where "declared=false" # 越权 GM 调用
nice-aos query InjectionPoint --where "interpolated=true" # 动态插值 XSS 面
nice-aos link calls --src "fn:steam-game-library-viewer/steam-game-library-viewer-2.10.0.user.js#renderOverview"支持 Flyway 风格的 MySQL 迁移脚本目录(.sql 文件)分析,产出独立的数据库模型和数据蓝图:
# 1. 扫描迁移脚本目录(产出 db-snapshot.json,与代码快照分离)
nice-aos db scan --dir /path/to/migrations
# 2. 查询数据库结构
nice-aos db query tables # 所有表
nice-aos db query tables --where "domain=auth" # 按领域过滤
nice-aos db query tables --where "patterns~soft_delete" # 按模式过滤
nice-aos db query foreignKeys # 外键关系
nice-aos db query migrations --where "version~V2.1" # 迁移历史
nice-aos db query domains # 领域分组
# 3. 生成数据蓝图 HTML(自包含,含 SVG ER 关系图,5 Tab;默认 fresh-green 淡绿主题)
nice-aos db export --format html --output db-overview.html
nice-aos db export --format html --theme deep-blue --output db-overview.html # 切换深蓝暗色主题
# 4. 增量扫描(仅处理新增/修改的迁移文件)
nice-aos db scan --dir /path/to/migrations --incremental数据库模型对象:表(Table)/列(Column)/外键(ForeignKey)/索引(Index)/迁移(Migration)/领域(DbDomain)/视图(View)/触发器(Trigger)/存储过程(Procedure),自动检测模式特征(软删除/审计字段/多租户/自引用/UUID主键)和领域分组。
数据蓝图 HTML 内嵌 <script id="db-viewer-data"> JSON 数据,蓝图 AI 助手(Tampermonkey 脚本)自动检测并切换至数据库分析模式。
扫描项目部署目录(如 ./deploy),解析 docker-compose / K8s manifest / Dockerfile / nginx.conf / .env / 部署脚本,产出独立的部署架构模型和部署蓝图:
# 1. 扫描部署配置目录(产出 deploy-snapshot.json,与代码/数据库快照分离)
nice-aos deploy scan --dir /path/to/deploy
# 2. 查询部署架构
nice-aos deploy query services # 所有服务
nice-aos deploy query services --where "type=gateway" # 按类型过滤
nice-aos deploy query routes # nginx 路由
nice-aos deploy query upstreams # nginx upstream
nice-aos deploy query dependencies # 服务依赖关系
nice-aos deploy query middleware # 中间件(MySQL/Redis/...)
nice-aos deploy query environments # 环境配置文件
nice-aos deploy query layers # 部署分层
# 3. 部署架构审计(5 大场景)
nice-aos deploy audit health # 综合健康评分(安全/高可用/一致性/依赖 加权)
nice-aos deploy audit security # 安全:latest 镜像/明文敏感值/端口暴露
nice-aos deploy audit resilience # 高可用:健康检查/探针/副本/资源限额
nice-aos deploy audit consistency # 配置一致性:环境漂移
nice-aos deploy audit dependency # 依赖:断链/循环依赖
# 4. 生成部署蓝图 HTML(自包含,8 Tab,分层拓扑 + SVG 依赖图;默认 deep-blue 深蓝主题)
nice-aos deploy export --format html --output deploy-overview.html
nice-aos deploy export --format html --theme fresh-green --output deploy-overview.html # 切换淡绿浅色主题
# 5. 增量扫描(无文件变化时直接复用快照)
nice-aos deploy scan --dir /path/to/deploy --incremental部署模型对象:服务(Service,12 类:网关/前端/后端/适配器/任务/数据库/缓存/对象存储/搜索引擎/注册中心/可观测/CI-CD/工具)/路由(Route,nginx location → proxy_pass)/上游(Upstream)/依赖(Dependency,depends_on + 环境引用 + 路由推导)/中间件(Middleware,含版本与消费方)/环境(Environment,敏感值自动脱敏)/分层(Layer,9 层部署拓扑)。跨文件同名服务自动归一化合并,${VAR:-default} 镜像插值解引用。
部署蓝图 HTML 内嵌 <script id="deploy-viewer-data"> JSON 数据,蓝图 AI 助手(Tampermonkey 脚本)自动检测并切换至「部署蓝图」智能体(12 个专属工具)。
三类蓝图(代码 blueprint / 数据 dataoverview / 部署 deployoverview)的 CSS 已拆分为「主题 token + 共享骨架 + 查看器专属布局」:布局骨架固定,视觉风格经 --theme 切换(主题注册表 src/themes/index.js 可扩展)。健康审计评分为炫彩 SVG 能量环——渐变弧 + 辉光滤镜 + 加载动画,环配色随主题(深蓝:紫→绿 / 淡绿:淡绿→深绿 / 典雅紫:紫→粉)。
| 蓝图 | 默认主题 | 命令 |
|---|---|---|
| 部署 deployoverview | deep-blue | deploy export --theme <name> |
| 数据 dataoverview | fresh-green | db export --theme <name> |
| 代码 blueprint | deep-blue | export --theme <name> |
可用主题:deep-blue(深蓝暗色)/ fresh-green(淡绿清新)/ elegant-purple(典雅紫)。
18 种对象类型按「概念范畴」(is-a 族)与「抽象层级」(L0-L3)双维组织,而非平铺罗列:
| 抽象层级 | 名称 | 说明 | 类型 |
|---|---|---|---|
| L3 | 架构层 | 产品级聚合:整体架构画像与功能域划分 | Project, Domain |
| L2 | 结构层 | 代码组织结构:模块、文件、路由、脚本与运行环境 | Module, SourceFile, Route, UserScript, Dependency |
| L1 | 单元层 | 可独立理解的代码单元(CodeUnit 概念族) | Component, Hook, Store, Service, Interface, Class, Method, ScriptFunction, PropEdge |
| L0 | 事实层 | 审计事实(AuditFact 概念族):从代码提取的行为证据 | GmApiUsage, InjectionPoint, NetworkEndpoint |
概念范畴:Container(Project/Domain/Module/SourceFile,按结构聚合)、CodeUnit(Component/Hook/Store/Service/Interface/Class/Method/ScriptFunction/PropEdge,可独立理解的逻辑单元与单元间关系边)、EntryPoint(Route,用户可触达的行为入口)、Script(UserScript,独立于宿主应用的脚本形态)、Environment(Dependency,外部环境要素)、AuditFact(GmApiUsage/InjectionPoint/NetworkEndpoint,安全审计原子事实)。
聚合节点(Project/Domain/Module)自动生成职责画像与自然语言总结(summary/architecture/health),避免"只罗列事实、没有抽象"。
| 类型 | ID 前缀 | 层级/范畴 | 关键属性 |
|---|---|---|---|
| Project | proj: |
L3 Container | framework(flutter/dart/expo/react-native/next/nuxt/vue/react/go/userscript), frameworkVariants(tauri/electron/capacitor/vite/riverpod/go_router 等变体), frameworkLabel(组合标签), language(TypeScript / TypeScript + Rust 等), hostRoot/hostConfigs(宿主定位证据,扫描子目录场景), goModule(module 名/Go 版本/所在目录,含子目录与上级形态), subProjects(一级子目录中的子项目清单:path + kind go/npm/dart), siblingProjects(定位子项目或代码子目录时的兄弟项目清单), fileCount, tsxFileCount, vueFileCount, rustFileCount/dartFileCount/goFileCount, tauriDetected/electronDetected/flutterDetected, userScriptFileCount, commitHash, branch, summary(框架定位 + 分层画像 + 功能域清单), architecture(语义分层占比), health(循环依赖/死代码四级/未声明依赖/高风险脚本/解析错误), analysisErrors |
| Domain | dom: |
L3 Container | name, sources(route/module), routeCount, componentCount, storeCount, scriptCount, fileCount, lineCount, capability(路由能力描述), summary(职责画像) |
| Module | mod: |
L2 Container | path, archLayer(语义架构层), layerComposition(子树层构成), fileCount, subtreeFileCount, parentId, unitCounts, routeCount, summary(职责画像) |
| SourceFile | file: |
L2 Container | path, archLayer, lineCount, isTest, isEntry, importIds, exportNames, unusedExports(导出级死代码候选) |
| Component | comp: |
L1 CodeUnit | kind(page/modal/card/…), propsCount, propsNames(解构 props 名清单), hooksUsed, stateCount, rendersIds, routeIds, propOutCount/propInCount(props 传递出入度), archLayer, domainIds |
| Hook | hook: |
L1 CodeUnit | name, filePath, lineCount, description(React Hook 与 Vue composable 统一归属), archLayer, domainIds |
| Store | store: |
L1 CodeUnit | stateKeys, actionKeys, hasPersist, storageKey, providerType(zustand/pinia/vuex/riverpod 状态库类型), location, archLayer, domainIds |
| Service | svc: |
L1 CodeUnit | pattern(singleton/class/functions), exportsCount, archLayer, domainIds |
| Interface | iface: |
L1 CodeUnit | exported, language(ts/vue/rust/dart/go), methodIds, extendsIds/extendsNames(接口继承,跨文件解析;Rust trait 的 supertrait → extends), deadCandidate/deadReason |
| Class | class: |
L1 CodeUnit | exported, language(ts/vue/rust/dart/go), isSingleton, methodIds, implementsIds/implementsNames, extendsId/extendsName(跨文件解析,含 type-only 与别名导入;Rust struct/enum → kind 区分,含 fields/derives/variants;Dart Widget → isWidget/widgetBase,Dart Store → isStore/withNames;Vue 组件 → vclass: kind=component,props 为 fields、computed/methods 为 methods;Go struct → kind=struct,字段含 json/yaml tag), rendersIds(组件组合), deadCandidate/deadReason |
| Method | method: |
L1 CodeUnit | ownerKind(class/interface/module), ownerName, isStatic/isAsync, signature(仅展示), overridesId/overriddenByIds(接口/父类方法 ↔ 实现类方法双向), callIds/calledByIds/compCallIds(Dart 方法逻辑调用链:方法间双向 + Widget 构造渲染链;Go 包级/跨包/方法调用同构映射), exported(Rust impl fn 与模块级 fn 同构映射;Go 首字母大写 = 导出), deadCandidate/deadReason(函数级死代码候选) |
| ScriptFunction | fn: |
L1 CodeUnit | kind(function/arrow/class/object/method), lineCount, callCount, calledByCount, gmApiCalls, callIds/calledByIds, deadCandidate/deadReason(函数级死代码候选), archLayer=script |
| Route | route: |
L2 EntryPoint | overlayId, routePath, routeType(overlay/react/vue/flutter/next/next-api/go/go-cli), domain, domainIds, componentFileId, navigatesToIds, rawPath/layoutFileIds/specialFiles/isDynamic/isClient/apiMethods(Next.js App Router 路由), hasPropsFactory/factoryProps(overlay 路由 props 工厂注入键), middlewares/frontendCalls(Go HTTP 路由中间件链 + 前端调用方溯源;go-cli 命令链与 flags 复用 specialFiles) |
| PropEdge | prop: |
L1 CodeUnit | fromComponentId/toComponentId, fromFileId/toFileId, props(名称 + 来源分类 + valueText + storeHook), renderCount(该组件对的渲染处数) |
| UserScript | us: |
L2 Script | name, version, matches, grants, connects, hostFramework(vue/react/unknown), riskLevel, isIife, usesStrict, unsafeWindowReads/Writes, deadFunctionCount, archLayer=script, domainIds |
| Dependency | dep: |
L2 Environment | version, scope, source(npm/workspace/undeclared/pub/go), importCount |
| GmApiUsage | gm: |
L0 AuditFact | name, category(network/storage/style/…), callCount, declared(与 @grant 比对) |
| InjectionPoint | inject: |
L0 AuditFact | kind(mount/inner-html/insert-adjacent/document-write/style-gm/style-element/shadow-dom), target, interpolated(动态插值 XSS 面) |
| NetworkEndpoint | net: |
L0 AuditFact | kind(gm-xhr/fetch/xhr/websocket/beacon), domain, urls, methods, allowedByConnect(与 @connect 比对) |
Method ID 约定:类/接口方法 method:<file>#<Owner>#<name>,模块函数 method:<file>#<fnName>;query Method --where "name~xxx" 一次命中接口签名、类实现与模块函数。
每个文件/模块推断一个语义架构层,以内容信号为准(单元构成、路由归属、引用结构),目录名仅作弱信号回退:
entry(入口)→ presentation(表现)→ state(状态)→ service(业务)→ integration(集成)→ shared(共享)→ types(类型)→ config(配置)→ tauri(Tauri 原生层,src-tauri Rust 代码强信号直判)→ electron(Electron 主进程,electron/ 目录强信号直判)→ script(油猴脚本)→ test(测试)→ mixed(混合,单一模块内构成分散、主导层 < 60% 时如实标记)
功能域(Domain)与架构层正交:架构层是纵向技术切片,功能域是横向业务切片(由路由域段 + 业务命名目录聚合而成)。
contains Project → Domain/Module → SourceFile → Component/Hook/Store/Service/Interface/Class/Method/UserScript(类型实体也可从 iface:/class: 下钻其方法)
imports / importedBy 文件级依赖(含 dep: 外部包)— 变更影响分析主链路
renders / renderedBy 组件 JSX/template 渲染关系
passesProps Component → Component / PropEdge → 两端组件(props 传递链:正向查某组件把 props 传给了谁;传 prop: 边 ID 返回两端组件)
navigatesTo Route → Route(React 的 Navigate/overlay 跳转、Vue 的 router.push/replace、Flutter 的 context.go/push GoRouter 导航边)
registers Route ↔ Component(路由注册)
usesStore / usesHook Store/Hook 使用关系(src 传 store:/hook: 反查使用者)
implements / implementedBy Class ↔ Interface 实现关系(双向:正向查类实现了哪些接口;反向查接口被哪些类实现 — 解决"实现关系记录在实现类里、从接口正向查不到"的断层)
extends / extendedBy Interface/Class 继承关系(双向)
overrides / overriddenBy Method 方法覆盖关系(双向:类方法 → 所实现的接口/父类方法;接口方法 → 全部实现)
usesGmApi UserScript ↔ GmApiUsage(src 传 gm: 反查所属脚本)
injectsInto UserScript ↔ InjectionPoint(DOM 注入点;src 传 inject: 反查所属脚本)
requestsTo UserScript ↔ NetworkEndpoint(网络端点;src 传 net: 反查所属脚本)
calls / calledBy ScriptFunction 调用图(脚本内函数间静态调用关系,双向)与 Dart Method 逻辑调用链(method: 前缀,含 Widget 构造渲染链)
belongsTo 功能域归属(双向:src 传 dom: 列出域全部成员;src 传 mod:/comp:/store:/hook:/route: 反查所属功能域)
query Project # 项目画像(summary/architecture/health)
query Domain --pretty # 功能域地图(横向业务切片)
query Route --all # 全部路由
query Component --where "kind=page" --pretty # 页面类组件,表格输出
query SourceFile --where "layer=services,isTest=false"
query Component --where "name~steam" # ~ 模糊匹配(忽略大小写子串)
query Module --where "archLayer=state" --pretty # 按语义架构层过滤模块
query Component --where "domainIds=dom:health" # 按功能域过滤成员
query Dependency --where "source=undeclared" # 未声明依赖(治理点)
query Store --where "hasPersist=true" # 持久化 store
query UserScript --where "hostFramework=vue" # Vue 宿主页面的油猴脚本
query UserScript --where "riskLevel=high" # 高风险脚本
query GmApiUsage --where "declared=false" # 未在 @grant 声明的 GM 调用(越权面)
query InjectionPoint --where "interpolated=true" # 动态插值 HTML 注入(XSS 面)
query ScriptFunction --where "kind=class" --pretty # 脚本内类(逻辑分布)
query Method --where "name~createinterface" # 按名找方法:一次命中接口签名/类实现/模块函数
query Method --where "ownerKind=interface" --pretty # 全部接口方法签名
query Interface --where "exported=true" # 导出接口清单
query Class --where "isSingleton=true" # 单例类
query Method --where "deadCandidate=true" # 函数级死代码候选(保守判定)
query Interface --where "deadCandidate=true" # 死接口(类型级)
query Class --where "deadCandidate=true" # 死类(类型级)
query ScriptFunction --where "deadCandidate=true" # 油猴死函数(函数级)
query PropEdge --where "id~SettingsOverlay" --pretty # 按组件名查 props 传递边(含来源分类)--where 语法:逗号分隔多条件 AND;k=v(或 k:v)精确相等,k~v 模糊包含;值为数组时精确做成员包含、模糊做任一成员包含(如 hooksUsed=useEffect)。默认返回前 50 条,--all 全量、--limit <n> 限制。
link importedBy --src "file:src/services/exerciseService.ts" # 变更影响分析
link renderedBy --src "comp:ExerciseReportPage"
link passesProps --src "comp:SettingsOverlay" # 该组件把 props 传给了谁(数据流正向)
link passesProps --src "prop:SettingsOverlay→SettingsSection" # 传递边两端组件
link navigatesTo --src "route:dietary_health" # 页面导航图
link registers --src "route:talent_result" # 路由 ↔ 组件
link usesStore --src "store:useThemeStore"
link usesHook --src "hook:useUserProfile"
link contains --src "mod:src/components/health" # 层次下钻
link usesGmApi --src "us:steam-game-library-viewer/steam-game-library-viewer-2.10.0.user.js" # 脚本用了哪些 GM API
link injectsInto --src "us:demo.user.js" # 脚本注入了哪些 DOM 点
link requestsTo --src "us:demo.user.js" # 脚本请求了哪些域名
link calls --src "fn:demo.user.js#renderOverview" # 函数调用了谁(调用图正向)
link calledBy --src "fn:demo.user.js#renderOverview" # 谁调用了该函数(反向影响面)
link belongsTo --src "dom:health" # 功能域 → 全部成员
link belongsTo --src "comp:HealthStatsPage" # 反查组件所属功能域
link implements --src "class:src/impl/localStorage.ts#LocalStorage" # 类实现了哪些接口
link implementedBy --src "iface:src/types/storage.ts#IStorage" # 接口被哪些类实现(反向)
link extends --src "class:src/core/repo.ts#UserRepo" # 类继承的父类
link overriddenBy --src "method:src/types/storage.ts#IStorage#get" # 接口方法的全部实现
link overrides --src "method:src/impl/localStorage.ts#LocalStorage#get" # 实现方法覆盖的契约方法
link contains --src "iface:src/types/storage.ts#IStorage" # 接口下钻其方法签名action refreshRepo --params '{"repoPath":"."}'
action analyzeFile --params '{"file":"Steam-License-Classifier.js"}' # 单文件分析(不落盘,stdout 输出本体 JSON)
action markReviewed --params '{"objectId":"comp:TalentResultPage"}'
action addNote --params '{"objectId":"comp:TalentResultPage","note":"核心页面"}'analyzeFile 支持 .ts/.tsx/.js/.jsx/.mjs/.vue/.rs/.dart 与油猴脚本(相对 cwd 或绝对路径);油猴文件输出 UserScript/GmApiUsage/InjectionPoint/NetworkEndpoint/ScriptFunction 五类,其余文件输出 Interface/Class/Method;单文件模式下仅"本文件内零引用"的非导出实体判死(导出实体无法判定跨文件使用,一律不判死)。
export --format markdown --output report.md # Markdown 全景报告
export --format json | jq '._meta.cycles' # JSON 供 jq 聚合
export --format html --output blueprint.html # 自包含蓝图 HTML(本体查看器)
export --format viewmodel # 视图模型 JSON(聚合数据,供 agent 消费)Markdown 报告含执行摘要(项目总结句 + 健康指标表)、架构总览(语义分层)(层/定位/文件数/占比)、功能域地图(Domain)(域/来源/路由/组件/Store/脚本/职责画像)、接口与实现(接口清单 + implementedBy 实现类 + 方法覆盖矩阵)、类与方法(类清单含 implements/extends/单例 + 契约热点 Top 30)与死代码候选四级(文件级 + 导出级 + 类型级 + 函数级)等章节,以及模块 Top 30(语义层 + 层构成 + 职责画像)。
nice-aos update --check # 仅检测:输出 JSON(current / latest / upToDate / installMode)
nice-aos update # 一键升级:全局安装时自动 npm install -g nice-aos@latest安装模式自动判定(installMode 字段):global(npm 全局安装,可直接一键升级;含 npm install -g <本地目录> 的符号链接形式,升级会替换为 registry 版本)/ npx(缓存运行,指引 npx nice-aos@latest 拉新)/ local(项目依赖,指引宿主项目内升级)/ repo(仓库源码运行,跟随 git)。检测用两个互补信号:调用入口路径(保留符号链接,process.argv[1])+ 模块真实路径布局(lib/node_modules/nice-aos 强信号,覆盖 homebrew/nvm 多 prefix 环境)。
Agent 前置校验约定(三个 skill 的前置条件均要求):npm 包方式(全局/npx)首次调用前先 update --check 确认最新版——分析能力随版本演进,旧版会缺失新对象类型/字段/命令;update 命令不存在说明版本 < 0.10.0,先执行一次 npm install -g nice-aos@latest;网络不可达时返回 ok:false(带 current 版本号),跳过升级不阻塞主流程。仓库内源码方式版本跟随 git,无需检测。
nice-aos serve # 默认 http://127.0.0.1:8420,服务 <root>/.nice-aos/data 与 <root>/blueprint.html
nice-aos serve --port 39481 # 指定端口(传 0 自动分配可用端口)
nice-aos serve --dir path/to/data # 显式指定快照目录(等价全局 --snapshot-dir / NICE_AOS_SNAPSHOT_DIR)
nice-aos serve --host 0.0.0.0 # 需要局域网访问时(默认仅本机 127.0.0.1)为 AI agent / 油猴脚本 / 网页提供跨源 HTTP 数据源(全端点 CORS *):
| 端点 | 内容 |
|---|---|
GET /snapshot.json |
完整本体快照 JSON(refreshRepo 产物) |
GET /blueprint.html |
蓝图页面(可直接浏览器打开) |
GET /api/status |
服务状态:目录解析结果、快照/蓝图就绪状态、端点清单 |
GET /api/stats |
快照统计摘要:项目名/框架/对象计数/循环依赖/死代码候选 |
GET / |
状态首页(HTML) |
就绪状态每次请求实时探测——"先起服务、后 refreshRepo / export"的工作流无需重启;快照缺失返回 404(附生成指引)、JSON 损坏返回 500。目录解析链:--dir → 全局 --snapshot-dir → NICE_AOS_SNAPSHOT_DIR → <root>/.nice-aos/data。典型配套用法见 contrib/blueprint-ai-agent。
src/ontology/viewer.js 是本体体系的使用者视图层,数据流为:快照 DataMap → buildViewerModel()(数据聚合)→ renderViewerHtml()(视图渲染)。视图模型(JSON)独立于渲染,可被 AI agent 与其他前端直接消费:
| 视图 | 内容 | 回答的问题 |
|---|---|---|
| 总览 | 项目画像、本体蓝图(taxonomy 概念分类体系 + 15 种对象/链接类型 + 实例计数)、健康度 | 这个仓库是什么、本体里都有什么 |
| 领域蓝图 | 每个功能域的业务层级构成(script/presentation/service/…)、代码组织(模块清单)、单元清单(组件/Store/Hook/Service/脚本)与职责画像;纯脚本仓库自动切换为意图功能域(按函数意图分组:渲染注入/数据获取/状态存取/事件监听/元素构建/纯逻辑) | 各业务领域的层级关系与代码组织关系 |
| 业务数据图 | Store 数据枢纽(state/action 键、持久化、被哪些域使用)、跨域数据依赖、持久化状态汇总;无 Store 时自动切换为脚本存储枢纽(localStorage/sessionStorage/indexedDB/GM 存储信号 + 状态存取函数 + 宿主数据读取) | 业务数据在哪、谁依赖谁 |
| 业务逻辑流向 | 架构层间导入流向矩阵(行=来源层,列=目标层)、跨域依赖边、高扇入 Service/Store 枢纽;无模块导入时自动切换为函数意图流转矩阵(调用边按「调用方意图 → 被调方意图」聚合)+ 高扇入函数 | 业务逻辑怎么流、哪些节点是枢纽 |
| 路由地图 | 路由导航链 SVG 图(节点按导航跳数分层:入口 → 1 跳 → 2 跳…,边框色 = 路由类型,悬停高亮相邻路由、点击查看详情含 use client/layout 链/API 方法)、路径层级树(动态段琥珀色高亮)、域分组、类型分布与入口/孤岛路由统计、全量路由清单表(导航去向/被导航双向);覆盖 overlay / react-router / vue-router / Flutter GoRoute+原生 / Next.js App Router 全类型 | 页面怎么组织、怎么互相跳转:入口在哪、哪些路由是孤岛 |
| 组件数据流 | Props 传递图 SVG(BFS 分层:顶层容器 → 子组件,边标签 = props 数,节点边框色 = 所属域,悬停高亮相邻边、点击查看 props 明细含来源与 store hook)、props 来源分布(forward/state/store/handler/computed/literal/spread 七类)、高传出/高传入组件 Top 榜(props 分发枢纽 vs 消费方)、Props 传递边清单(含跨域标记与渲染处数);域筛选与组件名/文件路径搜索;React JSX 与 Vue 模板绑定同构接入 | 数据怎么在组件间流动:谁分发 props、谁消费 props、某个 prop 从哪来 |
| 脚本蓝图 | 每个油猴脚本的函数调用关系图(SVG,从左到右为调用深度)、DOM 注入锚点、网络端点、函数业务角色分布(render/data/state/event/ui/logic) | 这个脚本怎么注入页面的:谁调谁、注入到哪个页面锚点、请求哪些域 |
| 实体类图 | UML 风格类图(SVG):类框(名称 + 字段/变体 + 方法摘要,Rust struct 含 derives)、关系边(implements 虚线 / extends 实线 / renders 绿色实线(Vue 组件组合)/ 接口继承)、按派生层级分列布局;语言/类型/架构层分布条形图;模块/类型/语言/关键词过滤与实体清单表格;Vue 组件合成为 «component» 实体(props 为字段、computed/methods 为方法) |
类型体系长什么样:谁实现谁、谁继承谁、跨语言(TS ↔ Rust ↔ Vue 组件)实体各占多少、Vue 组件组合谁 |
生成的 HTML 自包含零依赖(数据内嵌为 JSON,无外链),可直接离线打开分享;大仓库单元清单带截断保护(计数保留全量);宽屏分档适配(1600/1920/2240/2560px 断点扩展内容宽度并居中,SVG 图等比缩放不截断);油猴意图适配:无 React/Vue 结构的纯脚本仓库三视图按函数意图重建,分析不出有效数据(纯功能增强脚本:单一意图/无调用流转/无持久化)时对应 Tab 自动隐藏,不显示空壳。
脚本蓝图(逻辑注入链)是油猴脚本开发者的核心视图:函数节点按调用深度分层布局,实线为函数调用、青色虚线为 DOM 注入(指向还原后的页面锚点如 querySelector('#app'))、紫色点线为网络请求(指向域名端点);悬停高亮相邻节点、点击查看函数详情(角色/行号/调用关系/注入目标)。注入点与网络端点均携带归属函数(fns/fnIds),配合函数业务角色(按函数内行为推断:innerHTML/挂载 → render,网络请求 → data,GM 存储/localStorage → state,监听/观察/定时 → event,createElement → ui),一图直读"入口函数 → 调用链 → 注入锚点/网络域"的完整逻辑注入链。
- 导入解析:tsconfig
paths别名(@/*→src/*)、vue.config.jsconfigureWebpack.resolve.alias、jsconfig.json paths、子路径别名、相对路径 + 扩展名探测(.ts/.tsx/.js/.jsx/.vue/.dart/index.*)、.js→.ts回退;vue-cli 项目(vue.config.js +src/)自动兜底@/* → src/*;Dartpackage:/dart:导入(package:自身包名/...→ 项目内 lib/ 路径,其余 → pub 依赖;dart:内置库跳过;无./前缀的裸相对导入同样解析);资产后缀(css/png/svg…)跳过;tsconfig.json 含////* */注释也能解析(自动剥离) - 组件识别(React):
.tsx导出的 PascalCase 符号;支持export default function X、export const X: React.FC、分离式export default X、memo()/forwardRef()包装;kind 按名称后缀推断(Page/Modal/Card/…),pages/目录下被路由直接引用的组件自动升级为 page - 组件识别(Vue):
.vueSFC 整文件即组件;defineOptions({ name })与<script setup name="X">属性优先,否则文件名派生(index.vue→ 目录名);defineProps数组/对象形式计数;template 标签(kebab/PascalCase 统一)供 renders 关系 - Hook/Composable 识别:导出的
useXxx符号(含 React Hook 与 Vue composable),含 JSDoc 描述提取 - Store 识别:Zustand
create(...)(含create<T>()(...)、persist(...)包装)、PiniadefineStore(...)(setup 写法 + options 写法,含persist插件第三参数)与 Vuex 模块(对象字面量 /new Vuex.Store({})/ shorthand 引用),统一提取 state/action 键与 storageKey,并携带providerType(zustand/pinia/vuex)区分状态库 - Service 识别:
/services/目录或名称含 Service/Engine/Manager/Repository/Factory 后缀 - 类型实体(Interface/Class/Method):接口/类/方法/模块函数全量提取;跨文件
implements/extends解析(本文件声明优先,其次具名导入——含import type与IStorage as StorageContract别名导入,解析失败留存原名不报错);方法级overrides/overriddenBy双向链接(实现类方法与接口/父类方法按名匹配);query Method --where "name~xxx"一次命中声明与实现 - Rust 实体(Tauri src-tauri,独立解析器):
rustAnalyzer与 tsAnalyzer/vueAnalyzer 平级共存——pub struct/pub enum→ Class(kind: struct/enum,含 fields/derives/variants)、pub trait→ Interface(supertrait → extends)、impl块内fn→ Method(ownerKind=class)、模块级fn→ Method(ownerKind=module)、use→ imports;跨文件路径解析以use crate::a::B模块路径映射为主、全仓库唯一名匹配兜底(含use a::{B, C}花括号组与super::相对路径);Rust 类型引用即使用(Vec<Game>/-> Game/impl Game均计入引用),同样参与类型级死代码判定 - Dart/Flutter 实体(lib/ 组件,独立解析器):
dartAnalyzer轻量语法级解析(深度状态机 + 等长噪声剥离)——abstract class→ Interface、class/enum/mixin→ Class(extends/implements/with 关系、字段、方法)、类方法/顶层 fn → Method;Widget 基类(StatelessWidget/StatefulWidget/ConsumerWidget 等)→ Component(kind: page/widget,dartdoc 描述提取,文件名匹配主组件);ChangeNotifier/Notifier 子类与 Riverpod Provider 变量(final xxxProvider = NotifierProvider<...>.new(...),含 notifierClass 提取)→ Store(stateKeys/actionKeys);GoRoute(path/builder)→ dartRoutes(路径常量引用回填,builderWidget 跨文件组件解析);context.go/push('/path')→ overlayOpens → 路由导航边;方法体内调用 → callEdges → Method 逻辑调用链(本类方法/顶层函数/跨文件静态方法双向链接 + Widget 构造 → compCallIds 渲染链) - 客户端组件自动发现(Tauri/Electron/Flutter):显式 roots 之外自动发现项目内的客户端组件——
src-tauri/tauri.conf.json存在时把src-tauri/src纳入扫描(.rs 文件),electron/目录含 TS/JS 文件时纳入扫描,pubspec.yaml+lib/存在时把lib纳入扫描(.dart 文件,monorepo 多包递归发现);tauriDetected/electronDetected/flutterDetected落到 Project 画像,架构层新增tauri(Rust 原生层)与electron(主进程层)强信号直判;.rs仅在 Tauri 组件语境下扫描,Go 代码见下方「Go 适配」章节(Java 等其他后端暂不在扫描范围) - 死代码候选(四级):文件级(零引用 + 非入口 + 非测试 + 非路由组件,
_meta.orphanCandidates)+ 导出级(导出符号全仓库零导入且本文件零使用 →SourceFile.unusedExports/_meta.deadExportCandidates,入口/re-export/动态 import 豁免)+ 类型级/函数级(保守引用计数:非导出实体本文件零引用、导出实体全仓库零导入且本文件零引用 →deadCandidate/deadReason;接口方法为契约声明永不判死;排除声明处与自递归,宁可漏报不误报);油猴 ScriptFunction 同样判函数级死代码(额外排除事件回调与 unsafeWindow 暴露) - 依赖治理:package.json / pubspec.yaml 声明 vs 实际导入交叉比对,产出
source=undeclared(导入未声明)与used=false(声明未使用) - 循环依赖:Tarjan SCC 算法(
_meta.cycles) - 框架检测:package.json 依赖优先(expo / react-native / next / nuxt / vue / react,元框架优先于基座框架);
pubspec.yaml+lib/→ Flutter(依赖含fluttersdk 时为framework=flutter,纯 Dart 包为framework=dart);go.mod存在且有.go源码 →framework=go(混合仓库前端文件仍各自解析);扫描子目录(如src/)时自动向上定位宿主项目根(上限 4 层、不越过用户 home),用宿主依赖识别框架并回退项目名,宿主配置文件(capacitor.config / app.json(expo 键) / vite.config / electron 等)作旁证;跨端/构建变体(Capacitor/Electron/Vite/Webpack/Riverpod/GoRouter 等)组合为frameworkLabel(如 "Flutter 应用 + Riverpod 状态管理(GoRouter 路由)");无任何清单时按代码信号兜底(.vue → vue,tsx/jsx → react);存在油猴脚本且无前端框架 →framework=userscript
项目若使用 overlay 路由体系(src/routes/overlayGroups/*.ts + src/routes/lazyImports/*.ts,或文件名含 overlayGroup.ts / lazyImports.ts),自动解析路由条目与跳转边:
- 路由条目:overlay group 文件中含
id+component属性的对象字面量 - 组件解析链:
lazyImports.X→lazy(() => import(...))→ 目标文件 - 跳转边:
setActiveOverlay/openOverlay('id')字面量调用(含app.setActiveOverlay属性访问形式)
无该体系的普通 React 项目自动跳过,Route 对象为空列表。
项目若使用 <Routes>/<Route path element> 声明式路由(如 asdm-admin-web 的 AppRoutes.tsx),自动提取(测试文件中的 mock 路由已排除):
- 路由条目:
<Route path="/x" element={<Page />} />,嵌套相对路径自动拼接(/:scopeUid+edit→/:scopeUid/edit)、index路由、布局 Route(无 path)下的绝对 children - 组件解析链:
element={<Guard><Page /></Guard>}取最内层组件;element={layoutElement}(createElement布局变量)穿透到实际布局组件 - 跳转边:
<Navigate to="/x" />字面量重定向,相对to基于所属路由归一为绝对路径(to="_overview/summary"→/:scopeUid/_overview/summary)
项目若使用 createBrowserRouter / createHashRouter / createMemoryRouter 数据路由(如 steam-game-library 的 router/index.tsx),对象树 [{ path, element, index, children }] 自动提取:
- 路由条目:
index: true以父路径产出;子级相对 path 与父路径拼接('/'布局 +'games/:id'→/games/:id);有children的布局对象自身不产出(与 JSX 无 path 布局同语义) - 组件解析三级:import 引用 →
lazy(() => import('../pages/X'))/React.lazy包装变量(含.then((m) => ...)命名导出链)→ 本地包装函数(return JSX 最深组件递归展开);element: (<Suspense>...</Suspense>)括号包裹多行 JSX 正常解析;包装函数调用element: withSuspense(X)/withPlatformGuard(X, 'platform')取第一个组件参数递归解析(steam-game-hub-2.0 惯例) - 重定向路由:element 内直接
<Navigate to="/x" replace />(index 兜底 / catch-all*→/*)产出导航边,无组件关联 - 跳转边:
<NavLink to="/x">(字符串或{ pathname }对象)字面量;数据驱动侧边栏to={item.path}动态引用时提取同文件常量表(NAV_ITEMS 数组)中全部path值;常量成员引用{ path: ROUTES.DASHBOARD }——同文件const X = { KEY: '/value' }对象表 + named import 跨文件轻量解析;布局外壳导航闭包——布局 componentFile 及其直接 import 的内部文件(如 Sidebar.tsx)的导航调用并入全部子路由(侧边栏对所有子页面可达)
framework=next 且存在含约定文件(page/route/layout)的 app/ 或 src/app/ 目录(后者优先)时自动提取:
- 页面路由:
app/**/page.tsx→ Route(routeType=next),URL 按目录约定计算——路由组(group)与平行路由@slot段剔除出 URL、_private段整目录不产出路由、[id]→:id、[...slug]→:slug*、[[...slug]]→:slug?(isDynamic标记) - API 路由:
app/**/route.ts→ Route(routeType=next-api),导出的GET/POST/PUT/...方法名收集为apiMethods - layout 链:
layout.tsx不单独成路由,而是沿真实目录链(外→内,含路由组层)收集进后代路由的layoutFileIds;loading/error/not-found/template/global-error记入specialFiles - 客户端标记:page/route 文件头
'use client'指令探测为isClient(读不到文件时为 null) - 跳转边:page 文件内
<Link href="/x">(next/link,字符串或{ pathname: '/x' }对象形式)→ 目标路由的navigatesToIds;layout/共享组件文件内的 Link 不归属路由(避免边爆炸),动态变量 href 不解析
- 显式声明:
router/modules/*.ts中RouteRecordRaw对象(path/name/meta.title/component 动态 import/Layout 函数包装/children 拼接),component: () => import('@/views/x.vue')经别名解析到具体文件 - 文件路由:
src/views|pages/**/*.vue未被显式声明时自动推导(index.vue→ 父级路径,[...all].vue→ catch-all);<route lang="yaml">的 meta(title/name/path)作为路由描述 - 跳转边:
router.push('/path')/ 解构push/router.replace字面量调用(数组 push 不误报)
- GoRoute 路由条目:
GoRoute(path: '/x', builder: (context, state) => const XxxPage())全量提取;path: AppRoutes.dashboard常量引用自动回填(static const String dashboard = '/dashboard');builder/pageBuilder 目标 Widget 支持直接形式、块形式与包装函数形式 - 原生路由表:
Map<String, WidgetBuilder> routes = { '/x': (ctx) => const XxxPage() }(MaterialApproutes:命名路由)条目提取,深度感知扫描——builder 体内字符串(如arguments: {'tid': x})不误判为条目键,值取最后一个大写构造调用(routeType=flutter) - 组件解析链:builderWidget 经具名/通配导入解析到具体组件文件,回退本文件组件;Route 关联
componentId/componentFileId - 跳转边:任意 .dart 文件内
context.go/push/replace('/path')与Navigator.pushNamed/pushReplacementNamed/popAndPushNamed(Navigator.of(context).pushNamed(...)/Navigator.pushNamed(context, ...)两种形式)字面量导航调用 → 该文件组件所属路由 → 目标路由(navigatesToIds)
.tsx/.jsx 中 PascalCase JSX 标签、.vue 模板中的组件标签(:prop 绑定 / 静态属性 / v-model / .sync / @event / v-bind="obj"),属性传递按组件对聚合为 PropEdge 对象(prop:A→B),每个 prop 携带来源分类(词法近似:组件声明范围 + 文件级变量表判定,非作用域精确分析):
| 来源 | 判定(React) | 判定(Vue) | 说明 |
|---|---|---|---|
forward |
标识符命中父组件解构 props 名 | 标识符命中本组件 props 声明(Options API props / setup defineProps) |
父组件 props 透传(设置面板批量下发的 state/setter 对典型形态) |
state |
标识符为组件内 useState 解构首元素 |
标识符命中 data() 键或 setup 内 ref/reactive 声明变量 |
本地状态下发 |
store |
标识符为非 builtin hook 变量(useXxxStore/useQuery 等) |
标识符命中 mapState/mapGetters 提取键、setup 内 store 变量或 storeToRefs 解构名 |
状态库数据源,附 storeHook 溯源(Vue2 为 Vuex 模块名、Vue3 为 Pinia store 变量) |
handler |
内联函数或本地函数引用 | 标识符命中 methods 键或 setup 函数声明(含 @event 回调) |
事件回调 |
literal |
字符串/数字/布尔/裸属性(disabled = true) |
静态属性 max="10" / 裸属性 clearable |
常量配置 |
computed |
其余表达式 | 标识符命中 computed 键或 setup computed() 声明,其余表达式 |
计算值 |
spread |
{...obj} 整体透传 |
v-bind="obj" 整体透传 |
不展开成员,单条 spread 边 |
- 聚合规则:同一组件对的多处渲染聚合为一条边(
renderCount计渲染处数);同名 prop 出现多种来源时取优先级最高者(forward > state > store > handler > computed > literal > spread) - 组件出入度:Component 附
propOutCount/propInCount(传出/传入边数),配合 viewer「组件数据流」视图识别 props 分发枢纽与消费方 - 路由工厂注入:overlay 路由的
props: (app) => ({ item: app.item })工厂函数提取注入键为factoryProps(App → 工厂 → 页面组件的主干注入链,在路由地图以「工厂 N props」徽章展示,不计入组件间 PropEdge) - Vue 组件标签解析(Options API 与 setup 通用):局部
components注册表 → import 索引(local 名 + PascalCase 双键,default 导入取目标文件 primary 组件;defineAsyncComponent(() => import(...))与 React.lazy 包装的 const 变量同样进索引)→main.js的Vue.component()全局注册兜底 → 同文件兜底;kebab-case 标签 / camelCase 导入名 / 文件派生名(day.vue↔CrontabDay)均可对齐 - 边界:路由库组件(Link/Navigate/Outlet/router-link 等)、element-ui
el-前缀、Ant Design Vuea-前缀、原生 HTML / Vue 内置标签与指令属性(v-if/v-for/ref/class/style 等)跳过;自渲染(递归组件)不成边;Dart 组件暂不采集
- Options API 解析:
export default {}/Vue.extend({})/defineComponent({})提取 props(对象/数组/混合形式,含 type)、data(对象/函数/方法形式)、computed/methods 键集、components 局部注册表 - Vuex store:
/store/目录或导入 vuex 的文件,default export(对象字面量 /new Vuex.Store({})/ shorthand 引用顶层 const)提取 stateKeys + actionKeys(actions + mutations 合并)为 Store 实体(providerType=vuex) - 类视图实体(vclass):每个
.vue文件 primary 组件合成为kind=component的 Class 实体——props 为字段(含 type)、computed + methods 为方法实体;组件组合关系回填为 vclass 间 renders 边,在「实体类图」以绿色实线箭头呈现 - 导航:
<router-link to="/path">静态路径与this.$router.push('/path')产出路由导航边(动态:to表达式不可静态解析,跳过) - 别名解析:vue.config.js
configureWebpack.resolve.alias与 jsconfig.json paths;vue-cli 项目(存在 vue.config.js +src/)自动兜底@/* → src/*
- script setup 变量域:
<script setup>内ref/shallowRef/reactive/shallowReactive/customRef/toRef→ state 键、computed()→ computed 键、函数声明与 const 函数 → method 键、storeToRefs(...)解构名与 store 实例变量 → store 键(附 Pinia store 名溯源;hook 命名兼容useXxxStore与xxxStore双形态,storeToRefs(store)变量参数同样溯源),变量域统一进入模板绑定的 props 来源分类与 vclass 类视图实体输入 - 组件命名:
<script setup name="X">属性(vite-plugin-vue-setup-extend)与defineOptions({ name })均优先于文件名派生 - Pinia store:
defineStore('name', setup/options)两种写法统一提取 stateKeys/actionKeys,Store 实体携带providerType=pinia(Zustand 同理zustand),蓝图「业务数据图」与「Store 一览」展示 provider 类型徽章 - 异步组件:
const X = defineAsyncComponent(() => import('./x.vue'))与路由const X = () => import(...)顶层 const 懒加载包装统一进组件解析索引,模板标签<X />正常建立 renders 关系与 Props 传递边 - Vite 动态注册豁免(死代码防误报):
import.meta.glob(['/src/views/**.vue', '!/src/views/auth/**.vue'])模式采集(含!排除段、相对路径模式),命中文件豁免孤儿候选;vite.config.mjs 的unplugin-vue-componentsdirs(自动注册组件目录)与unplugin-auto-importdirs同样豁免 - Ant Design Vue 排除:
a-前缀标签(a-table/a-button 等)不进组件标签集与传递链,与 element-uiel-前缀同规则
独立的 goAnalyzer 轻量语法级解析器(深度状态机 + 大括号配对,不依赖 gopls/tree-sitter),适合 cobra CLI、agent 代理类小程序与「Go 后端 + 前端」融合仓库(如 one-api 类项目):
- 项目识别:
go.mod存在且有.go源码 → framework=go;require段(分组块与单行)解析为 Dependency(source=go);vendor/、testdata/、bin/自动跳过 - 实体映射:
struct→ Class(kind=struct,字段含json/yamltag 与匿名内嵌)、interface→ Interface(含嵌入接口 extends)、方法/顶层函数 → Method(大写导出判定 exported)、package 目录 → Module、Go 包 = 目录(同包跨文件方法合并,如接收者在另一文件声明的goOrphanMethods回填) - CLI 命令树(cobra):
var xxxCmd = &cobra.Command{Use/Short}+rootCmd.AddCommand(xxxCmd)边 → Route(routeType=go-cli,routePath 为smartide k8s init式命令链);Flags()/PersistentFlags()注册的 flag 提取为-T/--type徽章;跨包限定子命令(hostCmd.AddCommand(host.HostGetCmd))经 import 定位目标包目录归一 - HTTP 路由(Gin / 标准库):
router.Group("/api")前缀累积 +.GET/.POST/.PUT/.DELETE/.PATCH/Any("/path", ...)→ Route(routeType=go,apiMethods +:param/*wildcard动态段标记);handler 函数值(controller.GetSelf)经 importMap 定位包目录关联到 Method;组级apiRouter.Use(middleware.Auth())中间件按前缀链继承 + 内联中间件合并;Handle("GET", ...)与http.HandleFunc标准库形式兜底 - 逻辑走向(调用链):包级函数跨文件互调(同包无需 import)+
pkgAlias.Func()跨包调用(importMap 定位)+ 方法体内调用(接收者/参数/构造字面量类型推断,词法近似)→ Method 的calls/calledBy;Method 死代码候选按包级标识符引用判定 - 前后端逻辑映射(融合仓库核心价值):tsAnalyzer 提取前端
API.get/post/put/delete('/api/...')、axios.x()、fetch()(含模板串`/api/user/${id}`)调用 → 与 Go 路由路径匹配(:param通配任意段、*wildcard吞尾段、去 query、尾斜杠归一)→ Route.frontendCalls(文件+行号+method 溯源);未匹配调用进_meta.unmatchedFrontendCalls清单(路由地图「未匹配的前端调用」面板,用于发现死接口/路径漂移/外部 API) - 架构层:
main.go/cmd/→ entry,router/controller/middleware/handler/api→ presentation,model/dal/dao/repository/relay/service/biz/domain→ service,其余 → shared - 路由地图增强:Go HTTP 路由(方法徽章 + 中间件链 + 前端调用数)与 Go CLI 命令(路径层级树按命令段嵌套,flags 见详情)统一进既有路由地图视图;域取首个业务段(跳过
api/v1网关前缀)
独立的 userScriptAnalyzer 解析器,与 React/Vue 解析器平级共存、逻辑互不干扰:油猴文件不产出 Component/Store/Route,而是产出 UserScript/GmApiUsage/InjectionPoint/NetworkEndpoint/ScriptFunction 五类对象(React/Vue 项目内混入的油猴脚本同样被识别,framework 仍以宿主框架为准)。
- 脚本识别:
.user.js扩展名(强信号),或.js文件头部 4KB 内含// ==UserScript==元数据块(如steam-friend-manager-1.3.12.js) - 元数据解析:
@name/@version/@match/@include/@exclude/@grant/@connect/@require/@resource/@run-at/@noframes等字段全量提取(@grant none归零处理) - 函数使用与逻辑分布:IIFE 体内顶层函数/箭头函数/类(含
constructor)/常量对象(含对象方法storage.get、类方法Xxx.render)作为逻辑单元;每个函数统计行数、GM 调用、DOM 操作、网络调用、监听器、定时器;建立函数间静态调用图(calls/calledBy双向,覆盖直调 /this.method()类内互调 /const app = new Xxx(); app.method()实例变量调用 /new Xxx()构造入口)与 IIFE 顶层调用链;按函数内行为推断业务角色(innerHTML/挂载 → render,网络请求 → data,GM 存储 → state,监听/观察/定时 → event,createElement → ui,其余 → logic) - GM API 审计:
GM_*与GM.*(GM4 风格)两种调用风格统一归一;调用次数/行号统计,并与@grant声明交叉比对(未声明 →declared=false,@grant none下任何调用均标记风险) - DOM 注入:
innerHTML/outerHTML/insertAdjacentHTML/document.write(含动态插值标记 → XSS 面;receiver 为querySelector/getElementById变量时还原为页面锚点选择器)、appendChild/insertBefore等挂载(同样做变量锚点还原)、GM_addStyle、document.createElement('style')、attachShadowShadow DOM;每个注入点/网络端点记录归属函数(fns/fnIds),构成"函数 → 页面锚点/请求域"的逻辑注入链 - 请求与劫持:
GM_xmlhttpRequest(URL/method 提取 +@connect域名白名单比对)、fetch/XHR.open/WebSocket/sendBeacon调用域名;window.fetch、XMLHttpRequest.prototype.open/send、EventTarget.prototype.addEventListener、WebSocket、history.pushState/replaceState原型/全局重写识别为请求劫持 - 沙箱与宿主交互:
unsafeWindow读/写属性区分(写 → 中风险)、window.X = ...全局暴露、Object.defineProperty(window, ...);__vue__/__reactContainer$等标记推断宿主框架(vue/react/mixed/unknown) - 风险清单:请求劫持、eval/new Function 动态执行、cookie 读写、unsafeWindow 读写、动态插值 HTML 注入、未声明 GM API、未列入 @connect 的请求域名 —— 按 high/medium/low 汇总为脚本级
riskLevel
- 基于 TypeScript Compiler API 的语法级解析(不跑类型检查);动态拼接的 import 与动态
navigate(path)变量导航无法解析 - 类型实体提取覆盖
.ts/.tsx/.js/.jsx与.d.ts;Vue 组件以vclass类视图实体呈现(props/computed/methods 同构映射);Vue SFC<script>内声明的 interface/class 本期不提取;TS 方法级调用图(calls/calledBy)未扩展到 Method(调用图仅油猴 ScriptFunction 与 Dart Method 有) - Rust 解析为轻量语法级(深度状态机 + 等长噪声剥离,不依赖 rustc):泛型约束 / 关联类型 / macro 生成代码不解析;
mod声明文件树按目录约定映射(mod models;→models.rs或models/mod.rs);.rs文件仅在 Tauri 组件语境下扫描,独立 Rust 工程(纯后端 crate)不纳入 - Dart 解析为轻量语法级(深度状态机 + 等长噪声剥离,不依赖 analyzer):泛型方法/闭包体内声明、动态拼接路由 path、
Navigator.push(MaterialPageRoute(...))导航不解析;构造器不实体化为 Method;调用链为静态提取(变量间接调用/回调透传不解析) - Go 解析为轻量语法级(深度状态机 + 双通道噪声剥离,不依赖 gopls):泛型(type parameters)不解析(两参考项目均为 Go 1.17/1.18 前风格);调用链为静态提取(变量间接调用/回调透传/goroutine 内闭包捕获不解析);cobra
Run内联闭包不实体化为 Method;前端 httpCalls 限定API.x/axios.x/fetch标识符 + 字符串字面量首参(变量拼接 URL 取静态前缀,完整外链 URL 进未匹配清单);Java/Python 后端不在扫描范围 - 跨文件 implements/extends 按具名导入静态解析;命名空间导入、
export *再导出与动态import()的目标文件整体豁免死代码判定(无法按名追踪,保守不误报);仅被测试文件使用的导出符号会被判为死代码候选(测试文件不入扫描范围,删除前请人工确认) renders归属文件主组件(default export 优先),同文件多组件不细分- 函数透传式导航(
onOpenOverlay: app.setActiveOverlay)不产生跳转边 - Vue 适配覆盖 Vue 3 SFC(
<script setup>变量域 / Pinia setup 与 options 写法 / defineAsyncComponent / import.meta.glob 与 unplugin 目录豁免)、vue-router、unplugin-vue-router 文件路由与 unplugin-auto-import 隐式导入;Vue 2 Options API(props/data/computed/methods/components、Vuex 模块、Vue.component 全局注册、element-ui 排除、@ 别名)已支持;Nuxt 专属约定仅部分支持;Vue 模板动态:to导航与作用域插槽透传不解析;import.meta.glob高阶用法(函数形式{ eager: true }的具名导出、多变量别名)不展开 - 油猴脚本:调用图为脚本内静态调用(变量间接调用/回调透传不解析);动态拼接的请求 URL 域名记为
(dynamic),不做 @connect 比对;宿主框架仅按代码内__vue__/__reactContainer$等标记推断,未触碰宿主内部的脚本记为 unknown - 快照为全量重建(无增量);多进程并发写快照无保护;方法级实体化后大仓库(1000+ 文件)快照体积约增至 2-3 倍(万级 Method 实体),全量 JSON 载入仍在数百毫秒级
--where为全表扫描:=/:精确相等、~模糊包含(不支持数值比较,数值过滤请配合 jq)
CLI 保持原子普适(只提供对象/链接/字段/动作级通用能力),场景工作流下沉到 Skill。npm 包携带五个 SKILL.md(skills/**),随包分发:
| Skill | 职责 | 典型场景 |
|---|---|---|
nice-aos(核心查询) |
快照构建、通用本体查询、变更影响分析、接口/类/方法导航、蓝图导出 | "项目架构是什么样" / "IStorage 被谁实现" / "修改这个 service 影响谁" |
nice-aos-userscript(油猴审计) |
GM API 越权 / @connect 白名单 / XSS 面 / 风险分级五步审计 + 修复模板;单文件与仓库双模式 | "这个油猴脚本安全吗" / "@connect 齐不齐" / "哪里有 XSS 面" |
nice-aos-deadcode(死代码清理) |
四级死代码(文件/导出/类型/函数)检测 → 分级复核 → 清理 → 验证工作流;单文件死函数查询 | "哪些文件没人用" / "哪些函数没人调用" / "这个文件能删吗" |
nice-aos-database(数据库分析) |
MySQL 迁移脚本扫描 → 表/列/外键/索引/迁移/领域/模式特征查询 + 7 大审计(健康度/影响/领域耦合/索引优化/演进/外键链路/命名)+ dataoverview 蓝图 | "数据库有哪些表" / "外键关系" / "索引优化建议" / "哪个版本变化最大" |
nice-aos-deployment(部署分析) |
部署配置目录扫描(compose/K8s/Dockerfile/nginx/.env)→ 服务/路由/依赖/中间件/环境/分层查询 + 5 大审计(安全/高可用/一致性/依赖/健康度)+ deployoverview 蓝图 | "部署架构是什么样" / "nginx 路由怎么配的" / "哪些服务缺健康检查" / "用了哪些中间件" |
五者共享同一份 CLI 与快照根目录(<REPO_ROOT>/.nice-aos/data:snapshot.json / db-snapshot.json / deploy-snapshot.json),无独立安装步骤。
不进入 npm 包分发的可选周边,按需取用:
| 目录 | 说明 |
|---|---|
contrib/blueprint-ai-agent |
蓝图页 AI 分析助手(油猴脚本,Tampermonkey 安装):在蓝图 HTML 右下角注入浮窗按钮展开对话侧边栏,按页面类型自动切换智能体——代码蓝图(模块/组件/Store/Service/路由/接口/方法/功能域/死代码,9 工具)、数据库蓝图(表/外键/索引/迁移/领域/模式特征 + 7 审计,双智能体)、部署蓝图(服务/镜像/路由/依赖/中间件/环境/分层 + 5 审计,12 工具)。双数据源(页面内嵌 viewer-data / db-viewer-data / deploy-viewer-data 零依赖,或 nice-aos serve 本地快照地址),ReAct 文本协议工具循环驱动,支持多模型接入(DeepSeek/GLM/千问/Kimi/豆包/OpenAI/自定义)、新建会话、会话历史与 JSON/Markdown 导出 |
npm install
npm test # node --test 单元测试
node src/cli/index.js --help--where数值比较(lineCount>500)与索引- 增量刷新(按 git diff 重新解析变更文件)
- Python 后端解析(Flask/FastAPI 路由,如 oneapi-service 类微服务,与前后端映射打通)
- Go 泛型(type parameters)解析与 TS 方法级调用图(calls/calledBy 扩展到 Method)
- 更新日志见 CHANGELOG.md