架构与数据流
August 23, 2026 · View on GitHub
总览
flowchart LR Log["持久 Session Log"] --> Meter["官方 dsh-token-meter"] Meter --> Projection["tokenUsage 会话投影"] Projection --> NativeStats["Harness 原生聊天统计条"] Projection --> Dashboard["设置 → Token 用量"] Projection --> Reader["ctx.skinTokenUsage.read(session)"] Package["dsh-skin-token-dashboard Client"] --> ThemeRuntime["ctx.theme / ThemeRuntime"] ThemeRuntime --> Presenter["ui-layout 主题呈现"] Picker["设置中的皮肤与背景选择器"] --> ThemeRuntime Picker --> BackgroundController["背景偏好控制器"] Assets["内嵌摄影背景"] --> BackgroundController BackgroundController --> Presenter
插件遵循三个边界:
- Token 事实由官方 token-meter 拥有;本插件不重新订阅并折叠事件。
- DOM 主题应用由官方 ui-layout 拥有;本插件只注册语义 Token 和发起主题选择。
- 背景控制器只写根元素上的插件私有属性与 CSS 变量,不读取消息或工作区数据。
Token 统计链路
数据来源
@deepseek-ai/dsh-token-meter 在标准 base profile 中注册 tokenUsage 投影。投影按完整持久日志计算,而不是按当前页面已经加载的消息计算,因此:
- 向上翻页不会改变总量。
- 上下文压缩不会删除已产生的计费用量。
- usage chunk 与最终 assistant message 的同一步用量不会重复计数。
- reasoning token 已包含在 output 中。
设置页面
TokenUsageSource 在根设置作用域跟随 ctx.sessions.list.current,并订阅当前会话的 tokenUsage 投影。切换会话或收到新的投影帧时,“设置 → Token 用量”会同步刷新;未选择会话和投影不可用分别使用独立空状态,不用零值掩盖缺失能力。
汇总公式
billedInputTokens =
uncachedInputTokens
+ cacheReadTokens
+ cacheWriteTokens
totalTokens = billedInputTokens + outputTokens
cacheHitRate =
billedInputTokens == 0
? 0
: cacheReadTokens / billedInputTokens
API 失败语义
ctx.skinTokenUsage.read(session) 在正常标准 profile 中返回汇总。以下情况返回 undefined:
- 组合未提供
tokenUsage投影。 - 未来版本返回了不兼容结构。
- 任一计数不是非负安全整数。
插件不会用猜测值掩盖契约错误。
主题链路
themes.ts 中每个皮肤都是官方 ThemeDefinition:
id:全局唯一且避开light、dark、system。colorScheme:决定基于亮色还是暗色基础调色板。tokens:只覆盖--dsw-*语义变量。
Client 入口用 ctx.theme.register() 注册定义。选择器调用 ctx.theme.setTheme();theme/change 经 useSyncExternalStore 触发组件更新。
第三方主题 ID 是进程内扩展。恢复“跟随系统”会回到 Harness 内置、可持久化的 system 偏好。
背景链路
assets/backgrounds 中的图片来自 F:\tmp,提交前统一按 2560px 长边和 JPEG 质量 82 优化。生成脚本把图片编码进 background-assets.generated.ts,因此 Desktop 的 file:// 页面和 Web 页面都无需跨盘读取或额外静态文件路由。
backgrounds.ts 负责:
- 校验并恢复
localStorage中的背景 ID。 - 通过稳定快照向 React 选择器同步状态。
- 在文档根元素设置图片、焦点位置和皮肤叠色强度。
- 在插件卸载时清理 data 属性与 CSS 变量。
styles.ts 使用当前 --dsw-* 主题色生成线性与径向渐变。主题的层级背景使用半透明颜色,使照片在保持文字对比度的同时透过侧边栏和内容层;“使用纯色背景”会完全移除图片层。
生命周期与清理
所有注册都绑定 Cordis fiber:
- 主题定义卸载时注销。
- 设置 slot 卸载时移除。
- 样式标签卸载时删除。
- 背景控制器卸载时移除监听器和根元素状态。
- Host service 随插件 fiber 销毁。
因此开发期热重载不会不断累积主题、组件、背景状态或样式。