dsh-tab-status-light 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +182 -58
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,96 +1,220 @@
|
|
|
1
1
|
# dsh-tab-status-light
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Put the AI session state on your browser tab icon** — a plugin for the [DeepSeek Harness](https://github.com/deepseek-ai) Web UI.
|
|
4
|
+
|
|
5
|
+
[English](#english) · [繁體中文](#繁體中文)
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## English
|
|
12
|
+
|
|
13
|
+
While a turn runs, the tab icon blinks gray; when the turn finishes it turns green;
|
|
14
|
+
while the session waits for you it turns yellow; when a turn is interrupted it turns red.
|
|
15
|
+
You can tell the state of the agent at a glance — even from another tab — without
|
|
16
|
+
switching back to the app.
|
|
17
|
+
|
|
18
|
+
| State | Color | Animation | Derived from |
|
|
19
|
+
| --- | --- | --- | --- |
|
|
20
|
+
| Working | gray `#9ca3af` | blinks every 600 ms: **the plain whale** ↔ whale + gray dot (the off half has no dot at all) | `SessionStatus.running === true` |
|
|
21
|
+
| Done | green `#22c55e` | lit for 10 s, then back to the plain whale | a turn **seen running here** whose last `turn/end` reason is not an interruption |
|
|
22
|
+
| Waiting for you | yellow `#eab308` | stays lit until you answer | `SessionStatus.pendingInteraction !== undefined` (question / approval / plan review) |
|
|
23
|
+
| Interrupted | red `#ef4444` | lit for 20 s, then back to the plain whale | a turn **seen running here** whose last `turn/end` reason is `aborted` / `blocked` / `error` / `interrupted` |
|
|
24
|
+
|
|
25
|
+
The shipped whale is left untouched when no session is selected, when the session has
|
|
26
|
+
not finished a turn yet, or when you merely **switch to a session that finished long ago**
|
|
27
|
+
— green/red are news about something that just happened, not a replay of history.
|
|
28
|
+
`SETTLE_MS` (green, 10 s) and `SETTLE_MS_RED` (red, 20 s) control how long a settled
|
|
29
|
+
badge stays; any new finished turn lights it again.
|
|
30
|
+
|
|
31
|
+
### Install
|
|
32
|
+
|
|
33
|
+
The plugin ships as a DSH bundle (`dsh.bundle.patch`). Install it with the harness
|
|
34
|
+
`plugin_manager`:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
plugin_manager({ action: "install_bundle", target: "dsh-tab-status-light" })
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or from the CLI:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
dsh plugin --profile web add dsh-tab-status-light
|
|
44
|
+
# straight from GitHub instead of npm
|
|
45
|
+
dsh plugin --profile web add github:kyle2241345145351324321/dsh-tab-status-light
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or point at a checkout (handy while developing — edits apply on page reload):
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
plugin_manager({ action: "install_bundle", target: "/path/to/dsh-tab-status-light" })
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Reload the page (`Cmd+R` / `Ctrl+R`) after installing.
|
|
55
|
+
|
|
56
|
+
> Requires the harness Web profile with the `@deepseek-ai/dsh-client-ui-session` and
|
|
57
|
+
> `@deepseek-ai/dsh-api-session-controller` client packages available (a standard
|
|
58
|
+
> install has both).
|
|
59
|
+
|
|
60
|
+
### How it works
|
|
61
|
+
|
|
62
|
+
- **Pure Client plugin, occupies no slot**: it reads `ctx.sessions.list` (which session
|
|
63
|
+
is the main view) and `ctx.uiSession.sessionStatus` (running / pending interaction),
|
|
64
|
+
and follows the session's event source for the newest `turn/end` reason.
|
|
65
|
+
- The icon is **redrawn from the live favicon**: it `fetch()`es the shipped
|
|
66
|
+
`favicon.svg` / `favicon-dark.svg`, splices one `<circle>` in before `</svg>`, and
|
|
67
|
+
swaps the `href` of `<link rel="icon">` to a data URL (Chrome repaints the tab icon).
|
|
68
|
+
The original `href` is restored on teardown.
|
|
69
|
+
- Because of that, the whale artwork is never copied into this plugin — upstream logo
|
|
70
|
+
changes carry over automatically.
|
|
71
|
+
- Badge geometry inside the shipped 50×50 viewBox: `cx=37, cy=37, r=11, stroke-width=4`;
|
|
72
|
+
the ring uses the tab background (dark `#35363a`, light `#ffffff`) to separate the dot
|
|
73
|
+
from the mark.
|
|
74
|
+
- Blinking is driven by a tiny Web Worker, so it **keeps blinking while the tab is in
|
|
75
|
+
the background** (Chrome throttles page timers in hidden tabs). It falls back to a
|
|
76
|
+
page timer where workers are unavailable.
|
|
77
|
+
- Both blink halves are precomputed data URLs, so every swap paints on the tick — no
|
|
78
|
+
file re-read, which is what made the pulse look uneven in earlier versions.
|
|
79
|
+
|
|
80
|
+
### Tuning
|
|
81
|
+
|
|
82
|
+
All at the top of [`client.js`](client.js):
|
|
83
|
+
|
|
84
|
+
| Constant | Default | Meaning |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| `BADGE` | `{cx:37, cy:37, radius:11, ring:4}` | dot position / radius / ring width |
|
|
87
|
+
| `BADGE_COLOR` | gray / green / yellow / red | state colors |
|
|
88
|
+
| `BLINK_MS` | `600` | blink period while working |
|
|
89
|
+
| `SETTLE_MS` | `10000` | how long the green badge stays |
|
|
90
|
+
| `SETTLE_MS_RED` | `20000` | how long the red badge stays |
|
|
91
|
+
| `RED_TURN_END_KINDS` | `aborted` `blocked` `error` `interrupted` | turn endings that count as interruptions |
|
|
92
|
+
|
|
93
|
+
### Resource use
|
|
94
|
+
|
|
95
|
+
Blinking costs about **2 ms of JS per second** (≈0.2 % of one core); when idle it costs
|
|
96
|
+
nothing — no timers, no rescans.
|
|
97
|
+
|
|
98
|
+
### Known limits
|
|
99
|
+
|
|
100
|
+
- The icon reflects the **main view** session only; background sessions are not shown.
|
|
101
|
+
- Switching to a session that finished earlier does not flash green (only a turn watched
|
|
102
|
+
running lights up).
|
|
103
|
+
- Blinking continues in a background tab, but a **frozen** tab (Chrome Memory Saver /
|
|
104
|
+
battery saver) stops all page JS — no web API can bypass that. To keep it alive, add the
|
|
105
|
+
origin to `chrome://settings/performance` → "Always keep these sites active".
|
|
106
|
+
`navigator.wakeLock` does **not** help: it only keeps the screen awake and is released
|
|
107
|
+
as soon as the page is hidden.
|
|
108
|
+
- When a frozen or backgrounded tab wakes up, the plugin resyncs and repaints immediately,
|
|
109
|
+
so the icon is always correct when you look at it.
|
|
110
|
+
- It swaps SVG data URLs into `<link rel="icon">`; very old browsers without SVG favicon
|
|
111
|
+
support will show no change.
|
|
112
|
+
|
|
113
|
+
### Development
|
|
4
114
|
|
|
5
|
-
|
|
6
|
-
|
|
115
|
+
```js
|
|
116
|
+
// this repo *is* the installable bundle — there is no build step
|
|
117
|
+
plugin_manager({ action: "install_bundle", target: "/absolute/path/to/dsh-tab-status-light" })
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Edit `client.js`, then reload the page: the Client module is served from disk.
|
|
121
|
+
|
|
122
|
+
### License
|
|
123
|
+
|
|
124
|
+
[MIT](LICENSE)
|
|
7
125
|
|
|
8
|
-
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 繁體中文
|
|
129
|
+
|
|
130
|
+
**把 AI 的狀態畫在瀏覽器分頁圖示上** —— 一個給 DeepSeek Harness Web UI 用的外掛。
|
|
131
|
+
|
|
132
|
+
AI 在做事時分頁圖示會**灰色一閃一閃**;這一輪完成變**綠**;在等你回答(提問/核准/計畫審查)
|
|
133
|
+
時變**黃**;這一輪被打斷變成**紅**。切到別的分頁也看得到現在是什麼狀態,不用切回來確認。
|
|
9
134
|
|
|
10
135
|
| 狀態 | 顏色 | 動畫 | 判定依據 |
|
|
11
136
|
| --- | --- | --- | --- |
|
|
12
|
-
| 進行中 | 灰 `#9ca3af` |
|
|
13
|
-
| 完成 | 綠 `#22c55e` | 亮 10
|
|
14
|
-
| 等你回答 | 黃 `#eab308` |
|
|
15
|
-
| 中斷 | 紅 `#ef4444` | 亮 20
|
|
16
|
-
|
|
17
|
-
沒選 session
|
|
18
|
-
|
|
19
|
-
|
|
137
|
+
| 進行中 | 灰 `#9ca3af` | 每 600 ms 切換:**純鯨魚** ↔ 鯨魚+灰點(暗的那半完全沒有圓點) | `SessionStatus.running === true` |
|
|
138
|
+
| 完成 | 綠 `#22c55e` | 亮 10 秒後回到純鯨魚 | 這一輪**被看到在跑**,且最後一個 `turn/end` 原因不是中斷類 |
|
|
139
|
+
| 等你回答 | 黃 `#eab308` | 一直亮著直到你回答 | `SessionStatus.pendingInteraction !== undefined`(提問/核准/計畫審查) |
|
|
140
|
+
| 中斷 | 紅 `#ef4444` | 亮 20 秒後回到純鯨魚 | 這一輪**被看到在跑**,且最後一個 `turn/end` 原因是 `aborted`/`blocked`/`error`/`interrupted` |
|
|
141
|
+
|
|
142
|
+
沒選 session、該 session 還沒跑完任何一輪、或只是**切到一個早就結束的 session** 時,
|
|
143
|
+
不會動原本的鯨魚圖示 —— 綠/紅是「剛剛發生的事」的通知,不會把歷史重播一次。
|
|
144
|
+
綠燈停留由 `SETTLE_MS`(10 秒)控制、紅燈由 `SETTLE_MS_RED`(20 秒)控制,
|
|
20
145
|
任何新的一輪結束都會讓燈重新亮起。
|
|
21
146
|
|
|
22
|
-
|
|
147
|
+
### 安裝
|
|
23
148
|
|
|
24
|
-
外掛以 DSH bundle
|
|
149
|
+
外掛以 DSH bundle 形式發佈(`dsh.bundle.patch`),用 harness 的 `plugin_manager` 安裝:
|
|
25
150
|
|
|
26
151
|
```js
|
|
27
152
|
plugin_manager({ action: "install_bundle", target: "dsh-tab-status-light" })
|
|
28
153
|
```
|
|
29
154
|
|
|
30
|
-
|
|
155
|
+
或用 CLI:
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
dsh plugin --profile web add dsh-tab-status-light
|
|
159
|
+
# 也可以直接從 GitHub 安裝(不走 npm)
|
|
160
|
+
dsh plugin --profile web add github:kyle2241345145351324321/dsh-tab-status-light
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
開發時直接指到資料夾(改檔後重新整理就生效):
|
|
31
164
|
|
|
32
165
|
```js
|
|
33
166
|
plugin_manager({ action: "install_bundle", target: "/path/to/dsh-tab-status-light" })
|
|
34
167
|
```
|
|
35
168
|
|
|
36
|
-
安裝後重新整理頁面(`Cmd+R
|
|
169
|
+
安裝後重新整理頁面(`Cmd+R`/`Ctrl+R`)。
|
|
37
170
|
|
|
38
|
-
> 需要 harness 的 Web profile
|
|
39
|
-
> `@deepseek-ai/dsh-api-session-controller`
|
|
171
|
+
> 需要 harness 的 Web profile,且具備 `@deepseek-ai/dsh-client-ui-session` 與
|
|
172
|
+
> `@deepseek-ai/dsh-api-session-controller` 這兩個 Client 套件(標準安裝即有)。
|
|
40
173
|
|
|
41
|
-
|
|
174
|
+
### 運作方式
|
|
42
175
|
|
|
43
176
|
- **純 Client 外掛、不佔用任何 slot**:讀 `ctx.sessions.list`(哪個 session 是主視窗)與
|
|
44
|
-
`ctx.uiSession.sessionStatus`(running
|
|
45
|
-
event source 取得最新的 `turn/end`
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
- 閃爍由一個小型 Web Worker
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
| `BADGE` | `{cx:37, cy:37, radius:11, ring:4}` | 圓點位置 / 半徑 / 外圈寬 |
|
|
62
|
-
| `BADGE_COLOR` | 灰 / 綠 / 黃 / 紅 | 四種狀態的顏色 |
|
|
63
|
-
| `BLINK_MS` | `600` | 灰燈閃爍間隔(每 600 ms 切換一次) |
|
|
64
|
-
| `SETTLE_MS` | `10000` | 綠燈亮多久後收回 |
|
|
65
|
-
| `SETTLE_MS_RED` | `20000` | 紅燈亮多久後收回 |
|
|
66
|
-
| `RED_TURN_END_KINDS` | `aborted` `blocked` `error` `interrupted` | 哪些結束原因算中斷 |
|
|
177
|
+
`ctx.uiSession.sessionStatus`(running/pendingInteraction),並訂閱該 session 的
|
|
178
|
+
event source 取得最新的 `turn/end` 原因。
|
|
179
|
+
- 圖示是**即時重繪**的:`fetch()` 原本的 `favicon.svg`/`favicon-dark.svg`,在 `</svg>`
|
|
180
|
+
前插入一顆 `<circle>`,把 `<link rel="icon">` 的 `href` 換成 data URL(Chrome 會跟著
|
|
181
|
+
重畫分頁圖示),unmount 時還原原始 `href`。
|
|
182
|
+
- 因此鯨魚圖案不會被複製一份到外掛裡,上游換 logo 也會自動跟上。
|
|
183
|
+
- 圓點幾何(50×50 viewBox 內):`cx=37, cy=37, r=11, stroke-width=4`;
|
|
184
|
+
外圈用分頁底色(深色 `#35363a`、淺色 `#ffffff`)把圓點跟鯨魚隔開。
|
|
185
|
+
- 閃爍由一個小型 Web Worker 計時,**分頁切到背景仍會閃**(Chrome 會節流隱藏分頁的
|
|
186
|
+
頁面計時器);不支援 Worker 時自動退回頁面計時器。
|
|
187
|
+
- 閃爍的兩幀都是預先算好的 data URL,所以每一次切換都在節拍上完成 —— 早期版本會回去
|
|
188
|
+
讀原始圖檔,那一幀就會慢半拍,看起來忽長忽短。
|
|
189
|
+
|
|
190
|
+
### 可調參數
|
|
191
|
+
|
|
192
|
+
都在 [`client.js`](client.js) 檔頭(`BADGE`、`BADGE_COLOR`、`BLINK_MS`、`SETTLE_MS`、
|
|
193
|
+
`SETTLE_MS_RED`、`RED_TURN_END_KINDS`),說明同上表。
|
|
67
194
|
|
|
68
|
-
|
|
195
|
+
### 資源用量
|
|
69
196
|
|
|
70
|
-
|
|
197
|
+
閃爍中約 **2 ms JS/秒**(單核約 0.2%);閒置時 0(沒有計時器、沒有重新掃描)。
|
|
71
198
|
|
|
72
|
-
|
|
199
|
+
### 已知限制
|
|
73
200
|
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
`
|
|
79
|
-
-
|
|
80
|
-
|
|
81
|
-
會出現音訊指示、也比較耗電),不值得。
|
|
82
|
-
- 分頁解凍 / 切回前景時,外掛會立刻重新同步並重畫,所以回到分頁看到的永遠是正確狀態。
|
|
83
|
-
- 用純 SVG data URL 換 href,不支援 SVG favicon 的瀏覽器(很舊的)會看不到變化。
|
|
201
|
+
- 圖示只反映**主視窗**那個 session;其他背景 session 不會顯示。
|
|
202
|
+
- 切換到「早就跑完」的 session 不會亮綠燈(只亮真的看到跑完的那一輪)。
|
|
203
|
+
- 分頁在背景仍會閃;但被**凍結**(Chrome Memory Saver/省電模式)時任何網頁的 JS 都會停,
|
|
204
|
+
沒有 API 可以繞過。想讓它一直閃,把網址加進 `chrome://settings/performance` →
|
|
205
|
+
「永遠讓這些網站保持運作」。`navigator.wakeLock` **沒有用**:它只防螢幕休眠,分頁一隱藏就被釋放。
|
|
206
|
+
- 分頁解凍/切回前景時會立刻重新同步並重畫,所以看到的時候一定是正確狀態。
|
|
207
|
+
- 用 SVG data URL 換 `href`,不支援 SVG favicon 的舊瀏覽器看不到變化。
|
|
84
208
|
|
|
85
|
-
|
|
209
|
+
### 開發
|
|
86
210
|
|
|
87
211
|
```js
|
|
88
|
-
// 這個 repo 就是可直接安裝的 bundle
|
|
212
|
+
// 這個 repo 就是可直接安裝的 bundle,沒有 build step
|
|
89
213
|
plugin_manager({ action: "install_bundle", target: "/absolute/path/to/dsh-tab-status-light" })
|
|
90
214
|
```
|
|
91
215
|
|
|
92
216
|
改完 `client.js` 後在瀏覽器重新載入頁面即可生效(Client 模組是即時從磁碟供應的)。
|
|
93
217
|
|
|
94
|
-
|
|
218
|
+
### License
|
|
95
219
|
|
|
96
220
|
[MIT](LICENSE)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-tab-status-light",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Show the AI session state on the browser tab icon — gray blinking while working, green when done, yellow while it waits for your answer, red when interrupted. 把 AI 狀態畫在分頁圖示上:進行中灰燈閃爍、完成綠、等你回答黃、中斷紅。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kyle Fu",
|
|
7
7
|
"keywords": [
|