dsh-subagent-workspace-ui 1.7.0 → 1.9.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
@@ -19,7 +19,10 @@ A Web client plugin that adds a **子代理管理** button to the conversation-h
19
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
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.
21
21
  - Show session IDs beside names, compact metadata, token totals, and creation time in the relative-time tooltip.
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.
22
+ - Active children are grouped at the top in a collapsible section. The panel shows the latest two lines of live output, recent tool calls, context injection, command status, and a gray final snapshot after completion — for **every** running row, not only the selected child, because the plugin retains its own session binding instead of borrowing whatever the main view happens to hold.
23
+ - Ended rows mark how the last turn finished, from the child's own public read-only `subagentTiming.lastTurnCompleted` projection: a normal end is a **hollow green ring**, an abnormal one (stopped/aborted, error, blocked, a token ceiling …) a **solid red dot**, each with a zh/en hover label. A host that does not publish the projection keeps exactly the previous dot — an unknown end is never shown as a normal one — and a running row keeps its original green dot.
24
+ - An ended continuable row offers **`▶ Continue`** next to pause/hide/delete and sends one **localized** continue instruction into the child (Chinese UI `继续`, English UI `continue`) through the session face the host really exposes: `sessions.retain(…)` → `binding.session.prompt([…], 'queue')` where `retain` exists (0.1.6-alpha.2 on, including 0.1.7-rc.1), and the borrowed `sessions.binding` face on 0.1.5-rc.3, which has no `retain`. Pure capability probing, never a version check: a host without such a face renders no button at all, and running and one-shot rows never show it.
25
+ - The filter block (category tabs, scope/session selectors, sorting, grouping, options) opens **collapsed by default**, showing one summary line (`Current workspace · Current session … · All`, then `Sort · recent activity` and `Group · by session`). That summary line is itself the disclosure control — click it, or press Enter/Space (`role=button` / `aria-expanded`) — and the preference is still persisted.
23
26
 
24
27
  ## Screenshot guide
25
28
 
@@ -31,12 +34,12 @@ Both screenshots were taken on the `1.7.0-dev` line (commit `79d9d0f`) against a
31
34
 
32
35
  1. **Header** — panel title, `Current session n · Current workspace n · Active n`, the show-active-float toggle, and the close action.
33
36
  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.
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.
37
+ 3. **Classification row** (once the filter block is expanded) — built-in and custom categories with live counts, custom-category creation and deletion inside the same tab frame.
38
+ 4. **Filter block** — collapsed by default into a single summary line (`Current workspace · Current session … · All`, plus `Sort · recent activity` and `Group · by session`); clicking that summary line expands or collapses the block and Enter/Space do the same (`role=button` / `aria-expanded`). Expanding it reveals the classification row above, the workspace/session/sort/grouping selectors, and the options row: hide one-shot, hide long-inactive, subagent background colour (light/dark), and reset filters. The preference is still persisted.
36
39
  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.
40
+ 6. **Active subagents group** — pinned to the top and collapsible, with `Pause all`; each row carries the status dot (a green dot while running, a hollow green ring or a solid red dot once ended, according to how it ended), the name, the Session ID, the relative activity time, and the `◫` open-in-the-sidebar, `⏸ Pause`, `▶ Continue`, `⊘ Hide` and `🗑 Delete` actions.
38
41
  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.
42
+ 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. While it is shown it keeps every running child it lists live, independently of which child the main view has selected.
40
43
 
41
44
  ## Install in the Web profile
42
45
 
