按工作目录浏览 Claude Code、DSH 和 Codex 会话日志,查看每轮上下文构成、token 用量、压缩点和费用估算。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:Mt-Youya/dsh-plugins#path:/plugins/sessions-insight
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 简体中文
会话洞察 · dsh-sessions-insight(Sessions Insight)
DSH Web GUI 的只读「会话洞察」面板:解析 Claude Code / DSH / Codex 三个来源的会话日志,把模型每一轮实际收到的上下文拆开给人看——系统提示、工具定义、记忆与指令、历史、工具结果、图片各占多少,以及每个数字是精确的 usage 还是按字符折算的估算。

全程只读:不写源数据、不建索引、不落盘。唯一的缓存是进程内 LRU,进程结束即消失。
当前范围:只读洞察 + 摘要交接。交接把生成好的简报投递进 DSH 新会话,只调官方
session.create/session.prompt,不手写会话事件、不改写原会话(docs/HANDOFF.md、docs/adr/0003-never-handwrite-session-events.md、docs/adr/0007-accepted-is-not-success.md)。
它能回答什么
- 这一轮 392K 的上下文里,工具 schema 占了 95% 还是 5%?历史又被压缩换掉了多少?
- 同一个会话在第 7 轮之后为什么突变——压缩点在哪,前后窗口各是多少?
- 这个 29,018 是日志里的 usage,还是 chars/token 折算?每个数值都带
精确/估算徽标与口径。 - 三个来源里,某个工作目录一共有多少会话、多少轮、最近一次是什么时候?

界面
工作目录是唯一主轴,来源只是徽标。 工作目录 → 会话 → 轮次
- 顶栏:三个来源各自的可读状态和会话数(读不到会变暗,悬停看原因)、搜索、刷新、收起左栏。
- 左栏项目树:按工作目录分组,可以筛选;会话挂在项目下,带来源标记、时间和文件大小。列表只读文件头,点开会话才解析正文,所以大文件首开要等解压与解码。
- 会话头部:标题、来源、路径,以及四个指标卡:当前上下文(占窗口的比例,超过 80% 变黄)、峰值(出现在第几轮)、轮次(压缩点与工具调用数)、费用。
- 轮次列:顶部「累计水位」折线是每轮总上下文的走势,虚线竖条是压缩点,点任一点跳到那一轮。下面每行一轮:用户输入、token 数、构成条、时间、工具调用数、缩放系数和费用,各列上下对齐。每页 40 轮,底部「加载更多轮次」。
- 详情列:「第 N 轮」和用户输入固定在顶部,下面依次是上下文构成(每个分区带
精确/估算徽标)、压缩点、工具调用(默认折叠成一行摘要,报错的自动展开)、子代理会话。 ⌘K(Windows/Linux 上Ctrl+K)打开全库搜索,命中后直接跳到那一轮。

