Skip to content
dsh.fish
Bundle

traffic-light

DSH 会话状态信号灯:在输入框区域显示红/黄/绿三色灯,实时反映会话状态(就绪/生成中/出错),点击可查看详情。

Source
aliuguofa
License
MIT
Updated
Updated 23 hours ago

Readme

# traffic-light · DSH 会话状态信号灯

一个 DeepSeek Harness Web UI 插件:在聊天输入框区域显示一盏**红 / 黄 / 绿三色信号灯**,实时反映当前会话的状态,点击可查看详情。

| 灯色 | 含义 | 判定来源 |
| --- | --- | --- |
| 🟢 绿灯 | **就绪** —— 会话空闲,可以发送新消息 | `running === false` 且无错误 |
| 🟡 黄灯 | **生成中** —— 助手正在思考或调用工具 | `running === true` |
| 🔴 红灯 | **出错 / 中断** —— 上一次请求出错或被中断 | `promptError !== null` 或会话打开失败 |

亮灯带光晕脉冲动画,其余两盏灯暗灭。点击信号灯弹出详情面板,包含状态说明、(出错时)错误文本与排查提示、(生成中时)实时吞吐量。

## 状态判定逻辑

插件注入到 `conversation.composer.dock` 插槽(输入框下方的停靠区,会话级 scope),框架向每个 entry 注入 `useSession`、`useProjection`、`t` 三个 hook。信号灯据此判定:

```js
const running     = useSession((s) => s.running)        // 会话是否正在运行
const promptError = useSession((s) => s.promptError)    // 提交提示是否出错
const openState   = useSession((s) => s.openState)      // 会话打开状态
const openError   = useSession((s) => s.openError)      // 会话打开错误
const tps         = useProjection("liveTokenUsage")?.tokensPerSecond  // 实时吞吐(仅详情展示)

const hasError = promptError !== null || openState === "error"
const status   = hasError ? "red" : running ? "yellow" : "green"
```

优先级:**出错(红)> 生成中(黄)> 就绪(绿)**。所有信号均来自 DSH 客户端会话快照与官方 projection,无轮询、无猜测。

## 安装

将本目录作为一个 npm 包加入当前 DSH profile:

```bash
dsh plugin --profile desktop add ./traffic-light
```

或直接指向本地路径 / Git 仓库:

```bash
dsh plugin --profile desktop add D:/workbuddy/dsh/traffic-light
```

`cordis.patch.yml` 会自动把插件挂载到 Web 组合;`package.json` 的 `dsh.client.platform = "web"` 声明让浏览器半(`lib/client.js`)被模块加载器发现。安装后刷新 Web GUI 即可见到信号灯出现在输入框区域。

## 文件结构

```
traffic-light/
├── package.json          # dsh.bundle + dsh.client 声明,exports./client
├── cordis.patch.yml      # profile 层挂载(- insert: traffic-light)
├── lib/
│   ├── index.js          # 宿主半:空 apply(),纯 UI 插件
│   └── client.js         # 浏览器半:TrafficLight 组件 + 状态判定 + i18n + CSS
├── LICENSE
└── README.md
```

## 设计要点

- **纯 UI 插件**:宿主半 `lib/index.js` 为空 `apply()`,所有逻辑在浏览器半,参照官方 `reasoning-slider` 的自包含模式。
- **单文件自包含**:`client.js` 用 `React.createElement`(不依赖 `react/jsx-runtime`),CSS 以 `<style>` 内联注入(`data-plugin-css="traffic-light"`,幂等),无构建步骤、无外部依赖。
- **健壮降级**:当框架未注入 `useSession` / `useProjection` / `t` 时,信号灯仍能安全渲染(降级为默认文案),不会抛错破坏输入框;React hooks 调用次数恒定,符合 hooks 规则。
- **无障碍**:信号灯为 `button`,带 `aria-haspopup` / `aria-expanded` / `aria-label`;详情为 `role="dialog"`;支持 Escape 关闭、点击外部关闭;尊重 `prefers-reduced-motion`。
- **i18n**:通过 `ctx.get("locale").register("traffic-light", { zh, en })` 注册中英文字典;entry 注册带 `locale: NS`,`t` 自动绑定本命名空间。
- **复用官方 token**:颜色用语义色(红 = error、黄 = warn、绿 = success),其余用 `--dsw-alias-*` 设计令牌,随主题亮暗自适应。

## 自定义

- **位置/顺序**:在 `lib/client.js` 的 `slots.register` 中改 `order: 90`(数值越大越靠后,官方 `StatsLine` 为 0、`live-stats` TPS 行为 100)。
- **灯色**:修改 `.tl-lamp-on.tl-*` 三条 CSS 规则的 `background` / `box-shadow`。
- **文案**:编辑 `lib/client.js` 顶部 `zh` / `en` 字典。

## 兼容性

基于 DSH Desktop `0.1.1-rc.1` 的 Web UI 接口开发,依赖:

- `conversation.composer.dock` 插槽(session-scoped list)
- 会话快照字段 `running` / `promptError` / `openState` / `openError` / `composerPhase`
- `liveTokenUsage` projection(可选,仅详情展示)

仅读取官方稳定字段,不写入任何设置、不发起网络请求。

Install

dsh plugin --profile web add github:aliuguofa/dsh-traffic-light

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source