@@ -54,19 +57,21 @@ If you previously disabled `ui-subagent` manually in `$DSH_HOME/profiles/web/cor
54
57
 
55
58
  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.
56
59
 
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.
60
+ 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 a 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`. On hosts with the retain contract (**0.1.6-alpha.2** and on) the plugin first **retains** each running child itself — `sessions.binding(id)` merely borrows a binding somebody else retained, so without retaining, only the child the main view had selected ever streamed. Retention is bounded to 8 children (the float first, then the panel's rendered running rows, most recently active first) and is released as soon as a row stops rendering or stops running, when a surface closes, or when the plugin is disposed; a child beyond the cap, and any host without `retain`, falls back to the borrowed binding and then to the durable summary. Capability detection selects the path (never a version check), so the plugin stays forward compatible. 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
61
 
59
62
  ### Type and model (read-only projections)
60
63
 
61
64
  A child's type and model come from public host projections. The plugin adds no RPC and writes no state:
62
65
 
63
66
  ```text
64
- # type: one reader, two read-only rungs, resolved in this order
65
- ctx.sessions.list.getSnapshot().subagentsByParent[parentId].entries
67
+ # type: one reader, read-only catalog and identity rungs, resolved in this order
68
+ ctx.sessions.list.getSnapshot().subagentsByParent[parentId].entries # dsh ..0.1.6-alpha.2
66
69
  → entry.mode # rung 1: discovered catalog entry (present once that parent's catalog was pulled)
70
+ ctx.sessions.list.getSnapshot().byId[parentId].projectionValues.subagentCatalog # dsh 0.1.7-rc.1..
71
+ → entry.mode # rung 1': the parent's own catalog projection (same direct children, catalog event order)
67
72
  ctx.sessions.list.getSnapshot().byId[childId].projectionValues.subagent
68
73
  → { 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
74
+ → displayed value = rung 1 ?? rung 1' ?? rung 2 # all silent = the existing `typeLoading` text
70
75
 
71
76
  # model: the session projection modelSelection (probed by key; unreadable = the host does not publish it)
72
77
  ctx.sessions.list.getSnapshot().byId[childId].projectionValues.modelSelection
@@ -84,13 +89,15 @@ The display rules are identical on all three surfaces and differ only in density
84
89
 
85
90
  - `reasoningEffort` is appended **only when the host supplies it** (` · high`); no placeholder is rendered otherwise.
86
91
  - 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`.
92
+ - 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. The catalog itself has two generations — `subagentsByParent[parentId].entries` up to **0.1.6-alpha.2**, and the parent session's own `projectionValues.subagentCatalog` from **0.1.7-rc.1** on (with `projectionsBySession[parentId].values.subagentCatalog` as a defensive fallback) — and the legacy source wins whenever a host publishes both, so an older host reads exactly what it read before. 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
93
  - 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
94
  - **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`).
90
95
 
91
96
  ## Compatibility
92
97
 
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:
98
+ v1.8.0 and later support dsh **0.1.5-rc.3**, **0.1.6-alpha.2** and **0.1.7-rc.1** and stay backward compatible with all DeepSeek Harness versions. Those hosts span two API tiers — 0.1.5-rc.3 and 0.1.6-alpha.2 still publish `subagentsByParent`, `refreshSubagents` and `setSubagentCatalogOpen`, while 0.1.7-rc.1 **removed** `sessions.setSubagentCatalogOpen`, **renamed** `refreshSubagents(parentSessionId)` to `refreshProjections(sessionId)`, and **replaced** `SessionListState.subagentsByParent` with the parent session's own `subagentCatalog` projection. Every call site probes for the capability it needs, so both generations work and no version number is ever compared. Opening a subagent session is capability-detected at runtime and degrades in three tiers:
99
+
100
+ A smoke run on **0.1.5-rc.3** shows no degradation on that line: on a fresh instance with one running child the manager opens on the live session with the child's catalog label, `Type: continuable`, the concrete model id, `◫` on the row, the pause/hide/delete actions, the live-output section rendering that child's running `bash` tool, and the usage figures — with no error from this plugin in the console.
94
101
 
95
102
  ```text
96
103
  # dsh 0.1.2-alpha.5 .. 0.1.6-alpha.1: the session controller entry points
@@ -120,10 +127,27 @@ ctx.sessions.subagentAddress → typeof function (per-row address lookup)
120
127
  # with a readable reason instead of throwing.
121
128
  ```
122
129
 
130
+ Both faces are resolved **per row and per click, never once at activation**: dsh **0.1.7-rc.1** registers `sidebarRight`/`sidebarRightTabs` only *after* a plugin's `apply` has run — on **0.1.6-alpha.2** they are already present when `apply` runs — so a probe performed once at activation hides the whole `◫` column on the newer host while leaving the older one untouched.
131
+
123
132
  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
133
 
125
134
  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.
135
+ ## v1.9.0
136
+
137
+ - **Feature**: an ended subagent can be **continued from its own row**. The row action group (`⏸ Pause` / `⊘ Hide` / `🗑 Delete`) gains `▶ Continue`, which sends one **localized** continue instruction into that child (Chinese UI `继续`, English UI `continue`) so it runs again. The implementation is pure capability probing and **never compares a version**: a host with `retain` (0.1.6-alpha.2 on, including 0.1.7-rc.1) goes `sessions.retain(…)` → `binding.session.prompt([{ type: 'text', text: '继续' }], 'queue')` (the English UI passes `'continue'`), while **0.1.5-rc.3** has no `retain` and uses the same face obtained by borrowing `sessions.binding`, which works just as well. A host without that capability **renders no button**; running rows and one-shot rows never show it either; the manager panel itself lives in the parent session's header, so "the parent agent must be alive" is satisfied by construction in normal use (an unavailable parent only logs a console warning instead of becoming an uncaught rejection).
138
+ - **Feature**: the **filter block opens collapsed**. On first open the manager shows a single summary line (`Current workspace · Current session … · All`, plus `Sort · recent activity` and `Group · by session`); clicking that summary line expands or collapses the block, and Enter/Space do the same (`role=button` / `aria-expanded`). The preference is still persisted. A bug falls out with it: with the preference unset the toggle could only collapse and never expand, because `!undefined === true`.
139
+ - **Feature**: an **ended row separates a normal end from an abnormal one**. A normal end is a hollow green ring, an abnormal one (⏸ stopped/aborted, error, blocked, max-tokens …) a solid red dot, each with a zh/en hover label (`正常结束` / `异常结束`). The verdict comes only from the child's own public read-only `subagentTiming.lastTurnCompleted` projection (the host writes it on `turn/end` and removes it on `turn/start`); a host that does not publish the projection **keeps the previous dot**, so an unknown end is never rendered as a normal one. The verdict field itself is projected by the host only from **dsh 0.1.7-alpha.1**: **0.1.5-rc.3** and **0.1.6-alpha.2** publish `{ settledMs, active? }` only, so on those two hosts an ended row keeps the neutral dot and does not distinguish how it ended. Running rows keep their original green dot.
140
+ - **Compatibility**: all three changes are capability-probed and **never version-checked**; v1.9.0 supports dsh **0.1.5-rc.3** / **0.1.6-alpha.2** / **0.1.7-rc.1** exactly as v1.8.0 does (verified on all three hosts; the terminal indicator stays a neutral dot on 0.1.5-rc.3 and 0.1.6-alpha.2 per the boundary above). The only code changes are the row-action alignment (`src/client/styles.ts`) and one corrected comment (`src/client/format.ts`); the rest is the version bump and docs, and `pnpm run check` is green with the bundle freshness in sync.
141
+
142
+ ## v1.8.0
143
+
144
+ - **Fix**: live output only updated for the **currently selected** subagent. `sessions.binding(id)` only *borrows* a binding somebody else retained, and the stock view retains just the session the main view has selected — so every other child had no live region at all. The plugin now **retains** each running child it is showing itself: the float keeps every running child it displays, the panel keeps the running rows it renders, both share a cap of 8 (float first, most recently active first), and each row that stops rendering or stops running, every closed surface and the plugin's disposal releases in pairs. A host without `retain`, and any child beyond the cap, still falls back to the borrowed binding and then to the durable summary. Landing with it: **Pause now works on a row that is not selected** — it previously called into a binding that did not exist and silently did nothing.
145
+ - **Compatibility with dsh 0.1.7-rc.1**: that host **removed** `sessions.setSubagentCatalogOpen`, **renamed** `refreshSubagents(parentSessionId)` to `refreshProjections(sessionId)`, and **replaced** `SessionListState.subagentsByParent[parent]` with the parent session's own `projectionValues.subagentCatalog` projection (the same direct children in catalog event order; entries lost their `kind` discriminator and gained a third `mode: 'unknown'` arm). Un-guarded, the removed method threw out of the manager panel's open effect and the error boundary took the whole header slot down — **opening the manager crashed the title bar**. Every host call is now capability-probed and never version-checked: one reader resolves the catalog from the parent's `subagentCatalog` on 0.1.7-rc.1+ and from `subagentsByParent` up to 0.1.6-alpha.2 (the legacy source wins when a host publishes both, so older hosts read exactly what they read before), `refresh` prefers `refreshProjections` and falls back to `refreshSubagents`, and a missing `setSubagentCatalogOpen` is skipped. An entry whose `mode` is `unknown` keeps its label and yields the mode to the child's own identity projection instead of trusting that arm.
146
+ - **Fix**: on 0.1.7-rc.1 the per-row **open in the sidebar** action (`◫`) disappeared from every row. That host registers `sidebarRight`/`sidebarRightTabs` *after* this plugin's `apply` runs, so the one-time probe at activation judged both absent for good. Both faces are now resolved per row and per click: a host that never publishes them still renders no button (byte-for-byte the previous surface), while an available face whose row address does not validate keeps the existing disabled button and its readable reason.
147
+ - **Docs**: the type/model ladder documents both catalog generations, and the compatibility section records the 0.1.7-rc.1 API changes above.
148
+ - **Tweak**: the active float pins its background at **exactly 95% opacity**. dsh **0.1.7-rc.1** redefined `--dsw-specific-menu` as a translucent glass colour — `#30313680` in the dark theme (alpha `0x80` = 50%) and `#f8f9fa94` in the light one (58%) — where 0.1.6 pointed that same token at the opaque `--dsw-alias-bg-layer-3`, so the float turned see-through on the newer host. It now composites the host's **opaque** surface token at 95% (`color-mix`, with the previous declaration kept ahead of it as the fallback for a host without `color-mix`), which also makes the float's density identical on 0.1.6 and 0.1.7 — no version check, and the tone still comes from the host's own theme tokens.
126
149
 
150
+ Verified on dsh **0.1.6-alpha.2** and **0.1.7-rc.1**: `pnpm run check` green (bundle freshness in sync, 98,439 bytes). On 0.1.7-rc.1 the panel opens on a live session with all 7 of its subagents, rows carrying their catalog labels, `Type: continuable`, model and usage figures, `◫` on every row, and **no console error after the click**. On 0.1.6-alpha.2 the panel object is byte-for-byte identical to the pre-change build, and the same batch of data shows the same unknowns it showed before (a child whose projections the host never published stays `model unknown`, exactly as it does on 0.1.6). The float's background was then measured on a live 0.1.7-rc.1 instance with a running child: it renders `rgb(51,52,54)`, the exact value `#353638` at 95% predicts over the `rgb(21,21,23)` header backdrop behind it, where the previous 50% glass would have rendered `rgb(34,35,38)`; sampling the same float over a backdrop 22 levels lighter (`rgb(43,43,45)`) moved it by at most one level, which is what a 95% surface does and a 50% one cannot (it would have moved 11 levels). The host's own `dsh-client-ui-open-in-app` logs a load-time `inactive context` error on 0.1.7-rc.1; it is unrelated to this plugin and deliberately left alone.
127
151
 
128
152
  ## v1.7.0
129
153
 
package/README.zh.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  面向 DeepSeek Harness Web 的子代理管理插件。插件在会话标题栏提供一个紧凑的 `🧩 子代理 active/total` 入口,用于搜索、筛选、分组、排序、查看和批量归档当前运行时已发现的子代理。
4
4
 
5
- 当前发布版本:**v1.7.0**
5
+ 当前发布版本:**v1.9.0**
6
6
 
7
7
  ## 主要功能
8
8
 
@@ -56,12 +56,12 @@
56
56
 
57
57
  1. **标题栏** —— 面板标题、`当前会话 n 个 · 当前工作区 n 个 · 活跃 n 个`、活跃浮窗开关与关闭按钮。
58
58
  2. **搜索与范围行** —— 名称/标题/工作区搜索,`id: xxx` 专用于 Session ID 搜索;工作区、会话、排序、分组四个选择器同处一行。
59
- 3. **分类行** —— 内置分类与自定义分类(带实时数量),自定义分类的新建与删除都在同一标签框内。
60
- 4. **筛选行** —— 隐藏一次性、隐藏长期未活跃、子代理背景色(浅色/深色)与重置筛选。
59
+ 3. **分类行**(展开筛选块后)—— 内置分类与自定义分类(带实时数量),自定义分类的新建与删除都在同一标签框内。
60
+ 4. **筛选块** —— 默认折叠,只显示一行摘要(`当前工作区 · 当前会话 … · 全部` + `排序 · 最近活跃 分组 · 按会话`);点击该摘要行即可展开/收起,键盘 Enter/Space 同样有效(摘要行带 `role=button` / `aria-expanded`)。展开后才是上面的分类行、范围/会话/排序/分组选择器,以及选项行(隐藏一次性、隐藏长期未活跃、子代理背景色(浅色/深色)、重置筛选);折叠偏好仍然持久化。
61
61
  5. **汇总行** —— `显示 n/m 个`、显示详情、显示已隐藏,以及批量操作入口。
62
- 6. **活跃子代理分组** —— 置顶且可折叠,带「一键暂停」;每行包含活跃圆点、名称、Session ID、相对活动时间,以及 `◫` 在侧边栏打开、`⏸ 暂停`、`⊘ 隐藏`、`🗑 删除`。
63
- 7. **详情区** —— 直接来自宿主只读投影的 `类型:… · 模型:…`,以及官方口径的用量行 `↑ 计费输入 (未缓存…) / ↓ 输出 · 命中 n% · n tps · n 轮 · n 步`;运行中的子代理还会显示最新的实时输出,已完成的保留最终快照。
64
- 8. **活跃浮窗** —— 当前会话里运行中的子代理以紧凑浮窗常驻,每行带实时输出、用量行与暂停按钮;面板关闭且存在运行中子代理时自动出现。
62
+ 6. **活跃子代理分组** —— 置顶且可折叠,带「一键暂停」;每行包含状态点(运行中为绿点,已结束按结束方式显示空心绿环或实心红点)、名称、Session ID、相对活动时间,以及 `◫` 在侧边栏打开、`⏸ 暂停`、`▶ 继续`、`⊘ 隐藏`、`🗑 删除`。
63
+ 7. **详情区** —— 直接来自宿主只读投影的 `类型:… · 模型:…`,以及官方口径的用量行 `↑ 计费输入 (未缓存…) / ↓ 输出 · 命中 n% · n tps · n 轮 · n 步`;运行中的子代理都会显示最新的实时输出(不只当前选中的那一个),已完成的保留最终快照。
64
+ 8. **活跃浮窗** —— 当前会话里运行中的子代理以紧凑浮窗常驻,每行带实时输出、用量行与暂停按钮;面板关闭且存在运行中子代理时自动出现。浮窗显示期间会为其中每个运行中的子代理各自保留实时会话,与主视图当前选中哪一个无关。
65
65
 
66
66
  ### 分类标签
67
67
 
@@ -108,6 +108,7 @@
108
108
  - **浮窗单项暂停**:浮窗内每个正在运行的可继续子代理卡片均有“⏸ 暂停”按钮,点击确认后暂停该子代理。
109
109
  - **管理面板单项暂停**:列表和活跃分组中的每个运行中可继续子代理均有“⏸ 暂停”按钮。
110
110
  - **管理面板一键暂停**:“活跃子代理”折叠分组头部右侧提供“⏸ 一键暂停”按钮,支持一键暂停全部活跃子代理。
111
+ - **继续已结束的子代理**:已结束(非运行中)的可继续子代理行在操作区显示“▶ 继续”,点击后向该子代理发送一条**本地化**的继续指令(中文界面「继续」、英文界面 “continue”),让它接着跑。运行中与一次性子代理的行不显示该按钮;宿主没有该能力时**按钮不渲染**(纯能力探测,从不比较版本号)。管理器面板本身就在父会话 header 里,所以“父会话 agent 必须存活”这一前提在正常使用下天然满足;父会话不可用时只在控制台告警,不会把异常抛给用户。
111
112
 
112
113
  隐藏是插件本地状态,只在列表不显示子代理,不会删除 DSH 会话或工作区文件。默认情况下:
113
114
 
@@ -151,12 +152,24 @@
151
152
 
152
153
  实时输出具有金属光泽扫光动效;子代理结束后保留最后显示快照,并变为灰色。输出区域最多显示两行,避免持续滚动导致内容难以阅读。
153
154
 
155
+ **每个运行中的子代理都有自己的实时流(dsh 0.1.6-alpha.2 起)**:宿主 `sessions.binding(id)` 的契约是「借用已被保留的绑定,不创建保留」,而官方客户端里唯一保留会话的是主会话视图——它只保留**当前选中**的那一个。因此插件改为自己成为保留者:`sessions.retain(target, { source: 'subagentWorkspaceUi' })` 拿到 `SessionReference`,用 `reference.binding` 取 `session` / `eventSource`,不再依赖「是否被选中」。
156
+
157
+ 保留是有界且成对释放的:
158
+
159
+ - **浮窗常驻**:浮窗显示期间,对其中每个运行中的子代理各保留一个引用。
160
+ - **面板仅可见行**:管理面板只对当前筛选/分组后**实际渲染出来**的运行中行保留,打开面板不会去加载全部历史子代理。
161
+ - **上限 8**:浮窗优先,其次按最近活动优先;超出上限的运行中行按快照显示(仍有用量等持久信息)。
162
+ - **成对释放**:行不再渲染、子代理转为非运行态、浮窗/面板关闭或插件卸载时调用 `release()`;重复释放幂等。
163
+
154
164
  **兼容两个 API 代际(自动探测)**:
155
165
 
156
- - dsh **0.1.2-alpha.2**:使用 `binding.eventSource`(原始 `SessionEvent` 事件流)推导实时输出。
166
+ - dsh **0.1.6-alpha.2** 起:自己 `retain`(`reference.binding.eventSource` 原始 `SessionEvent` 事件流);宿主未提供 `retain` 时回退借用式 `binding(id)`。
167
+ - dsh **0.1.2-alpha.2**:`binding.eventSource`(原始 `SessionEvent` 事件流)推导实时输出。
157
168
  - dsh **0.1.1-rc.2** 及更早:回退 `session.getSnapshot().chat.legacy`(对话快照)路径。
158
169
 
159
- 按能力探测自动切换,向前兼容,老版本行为不变。
170
+ 按能力探测自动切换(不判版本号),向前兼容,老版本行为不变;两条路径都拿不到绑定时,界面回退到持久化摘要。
171
+
172
+ 已结束的行还会用状态点区分结束方式:**正常结束为空心绿环,异常结束(⏸ 停止/aborted、error、blocked、max-tokens 等)为实心红点**,hover 显示「正常结束 / 异常结束」文字(zh+en)。判定只读子代理自身的公共只读投影 `subagentTiming.lastTurnCompleted`(宿主仅在 `turn/end` 写入、`turn/start` 删除);宿主不提供该投影时**保持原样**,绝不把“未知”显示成“正常”,运行中的行保持原绿点。
160
173
 
161
174
  ## 界面说明
162
175
 
@@ -166,7 +179,7 @@
166
179
  2. **搜索框**:普通文本搜索;使用 `id: xxx` 查询 Session ID。
167
180
  3. **范围和排序行**:工作区、会话、排序、分组四个紧凑控件。
168
181
  4. **分类标签行**:分类名称和数量。
169
- 5. **筛选行**:一次性、长期未活跃、已归档和重置筛选。
182
+ 5. **筛选块**:默认折叠为一行摘要(范围 · 会话 · 分类 | 排序 · 分组),点击摘要行或按 Enter/Space 展开;展开后包含分类标签、筛选选项(隐藏一次性、隐藏长期未活跃、子代理背景色、重置筛选)。
170
183
  6. **结果统计**:显示当前结果数量和批量操作入口。
171
184
  7. **结果列表**:活跃分组、会话/工作区分组、子代理卡片和实时状态。
172
185
  8. **行内 `◫` 按钮**:在右侧边栏打开该子代理,主对话不跳转(见「在右侧边栏打开子代理」一节)。
@@ -199,15 +212,25 @@ http://127.0.0.1:3080
199
212
 
200
213
  ## 数据边界与兼容性
201
214
 
215
+ v1.8.0 及以后版本支持 dsh **0.1.5-rc.3**、**0.1.6-alpha.2** 与 **0.1.7-rc.1**,并对所有 DeepSeek Harness 版本保持向后兼容。这些宿主分属两代接口——0.1.5-rc.3 与 0.1.6-alpha.2 仍发布 `subagentsByParent`、`refreshSubagents` 与 `setSubagentCatalogOpen`,而 0.1.7-rc.1 删除了 `sessions.setSubagentCatalogOpen`、把 `refreshSubagents(parentSessionId)` 改名为 `refreshProjections(sessionId)`、并把 `SessionListState.subagentsByParent` 换成父会话自身的 `subagentCatalog` 投影。插件对每一项都做能力探测,因此两代宿主各自走可用路径,**从不比较版本号**。
216
+
217
+ **0.1.5-rc.3** 上实测无降级:全新实例 + 一个运行中子代理时,管理器在实时会话上正常打开,行显示目录标签、`类型:可继续`、具体模型 id、`◫`、暂停/隐藏/删除、渲染该子代理正在运行的 `bash` 工具的实时输出区,以及用量数字——控制台没有来自本插件的错误。
218
+
202
219
  插件只管理当前 DSH Web 客户端运行时已经发现的子代理目录,不伪造不存在的历史数据。首次加载以 40 条为一页;普通分页可以继续加载,批量时间选择最多扩展到 1000 条。
203
220
 
204
221
  公共 `SessionSummary` 不保证提供原始提示词或全部历史日志,因此插件不查询、不显示提示词。**类型与模型**改由宿主的公开投影提供,见下一节;实时输出按能力探测自动切换两种公开接口:
205
222
 
206
223
  ```text
207
- # dsh 0.1.2-alpha.2(新 API):绑定的事件源
224
+ # dsh 0.1.6-alpha.2 起(retain 契约):插件自己创建并持有绑定
225
+ sessions.retain({ parentSessionId, childSessionId, mode }, { source: 'subagentWorkspaceUi' })
226
+ → reference.binding.eventSource # 引用存续期间始终可用
227
+ → getSnapshot().entries # 原始 SessionEvent:assistant/chunk、tool/call、tool/result…
228
+ → release() # 行不再渲染 / 停止 / 浮窗·面板关闭 / 插件卸载
229
+
230
+ # 宿主没有 retain(能力探测):回退到借用他人保留的绑定(0.1.2-alpha.2 新 API)
208
231
  sessions.binding(childId).eventSource
209
232
  → open()
210
- → getSnapshot().entries # 原始 SessionEvent:assistant/chunk、tool/call、tool/result…
233
+ → getSnapshot().entries
211
234
 
212
235
  # dsh 0.1.1-rc.2 及更早(旧 API):对话快照
213
236
  sessions.binding(childId).session
@@ -215,19 +238,21 @@ sessions.binding(childId).session
215
238
  → session.getSnapshot().chat.legacy
216
239
  ```
217
240
 
218
- 如果在当前宿主拿不到对应的实时数据,插件只能显示持久化的会话摘要和统计信息。
241
+ 如果在当前宿主拿不到对应的实时数据(没有 `retain`、也借不到绑定,或该行超出 8 个保留上限),插件只显示持久化的会话摘要和统计信息。
219
242
 
220
243
  ### 类型与模型(只读投影)
221
244
 
222
245
  子代理的「类型」与「模型 provider/id」来自宿主的公开投影,不新增任何 RPC、也不写入任何状态:
223
246
 
224
247
  ```text
225
- # 类型:同一个取值函数、两级只读来源,按此顺序回退
226
- ctx.sessions.list.getSnapshot().subagentsByParent[parentId].entries
248
+ # 类型:同一个取值函数,只读的目录来源与身份来源,按此顺序回退
249
+ ctx.sessions.list.getSnapshot().subagentsByParent[parentId].entries # dsh ..0.1.6-alpha.2
227
250
  → entry.mode # 第 1 级:已发现的目录条目(该父会话的目录被拉取后才存在)
251
+ ctx.sessions.list.getSnapshot().byId[parentId].projectionValues.subagentCatalog # dsh 0.1.7-rc.1..
252
+ → entry.mode # 第 1' 级:父会话自身的目录投影(同一批直接子代理,目录事件顺序)
228
253
  ctx.sessions.list.getSnapshot().byId[childId].projectionValues.subagent
229
254
  → { mode, label, seq } | null # 第 2 级:子会话自身的身份投影(随实时控制流下发)
230
- → 显示值 = 第 1 级 ?? 第 2 级 # 两级都拿不到 = 沿用既有 `typeLoading` 兜底文案
255
+ → 显示值 = 第 1 级 ?? 第 1' 级 ?? 第 2 级 # 全部拿不到 = 沿用既有 `typeLoading` 兜底文案
231
256
 
232
257
  # 模型:会话投影 modelSelection(按 key 能力探测,读不到即视为宿主不提供)
233
258
  ctx.sessions.list.getSnapshot().byId[childId].projectionValues.modelSelection
@@ -262,7 +287,7 @@ ctx.get('uiWorkspace').openSession({ parentSessionId, childSessionId, mode } | s
262
287
  # 两者都不存在:提示当前 dsh 版本缺少可用的会话导航接口
263
288
  ```
264
289
 
265
- `uiWorkspace` 通过 `ctx.get('uiWorkspace')` 读取,而不是必填注入,因此未注册该服务的宿主(**0.1.2-alpha.5** 之前的全部版本)仍能正常加载并继续走会话控制器路径;而移除了 `openSubagent`/`open` 的 **0.1.6-alpha.2** 则走工作区服务。**探测顺序按「参数形态」而不是版本号决定**:`sessions.openSubagent` 在所有带它的宿主上都吃 address 对象,而 `uiWorkspace.openSession` 直到 **0.1.6-alpha.2** 才接受 `SessionTarget`——在 **0.1.5-alpha.2 … 0.1.6-alpha.1** 上它是 `openSession(sessionId)`,内部走 `sessions.open(id)`,传入对象会抛错。因此先试会话控制器一级、把工作区服务作为兜底。控制器路径下优先使用 `{ parentSessionId, childSessionId, mode }` 精确地址,仅在缺少 mode/child 时才降级为普通会话导航,因为 `openSubagent` 会拒绝非健康目录子项的地址。0.1.2 系列能力探测路径(实时输出走 `binding.eventSource`、对话标签切换走 slot `actions`)仍为首选分支,**0.1.1-rc.2** legacy 回退路径保持不变。本版本支持 **dsh 0.1.6-alpha.2**,并向下兼容所有 DeepSeek Harness 版本。
290
+ `uiWorkspace` 通过 `ctx.get('uiWorkspace')` 读取,而不是必填注入,因此未注册该服务的宿主(**0.1.2-alpha.5** 之前的全部版本)仍能正常加载并继续走会话控制器路径;而移除了 `openSubagent`/`open` 的 **0.1.6-alpha.2** 则走工作区服务。**探测顺序按「参数形态」而不是版本号决定**:`sessions.openSubagent` 在所有带它的宿主上都吃 address 对象,而 `uiWorkspace.openSession` 直到 **0.1.6-alpha.2** 才接受 `SessionTarget`——在 **0.1.5-alpha.2 … 0.1.6-alpha.1** 上它是 `openSession(sessionId)`,内部走 `sessions.open(id)`,传入对象会抛错。因此先试会话控制器一级、把工作区服务作为兜底。控制器路径下优先使用 `{ parentSessionId, childSessionId, mode }` 精确地址,仅在缺少 mode/child 时才降级为普通会话导航,因为 `openSubagent` 会拒绝非健康目录子项的地址。0.1.2 系列能力探测路径(实时输出走 `binding.eventSource`、对话标签切换走 slot `actions`)仍为首选分支,**0.1.1-rc.2** legacy 回退路径保持不变。本版本与 **v1.8.0** 一样支持 dsh **0.1.5-rc.3**、**0.1.6-alpha.2** 与 **0.1.7-rc.1**,并向下兼容所有 DeepSeek Harness 版本。
266
291
 
267
292
  归档、分类和最近使用顺序保存在浏览器本地 `localStorage` 中,不会写入 DSH 会话日志。
268
293
 
@@ -282,6 +307,8 @@ ctx.sessions.subagentAddress → 是函数(按行取地址)
282
307
  # 验证为空 → 该行按钮渲染为禁用态并给出可读说明,绝不抛异常给用户。
283
308
  ```
284
309
 
310
+ 两个能力面**按行、按次解析,绝不在激活时只探测一次**:dsh **0.1.7-rc.1** 在本插件 `apply` **之后**才注册 `sidebarRight`/`sidebarRightTabs`(**0.1.6-alpha.2** 在 `apply` 时已就绪),因此激活时的一次性探测会让新宿主上的整列 `◫` 消失,而旧宿主毫无异样。
311
+
285
312
  要点:
286
313
 
287
314
  - **默认点击不变**:点条目本身仍然把子代理打开到主对话区(与 v1.5.0 一致);新按钮 `stopPropagation`,既不触发默认跳转,也不会误触批量选择。
@@ -319,6 +346,23 @@ DSH_PLUGIN_DIR=.worktrees/x ./test.sh # 冒烟其它 checkout 的产物
319
346
  - UI 本地化(zh/en)由 [@Marcuss2](https://github.com/Marcuss2) 在 [PR #1](https://github.com/miuzel/dsh-subagent-ui/pull/1) 中贡献,特此致谢!
320
347
  - 子代理永久删除、会话生命周期清理及快照刷新机制的设计参考并致谢开源项目:[@heiheiha798/dsh-plugin-subagent-delete](https://github.com/heiheiha798/dsh-plugin-subagent-delete)。
321
348
 
349
+ ## v1.9.0 发布说明
350
+
351
+ - **特性:在管理器中让已结束的子代理继续运行**。行的操作区(`⏸ 暂停` / `⊘ 隐藏` / `🗑 删除` 一组)新增“▶ 继续”,点击后向该子代理发送一条**本地化**的继续指令(中文界面「继续」、英文界面 “continue”),让它接着跑。实现是纯能力探测、**从不比较版本号**:有 `retain` 的宿主(0.1.6-alpha.2 起,含 0.1.7-rc.1)走 `sessions.retain(...)` → `binding.session.prompt([{ type: 'text', text: '继续' }], 'queue')`(英文界面传入 `'continue'`),**0.1.5-rc.3** 没有 `retain`,走借用 `sessions.binding` 得到的同一个 face,同样可用。宿主没有该能力时**按钮不渲染**;运行中与一次性子代理的行也不显示该按钮;管理器面板本身就在父会话 header 里,因此“父会话 agent 必须存活”在正常使用下天然满足(父会话不可用时只在控制台告警,不会变成未捕获的异常)。
352
+ - **特性:筛选块默认折叠**。管理器筛选块首次打开即为折叠态,只显示一行摘要(`当前工作区 · 当前会话 … · 全部` + `排序 · 最近活跃 分组 · 按会话`);点击该摘要行即可展开/收起,键盘 Enter/Space 同样有效(摘要行带 `role=button` / `aria-expanded`)。折叠偏好仍持久化。顺带修掉一个 bug:此前在偏好未设置时,切换按钮因 `!undefined === true` 只能折叠、无法展开。
353
+ - **特性:已结束子代理区分正常/异常结束**。正常结束显示**空心绿环**,异常结束(⏸ 停止/aborted、error、blocked、max-tokens 等)显示**实心红点**,hover 显示「正常结束 / 异常结束」文字(zh+en)。数据只来自子代理自身的公共只读投影 `subagentTiming.lastTurnCompleted`(宿主仅在 `turn/end` 写入、`turn/start` 删除);宿主不提供该投影时**保持原样**,绝不把“未知”显示成“正常”。该判定字段自 **dsh 0.1.7-alpha.1** 起才由宿主投影:**0.1.5-rc.3** 与 **0.1.6-alpha.2** 只发布 `{ settledMs, active? }`,因此那两台宿主上已结束行保持中性状态点、不区分结束方式(有据才下结论,绝不伪造判据)。运行中的行保持原绿点。
354
+ - **兼容性**:以上三项都只依赖能力探测、**从不比较版本号**;v1.9.0 与 v1.8.0 一样支持 dsh **0.1.5-rc.3** / **0.1.6-alpha.2** / **0.1.7-rc.1**(已在三台上实测;终态标记在 0.1.5-rc.3 / 0.1.6-alpha.2 上按上述边界保持中性点)。本版代码改动只有两处——行操作按钮对齐(`src/client/styles.ts`)与一处失实注释订正(`src/client/format.ts`)——其余为版本号与文档:`pnpm run check` 全绿(bundle 新鲜度一致)。
355
+
356
+ ## v1.8.0 发布说明
357
+
358
+ - **修复:只有当前被选中的子代理才更新实时输出**。`sessions.binding(id)` 只是**借用**别人已经保留的绑定,而官方视图只保留主视图当前选中的那一个会话——于是其余子代理根本没有实时区域。现改为插件**自己成为保留者**:浮窗保留它显示的每个运行中子代理、面板保留它渲染的运行中行,两者共用上限 8(浮窗优先、最近活跃优先),行停止渲染或停止运行、界面关闭、插件卸载时成对释放;宿主没有 `retain`、以及超出上限的行,仍回落到借用式绑定、再回落到持久化摘要。随之落地的一项修复:**未选中行的「暂停」现在真正生效**——此前它调用的是一个并不存在的绑定,属于静默空操作。
359
+ - **兼容 dsh 0.1.7-rc.1**:该宿主**删除**了 `sessions.setSubagentCatalogOpen`、把 `refreshSubagents(parentSessionId)` **改名**为 `refreshProjections(sessionId)`、并把 `SessionListState.subagentsByParent[parent]` **换成**父会话自身的 `projectionValues.subagentCatalog` 投影(同一批直接子代理,目录事件顺序;条目去掉了 `kind` 判别字段,并多出一个 `mode: 'unknown'` 取值)。在缺少防护的旧实现里,被删除的方法从管理器面板的打开副作用里抛出,错误边界随即带走整个标题栏 slot——**点开管理器会让标题栏直接崩掉**。现在所有宿主调用一律能力探测、**从不比较版本号**:同一个取值函数在 0.1.7-rc.1 及以上读父会话的 `subagentCatalog`、在 0.1.6-alpha.2 及以前读 `subagentsByParent`(宿主两者都发布时旧来源优先,因此旧宿主读到的与改动前逐字相同),刷新优先 `refreshProjections`、回落 `refreshSubagents`,`setSubagentCatalogOpen` 缺失则跳过;`mode` 为 `unknown` 的条目保留 label,并把类型让给子会话自身的身份投影,而不是直接采信该取值。
360
+ - **修复:0.1.7-rc.1 上每行的 `◫`「在侧边栏打开」整列消失**。该宿主在本插件 `apply` **之后**才注册 `sidebarRight`/`sidebarRightTabs`,激活时的一次性探测便把两者永久判为不存在。现改为**按行、按次**解析:从不发布这两个能力的宿主依旧完全不渲染按钮(与改动前逐字相同),而能力可用但该行地址校验不通过时,仍保留既有的禁用按钮与可读原因。
361
+ - **文档**:类型/模型阶梯补上两代目录来源;兼容性小节记录上述 0.1.7-rc.1 接口变化。
362
+ - **微调:活跃浮窗背景固定为 95% 不透明度**。dsh **0.1.7-rc.1** 把 `--dsw-specific-menu` 改成了带透明度的「玻璃」色——深色主题 `#30313680`(alpha `0x80` = 50%)、浅色 `#f8f9fa94`(58%)——而 0.1.6 把同一个令牌指向不透明的 `--dsw-alias-bg-layer-3`,于是浮窗在新宿主上变得半透明。现在浮窗改用宿主**不透明**的表面色令牌按**恰好 95%** 合成(`color-mix`,并把旧声明保留在其前,作为不具备 `color-mix` 的宿主的回落),顺带让浮窗在 0.1.6 与 0.1.7 上的观感一致——不判断版本号,色调仍来自宿主自己的主题令牌。
363
+
364
+ 已在 dsh **0.1.6-alpha.2** 与 **0.1.7-rc.1** 上验证:`pnpm run check` 全绿(bundle 新鲜度一致,98,439 字节)。0.1.7-rc.1 上打开一个真实运行中的会话,面板列出全部 7 个子代理,行名回到目录标签、`Type: continuable`、模型与用量齐全、每行都有 `◫`,且**点击后控制台没有任何错误**;0.1.6-alpha.2 上面板对象与改动前逐字节相同,同一批数据仍显示与改动前相同的未知项(宿主从未发布过投影的子代理依旧是 `model unknown`,与 0.1.6 上的表现完全一致)。浮窗背景随后在一个真实运行中的 0.1.7-rc.1 实例上做了像素测量:它渲染为 `rgb(51,52,54)`,正是 `#353638` 按 95% 合成、叠在其身后的 `rgb(21,21,23)` 标题栏背景上的精确预测值,而此前的 50% 玻璃色在该处应渲染成 `rgb(34,35,38)`;把同一个浮窗放到亮 22 级的背景(`rgb(43,43,45)`)上,它最多只变化 1 级——这正是 95% 表面的行为,50% 表面不可能如此(它会变化 11 级)。0.1.7-rc.1 宿主自带的 `dsh-client-ui-open-in-app` 会在加载期报一条 `inactive context`,与本插件无关,本次刻意不动。
365
+
322
366
  ## v1.7.0 发布说明
323
367
 
324
368
  - **修复:`◫`「在侧边栏打开」按钮的点击面积远小于 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 祖先而非几何。
package/lib/client.js CHANGED
@@ -10,6 +10,8 @@ const css = `.dsh-sam-head-sub{display:flex;align-items:center;justify-content:f
10
10
  .dsh-sam-collapsed-left{display:inline-flex;align-items:center;gap:6px;min-width:0;overflow:hidden;text-overflow:ellipsis;flex:1}
11
11
  .dsh-sam-collapsed-right{display:inline-flex;align-items:center;gap:8px;flex:none;margin-left:auto}
12
12
  .dsh-sam-collapsed-tag{color:var(--dsw-alias-label-secondary);font-weight:500;overflow:hidden;text-overflow:ellipsis}
13
+ .dsh-sam-collapsed-info{cursor:pointer}
14
+ .dsh-sam-collapsed-info:focus-visible{outline:2px solid var(--dsw-alias-border-l2);outline-offset:1px}
13
15
  .dsh-sam-summary-items{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}
14
16
  .dsh-sam-summary-hidden-toggle{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--dsw-alias-label-secondary);cursor:pointer;user-select:none}
15
17
  .dsh-sam-summary-hidden-toggle input{margin:0;width:13px;height:13px;cursor:pointer}.dsh-sam-row-hidden{opacity:0.42;background:rgba(0,0,0,0.08)!important}
@@ -20,7 +22,7 @@ body[data-ds-dark-theme] .dsh-sam-row-hidden{background:rgba(255,255,255,0.03)!i
20
22
  .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
23
  .dsh-sam-search-clear:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}
22
24
  .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-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)}}
25
+ .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));background:color-mix(in srgb,var(--dsw-alias-bg-layer-3,var(--dsw-alias-bg-layer-2)) 95%,transparent);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-continue-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-continue-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.dsh-sam-continue-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-row-actions .dsh-sam-stop-btn,.dsh-sam-row-actions .dsh-sam-continue-btn{display:inline-flex;align-items:center;gap:2px;align-self:start;min-width:max-content;padding:0 4px;font-size:12px;line-height:16px}.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
26
  .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
27
  .dsh-sam-side-btn::after{content:"";position:absolute;left:6px;right:0;top:4px;bottom:4px;border-radius:5px;pointer-events:none}
26
28
  .dsh-sam-side-btn:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
@@ -30,6 +32,8 @@ body[data-ds-dark-theme] .dsh-sam-row-hidden{background:rgba(255,255,255,0.03)!i
30
32
  .dsh-sam-side-btn-compact::after{left:4px;right:3px;top:4px;bottom:4px}
31
33
  .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
34
  .dsh-sam-lineage-current{color:var(--dsw-alias-label-primary);cursor:default;font-weight:500}
35
+ .dsh-sam-dot.dsh-sam-dot-normal{background:transparent;box-shadow:inset 0 0 0 2px var(--dsw-alias-state-success-primary,#42bd7b)}
36
+ .dsh-sam-dot.dsh-sam-dot-abnormal{background:var(--dsw-alias-state-error-primary,#ef4444);box-shadow:0 0 0 3px rgba(236,19,19,.14)}
33
37
  `
34
38
 
35
39
  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) }
