← 返回列表
✓ 可直接安装
📖 English · 中文文档 · 📝 更新记录 · Releases · 🎨 在线演示
自动检查通过:npm 包已发布且 engines 声明满足基线;该结论来自程序自动检查,未经人工实机验证。 · 最近上游提交 2026/9/17 · 已提供中文文档
DSH browser tab favicon reflecting session state: idle / running / asking / done. · DSH 标签页 favicon 实时反映会话状态:待机 / 运行中 / 提问 / 完成
综合分
31.4
GitHub 分
31.4
用户评分
—
★ Stars
2
周下载量
—
兼容 / 相关生态插件(非 dsh 原生,请按其对应运行时安装)
git clone https://github.com/waknow/dsh-web-icon-indicator.git数据截至 2026/9/19(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查✓ 自动检查通过
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-web-icon-indicator @ 0.5.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/19 07:36:37
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-web-icon-indicator
📖 English · 中文文档 · 📝 更新记录 · Releases · 🎨 在线演示
awesome · DSH plugin
npm version
npm downloads
License: MIT
⚠️ DSH 版本支持 —— 需要 DSH ≥ 0.1.2(设置卡片所用的 settings 服务 API)。已针对当前最高测试版本 DSH 0.1.2-rc.1 构建并验证。在 DSH 🎨 在线演示** — · 在浏览器里直接体验四种状态、多 Agent 计数与全部特效,无需安装。试玩间还能驱动演示页自身标签页的真实 favicon——正如插件在 DSH 页面里做的那样。
✨ 功能特性
- 标签页 favicon 实时反映会话状态 —— 浏览器标签页图标同步 idle / running / asking / done(聚合优先级:asking > running > done > idle),后台标签页也能一眼看清 agent 们在做什么——包括 ask_user_question 提问,以及审批 / 沙箱提权等待(这两种情况会把图标钉在 asking 态)。
- 单个 SVG,浏览器内上色与动画 —— 只内置一个鲸鱼模板(icons/base.svg);每个状态、颜色、每一帧都在客户端渲染为 data:image/svg+xml URI,不再有按颜色拆分的图标文件。
- 六种内置特效 —— static(静止)、blink(闪烁)、breath(呼吸)、rainbow(彩虹)、heartbeat(心跳)、bounce(跳动),全部由 JavaScript 驱动(favicon 不会播放 SVG CSS 动画)。
- 完全可配置、即时生效 —— 每个状态的颜色、特效、周期,以及提问 / 完成驻留时长,改动约 1 秒内同步到已打开的标签页——无需刷新、无需重启。
- 内置配置 UI,无需手写 YAML —— DSH 设置页里的 标签页图标指示器 卡片可编辑整套配置,带实时色块预览,保存后自动写入 settings.yaml(路径见下)。
- 后台标签页与重启抗性 —— 隐藏标签页中 requestAnimationFrame 被暂停时,动画态会按墙钟时间补帧;状态轮询还能扛住 host 重启、后端停止:故障期间标签页图标绝不丢失(还原启动时缓存的原始图标 data:-URI 副本,或保留最后一帧插件图标),端点恢复后自动回到实时状态。切回前台时会立刻触发一次状态拉取并重绘——后台标签页的定时器会被浏览器节流,轮询可能滞后,所以回到标签页的瞬间就刷新最新状态(比如 done 保持期在隐藏期间过期、图标应退回 idle 的情况)。
- 多 agent 一目了然 —— 当同时有超过一个活动 agent(非待机:asking / running / done)时,favicon 从鲸鱼切换为占满整帧的数字块,实时显示活动数(上限 99+),颜色与动画和该状态下鲸鱼完全一致;活动数回到 0–1 时恢复鲸鱼。(视觉与 demo/badge.html 的「满幅数字」通道一致。)
🛠 配置界面——怎么找到它
| # | 步骤 |
| --- | --- |
| 1 | 打开 DSH Web GUI,进入 设置。 |
| 2 | 在 插件 选项卡中,打开 插件配置。 |
| 3 | 找到 标签页图标指示器(Favicon indicator) 卡片。 |
| 4 | 先用 默认图标颜色 设置待机鲸鱼的颜色(这是待机唯一的设置项——待机只画一种颜色、不做动画),再展开状态行(running / asking / done)编辑 特效、颜色(每个色块即原生取色器),以及周期(毫秒)——仅动画状态显示,静态状态无周期;用 提问驻留 / 完成驻留 调整两个时长。 |
改动会通过 settings 传输层持久化到 profile 的 settings.yaml,约 1 秒内应用到已打开的标签页——无需刷新、无需重启。完整键说明见 配置。
🎬 默认配置,可视化
四个默认状态在浏览器标签页中的实际效果(asking 那条鲸鱼真的在闪烁):
| 状态 | 颜色(默认) | 特效(默认) |
| --- | --- | --- |
| idle 待机 | #1a1a1a——深色鲸鱼(可用 defaultColor 替换) | static |
| running 运行中 | #FACC15——黄色 | static |
| asking 提问 | #E5484D ⇄ #FACC15——红/黄 | blink(400ms) |
| done 完成 | #22A06B——绿色 | static,保持 doneHoldMs 后回到 idle |
多 agent 可视化
当多个 agent 同时运行时,favicon 本身就是计数器:只要活动 agent 超过一个
(非待机:asking / running / done,含短暂的 done 保持期),鲸鱼就换成
占满整帧的数字块——实时显示 active 计数,底色取聚合状态色、特效与鲸鱼完全
同源(照常闪烁 / 呼吸 / 彩虹);活动数回到 0–1 时恢复鲸鱼。
| active(非待机 agent 数) | favicon |
| --- | --- |
| 0 | 深色 idle 鲸鱼 |
| 1 | 对应状态的鲸鱼(running 黄色,…) |
| 2–99 | 占满整帧的数字块,数字高度约占图标的 31%–52%(1 位 26、2 位 20、3+ 位 15.5)——16px 与固定标签页都可读 |
| 100+ | 99+ |
状态优先级不变:asking 仍以红 ⇄ 黄 400ms 闪烁接管(闪烁的是数字块),
done 按其颜色驻留 doneHoldMs,计数随状态轮询实时刷新(约 1 秒)。
视觉与 demo/badge.html 的「满幅数字」通道一致。
✨ 全部特效,动画演示
下面每个预览都是真实的鲸鱼路径,按插件实际渲染方式做动画(预览是自包含的动画 SVG,在浏览器里直接播放):
| 特效 | 效果 | 预览 |
| --- | --- | --- |
| static | 纯色单帧,无动画——使用 colors[0] | |
| blink | 在 colors[0] ⇄ colors[1] 之间按 speed 切换(缺省时自动推导更深的第二色) | |
| breath | 在 colors[0] 与 colors[1] 之间平滑呼吸过渡(缺省时推导) | |
| rainbow | 以 colors[0] 为起始色相,在 speed 内绕色轮循环 | |
| heartbeat | 在 speed 内做「lub-dub」式的尖锐缩放脉冲——颜色为 colors[0] | |
| bounce | 鲸鱼在 speed 内上下跳动——颜色为 colors[0] | |
想改颜色并实时观察标签页 favicon 变化?打开自包含 demo(demo/dynamic-color.html)——选择状态 + 特效并实时改色,favicon 即时更新(无构建、无依赖)。
安装
这是一个标准 DSH bundle 插件。安装到 web profile(GUI/TUI profile 会自动通过 cordis patch 层加载):
从 npm 安装(推荐):
dsh plugin --profile web add dsh-web-icon-indicator@latest
从 Git 源码安装:
dsh plugin --profile web add github:waknow/dsh-web-icon-indicator
或从本地目录 / tarball 安装:
dsh plugin --profile web add
或将目录放进 ~/.dsh/profiles/web/node_modules//,并附带与包内一致的 cordis.patch.yml。
配置
所有键均可选,默认值如下。statusPath 与 iconPathPrefix 是注册期键:
只能在合成条目(composition entry)里设置——它们在插件挂载时就被烘进路由表与注入
脚本,因此刻意不进入设置面(settings.yaml)。
| 键 | 默认值 | 含义 |
| --- | --- | --- |
| iconsDir | /icons/ | 单个 base.svg 所在目录 |
| statusPath | /dsh-web-icon-status.json | JSON 状态端点 —— 注册期(仅合成条目) |
| iconPathPrefix | /dsh-web-icon-indicator | base.svg 的 URL 前缀 —— 注册期(仅合成条目) |
| askingHoldMs | 3500 | 提问状态的最小保持时长 |
| doneHoldMs | 5000 | 完成状态保持时长,随后回到 idle |
| defaultColor | (未设置) | 默认图标颜色(待机鲸鱼的主色)—— 用于区分多个 DSH 实例;与其它状态颜色过于接近时会告警 |
| states | 见下 | 每个状态的视觉配置 |
states 中每个状态是一个对象:{ effect, colors[], speed? }:
config:
states:
idle: { effect: static, colors: ['#1a1a1a'] }
running: { effect: static, colors: ['#FACC15'] }
asking: { effect: blink, colors: ['#E5484D', '#FACC15'], speed: 400 }
done: { effect: static, colors: ['#22A06B'] }
- effect — 取 static | blink | breath | rainbow | heartbeat | bounce 之一。
- colors — 数组,多个 hex 颜色(#rgb / #rrggbb;非法项会被逐项忽略,全部无效时才回退到该状态的内置颜色)。colors[0] 为主色。多色特效读取更多项:blink 用 colors[0]⇄colors[1],breath 在 colors[0]⇄colors[1] 间过渡(缺省时自动推导更深的第二色),rainbow 仅用 colors[0] 作起始色相。
- speed — 可选,该状态的周期(ms),也是 blink 的切换间隔。默认 1200。
idle 比较特殊:它的颜色就是 defaultColor 键,设置卡片不为它提供状态条目
(一种颜色、不做动画、也没有周期)。若 states.idle 来自合成条目或手写的
settings.yaml,仍然会被沿用——这属于向后兼容,只是无法在卡片里编辑。
每个状态条目会在默认值之上做浅合并,因此只需覆盖少量状态。示例:
- id: dsh-web-icon-indicator
name: 'dsh-web-icon-indicator'
config:
states:
running: { effect: breath, colors: ['#FF9900', '#FFD9A0'], speed: 900 }
asking: { effect: rainbow, colors: ['#FF0000'] }
done: { effect: heartbeat, colors: ['#2ECC71'] }
区分多个实例(defaultColor)
同时开多个 DSH 实例(不同项目 / profile / 端口)时,给每个实例设一个自己的默认图标
颜色,浏览器标签页就能一眼区分,不必去改整套状态配色:
- id: dsh-web-icon-indicator
name: 'dsh-web-icon-indicator'
config:
defaultColor: '#5B8DEF'
- defaultColor 就是待机鲸鱼的主色。它会被折叠进 states.idle.colors[0],
因此 idle 仍保留自己配置的特效与第二色,其它状态的颜色语义(黄=运行、红/黄=提问、
绿=完成)不受影响;不设置(默认)即等于「沿用 idle 自己的颜色」,行为与之前完全一致。
- 这是按 DSH 实例生效的设置,不是按标签页:同一实例的所有标签页共用它;另一个实例
(自己的 profile / settings.yaml,例如 dsh web --port 3081)可以用另一种颜色。
- 恢复默认会把你的覆盖清回合成条目。当颜色本来就来自合成条目(base 层,
用户层的 unset 触及不到)时,卡片改为写入 idle 自己的颜色——这样「恢复默认」真的
能让图标回到朴素的鲸鱼色,而合成条目里配置的值仍可通过「清除覆盖」一键取回。
- 相似度告警:当默认颜色与其它状态颜色在感知上过于接近时,你会收到告警 —— 设置卡片里
实时显示(保存前即可见)、host 日志里记录、状态端点 warnings 中返回 —— 但该颜色
仍然会被应用(告警绝不阻断保存)。度量方式是 CIELAB 中的 CIE76 ΔE:ΔE running > done > idle。每次请求都会执行一次 reconcile() 检测 running → idle 的转换,因为 agent/status 的 idle 事件在回合结束时并不保证送达。状态端点还会上报 active——非待机 agent 数——当该数 > 1 时,注入脚本改为渲染占满整帧的数字块(demo/badge.html 的「满幅数字」通道:圆角色块,填充色与鲸鱼同源的逐帧状态色/特效,白色粗体数字约占图标高度 31%–52%,上限 99+),而不是鲸鱼,这样即使在 16px 的固定标签页里也能一眼看出同时有几个 agent 在忙。
- ask_user_question 工具调用(通过 tools/pre-execute / tools/result)把会话置为 asking,带可配置的最小保持时长,即使你立刻回答,图标也会保持可见。
- 权限 / 沙箱拦截等待同样会显示为 asking:当 agent 命中沙箱拒绝并请求提权(sandbox_permissions + justification),或其他工具需要征得同意时,审批服务会先写入一条 approval/asked 会话事件并阻塞 agent,直到你做出决定。插件监听 session/event(并以实时会话日志的权威折叠作为兜底)在整个等待期间将会话置为 asking 状态,收到 approval/decided 后清除。
- 浏览器脚本每秒轮询 /dsh-web-icon-status.json(轮询间隔在注入脚本里固定为 1000 ms,不是配置项),首次获取 base.svg,然后每个 requestAnimationFrame 周期把 favicon 重建为 data:image/svg+xml,… URI——把 __COLOR__ 占位符替换为状态配置的颜色,并应用该状态配置的特效。状态响应还会携带当前的每状态视觉配置,因此设置保存后约 1 秒内(下一个轮询 tick)即同步到已打开的标签页,无需刷新。浏览器不会播放 SVG favicon 的 CSS 动画,所以一切动画都由 JS 驱动。由于浏览器在隐藏(后台)标签页会暂停 requestAnimationFrame,轮询还会为动画态补绘一帧按墙钟时间计算的画面——后台标签页保持粗粒度动画(约每 1 秒)而不会冻结,切回前台后恢复满速动画。回到前台时还会通过 visibilitychange 立即触发一次状态拉取并重绘——后台定时器会被节流,轮询可能滞后,所以切回标签页的瞬间就能看到最新状态(例如隐藏期间 done 保持期已过、图标应退回 idle)。轮询还能扛住 host 重启 / 后端停止:启动时会把原始 favicon 缓存为离线安全的 data:-URI 副本,请求失败时还原该副本(副本未取到则保留最后一帧插件图标)——绝不写回原始的服务端 URL(后端停止时它恰恰不可达,写回正是「图标丢失」的根因);每个 tick 持续重试,端点恢复后第一个成功轮询即换回实时图标(SPA 原地重连,无需手动刷新)。
浏览器支持与已知限制
favicon 本质是一张图片,浏览器不会在标签页 UI 里运行 SVG 自带的 CSS/JS 动画——每一帧都在本插件里由 JavaScript 生成。
| 浏览器 | SVG favicon | 逐帧换色 / 换特效 | 说明 |
| --- | --- | --- | --- |
| Chrome / Edge | ✅ | ✅ 顺滑 | 实时重读 ;data: URI 的 SVG 可用。 |
| Firefox | ✅ | ✅ 顺滑 | 对 SVG favicon 支持良好(且会响应其 prefers-color-scheme,本插件未使用)。 |
| Safari(macOS) | ✅ 渲染为静态图 | ⚠️ 尽力而为 | 忽略 SVG 内嵌 CSS;favicon 缓存激进。 |
| Safari(iOS) | ✅ 渲染为静态图 | ⚠️ 基本不刷 | 通常需重新访问标签页才刷新。 |
已知限制(截至 Safari 26.3):
- favicon 有专属缓存。 Chrome 用 favicon 数据库、Firefox 用 favicons.sqlite、Safari 用系统级图标缓存——清普通缓存都清不掉,WebKit 甚至会把「无图标」这一状态也缓存起来。这就是改了图标后,已打开的标签页还可能显示旧图标的原因。本插件已通过「给 base.svg 与状态端点设置 Cache-Control: no-store、请求携带 freshness 参数(?t=Date.now())、每次切换状态时重建 节点」来缓解。
- Safari 渲染 SVG favicon,但忽略其内部 CSS——不支持 @media、prefers-color-scheme、CSS 动画。所以所有上色必须烘焙进每一帧的标记(本插件正是这么做的),而不能依赖 CSS 变量。
- data: URI 的 SVG favicon 在 Safari 不可靠(WebKit bug 236616,仍未关闭;Safari 17.6 复现)。本插件当前每帧都生成 data:image/svg+xml URI,因此在 Safari 上标签页图标可能完全不显示——这是最大的已知缺口。
- Safari 的动态 JS 更新为 hit-or-miss,可能需要刷新一次;Safari 会「锁定」它首次看到的图标。目前没有保证可靠的、符合规范的手段能在 Safari 中实时更换 favicon。
- 固定标签页图标()使用独立缓存,与普通 favicon 分开;它是靠 color 属性着色的单色剪影——仅 macOS + 固定标签页、页面加载时读取一次、并非实时。
完整机制与来源(WebKit bugs、Stack Overflow、浏览器工程博客)以及让 Safari 更顺滑变色/切换的推荐路径见 docs/safari-favicon-research.md。
已知限制
- favicon 的 SVG CSS 动画在浏览器标签页 UI 中不会运行——所有特效都由 JavaScript 每帧重建 data-URI 实现,这是零依赖设计的刻意取舍。(本文档中的动画预览只是演示素材——真实 favicon 的动画始终由 JS 驱动。)
- favicon 行为因浏览器而异,其中 Safari 限制最多——见 浏览器支持与已知限制。
- base.svg 模板必须保留 #p { fill: … } 规则中的 __COLOR__ 占位符;浏览器会替换该标记为每帧上色。
- 插件运行在 host 平面,必须挂载进 profile 的组合配置,不能作为会话级 agent preset。
- 文件读取走 fs 服务,以配置的 iconsDir 为 cwd。请确保该路径在部署环境的沙箱策略下可读。
许可
MIT扫码进群