dsh-task-guard-badge 0.0.0-stage → 0.7.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Leo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,120 @@
1
- # Temporary Holding Version
1
+ # dsh-task-guard-badge
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A small badge under the message composer that shows what the **task-guard** plugin is currently doing to your tool table — and lets you open the details.
4
+
5
+ [![npm](https://img.shields.io/badge/version-0.2.2-blue)]()
6
+
7
+ > Companion to [`dsh-task-guard`](https://github.com/qwq1223211/dsh-task-guard). This package is UI only: it reads the state file that task-guard writes.
8
+
9
+ ## What it looks like
10
+
11
+ Collapsed (always visible, never in the way). With no task running it is a dashed,
12
+ clickable pill instead:
13
+
14
+ ```
15
+ ● unity-ui −219 每轮省 48.6K ← task narrowed
16
+ ○ 工具表:全开(176) ▾ ← nothing narrowed; still clickable
17
+ ```
18
+
19
+ Click it and a card opens above the composer:
20
+
21
+ ```
22
+ ┌──────────────────────────────────────────┐
23
+ │ 任务收窄 [手动] [收窄中] ✕ │
24
+ │ [概览] [工具] [历史] │
25
+ ├──────────────────────────────────────────┤
26
+ │ ◐ 92% 摘掉 219 保留 20 │
27
+ │ 每轮省 48.6K token │
28
+ │ 工具表大小 ▁▂▃▅█ 274 │
29
+ │ 最近请求的阶段 unity-ui │
30
+ │ 保留范围 core plugin │
31
+ └──────────────────────────────────────────┘
32
+ ```
33
+
34
+ The **工具** tab has a search box and a tree grouped by the plugin that owns each tool;
35
+ the **历史** tab lists the last 20 router events. The header chip toggles **auto ⇄ manual**.
36
+
37
+ ## Install
38
+
39
+ ```bash
40
+ dsh plugin --profile desktop add github:qwq1223211/dsh-task-guard-badge
41
+ ```
42
+
43
+ Then **reload** it (Settings → Plugins → toggle off/on) and **refresh the page** — the client half is loaded at runtime, so a page refresh is what makes the new UI appear.
44
+
45
+ It needs `dsh-task-guard` installed; without it the badge simply shows "任务收窄 · 未开启".
46
+
47
+ ## What it shows
48
+
49
+ Three tabs, plus a mode switch in the header:
50
+
51
+ | Tab | Content |
52
+ |---|---|
53
+ | **Overview** | ring progress (narrowing ratio), removed/kept counts, mini bar chart of the last 8 requests, last request's stage, scope groups, goal |
54
+ | **Tools** | search box + a tree grouped by the plugin that provides each tool (click a plugin to expand its tools) |
55
+ | **History** | the last 20 events from the router ledger: stage switches, gate blocks, denials, tool-table changes |
56
+
57
+ The header chip toggles **auto ⇄ manual**:
58
+
59
+ | Mode | Who decides the tool table |
60
+ |---|---|
61
+ | `manual` (default) | you: click groups in the panel, or the model calls `route_stage` / `task_start` |
62
+ | `auto` | the model: the router's tail hint becomes "YOU decide the tool set", so it calls `route_use` / `task_start` itself |
63
+
64
+ Toggling writes `~/.dsh/task-guard/mode.json`; the router reads it (5 s cache). A missing or
65
+ broken file always falls back to `manual`, so control is never handed over by accident.
66
+
67
+ When **no task is running**, the pill is still clickable: it opens the manual panel with the
68
+ current table size and a group picker ("Narrow to selection" / "End task"), so you can adjust
69
+ the tool table without asking the model to do it.
70
+
71
+ ## What it reads
72
+
73
+ | Field | Source |
74
+ |---|---|
75
+ | Removed / kept tools, scope, goal | `~/.dsh/task-guard/current.json` |
76
+ | Which plugin owns each tool | scanned from the profile's bundled packages (cached 5 min) |
77
+ | Tool table size | probe record (`tools`) first, then `tool-registry.json` |
78
+ | Last request's stage | probe record, **only if fresher than 10 minutes** |
79
+ | History | `~/.dsh/minimal-router/activity.jsonl` (tail) |
80
+ | Auto/manual mode | `~/.dsh/task-guard/mode.json` |
81
+ | Last manual action result | `~/.dsh/task-guard/request-result.json` |
82
+
83
+ Group names are translated (`core` → 基础工具 / Core, `unity` → Unity, `ego` → 浏览器 / Browser, …);
84
+ unknown groups fall back to their raw tag.
85
+
86
+ ## Manual control
87
+
88
+ Buttons in the panel POST to `/task-guard/action`, which writes
89
+ `~/.dsh/task-guard/request.json`. `dsh-task-guard` consumes it on its next
90
+ `tools/pre-execute` (the only hook that has `agent.ctx.tools`), applies
91
+ `restrict({deny})` or disposes the restriction, and writes the result back.
92
+ Requests older than 60 s are ignored, and each id is consumed once.
93
+
94
+ ## Design notes
95
+
96
+ - **Theme-safe**: colours derive from `currentColor` via `color-mix`, plus system colours
97
+ (`Canvas` / `CanvasText`), so light and dark themes both work.
98
+ - **Responsive**: the panel is `min(380px, 100vw - 32px)`; it never overflows a narrow window.
99
+ - **Push, not poll**: the panel uses SSE (`/task-guard/stream`, 2 s) with a 6 s watchdog that
100
+ falls back to plain polling if frames stop arriving.
101
+ - **Fixed positioning**: the panel measures the pill and places itself with `position: fixed`,
102
+ so the composer dock's `overflow` cannot clip it.
103
+ - **Accessible**: `role="button"`, `aria-expanded`, Enter/Space to toggle, Escape or
104
+ click-outside to close, focus ring on keyboard focus.
105
+
106
+ ## Tests
107
+
108
+ `node test/state.test.mjs` — 13 tests over `lib/state.js` (tail reading, bad-line tolerance,
109
+ event mapping, 10-minute stage freshness, registry fallback, mode parsing, unified count).
110
+
111
+ ## Known rough edges
112
+
113
+ - With no task running the pill is muted; a first-time user may not realise it is clickable.
114
+ - The "last request stage" is an approximation: the probe file is global, so another session's
115
+ request could be the most recent one (the 10-minute freshness check bounds the damage).
116
+ - Group picker lists every tag from the registry, including trivial ones (1 tool).
117
+
118
+ ## License
119
+
120
+ MIT