@@ -96,28 +100,82 @@ statsLine=(tr,row)=>{const u=usageStats(tr,row),parts=[tr('stats.usage',{input:f
96
100
  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')}
97
101
  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
102
  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}
103
+ const knownMode=mode=>mode==='one-shot'||mode==='continuable'?mode:undefined
104
+ const catalogEntriesOf=(state,parentId)=>{const legacy=state?.subagentsByParent?.[parentId]?.entries;if(Array.isArray(legacy))return legacy.filter(e=>e.kind==='child').map(e=>({id:e.id,mode:knownMode(e.mode),label:e.label}));const projected=state?.byId?.[parentId]?.projectionValues?.subagentCatalog??state?.projectionsBySession?.[parentId]?.values?.subagentCatalog;return Array.isArray(projected)?projected.filter(e=>e&&e.id).map(e=>({id:e.id,mode:knownMode(e.mode),label:e.label})):[]}
105
+ const catalogEntryOf=(state,parentId,childId)=>catalogEntriesOf(state,parentId).find(e=>e.id===childId)
99
106
  const childModeOf=(s,catalog)=>catalog?.mode??projectionMode(s)
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)}
107
+ const modeMap=state=>{const parents=new Set();Object.keys(state?.subagentsByParent||{}).forEach(id=>parents.add(id));Object.keys(state?.byId||{}).forEach(id=>{if(state?.byId?.[id]?.projectionValues?.subagentCatalog)parents.add(id)});Object.keys(state?.projectionsBySession||{}).forEach(id=>{if(state?.projectionsBySession?.[id]?.values?.subagentCatalog)parents.add(id)});const map={};parents.forEach(parentId=>{catalogEntriesOf(state,parentId).forEach(entry=>{if(map[entry.id]===undefined)map[entry.id]=entry})});return map}, 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
108
  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
109
  const modelLabel=(tr,row)=>{const text=modelText(row);return text?tr('model.label',{model:text}):tr('modelUnknown')}
103
110
  const modelCompact=(tr,row)=>modelText(row)||tr('modelUnknown')
104
111
  const modeModelLine=(tr,row)=>`${tr('mode.label',{mode:modeLabel(tr,row?.mode)})} · ${modelLabel(tr,row)}`
105
112
  const modeModelCompact=(tr,row)=>`${modeLabel(tr,row?.mode)} · ${modelCompact(tr,row)}`
113
+ const terminalOf=(row)=>{const timing=row?.projectionValues?.subagentTiming,completed=timing?.lastTurnCompleted;if(completed!==true&&completed!==false)return undefined;if(timing?.active!==undefined)return undefined;return completed?'normal':'abnormal'}
114
+ const terminalClass=(row)=>{if(row?.running)return '';const ended=terminalOf(row);return ended===undefined?'':` dsh-sam-dot-${ended}`}
115
+ const terminalTitle=(tr,row)=>{if(row?.running)return undefined;const ended=terminalOf(row);return ended===undefined?undefined:ended==='normal'?tr('end.normalNamed',{name:row?.name}):tr('end.abnormalNamed',{name:row?.name})}
106
116
  const asideButton=(options)=>{
107
117
  const addressOf=options.addressOf
108
118
  if(typeof addressOf!=='function')return null
109
119
  const tr=options.tr
110
120
  let address=null
111
121
  try{address=addressOf(options.row)}catch(error){console.warn('subagent-workspace-ui: sidebar address lookup failed',error);address=null}
122
+ if(address===undefined)return null
112
123
  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
124
  }
114
125
 
115
126
  let sessionsRt=null
116
127
  const NOOP=()=>()=>{}
117
128
 
129
+ const RETAIN_SOURCE='subagentWorkspaceUi'
130
+ const RETAIN_LIMIT=8
131
+ const retainOrder=['float','panel']
132
+ const retainWants=new Map()
133
+ const retainEntries=new Map()
134
+ const retainListeners=new Set()
135
+ const retainSignature=(want)=>`${want.parentId||''}|${want.mode||''}`
136
+ const retainTarget=(want)=>want.parentId&&want.mode?{parentSessionId:want.parentId,childSessionId:want.childId,mode:want.mode}:want.childId
137
+ const retainNotify=()=>{retainListeners.forEach(listener=>{try{listener()}catch(error){console.warn('subagent-workspace-ui: retain listener failed',error)}})}
138
+ const retainDispose=(reference)=>{if(!reference)return;try{if(typeof reference.release==='function')reference.release();else if(typeof reference.dispose==='function')reference.dispose()}catch(error){console.warn('subagent-workspace-ui: unable to release a retained session',error)}}
139
+ const retainBindingOf=(reference)=>{if(!reference)return null;try{const binding=reference.binding;return binding&&(binding.session||binding.eventSource)?binding:null}catch{return null}}
140
+ const retainDrop=(childId)=>{const entry=retainEntries.get(childId);if(!entry)return false;retainEntries.delete(childId);retainDispose(entry.reference);return true}
141
+ const retainAcquire=(want)=>{const runtime=sessionsRt;if(!runtime||typeof runtime.retain!=='function')return null;let reference=null;try{reference=runtime.retain(retainTarget(want),{source:RETAIN_SOURCE})}catch(error){console.warn('subagent-workspace-ui: unable to retain a live session',want.childId,error);return null}const binding=retainBindingOf(reference);if(!binding){retainDispose(reference);return null}return {reference,binding,signature:retainSignature(want)}}
142
+ const retainSync=()=>{const ranked=[];for(const owner of retainOrder){const group=retainWants.get(owner);if(!group)continue;const list=[...group.values()].filter(want=>want&&want.childId);list.sort((a,b)=>(b.updatedAt||0)-(a.updatedAt||0));for(const want of list)ranked.push(want)}const kept=[],seen=new Set();for(const want of ranked){if(kept.length>=RETAIN_LIMIT)break;if(seen.has(want.childId))continue;seen.add(want.childId);kept.push(want)}let changed=false;for(const childId of [...retainEntries.keys()]){const want=kept.find(item=>item.childId===childId);if(!want||retainSignature(want)!==retainEntries.get(childId)?.signature){if(retainDrop(childId))changed=true}}for(const want of kept){if(retainEntries.has(want.childId))continue;const entry=retainAcquire(want);if(entry){retainEntries.set(want.childId,entry);changed=true}}if(changed)retainNotify()}
143
+ const retainDeclare=(owner,wants)=>{const group=new Map();for(const want of wants)if(want&&want.childId)group.set(want.childId,want);retainWants.set(owner,group);retainSync()}
144
+ const retainClear=(owner)=>{if(retainWants.delete(owner))retainSync()}
145
+ const retainReleaseAll=()=>{retainWants.clear();let changed=false;for(const childId of [...retainEntries.keys()])if(retainDrop(childId))changed=true;if(changed)retainNotify()}
146
+ const liveBindingFor=(childId)=>{const entry=retainEntries.get(childId);if(entry){const own=retainBindingOf(entry.reference);if(own)return own}try{return sessionsRt?.binding?.(childId)||null}catch{return null}}
147
+ const retainOwned=(childId)=>retainEntries.has(childId)
148
+ const retainSettled=async(childId)=>{const entry=retainEntries.get(childId);if(!entry)return;try{await entry.reference.ready}catch{}}
149
+ const retainSubscribe=(listener)=>{retainListeners.add(listener);return()=>{retainListeners.delete(listener)}}
150
+ const continueFaceFor=(rowId,fallbackIds)=>{
151
+ const owned=retainOwned(rowId)?liveBindingFor(rowId)?.session:null
152
+ if(owned&&typeof owned.prompt==='function')return owned
153
+ for(const id of fallbackIds){
154
+ if(!id||id===rowId)continue
155
+ const face=liveBindingFor(id)?.session
156
+ if(face&&typeof face.prompt==='function')return face
157
+ }
158
+ return null
159
+ }
160
+ const acquirePromptFace=async(childId,address)=>{
161
+ const runtime=sessionsRt
162
+ let reference=null
163
+ if(typeof runtime?.retain==='function'){
164
+ try{reference=runtime.retain(address&&address.mode?address:childId,{source:RETAIN_SOURCE})}catch(error){console.warn('subagent-workspace-ui: unable to retain a session for the continue instruction',childId,error);return null}
165
+ try{if(reference&&typeof reference.ready?.then==='function')await reference.ready}catch(error){console.warn('subagent-workspace-ui: the retained session never became ready',childId,error)}
166
+ const face=retainBindingOf(reference)?.session||null
167
+ if(!face||typeof face.prompt!=='function'){retainDispose(reference);return null}
168
+ return {face,release:()=>retainDispose(reference)}
169
+ }
170
+ const face=liveBindingFor(childId)?.session||null
171
+ if(!face||typeof face.prompt!=='function')return null
172
+ return {face,release:()=>{}}
173
+ }
174
+
118
175
  function LiveOutput({t:tr,parentId,childId,running,prefix=true,autoLoad=true,onLoad,live=true}){
119
- const [loading,setLoading]=React.useState(false),[,bump]=React.useState(0),[lastText,setLastText]=React.useState(''),wantLive=live&&(running||autoLoad),binding=React.useMemo(()=>{if(!wantLive)return null;try{return sessionsRt?.binding?.(childId)||null}catch{return null}},[childId,wantLive]),session=binding?.session||null,feed=binding?.eventSource||null
120
- React.useEffect(()=>{if(!binding)return;let alive=true,timer=null,scheduled=false;const notify=()=>{if(!alive||scheduled)return;scheduled=true;timer=setTimeout(()=>{scheduled=false;timer=null;if(alive)bump(v=>v+1)},100)};const setup=async()=>{try{if(parentId){const entries=sessionsRt?.list?.getSnapshot?.().subagentsByParent?.[parentId]?.entries||[],entry=entries.find(e=>e.kind==='child'&&e.id===childId);if(entry)session?.configureSubagent?.({parentSessionId:parentId,childSessionId:childId,mode:entry.mode})}await session?.open?.()}catch{}finally{if(alive){setLoading(false);bump(v=>v+1)}}};setup();const source=feed||session,unsub=source?.subscribe?.(notify)||NOOP();return()=>{alive=false;if(timer)clearTimeout(timer);unsub()}},[binding,session,feed,parentId,childId])
176
+ const [loading,setLoading]=React.useState(false),[,bump]=React.useState(0),[retainTick,setRetainTick]=React.useState(0),[lastText,setLastText]=React.useState(''),wantLive=live&&(running||autoLoad),binding=React.useMemo(()=>wantLive?liveBindingFor(childId):null,[childId,wantLive,retainTick]),session=binding?.session||null,feed=binding?.eventSource||null
177
+ React.useEffect(()=>{if(!binding)return;let alive=true,timer=null,scheduled=false;const notify=()=>{if(!alive||scheduled)return;scheduled=true;timer=setTimeout(()=>{scheduled=false;timer=null;if(alive)bump(v=>v+1)},100)};const setup=async()=>{try{if(retainOwned(childId)){await retainSettled(childId)}else{if(parentId){const entry=catalogEntryOf(sessionsRt?.list?.getSnapshot?.(),parentId,childId);if(entry?.mode)session?.configureSubagent?.({parentSessionId:parentId,childSessionId:childId,mode:entry.mode})}await session?.open?.()}}catch{}finally{if(alive){setLoading(false);bump(v=>v+1)}}};setup();const source=feed||session,unsub=source?.subscribe?.(notify)||NOOP();return()=>{alive=false;if(timer)clearTimeout(timer);unsub()}},[binding,session,feed,parentId,childId])
178
+ React.useEffect(()=>retainSubscribe(()=>setRetainTick(v=>v+1)),[])
121
179
  let text='',thinking=false;if(feed){const win=feed.getSnapshot?.();if(win&&win.entries){const out=liveFromEvents(tr,win.entries,running);thinking=!!out.thinking;const parts=[];if(out.activity.length)parts.push(out.activity.join('\n'));if(running&&out.streamText&&!out.thinking)parts.push(out.streamText);text=parts.length?parts.join('\n'):out.finalText}}else{const snap=session?.getSnapshot?.(),chat=snap?.chat,blocks=chat?.legacy?.partial?.blocks||[],runningCalls=chat?.legacy?.runningCalls||[],nodes=chat?.legacy?.nodes||[];const activity=[];runningCalls.slice(-2).forEach(c=>activity.push(`▶ ${c.name||tr('toolCall')}${c.argsRaw?` · ${toolDetail(c.argsRaw)}`:''}`));if(!activity.length)nodes.slice(-8).filter(n=>n.kind==='context'||n.kind==='tool-result'||n.kind==='command').slice(-2).forEach(n=>{if(n.kind==='context')activity.push(tr('contextInjection',{name:`${n.provenance?.label||n.form||'context'}`}));else if(n.kind==='tool-result')activity.push(`${n.isError?'✖':'✓'} ${n.call?.name||tr('toolCall')}${n.call?.argsRaw?` · ${toolDetail(n.call.argsRaw)}`:''}`);else activity.push(tr('command.named',{name:`${n.name||tr('command')}`}))});let streamText='';for(let i=blocks.length-1;i>=0;i--){const b=blocks[i];if((b.kind==='text'||b.kind==='reasoning')&&b.text){const lines=b.text.split('\n').map(x=>x.trim()).filter(Boolean);if(lines.length){streamText=(b.kind==='reasoning'?'💭 ':'')+lines.slice(-2).join('\n');break}}}if(runningCalls.length)text=activity.join('\n');else if(running&&streamText)text=streamText;else if(activity.length)text=activity.join('\n');else for(let i=blocks.length-1;i>=0;i--){const b=blocks[i];if((b.kind==='text'||b.kind==='reasoning')&&b.text){const lines=b.text.split('\n').map(x=>x.trim()).filter(Boolean);if(lines.length){text=(b.kind==='reasoning'?'💭 ':'')+lines.slice(-2).join('\n');break}}else if(b.kind==='tool-call'&&b.name){text=tr('callTool')+b.name;break}}}
122
180
  React.useEffect(()=>{if(text)setLastText(text)},[text])
123
181
  if(!wantLive){return jsx('button',{type:'button',className:'dsh-sam-load-live-btn',onClick:e=>{e.stopPropagation();setLoading(true);onLoad?.()},title:tr('loadHistoryTitle'),children:loading?tr('loading'):tr('loadLatest')})}
@@ -129,7 +187,7 @@ const elapsed=(tr,stamp)=>{const seconds=Math.max(0,Math.floor((Date.now()-(stam
129
187
 
130
188
  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}}
131
189
 
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))]})}
190
+ 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)},[]);React.useEffect(()=>{retainDeclare('float',rows.filter(r=>r.running).map(r=>({childId:r.id,parentId:r.parentId,mode:r.mode,updatedAt:r.updatedAt})))},[rows]);React.useEffect(()=>()=>retainClear('float'),[]);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))]})}
133
191
 
