dsh-plugin-agent-tree 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,8 @@
1
+ # Agent Tree —— DSH Web 插件
2
+ #
3
+ # 插入一个 host 行(插件宿主半部负责 GET /local/dsh-agent-tree/processes);
4
+ # 客户端半部由本包 package.json 的 dsh.client 声明(./client.js)。
5
+ - insert:
6
+ - id: dsh-agent-tree
7
+ name: 'dsh-plugin-agent-tree'
8
+ config: {}
Binary file
package/docs/compat.md ADDED
@@ -0,0 +1,43 @@
1
+ # 兼容性
2
+
3
+ ## 已验证组合
4
+
5
+ | 项目 | 版本 | 结果 |
6
+ |---|---|---|
7
+ | DSH | `0.2.1-rc.2`(npm 全局安装,Web profile) | 通过:座位注册、树、模型、定时、外部进程接口、鉴权(未登录 401) |
8
+ | Node.js | 22.x / 24.x | 通过:单测与 verify 脚本 |
9
+ | macOS | 14/15(Apple Silicon) | 通过(`ps` + `lsof` 进程探测) |
10
+ | Linux | 未实机验证 | 预期可用(两者都是 POSIX 工具,参数一致) |
11
+ | Windows | 不支持进程段 | 树本身正常;进程探测依赖 `ps -axo` / `lsof`,不可用 |
12
+
13
+ ## 依赖契约
14
+
15
+ - 客户端座位:`shell.overlay`(z-index 20 的浮层,`pointer-events` 只在卡片和按钮上开启)。
16
+ - 客户端服务注入:`@deepseek-ai/dsh-client-ui-workspace`(`ctx.workspaces.list`、`ctx.uiWorkspace.openSession`)。
17
+ - 客户端用到的数据:
18
+ - `useSessions()` / `useSessionStatus()`(拿不到时回落 `ctx.remote.$on('api-session/status')`)
19
+ - `projectionValues.subagentTiming` / `projectionValues.modelSelection`
20
+ - `ctx.remote.schedule.catalog()` + `schedule/changed`
21
+ - `ctx.sessions.subagentAddress()`
22
+ - 宿主侧服务:`webServer`(`ctx.webServer.register`)+ `connection.requestRejection` 鉴权。
23
+
24
+ ## 预发布版本的 peer 坑
25
+
26
+ DSH 还在 `-rc` 线时,`peerDependencies` 的范围必须**显式带上当前预发布标签**,否则 node-semver 会静默排除它:
27
+
28
+ ```json
29
+ "peerDependencies": { "@deepseek-ai/dsh": ">=0.2.1-rc.2 <0.3.0" } // ✅
30
+ "peerDependencies": { "@deepseek-ai/dsh": ">=0.2.1-rc.1 <0.3.0" } // ❌ 0.2.1-rc.2 被排除
31
+ ```
32
+
33
+ `engines.dsh` 同理(本包两者都写了,安装时会校验)。
34
+
35
+ ## 已知不兼容 / 限制
36
+
37
+ - **0.2.0 及更早**:客户端 `shell.overlay` 座位与 `schedule` 服务都不保证存在,不保证可用。
38
+ - **其它前端**(CLI、Desktop):本插件只注册 Web 客户端座位,非 Web 端不出现卡片。
39
+ - **多实例**:只看得到当前 Web 实例里的会话;`claude/codex` 进程段看的是本机所有进程(这是有意为之)。
40
+
41
+ ## 变更记录
42
+
43
+ 见 [CHANGELOG.md](../CHANGELOG.md)。
@@ -0,0 +1,87 @@
1
+ # Install & configuration
2
+
3
+ [简体中文](install.md) · English
4
+
5
+ `dsh-plugin-agent-tree` is a DSH Web client plugin with a tiny host half. It is not a standalone app: it runs on a
6
+ DSH profile and shows up as a small floating card in a corner of the DSH Web UI.
7
+
8
+ ## 0. Prerequisites
9
+
10
+ | Dependency | Version | Notes |
11
+ |---|---|---|
12
+ | Node.js | `^22.19` or `≥ 24` | same as the DSH runtime |
13
+ | pnpm | 10+ | DSH manages profile dependencies with pnpm |
14
+ | DSH | `≥ 0.2.1-rc.2 < 0.3.0` | verified on `0.2.1-rc.2`, npm-distributed build |
15
+ | An LLM provider | — | the plugin needs no key itself, but you need sessions to observe |
16
+
17
+ ```sh
18
+ npm i -g @deepseek-ai/dsh@0.2.1-rc.2
19
+ dsh --version
20
+ ```
21
+
22
+ ## 1. Fresh profile (recommended)
23
+
24
+ ```sh
25
+ dsh --profile agent-tree --from-default-profile web
26
+ dsh plugin --profile agent-tree add dsh-plugin-agent-tree
27
+ dsh --profile agent-tree --port 13090
28
+ ```
29
+
30
+ Open the URL printed in the terminal (the one with the token) — the card is in the bottom-right corner.
31
+
32
+ ## 2. Existing profile
33
+
34
+ ```sh
35
+ dsh plugin --profile web add dsh-plugin-agent-tree
36
+ # then restart the command you normally use to start dsh web
37
+ ```
38
+
39
+ ## 3. Other install paths
40
+
41
+ ```sh
42
+ dsh plugin --profile web add "github:yuna78/dsh-agent-tree"
43
+ dsh plugin --profile web add "$PWD" # local development
44
+ ```
45
+
46
+ ## 4. One mandatory step: restart
47
+
48
+ The plugin ships a **host half** (it registers `GET /local/dsh-agent-tree/processes` for the process probe), so the
49
+ `dsh` process must be restarted once after installing; then hard-refresh the browser (`Cmd/Ctrl + Shift + R`).
50
+
51
+ Client-only changes (`client.js`) need just a page refresh — the bundle `rev` is computed per request.
52
+
53
+ ## 5. Verify
54
+
55
+ 1. Open DSH Web: `● Agent 树 ▸` or the expanded tree card is in the corner.
56
+ 2. Start a conversation and let it work: the headline becomes `● 1 个 agent 在跑`.
57
+ 3. Run `claude --help` (or `codex --help`) in a terminal and leave it hanging: a `● claude …` row appears at the
58
+ bottom of the card within a few seconds — that proves the host endpoint works.
59
+
60
+ ## 6. Upgrade
61
+
62
+ ```sh
63
+ dsh plugin --profile web add dsh-plugin-agent-tree@latest
64
+ # restart dsh, hard-refresh the browser
65
+ ```
66
+
67
+ ## 7. Uninstall
68
+
69
+ ```sh
70
+ dsh plugin --profile web remove dsh-plugin-agent-tree
71
+ # restart dsh
72
+ ```
73
+
74
+ A stale `dsh-agent-tree:pos` key stays in `localStorage`; remove it with
75
+ `localStorage.removeItem('dsh-agent-tree:pos')` if you care.
76
+
77
+ ## 8. Troubleshooting
78
+
79
+ | Symptom | Cause / fix |
80
+ |---|---|
81
+ | No card at all | dsh not restarted (host half) / page not hard-refreshed / package missing: `dsh plugin --profile web list` |
82
+ | Card off-screen | drag it back, or clear `dsh-agent-tree:pos` and refresh |
83
+ | Card says `空闲` (idle) | nothing is running and no active schedule — start a conversation |
84
+ | Subagent missing from the tree | that session is not running, or it belongs to another profile (the card only sees this Web instance) |
85
+ | No claude/codex block | host half not loaded (no restart) / not macOS or Linux / executable basename is not exactly `claude` or `codex` |
86
+ | "Add plugin" in DSH can't find it | the market index refreshes nightly; make sure the name is `dsh-plugin-agent-tree` |
87
+ | `[dsh-agent-tree]` warning in the startup log | host half warns and skips the endpoint when `webServer` is unavailable; the client keeps working |
@@ -0,0 +1,95 @@
1
+ # 安装与配置
2
+
3
+ 简体中文 · [English](install.en.md)
4
+
5
+ `dsh-plugin-agent-tree` 是 DSH Web 的客户端插件(外加一个很小的宿主半部)。它不是独立 App,
6
+ 必须挂在 DSH 的 profile 上运行;装完的形态是 DSH Web 界面角落里的那张小卡片。
7
+
8
+ ## 0. 前置条件
9
+
10
+ | 依赖 | 版本 | 说明 |
11
+ |---|---|---|
12
+ | Node.js | `^22.19` 或 `≥ 24` | 与 DSH 运行时一致 |
13
+ | pnpm | 10+ | DSH 用 pnpm 管理 profile 依赖 |
14
+ | DSH | `≥ 0.2.1-rc.2 < 0.3.0` | 已验证 `0.2.1-rc.2`;用 npm 全局安装的发行版 |
15
+ | 一个 LLM provider | — | 插件本身不需要 key,但要能跑会话才有东西可看 |
16
+
17
+ ```sh
18
+ npm i -g @deepseek-ai/dsh@0.2.1-rc.2 # 若还没装
19
+ dsh --version
20
+ ```
21
+
22
+ ## 1. 装到新 profile(推荐,干净)
23
+
24
+ ```sh
25
+ dsh --profile agent-tree --from-default-profile web
26
+ dsh plugin --profile agent-tree add dsh-plugin-agent-tree
27
+ ```
28
+
29
+ 启动:
30
+
31
+ ```sh
32
+ dsh --profile agent-tree --port 13090
33
+ ```
34
+
35
+ 浏览器打开终端里打印的地址(带 token 的那个),卡片就在右下角。
36
+
37
+ ## 2. 装到现有 profile
38
+
39
+ ```sh
40
+ dsh plugin --profile web add dsh-plugin-agent-tree
41
+ # 然后重启你平时启动 dsh web 的那条命令
42
+ ```
43
+
44
+ ## 3. 其它安装方式
45
+
46
+ ```sh
47
+ # GitHub 源码(market 探测之外的花式装法)
48
+ dsh plugin --profile web add "github:yuna78/dsh-agent-tree"
49
+
50
+ # 本地目录(开发用;改 client.js 刷新即可,改 index.js 要重启)
51
+ dsh plugin --profile web add "$PWD"
52
+ ```
53
+
54
+ ## 4. 必须做的一步:重启
55
+
56
+ 插件有**宿主半部**(注册 `GET /local/dsh-agent-tree/processes` 进程探测接口),
57
+ 所以 `dsh` 进程需要重启一次才会生效;重启后浏览器硬刷新(`Cmd/Ctrl + Shift + R`)。
58
+
59
+ 只改 `client.js` 时不需要重启宿主,刷新页面即可(bundle 的 `rev` 是运行时计算的)。
60
+
61
+ ## 5. 验证装好了吗
62
+
63
+ 1. 打开 DSH Web,右下角出现 `● Agent 树 ▸` 或展开的树状卡;
64
+ 2. 起一个会话让它干活,卡片标题变成 `● 1 个 agent 在跑`;
65
+ 3. 在终端跑 `claude --help` 或 `codex --help` 让它挂着,几秒后卡片底部出现 `● claude …` 行
66
+ (说明宿主半部的进程接口通了)。
67
+
68
+ ## 6. 升级
69
+
70
+ ```sh
71
+ dsh plugin --profile web add dsh-plugin-agent-tree@latest
72
+ # 重启 dsh + 硬刷新
73
+ ```
74
+
75
+ ## 7. 卸载
76
+
77
+ ```sh
78
+ dsh plugin --profile web remove dsh-plugin-agent-tree
79
+ # 重启 dsh
80
+ ```
81
+
82
+ 浏览器 `localStorage` 里会残留一个位置键 `dsh-agent-tree:pos`,卸载后无副作用;
83
+ 想清掉就在浏览器控制台 `localStorage.removeItem('dsh-agent-tree:pos')`。
84
+
85
+ ## 8. 排查
86
+
87
+ | 现象 | 原因 / 处理 |
88
+ |---|---|
89
+ | 根本没有卡片 | 没重启 dsh(宿主半部)/ 页面没硬刷新 / profile 里没这个包:`dsh plugin --profile web list` |
90
+ | 卡片在屏幕外面 | 拖回来即可;或清 `dsh-agent-tree:pos` 后刷新 |
91
+ | 卡片是空的(`空闲`) | 当前没有正在跑的会话、也没有 active 定时任务;起个会话或 `dsh` 里发一条消息 |
92
+ | 有 subagent 但树里没有 | 该会话不是 running 状态;或它属于别的 profile(本卡只显示当前 Web 实例的会话) |
93
+ | 底部没有 claude/codex 段 | 宿主半部没加载(没重启)/ 平台不是 macOS、Linux / 进程 basename 不是精确的 `claude`、`codex` |
94
+ | 市场「Add plugin」搜不到包 | 见 <https://github.com/yuna78/dsh-agent-tree#readme>;通常是市场夜间索引还没收录,或包名打错(是 `dsh-plugin-agent-tree`) |
95
+ | 启动日志有 `[dsh-agent-tree]` 警告 | 宿主半部在缺 `webServer` 时会 warn 并跳过接口,客户端照常工作 |
@@ -0,0 +1,197 @@
1
+ # Manual: how to read the card
2
+
3
+ [简体中文](manual.md) · English
4
+
5
+ ```
6
+ ┌──────────────────────────────────────────────────┐
7
+ │ ● 5 个 agent 在跑 · 2 个定时 ▾ │ ← headline + collapse
8
+ ├──────────────────────────────────────────────────┤
9
+ │ ▾ ● dsh 2 个 workspace │ ← top-level agent: this DSH instance
10
+ │ ├─ ▾ proj-alpha 2 │ ← workspace
11
+ │ │ ├─ ▾ ● Refactor billing flow ⏱8m v4.1-pro │ ← conversation (green)
12
+ │ │ │ ├─ ● Explore repo structure 1m5s │ ← subagent (blue)
13
+ │ │ │ │ └─ ● Run unit tests 9s │ ← grandchild (violet)
14
+ │ │ │ └─ ● Write migration plan 31s │
15
+ │ │ └─ Fix flaky login test ⏱2h v4.1-flash │ ← scheduled, currently idle
16
+ │ ├─ ▾ my-repo 1 │
17
+ │ │ └─ ● Triage CI failures v4.1-pro │
18
+ │ ▾ ● claude proj-alpha 12m 3% │ ← top-level agent: local claude (dsh peer)
19
+ │ │ └─ computer use ×2 41m │ ← its children, grouped by kind
20
+ │ ▾ ● codex ChatGPT 69h35m 2% │
21
+ │ ├─ MCP ×2 2h50m │
22
+ │ ├─ computer use ×2 41m │
23
+ │ └─ code mode 41m │
24
+ │ 会话 6 · 子代理 3 · 运行中 5(live) │ ← self-check line
25
+ └──────────────────────────────────────────────────┘
26
+ ```
27
+
28
+ ## 1. Headline
29
+
30
+ | Text | Meaning |
31
+ |---|---|
32
+ | `● 5 个 agent 在跑 · 2 个定时` | 5 sessions/subagents are running; 2 sessions have an active schedule |
33
+ | `空闲 · 2 个定时待命` | nothing running, only scheduled tasks pending |
34
+ | `● Agent 树 ▸` | collapsed (single line) |
35
+ | `▾ / ▸` on the right | manual expand / collapse; manual wins over auto-collapse |
36
+
37
+ Auto-collapse rule: collapse when `running === 0 && scheduled === 0`; expand automatically as soon as work appears
38
+ (unless you collapsed it manually).
39
+
40
+ ## 1.4 Sessions waiting for your call
41
+
42
+ When an agent asks a question (`ask_user_question`), waits for an approval, or waits for a plan review, the session
43
+ stops at "waiting for input" and no longer counts as running. The card puts those rows **first**, in amber, with a badge:
44
+
45
+ ```
46
+ ├─ ● Research team 1 待答 v4.1-pro
47
+ │ └─ ● Plan review 待审
48
+ ```
49
+
50
+ - `待答` — the agent asked a question and waits for your answer.
51
+ - `待批` — waiting for you to approve one operation.
52
+ - `待审` — waiting for your plan review.
53
+
54
+ They sort above running rows, so they can never be collapsed away for "not running"; the headline becomes
55
+ `N waiting for you · M running · K scheduled`.
56
+
57
+ ## 1.5 Levels
58
+
59
+ Four levels (plus grandchild, i.e. five in the deepest row):
60
+
61
+ ```
62
+ dsh (this instance)
63
+ └─ workspace
64
+ └─ conversation
65
+ └─ subagent
66
+ └─ grandchild …
67
+ ```
68
+
69
+ The `dsh` root row collapses every workspace at once; its right side shows the workspace count.
70
+
71
+ ## 2. Row elements
72
+
73
+ | Element | Meaning |
74
+ |---|---|
75
+ | `├─ └─ │` | git-log-style connectors; each depth adds three columns of indentation |
76
+ | `▾ / ▸` | this row has children — expand / collapsed |
77
+ | `●` | status dot, colored by depth (below) |
78
+ | Title | session title (`displayTitle`), elided when long; running rows are bolder |
79
+ | `⏰` + `8m` | countdown to the next scheduled run: `now` / `<1m` / `8m` / `2h` / `3d` |
80
+ | `v4.1-flash` | model chip (right aligned) from `modelSelection`, with `deepseek-` / `anthropic-` prefixes stripped |
81
+ | `1m5s` | elapsed duration (subagent rows only): `45s` / `12m` / `1h5m` |
82
+
83
+ ## 3. Colors
84
+
85
+ | Color | Meaning |
86
+ |---|---|
87
+ | green | top-level conversation running in its own session |
88
+ | blue | level-2 subagent |
89
+ | violet | level 3 and deeper |
90
+ | grey / dim | finished, kept only to preserve the hierarchy |
91
+ | orange / green (bottom block) | claude process / codex process |
92
+
93
+ ## 4. Model inheritance
94
+
95
+ Subagent projections often carry no `modelSelection`; the card then uses the nearest ancestor's model and the tooltip
96
+ says it was inherited. So every row can answer "which model is this".
97
+
98
+ ## 5. Scheduled rows
99
+
100
+ DSH Automation tasks (`schedule.catalog()`) drive intermittent sessions: idle most of the time, they fire on a timer.
101
+ Those sessions are listed even while idle, with `⏱` showing the next fire time — clicking jumps to them as usual.
102
+
103
+ ## 6. Local external agents (peers of dsh)
104
+
105
+ Read-only probe from the host half, listing running `claude` / `codex` CLIs on this machine. They are
106
+ **top-level nodes just like `dsh`** (same row spec: same font size, same dot, same collapse); only the dot
107
+ color differs (claude orange / codex green):
108
+
109
+ ```
110
+ ├─ ● claude proj-alpha 12m 3%
111
+ └─ ● codex my-repo 3m
112
+ ```
113
+
114
+ - `label` resolution: real cwd basename → `--cwd/--cd/-C` from the command line → `ChatGPT` for the desktop backend → empty.
115
+ - Max 8 rows, 3s cache on the host, requires a logged-in session (401 otherwise).
116
+ - Purpose: "while I work inside DSH, is some other agent also running on this machine?"
117
+
118
+ ### 6.1 Children of an external agent
119
+
120
+ `claude` / `codex` children hang under them by `ppid`, grouped by kind:
121
+
122
+ ```
123
+ ├─ ▾ ● codex ChatGPT 69h35m 2%
124
+ │ ├─ MCP ×2 2h50m
125
+ │ ├─ computer use ×2 41m
126
+ │ └─ code mode 41m
127
+ ```
128
+
129
+ - `×N` = how many children of that kind; the right column shows the longest elapsed among them.
130
+ - Clicking the process root collapses its subtree.
131
+ - A real agent CLI found among the descendants is listed as its own root instead of being nested twice.
132
+
133
+ ### 6.2 codex sub-conversations (subagent threads)
134
+
135
+ Every codex session (CLI or ChatGPT desktop) writes a rollout: `~/.codex/sessions/<y>/<m>/<d>/rollout-*.jsonl`.
136
+ Its first line is `session_meta`, which already carries `thread_source: subagent`, `parent_thread_id`,
137
+ `agent_nickname` and `agent_path`. The plugin reads only those headers and rebuilds the tree by `parent_thread_id`,
138
+ hanging it under the codex row:
139
+
140
+ ```
141
+ ▾ ● codex ChatGPT 69h35m 2%
142
+ ├─ ● Hubble advance_review_logic running
143
+ ├─ ● Carson review_nextarchive_code 16m前
144
+ ├─ ● Wegener review_nextarchive_triage 1h42m前
145
+ ├─ MCP ×2 2h50m
146
+ └─ computer use ×2 41m
147
+ ```
148
+
149
+ - Active within the last two minutes → `running` (green, bold); otherwise "last active N ago".
150
+ - Which main session: matched by the process cwd first (worktree runs match on a cwd prefix); for ChatGPT desktop
151
+ processes the cwd is usually `/`, so a session whose `originator` contains `Desktop` wins.
152
+ - At most 8 sub-conversations, 3 levels deep. Local read-only, no network.
153
+
154
+ ### 6.3 The codex row's name
155
+
156
+ The row is named after **the first real request of that codex session** (skipping codex's own
157
+ `environment_context` / `AGENTS.md instructions` injections), followed by a grey directory chip:
158
+
159
+ ```
160
+ ▾ ● codex 推进一下能推进的任务,看看流水线… devline 69h35m 2%
161
+ ```
162
+
163
+ - Falls back to the directory name / `ChatGPT` only when the rollout has no user message yet.
164
+ - With several codex processes in one cwd, each claims a distinct session by recency, so rows never share a name.
165
+
166
+ ## 7. Interaction
167
+
168
+ | Action | Effect |
169
+ |---|---|
170
+ | click a row | jump to that session (subagents open their own conversation) |
171
+ | click `▾/▸` | collapse / expand that node's children |
172
+ | drag the header | move the card; position saved in `localStorage: dsh-agent-tree:pos` |
173
+ | click headline `▾/▸` | collapse / expand the whole card |
174
+
175
+ ## 8. Refresh cadence
176
+
177
+ | Data | Cadence |
178
+ |---|---|
179
+ | running state | official `api-session/status` events (`live`); 1s snapshot polling (`poll`) as fallback |
180
+ | scheduled tasks | `schedule/changed` events + a 15s poll |
181
+ | external processes | every 5s (host caches for 3s) |
182
+ | countdown / duration | recomputed every second |
183
+
184
+ ## 9. Self-check line
185
+
186
+ `会话 N · 子代理 M · 运行中 K(live|poll)`
187
+
188
+ - `N` sessions in the snapshot, `M` of them `origin: subagent`, `K` considered running;
189
+ - `live` = official realtime events, `poll` = fallback. If it stays `poll`, this DSH build lacks the global status
190
+ store — worth an issue.
191
+
192
+ ## 10. Known limits
193
+
194
+ - Only the current Web instance's sessions are visible (not other profiles or machines).
195
+ - Running state follows DSH status events; a finished subagent may linger for a second or two.
196
+ - Width is fixed at 288px; long titles elide (change `WIDTH` in `client.js`).
197
+ - UI strings are Chinese for now.
package/docs/manual.md ADDED
@@ -0,0 +1,205 @@
1
+ # 使用手册:这张卡怎么读
2
+
3
+ 简体中文 · [English](manual.en.md)
4
+
5
+ ```
6
+ ┌──────────────────────────────────────────────────┐
7
+ │ ● 5 个 agent 在跑 · 2 个定时 ▾ │ ← 头部:统计 + 折叠
8
+ ├──────────────────────────────────────────────────┤
9
+ │ ▾ ● dsh 2 个 workspace │ ← 顶层 agent:这个 DSH 实例
10
+ │ ├─ ▾ proj-alpha 2 │ ← workspace
11
+ │ │ ├─ ▾ ● ⏰ Refactor billing flow 8m v4.1-pro │ ← 对话(绿点,挂了定时)
12
+ │ │ │ ├─ ● Explore repo structure 1m5s │ ← subagent(蓝点)
13
+ │ │ │ │ └─ ● Run unit tests 9s │ ← 孙代理(紫点)
14
+ │ │ │ └─ ● Write migration plan 31s │
15
+ │ │ └─ ⏰ Fix flaky login test 2h v4.1-flash │ ← 有定时、当前空闲
16
+ │ ├─ ▾ my-repo 1 │
17
+ │ │ └─ ● Triage CI failures v4.1-pro │
18
+ │ ▾ ● claude proj-alpha 12m 3% │ ← 顶层 agent:本机 claude(和 dsh 同级)
19
+ │ │ └─ computer use ×2 41m │ ← 它的子进程(按种类归组)
20
+ │ ▾ ● codex ChatGPT 69h35m 2% │
21
+ │ ├─ MCP ×2 2h50m │
22
+ │ ├─ computer use ×2 41m │
23
+ │ └─ code mode 41m │
24
+ │ 会话 6 · 子代理 3 · 运行中 5(live) │ ← 自检行
25
+ └──────────────────────────────────────────────────┘
26
+ ```
27
+
28
+ ## 1. 头部
29
+
30
+ | 文案 | 含义 |
31
+ |---|---|
32
+ | `● 5 个 agent 在跑 · 2 个定时` | 5 个会话/子代理处于 running;另有 2 个会话有 active 定时任务 |
33
+ | `空闲 · 2 个定时待命` | 没有正在跑的,只有定时任务等着 |
34
+ | `● Agent 树 ▸` | 收起状态(只有一行) |
35
+ | 右侧 `▾ / ▸` | 手动展开 / 收起;手动操作优先于自动折叠 |
36
+
37
+ 自动折叠规则:`running === 0 && scheduled === 0` 时收起;一旦有活儿自动展开(除非你手动收起了)。
38
+
39
+ ## 1.4 需要你拍板的会话
40
+
41
+ agent 提问(`ask_user_question`)、等你批准一次操作、等你审阅计划时,会话会停在「等输入」状态,不算在跑。
42
+ 卡片把这类会话**放在最上面**,并换成琥珀色 + 小徽标:
43
+
44
+ ```
45
+ ├─ ● 智力研发团队 1 待答 v4.1-pro
46
+ │ └─ ● 计划审阅 待审
47
+ ```
48
+
49
+ - `待答`:agent 提了问题,等你选/答。
50
+ - `待批`:等你批准一次操作(命令、写文件、联网等)。
51
+ - `待审`:等你审阅计划(plan review)。
52
+
53
+ 这类行排在「在跑」之前,所以永远不会因为「没在跑」被折叠掉;标题栏也会变成
54
+ 「N 个等你处理 · M 个在跑 · K 个定时」。
55
+
56
+ ## 1.5 层级
57
+
58
+ **顶层是「本机上的 agent」列表**:`dsh`(这个实例)和每个外部 `claude` / `codex` 是同级节点,
59
+ 各自往下展开:
60
+
61
+ ```
62
+ dsh(这个实例) claude / codex(本机其它 agent)
63
+ └─ workspace └─ 子进程(按种类归组)
64
+ └─ 对话
65
+ └─ subagent
66
+ └─ 孙代理 …
67
+ ```
68
+
69
+ 所以从 `dsh` 往下是 4 层(workspace → 对话 → subagent → 孙代理),每个顶层 agent 都可以单独折叠。
70
+
71
+ ## 2. 树行元素
72
+
73
+ 从左到右:
74
+
75
+ | 元素 | 含义 |
76
+ |---|---|
77
+ | `├─ └─ │` | git log 风格连接线,表示层级;每深一层多三格缩进 |
78
+ | `▾ / ▸` | 这一行有子代理,可展开 / 已收起 |
79
+ | `●` | 状态点:颜色见下表 |
80
+ | 标题 | 会话标题(`displayTitle`),过长省略;运行的会话字更粗更深 |
81
+ | `⏰` + `8m` | 标题前的小闹钟表示这行挂了定时 / 循环任务;右侧是倒计时:`now` / `<1m` / `8m` / `2h` / `3d`(到期显示 `now`,闹钟不消失) |
82
+ | `v4.1-flash` | 模型标签(右侧对齐):来自 `modelSelection`,`deepseek-` / `anthropic-` 前缀会去掉 |
83
+ | `1m5s` | 运行或已运行时长(subagent 行才有):`45s` / `12m` / `1h5m` |
84
+
85
+ ## 3. 颜色
86
+
87
+ | 颜色 | 含义 |
88
+ |---|---|
89
+ | 绿点 | 顶层对话在自己的会话里跑 |
90
+ | 蓝点 | 第 2 层 subagent |
91
+ | 紫点 | 第 3 层及更深(孙代理……) |
92
+ | 灰点 / 浅字 | 已结束,但为了让层级完整仍保留的行 |
93
+ | 橙点 / 绿点(底部段) | claude 进程 / codex 进程 |
94
+
95
+ ## 4. 模型标签的继承
96
+
97
+ subagent 的 `modelSelection` 常常为空,这时用最近一个祖先会话的模型,悬停会显示「继承自上级」。
98
+ 所以「这一行用的是哪个模型」永远有答案,不会留白。
99
+
100
+ ## 5. 定时任务行
101
+
102
+ DSH 的 Automation tasks(`schedule.catalog()`)驱动的是「间歇式工作」的会话:它们大部分时间空闲,
103
+ 到点自己跑一次。卡片会把这些会话**即使不在跑也列出来**:
104
+
105
+ - 标题前固定一个 `⏰`(小闹钟),一眼认出「这行是循环任务」;
106
+ - 右侧是距下次触发的倒计时;
107
+ - 刚跑完、倒计时到期时显示 `now`,但 `⏰` 保持——正在跑的循环任务不会看起来像普通会话。
108
+
109
+ 点它同样能跳过去看上一次跑出来的东西。
110
+
111
+ ## 6. 本机外部 agent(和 dsh 同级)
112
+
113
+ 宿主半部的只读探测,列出本机正在跑的 `claude` / `codex` CLI。它们**和 `dsh` 一样是顶层节点**
114
+ (同一套行规格:同样字号、同样圆点、同样折叠),区别只有圆点颜色(claude 橙 / codex 绿):
115
+
116
+ ```
117
+ ▾ ● claude proj-alpha 12m 3%
118
+ ▾ ● codex ChatGPT 69h35m 2%
119
+ ```
120
+
121
+ - 行名(`label`)的取值顺序:该 codex 会话的第一条真实用户消息(跳过 `environment_context` / `AGENTS.md` 注入)
122
+ → 进程真实 cwd 的目录名 → 命令行里的 `--cwd/--cd/-C` → `ChatGPT`(桌面端 backend)→ 空。
123
+ - 只显示前 8 条;结果缓存 3 秒;接口需要登录态(未登录 401)。
124
+ - 目的是「我在 DSH 里干活时,本机还有没有别的 agent 在偷偷跑」;点这一行可折叠子树。
125
+
126
+ ### 6.1 外部 agent 的子进程
127
+
128
+ `claude` / `codex` 的子进程按 `ppid` 挂成子树;同一种子进程会归组成一行:
129
+
130
+ ```
131
+ ├─ ▾ ● codex ChatGPT 69h35m 2%
132
+ │ ├─ MCP ×2 2h50m
133
+ │ ├─ computer use ×2 41m
134
+ │ └─ code mode 41m
135
+ ```
136
+
137
+ - `×N` 表示有几个同类子进程,右侧显示其中跑得最久的时长;
138
+ - 点进程根行可以折叠它的子树;
139
+ - 子孙里如果又是一个真正的 agent CLI,会单独作为根出现,不重复挂。
140
+
141
+ ### 6.2 codex 的子对话(subagent threads)
142
+
143
+ codex(CLI 和 ChatGPT 桌面端)每开一个会话都会写一条 rollout:`~/.codex/sessions/<年>/<月>/<日>/rollout-*.jsonl`。
144
+ 第一行是 `session_meta`,里面就有 `thread_source: subagent`、`parent_thread_id`、`agent_nickname`、`agent_path`。
145
+ 插件只读这些头部、按 `parent_thread_id` 串成树,挂在 codex 那一行下面:
146
+
147
+ ```
148
+ ▾ ● codex ChatGPT 69h35m 2%
149
+ ├─ ● Hubble advance_review_logic running
150
+ ├─ ● Carson review_nextarchive_code 16m前
151
+ ├─ ● Wegener review_nextarchive_triage 1h42m前
152
+ ├─ MCP ×2 2h50m
153
+ └─ computer use ×2 41m
154
+ ```
155
+
156
+ - 2 分钟内活动过标 `running`(绿点加粗),否则显示「最后活动多久前」。
157
+ - 找的是哪条主会话:先按进程 cwd 匹配,worktree 里跑的就取 cwd 互为前缀的那条;
158
+ ChatGPT 桌面端进程 cwd 常常是 `/`,这时优先挑 `originator` 带 `Desktop` 的会话。
159
+ - 最多 8 个子对话、最深 3 层。只读本机、不联网、不外发。
160
+
161
+ ### 6.3 codex 那行的名字
162
+
163
+ 行名不是目录名,而是**这条 codex 会话的第一句真实需求**(跳过 codex 自己塞的 `environment_context`、
164
+ `AGENTS.md instructions` 这类上下文),后面跟一个灰色的目录小标签:
165
+
166
+ ```
167
+ ▾ ● codex 推进一下能推进的任务,看看流水线… devline 69h35m 2%
168
+ ```
169
+
170
+ - 取不到(rollout 刚建、还没写用户消息)才回落到目录名 / `ChatGPT`。
171
+ - 同一 cwd 下有多个 codex 进程时,按时间各认领一条会话,所以不会出现两行同名。
172
+
173
+ ## 7. 交互
174
+
175
+ | 操作 | 效果 |
176
+ |---|---|
177
+ | 点一行 | 跳到该会话(subagent 会落到它自己的对话) |
178
+ | 点 `▾/▸` | 折叠 / 展开该节点的子代理 |
179
+ | 拖标题栏 | 移动卡片,位置存 `localStorage: dsh-agent-tree:pos` |
180
+ | 点头部 `▾/▸` | 收起 / 展开整张卡 |
181
+
182
+ ## 8. 刷新节奏
183
+
184
+ | 数据 | 频率 |
185
+ |---|---|
186
+ | running 状态 | 官方实时事件 `api-session/status`(`live`);拿不到时 1s 轮询快照(`poll`) |
187
+ | 定时任务 | 事件 `schedule/changed` + 15s 轮询兜底 |
188
+ | 外部进程 | 5s 一次(宿主侧再缓存 3s) |
189
+ | 倒计时 / 时长 | 每秒重算显示 |
190
+
191
+ ## 9. 自检行
192
+
193
+ `会话 N · 子代理 M · 运行中 K(live|poll)`
194
+
195
+ - `N` 是快照里能看到的会话数,`M` 是其中 `origin: subagent` 的数量;
196
+ - `K` 是判定为 running 的数量;
197
+ - `live` 表示用的是官方实时事件,`poll` 表示回落到了轮询 —— 如果长期是 `poll`,说明这个 DSH 版本的全局
198
+ props 里没有状态 store,可以据此提 issue。
199
+
200
+ ## 10. 已知限制
201
+
202
+ - 只显示**当前 Web 实例**的会话(别的 profile / 别的机器看不到)。
203
+ - 运行状态以 DSH 的状态事件为准;如果某个子代理在 DSH 里已经结束、但事件还没到,可能短暂多显示一两秒。
204
+ - 卡宽固定 288px,超长标题会省略;想加宽改 `client.js` 顶部的 `WIDTH`。
205
+ - UI 文案暂时是中文。