Skip to main content
F

dsh-pkg-atlas

flyingbamboo/dsh-pkg-atlas

DSH 本机代码包依赖图谱(开发工具):把已安装的 @deepseek-ai/* 包与第三方插件的依赖、挂载关系画成区-组-包三层交互图,支持聚焦、拖拽布局与中英切换。零运行时依赖,内置 cytoscape,断网可用。

Install

dsh plugin --profile web add github:flyingbamboo/dsh-pkg-atlas

README

dsh-pkg-atlas

中文 · English

本机 DSH 包依赖图谱:一个独立 HTTP 页面,展示当前 DSH_HOME 已安装的官方 @deepseek-ai/* 包与第三方插件之间的依赖与挂载关系。图谱按功能大类分区、 组为复合节点、包在组内成网格,首屏有扫描进度。没有运行时依赖,数据全部来自 本机,页面只读,离线也能用。 它是按 DSH 高频迭代来设计的:零运行时依赖、不碰宿主内部模块,升级带来的破坏 多半落在扫描层(见「低耦合设计」一节)。

页面地址(安装并重启后):http://127.0.0.1:3080/dsh-pkg-atlas/

它回答什么问题

  • 某个工具/插件在 DSH 生态里的位置:属于哪个大类、哪个功能组、被谁依赖、挂了哪些 bundle。
  • 一个官方 bundle(如 dsh-base)到底把哪些包挂载进 profile(BFS 展开 cordis.patch.yml 的 name: 行)。
  • 哪些目录断了链(broken junction,标红伪节点)、哪些版本区间装不到满足版本 (红色 unsatisfied 边)。

安装(web profile)

GitHub 直装(pnpm 按 owner/repo 解析):

dsh plugin --profile web add FlyingBamboo/dsh-pkg-atlas

或在 DSH Web GUI「市场」搜 dsh-pkg-atlas 一键安装。 重启 DSH 后打开 http://127.0.0.1:3080/dsh-pkg-atlas/。

卸载

dsh plugin --profile web remove dsh-pkg-atlas
# 重启后人工核对 profiles/web/package.json 的 dsh.profile.bundles 中
# 无 "dsh-pkg-atlas" 残留行(本插件自身无运行时状态,无其它残留面)

打开页面先看什么

  • 顶栏「组级 | 包级」两态开关,默认组级:画面是 大类区 → 组卡 → 展开的包。
  • 冷态下左键单击任何节点只做选中和详情(包与组对称;冷态 = 尚未进入聚焦时)。
  • 双击按档位不同:组级双击组卡展开/收拢该组,双击大类区标题折叠整区; 包级下这两样双击都是有意空操作。
  • 右键任意目标弹它自己的命令行;空白画布上:复位视图 / 退出聚焦 / 自动排布。
  • 搜索:包名或中文描述,回车项点击定位(自动展开祖先)。
  • 顶栏两个按钮:复位视图把当前渲染集 fit 回视野;自动排布清掉全部手动拖动位置。
  • 图例(左下角,可折叠):4 种节点形状 + 5 种边类型 + 聚焦两色(依赖路径 ↓ / 被依赖路径 ↑)。

用法细节

视图与粒度

  • 图分三层:大类区 → 组 → 包(组内网格)。大类区是功能分类(内核·装配 / 会话·状态 / 界面 / LLM·模型 / 编排 / 平台 / 工具 / 集成 / 基础设施,外加 插件、 profiles、断链、未归类 四个特殊区);组按 repository.directory 推导,复合容器节点。
  • 显示粒度只有两态,没有「自动」档:组级看到 大类区 → 组卡 → 展开的包, 包级把所有组同时展开。滚轮只放大画面,不改变层级。
  • 粒度切换按结构性变更处理、整体重建,镜头保持不动。包级会强制打开真实跨包边, 切回组级即恢复(复选框的用户原值保留)。
  • 坐标由视图模型按展开态预先分配,没有布局引擎。展开、折叠、筛选、切粒度只重建 元素集合,不重排也不移动,位置在交互之间保持稳定。
  • 镜头只有四处会动:首屏 fit、搜索或深链定位、复位视图、自动排布。复位视图 (顶栏按钮或空白画布右键)把当前渲染集整体 fit 回视野(padding 40、250ms 补间),只动镜头,不改聚焦/选中/折叠/快照。重绘一律保留视口,重扫不挪镜头。
  • 首屏进度:扫描按 目录清单→manifest 读取→组装 三阶段推进,进度条实时显示 已扫/总数(/api/status 轮询);服务端启动即预热,通常首屏即缓存就绪。

聚焦与路径

  • 聚焦:界面上叫依赖图,进入后双向高亮其依赖路径与被依赖路径:琥珀色为它依赖的 下游,青色为依赖它的上游,洋红为双向/成环成员;非路径元素淡出,祖先容器不再 「陪绑」,改成虚线半透明的上下文框。
  • 进入的入口都是显式导航:右键包 →「依赖图」、双击包、详情面板的路径行/挂载行/ 跳转按钮、表格行、搜索命中定位、深链 #node=<id>。仅包节点可作路径根:点组卡会 转成该组的组聚焦,点空白/类型/profile 即退出。
  • 聚焦期间再点另一个包 = 沿路径行走,前一个根进顶栏面包屑「← 返回 (a → b → c)」, 逐级回退(最多记 20 步,显示最近 4 级);点空白、Esc 或「退出依赖图」按钮退出。
  • 深度默认「不限」,可选 1-3;路径内取消勾选的边类型直接隐藏(区别于淡出的非成员)。
  • 挂载 mount 不是向下方向(X→mount→Y 意为 Y 沿挂载向上到 X),某包挂载的内容 单列在详情的「挂载 ↓」里。
  • 组聚焦:右键组卡 →「聚焦邻域(1 跳)」,或用深链 #node=g:<组名> 直接分享。 聚合边只在组聚焦内出现(粗细∝触碰边计数),深度恒 1 跳。
  • 组聚焦的邻居组卡(组已展开或包级档时为成员包)按方向着色:琥珀 = 该组依赖的 下游、青 = 依赖它的上游(含挂载攀爬)、洋红 = 双向;根卡保留金色选中环但不染方向, 祖先转虚线上下文。点邻居组卡走栈换根,点成员包转入依赖图,点空白或 Esc 退出 (不挪镜头)。
  • 组聚焦期间详情面板出现 相关组(N)/ 相关包(N)两段:行 = 方向箭头 + 名称 ×计数 + 边型徽章 +(断链区 ⚠),按 down→up→both、名称排序,组行点击走该组,包行点击以该包 进依赖图。

开关与过滤

  • 大类筛选 chips:单击 = 隐藏该区(再点恢复);双击 = 单独显示该区(其余全隐藏, 同颗再双击恢复全部);行尾「全部显示 / 全部隐藏」按钮批量开关。
  • 官方/第三方、边类型(mount/peer/dep/peer-optional)、profile 挂载面、真实跨包边 开关、深浅主题、中英切换、显示粒度两态开关均在顶栏。

拖拽

  • 手动拖过的元素(大类区/组框/包)落在渲染层的覆盖表里,切档、筛选、展开合并、 聚焦进出都不清这份覆盖,只有重扫后已不存在的元素会被摘掉条目。
  • 拖父框实时平移它当前渲染的整棵子树(区→卡→包、组框→成员包),落点把父和每个 被带动的子级各记绝对位;拖子只动子级,父框留在原地。
  • 所见即所得在每一层都成立:组卡拖过之后切到包级不再被成员 重定心;没单独拖过的成员按「父渲染位+模型内子相对槽偏移」 跟随父框。
  • 想把手感交还给模型:按顶栏「自动排布」(或空白右键同名菜单行,没拖动过时 置灰),清空覆盖 → 回到区带网格 → 一次 fit 掠过复原后的版面。

详情面板

  • 悬停速览卡:在任何节点(含路径内节点)停留 250ms 弹小卡,卡内有名称@版本、 大类 · 组、截断描述、直接依赖/直接被依赖计数(按路径语义计数,mount 不计 下游)、⚠ 含未满足边 / 断链包标记。纯只读,不改变聚焦与选中,移开/平移/ 缩放/点击即收起。
  • 详情(包节点):大类/组/类型三级面包屑、描述、依赖路径 ↓ 与被依赖路径 ↑ 两条列表, 按 BFS 层分档折叠:d1(直接命中)默认展开,d2 起收在「d2 (N)」档头后面,点档头开合; 每层最多列 60 行,超出显示 +N 更多。每行 名称@版本 · d{层数} · 边型徽章 · ⚠, 点击即以该行为根进入/换根(profile 行不是合法路径根,点击即退出依赖图)。另有挂载 ↓、 外部依赖、README 原文。
  • 详情(组卡 / 大类区):成员包列表。表头「成员包(N)」的 N 永远是真实总数(与列表是否 被截断无关),每行 名称@版本 [类型] [第三方] ⚠断链包 ⚠未满足,按 名称→版本→id 全序 排列,最多渲染 200 行,超出显示「+N 更多」。点任意成员行 = 走搜索定位同一条通路:展开 它的区与组、以它为根进入依赖图、居中闪烁,并顺带收起速览卡;点断链包这类非法路径根则 选中并退出路径。大类区详情按组分节,组名按字母序:节头「组名 ×组内总数」点击 = 纯选中 该组(零导航),每组最多列 10 行,超出显示「还有 N」。
  • 面板内的名字与版本:成员共享同一 npm scope 前缀(如 @deepseek-ai/)时行内省略该前缀, 完整前缀以徽章在面板头出现一次,全名@全版本随行 hover 可查;组内版本全同上提组头 (· ver)行内不显,多数相同时组头显多数版本、异版本行琥珀标注,全不同则行内全显。 区/组/包三级详情容器各带标题徽章与左缘色带,一眼看出面板停在哪一层。

通用

  • 右键命令菜单出现在点击处(贴边自动翻转到框内),只关闭不选中:关闭它的那一下 点击被吞掉,下一次点击照常工作;平移、缩放、窗口缩放、任何结构重绘都会收起它。 右键边(edge)不弹菜单,没有对应命令。不可用的行置灰保留,不做隐藏。
  • 各目标的命令行:组卡:展开⇄合并 / 聚焦邻域(1 跳)/ 只看该区;大类区:折叠该区⇄ 展开该区 / 只看该区 / 隐藏该区;包:依赖图;空白画布:复位视图 / 退出聚焦 / 自动排布。
  • Esc:先关右键菜单,再关搜索结果面板,然后(不在输入框里时)退出聚焦;否则无操作。
  • 包标签钳 50px 并省略号收尾,图上不追求可读全名,完整名称看速览卡与详情面板。 滚轮缩放灵敏度 2.5。
  • 中英切换、深浅主题都在顶栏。页面全离线,断网重开仍可用。

低耦合设计

DSH 迭代快,挂在内部 API 上的插件会跟着一次次坏。所以这里把耦合面压到接近零:

  • 零运行时依赖:node 侧只用 Node 标准库;页面侧唯一第三方是 vendored 的 cytoscape 固定文件(sha256 钉住,见 test/vendor-pinned.test.mjs),不走 npm install。
  • 不调用宿主任何内部模块:数据全部来自扫描 DSH_HOME 磁盘上的已安装内容(package.json、 cordis.patch.yml、目录 junction),不 import、不 hook DSH。
  • 挂载点只有一个且可选:宿主 webserver 在场才注册路由(ctx.inject(['webServer'], …)), 不在场则 inject 永不满件、插件静默失活,不影响宿主启动;这个 peerDependency 标了 optional,路由注册被宿主拒绝时也只记日志、不抛。
  • 无构建步骤:浏览器代码是普通 script,仓库里是什么就跑什么。

后果是:DSH 升级如果还能弄坏这个插件,坏点多半在「输入格式变了」,修复发生在扫描层; 页面与渲染不受宿主变更影响。

安全模型

  • 无任何写操作;路由只读(GET/HEAD),非 GET 一律 405(带 Allow: GET, HEAD)。
  • /api/readme 的 id 仅用于在扫描快照中查节点,文件路径取自扫描结果内部字段(_dir, 对外 JSON 一律剔除 _ 前缀字段),用户输入永不参与路径拼接;恶意 id 在正则卫生层即 400。
  • 响应不回显内部错误文本(500 固定 {error:'internal-error'},真错误只进宿主 logger); 页面与 API/资产响应带 X-Content-Type-Options: nosniff;页面 CSP 为 default-src 'self' (style 另放行 'unsafe-inline')。
  • 图数据中的路径一律相对化为 $DSH_HOME/...,不泄露绝对路径。
  • 页面挂在宿主 web 端口上,自身没有鉴权:若启用 DSH 远程访问(tailscale/配对等),本页面 与 /api/graph 的包清单一并暴露给可达者,请视为知情选择。

已知限制(使用者视角)

  • 缓存 = 60s TTL + 手动「重扫」:外部安装/卸载后最长 60s 视图陈旧。
  • 挂载面为 bundle/patch 的 name: 行启发式抽取:不解析 YAML 结构、disabled 语义、嵌套值;行尾内联注释容忍;config: 下恰好叫 name 的键可能误抽。
  • 非 semver 安装描述(github:/git:/link:/file:/npm:/workspace:/ catalog:/URL)不做版本判定:直接挂最高版本,不标 unsatisfied。
  • semver 为最小实现:空格复合区间(">=1.0.0 <2.0.0")只取下界;预发布版 可满足未提及它的区间(对 DSH rc 生态有意为之,已测试钉住)。
  • 第三方插件自身 bundle 成员不递归展开(只展开官方包 patch)。
  • repository.directory 不以 packages/ 开头的官方包落在「未归类」区:组派生只认 packages/<组> 模式。
  • 浏览器降级表格模式(cytoscape 加载失败时)为一次性:恢复需刷新页面。
  • DSH Desktop profile 未验证(CLI 拒绝 boot desktop)。
  • 数据源为 DSH_HOME 已安装内容;不含任何线上目录,无遥测,GET-only。

开发

npm test          # node:test,fixture 全部合成,不读真实 ~/.dsh
npm run check     # node --check 全部 lib + web 脚本

隔离真机验证流程、浏览器人工清单、布局说明与维护者向的已知边界见 docs/DEVELOPMENT.md。

许可

MIT(见 LICENSE)。vendored cytoscape.min.js 3.34.1 同为 MIT,见 web/vendor/LICENSE-cytoscape.txt。

Related plugins