134
192
  let chatViewPinGen=0
135
193
  function pinChatViewTab(sessionId){
@@ -151,12 +209,15 @@ function pinChatViewTab(sessionId){
151
209
  setTimeout(tryPin,0)
152
210
  }
153
211
  function Manager({t:tr,useSessions,openChild,openSession,refresh,setCatalogOpen,sessionId,actions,asideAddressOf,openAside}){
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)
212
+ const state=useSessions(s=>s,(a,b)=>a?.byId===b?.byId&&a?.subagentsByParent===b?.subagentsByParent&&a?.projectionsBySession===b?.projectionsBySession&&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),[continuingIds,setContinuingIds]=React.useState(new Set),[manualLoadedIds,setManualLoadedIds]=React.useState(new Set),runningSeen=React.useRef(false),runningIdsSeen=React.useRef(new Set),noticeTimers=React.useRef(new Map)
155
213
  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
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])
214
+ const filterCollapsed=prefs.filterCollapsed!==false
215
+ const modes=React.useMemo(()=>modeMap(state),[state]),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])
157
216
  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])
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})}}
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})}}
217
+ 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=liveBindingFor(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){refresh(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})}}
218
+ 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=liveBindingFor(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){refresh(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})}}
219
+ const fireAndForgetContinue=pending=>{if(pending&&typeof pending.catch==='function')pending.catch(error=>console.warn('subagent-workspace-ui: unable to continue the subagent',error))},
220
+ continueSubagent=async row=>{if(row.running||row.mode==='one-shot'||continuingIds.has(row.id))return;setContinuingIds(prev=>new Set(prev).add(row.id));try{const address=row.parentId&&row.mode?{parentSessionId:row.parentId,childSessionId:row.id,mode:row.mode}:null,held=await acquirePromptFace(row.id,address);if(!held){console.warn('subagent-workspace-ui: no session face carrying a prompt is reachable for this subagent',row.id);return}try{if(address)held.face.configureSubagent?.(address);const result=await held.face.prompt([{type:'text',text:tr('continuePrompt')}],'queue');if(result&&result.ok===false){const code=result.error?.code||'';if(code==='subagent/parent-unavailable')console.warn('subagent-workspace-ui: the parent session is not live, so the subagent cannot be continued',row.parentId,row.id);else console.warn('subagent-workspace-ui: the host refused the continue instruction',row.id,code||result.error);return}if(row.parentId)refresh(row.parentId)}finally{held.release()}}catch(e){console.warn('Unable to continue subagent',row.id,e)}finally{setContinuingIds(prev=>{const next=new Set(prev);next.delete(row.id);return next})}}
160
221
 
