架构与数据流

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:全局唯一且避开 lightdarksystem
  • colorScheme:决定基于亮色还是暗色基础调色板。
  • tokens:只覆盖 --dsw-* 语义变量。

Client 入口用 ctx.theme.register() 注册定义。选择器调用 ctx.theme.setTheme()theme/changeuseSyncExternalStore 触发组件更新。

第三方主题 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 销毁。

因此开发期热重载不会不断累积主题、组件、背景状态或样式。