三源与读取位置
| 来源 | 默认根目录 | 覆盖用的环境变量 |
|---|---|---|
| Claude Code | ~/.claude/projects |
DSH_CONTEXT_INSIGHT_CLAUDE_ROOT |
| DSH | ~/.dsh/sessions |
DSH_CONTEXT_INSIGHT_DSH_ROOT |
| Codex | ~/.codex/sessions |
DSH_CONTEXT_INSIGHT_CODEX_ROOT |
某个来源缺失或不可读不影响其余来源:顶部只把该源标为「不可用」,并给出原因(根目录不存在 / 不可读 / 适配器异常)。
安装
需要 DSH 0.2.1-rc.2 或更高(插件按运行版 app.asar 内的行为对齐,见 docs/adr/0002-asar-021-is-the-contract.md)。
第 0 步:先确认装进哪个 profile
装错 profile 不会报错,只是面板不会出现。两者是不同的 profile,不是同一份配置:
| 你怎么启动 | 实际 profile | 命令 |
|---|---|---|
双击 DeepSeek Harness.app(桌面端) |
desktop |
--profile desktop |
dsh web(命令行 / 远程) |
web |
--profile web |
不确定时看进程参数或 ~/.dsh/profiles/ 下哪个目录在更新。
第 1 步:把包装进 profile
单独安装本插件:
dsh plugin --profile desktop add @cyrus/dsh-sessions-insight # 桌面端
dsh plugin --profile web add @cyrus/dsh-sessions-insight # dsh web
# 本地开发时换成目录或打包产物:
# dsh plugin --profile <name> add link:$PWD
# dsh plugin --profile <name> add /abs/path/cyrus-dsh-sessions-insight-<版本>.tgz
也可以装组合包 @cyrus/dsh-plugins,它会把合集里的插件一起装上(见仓库根 README)。
两种方式只能选一种。 组合包和本插件都会往加载树里插
id: sessions-insight,两个都在dsh.profile.bundles里时,DSH 启动会报duplicate loader entry id: sessions-insight并退出。
第 2 步:确认包名在 dsh.profile.bundles 里
实测 dsh plugin ... add 会顺带把包名追加到 ~/.dsh/profiles/<name>/package.json 的 dsh.profile.bundles 末尾。没自动加上时(link: 安装、手改过 package.json、或从旧版本升级)手工补齐——顺序有意义,后面的层覆盖前面的层:
{
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@cyrus/dsh-sessions-insight"]
}
}
}
第 3 步:重启
dsh web
侧边栏出现「会话洞察」一行即挂载成功。(市场里另有一个 dsh-context 插件叫「上下文洞察」,两者无关。)宿主侧自检(不带 Origin 头视为同源):
curl -sS http://127.0.0.1:<port>/api/dsh-sessions-insight/health
# {"ok":true,"value":{"version":"<版本号>","sources":["claude","dsh","codex"]}}
# value.version 是宿主侧常量 PLUGIN_VERSION,构建时从 package.json 注入
loader 行只在 boot 时组合,改完必须重启;浏览器热重载只覆盖「客户端 bundle 被重建」这一种情况。
权限与安全边界
- 只读:三个源目录只做
stat与读文件,从不写、不删、不改名。 - 不落盘:不建索引、不写缓存文件;进程内 LRU 以
source + id + mtime + size失效。 - 路径白名单:所有路径参数先解析、再做
realpath校验,必须仍落在三个白名单根目录之内——挡掉..与符号链接逃逸。 - 同源校验:每条路由都是
kind:'exact',先过 Origin/Host 门:Sec-Fetch-Site: cross-site直接 403,Origin与Host不一致 403;不带Origin的同源 GET 放行。 - 写路径只有交接:查询面全是 GET(
health/sources/workdirs/sessions/session/search/cost);唯一的写动作是handoff/apply,它只调官方session.create+session.prompt——不写源目录,也不往活会话里塞事件。 - 读取上限:单文件解码有字节上限,超限返回
read-limit,不会把宿主拖死。
已知限制
搜索有 2.5 秒预算。 全库搜索是流式的,达到
SEARCH_DEADLINE_MS = 2500就停:响应里truncated: true、remaining是没轮到的会话数,界面显示「预算内未扫完,还剩 N 个会话」。语料特别大时请缩窄来源,或按工作目录逐层点开。Claude 会话没有
prompt_snapshot时,面板会显示一大块「未知」。 这类会话(本机语料 121 个文件里 56 个)看不到工具定义与系统提示的原文,那一份只能留在residual里显式画成「未知」切片,不会等比摊进其他类别。这是有意为之,见docs/adr/0005-honest-attribution-residual.md。Codex 的思维链拿不到。
response_item.reasoning.encrypted_content是密文,只能计数、无法测量,因此 Codex 轮次不显示「思考」分块。分块数字是估算,总量才是精确值。 分块按 2.6 chars/token 折算,对指令体偏高约 23%;做过等比对账的轮次会显示
reconciled.factor(见docs/adr/0006-projection-not-differencing.md)。不要拿分块数字做计费。DSH 正文必须解日志。 projcache 只有元数据、没有正文投影,看内容时仍要逐帧解压会话日志,几 MB 的会话首开有明显停顿。
交接的
delivered是投递瞬间的状态,不是可持续观察的状态。 宿主接受 prompt 后约 30ms 内就会发出turn/start,所以轮询能看到的稳定状态只有running/succeeded/failed。成功判定以turn/end reason=completed为准,见docs/adr/0007-accepted-is-not-success.md。成本是「多张价目表」并存的,不做汇率换算。 共两张表,各自带
version/asOf/source:official(USD):DeepSeek 官方定价页,取 peak 价作为保守上界(cacheWrite 记 0——官方只按 cache hit/miss 计价);openrouter(USD):公开参考价,从/api/v1/models抽取,只作「参考」列。
主金额只取
official:DeepSeek 模型有主价,Claude/GPT 没有主价(null,不估算),只显示 openrouter 参考列。同一会话里出现不同币种时,合计按(表, 币种)分组并列,绝不跨表或跨币种相加、也没有汇率换算。价目里某通道未列价 ≠ 免费:该通道按 0 计入,金额前加≥并标partial。这些数字用于理解用量结构,不要拿去对账。
目录结构
本包只有两个半边,能力在它依赖的 workspace 包里。依赖方向是 plugins/sessions-insight → packages/*,由包边界维持:包名到源码的映射在 tooling/aliases.ts,tsconfig.json 的 paths 与之对应。
本包 plugins/sessions-insight/src/:
src/
├── index.ts 宿主入口:装配三源、注册路由(唯一碰 cordis 的文件)
├── protocol.ts 本包的线上契约出口:路由路径 + 转出契约包的 IR / 类型 / 守卫
├── version.ts 版本常量(构建时从 package.json 注入)
├── host/ 宿主半边
│ ├── http/ 同源门、信封、路由表(routes.ts + routes/)
│ ├── sources/ 三源装配、工作目录归并、快照索引、路径白名单
│ ├── views/ search / cost / pricing / brief
│ └── handoff/ 交接状态机(accepted ≠ 成功)
└── client/ 浏览器半边
├── index.tsx 入口:注册 sidebar/main 槽位与词典
├── api.ts 同源 fetch + 响应解码
├── format.ts / labels.ts / locale.ts 格式化、标签回落、zh/en 词典
├── styles.ts 注入编译好的 CSS(一次)
├── state/ 纯状态逻辑:树展平、轮次行、堆叠条算术
├── theme/ app.css、components.css、构建产物 generated.css.ts
└── ui/ 组件:面板、工具栏、项目树、会话头部、轮次列表与详情、工具明细、交接、搜索面板…
它依赖的包(packages/,构建时内联进 lib/,不单独发布):
packages/
├── plugin-kit/ 零依赖底座:JSON 信封、URL 拼法
├── session-contract/ 统一 IR、线上类型、guards → plugin-kit
├── session-readers/ Claude / Codex / DSH 三源适配与计量 → session-contract
├── plugin-kit-host/ 路由表、同源门、信封、LRU → plugin-kit
└── plugin-kit-client/ 解码 fetch、样式注入、槽位注册 → plugin-kit
开发
这些命令都在仓库根执行(本包不是独立仓库):
pnpm install
npx tsc --noEmit # 类型门禁:各包与宿主半边
npx tsc --noEmit -p tsconfig.client.json # 类型门禁:浏览器半边(types: [],摘掉 node 类型)
npx vitest run # 单测
npx tsdown # 构建 lib/index.js 与 lib/client.js
node scripts/check-bundle.mjs plugins/sessions-insight # 宿主加载契约
在包内也可以只构建自己:pnpm --filter @cyrus/dsh-sessions-insight build(等价于 css + tsdown)。
产物两个入口:
lib/index.js— 宿主半边(ESM,在 Host 的node:vmrealm 里跑)lib/client.js— 浏览器半边,必须是window.__ModuleLoader__.load({ id, factory })包装,react外置不打包
想验证挂载而不污染生产 profile,用隔离 DSH_HOME:
export DSH_HOME=/tmp/dsh-try
dsh try --from-default-profile web --dump-config # 从内置模板建 profile,只打印组合树
dsh plugin --profile try add "$PWD"
# 再把包名追加进 profiles/try/package.json 的 dsh.profile.bundles
dsh try --dump-config | grep -A2 sessions-insight # 确认 patch 行已插入
dsh try --host 127.0.0.1 --port 49744 --no-open # 独立端口 boot
文档
这些文档都在仓库根,不在本包目录内(npm tarball 只带 docs/images):
docs/RELEASE.md— npm 发布步骤docs/PLAN.md— 决策与里程碑docs/IR.md— 三源统一的轮次 IR(adapter 契约)docs/API.md— 宿主路由契约docs/HANDOFF.md— 交接链路契约docs/adr— 架构决策记录GLOSSARY.md— 词表
许可
链接
同类插件
bowenliang123/dsh-context★ 3190
DSH 上下文洞察面板:Context 仪表盘 + /context命令 + Context 浏览器,查看 Context的分类组成、内容详情、演进趋势、压缩/注入事件、统计等一站式 Context 全生命周期管理。
Han-1413141/dsh-cost-meter★ 489
会话与当日 API 费用统计、预算图框(已用%)、官方余额、历史看板,支持峰谷计价与官方价格一键同步。
wssfk12138/dsh-damage-pulse★ 273
在 DSH Web 界面追踪 DeepSeek Token 用量、单次与会话费用及账户余额,并显示缓存感知的扣费动画。
zh667/TokenLedger★ 199
侧边栏用量面板:把 Token 归属到实际服务该请求的中转站,站点从已有的 provider 配置中读出,无需额外配置;含今日/本月/累计三窗口、按站点与模型下钻、一年活跃度热力图,以及 New API / Sub2API / DeepSeek 余额。
Ychris12138/dsh-usage-stats★ 183
多供应商用量看板:按供应商/模型统计 Token 与日期下钻,统一展示账户余额,并追踪 OpenCode Go / Z.ai 订阅额度。
PolinniZhong/dsh-personal-center★ 112
DeepSeek Harness 个人中心:跨会话用量统计、按模型成本估算、全局自定义指令、外观全局字号、数据驱动的桌面宠物(位图/矢量皮肤)与会话状态概览,纯本地离线运行。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。