161
222
  const deleteSubagent=async row=>{
162
223
  if(row.running){
@@ -171,7 +232,7 @@ function Manager({t:tr,useSessions,openChild,openSession,refresh,setCatalogOpen,
171
232
  })
172
233
  const data=await resp.json()
173
234
  if(data.ok){
174
- if(row.parentId){sessionsRt?.refreshSubagents?.(row.parentId)}
235
+ if(row.parentId){refresh(row.parentId)}
175
236
  sessionsRt?.refresh?.()
176
237
  setPrefs(p=>({
177
238
  ...p,
@@ -198,7 +259,7 @@ function Manager({t:tr,useSessions,openChild,openSession,refresh,setCatalogOpen,
198
259
  const data=await resp.json()
199
260
  if(data.ok){
200
261
  const parents=new Set(items.map(x=>x.parentSessionId).filter(Boolean))
201
- parents.forEach(pid=>sessionsRt?.refreshSubagents?.(pid))
262
+ parents.forEach(pid=>refresh(pid))
202
263
  sessionsRt?.refresh?.()
203
264
  setPrefs(p=>({
204
265
  ...p,
@@ -221,17 +282,19 @@ function Manager({t:tr,useSessions,openChild,openSession,refresh,setCatalogOpen,
221
282
  currentGroupName=grouping==='session'?tr('grouping.bySession'):grouping==='workspace'?tr('grouping.byWorkspace'):grouping==='category'?tr('grouping.byCategory'):grouping==='type'?tr('grouping.byType'):tr('grouping.none')
222
283
 
223
284
  const tabCounts=React.useMemo(()=>{if(!open)return {};const candidates=deferredSubagentRows.filter(s=>(!workspaceKey||s.parentCwd===workspaceKey)&&(selectedSession==='all'||s.parentId===selectedSession)&&(prefs.showArchived||!archived.has(s.id))&&(!prefs.hideOneShot||s.mode!=='one-shot')&&(!prefs.hideOld||s.running||Date.now()-s.updatedAt<=(prefs.oldDays||30)*DAY)),counts={};for(const t of tabs){if(t.id==='all')counts[t.id]=candidates.length;else if(t.regex==='__OTHER__')counts[t.id]=candidates.filter(s=>!tabs.some(x=>!['all','other','filtered'].includes(x.id)&&x.regex&&(()=>{try{return new RegExp(x.regex,'i').test(s.name)}catch{return false}})())).length;else counts[t.id]=candidates.filter(s=>{try{return t.regex&&new RegExp(t.regex,'i').test(s.name)}catch{return false}}).length}return counts},[open,deferredSubagentRows,workspaceKey,selectedSession,prefs,tabs]),rows=allRows.slice(0,limit),currentSessionRows=subagentRows.filter(r=>r.parentId===currentId&&(prefs.showArchived||!archived.has(r.id))&&(!prefs.hideOneShot||r.mode!=='one-shot')),active=currentSessionRows.filter(r=>r.running).length,currentCount=currentSessionRows.length,liveCap=Math.max(0,prefs.liveCap??3),runningLiveIds=liveCap>0?new Set(rows.filter(r=>r.running).slice(0,liveCap).map(r=>r.id)):null
285
+ const panelLiveKey=prefs.showDetails===false?'':rows.filter(r=>r.running).map(r=>`${r.id}:${r.updatedAt}`).join(','),panelLiveWants=React.useMemo(()=>panelLiveKey?rows.filter(r=>r.running).map(r=>({childId:r.id,parentId:r.parentId,mode:r.mode,updatedAt:r.updatedAt})):[],[panelLiveKey])
286
+ React.useEffect(()=>{retainDeclare('panel',panelLiveWants)},[panelLiveWants]);React.useEffect(()=>()=>retainClear('panel'),[])
224
287
  const groups=React.useMemo(()=>{const out={};for(const row of rows){const parent=row.parentId?state.byId[row.parentId]:undefined,sameSession=row.parentId===currentId,sameWorkspace=currentCwd&&parent?.cwd===currentCwd;let bucket=row.running?tr('group.active'):grouping==='session'?`${workspace(tr,parent||row)} · ${title(parent||current)}`:grouping==='type'?modeLabel(tr,row.mode):grouping==='category'?(()=>{const hit=tabs.find(t=>t.id!=='filtered'&&t.id!=='all'&&t.regex&&(()=>{try{return new RegExp(t.regex,'i').test(row.name)}catch{return false}})());return hit?nameOf(hit):tr('group.other')})():grouping==='workspace'?workspace(tr,parent||row):grouping==='none'?tr('group.allResults'):sameSession?tr('scope.currentSession'):sameWorkspace?tr('session.currentWorkspaceDot',{name:workspace(tr,parent||row)}):(parent?`${workspace(tr,parent)} · ${title(parent)}`:tr('group.otherSessions'));(out[bucket]||=[]).push(row)}return out},[rows,grouping,state.byId,sessionId,state.current,currentCwd,tr])
225
288
  React.useEffect(()=>{localStorage.setItem(key,JSON.stringify(prefs))},[prefs]);React.useEffect(()=>{if(!open)return;const ps=[...new Set(rows.map(r=>r.parentId).filter(Boolean))];ps.forEach(p=>{setCatalogOpen(p,true);refresh(p)});return()=>ps.forEach(p=>setCatalogOpen(p,false))},[open,limit,grouping,sort,query])
226
289
  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'))}}
227
290
  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])
228
291
  const activeGroupContinuableRows=groups[tr('group.active')]?.filter(r=>r.mode!=='one-shot')||[]
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))})]})})]})
292
+ 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:'×'})]}),!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')}`}),!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))]}),!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:filterCollapsed?tr('expandFiltersFull'):tr('collapseFiltersFull'),onClick:()=>setPrefs(p=>({...p,filterCollapsed:!(p.filterCollapsed!==false)})),children:filterCollapsed?tr('expandFilters'):tr('collapseFilters')})]})]}),!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))}),!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))})]})]}),!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')})]}),filterCollapsed&&jsxs('div',{className:'dsh-sam-collapsed-info',role:'button',tabIndex:0,'aria-expanded':false,title:tr('expandFiltersFull'),onClick:e=>{if(e.target instanceof HTMLElement&&e.target.closest('button,select,input,textarea,a'))return;setPrefs(p=>({...p,filterCollapsed:false}))},onKeyDown:e=>{if(e.target!==e.currentTarget)return;if(e.key==='Enter'||e.key===' '){e.preventDefault();setPrefs(p=>({...p,filterCollapsed:false}))}},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':''}${terminalClass(row)}`,title:terminalTitle(tr,row),'aria-label':terminalTitle(tr,row)})]}),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')}),!row.running&&row.mode!=='one-shot'&&continueFaceFor(row.id,[currentId,sessionId])&&jsx('button',{type:'button',className:'dsh-sam-continue-btn',disabled:continuingIds.has(row.id),onClick:e=>{e.stopPropagation();fireAndForgetContinue(continueSubagent(row))},'aria-label':tr('continue.named',{name:row.name}),'title':tr('continueSubagent'),children:continuingIds.has(row.id)?tr('continuePending'):tr('continue')}),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))})]})})]})
230
293
  }
