# dsh-graph-usage

> DeepSeek Harness 已装插件关系图谱 —— 侧边栏展开面板：插件关系图 + 技能使用 + Token 缓存成本分析。

[![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![node](https://img.shields.io/badge/node-%3E%3D22.2-green)](#要求)

## 功能

一个 DSH Web 插件，侧边栏底部「插件图谱」按钮，点击**展开**（不跳页）浮动面板，含三个视图：

**1. 图谱** — 已装插件网络图（Obsidian 关系网风格：打开时节点弹性炸开、可拖拽/平移/滚轮锚点缩放）

- **球大小 = 调用/使用频次**（log 缩放）
- **颜色 = 类型**（皮肤/主题、用量/统计、插件市场、架构/绘图、技能、核心…）
- **亮暗 = 启用状态**：启用且非依赖 → 亮；核心/依赖 → 暗灰；已装未启用 → 暗色
- 线型：实线=依赖、点线=对等依赖、虚点线=同类、长虚线=同项目
- 点击节点 → 详情（状态/版本/来源/分类/频次/下载量/描述/邻居）

**2. 技能** — 技能目录（`.dsh/skills`）全部技能：加载次数、会话数、重复加载会话数、累计读取量(tokens)、平均耗时、是否已收录。

**3. 缓存分析** — 实时会话投影 + 历史日志扫描：输入/缓存命中/命中率/节省占比/估算成本(¥)/节省(¥)、按模型维度、**今日/本周/本月**周期统计（北京时间）、**减 Token 策略**（按优先级量化 tokens 与 ¥）。成本按 DeepSeek v4 官方价**高峰/空闲分时**估算（北京时间 09-12/14-18 为高峰）。

## 截图

![插件关系图谱](assets/graph.jpg)

![技能使用](assets/skills.jpg)

![缓存分析](assets/cache.jpg)

## 要求

- DeepSeek Harness（web profile）
- Node.js ≥ 22.2（`node:zlib` 的 zstd 支持）

## 安装

```sh
# 从 npm 安装（企业 scope 包）
dsh plugin --profile web add @eave_bounty/dsh-graph-usage

# 从 GitHub 安装（仓库名不变，直装不受改名影响）
dsh plugin --profile web add EaveBounty/dsh-plugin-graph

# 或从本地源码目录
dsh plugin --profile web add <path-to>/dsh-plugin-graph
```

重启 `dsh web`，侧边栏底部出现「插件图谱」按钮。

> **包名说明**：npm 发布名为 **`@eave_bounty/dsh-graph-usage`**（企业 scope，公开）。`dsh plugin` 按包的真实 `name` 对账依赖键与 `dsh.profile.bundles`，所以** bundles 里请写 `@eave_bounty/dsh-graph-usage`**。客户端 bundle 同时注册 `@eave_bounty/dsh-graph-usage`、旧名 `dsh-graph-usage` 与仓库名 `dsh-plugin-graph` 三个 id，兼容历史命名；但 boot key 必须是真实包名。

## 数据源

- 插件清单/依赖：`$DSH_HOME/profiles/<profile>/package.json` + 各包 manifest
- 使用频次/缓存/技能：`$DSH_HOME/sessions/**/session.jsonl(.zstd)`（有界扫描 + 内存缓存）+ 当前进行中会话的实时投影
- 市场下载量：`api.npmjs.org/downloads/point/last-week/<pkg>`（10 分钟缓存，离线降级）

## API

`GET /api/dsh-plugin-graph` → `{ ok, nodes, links, meta, skills, cache, scannedSessionIds }`

## 局限

- 插件"使用频次"近似为会话日志中插件 id 的命中次数（多接近 0）；技能维度是真实的 skill 工具调用统计。
- 已完成会话从日志扫描；当前进行中会话由实时投影统计（客户端按 `scannedSessionIds` 去重，避免重复计数）。
- 分类/项目分组为内置规则表（`lib/index.js` / `lib/stats.js`）。

## 架构

- `lib/index.js` — cordis 宿主：`/api/dsh-plugin-graph` 端点 + `pluginGraphStats` 会话投影（token 桶 + 技能调用配对）
- `lib/stats.js` — 会话日志(zstd)扫描、技能清单、成本/缓存模型
- `lib/client.js` — React 客户端（`window.__ModuleLoader__`）：图谱力模拟 + 技能/缓存视图
- `cordis.patch.yml` — 注册到 bundle 的补丁

> 说明：`lib/client.js` 为手写校验的 JSX bundle（无独立构建步骤），修改后直接生效于 web 端。

## 贡献

欢迎 Issue / PR。请保持 zh/en 文案对等，并在 `README.md` 追加变更日志。

## 协议

[MIT](LICENSE)

## 变更日志

- 2026-08-18 修复启动失败：运行时依赖 `@deepseek-ai/dsh-home-paths` 需随插件本地下发，否则 D 盘 link 加载时无法从 profile node_modules 解析。
- 2026-08-19 修复启动失败：`sessionProjections.register` 缺 `stateVersion`（补 `stateVersion: 1`）；补 `view(state)` 实现。
- 2026-08-19 可视化语义重定义：颜色=类型、亮暗=启用状态、球大小=调用频次；移除"市场深浅=下载量"旧规则。
- 2026-08-19 多代理企业级审评修复：双重计数（`scannedSessionIds` 去重）、省钱数学 ~30× 虚高修正、关闭侧边栏停止后台轮询、图刷新保留 pan/zoom、session 大文件 64MB 上限 + zstd 特性检测、图/统计内存缓存与去重、过时文案与硬编码中文修复。
- 2026-08-19 UI/交互优化：未启用对比度提升、标签描边晕环、图例补类型色相；策略表本地化（zh/en 对等 79/79）；浮动动画 5s 衰减归零、拖拽不被边界弹回、`pointercancel` 不误选。
- 2026-08-19 功能正确性：`collectUsage` 二值 0/1 缺陷修复（逐会话计数 + 边界匹配防前缀误报）；聚合成本改为按模型分别计价后求和。
- 2026-08-20 截图与改名：README 新增图谱/技能/缓存三视图截图；npm 包改名 `dsh-graph-usage`（规避 erduotong 同名占用，同步 `cordis.patch.yml` 的 `name` 与文档；GitHub-only 直装不变）。
- 2026-08-20 定价成熟化：成本改为**高峰/空闲分时计价**（北京时间 09-12/14-18 高峰）+ **2026-08-17 前历史价** + 按会话逐条计价；支持 `prices`/`priceSchedule` 覆盖（`buildStats`/`getStats` 可传入）。
- 2026-08-20 周期统计：新增**今日/本周/本月**（北京时间天桶）成本与 token 统计，缓存分析视图展示。
- 2026-08-20 修复客户端加载失败「bundle client.js 未注册 dsh-plugin-graph」：profile 以 `dsh-plugin-graph` 为 boot key 安装（旧名遗留），而客户端模块表按 boot key 校验、bundle 原注册 `dsh-graph-usage`。最终方案为**多 id 注册**：`lib/client.js` 用共享 factory 同时注册规范名 `@eave_bounty/dsh-graph-usage` 与旧名 `dsh-graph-usage`、`dsh-plugin-graph`；`scripts/preflight.mjs` 校验全部注册。
- 2026-08-20 首次发布 npm：包名 `@eave_bounty/dsh-graph-usage`@0.1.0（企业 scope，公开 `--access public`）；`publishConfig` 加 `access: public`；`cordis.patch.yml` 的 `name` 同步为 scoped 名；profile boot key 改为 `@eave_bounty/dsh-graph-usage`。
