dsh-subagent-workspace-ui 1.5.0 → 1.7.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 CHANGED
@@ -11,27 +11,32 @@ A Web client plugin that adds a **子代理管理** button to the conversation-h
11
11
  - Group by session, workspace, category, type, or no grouping. Session headers show the workspace and parent session name.
12
12
  - Browser-local classification tabs support custom regular expressions. Built-ins include all, other, review, test, implementation, and planning.
13
13
  - One-shot children carry a compact `⚡ 一次性` badge; continuable children remain visually uncluttered.
14
+ - Show each child's current **type and model provider/id** (`provider/model`, plus the reasoning effort when the host publishes one) from the host's public projections only — no new RPC, no model-switch UI. See [Type and model](#type-and-model-read-only-projections).
15
+ - Show each child's usage inline, computed with the host's own definitions: `↑ 131.3k (未缓存 39.1k) / ↓ 12.7k · 命中 70% · 104 tps · 3 轮 · 9 步` (English UI: `miss` / `Hit` / `rnds` / `stps`). The `↑` figure is the **billed input** (`uncachedInputTokens + cacheReadTokens + cacheWriteTokens`) and that billed input alone is the cache-hit denominator — exactly what DSH's own composer footer does, so the plugin and the host agree instead of disagreeing by six points. `tps` is `decodeTokens / (decodeMs / 1000)` from the same public `sessionStats` projection. Hovering the row or the floating panel reveals the complete breakdown — total, every bucket, the share, the speed, and the session's LLM / tool / TTFT timings — in the native `title` tooltip.
14
16
  - Archive state is local and never deletes a DSH session. Single-row archive actions and a batch mode support shift-selection, select-all, time-based selection (up to 1,000 rows), batch archive, restore, and archive-all.
15
17
  - Load catalogs in pages of 40 with an independent wheel-scroll container; batch time selection expands loading up to 1,000 children.
16
18
  - Batch mode changes cards into selection targets and hides individual archive/restore actions. The highlighted 完成 button exits batch mode.
17
19
  - Open a loaded child at its exact `{ parentSessionId, childSessionId, mode }` address. In normal mode the whole card opens the child; archive controls do not.
20
+ - Every row also carries a dedicated **open in the sidebar** button (`◫`) that opens the child as a right-sidebar tab, so the main conversation stays where it is. The button stops propagation (it never triggers the row's default navigation and never toggles batch selection), and it is rendered only when the runtime exposes the sidebar capability: without `ctx.sidebarRight` plus a type that claims the address, the button is hidden entirely; for a single row whose subagent address cannot be resolved it stays visible but disabled with a readable reason. The same button is on the active-subagent floating panel.
18
21
  - Show session IDs beside names, compact metadata, token totals, and creation time in the relative-time tooltip.
19
22
  - Active children are grouped at the top in a collapsible section. When the runtime exposes conversation snapshots, the panel shows the latest two lines of live output, recent tool calls, context injection, command status, and a gray final snapshot after completion.
20
23
 
21
24
  ## Screenshot guide
22
25
 
23
- The screenshots demonstrate the compact manager and active-agent floating panel:
26
+ Both screenshots were taken on the `1.7.0-dev` line (commit `79d9d0f`) against a real dsh **0.1.6-alpha.2** instance in its dark theme. The session had four background subagents at once — three still running and one already finished — so every row could be shown with its real type, model and usage figures. The pair below is the English UI; the Chinese UI pair is in [`README.zh.md`](README.zh.md).
24
27
 
25
- ![Subagent manager panel](docs/images/screenshot-1.png)
28
+ ![Subagent manager panel (English UI)](docs/images/screenshot-1.en.png)
26
29
 
27
- ![Active subagent floating panel](docs/images/screenshot-2.png)
30
+ ![Active subagent floating panel (English UI)](docs/images/screenshot-2.en.png)
28
31
 
29
- 1. **Header** — title, current-session/workspace counts, and close action.
32
+ 1. **Header** — panel title, `Current session n · Current workspace n · Active n`, the show-active-float toggle, and the close action.
30
33
  2. **Search and scope row** — ordinary name/title/workspace search, with `id: xxx` reserved for Session ID search; workspace, session, sorting, and grouping selectors stay on one compact row.
31
- 3. **Classification row** — built-in and custom categories, with custom-category deletion inside the same tab frame.
32
- 4. **Filter row** — hide one-shot, hide stale children, show archived, and reset filters.
33
- 5. **Results** — collapsible active group, workspace/session group headers, Session ID beside each name, relative activity time, and archive status.
34
- 6. **Live activity** — when available, the last two output lines or the latest tool/context status appear at the bottom of the card; the final snapshot remains gray after completion.
34
+ 3. **Classification row** — built-in and custom categories with live counts, custom-category creation and deletion inside the same tab frame.
35
+ 4. **Filter row** — hide one-shot, hide long-inactive, subagent background colour (light/dark), and reset filters.
36
+ 5. **Summary row** — `Showing n/m`, show details, show hidden, and the batch-mode entry.
37
+ 6. **Active subagents group** — pinned to the top and collapsible, with `Pause all`; each row carries the activity dot, the name, the Session ID, the relative activity time, and the `◫` open-in-the-sidebar, `⏸ Pause`, `⊘ Hide` and `🗑 Delete` actions.
38
+ 7. **Detail block** — `Type: … · Model: …` straight from the host's read-only projections, then the official usage line `↑ billed (miss …) / ↓ output · Hit n% · n tps · n rnds · n stps`; a running child also shows its latest live-output lines, while a finished child keeps its final snapshot.
39
+ 8. **Floating panel** — the running children of the current session in a compact always-on-top card, each with its live output, usage line and stop button; it appears whenever at least one child is running and the manager panel is closed.
35
40
 
36
41
  ## Install in the Web profile
37
42
 
@@ -41,19 +46,51 @@ From this directory:
41
46
  dsh plugin --profile web add file:.
42
47
  ```
43
48
 
44
- The bundle includes [`cordis.patch.yml`](cordis.patch.yml), which inserts the manager and disables DSH’s stock `ui-subagent` lineage dropdown while the package is installed. Removing the package removes this bundle layer and restores the underlying `ui-subagent` setting. Restart the existing `dsh web` process, then refresh `http://127.0.0.1:3080` after the plugin is available.
49
+ The bundle includes [`cordis.patch.yml`](cordis.patch.yml), which inserts the manager and shadows exactly one stock slot: `conversation.session.header.lineage` is claimed by a `priority: -1` title-only shadow so DSH's stock `ui-subagent` lineage dropdown stays invisible while this package is installed. The stock `ui-subagent` plugin itself is **left enabled** — this package no longer disables it wholesale, because the sidebar tab it provides is the navigation target of the new "open in the sidebar" button. The shadow renders the session title instead of an empty entry, so the subagent session header keeps its title. Removing the package removes this bundle layer, and the host's `ui-subagent` setting is untouched, so your own configuration is restored as it was. Restart the existing `dsh web` process, then refresh `http://127.0.0.1:3080` after the plugin is available.
45
50
 
46
- If you previously disabled `ui-subagent` manually in `$DSH_HOME/profiles/web/cordis.patch.yml`, remove that manual stanza when testing automatic restoration; user-owned settings are intentionally preserved.
51
+ If you previously disabled `ui-subagent` manually in `$DSH_HOME/profiles/web/cordis.patch.yml`, you can keep that stanza: it is user-owned and intentionally preserved. The plugin no longer needs (or writes) such a stanza.
47
52
 
48
53
  ## Runtime data boundary
49
54
 
50
55
  The public DSH Web session store exposes subagent summaries that have been discovered in the current browser runtime. It deliberately does not expose a global historical subagent index or a mode for every unvisited child. Therefore this first plugin version manages the discovered catalog; rows whose type is not yet loaded remain visible and searchable and fall back to DSH's retained session navigation. Exact catalog navigation is used automatically as soon as DSH supplies the address and mode.
51
56
 
52
- A full persistent workspace-wide archive view requires a host-side catalog RPC (or an upstream DSH API) that enumerates every child address and its mode. The public `SessionSummary` does not expose the original prompt or provider/model route, so those are intentionally not queried or displayed. Live output and tool/context activity are read from the bound session automatically: on dsh **0.1.2-alpha.2** they are derived from the raw `binding.eventSource` event stream (showing the tool description or target filename), while older hosts (e.g. **0.1.1-rc.2**) fall back to `session.getSnapshot().chat.legacy`. Capability detection selects the path, so the plugin stays forward compatible. If the host publishes neither, the panel falls back to the durable summary. The UI is isolated in [`lib/client.js`](lib/client.js), so it can switch to a richer source without changing the panel interaction model.
57
+ A full persistent workspace-wide archive view requires a host-side catalog RPC (or an upstream DSH API) that enumerates every child address and its mode. The public `SessionSummary` does not expose the original prompt, so prompts are neither queried nor displayed; **type and model** come from the public projections documented in [Type and model](#type-and-model-read-only-projections). Live output and tool/context activity are read from the bound session automatically: on dsh **0.1.2-alpha.2** they are derived from the raw `binding.eventSource` event stream (showing the tool description or target filename), while older hosts (e.g. **0.1.1-rc.2**) fall back to `session.getSnapshot().chat.legacy`. Capability detection selects the path, so the plugin stays forward compatible. If the host publishes neither, the panel falls back to the durable summary. The UI is isolated in [`lib/client.js`](lib/client.js), so it can switch to a richer source without changing the panel interaction model.
58
+
59
+ ### Type and model (read-only projections)
60
+
61
+ A child's type and model come from public host projections. The plugin adds no RPC and writes no state:
62
+
63
+ ```text
64
+ # type: one reader, two read-only rungs, resolved in this order
65
+ ctx.sessions.list.getSnapshot().subagentsByParent[parentId].entries
66
+ → entry.mode # rung 1: discovered catalog entry (present once that parent's catalog was pulled)
67
+ ctx.sessions.list.getSnapshot().byId[childId].projectionValues.subagent
68
+ → { mode, label, seq } | null # rung 2: the child's own identity projection (pushed on the live-control stream)
69
+ → displayed value = rung 1 ?? rung 2 # both silent = the existing `typeLoading` text
70
+
71
+ # model: the session projection modelSelection (probed by key; unreadable = the host does not publish it)
72
+ ctx.sessions.list.getSnapshot().byId[childId].projectionValues.modelSelection
73
+ → { lastUsed, next } # next = pending selection ?? lastUsed
74
+ → displayed value = next ?? lastUsed # { provider, model, reasoningEffort? }
75
+ ```
76
+
77
+ The display rules are identical on all three surfaces and differ only in density:
78
+
79
+ | Surface | Rendering |
80
+ | --- | --- |
81
+ | List-row meta line | no model (unchanged: relative time and summary stats) |
82
+ | Card detail row (expanded by default) | `Type: continuable · Model: newapi-test/DeepSeek-V4.1-Flash · high` |
83
+ | Active-subagent float | compact: `continuable · newapi-test/DeepSeek-V4.1-Flash · high` |
84
+
85
+ - `reasoningEffort` is appended **only when the host supplies it** (` · high`); no placeholder is rendered otherwise.
86
+ - All three surfaces share one `modelText()` reader, so the source, the precedence (`next ?? lastUsed`), and the fallback are the same everywhere; the float only drops the field labels.
87
+ - The type is resolved by one reader (`childModeOf`) with one fallback order, shared by the detail row, the row badge and the float: the discovered catalog entry first, then the child's own `subagent` identity projection. Rung 2 is what makes the type correct on a freshly loaded page **without** opening the manager panel — the host pushes that projection on the live-control stream and on every session-added summary, while rung 1 only arrives when a parent's catalog is pulled (opening the panel is one such pull). Both rungs silent keeps the existing fallback: the panel and the float show **type loading…** (`类型待加载` in Chinese), never a blank or a `null`.
88
+ - When the host does not publish the projection (e.g. **0.1.1-rc.2**), when the projection value is empty, or when provider/model is an empty string, the plugin shows the explicit fallback **model unknown** (`模型未知` in Chinese) instead of a blank or `null/null`. That fallback has its own i18n key (`modelUnknown`) and never reuses `typeLoading`: on an old host the two fields degrade independently (observed row: `Type: type loading… · Model: model unknown`).
89
+ - **Read-only, no switching**: the plugin calls no model write API such as `selectedModel` and offers no model-switch UI; the official SDK marks model selection as unavailable for addressed subagent sessions (`model selection is unavailable for addressed subagent sessions`).
53
90
 
54
91
  ## Compatibility
55
92
 
56
- v1.5.0 supports dsh **0.1.6-alpha.2** and stays backward compatible with all DeepSeek Harness versions. Opening a subagent session is capability-detected at runtime and degrades in three tiers:
93
+ v1.7.0 supports dsh **0.1.6-alpha.2** and stays backward compatible with all DeepSeek Harness versions. Opening a subagent session is capability-detected at runtime and degrades in three tiers:
57
94
 
58
95
  ```text
59
96
  # dsh 0.1.2-alpha.5 .. 0.1.6-alpha.1: the session controller entry points
@@ -68,6 +105,43 @@ ctx.get('uiWorkspace').openSession({ parentSessionId, childSessionId, mode } | s
68
105
 
69
106
  `uiWorkspace` is read through `ctx.get('uiWorkspace')`, never through a required injection, so hosts that do not register the service (everything before **0.1.2-alpha.5**) still load and keep using the session-controller path, while hosts that removed `openSubagent`/`open` (**0.1.6-alpha.2**) use the workspace service. **The probe order follows the argument shape, not the version**: `sessions.openSubagent` accepts an address object on every host that has it, whereas `uiWorkspace.openSession` only accepts a `SessionTarget` from **0.1.6-alpha.2** on — on **0.1.5-alpha.2 … 0.1.6-alpha.1** it is `openSession(sessionId)` and routes through `sessions.open(id)`, which throws on an address. The session-controller tier is therefore tried first and the workspace service is the fallback. Within the controller tier the exact `{ parentSessionId, childSessionId, mode }` address is used first and only a missing mode/child falls back to plain session navigation, because `openSubagent` rejects addresses that are not healthy catalog children. The 0.1.2-series capability paths (live output via `binding.eventSource`, chat-tab switch via slot `actions`) remain the primary branches, and the **0.1.1-rc.2** legacy fallbacks (`chat.legacy` snapshot) are unchanged.
70
107
 
108
+ The **open in the sidebar** button follows the same rule — capability detection, never a version check:
109
+
110
+ ```text
111
+ # button hidden entirely unless every piece is present
112
+ ctx.get('sidebarRight') → typeof openResource === 'function'
113
+ ctx.get('sidebarRightTabs') → typeof candidates === 'function'
114
+ ctx.sessions.subagentAddress → typeof function (per-row address lookup)
115
+
116
+ # per row: address = subagentAddress(row.id) rebuilt into the canonical
117
+ # dsh-resource://subagentchat/session/<child>?parent=…&mode=… form and then
118
+ # validated with sidebarRightTabs.candidates(address) — the registry's own
119
+ # "would any type open this?" check. Empty ⇒ the row's button renders disabled
120
+ # with a readable reason instead of throwing.
121
+ ```
122
+
123
+ Adding the sidebar capability does not change the navigation probe above: the row's default click still walks the same three tiers, and the new button never touches them.
124
+
125
+ Opening a subagent in the right sidebar uses DSH's own `subagentchat` right-sidebar tab, so the pane is a *session view*: the subagent session's composer there is DSH's official read-only composer (`一次性子代理记录` / "one-shot subagent record") rather than this plugin's UI. That is expected, and it is the only official way to read a child session without leaving the main conversation.
126
+
127
+
128
+ ## v1.7.0
129
+
130
+ - **Fix**: the **open in the sidebar** button (`◫`) — on a panel row and on the active float — was a far smaller target than the 24×24 CSS px minimum: 18.03×16 and 17.14×17, i.e. only the glyph itself was clickable. Both now measure **24.03×24** and **24.14×25**, while the layout box, the glyph position, the row heights and every neighbouring button's coordinates stay **pixel-identical**: the padding growth is cancelled by negative margins, and the hover pill moved into an `::after` pseudo-element whose insets reproduce the previous border box exactly (18.03×16 / 17.14×17). The one rendering difference is compositing order — the hover overlay now paints over the glyph instead of under it (≲1.3/255 per channel in the dark theme, ≲0.7/255 in the light one), which is imperceptible. Disabled rows keep their opacity and `not-allowed` cursor, and the larger area cannot turn a row press into a float drag: `closest('button,input,label')` is DOM ancestry, not geometry.
131
+ - **Docs**: the dshmarket screenshots were re-shot on a real dsh **0.1.6-alpha.2** instance of the `1.7.0-dev` line (commit `79d9d0f`) — the manager panel and the active-subagents float, each in Chinese and in English (`*.en.png`, the host locale actually switched), dark theme, 1280×900 CSS at DPR 1.75. The captured session ran four background subagents at once (three running, one finished), so every row carries its real type, model and the official usage line instead of fallback text, with the `◫`, pause, hide and delete actions visible. `screenshots.json` now lists all four paths (dshmarket's carousel cap is 6), each README points at its own language pair instead of both sharing one, and the screenshot guide was rewritten — it still described controls (`show archived`, `→ archive`) that no longer exist.
132
+
133
+ Verified on dsh **0.1.6-alpha.2**: `pnpm run check` green — the bundle's only change in this release is the hit-area CSS, and the screenshot work touched no source at all (four PNGs, `screenshots.json` and the two READMEs). The hit area was checked geometrically (padding / margin / `::after` insets against the previous border box) and by a pixel profile of the button column before and after; `./test.sh` smoke runs on an isolated `DSH_HOME` clicked the newly added edge on both the panel row and the float, exercised a disabled orphan row, and A/B-tested that pressing the enlarged area still opens the sidebar without starting a float drag or misfiring the neighbouring pause button.
134
+
135
+ ## v1.6.0
136
+
137
+ - **Feature**: every row and the active-subagent floating panel now carry an **open in the sidebar** button (`◫`) that opens the child as DSH's own `subagentchat` right-sidebar tab, so the main conversation stays where it is. It is capability-detected and never version-checked: the button is hidden entirely when the runtime exposes no `sidebarRight` / `sidebarRightTabs` capability or no tab type claims the row's address, and a single row whose address cannot be resolved stays visible but disabled with a readable reason. Clicking it never triggers the row's default navigation and never toggles batch selection. Because that sidebar tab *is* stock `ui-subagent`'s, the bundle patch no longer disables that plugin wholesale — it now only shadows `conversation.session.header.lineage` at `priority: -1` (a **title-only** shadow, so a subagent session's header title survives) and `ui-subagent` itself stays enabled. Your own `cordis.patch.yml` stanza is still preserved on removal.
138
+ - **Feature**: the manager shows each child's **type and model** (`provider/model`, plus the reasoning effort when the host publishes one) purely from public read-only projections, with the type and the model degrading independently (`类型待加载` / `模型未知`). No new RPC, no model-switch UI.
139
+ - **Fix**: a child's type could read `类型待加载` (*type loading*) until the manager panel had been opened once, even though the host had already published the mode — and opening the panel then flipped that same row to `一次性`. The mode was read only from the lazily pulled subagent catalog, and only the panel pulls it. It now resolves through one reader with one fallback order: ① the discovered catalog entry → ② the child's own `subagent` identity projection (pushed on the live-control stream and on every session-added summary, so a freshly loaded page already has it) → ③ the existing fallback text. A freshly spawned child's sidebar button can stay briefly disabled until that child is discovered; that is the documented capability probe, not a defect.
140
+ - **Fix**: the inline usage figures disagreed with DSH's own composer footer for the same child (`in 39.1k / out 12.7k · cache hit 64%` versus `143K tok · Cache hit 70%`). The line showed the *uncached input* bucket labelled as "input", and it divided the cache-hit share by the four-bucket **total**, which counts output tokens in a prompt-side ratio. Both now follow the host's definitions: `↑ billed input (uncached) / ↓ output · 命中 n% · tps · turns · steps`, with the billed input alone as the denominator, and `tps = decodeTokens / (decodeMs / 1000)` from the same public `sessionStats` projection. The complete breakdown — total, every bucket, the share, the speed and the session's LLM / tool / TTFT timings — moved into the native `title` tooltip on both the row and the float. The host's cache-hit formatter is ported expression-for-expression, so a partial hit can never round up to 100%.
141
+ - **Docs**: the lineage slot shadow is now described as what it is — a *title-only* shadow. The host's conversation module replaces the caller fallback once an entry exists in that single slot, so a literally empty entry would delete a subagent session's header title.
142
+
143
+ Verified on dsh **0.1.6-alpha.2**: `pnpm run check` green, and the usage figures cross-checked against the official composer footer for the same child in a single screenshot (`132 tok/s` / `缓存命中 98%` / `29.8M tok` against `132 tps` / `命中 98%` / `↑ 29.7m + ↓ 119.6k` = `29.8M`). The cache-hit formatter is covered by a differential test that slices the three official helper functions out of the installed host client at run time and asserts identical output over 80,980 `(read, billed)` pairs — 0 mismatches, with 425 cases where the previous implementation differed.
144
+
71
145
  ## v1.5.0
72
146
 
73
147
  - **Fix**: on DeepSeek Harness **0.1.6-alpha.2** clicking a subagent row failed with `TypeError: ctx.sessions.openSubagent is not a function` (the click was silently swallowed by the row's `try`/`catch`, so the panel just looked dead). 0.1.6-alpha.2 removed `sessions.openSubagent(address)` and `sessions.open(id)`; the plugin now detects the navigation capability at runtime in three tiers (`sessions.openSubagent` → `sessions.open` → `uiWorkspace.openSession`) instead of hard-switching, so the same bundle keeps working on both sides of that upstream change, and the failure is surfaced in the UI when no navigation API exists at all.
package/README.zh.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  面向 DeepSeek Harness Web 的子代理管理插件。插件在会话标题栏提供一个紧凑的 `🧩 子代理 active/total` 入口,用于搜索、筛选、分组、排序、查看和批量归档当前运行时已发现的子代理。
4
4
 
5
- 当前发布版本:**v1.5.0**
5
+ 当前发布版本:**v1.7.0**
6
6
 
7
7
  ## 主要功能
8
8
 
@@ -46,13 +46,22 @@
46
46
 
47
47
  ## 界面截图
48
48
 
49
- ### 子代理管理抽屉
49
+ 两张截图拍摄于 `1.7.0-dev` 分支(commit `79d9d0f`)上真实运行的 dsh **0.1.6-alpha.2** 实例,深色主题。拍摄时同一个会话里并存 4 个后台子代理——3 个仍在运行、1 个已完成,因此每行都能展示真实的类型、模型与用量数字。这里是中文界面;英文界面两张见 [`README.md`](README.md)。
50
50
 
51
- ![子代理管理抽屉](docs/images/screenshot-1.png)
51
+ ![子代理管理抽屉(中文界面)](docs/images/screenshot-1.png)
52
52
 
53
- ### 活跃子代理浮窗
53
+ ![活跃子代理浮窗(中文界面)](docs/images/screenshot-2.png)
54
54
 
55
- ![活跃子代理浮窗](docs/images/screenshot-2.png)
55
+ 管理面板自上而下依次是:
56
+
57
+ 1. **标题栏** —— 面板标题、`当前会话 n 个 · 当前工作区 n 个 · 活跃 n 个`、活跃浮窗开关与关闭按钮。
58
+ 2. **搜索与范围行** —— 名称/标题/工作区搜索,`id: xxx` 专用于 Session ID 搜索;工作区、会话、排序、分组四个选择器同处一行。
59
+ 3. **分类行** —— 内置分类与自定义分类(带实时数量),自定义分类的新建与删除都在同一标签框内。
60
+ 4. **筛选行** —— 隐藏一次性、隐藏长期未活跃、子代理背景色(浅色/深色)与重置筛选。
61
+ 5. **汇总行** —— `显示 n/m 个`、显示详情、显示已隐藏,以及批量操作入口。
62
+ 6. **活跃子代理分组** —— 置顶且可折叠,带「一键暂停」;每行包含活跃圆点、名称、Session ID、相对活动时间,以及 `◫` 在侧边栏打开、`⏸ 暂停`、`⊘ 隐藏`、`🗑 删除`。
63
+ 7. **详情区** —— 直接来自宿主只读投影的 `类型:… · 模型:…`,以及官方口径的用量行 `↑ 计费输入 (未缓存…) / ↓ 输出 · 命中 n% · n tps · n 轮 · n 步`;运行中的子代理还会显示最新的实时输出,已完成的保留最终快照。
64
+ 8. **活跃浮窗** —— 当前会话里运行中的子代理以紧凑浮窗常驻,每行带实时输出、用量行与暂停按钮;面板关闭且存在运行中子代理时自动出现。
56
65
 
57
66
  ### 分类标签
58
67
 
@@ -160,6 +169,8 @@
160
169
  5. **筛选行**:一次性、长期未活跃、已归档和重置筛选。
161
170
  6. **结果统计**:显示当前结果数量和批量操作入口。
162
171
  7. **结果列表**:活跃分组、会话/工作区分组、子代理卡片和实时状态。
172
+ 8. **行内 `◫` 按钮**:在右侧边栏打开该子代理,主对话不跳转(见「在右侧边栏打开子代理」一节)。
173
+ 9. **行内用量与统计**:卡片详情行与浮窗显示同一行 `↑ 计费输入 (未缓存…) / ↓ 输出 · 命中 n% · tps · 轮数 · 步数`,口径与官方 composer 页脚一致;完整信息(总量、各分桶、命中率、速度、模型/工具/首字耗时)在原生 `title` tooltip 中。
163
174
 
164
175
  插件不在左侧全局菜单增加入口按钮;入口仅位于会话标题栏。
165
176
 
@@ -178,19 +189,19 @@ dsh plugin --profile web remove dsh-subagent-workspace-ui
178
189
  dsh plugin --profile web add file:.
179
190
  ```
180
191
 
181
- 插件 bundle 会自动加载 [`cordis.patch.yml`](cordis.patch.yml):安装期间插入管理器,并禁用 DSH 自带的 `ui-subagent` 子代理导航。卸载插件后,该 bundle 层会移除,底层的 `ui-subagent` 设置自动恢复。请重启现有的 `dsh web` 进程,然后刷新:
192
+ 插件 bundle 会自动加载 [`cordis.patch.yml`](cordis.patch.yml):安装期间插入管理器,并且**只遮蔽一个 slot**——用 `priority: -1` 的**标题位遮蔽**占用 `conversation.session.header.lineage`,从而让 DSH 自带的 `ui-subagent` 血统下拉保持不可见。自带 `ui-subagent` 插件本身**保持启用**(本插件不再整体禁用它),因为新版「在侧边栏打开」按钮正是复用它提供的 `subagentchat` 右侧栏标签页。该遮蔽渲染的是会话标题而不是空内容,所以子代理会话标题不会消失。卸载插件后,这层 bundle patch 会被移除,宿主的 `ui-subagent` 设置从未被改动,恢复如初。请重启现有的 `dsh web` 进程,然后刷新:
182
193
 
183
194
  ```text
184
195
  http://127.0.0.1:3080
185
196
  ```
186
197
 
187
- 如果之前在 `$DSH_HOME/profiles/web/cordis.patch.yml` 中手动禁用了 `ui-subagent`,测试自动恢复前请移除那条手动配置;插件不会覆盖用户自己的设置。
198
+ 如果之前在 `$DSH_HOME/profiles/web/cordis.patch.yml` 中手动禁用了 `ui-subagent`,那条配置属于用户所有,插件不会覆盖、也不会依赖它——可以保留。
188
199
 
189
200
  ## 数据边界与兼容性
190
201
 
191
202
  插件只管理当前 DSH Web 客户端运行时已经发现的子代理目录,不伪造不存在的历史数据。首次加载以 40 条为一页;普通分页可以继续加载,批量时间选择最多扩展到 1000 条。
192
203
 
193
- 公共 `SessionSummary` 不保证提供原始提示词、provider/model 或全部历史日志,因此插件不会查询或显示 provider/model。实时输出按能力探测自动切换两种公开接口:
204
+ 公共 `SessionSummary` 不保证提供原始提示词或全部历史日志,因此插件不查询、不显示提示词。**类型与模型**改由宿主的公开投影提供,见下一节;实时输出按能力探测自动切换两种公开接口:
194
205
 
195
206
  ```text
196
207
  # dsh 0.1.2-alpha.2(新 API):绑定的事件源
@@ -206,6 +217,38 @@ sessions.binding(childId).session
206
217
 
207
218
  如果在当前宿主拿不到对应的实时数据,插件只能显示持久化的会话摘要和统计信息。
208
219
 
220
+ ### 类型与模型(只读投影)
221
+
222
+ 子代理的「类型」与「模型 provider/id」来自宿主的公开投影,不新增任何 RPC、也不写入任何状态:
223
+
224
+ ```text
225
+ # 类型:同一个取值函数、两级只读来源,按此顺序回退
226
+ ctx.sessions.list.getSnapshot().subagentsByParent[parentId].entries
227
+ → entry.mode # 第 1 级:已发现的目录条目(该父会话的目录被拉取后才存在)
228
+ ctx.sessions.list.getSnapshot().byId[childId].projectionValues.subagent
229
+ → { mode, label, seq } | null # 第 2 级:子会话自身的身份投影(随实时控制流下发)
230
+ → 显示值 = 第 1 级 ?? 第 2 级 # 两级都拿不到 = 沿用既有 `typeLoading` 兜底文案
231
+
232
+ # 模型:会话投影 modelSelection(按 key 能力探测,读不到即视为宿主不提供)
233
+ ctx.sessions.list.getSnapshot().byId[childId].projectionValues.modelSelection
234
+ → { lastUsed, next } # next = 待生效选择 ?? lastUsed
235
+ → 显示值 = next ?? lastUsed # { provider, model, reasoningEffort? }
236
+ ```
237
+
238
+ 显示规则在三处完全一致,只有密度不同:
239
+
240
+ | 位置 | 显示形态 |
241
+ | --- | --- |
242
+ | 管理面板列表行的元信息行 | 不含模型(保持原样:时间、统计) |
243
+ | 卡片详情行(默认展开) | `类型:可继续 · 模型:newapi-test/DeepSeek-V4.1-Flash · high` |
244
+ | 活跃子代理浮窗 | 紧凑形态:`可继续 · newapi-test/DeepSeek-V4.1-Flash · high` |
245
+
246
+ - `reasoningEffort` **仅在宿主提供时**追加(` · high`),宿主不提供就不显示占位符。
247
+ - 三处共用同一个 `modelText()` 取值函数,来源、优先级(`next ?? lastUsed`)与兜底逻辑完全相同,浮窗只省略字段标签。
248
+ - 类型由同一个取值函数 `childModeOf` 按同一回退顺序解析,详情行、条目徽章与浮窗共用:先取已发现的目录条目,再回退到子会话自身的 `subagent` 身份投影。第 2 级正是「刷新页面后**不打开**管理面板也能拿到正确类型」的原因——宿主在实时控制流与每次 session-added 摘要里都会下发该投影;而第 1 级只在某个父会话的目录被拉取(打开面板即其中一种)之后才出现。两级都拿不到时沿用既有兜底:面板与浮窗显示 **类型待加载**(英文界面 `type loading…`),不空白、不出现 `null`。
249
+ - 宿主未提供该投影(例如 **0.1.1-rc.2**)、投影值为空或 provider/model 为空串时,统一显示兜底文案 **模型未知**(英文界面 `model unknown`),不会出现空白或 `null/null`。该兜底使用独立 i18n 键 `modelUnknown`,不复用 `typeLoading`:老版本宿主上类型与模型各自独立降级(实测同行为 `类型:类型加载中… · 模型未知`)。
250
+ - **只读、无切换入口**:插件不调用 `selectedModel` 等任何模型写入 API,也不提供模型切换 UI;官方 SDK 对子代理地址的模型选择明确不可用(`model selection is unavailable for addressed subagent sessions`)。
251
+
209
252
  ### 打开子代理会话的三级能力探测
210
253
 
211
254
  ```text
@@ -223,6 +266,30 @@ ctx.get('uiWorkspace').openSession({ parentSessionId, childSessionId, mode } | s
223
266
 
224
267
  归档、分类和最近使用顺序保存在浏览器本地 `localStorage` 中,不会写入 DSH 会话日志。
225
268
 
269
+ ### 在右侧边栏打开子代理(`◫` 按钮)
270
+
271
+ 管理面板的每个子代理条目、以及活跃子代理浮窗的每一行,都带一个 `◫` 图标按钮:点击后**不离开当前主对话**,直接把这个子代理作为 DSH 右侧栏的 `subagentchat` 标签页打开,标签标题就是子代理的名称/label。两处行为完全一致(浮窗只是紧凑样式),并遵循同一套降级规则:
272
+
273
+ ```text
274
+ # 能力探测(不判版本号):三者缺一就不渲染按钮
275
+ ctx.get('sidebarRight') → 有 openResource 函数
276
+ ctx.get('sidebarRightTabs') → 有 candidates 函数
277
+ ctx.sessions.subagentAddress → 是函数(按行取地址)
278
+
279
+ # 单行地址:subagentAddress(row.id) 重建为
280
+ # dsh-resource://subagentchat/session/<child>?parent=…&mode=…
281
+ # 再用 sidebarRightTabs.candidates(address)(官方认定的「谁能打开」检查)验证。
282
+ # 验证为空 → 该行按钮渲染为禁用态并给出可读说明,绝不抛异常给用户。
283
+ ```
284
+
285
+ 要点:
286
+
287
+ - **默认点击不变**:点条目本身仍然把子代理打开到主对话区(与 v1.5.0 一致);新按钮 `stopPropagation`,既不触发默认跳转,也不会误触批量选择。
288
+ - **地址可用性**:一次性与可继续子代理都能打开。`ctx.sessions.subagentAddress()` 只能解析**当前客户端运行时已经发现**的子代理,因此刚派发、尚未被目录刷新的子代理,其按钮会短暂处于「没有可用的子代理地址」的禁用态(打开一次管理面板即会刷新目录并恢复可用);跨工作区、基准测试等拿不到地址的条目同样只禁用、不报错。
289
+ - **落点**:右栏会自动展开,主对话保持在原会话,可以一边看子代理一边继续主对话。
290
+ - 右侧栏里的子代理会话使用 DSH 官方的只读输入区(`一次性子代理记录` / “one-shot subagent record”),这是复用官方标签页带来的既有行为,属预期。
291
+ - 图标按钮带 tooltip:可用时为「在侧边栏打开 <名称>」,不可用时为「该条目没有可用的子代理地址,无法在侧边栏打开」;中英文案均已接入 i18n。
292
+
226
293
  ## 开发与验证
227
294
 
228
295
  插件的客户端实现自 v1.4.0 起使用 TypeScript 编写,位于 [`src/client/`](src/client/);发布产物 [`lib/client.js`](lib/client.js) 由构建脚本生成,**不要直接编辑**。宿主入口 [`lib/index.js`](lib/index.js) 仍为手写。
@@ -252,6 +319,23 @@ DSH_PLUGIN_DIR=.worktrees/x ./test.sh # 冒烟其它 checkout 的产物
252
319
  - UI 本地化(zh/en)由 [@Marcuss2](https://github.com/Marcuss2) 在 [PR #1](https://github.com/miuzel/dsh-subagent-ui/pull/1) 中贡献,特此致谢!
253
320
  - 子代理永久删除、会话生命周期清理及快照刷新机制的设计参考并致谢开源项目:[@heiheiha798/dsh-plugin-subagent-delete](https://github.com/heiheiha798/dsh-plugin-subagent-delete)。
254
321
 
322
+ ## v1.7.0 发布说明
323
+
324
+ - **修复:`◫`「在侧边栏打开」按钮的点击面积远小于 24×24 CSS px 下限**:面板行实测 18.03×16、活跃浮窗 17.14×17,等于只有字形本身可点。现分别为 **24.03×24** 与 **24.14×25**,而**布局盒、字形位置、行高与相邻按钮坐标逐像素不变**——padding 的增量被等量负 margin 抵消,hover 药丸改由 `::after` 伪元素承载、其 inset 恰好还原原边框盒(18.03×16 / 17.14×17)。唯一的渲染差异是合成顺序:hover 叠加层现在画在字形**之上**而非之下(深色主题每通道 ≲1.3/255、浅色 ≲0.7/255,肉眼不可分辨)。禁用行仍保持透明度与 `not-allowed` 光标;扩大后的区域不会把「按行」变成「拖浮窗」——`closest('button,input,label')` 判定的是 DOM 祖先而非几何。
325
+ - **文档:dshmarket 截图重拍**:在 `1.7.0-dev` 分支(commit `79d9d0f`)上真实运行的 dsh **0.1.6-alpha.2** 实例拍摄,管理器面板与活跃浮窗各出中英两张(`*.en.png`,**真正切换宿主语言**而非给中文图配英文题注),深色主题、1280×900 CSS @ DPR 1.75。拍摄时同一会话并存 4 个后台子代理(3 个运行中、1 个已完成),因此每行都带**真实**类型、模型与官方口径用量行(不再是兜底文案),`◫`、暂停、隐藏、删除四个动作齐全。`screenshots.json` 现列出全部四条路径(dshmarket 轮播上限 6),两个 README 各自引用对应语言的图(不再共用同一对),且「界面截图」导览已按新 UI 重写——旧导览仍在描述本版已不存在的控件(「显示已归档」「→ 归档」等)。
326
+
327
+ 已在 dsh **0.1.6-alpha.2** 上实机验证:`pnpm run check` 全绿——本版产物只有命中区这一处 CSS 改动,截图工作未触碰任何源码(只改 4 张 PNG + `screenshots.json` + 两个 README)。命中区另经几何核算(padding / margin / `::after` inset 与原边框盒的算式)与按钮列改造前后的像素剖面对照;并用隔离 `DSH_HOME` 跑 `./test.sh` 冒烟:在面板行与浮窗上点击**新增的边缘**内侧都能打开侧边栏、孤儿禁用行行为正确,且 A/B 验证了按按钮不会变成拖浮窗、也不会误触邻居的暂停按钮。
328
+
329
+ ## v1.6.0 发布说明
330
+
331
+ - **特性:在右侧边栏打开子代理(`◫` 按钮)**:列表行与活跃浮窗都新增 `◫`,把子代理打开为 DSH 自带的 `subagentchat` 右侧栏标签页,主对话不跳转。按钮按**能力探测、不按版本号判断**:运行时没有 `sidebarRight` / `sidebarRightTabs` 能力、或没有标签页类型认领该行地址时,按钮整体隐藏;单行地址解析不出来时保持可见但禁用,并给出可读原因。点击不会触发行的默认跳转,也不会误触批量选择。由于该标签页正是自带 `ui-subagent` 提供的,bundle patch 不再整体禁用该插件:现在只以 `priority: -1` 遮蔽 `conversation.session.header.lineage`(**标题位遮蔽**,子代理会话标题因此不会消失),`ui-subagent` 本身保持启用;卸载时用户自己的 `cordis.patch.yml` 配置依旧原样保留。
332
+ - **特性:显示子代理的类型与模型**:`provider/model`(宿主发布时附推理档位)全部取自宿主公开只读投影,类型与模型各自独立降级(`类型待加载` / `模型未知`);不新增任何 RPC,也不提供模型切换入口。
333
+ - **修复:类型在打开过一次管理面板前显示「类型待加载」**:此前 mode 只从「惰性拉取的子代理目录」读取,而该目录只有管理面板会拉,于是宿主明明已发布 mode、界面却落兜底,且打开一次面板后同一条目会突然「变对」。现改为同一个取值函数、同一回退顺序:① 已发现的目录条目 → ② 子会话自身的 `subagent` 身份投影(随实时控制流与每次 session-added 摘要下发,刷新页面即已具备)→ ③ 既有兜底文案;因此**不打开面板**、首屏即正确。刚派生的子代理在被发现前,其侧边栏按钮可能短暂禁用——这是既有的能力探测行为,不是缺陷。
334
+ - **修复:行内用量与官方 composer 页脚对不上**:同一子代理,插件显示 `in 39.1k / out 12.7k · cache hit 64%`,官方页脚显示 `143K tok · Cache hit 70%`。原因有二:行内「输入」实为**未缓存输入**这一桶,且命中率分母取了**四项总和**(把输出 token 也算进提示词侧比例)。现全部改为官方口径:`↑ 计费输入 (未缓存…) / ↓ 输出 · 命中 n% · tps · 轮数 · 步数`,命中率分母只取计费输入,`tps = decodeTokens / (decodeMs / 1000)`(取自同一个公开 `sessionStats` 投影);完整信息——总量、各分桶、命中率、速度、以及模型/工具/首字耗时——移入行与浮窗的原生 `title` tooltip。官方命中率格式化函数已逐表达式移植,**部分命中永远不会被凑成 100%**。
335
+ - **文档**:把血统 slot 遮蔽如实描述为**标题位遮蔽**。宿主会话模块在该 slot 一旦存在条目就会替换调用方 fallback,因此字面上的「空占位」会删掉子代理会话的标题。
336
+
337
+ 已在 dsh **0.1.6-alpha.2** 上实机验证:`pnpm run check` 全绿;并在同一张截图里对同一子代理与官方页脚交叉核对(`132 tok/s` / `缓存命中 98%` / `29.8M tok` 对 `132 tps` / `命中 98%` / `↑ 29.7m + ↓ 119.6k` = `29.8M`)。命中率格式化函数另有差分测试:运行时从已安装的宿主客户端切片出官方三个函数,对 80,980 组 `(read, billed)` 断言输出完全一致(0 处不符,其中 425 组是旧实现给出不同结果的用例)。
338
+
255
339
  ## v1.5.0 发布说明
256
340
 
257
341
  - **修复:dsh 0.1.6-alpha.2 点击子代理行无法打开会话**:报错 `TypeError: ctx.sessions.openSubagent is not a function`,且该错误被行点击的 `try`/`catch` 吞掉,界面表现为「点了没反应」。0.1.6-alpha.2 删除了 `sessions.openSubagent(address)` 与 `sessions.open(id)`;插件改为运行时三级能力探测(`sessions.openSubagent` → `sessions.open` → `uiWorkspace.openSession`),不再硬切调用,同一份产物在上下游变更两侧都能工作;三级都不可用时在界面上提示当前版本不支持。
package/cordis.patch.yml CHANGED
@@ -3,7 +3,12 @@
3
3
  - id: subagent-workspace-manager
4
4
  name: 'dsh-subagent-workspace-ui'
5
5
 
6
- # Disable the stock lineage dropdown while this manager is installed.
7
- # Removing this bundle restores the user's underlying ui-subagent setting.
8
- - id: ui-subagent
9
- disabled: true
6
+ # The stock ui-subagent plugin is deliberately left ENABLED: the manager reuses
7
+ # its right-sidebar chat tab for the new "open in the sidebar" button. Its
8
+ # session-header lineage dropdown is hidden instead by this plugin's own client
9
+ # bundle, which registers a title-only cell at priority -1 in
10
+ # conversation.session.header.lineage (a `single` slot renders its lowest
11
+ # priority winner, so -1 shadows the stock registration without throwing).
12
+ # Removing this package removes that registration with it, and this file no
13
+ # longer touches ui-subagent at all — a manual ui-subagent stanza a user wrote in
14
+ # the profile patch is intentionally preserved and keeps working.
package/lib/client.js CHANGED
@@ -20,7 +20,17 @@ body[data-ds-dark-theme] .dsh-sam-row-hidden{background:rgba(255,255,255,0.03)!i
20
20
  .dsh-sam-search-clear{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:0 4px;font-size:15px;line-height:1;border-radius:4px}
21
21
  .dsh-sam-search-clear:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}
22
22
  .dsh-sam-filter-toggle{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:6px 10px;font-size:11px;line-height:1;border-radius:6px;display:inline-flex;align-items:center;gap:2px}
23
- .dsh-sam-filter-toggle:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsh-sam-hide-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:0 4px;font-size:12px;line-height:16px;white-space:nowrap;align-self:start;min-width:max-content;display:inline-flex;align-items:center;gap:2px}.dsh-sam-hide-btn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);border-radius:5px}.dsh-sam-hidden-badge{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary);white-space:nowrap}.dsh-sam-delete-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:0 4px;font-size:12px;line-height:16px;white-space:nowrap;align-self:start;min-width:max-content}.dsh-sam-delete-btn:hover{color:var(--dsw-alias-state-error-primary,#ef4444);background:var(--dsw-alias-interactive-bg-hover-danger,rgba(236,19,19,.12));border-radius:5px}.dsh-sam-batch-delete-btn{color:var(--dsw-alias-state-error-primary,#ef4444)!important}.dsh-sam-batch-delete-btn:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(236,19,19,.12))!important}.dsh-sam-trigger{display:inline-flex;align-items:center;gap:0;border:0;background:transparent;color:var(--dsw-alias-label-secondary);border-radius:7px;padding:5px 7px;font:inherit;font-size:12px;cursor:pointer}.dsh-sam-trigger:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.dsh-sam-trigger-wrap{position:relative;display:inline-flex;align-items:center}.dsh-sam-active-float{position:fixed;top:56px;right:12px;z-index:999;box-sizing:border-box;width:min(360px,calc(100vw - 24px));max-height:calc(100vh - 24px);overflow:auto;padding:6px 8px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary)}.dsh-sam-active-head{display:flex;align-items:center;justify-content:space-between;gap:6px;padding:1px 2px 5px;color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:600;user-select:none}.dsh-sam-active-drag-handle{cursor:move}.dsh-sam-active-drag-handle:active{cursor:grabbing}.dsh-sam-active-actions{display:inline-flex;align-items:center;gap:6px;margin-left:auto}.dsh-sam-active-live-toggle{display:inline-flex;align-items:center;gap:3px;color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:400;cursor:pointer}.dsh-sam-active-live-toggle input{width:12px;height:12px;margin:0;accent-color:#42bd7b}.dsh-sam-active-close{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);font-size:17px;line-height:17px;cursor:pointer;padding:0 2px}.dsh-sam-active-close:hover{color:var(--dsw-alias-label-primary)}.dsh-sam-active-item{padding:7px 4px;border-top:1px solid var(--dsw-alias-border-l2);cursor:pointer}.dsh-sam-active-item:hover{background:var(--dsw-alias-interactive-bg-hover);border-radius:6px}.dsh-sam-active-title{display:flex;align-items:center;gap:5px;min-width:0;font-size:12px;line-height:17px;font-weight:600}.dsh-sam-active-icon{flex:none;color:#42bd7b;font-size:12px}.dsh-sam-active-elapsed{margin-left:auto;flex:none;color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:400}.dsh-sam-stop-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:5px;padding:2px 5px;font:inherit;font-size:10px;line-height:15px;white-space:nowrap;cursor:pointer}.dsh-sam-stop-btn:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(236,19,19,.12));color:var(--dsw-alias-state-error-primary,#ef4444)}.dsh-sam-stop-btn:disabled{opacity:.45;cursor:wait}.dsh-sam-stop-all-btn{border:0;background:transparent;color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-tertiary));border-radius:4px;padding:1px 5px;font:inherit;font-size:10px;line-height:14px;white-space:nowrap;cursor:pointer}.dsh-sam-stop-all-btn:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(236,19,19,.12));color:var(--dsw-alias-state-error-primary,#ef4444)}.dsh-sam-stop-all-btn:disabled{opacity:.45;cursor:wait}.dsh-sam-row-actions{display:inline-flex;align-items:center;gap:2px;white-space:nowrap}.dsh-sam-active-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsh-sam-active-item .dsh-sam-live{margin:3px 0 3px 17px;max-height:32px;font-size:11px;line-height:15px;pointer-events:none;user-select:none}.dsh-sam-active-stats{margin-left:17px;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dsh-sam-new-agent{position:absolute;top:calc(100% + 6px);left:0;z-index:1001;max-width:280px;padding:7px 10px;border:1px solid var(--dsw-alias-interactive-label-brand);border-radius:8px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-primary);font-size:12px;white-space:nowrap;pointer-events:none;transform-origin:top left;animation:dsh-sam-new-agent 5s ease-out both}@keyframes dsh-sam-new-agent{0%{opacity:0;transform:translateY(-5px) scale(.96)}8%,78%{opacity:1;transform:translateY(0) scale(1)}100%{opacity:0;transform:translateY(-3px) scale(.98)}}.dsh-sam-pulse{width:7px;height:7px;border-radius:50%;background:#42bd7b;animation:dsh-sam-pulse 1.5s ease-in-out infinite}@keyframes dsh-sam-pulse{0%,100%{box-shadow:0 0 0 0 rgba(66,189,123,.55)}50%{box-shadow:0 0 0 4px rgba(66,189,123,0)}}.dsh-sam-count{font-variant-numeric:tabular-nums}.dsh-sam-icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px}.dsh-sam-icon.dsh-sam-pulse{width:18px;height:18px;background:transparent}.dsh-sam-panel mark{background:#d7a83d;color:#171717;border-radius:2px;padding:0 1px}.dsh-sam-backdrop{position:fixed;inset:0;z-index:1000;background:rgba(0,0,0,.38);display:flex;justify-content:flex-end;pointer-events:auto}.dsh-sam-panel{height:100%;width:min(680px,100vw);box-sizing:border-box;display:flex;flex-direction:column;background:var(--dsw-specific-sidebar-fill,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-label-primary);box-shadow:var(--dsw-shadow-lv3);padding:22px;gap:14px}.dsh-sam-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dsh-sam-head h2{font-size:20px;margin:0}.dsh-sam-close{border:0;background:transparent;color:inherit;font-size:26px;line-height:24px;cursor:pointer}.dsh-sam-controls{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1.45fr) minmax(0,1.1fr) minmax(0,1.1fr);gap:8px;align-items:center;order:1;position:relative}.dsh-sam-controls input{grid-column:1/-1;grid-row:1}.dsh-sam-controls>select{display:block;grid-row:2;box-sizing:border-box;width:100%;min-width:0;height:30px!important;min-height:30px!important;padding:0 16px 0 8px!important;font:inherit;font-size:11px!important;line-height:normal!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsh-sam-controls option{font:inherit;font-size:12px!important;line-height:normal!important}.dsh-sam-tabs{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.dsh-sam-tab-wrap{display:inline-flex;align-items:center}.dsh-sam-tab-count{display:inline-block;margin-left:5px;min-width:14px;color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:500;line-height:14px;vertical-align:middle}.dsh-sam-custom-wrap{border-radius:7px;background:transparent;overflow:hidden}.dsh-sam-custom-wrap.dsh-sam-tab-selected{background:var(--dsw-alias-interactive-bg-hover)}.dsh-sam-custom-wrap:hover{box-shadow:inset 0 0 0 1px var(--dsw-alias-interactive-label-brand)}.dsh-sam-custom-wrap .dsh-sam-custom-tab,.dsh-sam-custom-wrap .dsh-sam-custom-tab[aria-pressed=true]{background:transparent!important;border-radius:0}.dsh-sam-custom-wrap .dsh-sam-delete-tab{margin-left:0;padding:0 6px 0 2px}.dsh-sam-tab-wrap:has(.dsh-sam-other-tab){order:99}.dsh-sam-new-tab{order:98}.dsh-sam-other-tab{order:0}.dsh-sam-delete-tab{border:0;background:transparent;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1;padding:0 2px;margin-left:-5px;cursor:pointer}.dsh-sam-delete-tab:hover{color:var(--dsw-alias-label-primary)}.dsh-sam-one-shot{display:inline-block;margin-left:6px;padding:1px 4px;border-radius:4px;background:rgba(214,166,70,.18);color:#d6a646;font-size:10px;font-weight:500;vertical-align:middle}.dsh-sam-session-id{display:inline-block;margin-left:8px;color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));font-size:11px;font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;max-width:45%}.dsh-sam-controls>select:nth-of-type(1){grid-column:1}.dsh-sam-controls>select:nth-of-type(2){grid-column:2}.dsh-sam-controls>select:nth-of-type(3){grid-column:4}.dsh-sam-controls>select:nth-of-type(4){grid-column:3}.dsh-sam-filter-btn{display:none}.dsh-sam-tabs{order:2;min-width:0;width:100%;overflow-x:auto;scrollbar-width:none}.dsh-sam-options{order:2}.dsh-sam-panel>.dsh-sam-summary{order:3}.dsh-sam-summary-line{order:3;display:flex;align-items:center;justify-content:space-between;gap:10px}.dsh-sam-batch-btn{border:0;background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:5px;padding:4px 8px;font:inherit;font-size:12px;cursor:pointer}.dsh-sam-batch-done{background:#d6a646;color:#171717;font-weight:700;box-shadow:0 0 0 2px rgba(214,166,70,.28)}.dsh-sam-row-batch{cursor:default}.dsh-sam-row-batch:hover{background:rgba(214,166,70,.08)}.dsh-sam-row-selected{background:rgba(214,166,70,.16)}.dsh-sam-archive-btn:disabled{opacity:.4;cursor:not-allowed}.dsh-sam-row-batch .dsh-sam-archive-btn{opacity:.4;cursor:default}.dsh-sam-archived-label{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary);white-space:nowrap}.dsh-sam-batch-bar{order:3;display:flex;flex-wrap:wrap;gap:6px;align-items:center}.dsh-sam-batch-bar button{border:0;background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:5px;padding:4px 7px;font:inherit;font-size:11px;cursor:pointer}.dsh-sam-batch-bar button:disabled{opacity:.45;cursor:not-allowed}.dsh-sam-panel>.dsh-sam-list{order:4}.dsh-sam-filter-popover{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv2)}.dsh-sam-filter-popover label{font-size:11px;color:var(--dsw-alias-label-tertiary);display:flex;flex-direction:column;gap:4px}.dsh-sam-filter-popover select{color:inherit;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:7px;font:inherit}.dsh-sam-filter-popover .dsh-sam-filter-wide{grid-column:1/-1}.dsh-sam-controls>*{height:40px;box-sizing:border-box}.dsh-sam-controls input,.dsh-sam-controls select,.dsh-sam-options select{min-width:0;color:inherit;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:8px;font:inherit}.dsh-sam-tabs{display:flex;gap:6px;overflow-x:auto;padding-bottom:2px}.dsh-sam-tabs button{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);padding:6px 9px;border-radius:6px;white-space:nowrap;cursor:pointer}.dsh-sam-tabs button:hover,.dsh-sam-tabs button[aria-pressed="true"]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.dsh-sam-tabs button[aria-pressed="true"]{box-shadow:inset 0 -2px 0 var(--dsw-alias-interactive-label-brand)}.dsh-sam-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;color:var(--dsw-alias-label-secondary);font-size:12px}.dsh-sam-options label{display:flex;align-items:center;gap:5px;cursor:pointer}.dsh-sam-bg-config{display:inline-flex;align-items:center;gap:6px;padding:2px 6px;border-radius:6px;background:var(--dsw-alias-interactive-bg-hover)}.dsh-sam-color-input{width:18px;height:18px;padding:0;border:0;border-radius:4px;cursor:pointer;background:transparent;vertical-align:middle}.dsh-sam-summary{font-size:12px;color:var(--dsw-alias-label-tertiary)}.dsh-sam-list{min-height:0;flex:1;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;display:flex;flex-direction:column;gap:10px;padding:2px 4px 20px 2px;scrollbar-gutter:stable}.dsh-sam-group{border:1px solid var(--dsw-alias-border-l2);border-radius:10px;overflow:hidden;flex:none}.dsh-sam-group-head{width:100%;border:0;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);padding:9px 12px;text-align:left;display:flex;justify-content:space-between;align-items:center;font:inherit;font-size:12px;font-weight:600;cursor:pointer}.dsh-sam-group-head-actions{display:inline-flex;align-items:center;gap:8px}.dsh-sam-row{width:100%;box-sizing:border-box;min-width:0;border:0;border-top:1px solid var(--dsw-alias-border-l2);background:transparent;color:inherit;text-align:left;padding:10px 12px;cursor:pointer;display:grid;grid-template-columns:minmax(22px,auto) minmax(0,1fr) auto auto;gap:9px;align-items:start}.dsh-sam-row:hover{background:var(--dsw-alias-bg-layer-2)}.dsh-sam-marker{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-width:18px;height:18px;align-self:center}.dsh-sam-marker input{margin:0;width:16px;height:16px}.dsh-sam-dot{width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-label-caption);display:inline-block;flex:none}.dsh-sam-dot.running{background:#42bd7b;box-shadow:0 0 0 3px rgba(66,189,123,.16)}.dsh-sam-dot.hidden-dot{background:transparent!important;border-radius:0!important;font-size:13px;line-height:1;width:auto;height:auto;box-shadow:none!important;display:inline-flex;align-items:center;justify-content:center}.dsh-sam-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.dsh-sam-meta{margin-top:3px;font-size:11px;color:var(--dsw-alias-label-tertiary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsh-sam-time{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;align-self:start}.dsh-sam-details{grid-column:2/-1;box-sizing:border-box;width:100%;color:var(--dsw-alias-label-tertiary);font-size:11px}.dsh-sam-details summary{cursor:pointer;color:var(--dsw-alias-label-secondary)}.dsh-sam-live{color:#42bd7b;white-space:pre-wrap;line-height:16px;max-height:32px;overflow:hidden}.dsh-sam-live-old{display:block;opacity:.48}.dsh-sam-live-latest{display:block;opacity:1;font-weight:500}.dsh-sam-live-running{color:#42bd7b}.dsh-sam-live-running .dsh-sam-live-latest{background:linear-gradient(110deg,#42bd7b 20%,#f2fff7 45%,#42bd7b 70%);background-size:220% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:dsh-sam-live-shine 2.4s linear infinite}@keyframes dsh-sam-live-shine{from{background-position:180% 0}to{background-position:-20% 0}}.dsh-sam-live-final{color:var(--dsw-alias-label-tertiary);opacity:.82}.dsh-sam-load-live-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:0 4px;font-size:11px;line-height:16px;border-radius:4px;display:inline-flex;align-items:center;gap:3px;margin:2px 0;opacity:.85}.dsh-sam-load-live-btn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);opacity:1}.dsh-sam-archive-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:0 4px;font-size:12px;line-height:16px;white-space:nowrap;align-self:start;min-width:max-content}.dsh-sam-archive-btn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);border-radius:5px}.dsh-sam-more{width:100%;border:0;border-top:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);padding:9px 12px;text-align:left;font:inherit;font-size:12px;cursor:pointer}.dsh-sam-more:hover{background:var(--dsw-alias-bg-layer-2)}.dsh-sam-empty{padding:30px 12px;text-align:center;color:var(--dsw-alias-label-tertiary)}@media(max-width:560px){.dsh-sam-panel{padding:16px;max-width:100vw;overflow:hidden}.dsh-sam-controls{grid-template-columns:minmax(0,1fr);width:100%}.dsh-sam-controls>*{grid-column:auto!important;width:100%;box-sizing:border-box}.dsh-sam-controls input{grid-column:1/-1!important}.dsh-sam-row{grid-template-columns:8px minmax(0,1fr) auto 42px;gap:6px}.dsh-sam-meta{max-width:100%;overflow:hidden;text-overflow:ellipsis}.dsh-sam-archive-btn{white-space:nowrap;font-size:11px;padding:2px}.dsh-sam-list{width:100%;box-sizing:border-box}}.dsh-sam-thinking{display:inline-flex;align-items:center;gap:5px;font-size:11px;line-height:15px;color:var(--dsw-alias-label-secondary);font-weight:500}.dsh-sam-thinking::before{content:"";width:9px;height:9px;border-radius:50%;border:2px solid transparent;border-top-color:currentColor;border-right-color:currentColor;animation:dsh-sam-spin .7s linear infinite;flex:none}@keyframes dsh-sam-spin{to{transform:rotate(360deg)}}`
23
+ .dsh-sam-filter-toggle:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsh-sam-hide-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:0 4px;font-size:12px;line-height:16px;white-space:nowrap;align-self:start;min-width:max-content;display:inline-flex;align-items:center;gap:2px}.dsh-sam-hide-btn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);border-radius:5px}.dsh-sam-hidden-badge{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary);white-space:nowrap}.dsh-sam-delete-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:0 4px;font-size:12px;line-height:16px;white-space:nowrap;align-self:start;min-width:max-content}.dsh-sam-delete-btn:hover{color:var(--dsw-alias-state-error-primary,#ef4444);background:var(--dsw-alias-interactive-bg-hover-danger,rgba(236,19,19,.12));border-radius:5px}.dsh-sam-batch-delete-btn{color:var(--dsw-alias-state-error-primary,#ef4444)!important}.dsh-sam-batch-delete-btn:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(236,19,19,.12))!important}.dsh-sam-trigger{display:inline-flex;align-items:center;gap:0;border:0;background:transparent;color:var(--dsw-alias-label-secondary);border-radius:7px;padding:5px 7px;font:inherit;font-size:12px;cursor:pointer}.dsh-sam-trigger:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.dsh-sam-trigger-wrap{position:relative;display:inline-flex;align-items:center}.dsh-sam-active-float{position:fixed;top:56px;right:12px;z-index:999;box-sizing:border-box;width:min(360px,calc(100vw - 24px));max-height:calc(100vh - 24px);overflow:auto;padding:6px 8px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary)}.dsh-sam-active-head{display:flex;align-items:center;justify-content:space-between;gap:6px;padding:1px 2px 5px;color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:600;user-select:none}.dsh-sam-active-drag-handle{cursor:move}.dsh-sam-active-drag-handle:active{cursor:grabbing}.dsh-sam-active-actions{display:inline-flex;align-items:center;gap:6px;margin-left:auto}.dsh-sam-active-live-toggle{display:inline-flex;align-items:center;gap:3px;color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:400;cursor:pointer}.dsh-sam-active-live-toggle input{width:12px;height:12px;margin:0;accent-color:#42bd7b}.dsh-sam-active-close{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);font-size:17px;line-height:17px;cursor:pointer;padding:0 2px}.dsh-sam-active-close:hover{color:var(--dsw-alias-label-primary)}.dsh-sam-active-item{padding:7px 4px;border-top:1px solid var(--dsw-alias-border-l2);cursor:pointer}.dsh-sam-active-item:hover{background:var(--dsw-alias-interactive-bg-hover);border-radius:6px}.dsh-sam-active-title{display:flex;align-items:center;gap:5px;min-width:0;font-size:12px;line-height:17px;font-weight:600}.dsh-sam-active-icon{flex:none;color:#42bd7b;font-size:12px}.dsh-sam-active-elapsed{margin-left:auto;flex:none;color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:400}.dsh-sam-stop-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:5px;padding:2px 5px;font:inherit;font-size:10px;line-height:15px;white-space:nowrap;cursor:pointer}.dsh-sam-stop-btn:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(236,19,19,.12));color:var(--dsw-alias-state-error-primary,#ef4444)}.dsh-sam-stop-btn:disabled{opacity:.45;cursor:wait}.dsh-sam-stop-all-btn{border:0;background:transparent;color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-tertiary));border-radius:4px;padding:1px 5px;font:inherit;font-size:10px;line-height:14px;white-space:nowrap;cursor:pointer}.dsh-sam-stop-all-btn:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(236,19,19,.12));color:var(--dsw-alias-state-error-primary,#ef4444)}.dsh-sam-stop-all-btn:disabled{opacity:.45;cursor:wait}.dsh-sam-row-actions{display:inline-flex;align-items:center;gap:2px;white-space:nowrap}.dsh-sam-active-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsh-sam-active-item .dsh-sam-live{margin:3px 0 3px 17px;max-height:32px;font-size:11px;line-height:15px;pointer-events:none;user-select:none}.dsh-sam-active-stats{margin-left:17px;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dsh-sam-active-model{margin-left:17px;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dsh-sam-new-agent{position:absolute;top:calc(100% + 6px);left:0;z-index:1001;max-width:280px;padding:7px 10px;border:1px solid var(--dsw-alias-interactive-label-brand);border-radius:8px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-primary);font-size:12px;white-space:nowrap;pointer-events:none;transform-origin:top left;animation:dsh-sam-new-agent 5s ease-out both}@keyframes dsh-sam-new-agent{0%{opacity:0;transform:translateY(-5px) scale(.96)}8%,78%{opacity:1;transform:translateY(0) scale(1)}100%{opacity:0;transform:translateY(-3px) scale(.98)}}.dsh-sam-pulse{width:7px;height:7px;border-radius:50%;background:#42bd7b;animation:dsh-sam-pulse 1.5s ease-in-out infinite}@keyframes dsh-sam-pulse{0%,100%{box-shadow:0 0 0 0 rgba(66,189,123,.55)}50%{box-shadow:0 0 0 4px rgba(66,189,123,0)}}.dsh-sam-count{font-variant-numeric:tabular-nums}.dsh-sam-icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px}.dsh-sam-icon.dsh-sam-pulse{width:18px;height:18px;background:transparent}.dsh-sam-panel mark{background:#d7a83d;color:#171717;border-radius:2px;padding:0 1px}.dsh-sam-backdrop{position:fixed;inset:0;z-index:1000;background:rgba(0,0,0,.38);display:flex;justify-content:flex-end;pointer-events:auto}.dsh-sam-panel{height:100%;width:min(680px,100vw);box-sizing:border-box;display:flex;flex-direction:column;background:var(--dsw-specific-sidebar-fill,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-label-primary);box-shadow:var(--dsw-shadow-lv3);padding:22px;gap:14px}.dsh-sam-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dsh-sam-head h2{font-size:20px;margin:0}.dsh-sam-close{border:0;background:transparent;color:inherit;font-size:26px;line-height:24px;cursor:pointer}.dsh-sam-controls{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1.45fr) minmax(0,1.1fr) minmax(0,1.1fr);gap:8px;align-items:center;order:1;position:relative}.dsh-sam-controls input{grid-column:1/-1;grid-row:1}.dsh-sam-controls>select{display:block;grid-row:2;box-sizing:border-box;width:100%;min-width:0;height:30px!important;min-height:30px!important;padding:0 16px 0 8px!important;font:inherit;font-size:11px!important;line-height:normal!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsh-sam-controls option{font:inherit;font-size:12px!important;line-height:normal!important}.dsh-sam-tabs{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.dsh-sam-tab-wrap{display:inline-flex;align-items:center}.dsh-sam-tab-count{display:inline-block;margin-left:5px;min-width:14px;color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:500;line-height:14px;vertical-align:middle}.dsh-sam-custom-wrap{border-radius:7px;background:transparent;overflow:hidden}.dsh-sam-custom-wrap.dsh-sam-tab-selected{background:var(--dsw-alias-interactive-bg-hover)}.dsh-sam-custom-wrap:hover{box-shadow:inset 0 0 0 1px var(--dsw-alias-interactive-label-brand)}.dsh-sam-custom-wrap .dsh-sam-custom-tab,.dsh-sam-custom-wrap .dsh-sam-custom-tab[aria-pressed=true]{background:transparent!important;border-radius:0}.dsh-sam-custom-wrap .dsh-sam-delete-tab{margin-left:0;padding:0 6px 0 2px}.dsh-sam-tab-wrap:has(.dsh-sam-other-tab){order:99}.dsh-sam-new-tab{order:98}.dsh-sam-other-tab{order:0}.dsh-sam-delete-tab{border:0;background:transparent;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1;padding:0 2px;margin-left:-5px;cursor:pointer}.dsh-sam-delete-tab:hover{color:var(--dsw-alias-label-primary)}.dsh-sam-one-shot{display:inline-block;margin-left:6px;padding:1px 4px;border-radius:4px;background:rgba(214,166,70,.18);color:#d6a646;font-size:10px;font-weight:500;vertical-align:middle}.dsh-sam-session-id{display:inline-block;margin-left:8px;color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));font-size:11px;font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;max-width:45%}.dsh-sam-controls>select:nth-of-type(1){grid-column:1}.dsh-sam-controls>select:nth-of-type(2){grid-column:2}.dsh-sam-controls>select:nth-of-type(3){grid-column:4}.dsh-sam-controls>select:nth-of-type(4){grid-column:3}.dsh-sam-filter-btn{display:none}.dsh-sam-tabs{order:2;min-width:0;width:100%;overflow-x:auto;scrollbar-width:none}.dsh-sam-options{order:2}.dsh-sam-panel>.dsh-sam-summary{order:3}.dsh-sam-summary-line{order:3;display:flex;align-items:center;justify-content:space-between;gap:10px}.dsh-sam-batch-btn{border:0;background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:5px;padding:4px 8px;font:inherit;font-size:12px;cursor:pointer}.dsh-sam-batch-done{background:#d6a646;color:#171717;font-weight:700;box-shadow:0 0 0 2px rgba(214,166,70,.28)}.dsh-sam-row-batch{cursor:default}.dsh-sam-row-batch:hover{background:rgba(214,166,70,.08)}.dsh-sam-row-selected{background:rgba(214,166,70,.16)}.dsh-sam-archive-btn:disabled{opacity:.4;cursor:not-allowed}.dsh-sam-row-batch .dsh-sam-archive-btn{opacity:.4;cursor:default}.dsh-sam-archived-label{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary);white-space:nowrap}.dsh-sam-batch-bar{order:3;display:flex;flex-wrap:wrap;gap:6px;align-items:center}.dsh-sam-batch-bar button{border:0;background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:5px;padding:4px 7px;font:inherit;font-size:11px;cursor:pointer}.dsh-sam-batch-bar button:disabled{opacity:.45;cursor:not-allowed}.dsh-sam-panel>.dsh-sam-list{order:4}.dsh-sam-filter-popover{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv2)}.dsh-sam-filter-popover label{font-size:11px;color:var(--dsw-alias-label-tertiary);display:flex;flex-direction:column;gap:4px}.dsh-sam-filter-popover select{color:inherit;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:7px;font:inherit}.dsh-sam-filter-popover .dsh-sam-filter-wide{grid-column:1/-1}.dsh-sam-controls>*{height:40px;box-sizing:border-box}.dsh-sam-controls input,.dsh-sam-controls select,.dsh-sam-options select{min-width:0;color:inherit;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:8px;font:inherit}.dsh-sam-tabs{display:flex;gap:6px;overflow-x:auto;padding-bottom:2px}.dsh-sam-tabs button{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);padding:6px 9px;border-radius:6px;white-space:nowrap;cursor:pointer}.dsh-sam-tabs button:hover,.dsh-sam-tabs button[aria-pressed="true"]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.dsh-sam-tabs button[aria-pressed="true"]{box-shadow:inset 0 -2px 0 var(--dsw-alias-interactive-label-brand)}.dsh-sam-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;color:var(--dsw-alias-label-secondary);font-size:12px}.dsh-sam-options label{display:flex;align-items:center;gap:5px;cursor:pointer}.dsh-sam-bg-config{display:inline-flex;align-items:center;gap:6px;padding:2px 6px;border-radius:6px;background:var(--dsw-alias-interactive-bg-hover)}.dsh-sam-color-input{width:18px;height:18px;padding:0;border:0;border-radius:4px;cursor:pointer;background:transparent;vertical-align:middle}.dsh-sam-summary{font-size:12px;color:var(--dsw-alias-label-tertiary)}.dsh-sam-list{min-height:0;flex:1;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;display:flex;flex-direction:column;gap:10px;padding:2px 4px 20px 2px;scrollbar-gutter:stable}.dsh-sam-group{border:1px solid var(--dsw-alias-border-l2);border-radius:10px;overflow:hidden;flex:none}.dsh-sam-group-head{width:100%;border:0;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);padding:9px 12px;text-align:left;display:flex;justify-content:space-between;align-items:center;font:inherit;font-size:12px;font-weight:600;cursor:pointer}.dsh-sam-group-head-actions{display:inline-flex;align-items:center;gap:8px}.dsh-sam-row{width:100%;box-sizing:border-box;min-width:0;border:0;border-top:1px solid var(--dsw-alias-border-l2);background:transparent;color:inherit;text-align:left;padding:10px 12px;cursor:pointer;display:grid;grid-template-columns:minmax(22px,auto) minmax(0,1fr) auto auto;gap:9px;align-items:start}.dsh-sam-row:hover{background:var(--dsw-alias-bg-layer-2)}.dsh-sam-marker{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-width:18px;height:18px;align-self:center}.dsh-sam-marker input{margin:0;width:16px;height:16px}.dsh-sam-dot{width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-label-caption);display:inline-block;flex:none}.dsh-sam-dot.running{background:#42bd7b;box-shadow:0 0 0 3px rgba(66,189,123,.16)}.dsh-sam-dot.hidden-dot{background:transparent!important;border-radius:0!important;font-size:13px;line-height:1;width:auto;height:auto;box-shadow:none!important;display:inline-flex;align-items:center;justify-content:center}.dsh-sam-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.dsh-sam-meta{margin-top:3px;font-size:11px;color:var(--dsw-alias-label-tertiary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsh-sam-time{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;align-self:start}.dsh-sam-details{grid-column:2/-1;box-sizing:border-box;width:100%;color:var(--dsw-alias-label-tertiary);font-size:11px}.dsh-sam-details summary{cursor:pointer;color:var(--dsw-alias-label-secondary)}.dsh-sam-live{color:#42bd7b;white-space:pre-wrap;line-height:16px;max-height:32px;overflow:hidden}.dsh-sam-live-old{display:block;opacity:.48}.dsh-sam-live-latest{display:block;opacity:1;font-weight:500}.dsh-sam-live-running{color:#42bd7b}.dsh-sam-live-running .dsh-sam-live-latest{background:linear-gradient(110deg,#42bd7b 20%,#f2fff7 45%,#42bd7b 70%);background-size:220% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:dsh-sam-live-shine 2.4s linear infinite}@keyframes dsh-sam-live-shine{from{background-position:180% 0}to{background-position:-20% 0}}.dsh-sam-live-final{color:var(--dsw-alias-label-tertiary);opacity:.82}.dsh-sam-load-live-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:0 4px;font-size:11px;line-height:16px;border-radius:4px;display:inline-flex;align-items:center;gap:3px;margin:2px 0;opacity:.85}.dsh-sam-load-live-btn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);opacity:1}.dsh-sam-archive-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:0 4px;font-size:12px;line-height:16px;white-space:nowrap;align-self:start;min-width:max-content}.dsh-sam-archive-btn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);border-radius:5px}.dsh-sam-more{width:100%;border:0;border-top:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);padding:9px 12px;text-align:left;font:inherit;font-size:12px;cursor:pointer}.dsh-sam-more:hover{background:var(--dsw-alias-bg-layer-2)}.dsh-sam-empty{padding:30px 12px;text-align:center;color:var(--dsw-alias-label-tertiary)}@media(max-width:560px){.dsh-sam-panel{padding:16px;max-width:100vw;overflow:hidden}.dsh-sam-controls{grid-template-columns:minmax(0,1fr);width:100%}.dsh-sam-controls>*{grid-column:auto!important;width:100%;box-sizing:border-box}.dsh-sam-controls input{grid-column:1/-1!important}.dsh-sam-row{grid-template-columns:8px minmax(0,1fr) auto 42px;gap:6px}.dsh-sam-meta{max-width:100%;overflow:hidden;text-overflow:ellipsis}.dsh-sam-archive-btn{white-space:nowrap;font-size:11px;padding:2px}.dsh-sam-list{width:100%;box-sizing:border-box}}.dsh-sam-thinking{display:inline-flex;align-items:center;gap:5px;font-size:11px;line-height:15px;color:var(--dsw-alias-label-secondary);font-weight:500}.dsh-sam-thinking::before{content:"";width:9px;height:9px;border-radius:50%;border:2px solid transparent;border-top-color:currentColor;border-right-color:currentColor;animation:dsh-sam-spin .7s linear infinite;flex:none}@keyframes dsh-sam-spin{to{transform:rotate(360deg)}}
24
+ .dsh-sam-side-btn{border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;padding:4px 4px 4px 10px;margin:-4px 0 -4px -6px;font-size:12px;line-height:16px;white-space:nowrap;align-self:start;min-width:24px;display:inline-flex;align-items:center;gap:2px;position:relative}
25
+ .dsh-sam-side-btn::after{content:"";position:absolute;left:6px;right:0;top:4px;bottom:4px;border-radius:5px;pointer-events:none}
26
+ .dsh-sam-side-btn:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
27
+ .dsh-sam-side-btn:hover:not(:disabled)::after{background:var(--dsw-alias-interactive-bg-hover)}
28
+ .dsh-sam-side-btn:disabled{opacity:.4;cursor:not-allowed}
29
+ .dsh-sam-side-btn-compact{font-size:11px;line-height:15px;padding:5px 7px 5px 8px;margin:-4px -3px -4px -4px;border-radius:5px}
30
+ .dsh-sam-side-btn-compact::after{left:4px;right:3px;top:4px;bottom:4px}
31
+ .dsh-sam-lineage-title{max-width:220px;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;background:0 0;border:none;border-radius:12px;padding:4px 8px;font-family:inherit;font-size:12px;line-height:18px;overflow:hidden;cursor:pointer}
32
+ .dsh-sam-lineage-current{color:var(--dsw-alias-label-primary);cursor:default;font-weight:500}
33
+ `
24
34
 
25
35
  if (!document.querySelector('style[data-plugin-css="dsh-subagent-workspace-ui"]')) { const tag=document.createElement('style'); tag.dataset.pluginCss='dsh-subagent-workspace-ui'; tag.textContent=css; document.head.appendChild(tag) }
26
36
  const DAY=86400000, PAGE=40, key='dsh-subagent-workspace-ui/preferences', defaultTabs=[{id:'all',nameKey:'tab.all',regex:'__ALL__'},{id:'other',nameKey:'tab.other',regex:'__OTHER__'},{id:'preset-review',nameKey:'tab.audit',regex:'\\b(?:re[- ]?)?review\\b|\\baudit\\b|\\bverify\\b|\\bverification\\b|\\binspect\\b|审计|评审|复核|核查|验证'},{id:'preset-test',nameKey:'tab.test',regex:'\\btests?\\b|\\bspecs?\\b|测试'},{id:'preset-implement',nameKey:'tab.implement',regex:'\\bimplement(?:ation)?\\b|\\bfeatures?\\b|\\bdevelop(?:ment)?\\b|\\bfix(?:es|ed)?\\b|\\brepair\\b|实现|开发|修复|修改'},{id:'preset-planning',nameKey:'tab.planning',regex:'\\bplans?\\b|\\bplanning\\b|\\bdesign\\b|\\broadmap\\b|规划|计划|方案|设计'}]
@@ -28,9 +38,79 @@ const DEFAULT_LIGHT_BG='#edf3fe', DEFAULT_DARK_BG='#1c2333'
28
38
  const load=()=>{try{return JSON.parse(localStorage.getItem(key))||{}}catch{return {}}}
29
39
 
30
40
  const age=(tr,stamp)=>{const seconds=Math.max(0,Math.floor((Date.now()-(stamp||Date.now()))/1000));if(seconds<60)return tr('age.sAgo',{s:seconds});const minutes=Math.floor(seconds/60);if(minutes<60)return tr('age.mAgo',{m:minutes});const hours=Math.floor(minutes/60);if(hours<24)return tr('age.hmAgo',{h:hours,m:minutes%60});return tr('age.dAgo',{d:Math.floor(hours/24)})}
31
- const title=s=>s.title||s.displayTitle||s.id, short=(tr,v)=>v?v.replace(/^session-/,'').slice(0,8):tr('unknown'), workspace=(tr,s)=>s?.cwd?s.cwd.split(/[\\/]/).filter(Boolean).pop():tr('unknownWorkspace'), modeLabel=(tr,m)=>m==='one-shot'?tr('oneShot'):m==='continuable'?tr('continuable'):tr('typeLoading'), tokenTotal=s=>{const u=s?.projectionValues?.tokenUsage;return u?u.uncachedInputTokens+u.outputTokens+u.cacheReadTokens+u.cacheWriteTokens:undefined},fmt=(tr,n)=>n==null?tr('unknown'):n>=1e6?`${(n/1e6).toFixed(1)}m`:n>=1e3?`${(n/1e3).toFixed(1)}k`:String(n), promptPreview=s=>String(s?.prompt||s?.projectionValues?.prompt||'').slice(0,100),statsLine=(tr,row)=>{const u=row?.projectionValues?.tokenUsage,t=tokenTotal(row);return tr('statsLine',{input:fmt(tr,u?.uncachedInputTokens),output:fmt(tr,u?.outputTokens),cacheHit:u?.cacheReadTokens!=null&&t?Math.round(u.cacheReadTokens/t*100):tr('unknown'),turns:row?.projectionValues?.sessionStats?.turns??row?.projectionValues?.turns??tr('unknown'),steps:row?.projectionValues?.sessionStats?.steps??row?.projectionValues?.steps??tr('unknown')})}
41
+ function roundedPercentUnits(cacheReadTokens,denominator,decimalPlaces){
42
+ const scale=(decimalPlaces===0?1:10)*100
43
+ const doubledScale=scale*2
44
+ const denominatorQuotient=Math.floor(denominator/doubledScale)
45
+ const denominatorRemainder=denominator%doubledScale
46
+ let lower=0
47
+ let upper=scale
48
+ while(lower<upper){
49
+ const candidate=Math.floor((lower+upper+1)/2)
50
+ const factor=candidate*2-1
51
+ if(cacheReadTokens>=factor*denominatorQuotient+Math.ceil(factor*denominatorRemainder/doubledScale))lower=candidate
52
+ else upper=candidate-1
53
+ }
54
+ return lower
55
+ }
56
+ function displayPercentUnits(units,decimalPlaces){
57
+ if(decimalPlaces===0)return String(units)
58
+ const whole=Math.floor(units/10)
59
+ const tenths=units%10
60
+ return tenths===0?String(whole):`${whole}.${tenths}`
61
+ }
62
+ function formatCacheHitPercent(cacheReadTokens,promptTokens,decimalPlaces){
63
+ if(promptTokens===0)return null
64
+ const missedInputTokens=promptTokens-cacheReadTokens
65
+ if(missedInputTokens===0)return '100'
66
+ const roundedUnits=roundedPercentUnits(cacheReadTokens,promptTokens,decimalPlaces)
67
+ if(roundedUnits<(decimalPlaces===0?100:1e3))return displayPercentUnits(roundedUnits,decimalPlaces)
68
+ let distinguishingPlaces=1
69
+ let scaledDoubleGap=missedInputTokens*200
70
+ const denominatorTens=Math.floor(promptTokens/10)
71
+ while(scaledDoubleGap<=denominatorTens){
72
+ scaledDoubleGap*=10
73
+ distinguishingPlaces+=1
74
+ }
75
+ const denominatorOnes=promptTokens%10
76
+ let roundedLoss=5
77
+ for(let loss=1;loss<5;loss+=1){
78
+ const factor=loss*2+1
79
+ const threshold=factor*denominatorTens+Math.floor(factor*denominatorOnes/10)
80
+ if(scaledDoubleGap<=threshold){
81
+ roundedLoss=loss
82
+ break
83
+ }
84
+ }
85
+ return `99.${'9'.repeat(distinguishingPlaces-1)}${10-roundedLoss}`
86
+ }
87
+ const title=s=>s.title||s.displayTitle||s.id, short=(tr,v)=>v?v.replace(/^session-/,'').slice(0,8):tr('unknown'), workspace=(tr,s)=>s?.cwd?s.cwd.split(/[\\/]/).filter(Boolean).pop():tr('unknownWorkspace'), modeLabel=(tr,m)=>m==='one-shot'?tr('oneShot'):m==='continuable'?tr('continuable'):tr('typeLoading'), // Token arithmetic shared by every usage surface, mirroring the official chat
88
+ num=(v)=>typeof v==='number'&&Number.isFinite(v)?v:undefined,
89
+ billedTokens=(u)=>{const uncached=num(u?.uncachedInputTokens),read=num(u?.cacheReadTokens),write=num(u?.cacheWriteTokens);return uncached==null||read==null||write==null?undefined:uncached+read+write},
90
+ cacheHitText=(read,billed)=>billed==null||billed<=0||read==null?null:read>=billed?'100':formatCacheHitPercent(read,billed,0),
91
+ tpsText=(tokens,ms)=>{const decodeTokens=num(tokens),decodeMs=num(ms);if(decodeTokens==null||decodeMs==null||decodeTokens<=0||decodeMs<=0)return null;const tps=decodeTokens/(decodeMs/1e3);return tps>=10?String(Math.round(tps)):String(Math.round(tps*10)/10)},
92
+ durationText=(ms)=>ms>=10000?`${Math.round(ms/1000)}s`:`${(ms/1000).toFixed(1)}s`,
93
+ fmt=(tr,n)=>n==null?tr('unknown'):n>=1e6?`${(n/1e6).toFixed(1)}m`:n>=1e3?`${(n/1e3).toFixed(1)}k`:String(n), promptPreview=s=>String(s?.prompt||s?.projectionValues?.prompt||'').slice(0,100),// The single usage reader: the host tokenUsage buckets plus the sessionStats
94
+ usageStats=(tr,row)=>{const values=row?.projectionValues,u=values?.tokenUsage,s=values?.sessionStats,billed=billedTokens(u),cacheRead=num(u?.cacheReadTokens),output=num(u?.outputTokens);return{total:billed==null||output==null?undefined:billed+output,billed,uncached:num(u?.uncachedInputTokens),cacheRead,cacheWrite:num(u?.cacheWriteTokens),output,hit:cacheHitText(cacheRead,billed),tps:tpsText(num(s?.decodeTokens),num(s?.decodeMs)),turns:num(s?.turns)??num(values?.turns)??tr('unknown'),steps:num(s?.steps)??num(values?.steps)??tr('unknown'),llmMs:num(s?.llmMs),toolMs:num(s?.toolMs),ttftMs:num(s?.ttftMs)}},
95
+ statsLine=(tr,row)=>{const u=usageStats(tr,row),parts=[tr('stats.usage',{input:fmt(tr,u.billed),uncached:fmt(tr,u.uncached),output:fmt(tr,u.output)})];if(u.hit!=null)parts.push(tr('stats.hit',{percent:u.hit}));if(u.tps!=null)parts.push(tr('stats.tps',{tps:u.tps}));parts.push(tr('stats.turns',{turns:u.turns}));parts.push(tr('stats.steps',{steps:u.steps}));return parts.join(' · ')},
96
+ statsUsageTitle=(tr,row)=>{const u=usageStats(tr,row),lines=[tr('stats.titleLine'),tr('stats.f.total',{value:fmt(tr,u.total)}),tr('stats.f.billed',{value:fmt(tr,u.billed)}),tr('stats.f.uncached',{value:fmt(tr,u.uncached)}),tr('stats.f.cacheRead',{value:fmt(tr,u.cacheRead)}),tr('stats.f.cacheWrite',{value:fmt(tr,u.cacheWrite)}),tr('stats.f.output',{value:fmt(tr,u.output)}),tr('stats.f.hit',{value:u.hit!=null?`${u.hit}%`:tr('unknown')}),tr('stats.f.tps',{value:u.tps!=null?tr('stats.tps',{tps:u.tps}):tr('unknown')}),tr('stats.f.turns',{value:u.turns}),tr('stats.f.steps',{value:u.steps})];if(u.llmMs!=null)lines.push(tr('stats.f.llm',{value:durationText(u.llmMs)}));if(u.toolMs!=null)lines.push(tr('stats.f.tool',{value:durationText(u.toolMs)}));if(u.ttftMs!=null)lines.push(tr('stats.f.ttft',{value:durationText(u.ttftMs)}));return lines.join('\n')}
32
97
  const category=(tr,name)=>{const clean=name.trim();const part=clean.split(/[::|—–-]/)[0].trim();return part.length>1&&part.length<28?part:clean.split(/\\s+/).slice(0,2).join(' ')||tr('uncategorized')},rootSession=(byId,id)=>{let current=id,seen=new Set();while(current&&byId[current]?.origin==='subagent'&&byId[current].parentId&&!seen.has(current)){seen.add(current);current=byId[current].parentId}return current}
98
+ const projectionMode=(s)=>{const raw=s?.projectionValues?.subagent,identity=raw?.identity,mode=identity?identity.mode:raw?.mode;return mode==='one-shot'||mode==='continuable'?mode:undefined}
99
+ const childModeOf=(s,catalog)=>catalog?.mode??projectionMode(s)
33
100
  const modeMap=c=>Object.values(c||{}).flatMap(x=>x.entries||[]).reduce((o,e)=>{if(e.kind==='child')o[e.id]={mode:e.mode,label:e.label};return o},{}), highlight=(text,term)=>{if(!term)return text;const parts=String(text).split(new RegExp(`(${term.replace(/[.*+?^${}()|[\\]\\\\]/g,'\\\\$&')})`,'ig'));return parts.map((part,i)=>i%2?jsx('mark',{children:part},i):part)}
101
+ const modelText=(row)=>{const sel=row?.projectionValues?.modelSelection,shown=sel?.next??sel?.lastUsed;if(!shown||!shown.provider||!shown.model)return '';return shown.reasoningEffort?`${shown.provider}/${shown.model} · ${shown.reasoningEffort}`:`${shown.provider}/${shown.model}`}
102
+ const modelLabel=(tr,row)=>{const text=modelText(row);return text?tr('model.label',{model:text}):tr('modelUnknown')}
103
+ const modelCompact=(tr,row)=>modelText(row)||tr('modelUnknown')
104
+ const modeModelLine=(tr,row)=>`${tr('mode.label',{mode:modeLabel(tr,row?.mode)})} · ${modelLabel(tr,row)}`
105
+ const modeModelCompact=(tr,row)=>`${modeLabel(tr,row?.mode)} · ${modelCompact(tr,row)}`
106
+ const asideButton=(options)=>{
107
+ const addressOf=options.addressOf
108
+ if(typeof addressOf!=='function')return null
109
+ const tr=options.tr
110
+ let address=null
111
+ try{address=addressOf(options.row)}catch(error){console.warn('subagent-workspace-ui: sidebar address lookup failed',error);address=null}
112
+ return jsx('button',{type:'button',className:options.compact?'dsh-sam-side-btn dsh-sam-side-btn-compact':'dsh-sam-side-btn',disabled:!address,title:address?tr('openInSidebar'):tr('openInSidebarUnavailable'),'aria-label':address?tr('openInSidebar.named',{name:options.row.name}):tr('openInSidebarUnavailable'),onClick:event=>{event.stopPropagation();if(!address)return;if(typeof options.open==='function'&&options.open(address)===true){if(typeof options.onOpened==='function')options.onOpened();return}window.alert(tr('openInSidebarFailed'))},children:'◫'})
113
+ }
34
114
 
35
115
  let sessionsRt=null
36
116
  const NOOP=()=>()=>{}
@@ -49,7 +129,7 @@ const elapsed=(tr,stamp)=>{const seconds=Math.max(0,Math.floor((Date.now()-(stam
49
129
 
50
130
  const liveFromEvents=(tr,entries,running)=>{const tail=s=>{const lines=String(s||'').split('\n').map(x=>x.trim()).filter(Boolean);return lines.length?lines.slice(-2).join('\n'):''},finalOf=blocks=>{const list=Array.isArray(blocks)?blocks:[];for(let i=list.length-1;i>=0;i--){const b=list[i];if(b?.type==='text'||b?.type==='reasoning'){const t=tail(b.text);if(t)return (b.type==='reasoning'?'💭 ':'')+t}if(b?.type==='tool-call'&&b.name)return tr('callTool')+b.name}return ''};let text='',reasoning='',finalText='',hasStream=false,lastKind='text';const pending=[],done=[],context=[],byCall=new Map();for(const entry of entries){if(!entry||entry.type!=='event')continue;const e=entry.event;if(!e||typeof e.type!=='string')continue;switch(e.type){case 'assistant/chunk':{const c=e.data?.chunk;if(!c)break;if(c.type==='text-delta'){text+=c.text||'';hasStream=true;lastKind='text'}else if(c.type==='reasoning-delta'){reasoning+=c.text||'';hasStream=true;lastKind='reasoning'}else if(c.type==='tool-call-delta'&&c.id){let rec=byCall.get(c.id);if(!rec){rec={name:c.name||tr('toolCall'),args:'',complete:false,running:true};byCall.set(c.id,rec);pending.push(rec)}if(c.name)rec.name=c.name;rec.args+=c.argumentsDelta||''}else if(c.type==='block-end'&&c.block?.type==='tool-call'){let rec=byCall.get(c.block.id);if(!rec){rec={name:c.block.name||tr('toolCall'),args:'',complete:false,running:true};byCall.set(c.block.id,rec);pending.push(rec)}if(c.block.name)rec.name=c.block.name;rec.args=c.block.arguments||rec.args;rec.complete=true}break}case 'user/message':{const src=e.data?.source;if(src?.kind==='plugin'||src?.kind==='relay'||src?.kind==='recall')context.push(tr('contextInjection',{name:`${src?.form||src?.plugin||src?.kind}`}));break}case 'assistant/message':{finalText=finalOf(e.data?.message?.content);text='';reasoning='';hasStream=false;break}case 'tool/call':{let rec=byCall.get(e.data?.callId);if(!rec){rec={name:e.data?.name||tr('toolCall'),args:'',complete:false,running:true};byCall.set(e.data?.callId,rec);pending.push(rec)}if(e.data?.name)rec.name=e.data?.name;if(e.data?.arguments!=null){rec.args=e.data?.arguments;rec.complete=true}rec.running=true;break}case 'tool/result':{const rec=byCall.get(e.data?.message?.source?.callId),block=e.data?.message?.content?.[0];if(rec){rec.running=false;done.push({name:rec.name,args:rec.args,complete:rec.complete,isError:block?.isError})}break}default:break}}const open=pending.filter(r=>r.running!==false);return{pendingCount:open.length,activity:[...open.slice(-2).map(r=>`▶ ${r.name||tr('toolCall')}${r.complete&&r.args?` · ${toolDetail(r.args)}`:''}`),...done.slice(-2).map(r=>`${r.isError?'✖':'✓'} ${r.name||tr('toolCall')}${r.complete&&r.args?` · ${toolDetail(r.args)}`:''}`),...context.slice(-2)],streamText:hasStream?((lastKind==='reasoning'?'💭 ':'')+tail(lastKind==='reasoning'?reasoning:text)):'',thinking:hasStream&&lastKind==='reasoning',finalText}}
51
131
 
52
- function ActiveFloat({t:tr,rows,openRow,onHide,stopAgent,stopAllAgents,stoppingIds,liveEnabled,onLiveChange,liveCap}){const [,tick]=React.useState(0),[position,setPosition]=React.useState(null),drag=React.useRef(null);React.useEffect(()=>{const timer=setInterval(()=>tick(v=>v+1),1000);return()=>clearInterval(timer)},[]);const move=e=>{if(!drag.current)return;const {offsetX,offsetY,width,height}=drag.current;setPosition({x:Math.max(8,Math.min(window.innerWidth-width-8,e.clientX-offsetX)),y:Math.max(8,Math.min(window.innerHeight-height-8,e.clientY-offsetY))})},startDrag=e=>{if(e.button!==0||e.target.closest('button,input,label'))return;const rect=e.currentTarget.parentElement.getBoundingClientRect();drag.current={offsetX:e.clientX-rect.left,offsetY:e.clientY-rect.top,width:rect.width,height:rect.height};e.currentTarget.setPointerCapture?.(e.pointerId)},stopDrag=()=>{drag.current=null},dragStyle=position?{left:position.x,top:position.y,right:'auto'}:undefined;const continuableRows=rows.filter(r=>r.mode!=='one-shot');return jsx('aside',{className:'dsh-sam-active-float',style:dragStyle,onPointerMove:move,onPointerUp:stopDrag,onPointerCancel:stopDrag,role:'status',children:[jsxs('div',{className:'dsh-sam-active-head dsh-sam-active-drag-handle',onPointerDown:startDrag,children: [jsx('span',{children:tr('activeFloat.title',{count:rows.length})}),jsxs('div',{className:'dsh-sam-active-actions',children:[continuableRows.length>0&&jsx('button',{type:'button',className:'dsh-sam-stop-all-btn',title:tr('pauseAllActive'),disabled:continuableRows.some(r=>stoppingIds.has(r.id)),onClick:e=>{e.stopPropagation();stopAllAgents(continuableRows)},children:continuableRows.some(r=>stoppingIds.has(r.id))?tr('pausing'):tr('pauseAll')}),jsx('label',{className:'dsh-sam-active-live-toggle',children:[jsx('input',{type:'checkbox',checked:liveEnabled,onChange:e=>onLiveChange(e.target.checked)}),tr('liveOutput')]}),jsx('button',{type:'button',className:'dsh-sam-active-close',onClick:e=>{e.stopPropagation();onHide()},'aria-label':tr('hideActiveFloat'),children:'×'})]})]}),rows.map((row,idx)=>jsxs('div',{className:'dsh-sam-active-item',onClick:()=>openRow(row),children:[jsxs('div',{className:'dsh-sam-active-title',children:[jsx('span',{className:'dsh-sam-active-icon',children:'🧩'}),jsx('span',{className:'dsh-sam-active-name',children:row.name}),jsx('span',{className:'dsh-sam-active-elapsed',children:elapsed(tr,row.createdAt||row.updatedAt)}),row.mode!=='one-shot'&&jsx('button',{type:'button',className:'dsh-sam-stop-btn',disabled:stoppingIds.has(row.id),onClick:e=>{e.stopPropagation();stopAgent(row)},'aria-label':tr('pause.named',{name:row.name}),'title':tr('pauseSubagent'),children:stoppingIds.has(row.id)?tr('pausing'):tr('pause')})]}),liveEnabled&&(liveCap<=0||idx<liveCap)&&jsx(LiveOutput,{t:tr,parentId:row.parentId,childId:row.id,running:true,prefix:false}),jsx('div',{className:'dsh-sam-active-stats',children:tr('statsLine',{input:fmt(tr,row.projectionValues?.tokenUsage?.uncachedInputTokens),output:fmt(tr,row.projectionValues?.tokenUsage?.outputTokens),cacheHit:row.projectionValues?.tokenUsage?.cacheReadTokens!=null&&tokenTotal(row)?Math.round(row.projectionValues.tokenUsage.cacheReadTokens/tokenTotal(row)*100):tr('unknown'),turns:row.projectionValues?.sessionStats?.turns??row.projectionValues?.turns??tr('unknown'),steps:row.projectionValues?.sessionStats?.steps??row.projectionValues?.steps??tr('unknown')})})]},row.id))]})}
132
+ function ActiveFloat({t:tr,rows,openRow,onHide,stopAgent,stopAllAgents,stoppingIds,liveEnabled,onLiveChange,liveCap,asideAddressOf,openAside}){const [,tick]=React.useState(0),[position,setPosition]=React.useState(null),drag=React.useRef(null);React.useEffect(()=>{const timer=setInterval(()=>tick(v=>v+1),1000);return()=>clearInterval(timer)},[]);const move=e=>{if(!drag.current)return;const {offsetX,offsetY,width,height}=drag.current;setPosition({x:Math.max(8,Math.min(window.innerWidth-width-8,e.clientX-offsetX)),y:Math.max(8,Math.min(window.innerHeight-height-8,e.clientY-offsetY))})},startDrag=e=>{if(e.button!==0||e.target.closest('button,input,label'))return;const rect=e.currentTarget.parentElement.getBoundingClientRect();drag.current={offsetX:e.clientX-rect.left,offsetY:e.clientY-rect.top,width:rect.width,height:rect.height};e.currentTarget.setPointerCapture?.(e.pointerId)},stopDrag=()=>{drag.current=null},dragStyle=position?{left:position.x,top:position.y,right:'auto'}:undefined;const continuableRows=rows.filter(r=>r.mode!=='one-shot');return jsx('aside',{className:'dsh-sam-active-float',style:dragStyle,onPointerMove:move,onPointerUp:stopDrag,onPointerCancel:stopDrag,role:'status',children:[jsxs('div',{className:'dsh-sam-active-head dsh-sam-active-drag-handle',onPointerDown:startDrag,children: [jsx('span',{children:tr('activeFloat.title',{count:rows.length})}),jsxs('div',{className:'dsh-sam-active-actions',children:[continuableRows.length>0&&jsx('button',{type:'button',className:'dsh-sam-stop-all-btn',title:tr('pauseAllActive'),disabled:continuableRows.some(r=>stoppingIds.has(r.id)),onClick:e=>{e.stopPropagation();stopAllAgents(continuableRows)},children:continuableRows.some(r=>stoppingIds.has(r.id))?tr('pausing'):tr('pauseAll')}),jsx('label',{className:'dsh-sam-active-live-toggle',children:[jsx('input',{type:'checkbox',checked:liveEnabled,onChange:e=>onLiveChange(e.target.checked)}),tr('liveOutput')]}),jsx('button',{type:'button',className:'dsh-sam-active-close',onClick:e=>{e.stopPropagation();onHide()},'aria-label':tr('hideActiveFloat'),children:'×'})]})]}),rows.map((row,idx)=>jsxs('div',{className:'dsh-sam-active-item',onClick:()=>openRow(row),children:[jsxs('div',{className:'dsh-sam-active-title',children:[jsx('span',{className:'dsh-sam-active-icon',children:'🧩'}),jsx('span',{className:'dsh-sam-active-name',children:row.name}),jsx('span',{className:'dsh-sam-active-elapsed',children:elapsed(tr,row.createdAt||row.updatedAt)}),asideButton({tr,row,addressOf:asideAddressOf,open:openAside,compact:true}),row.mode!=='one-shot'&&jsx('button',{type:'button',className:'dsh-sam-stop-btn',disabled:stoppingIds.has(row.id),onClick:e=>{e.stopPropagation();stopAgent(row)},'aria-label':tr('pause.named',{name:row.name}),'title':tr('pauseSubagent'),children:stoppingIds.has(row.id)?tr('pausing'):tr('pause')})]}),liveEnabled&&(liveCap<=0||idx<liveCap)&&jsx(LiveOutput,{t:tr,parentId:row.parentId,childId:row.id,running:true,prefix:false}),jsx('div',{className:'dsh-sam-active-model',children:modeModelCompact(tr,row)}),jsx('div',{className:'dsh-sam-active-stats',title:statsUsageTitle(tr,row),children:statsLine(tr,row)})]},row.id))]})}
53
133
 
54
134
  let chatViewPinGen=0
55
135
  function pinChatViewTab(sessionId){
@@ -70,10 +150,10 @@ function pinChatViewTab(sessionId){
70
150
  }
71
151
  setTimeout(tryPin,0)
72
152
  }
73
- function Manager({t:tr,useSessions,openChild,openSession,refresh,setCatalogOpen,sessionId,actions}){
153
+ function Manager({t:tr,useSessions,openChild,openSession,refresh,setCatalogOpen,sessionId,actions,asideAddressOf,openAside}){
74
154
  const state=useSessions(s=>s,(a,b)=>a?.byId===b?.byId&&a?.subagentsByParent===b?.subagentsByParent&&a?.current===b?.current),[open,setOpen]=React.useState(false),[query,setQuery]=React.useState(''),[grouping,setGrouping]=React.useState('session'),[sort,setSort]=React.useState('recent'),[prefs,setPrefs]=React.useState(load),[limit,setLimit]=React.useState(PAGE),[tab,setTab]=React.useState('all'),[scope,setScope]=React.useState('currentWorkspace'),[filterOpen,setFilterOpen]=React.useState(false),[activeOpen,setActiveOpen]=React.useState(true),[scopeDetail,setScopeDetail]=React.useState(''),[sessionScope,setSessionScope]=React.useState(''),[recentIds,setRecentIds]=React.useState([]),[batchMode,setBatchMode]=React.useState(false),[selectedIds,setSelectedIds]=React.useState(new Set),[lastSelectedIndex,setLastSelectedIndex]=React.useState(-1),[lastSelectedAction,setLastSelectedAction]=React.useState(null),[oldHours,setOldHours]=React.useState(null),[newAgents,setNewAgents]=React.useState([]),[floatHidden,setFloatHidden]=React.useState(false),[stoppingIds,setStoppingIds]=React.useState(new Set),[manualLoadedIds,setManualLoadedIds]=React.useState(new Set),runningSeen=React.useRef(false),runningIdsSeen=React.useRef(new Set),noticeTimers=React.useRef(new Map)
75
155
  const nameOf=tab=>tab.nameKey?tr(tab.nameKey):tab.name,tabs=[...defaultTabs,...(prefs.tabs||[])].filter(t=>t.id!=='filtered').filter((t,i,a)=>a.findIndex(x=>x.id===t.id)===i), archived=new Set(prefs.archived||[]), archivedParents=prefs.archivedParents||{}, currentId=rootSession(state.byId,sessionId||state.current), current=state.byId[currentId], currentCwd=current?.cwd, parentRows=Object.values(state.byId).filter(s=>s.origin!=='subagent'), scopeOptions=[...new Set(parentRows.map(s=>s.cwd).filter(Boolean))],workspaceKey=scope.startsWith('workspace:')?scope.slice(10):scope==='currentWorkspace'?currentCwd:undefined,availableSessions=parentRows.filter(s=>!workspaceKey||s.cwd===workspaceKey),selectedSession=sessionScope||currentId
76
- const modes=React.useMemo(()=>modeMap(state.subagentsByParent),[state.subagentsByParent]),subagentRows=React.useMemo(()=>{const byId=state.byId;return Object.values(byId).filter(s=>s.origin==='subagent').map(s=>({...s,...modes[s.id],name:modes[s.id]?.label||title(s),parentCwd:byId[s.parentId]?.cwd}))},[state.byId,modes]),allRows=React.useMemo(()=>{if(!open)return [];const rawTerm=query.trim().toLocaleLowerCase(),idOnly=rawTerm.startsWith('id:'),term=idOnly?rawTerm.slice(3).trim():rawTerm;return subagentRows.filter(s=>{if(workspaceKey&&s.parentCwd!==workspaceKey)return false;if(selectedSession!=='all'&&s.parentId!==selectedSession)return false;const unfiltered=tab==='all';if(!prefs.showArchived&&archived.has(s.id))return false;if(prefs.hideOneShot&&s.mode==='one-shot')return false;if(!unfiltered&&prefs.hideOld&&!s.running&&Date.now()-s.updatedAt>(prefs.oldDays||30)*DAY)return false;const custom=tabs.find(t=>t.id===tab);if(custom?.regex==='__OTHER__'){const matched=tabs.some(t=>!['filtered','all','other'].includes(t.id)&&t.regex&&(()=>{try{return new RegExp(t.regex,'i').test(s.name)}catch{return false}})());if(matched)return false}else if(custom?.regex&&custom.regex!=='__ALL__'){try{if(!new RegExp(custom.regex,'i').test(s.name))return false}catch{return false}}return !term||`${idOnly?`${s.id} ${s.parentId||''}`:`${s.name} ${title(s)} ${workspace(tr,s)}`}`.toLocaleLowerCase().includes(term)}).sort((a,b)=>{const ar=recentIds.indexOf(a.id),br=recentIds.indexOf(b.id);return ar!==br?(ar<0?1:br<0?-1:ar-br):a.running!==b.running?(b.running?1:-1):sort==='title'?a.name.localeCompare(b.name):sort==='type'?modeLabel(tr,a.mode).localeCompare(modeLabel(tr,b.mode)):b.updatedAt-a.updatedAt})},[open,subagentRows,query,sort,prefs,scope,currentCwd,currentId,scopeDetail,workspaceKey,selectedSession,tab,tabs,recentIds,tr])
156
+ const modes=React.useMemo(()=>modeMap(state.subagentsByParent),[state.subagentsByParent]),subagentRows=React.useMemo(()=>{const byId=state.byId;return Object.values(byId).filter(s=>s.origin==='subagent').map(s=>{const catalog=modes[s.id];return {...s,...catalog,mode:childModeOf(s,catalog),name:catalog?.label||title(s),parentCwd:byId[s.parentId]?.cwd}})},[state.byId,modes]),allRows=React.useMemo(()=>{if(!open)return [];const rawTerm=query.trim().toLocaleLowerCase(),idOnly=rawTerm.startsWith('id:'),term=idOnly?rawTerm.slice(3).trim():rawTerm;return subagentRows.filter(s=>{if(workspaceKey&&s.parentCwd!==workspaceKey)return false;if(selectedSession!=='all'&&s.parentId!==selectedSession)return false;const unfiltered=tab==='all';if(!prefs.showArchived&&archived.has(s.id))return false;if(prefs.hideOneShot&&s.mode==='one-shot')return false;if(!unfiltered&&prefs.hideOld&&!s.running&&Date.now()-s.updatedAt>(prefs.oldDays||30)*DAY)return false;const custom=tabs.find(t=>t.id===tab);if(custom?.regex==='__OTHER__'){const matched=tabs.some(t=>!['filtered','all','other'].includes(t.id)&&t.regex&&(()=>{try{return new RegExp(t.regex,'i').test(s.name)}catch{return false}})());if(matched)return false}else if(custom?.regex&&custom.regex!=='__ALL__'){try{if(!new RegExp(custom.regex,'i').test(s.name))return false}catch{return false}}return !term||`${idOnly?`${s.id} ${s.parentId||''}`:`${s.name} ${title(s)} ${workspace(tr,s)}`}`.toLocaleLowerCase().includes(term)}).sort((a,b)=>{const ar=recentIds.indexOf(a.id),br=recentIds.indexOf(b.id);return ar!==br?(ar<0?1:br<0?-1:ar-br):a.running!==b.running?(b.running?1:-1):sort==='title'?a.name.localeCompare(b.name):sort==='type'?modeLabel(tr,a.mode).localeCompare(modeLabel(tr,b.mode)):b.updatedAt-a.updatedAt})},[open,subagentRows,query,sort,prefs,scope,currentCwd,currentId,scopeDetail,workspaceKey,selectedSession,tab,tabs,recentIds,tr])
77
157
  const deferredSubagentRows=React.useDeferredValue(subagentRows),activeRows=React.useMemo(()=>subagentRows.filter(s=>s.running).filter(s=>(!currentCwd||s.parentCwd===currentCwd)&&(prefs.showArchived||!archived.has(s.id))&&(!prefs.hideOneShot||s.mode!=='one-shot')).sort((a,b)=>b.updatedAt-a.updatedAt),[subagentRows,currentCwd,prefs,archived])
78
158
  const stopAgent=async row=>{if(row.mode==='one-shot'||stoppingIds.has(row.id))return;if(!window.confirm(tr('confirm.pauseNamed',{name:row.name})))return;setStoppingIds(prev=>new Set(prev).add(row.id));try{const session=sessionsRt?.binding?.(row.id)?.session;if(session){if(row.parentId&&row.mode){session.configureSubagent?.({parentSessionId:row.parentId,childSessionId:row.id,mode:row.mode})}await session.open?.();await session.cancel?.();if(row.parentId){sessionsRt?.refreshSubagents?.(row.parentId)}}}catch(e){console.warn('Unable to stop subagent',e)}finally{setStoppingIds(prev=>{const next=new Set(prev);next.delete(row.id);return next})}}
79
159
  const stopAllAgents=async rowsToStop=>{const targetRows=rowsToStop.filter(r=>r.mode!=='one-shot'&&!stoppingIds.has(r.id));if(!targetRows.length)return;if(!window.confirm(tr('confirm.pauseSelected',{count:targetRows.length})))return;const ids=targetRows.map(r=>r.id);setStoppingIds(prev=>new Set([...prev,...ids]));try{await Promise.allSettled(targetRows.map(async row=>{try{const session=sessionsRt?.binding?.(row.id)?.session;if(session){if(row.parentId&&row.mode){session.configureSubagent?.({parentSessionId:row.parentId,childSessionId:row.id,mode:row.mode})}await session.open?.();await session.cancel?.();if(row.parentId){sessionsRt?.refreshSubagents?.(row.parentId)}}}catch(e){console.warn('Unable to stop subagent',row.id,e)}}))}finally{setStoppingIds(prev=>{const next=new Set(prev);ids.forEach(id=>next.delete(id));return next})}}
@@ -146,15 +226,44 @@ function Manager({t:tr,useSessions,openChild,openSession,refresh,setCatalogOpen,
146
226
  React.useEffect(()=>{const runningIds=subagentRows.filter(r=>r.running).map(r=>r.id);if(!runningIds.length)return;setRecentIds(prev=>{const next=[...runningIds,...prev.filter(id=>!runningIds.includes(id))].slice(0,100);return next.length===prev.length&&next.every((id,i)=>id===prev[i])?prev:next})},[subagentRows]);React.useEffect(()=>{if(!subagentRows.length)return;const runningIds=subagentRows.filter(r=>r.running).map(r=>r.id),current=new Set(runningIds);if(!runningSeen.current){runningSeen.current=true;runningIdsSeen.current=current;return}const fresh=runningIds.filter(id=>!runningIdsSeen.current.has(id));runningIdsSeen.current=current;if(!fresh.length)return;const names=fresh.map(id=>({id,name:subagentRows.find(r=>r.id===id)?.name})).filter(r=>r.name).slice(0,5);if(!names.length)return;setFloatHidden(false);setNewAgents(prev=>[...prev,...names].slice(-5));names.forEach(item=>{const timer=setTimeout(()=>{setNewAgents(prev=>prev.filter(x=>x.id!==item.id));noticeTimers.current.delete(item.id)},5000);if(noticeTimers.current.has(item.id))clearTimeout(noticeTimers.current.get(item.id));noticeTimers.current.set(item.id,timer)})},[subagentRows]);React.useEffect(()=>()=>{noticeTimers.current.forEach(timer=>clearTimeout(timer));noticeTimers.current.clear()},[]);const toggleSelected=(row,index,e)=>{const isShift=Boolean(e?.shiftKey&&lastSelectedIndex>=0);setSelectedIds(prev=>{const next=new Set(prev);if(isShift){const from=Math.min(lastSelectedIndex,index),to=Math.max(lastSelectedIndex,index);const shouldSelect=lastSelectedAction!==false;for(let i=from;i<=to;i++){const id=rows[i]?.id;if(!id)continue;if(shouldSelect)next.add(id);else next.delete(id)}}else{const willSelect=!next.has(row.id);if(willSelect)next.add(row.id);else next.delete(row.id);setLastSelectedAction(willSelect)};return next});setLastSelectedIndex(index)},batchArchive=(ids,restore=false)=>setPrefs(p=>{const current=new Set(p.archived||[]);ids.forEach(id=>restore?current.delete(id):current.add(id));const nextParents={...(p.archivedParents||{})};if(restore)ids.forEach(id=>delete nextParents[id]);else ids.forEach(id=>{const row=state.byId[id];if(row)nextParents[id]=row.parentId});return {...p,archived:[...current],archivedParents:nextParents}}),archiveSelected=(restore=false)=>{const ids=[...selectedIds];if(ids.length){batchArchive(ids,restore);setSelectedIds(new Set)}},selectOld=()=>{const hours=Number(window.prompt(tr('selectHoursPrompt'),'24'));if(!Number.isFinite(hours)||hours<0)return;const cutoff=Date.now()-hours*3600000;setSelectedIds(new Set(allRows.filter(r=>r.updatedAt&&r.updatedAt<=cutoff).slice(0,1000).map(r=>r.id)));setLimit(1000);setOldHours(hours);parentRows.forEach(p=>{setCatalogOpen(p.id,true);refresh(p.id)})},archive=row=>setPrefs(p=>{const was=p.archived?.includes(row.id);const nextArchived=was?p.archived.filter(x=>x!==row.id):[...(p.archived||[]),row.id];const nextParents={...(p.archivedParents||{})};if(was)delete nextParents[row.id];else nextParents[row.id]=row.parentId;return {...p,archived:nextArchived,archivedParents:nextParents}}),openRow=r=>{try{const opened=r.parentId&&r.mode?openChild({parentSessionId:r.parentId,childSessionId:r.id,mode:r.mode}):openSession(r.id);if(opened===false)window.alert(tr('openUnsupported'));else if(actions?.setView)actions.setView('chat');else pinChatViewTab(r.id);setOpen(false);setBatchMode(false)}catch(e){console.warn('Unable to open subagent',e);window.alert(tr('openUnsupported'))}}
147
227
  React.useEffect(()=>{const styleId='dsh-sam-subagent-bg-style';let el=document.getElementById(styleId);const isSubagent=sessionId&&state.byId[sessionId]?.origin==='subagent';if(isSubagent){const lightBg=prefs.subagentBgLight||DEFAULT_LIGHT_BG,darkBg=prefs.subagentBgDark||DEFAULT_DARK_BG;const bgRule=prefs.customSubagentBg!==false?`body:not([data-ds-dark-theme]) [data-conversation-scroll],body:not([data-ds-dark-theme]) [data-conversation-scroll] > *{--dsw-alias-bg-base:${lightBg}!important}body[data-ds-dark-theme] [data-conversation-scroll],body[data-ds-dark-theme] [data-conversation-scroll] > *{--dsw-alias-bg-base:${darkBg}!important}`:'';const statsRule=`div[class*="StatsLine_root"],.FJxK0a_root{background:var(--dsw-alias-bg-layer-2,rgba(128,128,128,0.08))!important;border:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,0.15))!important;border-radius:999px!important;padding:3px 14px 4px 10px!important;margin:6px auto!important;width:fit-content!important;max-width:min(calc(100% - 32px),var(--dsh-chat-content-width,748px))!important;box-shadow:var(--dsw-shadow-lv1,0 1px 3px rgba(0,0,0,0.05))!important;backdrop-filter:blur(8px)!important;color:var(--dsw-alias-label-secondary)!important;display:flex!important;align-items:center!important;justify-content:center!important}div[class*="StatsLine_root"]::before,.FJxK0a_root::before{content:"\\1F9E9";margin-right:6px;font-size:13px;line-height:1;display:inline-block;flex:none}`;if(!el){el=document.createElement('style');el.id=styleId;document.head.appendChild(el)}el.textContent=`${bgRule}${statsRule}`}else{if(el)el.remove()}},[sessionId,state.byId,prefs.customSubagentBg,prefs.subagentBgLight,prefs.subagentBgDark])
148
228
  const activeGroupContinuableRows=groups[tr('group.active')]?.filter(r=>r.mode!=='one-shot')||[]
149
- return jsxs(React.Fragment,{children:[(!open&&prefs.activeFloat!==false&&Boolean(activeRows.length)&&!floatHidden)?jsx(ActiveFloat,{t:tr,rows:activeRows,openRow,onHide:()=>setFloatHidden(true),stopAgent,stopAllAgents,stoppingIds,liveEnabled:prefs.activeFloatLive!==false,onLiveChange:value=>setPrefs(p=>({...p,activeFloatLive:value})),liveCap}):null,jsxs('div',{className:'dsh-sam-trigger-wrap',children:[jsx('button',{type:'button',className:'dsh-sam-trigger',onClick:()=>{setLimit(PAGE);setOpen(true)},title:tr('openManager'),children:[jsx('span',{className:`dsh-sam-icon ${active>0?'dsh-sam-pulse':''}`,children:'🧩'}),jsx('span',{children:tr('chip.count',{active:active,total:currentCount})})]}),!open&&newAgents.map((item,index)=>jsx('div',{className:'dsh-sam-new-agent',style:{top:`calc(100% + ${6+index*34}px)`},role:'status',children:tr('newAgent',{name:item.name})},item.id))]}),open&&jsx('div',{className:'dsh-sam-backdrop',onMouseDown:e=>{if(e.target===e.currentTarget){setOpen(false);setBatchMode(false);setSelectedIds(new Set);setLastSelectedIndex(-1);setLastSelectedAction(null)}},children:jsxs('section',{className:'dsh-sam-panel',role:'dialog','aria-modal':true,children:[jsxs('header',{className:'dsh-sam-head',children:[jsxs('div',{style:{flex:1,minWidth:0},children:[jsx('h2',{children:tr('managerTitle')}),jsxs('div',{className:'dsh-sam-head-sub',children:[jsx('div',{className:'dsh-sam-summary',children:tr('head.summary',{session:allRows.filter(r=>r.parentId===currentId).length,workspace:allRows.filter(r=>currentCwd&&state.byId[r.parentId]?.cwd===currentCwd).length,active:active})}),jsx('span',{className:'dsh-sam-summary',style:{opacity:0.6},children:'·'}),jsx('label',{className:'dsh-sam-head-float-toggle',children:[jsx('input',{type:'checkbox',checked:prefs.activeFloat!==false,onChange:()=>{setFloatHidden(false);setPrefs(p=>({...p,activeFloat:p.activeFloat===false}))}}),tr('showActiveFloat')]})]})]}),jsx('button',{className:'dsh-sam-close',type:'button',onClick:()=>{setOpen(false);setBatchMode(false);setSelectedIds(new Set);setLastSelectedIndex(-1)},children:'×'})]}),!prefs.filterCollapsed&&jsxs('div',{className:'dsh-sam-tabs',children:[tabs.map(t=>jsxs('span',{className:`dsh-sam-tab-wrap ${(prefs.tabs?.some(x=>x.id===t.id)&&!defaultTabs.some(x=>x.id===t.id))?`dsh-sam-custom-wrap ${tab===t.id?'dsh-sam-tab-selected':''}`:''}`,children:[jsx('button',{type:'button',className:`${t.id==='other'?'dsh-sam-other-tab ':''}${(prefs.tabs?.some(x=>x.id===t.id)&&!defaultTabs.some(x=>x.id===t.id))?'dsh-sam-custom-tab':''}`,'aria-pressed':tab===t.id,onClick:()=>{setTab(t.id);setLimit(PAGE)},children:jsxs(React.Fragment,{children:[nameOf(t),jsx('small',{className:'dsh-sam-tab-count',children:tabCounts[t.id]>99?'99+':tabCounts[t.id]||0})]})},`tab-select-${t.id}`),...((prefs.tabs?.some(x=>x.id===t.id)&&!defaultTabs.some(x=>x.id===t.id))?[jsx('button',{type:'button',className:'dsh-sam-delete-tab',title:tr('deleteCategory.named',{name:t.name}),'aria-label':tr('deleteCategory.named',{name:t.name}),onClick:e=>{e.stopPropagation();if(!window.confirm(tr('confirm.deleteCategory',{name:t.name})))return;setPrefs(p=>({...p,tabs:(p.tabs||[]).filter(x=>x.id!==t.id)}));if(tab===t.id)setTab('all')},children:'×'},`tab-delete-${t.id}`)]:[])]},t.id)),jsx('button',{type:'button',className:'dsh-sam-new-tab',onClick:()=>{const name=window.prompt(tr('categoryNamePrompt'));if(!name)return;const regex=window.prompt(tr('regexPrompt'));if(!regex)return;setPrefs(p=>({...p,tabs:[...(p.tabs||defaultTabs),{id:`tab-${Date.now()}`,name,regex}]}))},children:tr('newCategory')})]}),jsxs('div',{className:'dsh-sam-controls',children:[jsx('button',{type:'button',className:'dsh-sam-filter-btn',onClick:()=>setFilterOpen(v=>!v),children:`⚙ ${tr('filterSort')} · ${scope==='currentWorkspace'?tr('scope.currentWorkspace'):scope==='currentSession'?tr('scope.currentSession'):tr('scope.custom')} · ${sort==='recent'?tr('sort.recent'):sort==='title'?tr('sort.name'):tr('sort.type')}`}),!prefs.filterCollapsed&&jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},'aria-label':tr('scopeAria'),children:[jsx('option',{value:'currentWorkspace',children:tr('scope.currentWorkspace')}),jsx('option',{value:'all',children:tr('scope.allWorkspaces')}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:workspace(tr,{cwd:c})},c))]}),!prefs.filterCollapsed&&jsx('select',{value:selectedSession,onChange:e=>setSessionScope(e.target.value),children:[jsx('option',{value:'all',children:tr('scope.allSessions')}),...availableSessions.map(s=>jsx('option',{value:s.id,children:s.id===currentId?tr('session.currentDot',{name:title(s)}):title(s)},s.id))]}),jsxs('div',{className:'dsh-sam-search-wrap',children:[jsx('input',{autoFocus:true,value:query,placeholder:tr('searchPlaceholder'),onChange:e=>{setQuery(e.target.value);setLimit(PAGE)}}),jsxs('div',{className:'dsh-sam-search-actions',children:[query&&jsx('button',{type:'button',className:'dsh-sam-search-clear',title:tr('clearSearch'),onClick:()=>setQuery(''),children:'×'}),jsx('button',{type:'button',className:'dsh-sam-filter-toggle',title:prefs.filterCollapsed?tr('expandFiltersFull'):tr('collapseFiltersFull'),onClick:()=>setPrefs(p=>({...p,filterCollapsed:!p.filterCollapsed})),children:prefs.filterCollapsed?tr('expandFilters'):tr('collapseFilters')})]})]}),!prefs.filterCollapsed&&jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session',tr('grouping.optionSession')],['workspace',tr('grouping.optionWorkspace')],['category',tr('grouping.optionCategory')],['type',tr('grouping.optionType')],['none',tr('grouping.optionNone')]].map(([v,l])=>jsx('option',{value:v,children:l},v))}),!prefs.filterCollapsed&&jsx('select',{value:sort,onChange:e=>setSort(e.target.value),children:[['recent',tr('sort.optionRecent')],['title',tr('sort.optionName')],['type',tr('sort.optionType')]].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),filterOpen&&jsxs('div',{className:'dsh-sam-filter-popover',children:[jsx('label',{children:[tr('scope'),jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},children:[jsx('option',{value:'currentWorkspace',children:tr('scope.currentWorkspace')}),jsx('option',{value:'currentSession',children:tr('scope.currentSession')}),jsx('option',{value:'all',children:tr('scope.allWorkspaces')}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:tr('workspace.named',{name:workspace(tr,{cwd:c})})},c)),...parentRows.map(s=>jsx('option',{value:`session:${s.id}`,children:tr('session.named',{name:`${workspace(tr,s)} / ${title(s)}`})},s.id))]})]}),jsx('label',{children:[tr('grouping'),jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session',tr('grouping.bySession')],['workspace',tr('grouping.byWorkspace')],['category',tr('grouping.byCategory')],['type',tr('grouping.byType')],['none',tr('grouping.none')]].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),jsx('label',{children:[tr('sort'),jsx('select',{value:sort,onChange:e=>{setSort(e.target.value);setLimit(PAGE)},children:[['recent',tr('sort.recent')],['title',tr('name')],['type',tr('type')]].map(([v,l])=>jsx('option',{value:v,children:l},v))})]})]}),!prefs.filterCollapsed&&jsxs('div',{className:'dsh-sam-options',children:[jsx('label',{children:[jsx('input',{type:'checkbox',checked:!!prefs.hideOneShot,onChange:()=>setPrefs(p=>({...p,hideOneShot:!p.hideOneShot}))}),tr('hideOneShot')]}),jsx('label',{children:[jsx('input',{type:'checkbox',checked:!!prefs.hideOld,onChange:()=>setPrefs(p=>({...p,hideOld:!p.hideOld}))}),tr('hideLongInactive')]}),jsxs('span',{className:'dsh-sam-bg-config',children:[jsx('label',{children:[jsx('input',{type:'checkbox',checked:prefs.customSubagentBg!==false,onChange:()=>setPrefs(p=>({...p,customSubagentBg:p.customSubagentBg===false}))}),tr('subagentBg')]}),prefs.customSubagentBg!==false&&jsxs(React.Fragment,{children:[jsx('label',{title:tr('subagentBgLightTitle'),children:[jsx('input',{type:'color',className:'dsh-sam-color-input',value:prefs.subagentBgLight||DEFAULT_LIGHT_BG,onChange:e=>setPrefs(p=>({...p,subagentBgLight:e.target.value}))}),tr('light')]}),jsx('label',{title:tr('subagentBgDarkTitle'),children:[jsx('input',{type:'color',className:'dsh-sam-color-input',value:prefs.subagentBgDark||DEFAULT_DARK_BG,onChange:e=>setPrefs(p=>({...p,subagentBgDark:e.target.value}))}),tr('dark')]})]})]}),jsx('button',{type:'button',onClick:()=>{setQuery('');setScope('currentWorkspace');setScopeDetail('');setSessionScope('all');setTab('all');setGrouping('session');setSort('recent');setLimit(PAGE)},children:tr('resetFilters')})]}),prefs.filterCollapsed&&jsxs('div',{className:'dsh-sam-collapsed-info',children:[jsxs('div',{className:'dsh-sam-collapsed-left',children:[jsx('span',{className:'dsh-sam-collapsed-tag',children:currentScopeName}),jsx('span',{children:'·'}),jsx('span',{className:'dsh-sam-collapsed-tag',children:currentSessionName}),jsx('span',{children:'·'}),jsx('span',{className:'dsh-sam-collapsed-tag',children:currentTabName})]}),jsxs('div',{className:'dsh-sam-collapsed-right',children:[jsx('span',{children:tr('sort.current',{name:currentSortName})}),jsx('span',{children:tr('grouping.current',{name:currentGroupName})})]})]}),jsxs('div',{className:'dsh-sam-summary-line',children:[jsxs('div',{className:'dsh-sam-summary-items',children:[jsx('span',{className:'dsh-sam-summary',children:tr('summary.showing',{shown:rows.length,total:allRows.length})}),jsx('label',{className:'dsh-sam-summary-hidden-toggle',children:[jsx('input',{type:'checkbox',checked:prefs.showDetails!==false,onChange:()=>setPrefs(p=>({...p,showDetails:p.showDetails===false}))}),tr('showDetails')]}),jsx('label',{className:'dsh-sam-summary-hidden-toggle',children:[jsx('input',{type:'checkbox',checked:!!prefs.showArchived,onChange:()=>setPrefs(p=>({...p,showArchived:!p.showArchived}))}),tr('showHidden')]}),jsx('span',{className:'dsh-sam-summary',style:{fontSize:'11px'},children:tr('hideNote')})]}),jsx('button',{type:'button',className:`dsh-sam-batch-btn ${batchMode?'dsh-sam-batch-done':''}`,onClick:()=>{setBatchMode(v=>!v);setSelectedIds(new Set)},children:batchMode?tr('done'):tr('batch')})]}),batchMode&&jsxs('div',{className:'dsh-sam-batch-bar',children:[jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set(allRows.map(r=>r.id))),children:tr('selectAll')}),jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set),children:tr('clear')}),jsx('button',{type:'button',onClick:selectOld,children:tr('selectOld')}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(false),title:tr('hideSelectedTitle'),children:tr('batch.hide',{count:selectedIds.size})}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(true),title:tr('unhideSelectedTitle'),children:tr('batchUnhide')}),jsx('button',{type:'button',onClick:()=>{if(!window.confirm(tr('confirmHideAll')))return;batchArchive(allRows.map(r=>r.id));setSelectedIds(new Set)},children:tr('hideAll')}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',disabled:!selectedIds.size,onClick:()=>batchDeleteSubagents([...selectedIds]),children:tr('batch.delete',{count:selectedIds.size})}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',onClick:()=>batchDeleteSubagents(allRows.map(r=>r.id)),children:tr('deleteAll')})]}),jsx('div',{className:'dsh-sam-list',onWheel:e=>e.stopPropagation(),children:Object.keys(groups).length===0?jsx('div',{className:'dsh-sam-empty',children:tr('empty')}):Object.entries(groups).map(([name,entries])=>jsxs('section',{className:'dsh-sam-group',children:[jsxs('div',{className:'dsh-sam-group-head',onClick:()=>name===tr('group.active')&&setActiveOpen(v=>!v),children:[jsx('span',{children:`${name}${name===tr('group.active')?(activeOpen?' ▾':' ▸'):''}`}),jsxs('div',{className:'dsh-sam-group-head-actions',children:[name===tr('group.active')&&activeGroupContinuableRows.length>0&&jsx('button',{type:'button',className:'dsh-sam-stop-all-btn',title:tr('pauseAllActive'),disabled:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id)),onClick:e=>{e.stopPropagation();stopAllAgents(activeGroupContinuableRows)},children:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id))?tr('pausing'):tr('pauseAll')}),jsx('span',{children:entries.length})]})]}),(name===tr('group.active')&&!activeOpen?[]:entries).map(row=>jsx('div',{className:`dsh-sam-row ${batchMode?'dsh-sam-row-batch':''}${selectedIds.has(row.id)?' dsh-sam-row-selected':''}${archived.has(row.id)?' dsh-sam-row-hidden':''}`,onClick:e=>{if(batchMode)toggleSelected(row,rows.indexOf(row),e);else openRow(row)},title:prefs.showDetails!==false?undefined:statsLine(tr,row),children:[jsx('span',{className:'dsh-sam-marker',children:[batchMode&&jsx('input',{type:'checkbox',checked:selectedIds.has(row.id),onChange:e=>toggleSelected(row,rows.indexOf(row),e),onClick:e=>e.stopPropagation(),'aria-label':tr('select.named',{name:row.name})}),archived.has(row.id)?jsx('span',{className:'dsh-sam-dot hidden-dot',title:tr('hidden'),children:'\u{1F648}'}):jsx('span',{className:`dsh-sam-dot ${row.running?'running':''}`})]}),jsx('button',{type:'button',className:'dsh-sam-row-open',style:{all:'unset',cursor:batchMode?'default':'pointer',minWidth:0},onClick:e=>{e.stopPropagation();if(batchMode)toggleSelected(row,rows.indexOf(row),e);else openRow(row)},title:prefs.showDetails!==false?`${row.name}\n${row.id}`:`${row.name}\n${statsLine(tr,row)}`,children:jsxs('span',{children:[jsx('div',{className:'dsh-sam-title',children:jsxs('span',{children:[highlight(row.name,query),row.mode==='one-shot'&&jsx('small',{className:'dsh-sam-one-shot',children:tr('oneShotBadge')}),jsx('small',{className:'dsh-sam-session-id',children:row.id})]})}),grouping==='session'?null:jsx('div',{className:'dsh-sam-meta',children:highlight(`${modeLabel(tr,row.mode)}${grouping==='session'?'':` · ${row.parentId?`${workspace(tr,state.byId[row.parentId]||row)} / ${title(state.byId[row.parentId]||row)}`:tr('noParent')}`}`,query)})]})}),jsx('span',{className:'dsh-sam-time',title:tr('lastActivity',{time:new Date(row.updatedAt).toLocaleString()}),children:age(tr,row.updatedAt)}),batchMode?(archived.has(row.id)&&jsx('span',{className:'dsh-sam-archived-label',children:tr('hidden')})):jsxs('span',{className:'dsh-sam-row-actions',children:[row.running&&row.mode!=='one-shot'&&jsx('button',{type:'button',className:'dsh-sam-stop-btn',disabled:stoppingIds.has(row.id),onClick:e=>{e.stopPropagation();stopAgent(row)},'aria-label':tr('pause.named',{name:row.name}),'title':tr('pauseSubagent'),children:stoppingIds.has(row.id)?tr('pausing'):tr('pause')}),jsx('button',{type:'button',className:'dsh-sam-hide-btn',onClick:e=>{e.stopPropagation();archive(row)},title:archived.has(row.id)?tr('unhide'):tr('hideTitle'),'aria-label':`${archived.has(row.id)?tr('unhide'):tr('hide')} ${row.name}`,children:archived.has(row.id)?tr('unhideShort'):tr('hideShort')}),jsx('button',{type:'button',className:'dsh-sam-delete-btn',onClick:e=>{e.stopPropagation();deleteSubagent(row)},title:tr('deleteForever'),'aria-label':tr('delete.named',{name:row.name}),children:tr('deleteTrash')})]}),prefs.showDetails!==false&&jsxs('div',{className:'dsh-sam-details',children:[jsx('div',{children:tr('statsLine',{input:fmt(tr,row.projectionValues?.tokenUsage?.uncachedInputTokens),output:fmt(tr,row.projectionValues?.tokenUsage?.outputTokens),cacheHit:row.projectionValues?.tokenUsage?.cacheReadTokens!=null&&tokenTotal(row)?Math.round(row.projectionValues.tokenUsage.cacheReadTokens/tokenTotal(row)*100):tr('unknown'),turns:row.projectionValues?.sessionStats?.turns??row.projectionValues?.turns??tr('unknown'),steps:row.projectionValues?.sessionStats?.steps??row.projectionValues?.steps??tr('unknown')})}),promptPreview(row)&&jsx('div',{children:tr('prompt.label',{prompt:promptPreview(row)})}),jsx(LiveOutput,{t:tr,parentId:row.parentId,childId:row.id,running:row.running,autoLoad:rows.slice(0,10).some(r=>r.id===row.id)||manualLoadedIds.has(row.id),live:(!row.running||(runningLiveIds?runningLiveIds.has(row.id):true)||manualLoadedIds.has(row.id)),onLoad:()=>setManualLoadedIds(prev=>new Set(prev).add(row.id))})]})]},row.id)),limit<allRows.length&&jsx('button',{type:'button',className:'dsh-sam-more',onClick:()=>setLimit(n=>n+PAGE),children:tr('loadMore',{remaining:allRows.length-limit})})]},name))})]})})]})
229
+ return jsxs(React.Fragment,{children:[(!open&&prefs.activeFloat!==false&&Boolean(activeRows.length)&&!floatHidden)?jsx(ActiveFloat,{t:tr,rows:activeRows,openRow,onHide:()=>setFloatHidden(true),stopAgent,stopAllAgents,stoppingIds,liveEnabled:prefs.activeFloatLive!==false,onLiveChange:value=>setPrefs(p=>({...p,activeFloatLive:value})),liveCap,asideAddressOf,openAside}):null,jsxs('div',{className:'dsh-sam-trigger-wrap',children:[jsx('button',{type:'button',className:'dsh-sam-trigger',onClick:()=>{setLimit(PAGE);setOpen(true)},title:tr('openManager'),children:[jsx('span',{className:`dsh-sam-icon ${active>0?'dsh-sam-pulse':''}`,children:'🧩'}),jsx('span',{children:tr('chip.count',{active:active,total:currentCount})})]}),!open&&newAgents.map((item,index)=>jsx('div',{className:'dsh-sam-new-agent',style:{top:`calc(100% + ${6+index*34}px)`},role:'status',children:tr('newAgent',{name:item.name})},item.id))]}),open&&jsx('div',{className:'dsh-sam-backdrop',onMouseDown:e=>{if(e.target===e.currentTarget){setOpen(false);setBatchMode(false);setSelectedIds(new Set);setLastSelectedIndex(-1);setLastSelectedAction(null)}},children:jsxs('section',{className:'dsh-sam-panel',role:'dialog','aria-modal':true,children:[jsxs('header',{className:'dsh-sam-head',children:[jsxs('div',{style:{flex:1,minWidth:0},children:[jsx('h2',{children:tr('managerTitle')}),jsxs('div',{className:'dsh-sam-head-sub',children:[jsx('div',{className:'dsh-sam-summary',children:tr('head.summary',{session:allRows.filter(r=>r.parentId===currentId).length,workspace:allRows.filter(r=>currentCwd&&state.byId[r.parentId]?.cwd===currentCwd).length,active:active})}),jsx('span',{className:'dsh-sam-summary',style:{opacity:0.6},children:'·'}),jsx('label',{className:'dsh-sam-head-float-toggle',children:[jsx('input',{type:'checkbox',checked:prefs.activeFloat!==false,onChange:()=>{setFloatHidden(false);setPrefs(p=>({...p,activeFloat:p.activeFloat===false}))}}),tr('showActiveFloat')]})]})]}),jsx('button',{className:'dsh-sam-close',type:'button',onClick:()=>{setOpen(false);setBatchMode(false);setSelectedIds(new Set);setLastSelectedIndex(-1)},children:'×'})]}),!prefs.filterCollapsed&&jsxs('div',{className:'dsh-sam-tabs',children:[tabs.map(t=>jsxs('span',{className:`dsh-sam-tab-wrap ${(prefs.tabs?.some(x=>x.id===t.id)&&!defaultTabs.some(x=>x.id===t.id))?`dsh-sam-custom-wrap ${tab===t.id?'dsh-sam-tab-selected':''}`:''}`,children:[jsx('button',{type:'button',className:`${t.id==='other'?'dsh-sam-other-tab ':''}${(prefs.tabs?.some(x=>x.id===t.id)&&!defaultTabs.some(x=>x.id===t.id))?'dsh-sam-custom-tab':''}`,'aria-pressed':tab===t.id,onClick:()=>{setTab(t.id);setLimit(PAGE)},children:jsxs(React.Fragment,{children:[nameOf(t),jsx('small',{className:'dsh-sam-tab-count',children:tabCounts[t.id]>99?'99+':tabCounts[t.id]||0})]})},`tab-select-${t.id}`),...((prefs.tabs?.some(x=>x.id===t.id)&&!defaultTabs.some(x=>x.id===t.id))?[jsx('button',{type:'button',className:'dsh-sam-delete-tab',title:tr('deleteCategory.named',{name:t.name}),'aria-label':tr('deleteCategory.named',{name:t.name}),onClick:e=>{e.stopPropagation();if(!window.confirm(tr('confirm.deleteCategory',{name:t.name})))return;setPrefs(p=>({...p,tabs:(p.tabs||[]).filter(x=>x.id!==t.id)}));if(tab===t.id)setTab('all')},children:'×'},`tab-delete-${t.id}`)]:[])]},t.id)),jsx('button',{type:'button',className:'dsh-sam-new-tab',onClick:()=>{const name=window.prompt(tr('categoryNamePrompt'));if(!name)return;const regex=window.prompt(tr('regexPrompt'));if(!regex)return;setPrefs(p=>({...p,tabs:[...(p.tabs||defaultTabs),{id:`tab-${Date.now()}`,name,regex}]}))},children:tr('newCategory')})]}),jsxs('div',{className:'dsh-sam-controls',children:[jsx('button',{type:'button',className:'dsh-sam-filter-btn',onClick:()=>setFilterOpen(v=>!v),children:`⚙ ${tr('filterSort')} · ${scope==='currentWorkspace'?tr('scope.currentWorkspace'):scope==='currentSession'?tr('scope.currentSession'):tr('scope.custom')} · ${sort==='recent'?tr('sort.recent'):sort==='title'?tr('sort.name'):tr('sort.type')}`}),!prefs.filterCollapsed&&jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},'aria-label':tr('scopeAria'),children:[jsx('option',{value:'currentWorkspace',children:tr('scope.currentWorkspace')}),jsx('option',{value:'all',children:tr('scope.allWorkspaces')}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:workspace(tr,{cwd:c})},c))]}),!prefs.filterCollapsed&&jsx('select',{value:selectedSession,onChange:e=>setSessionScope(e.target.value),children:[jsx('option',{value:'all',children:tr('scope.allSessions')}),...availableSessions.map(s=>jsx('option',{value:s.id,children:s.id===currentId?tr('session.currentDot',{name:title(s)}):title(s)},s.id))]}),jsxs('div',{className:'dsh-sam-search-wrap',children:[jsx('input',{autoFocus:true,value:query,placeholder:tr('searchPlaceholder'),onChange:e=>{setQuery(e.target.value);setLimit(PAGE)}}),jsxs('div',{className:'dsh-sam-search-actions',children:[query&&jsx('button',{type:'button',className:'dsh-sam-search-clear',title:tr('clearSearch'),onClick:()=>setQuery(''),children:'×'}),jsx('button',{type:'button',className:'dsh-sam-filter-toggle',title:prefs.filterCollapsed?tr('expandFiltersFull'):tr('collapseFiltersFull'),onClick:()=>setPrefs(p=>({...p,filterCollapsed:!p.filterCollapsed})),children:prefs.filterCollapsed?tr('expandFilters'):tr('collapseFilters')})]})]}),!prefs.filterCollapsed&&jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session',tr('grouping.optionSession')],['workspace',tr('grouping.optionWorkspace')],['category',tr('grouping.optionCategory')],['type',tr('grouping.optionType')],['none',tr('grouping.optionNone')]].map(([v,l])=>jsx('option',{value:v,children:l},v))}),!prefs.filterCollapsed&&jsx('select',{value:sort,onChange:e=>setSort(e.target.value),children:[['recent',tr('sort.optionRecent')],['title',tr('sort.optionName')],['type',tr('sort.optionType')]].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),filterOpen&&jsxs('div',{className:'dsh-sam-filter-popover',children:[jsx('label',{children:[tr('scope'),jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},children:[jsx('option',{value:'currentWorkspace',children:tr('scope.currentWorkspace')}),jsx('option',{value:'currentSession',children:tr('scope.currentSession')}),jsx('option',{value:'all',children:tr('scope.allWorkspaces')}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:tr('workspace.named',{name:workspace(tr,{cwd:c})})},c)),...parentRows.map(s=>jsx('option',{value:`session:${s.id}`,children:tr('session.named',{name:`${workspace(tr,s)} / ${title(s)}`})},s.id))]})]}),jsx('label',{children:[tr('grouping'),jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session',tr('grouping.bySession')],['workspace',tr('grouping.byWorkspace')],['category',tr('grouping.byCategory')],['type',tr('grouping.byType')],['none',tr('grouping.none')]].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),jsx('label',{children:[tr('sort'),jsx('select',{value:sort,onChange:e=>{setSort(e.target.value);setLimit(PAGE)},children:[['recent',tr('sort.recent')],['title',tr('name')],['type',tr('type')]].map(([v,l])=>jsx('option',{value:v,children:l},v))})]})]}),!prefs.filterCollapsed&&jsxs('div',{className:'dsh-sam-options',children:[jsx('label',{children:[jsx('input',{type:'checkbox',checked:!!prefs.hideOneShot,onChange:()=>setPrefs(p=>({...p,hideOneShot:!p.hideOneShot}))}),tr('hideOneShot')]}),jsx('label',{children:[jsx('input',{type:'checkbox',checked:!!prefs.hideOld,onChange:()=>setPrefs(p=>({...p,hideOld:!p.hideOld}))}),tr('hideLongInactive')]}),jsxs('span',{className:'dsh-sam-bg-config',children:[jsx('label',{children:[jsx('input',{type:'checkbox',checked:prefs.customSubagentBg!==false,onChange:()=>setPrefs(p=>({...p,customSubagentBg:p.customSubagentBg===false}))}),tr('subagentBg')]}),prefs.customSubagentBg!==false&&jsxs(React.Fragment,{children:[jsx('label',{title:tr('subagentBgLightTitle'),children:[jsx('input',{type:'color',className:'dsh-sam-color-input',value:prefs.subagentBgLight||DEFAULT_LIGHT_BG,onChange:e=>setPrefs(p=>({...p,subagentBgLight:e.target.value}))}),tr('light')]}),jsx('label',{title:tr('subagentBgDarkTitle'),children:[jsx('input',{type:'color',className:'dsh-sam-color-input',value:prefs.subagentBgDark||DEFAULT_DARK_BG,onChange:e=>setPrefs(p=>({...p,subagentBgDark:e.target.value}))}),tr('dark')]})]})]}),jsx('button',{type:'button',onClick:()=>{setQuery('');setScope('currentWorkspace');setScopeDetail('');setSessionScope('all');setTab('all');setGrouping('session');setSort('recent');setLimit(PAGE)},children:tr('resetFilters')})]}),prefs.filterCollapsed&&jsxs('div',{className:'dsh-sam-collapsed-info',children:[jsxs('div',{className:'dsh-sam-collapsed-left',children:[jsx('span',{className:'dsh-sam-collapsed-tag',children:currentScopeName}),jsx('span',{children:'·'}),jsx('span',{className:'dsh-sam-collapsed-tag',children:currentSessionName}),jsx('span',{children:'·'}),jsx('span',{className:'dsh-sam-collapsed-tag',children:currentTabName})]}),jsxs('div',{className:'dsh-sam-collapsed-right',children:[jsx('span',{children:tr('sort.current',{name:currentSortName})}),jsx('span',{children:tr('grouping.current',{name:currentGroupName})})]})]}),jsxs('div',{className:'dsh-sam-summary-line',children:[jsxs('div',{className:'dsh-sam-summary-items',children:[jsx('span',{className:'dsh-sam-summary',children:tr('summary.showing',{shown:rows.length,total:allRows.length})}),jsx('label',{className:'dsh-sam-summary-hidden-toggle',children:[jsx('input',{type:'checkbox',checked:prefs.showDetails!==false,onChange:()=>setPrefs(p=>({...p,showDetails:p.showDetails===false}))}),tr('showDetails')]}),jsx('label',{className:'dsh-sam-summary-hidden-toggle',children:[jsx('input',{type:'checkbox',checked:!!prefs.showArchived,onChange:()=>setPrefs(p=>({...p,showArchived:!p.showArchived}))}),tr('showHidden')]}),jsx('span',{className:'dsh-sam-summary',style:{fontSize:'11px'},children:tr('hideNote')})]}),jsx('button',{type:'button',className:`dsh-sam-batch-btn ${batchMode?'dsh-sam-batch-done':''}`,onClick:()=>{setBatchMode(v=>!v);setSelectedIds(new Set)},children:batchMode?tr('done'):tr('batch')})]}),batchMode&&jsxs('div',{className:'dsh-sam-batch-bar',children:[jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set(allRows.map(r=>r.id))),children:tr('selectAll')}),jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set),children:tr('clear')}),jsx('button',{type:'button',onClick:selectOld,children:tr('selectOld')}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(false),title:tr('hideSelectedTitle'),children:tr('batch.hide',{count:selectedIds.size})}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(true),title:tr('unhideSelectedTitle'),children:tr('batchUnhide')}),jsx('button',{type:'button',onClick:()=>{if(!window.confirm(tr('confirmHideAll')))return;batchArchive(allRows.map(r=>r.id));setSelectedIds(new Set)},children:tr('hideAll')}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',disabled:!selectedIds.size,onClick:()=>batchDeleteSubagents([...selectedIds]),children:tr('batch.delete',{count:selectedIds.size})}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',onClick:()=>batchDeleteSubagents(allRows.map(r=>r.id)),children:tr('deleteAll')})]}),jsx('div',{className:'dsh-sam-list',onWheel:e=>e.stopPropagation(),children:Object.keys(groups).length===0?jsx('div',{className:'dsh-sam-empty',children:tr('empty')}):Object.entries(groups).map(([name,entries])=>jsxs('section',{className:'dsh-sam-group',children:[jsxs('div',{className:'dsh-sam-group-head',onClick:()=>name===tr('group.active')&&setActiveOpen(v=>!v),children:[jsx('span',{children:`${name}${name===tr('group.active')?(activeOpen?' ▾':' ▸'):''}`}),jsxs('div',{className:'dsh-sam-group-head-actions',children:[name===tr('group.active')&&activeGroupContinuableRows.length>0&&jsx('button',{type:'button',className:'dsh-sam-stop-all-btn',title:tr('pauseAllActive'),disabled:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id)),onClick:e=>{e.stopPropagation();stopAllAgents(activeGroupContinuableRows)},children:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id))?tr('pausing'):tr('pauseAll')}),jsx('span',{children:entries.length})]})]}),(name===tr('group.active')&&!activeOpen?[]:entries).map(row=>jsx('div',{className:`dsh-sam-row ${batchMode?'dsh-sam-row-batch':''}${selectedIds.has(row.id)?' dsh-sam-row-selected':''}${archived.has(row.id)?' dsh-sam-row-hidden':''}`,onClick:e=>{if(batchMode)toggleSelected(row,rows.indexOf(row),e);else openRow(row)},title:prefs.showDetails!==false?undefined:statsLine(tr,row),children:[jsx('span',{className:'dsh-sam-marker',children:[batchMode&&jsx('input',{type:'checkbox',checked:selectedIds.has(row.id),onChange:e=>toggleSelected(row,rows.indexOf(row),e),onClick:e=>e.stopPropagation(),'aria-label':tr('select.named',{name:row.name})}),archived.has(row.id)?jsx('span',{className:'dsh-sam-dot hidden-dot',title:tr('hidden'),children:'\u{1F648}'}):jsx('span',{className:`dsh-sam-dot ${row.running?'running':''}`})]}),jsx('button',{type:'button',className:'dsh-sam-row-open',style:{all:'unset',cursor:batchMode?'default':'pointer',minWidth:0},onClick:e=>{e.stopPropagation();if(batchMode)toggleSelected(row,rows.indexOf(row),e);else openRow(row)},title:prefs.showDetails!==false?`${row.name}\n${row.id}`:`${row.name}\n${statsLine(tr,row)}`,children:jsxs('span',{children:[jsx('div',{className:'dsh-sam-title',children:jsxs('span',{children:[highlight(row.name,query),row.mode==='one-shot'&&jsx('small',{className:'dsh-sam-one-shot',children:tr('oneShotBadge')}),jsx('small',{className:'dsh-sam-session-id',children:row.id})]})}),grouping==='session'?null:jsx('div',{className:'dsh-sam-meta',children:highlight(`${modeLabel(tr,row.mode)}${grouping==='session'?'':` · ${row.parentId?`${workspace(tr,state.byId[row.parentId]||row)} / ${title(state.byId[row.parentId]||row)}`:tr('noParent')}`}`,query)})]})}),jsx('span',{className:'dsh-sam-time',title:tr('lastActivity',{time:new Date(row.updatedAt).toLocaleString()}),children:age(tr,row.updatedAt)}),batchMode?(archived.has(row.id)&&jsx('span',{className:'dsh-sam-archived-label',children:tr('hidden')})):jsxs('span',{className:'dsh-sam-row-actions',children:[asideButton({tr,row,addressOf:asideAddressOf,open:openAside,onOpened:()=>{setOpen(false);setBatchMode(false)}}),row.running&&row.mode!=='one-shot'&&jsx('button',{type:'button',className:'dsh-sam-stop-btn',disabled:stoppingIds.has(row.id),onClick:e=>{e.stopPropagation();stopAgent(row)},'aria-label':tr('pause.named',{name:row.name}),'title':tr('pauseSubagent'),children:stoppingIds.has(row.id)?tr('pausing'):tr('pause')}),jsx('button',{type:'button',className:'dsh-sam-hide-btn',onClick:e=>{e.stopPropagation();archive(row)},title:archived.has(row.id)?tr('unhide'):tr('hideTitle'),'aria-label':`${archived.has(row.id)?tr('unhide'):tr('hide')} ${row.name}`,children:archived.has(row.id)?tr('unhideShort'):tr('hideShort')}),jsx('button',{type:'button',className:'dsh-sam-delete-btn',onClick:e=>{e.stopPropagation();deleteSubagent(row)},title:tr('deleteForever'),'aria-label':tr('delete.named',{name:row.name}),children:tr('deleteTrash')})]}),prefs.showDetails!==false&&jsxs('div',{className:'dsh-sam-details',children:[jsx('div',{children:modeModelLine(tr,row)}),jsx('div',{title:statsUsageTitle(tr,row),children:statsLine(tr,row)}),promptPreview(row)&&jsx('div',{children:tr('prompt.label',{prompt:promptPreview(row)})}),jsx(LiveOutput,{t:tr,parentId:row.parentId,childId:row.id,running:row.running,autoLoad:rows.slice(0,10).some(r=>r.id===row.id)||manualLoadedIds.has(row.id),live:(!row.running||(runningLiveIds?runningLiveIds.has(row.id):true)||manualLoadedIds.has(row.id)),onLoad:()=>setManualLoadedIds(prev=>new Set(prev).add(row.id))})]})]},row.id)),limit<allRows.length&&jsx('button',{type:'button',className:'dsh-sam-more',onClick:()=>setLimit(n=>n+PAGE),children:tr('loadMore',{remaining:allRows.length-limit})})]},name))})]})})]})
150
230
  }
151
231
 
152
232
  const NS='subagent-workspace-ui'
153
- const zh={"activeFloat.title": "活跃子代理 · {count}", "age.dAgo": "{d} 天前", "age.hmAgo": "{h} 小时 {m} 分钟前", "age.mAgo": "{m} 分钟前", "age.sAgo": "{s} 秒前", "batch": "批量操作", "batch.delete": "批量删除 ({count})", "batch.hide": "批量隐藏 ({count})", "batchDeleteFailed": "批量删除失败:", "batchDeleteRequestFailed": "批量删除请求失败:", "batchUnhide": "批量显示", "callTool": "⚙ 调用工具 ", "categoryNamePrompt": "分类名称", "chip.count": "子代理 {active}/{total}", "clear": "清空", "clearSearch": "清空搜索", "collapseFilters": "⚙ 折叠 ▴", "collapseFiltersFull": "折叠筛选与配置", "command": "命令", "command.named": "⌘ {name}", "confirm.deleteCategory": "确认删除分类“{name}”?", "confirm.deleteMany": "确认永久删除选中的 {count} 个子代理?删除后不可恢复!", "confirm.deleteOne": "确认永久删除子代理“{name}”?删除后不可恢复!", "confirm.deleteRunning": "子代理“{name}”正在运行中,删除将强制终止它。确认继续?", "confirm.pauseNamed": "确认暂停子代理“{name}”?", "confirm.pauseSelected": "确认暂停选中的 {count} 个子代理?", "confirmHideAll": "确认隐藏当前筛选出的全部子代理?", "contextInjection": "上下文注入 · {name}", "continuable": "可继续", "dark": "深色", "delete.named": "删除 {name}", "deleteAll": "一键删除全部", "deleteCategory.named": "删除分类“{name}”", "deleteFailed": "删除失败:", "deleteForever": "永久删除该子代理", "deleteRequestFailed": "删除请求失败:", "deleteTrash": "🗑 删除", "done": "完成", "elapsed.hm": "{h}时{m}分", "elapsed.ms": "{m}分{s}秒", "elapsed.s": "{s}秒", "empty": "没有符合条件的子代理。", "expandFilters": "⚙ 展开筛选 ▾", "expandFiltersFull": "展开筛选与配置", "filterSort": "筛选排序", "group.active": "活跃子代理", "group.allResults": "全部结果", "group.other": "其他", "group.otherSessions": "其他会话", "grouping": "分组", "grouping.byCategory": "按分类", "grouping.bySession": "按会话", "grouping.byType": "按类型", "grouping.byWorkspace": "按工作区", "grouping.current": "分组 · {name}", "grouping.none": "不分组", "grouping.optionCategory": "分组:按分类", "grouping.optionNone": "分组:不分组", "grouping.optionSession": "分组:按会话", "grouping.optionType": "分组:按类型", "grouping.optionWorkspace": "分组:按工作区", "head.summary": "当前会话 {session} 个 · 当前工作区 {workspace} 个 · 活跃 {active} 个", "hidden": "已隐藏", "hide": "隐藏", "hideActiveFloat": "隐藏活跃子代理浮窗", "hideAll": "一键全部隐藏", "hideLongInactive": "隐藏长期未活跃", "hideNote": "隐藏仅在列表不显示,不删除会话", "hideOneShot": "隐藏一次性", "hideSelectedTitle": "将选中的子代理隐藏", "hideShort": "⊘ 隐藏", "hideTitle": "隐藏(仅在列表隐藏,不删除会话)", "lastActivity": "最近活动:{time}", "light": "浅色", "liveOutput": "实时输出", "liveOutputPrefix": "实时输出:", "loadHistoryTitle": "加载该子代理的历史最新消息", "loadLatest": "📥 加载最新消息", "loadMore": "加载下一页(剩余 {remaining} 个)", "loading": "⏳ 加载中...", "managerTitle": "子代理管理", "name": "名字", "newAgent": "新子代理:{name}", "newCategory": "+ 新建分类", "noParent": "无父会话", "oneShot": "一次性", "oneShotBadge": "⚡ 一次性", "openManager": "打开子代理管理", "openUnsupported": "当前 dsh 版本不支持打开子代理会话(缺少可用的会话导航接口)。", "pause": "⏸ 暂停", "pause.named": "暂停 {name}", "pauseAll": "⏸ 一键暂停", "pauseAllActive": "一键暂停所有活跃可继续子代理", "pauseSubagent": "暂停子代理", "pausing": "暂停中", "prompt.label": "提示词:{prompt}", "regexPrompt": "匹配正则(例如:^审计|review)", "resetFilters": "重置筛选", "scope": "范围", "scope.allSessions": "全部会话", "scope.allWorkspaces": "全部工作区", "scope.currentSession": "当前会话", "scope.currentWorkspace": "当前工作区", "scope.custom": "自定义范围", "scopeAria": "显示范围", "searchPlaceholder": "搜索名称、标题或工作区;输入 id: 搜索 Session ID", "select.named": "选择 {name}", "selectAll": "全选", "selectHoursPrompt": "选择多少小时前的子代理?", "selectOld": "选择 N 小时前", "session.currentDot": "当前会话 · {name}", "session.currentParen": "当前会话 ({name})", "session.currentWorkspaceDot": "当前工作区 · {name}", "session.named": "会话 · {name}", "showActiveFloat": "显示活跃浮窗", "showDetails": "显示详情", "showHidden": "显示已隐藏", "sort": "排序", "sort.current": "排序 · {name}", "sort.name": "名字", "sort.optionName": "排序:名字", "sort.optionRecent": "排序:最近活跃", "sort.optionType": "排序:类型", "sort.recent": "最近活跃", "sort.type": "类型", "statsLine": "输入 {input} / 输出 {output} · 缓存命中 {cacheHit}% · 轮数 {turns} · 步数 {steps}", "subagentBg": "子代理背景色", "subagentBgDarkTitle": "深色主题下的子代理背景色", "subagentBgLightTitle": "浅色主题下的子代理背景色", "summary.showing": "显示 {shown}/{total} 个", "tab.all": "全部", "tab.audit": "审计", "tab.implement": "实现", "tab.other": "其他", "tab.planning": "规划", "tab.test": "测试", "thinking": "思考中…", "toolCall": "工具调用", "type": "类型", "typeLoading": "类型待加载", "uncategorized": "未分类", "unhide": "取消隐藏", "unhideSelectedTitle": "取消隐藏选中的子代理", "unhideShort": "👁 显示", "unknown": "未知", "unknownError": "未知错误", "unknownWorkspace": "未知工作区", "workspace.named": "工作区 · {name}"}
154
- const en={"activeFloat.title": "Active subagents · {count}", "age.dAgo": "{d}d ago", "age.hmAgo": "{h}h {m}m ago", "age.mAgo": "{m}m ago", "age.sAgo": "{s}s ago", "batch": "Batch", "batch.delete": "Delete ({count})", "batch.hide": "Hide ({count})", "batchDeleteFailed": "Batch delete failed: ", "batchDeleteRequestFailed": "Batch delete request failed: ", "batchUnhide": "Unhide", "callTool": "⚙ Call tool ", "categoryNamePrompt": "Category name", "chip.count": "Subagents {active}/{total}", "clear": "Clear", "clearSearch": "Clear search", "collapseFilters": "⚙ Collapse ▴", "collapseFiltersFull": "Collapse filters & options", "command": "Command", "command.named": "⌘ {name}", "confirm.deleteCategory": "Delete category \"{name}\"?", "confirm.deleteMany": "Permanently delete the selected {count} subagents? This cannot be undone!", "confirm.deleteOne": "Permanently delete subagent \"{name}\"? This cannot be undone!", "confirm.deleteRunning": "Subagent \"{name}\" is still running; deleting will force-terminate it. Continue?", "confirm.pauseNamed": "Pause subagent \"{name}\"?", "confirm.pauseSelected": "Pause the selected {count} subagents?", "confirmHideAll": "Hide ALL currently filtered subagents?", "contextInjection": "Context injection · {name}", "continuable": "continuable", "dark": "Dark", "delete.named": "Delete {name}", "deleteAll": "Delete all", "deleteCategory.named": "Delete category \"{name}\"", "deleteFailed": "Delete failed: ", "deleteForever": "Permanently delete this subagent", "deleteRequestFailed": "Delete request failed: ", "deleteTrash": "🗑 Delete", "done": "Done", "elapsed.hm": "{h}h{m}m", "elapsed.ms": "{m}m{s}s", "elapsed.s": "{s}s", "empty": "No subagents match the current filters.", "expandFilters": "⚙ Expand ▾", "expandFiltersFull": "Expand filters & options", "filterSort": "Filter & sort", "group.active": "Active subagents", "group.allResults": "All results", "group.other": "Other", "group.otherSessions": "Other sessions", "grouping": "Grouping", "grouping.byCategory": "by category", "grouping.bySession": "by session", "grouping.byType": "by type", "grouping.byWorkspace": "by workspace", "grouping.current": "Group · {name}", "grouping.none": "none", "grouping.optionCategory": "Group: by category", "grouping.optionNone": "Group: none", "grouping.optionSession": "Group: by session", "grouping.optionType": "Group: by type", "grouping.optionWorkspace": "Group: by workspace", "head.summary": "Current session {session} · Current workspace {workspace} · Active {active}", "hidden": "hidden", "hide": "Hide", "hideActiveFloat": "Hide the active-subagents float", "hideAll": "Hide all", "hideLongInactive": "Hide long-inactive", "hideNote": "Hiding only removes it from the list; the session is not deleted", "hideOneShot": "Hide one-shot", "hideSelectedTitle": "Hide the selected subagents", "hideShort": "⊘ Hide", "hideTitle": "Hide (hides from the list only; the session is not deleted)", "lastActivity": "Last activity: {time}", "light": "Light", "liveOutput": "Live output", "liveOutputPrefix": "Live output: ", "loadHistoryTitle": "Load the latest messages from this subagent’s history", "loadLatest": "📥 Load latest messages", "loadMore": "Load next page ({remaining} left)", "loading": "⏳ Loading...", "managerTitle": "Subagent manager", "name": "name", "newAgent": "New subagent: {name}", "newCategory": "+ New category", "noParent": "no parent session", "oneShot": "one-shot", "oneShotBadge": "⚡ one-shot", "openManager": "Open subagent manager", "openUnsupported": "This dsh version does not expose a session navigation API, so the subagent session cannot be opened.", "pause": "⏸ Pause", "pause.named": "Pause {name}", "pauseAll": "⏸ Pause all", "pauseAllActive": "Pause all active continuable subagents", "pauseSubagent": "Pause subagent", "pausing": "Pausing…", "prompt.label": "Prompt: {prompt}", "regexPrompt": "Match regex (e.g. ^audit|review)", "resetFilters": "Reset filters", "scope": "Scope", "scope.allSessions": "All sessions", "scope.allWorkspaces": "All workspaces", "scope.currentSession": "Current session", "scope.currentWorkspace": "Current workspace", "scope.custom": "Custom scope", "scopeAria": "Scope", "searchPlaceholder": "Search names, titles, or workspaces; type id: to search Session IDs", "select.named": "Select {name}", "selectAll": "Select all", "selectHoursPrompt": "Select subagents from how many hours back?", "selectOld": "Select N hours ago", "session.currentDot": "Current session · {name}", "session.currentParen": "Current session ({name})", "session.currentWorkspaceDot": "Current workspace · {name}", "session.named": "Session · {name}", "showActiveFloat": "Show active float", "showDetails": "Show details", "showHidden": "Show hidden", "sort": "Sort", "sort.current": "Sort · {name}", "sort.name": "name", "sort.optionName": "Sort: name", "sort.optionRecent": "Sort: recent activity", "sort.optionType": "Sort: type", "sort.recent": "recent activity", "sort.type": "type", "statsLine": "in {input} / out {output} · cache hit {cacheHit}% · turns {turns} · steps {steps}", "subagentBg": "Subagent background color", "subagentBgDarkTitle": "Subagent background color in dark theme", "subagentBgLightTitle": "Subagent background color in light theme", "summary.showing": "Showing {shown}/{total}", "tab.all": "All", "tab.audit": "audit", "tab.implement": "implement", "tab.other": "Other", "tab.planning": "planning", "tab.test": "test", "thinking": "thinking…", "toolCall": "Tool call", "type": "type", "typeLoading": "type loading…", "uncategorized": "uncategorized", "unhide": "Unhide", "unhideSelectedTitle": "Unhide selected subagents", "unhideShort": "👁 Unhide", "unknown": "unknown", "unknownError": "unknown error", "unknownWorkspace": "Unknown workspace", "workspace.named": "Workspace · {name}"}
233
+ const zh={"activeFloat.title": "活跃子代理 · {count}", "age.dAgo": "{d} 天前", "age.hmAgo": "{h} 小时 {m} 分钟前", "age.mAgo": "{m} 分钟前", "age.sAgo": "{s} 秒前", "batch": "批量操作", "batch.delete": "批量删除 ({count})", "batch.hide": "批量隐藏 ({count})", "batchDeleteFailed": "批量删除失败:", "batchDeleteRequestFailed": "批量删除请求失败:", "batchUnhide": "批量显示", "callTool": "⚙ 调用工具 ", "categoryNamePrompt": "分类名称", "chip.count": "子代理 {active}/{total}", "clear": "清空", "clearSearch": "清空搜索", "collapseFilters": "⚙ 折叠 ▴", "collapseFiltersFull": "折叠筛选与配置", "command": "命令", "command.named": "⌘ {name}", "confirm.deleteCategory": "确认删除分类“{name}”?", "confirm.deleteMany": "确认永久删除选中的 {count} 个子代理?删除后不可恢复!", "confirm.deleteOne": "确认永久删除子代理“{name}”?删除后不可恢复!", "confirm.deleteRunning": "子代理“{name}”正在运行中,删除将强制终止它。确认继续?", "confirm.pauseNamed": "确认暂停子代理“{name}”?", "confirm.pauseSelected": "确认暂停选中的 {count} 个子代理?", "confirmHideAll": "确认隐藏当前筛选出的全部子代理?", "contextInjection": "上下文注入 · {name}", "continuable": "可继续", "dark": "深色", "delete.named": "删除 {name}", "deleteAll": "一键删除全部", "deleteCategory.named": "删除分类“{name}”", "deleteFailed": "删除失败:", "deleteForever": "永久删除该子代理", "deleteRequestFailed": "删除请求失败:", "deleteTrash": "🗑 删除", "done": "完成", "elapsed.hm": "{h}时{m}分", "elapsed.ms": "{m}分{s}秒", "elapsed.s": "{s}秒", "empty": "没有符合条件的子代理。", "expandFilters": "⚙ 展开筛选 ▾", "expandFiltersFull": "展开筛选与配置", "filterSort": "筛选排序", "group.active": "活跃子代理", "group.allResults": "全部结果", "group.other": "其他", "group.otherSessions": "其他会话", "grouping": "分组", "grouping.byCategory": "按分类", "grouping.bySession": "按会话", "grouping.byType": "按类型", "grouping.byWorkspace": "按工作区", "grouping.current": "分组 · {name}", "grouping.none": "不分组", "grouping.optionCategory": "分组:按分类", "grouping.optionNone": "分组:不分组", "grouping.optionSession": "分组:按会话", "grouping.optionType": "分组:按类型", "grouping.optionWorkspace": "分组:按工作区", "head.summary": "当前会话 {session} 个 · 当前工作区 {workspace} 个 · 活跃 {active} 个", "hidden": "已隐藏", "hide": "隐藏", "hideActiveFloat": "隐藏活跃子代理浮窗", "hideAll": "一键全部隐藏", "hideLongInactive": "隐藏长期未活跃", "hideNote": "隐藏仅在列表不显示,不删除会话", "hideOneShot": "隐藏一次性", "hideSelectedTitle": "将选中的子代理隐藏", "hideShort": "⊘ 隐藏", "hideTitle": "隐藏(仅在列表隐藏,不删除会话)", "lastActivity": "最近活动:{time}", "light": "浅色", "liveOutput": "实时输出", "liveOutputPrefix": "实时输出:", "loadHistoryTitle": "加载该子代理的历史最新消息", "loadLatest": "📥 加载最新消息", "loadMore": "加载下一页(剩余 {remaining} 个)", "loading": "⏳ 加载中...", "managerTitle": "子代理管理", "mode.label": "类型:{mode}", "model.label": "模型:{model}", "modelUnknown": "模型未知", "name": "名字", "newAgent": "新子代理:{name}", "newCategory": "+ 新建分类", "noParent": "无父会话", "oneShot": "一次性", "oneShotBadge": "⚡ 一次性", "openInSidebar": "在侧边栏打开", "openInSidebar.named": "在侧边栏打开 {name}", "openInSidebarFailed": "无法在侧边栏打开该子代理会话。", "openInSidebarUnavailable": "该条目没有可用的子代理地址,无法在侧边栏打开", "openManager": "打开子代理管理", "openUnsupported": "当前 dsh 版本不支持打开子代理会话(缺少可用的会话导航接口)。", "pause": "⏸ 暂停", "pause.named": "暂停 {name}", "pauseAll": "⏸ 一键暂停", "pauseAllActive": "一键暂停所有活跃可继续子代理", "pauseSubagent": "暂停子代理", "pausing": "暂停中", "prompt.label": "提示词:{prompt}", "regexPrompt": "匹配正则(例如:^审计|review)", "resetFilters": "重置筛选", "scope": "范围", "scope.allSessions": "全部会话", "scope.allWorkspaces": "全部工作区", "scope.currentSession": "当前会话", "scope.currentWorkspace": "当前工作区", "scope.custom": "自定义范围", "scopeAria": "显示范围", "searchPlaceholder": "搜索名称、标题或工作区;输入 id: 搜索 Session ID", "select.named": "选择 {name}", "selectAll": "全选", "selectHoursPrompt": "选择多少小时前的子代理?", "selectOld": "选择 N 小时前", "session.currentDot": "当前会话 · {name}", "session.currentParen": "当前会话 ({name})", "session.currentWorkspaceDot": "当前工作区 · {name}", "session.named": "会话 · {name}", "showActiveFloat": "显示活跃浮窗", "showDetails": "显示详情", "showHidden": "显示已隐藏", "sort": "排序", "sort.current": "排序 · {name}", "sort.name": "名字", "sort.optionName": "排序:名字", "sort.optionRecent": "排序:最近活跃", "sort.optionType": "排序:类型", "sort.recent": "最近活跃", "sort.type": "类型", "stats.f.billed": "计费输入 Billed input: {value}", "stats.f.cacheRead": "缓存读取 Cache read: {value}", "stats.f.cacheWrite": "缓存写入 Cache write: {value}", "stats.f.hit": "缓存命中 Cache hit: {value}", "stats.f.llm": "模型耗时 LLM time: {value}", "stats.f.output": "输出 Output: {value}", "stats.f.steps": "步数 Steps: {value}", "stats.f.tool": "工具耗时 Tool time: {value}", "stats.f.total": "总量 Total: {value}", "stats.f.tps": "输出速度 TPS: {value}", "stats.f.ttft": "首字延迟 TTFT: {value}", "stats.f.turns": "轮数 Turns: {value}", "stats.f.uncached": "未缓存输入 Uncached input: {value}", "stats.hit": "命中 {percent}%", "stats.steps": "{steps} 步", "stats.titleLine": "子代理用量 Subagent usage", "stats.tps": "{tps} tps", "stats.turns": "{turns} 轮", "stats.usage": "↑ {input} (未缓存 {uncached}) / ↓ {output}", "subagentBg": "子代理背景色", "subagentBgDarkTitle": "深色主题下的子代理背景色", "subagentBgLightTitle": "浅色主题下的子代理背景色", "summary.showing": "显示 {shown}/{total} 个", "tab.all": "全部", "tab.audit": "审计", "tab.implement": "实现", "tab.other": "其他", "tab.planning": "规划", "tab.test": "测试", "thinking": "思考中…", "toolCall": "工具调用", "type": "类型", "typeLoading": "类型待加载", "uncategorized": "未分类", "unhide": "取消隐藏", "unhideSelectedTitle": "取消隐藏选中的子代理", "unhideShort": "👁 显示", "unknown": "未知", "unknownError": "未知错误", "unknownWorkspace": "未知工作区", "workspace.named": "工作区 · {name}"}
234
+ const en={"activeFloat.title": "Active subagents · {count}", "age.dAgo": "{d}d ago", "age.hmAgo": "{h}h {m}m ago", "age.mAgo": "{m}m ago", "age.sAgo": "{s}s ago", "batch": "Batch", "batch.delete": "Delete ({count})", "batch.hide": "Hide ({count})", "batchDeleteFailed": "Batch delete failed: ", "batchDeleteRequestFailed": "Batch delete request failed: ", "batchUnhide": "Unhide", "callTool": "⚙ Call tool ", "categoryNamePrompt": "Category name", "chip.count": "Subagents {active}/{total}", "clear": "Clear", "clearSearch": "Clear search", "collapseFilters": "⚙ Collapse ▴", "collapseFiltersFull": "Collapse filters & options", "command": "Command", "command.named": "⌘ {name}", "confirm.deleteCategory": "Delete category \"{name}\"?", "confirm.deleteMany": "Permanently delete the selected {count} subagents? This cannot be undone!", "confirm.deleteOne": "Permanently delete subagent \"{name}\"? This cannot be undone!", "confirm.deleteRunning": "Subagent \"{name}\" is still running; deleting will force-terminate it. Continue?", "confirm.pauseNamed": "Pause subagent \"{name}\"?", "confirm.pauseSelected": "Pause the selected {count} subagents?", "confirmHideAll": "Hide ALL currently filtered subagents?", "contextInjection": "Context injection · {name}", "continuable": "continuable", "dark": "Dark", "delete.named": "Delete {name}", "deleteAll": "Delete all", "deleteCategory.named": "Delete category \"{name}\"", "deleteFailed": "Delete failed: ", "deleteForever": "Permanently delete this subagent", "deleteRequestFailed": "Delete request failed: ", "deleteTrash": "🗑 Delete", "done": "Done", "elapsed.hm": "{h}h{m}m", "elapsed.ms": "{m}m{s}s", "elapsed.s": "{s}s", "empty": "No subagents match the current filters.", "expandFilters": "⚙ Expand ▾", "expandFiltersFull": "Expand filters & options", "filterSort": "Filter & sort", "group.active": "Active subagents", "group.allResults": "All results", "group.other": "Other", "group.otherSessions": "Other sessions", "grouping": "Grouping", "grouping.byCategory": "by category", "grouping.bySession": "by session", "grouping.byType": "by type", "grouping.byWorkspace": "by workspace", "grouping.current": "Group · {name}", "grouping.none": "none", "grouping.optionCategory": "Group: by category", "grouping.optionNone": "Group: none", "grouping.optionSession": "Group: by session", "grouping.optionType": "Group: by type", "grouping.optionWorkspace": "Group: by workspace", "head.summary": "Current session {session} · Current workspace {workspace} · Active {active}", "hidden": "hidden", "hide": "Hide", "hideActiveFloat": "Hide the active-subagents float", "hideAll": "Hide all", "hideLongInactive": "Hide long-inactive", "hideNote": "Hiding only removes it from the list; the session is not deleted", "hideOneShot": "Hide one-shot", "hideSelectedTitle": "Hide the selected subagents", "hideShort": "⊘ Hide", "hideTitle": "Hide (hides from the list only; the session is not deleted)", "lastActivity": "Last activity: {time}", "light": "Light", "liveOutput": "Live output", "liveOutputPrefix": "Live output: ", "loadHistoryTitle": "Load the latest messages from this subagent’s history", "loadLatest": "📥 Load latest messages", "loadMore": "Load next page ({remaining} left)", "loading": "⏳ Loading...", "managerTitle": "Subagent manager", "mode.label": "Type: {mode}", "model.label": "Model: {model}", "modelUnknown": "model unknown", "name": "name", "newAgent": "New subagent: {name}", "newCategory": "+ New category", "noParent": "no parent session", "oneShot": "one-shot", "oneShotBadge": "⚡ one-shot", "openInSidebar": "Open in the sidebar", "openInSidebar.named": "Open {name} in the sidebar", "openInSidebarFailed": "Unable to open this subagent session in the sidebar.", "openInSidebarUnavailable": "This entry has no subagent address, so it cannot open in the sidebar", "openManager": "Open subagent manager", "openUnsupported": "This dsh version does not expose a session navigation API, so the subagent session cannot be opened.", "pause": "⏸ Pause", "pause.named": "Pause {name}", "pauseAll": "⏸ Pause all", "pauseAllActive": "Pause all active continuable subagents", "pauseSubagent": "Pause subagent", "pausing": "Pausing…", "prompt.label": "Prompt: {prompt}", "regexPrompt": "Match regex (e.g. ^audit|review)", "resetFilters": "Reset filters", "scope": "Scope", "scope.allSessions": "All sessions", "scope.allWorkspaces": "All workspaces", "scope.currentSession": "Current session", "scope.currentWorkspace": "Current workspace", "scope.custom": "Custom scope", "scopeAria": "Scope", "searchPlaceholder": "Search names, titles, or workspaces; type id: to search Session IDs", "select.named": "Select {name}", "selectAll": "Select all", "selectHoursPrompt": "Select subagents from how many hours back?", "selectOld": "Select N hours ago", "session.currentDot": "Current session · {name}", "session.currentParen": "Current session ({name})", "session.currentWorkspaceDot": "Current workspace · {name}", "session.named": "Session · {name}", "showActiveFloat": "Show active float", "showDetails": "Show details", "showHidden": "Show hidden", "sort": "Sort", "sort.current": "Sort · {name}", "sort.name": "name", "sort.optionName": "Sort: name", "sort.optionRecent": "Sort: recent activity", "sort.optionType": "Sort: type", "sort.recent": "recent activity", "sort.type": "type", "stats.f.billed": "Billed input 计费输入: {value}", "stats.f.cacheRead": "Cache read 缓存读取: {value}", "stats.f.cacheWrite": "Cache write 缓存写入: {value}", "stats.f.hit": "Cache hit 缓存命中: {value}", "stats.f.llm": "LLM time 模型耗时: {value}", "stats.f.output": "Output 输出: {value}", "stats.f.steps": "Steps 步数: {value}", "stats.f.tool": "Tool time 工具耗时: {value}", "stats.f.total": "Total 总量: {value}", "stats.f.tps": "TPS 输出速度: {value}", "stats.f.ttft": "TTFT 首字延迟: {value}", "stats.f.turns": "Turns 轮数: {value}", "stats.f.uncached": "Uncached input 未缓存输入: {value}", "stats.hit": "Hit {percent}%", "stats.steps": "{steps} stps", "stats.titleLine": "Subagent usage 子代理用量", "stats.tps": "{tps} tps", "stats.turns": "{turns} rnds", "stats.usage": "↑ {input} (miss {uncached}) / ↓ {output}", "subagentBg": "Subagent background color", "subagentBgDarkTitle": "Subagent background color in dark theme", "subagentBgLightTitle": "Subagent background color in light theme", "summary.showing": "Showing {shown}/{total}", "tab.all": "All", "tab.audit": "audit", "tab.implement": "implement", "tab.other": "Other", "tab.planning": "planning", "tab.test": "test", "thinking": "thinking…", "toolCall": "Tool call", "type": "type", "typeLoading": "type loading…", "uncategorized": "uncategorized", "unhide": "Unhide", "unhideSelectedTitle": "Unhide selected subagents", "unhideShort": "👁 Unhide", "unknown": "unknown", "unknownError": "unknown error", "unknownWorkspace": "Unknown workspace", "workspace.named": "Workspace · {name}"}
155
235
 
156
236
  const uiWorkspaceOf=ctx=>{try{const ws=ctx.get?.('uiWorkspace');return typeof ws?.openSession==='function'?ws:null}catch{return null}}
157
- function apply(ctx){sessionsRt=ctx.sessions;ctx.effect(()=>ctx.locale.register(NS,{zh,en}),'subagent-workspace-ui: dictionaries');const actions={openChild:a=>{if(typeof ctx.sessions?.openSubagent==='function'){ctx.sessions.openSubagent(a);return true}const ws=uiWorkspaceOf(ctx);if(ws){ws.openSession(a);return true}if(a?.childSessionId)return actions.openSession(a.childSessionId);return false},openSession:id=>{if(typeof ctx.sessions?.open==='function'){ctx.sessions.open(id);return true}const ws=uiWorkspaceOf(ctx);if(ws){ws.openSession(id);return true}return false},refresh:p=>ctx.sessions.refreshSubagents(p),setCatalogOpen:(p,o)=>ctx.sessions.setSubagentCatalogOpen(p,o)},face=()=>actions;ctx.slots.inject('conversation.session.header.actions',()=>ctx.slots.register({name:'conversation.session.header.actions',id:'subagent-workspace-manager',order:100,locale:NS,inject:face},Manager))}
237
+ const serviceOf=(ctx,name)=>{try{const value=ctx.get?.(name);return value??null}catch(error){console.warn('subagent-workspace-ui: service probe failed for',name,error);return null}}
238
+ const LineageShadow=({displayTitle,lineageSessionId,useSessions,openTitle})=>{
239
+ const isSubagent=typeof useSessions==='function'?useSessions(s=>s?.byId?.[lineageSessionId]?.origin==='subagent'):false
240
+ if(!isSubagent||!displayTitle)return null
241
+ const open=typeof openTitle==='function'?openTitle:null
242
+ return jsx('button',{type:'button',className:open?'dsh-sam-lineage-title':'dsh-sam-lineage-title dsh-sam-lineage-current',disabled:!open,title:displayTitle,onClick:open||undefined,children:displayTitle})
243
+ }
244
+ const SUBAGENT_CHAT_PREFIX='dsh-resource://subagentchat/session/'
245
+ const subagentChatAddressOf=address=>`${SUBAGENT_CHAT_PREFIX}${encodeURIComponent(address.childSessionId)}?${new URLSearchParams({parent:address.parentSessionId,mode:address.mode})}`
246
+ function apply(ctx){
247
+ sessionsRt=ctx.sessions
248
+ ctx.effect(()=>ctx.locale.register(NS,{zh,en}),'subagent-workspace-ui: dictionaries')
249
+ const actions={openChild:a=>{if(typeof ctx.sessions?.openSubagent==='function'){ctx.sessions.openSubagent(a);return true}const ws=uiWorkspaceOf(ctx);if(ws){ws.openSession(a);return true}if(a?.childSessionId)return actions.openSession(a.childSessionId);return false},openSession:id=>{if(typeof ctx.sessions?.open==='function'){ctx.sessions.open(id);return true}const ws=uiWorkspaceOf(ctx);if(ws){ws.openSession(id);return true}return false},refresh:p=>ctx.sessions.refreshSubagents(p),setCatalogOpen:(p,o)=>ctx.sessions.setSubagentCatalogOpen(p,o)}
250
+ const sidebarRight=serviceOf(ctx,'sidebarRight'),tabs=serviceOf(ctx,'sidebarRightTabs'),
251
+ asideAddressOf=(sidebarRight&&typeof sidebarRight.openResource==='function'&&tabs&&typeof tabs.candidates==='function'&&typeof ctx.sessions?.subagentAddress==='function')?row=>{
252
+ try{
253
+ const address=ctx.sessions.subagentAddress(row.id)
254
+ if(!address||!address.parentSessionId||!address.childSessionId||!address.mode)return null
255
+ const value=subagentChatAddressOf(address)
256
+ if(tabs.candidates(value).length===0)return null
257
+ return value
258
+ }catch(error){console.warn('subagent-workspace-ui: unable to resolve a sidebar address',error);return null}
259
+ }:null,
260
+ openAside=asideAddressOf?address=>{
261
+ try{sidebarRight.openResource(address,{preferNewPane:true});return true}catch(error){console.warn('subagent-workspace-ui: unable to open the sidebar resource',address,error);return false}
262
+ }:null,
263
+ face=()=>({...actions,asideAddressOf,openAside})
264
+ ctx.slots.inject('conversation.session.header.actions',()=>ctx.slots.register({name:'conversation.session.header.actions',id:'subagent-workspace-manager',order:100,locale:NS,inject:face},Manager))
265
+ ctx.slots.inject('conversation.session.header.lineage',()=>ctx.slots.register({name:'conversation.session.header.lineage',priority:-1},LineageShadow))
266
+ }
158
267
  return {inject:['sessions','slots','locale'],apply}
159
268
  }
160
269
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-subagent-workspace-ui",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "description": "Searchable workspace subagent manager for DeepSeek Harness Web",
6
6
  "license": "MIT",
@@ -30,6 +30,8 @@
30
30
  "@deepseek-ai/dsh-client-locale",
31
31
  "@deepseek-ai/dsh-client-ui-conversation",
32
32
  "@deepseek-ai/dsh-client-ui-sidebar",
33
+ "@deepseek-ai/dsh-client-ui-sidebar-right",
34
+ "@deepseek-ai/dsh-client-ui-subagent",
33
35
  "@deepseek-ai/dsh-client-ui-workspace"
34
36
  ],
35
37
  "platform": "web"