231
294
 
232
295
  const NS='subagent-workspace-ui'
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}"}
296
+ 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": "可继续", "continue": "▶ 继续", "continue.named": "继续 {name}", "continuePending": "继续中", "continuePrompt": "继续", "continueSubagent": "向该子代理发送一条继续指令", "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": "没有符合条件的子代理。", "end.abnormal": "异常结束", "end.abnormalNamed": "异常结束 · {name}", "end.normal": "正常结束", "end.normalNamed": "正常结束 · {name}", "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}"}
297
+ 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", "continue": "▶ Continue", "continue.named": "Continue {name}", "continuePending": "Continuing…", "continuePrompt": "continue", "continueSubagent": "Send this subagent a continue instruction", "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.", "end.abnormal": "Ended abnormally", "end.abnormalNamed": "Ended abnormally · {name}", "end.normal": "Ended normally", "end.normalNamed": "Ended normally · {name}", "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}"}
235
298
 
236
299
  const uiWorkspaceOf=ctx=>{try{const ws=ctx.get?.('uiWorkspace');return typeof ws?.openSession==='function'?ws:null}catch{return null}}
237
300
  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}}
@@ -246,20 +309,27 @@ const subagentChatAddressOf=address=>`${SUBAGENT_CHAT_PREFIX}${encodeURIComponen
246
309
  function apply(ctx){
247
310
  sessionsRt=ctx.sessions
248
311
  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=>{
312
+ ctx.effect(()=>()=>retainReleaseAll(),'subagent-workspace-ui: retained live bindings')
313
+ const fireAndForget=pending=>{if(pending&&typeof pending.catch==='function')pending.catch(error=>console.warn('subagent-workspace-ui: unable to refresh session projections',error))},
314
+ refreshCatalog=p=>{if(typeof ctx.sessions?.refreshProjections==='function'){fireAndForget(ctx.sessions.refreshProjections(p));return}if(typeof ctx.sessions?.refreshSubagents==='function')fireAndForget(ctx.sessions.refreshSubagents(p))}
315
+ 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:refreshCatalog,setCatalogOpen:(p,o)=>{if(typeof ctx.sessions?.setSubagentCatalogOpen==='function')ctx.sessions.setSubagentCatalogOpen(p,o)}}
316
+ const sidebarServices=()=>{const sidebarRight=serviceOf(ctx,'sidebarRight'),tabs=serviceOf(ctx,'sidebarRightTabs'),sessions=ctx.sessions;return typeof sidebarRight?.openResource==='function'&&typeof tabs?.candidates==='function'&&typeof sessions?.subagentAddress==='function'?{sidebarRight,tabs,sessions}:null},
317
+ asideAddressOf=row=>{
318
+ const services=sidebarServices()
319
+ if(!services)return undefined
252
320
  try{
253
- const address=ctx.sessions.subagentAddress(row.id)
321
+ const address=services.sessions.subagentAddress(row.id)
254
322
  if(!address||!address.parentSessionId||!address.childSessionId||!address.mode)return null
255
323
  const value=subagentChatAddressOf(address)
256
- if(tabs.candidates(value).length===0)return null
324
+ if(services.tabs.candidates(value).length===0)return null
257
325
  return value
258
326
  }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,
327
+ },
328
+ openAside=address=>{
329
+ const services=sidebarServices()
330
+ if(!services)return false
331
+ try{services.sidebarRight.openResource(address,{preferNewPane:true});return true}catch(error){console.warn('subagent-workspace-ui: unable to open the sidebar resource',address,error);return false}
332
+ },
263
333
  face=()=>({...actions,asideAddressOf,openAside})
264
334
  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
335
  ctx.slots.inject('conversation.session.header.lineage',()=>ctx.slots.register({name:'conversation.session.header.lineage',priority:-1},LineageShadow))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-subagent-workspace-ui",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "type": "module",
5
5
  "description": "Searchable workspace subagent manager for DeepSeek Harness Web",
6
6
  "license": "MIT",