dsh-subagent-workspace-ui 1.4.0 → 1.5.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
@@ -53,7 +53,26 @@ A full persistent workspace-wide archive view requires a host-side catalog RPC (
53
53
 
54
54
  ## Compatibility
55
55
 
56
- v1.4.0 supports dsh **0.1.5-rc.2** and stays backward compatible with all DeepSeek Harness versions: the 0.1.2-series capability-detection paths (live output via `binding.eventSource`, chat-tab switch via slot `actions`) remain the primary branches, and the **0.1.1-rc.2** legacy fallbacks (`chat.legacy` snapshot) are unchanged.
56
+ v1.5.0 supports dsh **0.1.6-alpha.2** and stays backward compatible with all DeepSeek Harness versions. Opening a subagent session is capability-detected at runtime and degrades in three tiers:
57
+
58
+ ```text
59
+ # dsh 0.1.2-alpha.5 .. 0.1.6-alpha.1: the session controller entry points
60
+ ctx.sessions.openSubagent(address) # exact child address
61
+ ctx.sessions.open(sessionId) # retained session navigation
62
+
63
+ # dsh 0.1.6-alpha.2 and later: the workspace navigation service
64
+ ctx.get('uiWorkspace').openSession({ parentSessionId, childSessionId, mode } | sessionId)
65
+
66
+ # neither is available: the click reports that the host has no session navigation API
67
+ ```
68
+
69
+ `uiWorkspace` is read through `ctx.get('uiWorkspace')`, never through a required injection, so hosts that do not register the service (everything before **0.1.2-alpha.5**) still load and keep using the session-controller path, while hosts that removed `openSubagent`/`open` (**0.1.6-alpha.2**) use the workspace service. **The probe order follows the argument shape, not the version**: `sessions.openSubagent` accepts an address object on every host that has it, whereas `uiWorkspace.openSession` only accepts a `SessionTarget` from **0.1.6-alpha.2** on — on **0.1.5-alpha.2 … 0.1.6-alpha.1** it is `openSession(sessionId)` and routes through `sessions.open(id)`, which throws on an address. The session-controller tier is therefore tried first and the workspace service is the fallback. Within the controller tier the exact `{ parentSessionId, childSessionId, mode }` address is used first and only a missing mode/child falls back to plain session navigation, because `openSubagent` rejects addresses that are not healthy catalog children. The 0.1.2-series capability paths (live output via `binding.eventSource`, chat-tab switch via slot `actions`) remain the primary branches, and the **0.1.1-rc.2** legacy fallbacks (`chat.legacy` snapshot) are unchanged.
70
+
71
+ ## v1.5.0
72
+
73
+ - **Fix**: on DeepSeek Harness **0.1.6-alpha.2** clicking a subagent row failed with `TypeError: ctx.sessions.openSubagent is not a function` (the click was silently swallowed by the row's `try`/`catch`, so the panel just looked dead). 0.1.6-alpha.2 removed `sessions.openSubagent(address)` and `sessions.open(id)`; the plugin now detects the navigation capability at runtime in three tiers (`sessions.openSubagent` → `sessions.open` → `uiWorkspace.openSession`) instead of hard-switching, so the same bundle keeps working on both sides of that upstream change, and the failure is surfaced in the UI when no navigation API exists at all.
74
+ - **Fix**: the tier order above is argument-shape driven, because **0.1.5-alpha.2 … 0.1.6-alpha.1** ships a `uiWorkspace.openSession(sessionId)` that only accepts a string id and throws `sessions.select: unknown session [object Object]` for an address, while `sessions.openSubagent(address)` is still present and does accept one on those hosts. Trying the workspace service first there swallowed that throw and showed the "unsupported version" notice, so the address now goes to the object-capable controller entry point first and `uiWorkspace` remains the fallback for 0.1.6-alpha.2+. Verified live on both sides of the band: on **0.1.5-alpha.1** (client packages 0.1.5-rc.2) the reordered bundle switches session in ~142 ms with no alert and no navigation error, and on **0.1.6-alpha.2** the served bundle still resolves to `uiWorkspace.openSession` and opens the child session.
75
+ - **Fix**: 0.1.6-alpha.2 also dropped the `current` field from the session list snapshot, which the current-session resolution and the Chat-tab fallback relied on. Both now degrade gracefully: the fallback recognizes a missing `current`, tries the host's own Chat tab immediately, and gives up quietly after 2 s instead of polling for 8 s.
57
76
 
58
77
  ## v1.4.0
59
78
 
@@ -94,9 +113,14 @@ Smoke-test a specific dsh version:
94
113
 
95
114
  ```bash
96
115
  ./test.sh # local dsh, port 8084
97
- DSH_VERSION=0.1.1-rc.2 ./test.sh # pnpx @deepseek-ai/dsh@0.1.1-rc.2 (via proxychains4 -q)
116
+ ./test.sh 8085 # explicit port
117
+ DSH_VERSION=0.1.6-alpha.2 ./test.sh # pnpx @deepseek-ai/dsh@0.1.6-alpha.2 (via proxychains4 -q)
118
+ DSH_VERSION=0.1.1-rc.2 ./test.sh # legacy-API smoke on an old dsh
119
+ DSH_PLUGIN_DIR=.worktrees/x ./test.sh # smoke another checkout's bundle
98
120
  ```
99
121
 
122
+ The script always uses an isolated `DSH_HOME` (`$HOME/tmp/dsh-test`, override with `DSH_SMOKE_HOME=…`) and refuses to touch the real `~/.dsh` profile. With `DSH_VERSION` set it runs `pnpx @deepseek-ai/dsh@<version>`; pnpm 12 ignores dependency lifecycle scripts by default, so the script passes `--allow-build=<pkg>` for dsh's native dependencies (`DSH_ALLOW_BUILDS=…` overrides the list).
123
+
100
124
  ## Acknowledgements
101
125
 
102
126
  - UI localization (zh/en) contributed by [@Marcuss2](https://github.com/Marcuss2) via [PR #1](https://github.com/miuzel/dsh-subagent-ui/pull/1) — many thanks!
package/README.zh.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  面向 DeepSeek Harness Web 的子代理管理插件。插件在会话标题栏提供一个紧凑的 `🧩 子代理 active/total` 入口,用于搜索、筛选、分组、排序、查看和批量归档当前运行时已发现的子代理。
4
4
 
5
- 当前发布版本:**v1.4.0**
5
+ 当前发布版本:**v1.5.0**
6
6
 
7
7
  ## 主要功能
8
8
 
@@ -204,7 +204,22 @@ sessions.binding(childId).session
204
204
  → session.getSnapshot().chat.legacy
205
205
  ```
206
206
 
207
- 如果在当前宿主拿不到对应的实时数据,插件只能显示持久化的会话摘要和统计信息。本版本支持 **dsh 0.1.5-rc.2**,并向下兼容所有 DeepSeek Harness 版本(0.1.2 系列能力探测路径为首选分支,**0.1.1-rc.2** legacy 回退路径保持不变)。
207
+ 如果在当前宿主拿不到对应的实时数据,插件只能显示持久化的会话摘要和统计信息。
208
+
209
+ ### 打开子代理会话的三级能力探测
210
+
211
+ ```text
212
+ # dsh 0.1.2-alpha.5 ~ 0.1.6-alpha.1:会话控制器入口
213
+ ctx.sessions.openSubagent(address) # 精确子代理地址
214
+ ctx.sessions.open(sessionId) # 保留的会话导航
215
+
216
+ # dsh 0.1.6-alpha.2 及以后:工作区导航服务
217
+ ctx.get('uiWorkspace').openSession({ parentSessionId, childSessionId, mode } | sessionId)
218
+
219
+ # 两者都不存在:提示当前 dsh 版本缺少可用的会话导航接口
220
+ ```
221
+
222
+ `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 版本。
208
223
 
209
224
  归档、分类和最近使用顺序保存在浏览器本地 `localStorage` 中,不会写入 DSH 会话日志。
210
225
 
@@ -225,16 +240,24 @@ pnpm run check # 构建 + tsc --noEmit + node --check lib/index.js + 产物
225
240
  ```bash
226
241
  ./test.sh # 本地 dsh 跑 web,端口 8084
227
242
  ./test.sh 8085 # 指定端口
228
- DSH_VERSION=0.1.1-rc.2 ./test.sh # 用 pnpx 拉取指定 dsh 版本跑 web(默认经 proxychains4 -q 走代理)
243
+ DSH_VERSION=0.1.6-alpha.2 ./test.sh # 用 pnpx 拉取 0.1.6-alpha.2 跑 web(默认经 proxychains4 -q 走代理)
244
+ DSH_VERSION=0.1.1-rc.2 ./test.sh # 旧版本兼容性冒烟(legacy 导航路径)
245
+ DSH_PLUGIN_DIR=.worktrees/x ./test.sh # 冒烟其它 checkout 的产物
229
246
  ```
230
247
 
231
- `DSH_HOME` 固定为 `$HOME/tmp/dsh-test`;`DSH_VERSION` 非空时用 `pnpx @deepseek-ai/dsh@<version>` 运行,可用于冒烟测试旧版本(如 0.1.1-rc.2)的兼容性。
248
+ `DSH_HOME` 固定用隔离目录(`$HOME/tmp/dsh-test`,可用 `DSH_SMOKE_HOME=/path` 覆盖),并在启动前拒绝把真实 `~/.dsh` 当冒烟目录。`DSH_VERSION` 非空时用 `pnpx @deepseek-ai/dsh@<version>` 运行,可用于冒烟任意 dsh 版本(如 0.1.6-alpha.2、legacy 的 0.1.1-rc.2)。pnpm 12 默认忽略依赖的生命周期脚本,脚本会为 dsh 的原生依赖逐个传 `--allow-build=<pkg>`(清单可用 `DSH_ALLOW_BUILDS=…` 覆盖)。
232
249
 
233
250
  ## 致谢与参考
234
251
 
235
252
  - UI 本地化(zh/en)由 [@Marcuss2](https://github.com/Marcuss2) 在 [PR #1](https://github.com/miuzel/dsh-subagent-ui/pull/1) 中贡献,特此致谢!
236
253
  - 子代理永久删除、会话生命周期清理及快照刷新机制的设计参考并致谢开源项目:[@heiheiha798/dsh-plugin-subagent-delete](https://github.com/heiheiha798/dsh-plugin-subagent-delete)。
237
254
 
255
+ ## v1.5.0 发布说明
256
+
257
+ - **修复:dsh 0.1.6-alpha.2 点击子代理行无法打开会话**:报错 `TypeError: ctx.sessions.openSubagent is not a function`,且该错误被行点击的 `try`/`catch` 吞掉,界面表现为「点了没反应」。0.1.6-alpha.2 删除了 `sessions.openSubagent(address)` 与 `sessions.open(id)`;插件改为运行时三级能力探测(`sessions.openSubagent` → `sessions.open` → `uiWorkspace.openSession`),不再硬切调用,同一份产物在上下游变更两侧都能工作;三级都不可用时在界面上提示当前版本不支持。
258
+ - **修复:三级探测的顺序按参数形态决定**:**0.1.5-alpha.2 … 0.1.6-alpha.1** 这一带同时存在两级 API,但其中的 `uiWorkspace.openSession(sessionId)` 只接受字符串,传入 address 会走 `sessions.open(id)` 并抛 `sessions.select: unknown session [object Object]`;而 `sessions.openSubagent(address)` 在这些宿主上仍然存在且吃对象。若优先试工作区服务,该异常会被吞掉并误报「当前版本不支持」,因此改为 address 先走会话控制器一级、`uiWorkspace` 作为 0.1.6-alpha.2+ 的兜底。已在危险带两侧实机验证:**0.1.5-alpha.1**(客户端包 0.1.5-rc.2)上顺序修正后的产物约 142 ms 完成会话切换、无告警、无导航报错;**0.1.6-alpha.2** 上服务端实际下发的产物仍命中 `uiWorkspace.openSession` 并正常打开子代理会话。
259
+ - **修复:dsh 0.1.6-alpha.2 的 `current` 字段缺失**:会话列表快照不再提供 `current`,而当前会话解析与「对话」标签页兜底依赖它。两处均已优雅退化——兜底逻辑识别 `current` 缺失后立即尝试点击宿主自身的「对话」标签,并在 2 秒内安静放弃,不再空转 8 秒。
260
+
238
261
  ## v1.4.0 发布说明
239
262
 
240
263
  - **支持 DeepSeek Harness 0.1.5-rc.2,向下兼容所有 dsh 版本**:适配 0.1.5-rc.2 的对话页视图结构变化(slot 渲染器不再向未声明 store 的注册项注入 `actions`;视图选择改为按会话持久化,新增「轨迹」等标签页)——点击子代理重新正确落回「对话」标签页(`actions` 缺失时改为点击宿主自身的「对话」标签完成切换,激活与持久化语义完整)。0.1.2 系列能力探测路径保留为首选分支、调用方式不变,0.1.1 legacy 回退路径零改动,旧版本行为完全一致。
package/lib/client.js CHANGED
@@ -53,10 +53,11 @@ function ActiveFloat({t:tr,rows,openRow,onHide,stopAgent,stopAllAgents,stoppingI
53
53
 
54
54
  let chatViewPinGen=0
55
55
  function pinChatViewTab(sessionId){
56
- const gen=++chatViewPinGen,until=Date.now()+8000
56
+ const gen=++chatViewPinGen,until=Date.now()+2000
57
57
  const tryPin=()=>{
58
58
  if(gen!==chatViewPinGen||Date.now()>until)return
59
- if(sessionsRt?.list?.getSnapshot?.().current!==sessionId){setTimeout(tryPin,100);return}
59
+ const current=sessionsRt?.list?.getSnapshot?.()?.current
60
+ if(current!==undefined&&current!==sessionId){setTimeout(tryPin,100);return}
60
61
  const lists=document.querySelectorAll('header div[role="tablist"]')
61
62
  for(const list of lists){
62
63
  const tabs=Array.from(list.querySelectorAll('button[role="tab"]'))
@@ -142,17 +143,18 @@ function Manager({t:tr,useSessions,openChild,openSession,refresh,setCatalogOpen,
142
143
  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
143
144
  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])
144
145
  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])
145
- 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{if(r.parentId&&r.mode)openChild({parentSessionId:r.parentId,childSessionId:r.id,mode:r.mode});else openSession(r.id);if(actions?.setView)actions.setView('chat');else pinChatViewTab(r.id);setOpen(false);setBatchMode(false)}catch(e){console.warn('Unable to open subagent',e)}}
146
+ 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'))}}
146
147
  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])
147
148
  const activeGroupContinuableRows=groups[tr('group.active')]?.filter(r=>r.mode!=='one-shot')||[]
148
149
  return jsxs(React.Fragment,{children:[(!open&&prefs.activeFloat!==false&&Boolean(activeRows.length)&&!floatHidden)?jsx(ActiveFloat,{t:tr,rows:activeRows,openRow,onHide:()=>setFloatHidden(true),stopAgent,stopAllAgents,stoppingIds,liveEnabled:prefs.activeFloatLive!==false,onLiveChange:value=>setPrefs(p=>({...p,activeFloatLive:value})),liveCap}):null,jsxs('div',{className:'dsh-sam-trigger-wrap',children:[jsx('button',{type:'button',className:'dsh-sam-trigger',onClick:()=>{setLimit(PAGE);setOpen(true)},title:tr('openManager'),children:[jsx('span',{className:`dsh-sam-icon ${active>0?'dsh-sam-pulse':''}`,children:'🧩'}),jsx('span',{children:tr('chip.count',{active:active,total:currentCount})})]}),!open&&newAgents.map((item,index)=>jsx('div',{className:'dsh-sam-new-agent',style:{top:`calc(100% + ${6+index*34}px)`},role:'status',children:tr('newAgent',{name:item.name})},item.id))]}),open&&jsx('div',{className:'dsh-sam-backdrop',onMouseDown:e=>{if(e.target===e.currentTarget){setOpen(false);setBatchMode(false);setSelectedIds(new Set);setLastSelectedIndex(-1);setLastSelectedAction(null)}},children:jsxs('section',{className:'dsh-sam-panel',role:'dialog','aria-modal':true,children:[jsxs('header',{className:'dsh-sam-head',children:[jsxs('div',{style:{flex:1,minWidth:0},children:[jsx('h2',{children:tr('managerTitle')}),jsxs('div',{className:'dsh-sam-head-sub',children:[jsx('div',{className:'dsh-sam-summary',children:tr('head.summary',{session:allRows.filter(r=>r.parentId===currentId).length,workspace:allRows.filter(r=>currentCwd&&state.byId[r.parentId]?.cwd===currentCwd).length,active:active})}),jsx('span',{className:'dsh-sam-summary',style:{opacity:0.6},children:'·'}),jsx('label',{className:'dsh-sam-head-float-toggle',children:[jsx('input',{type:'checkbox',checked:prefs.activeFloat!==false,onChange:()=>{setFloatHidden(false);setPrefs(p=>({...p,activeFloat:p.activeFloat===false}))}}),tr('showActiveFloat')]})]})]}),jsx('button',{className:'dsh-sam-close',type:'button',onClick:()=>{setOpen(false);setBatchMode(false);setSelectedIds(new Set);setLastSelectedIndex(-1)},children:'×'})]}),!prefs.filterCollapsed&&jsxs('div',{className:'dsh-sam-tabs',children:[tabs.map(t=>jsxs('span',{className:`dsh-sam-tab-wrap ${(prefs.tabs?.some(x=>x.id===t.id)&&!defaultTabs.some(x=>x.id===t.id))?`dsh-sam-custom-wrap ${tab===t.id?'dsh-sam-tab-selected':''}`:''}`,children:[jsx('button',{type:'button',className:`${t.id==='other'?'dsh-sam-other-tab ':''}${(prefs.tabs?.some(x=>x.id===t.id)&&!defaultTabs.some(x=>x.id===t.id))?'dsh-sam-custom-tab':''}`,'aria-pressed':tab===t.id,onClick:()=>{setTab(t.id);setLimit(PAGE)},children:jsxs(React.Fragment,{children:[nameOf(t),jsx('small',{className:'dsh-sam-tab-count',children:tabCounts[t.id]>99?'99+':tabCounts[t.id]||0})]})},`tab-select-${t.id}`),...((prefs.tabs?.some(x=>x.id===t.id)&&!defaultTabs.some(x=>x.id===t.id))?[jsx('button',{type:'button',className:'dsh-sam-delete-tab',title:tr('deleteCategory.named',{name:t.name}),'aria-label':tr('deleteCategory.named',{name:t.name}),onClick:e=>{e.stopPropagation();if(!window.confirm(tr('confirm.deleteCategory',{name:t.name})))return;setPrefs(p=>({...p,tabs:(p.tabs||[]).filter(x=>x.id!==t.id)}));if(tab===t.id)setTab('all')},children:'×'},`tab-delete-${t.id}`)]:[])]},t.id)),jsx('button',{type:'button',className:'dsh-sam-new-tab',onClick:()=>{const name=window.prompt(tr('categoryNamePrompt'));if(!name)return;const regex=window.prompt(tr('regexPrompt'));if(!regex)return;setPrefs(p=>({...p,tabs:[...(p.tabs||defaultTabs),{id:`tab-${Date.now()}`,name,regex}]}))},children:tr('newCategory')})]}),jsxs('div',{className:'dsh-sam-controls',children:[jsx('button',{type:'button',className:'dsh-sam-filter-btn',onClick:()=>setFilterOpen(v=>!v),children:`⚙ ${tr('filterSort')} · ${scope==='currentWorkspace'?tr('scope.currentWorkspace'):scope==='currentSession'?tr('scope.currentSession'):tr('scope.custom')} · ${sort==='recent'?tr('sort.recent'):sort==='title'?tr('sort.name'):tr('sort.type')}`}),!prefs.filterCollapsed&&jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},'aria-label':tr('scopeAria'),children:[jsx('option',{value:'currentWorkspace',children:tr('scope.currentWorkspace')}),jsx('option',{value:'all',children:tr('scope.allWorkspaces')}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:workspace(tr,{cwd:c})},c))]}),!prefs.filterCollapsed&&jsx('select',{value:selectedSession,onChange:e=>setSessionScope(e.target.value),children:[jsx('option',{value:'all',children:tr('scope.allSessions')}),...availableSessions.map(s=>jsx('option',{value:s.id,children:s.id===currentId?tr('session.currentDot',{name:title(s)}):title(s)},s.id))]}),jsxs('div',{className:'dsh-sam-search-wrap',children:[jsx('input',{autoFocus:true,value:query,placeholder:tr('searchPlaceholder'),onChange:e=>{setQuery(e.target.value);setLimit(PAGE)}}),jsxs('div',{className:'dsh-sam-search-actions',children:[query&&jsx('button',{type:'button',className:'dsh-sam-search-clear',title:tr('clearSearch'),onClick:()=>setQuery(''),children:'×'}),jsx('button',{type:'button',className:'dsh-sam-filter-toggle',title:prefs.filterCollapsed?tr('expandFiltersFull'):tr('collapseFiltersFull'),onClick:()=>setPrefs(p=>({...p,filterCollapsed:!p.filterCollapsed})),children:prefs.filterCollapsed?tr('expandFilters'):tr('collapseFilters')})]})]}),!prefs.filterCollapsed&&jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session',tr('grouping.optionSession')],['workspace',tr('grouping.optionWorkspace')],['category',tr('grouping.optionCategory')],['type',tr('grouping.optionType')],['none',tr('grouping.optionNone')]].map(([v,l])=>jsx('option',{value:v,children:l},v))}),!prefs.filterCollapsed&&jsx('select',{value:sort,onChange:e=>setSort(e.target.value),children:[['recent',tr('sort.optionRecent')],['title',tr('sort.optionName')],['type',tr('sort.optionType')]].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),filterOpen&&jsxs('div',{className:'dsh-sam-filter-popover',children:[jsx('label',{children:[tr('scope'),jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},children:[jsx('option',{value:'currentWorkspace',children:tr('scope.currentWorkspace')}),jsx('option',{value:'currentSession',children:tr('scope.currentSession')}),jsx('option',{value:'all',children:tr('scope.allWorkspaces')}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:tr('workspace.named',{name:workspace(tr,{cwd:c})})},c)),...parentRows.map(s=>jsx('option',{value:`session:${s.id}`,children:tr('session.named',{name:`${workspace(tr,s)} / ${title(s)}`})},s.id))]})]}),jsx('label',{children:[tr('grouping'),jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session',tr('grouping.bySession')],['workspace',tr('grouping.byWorkspace')],['category',tr('grouping.byCategory')],['type',tr('grouping.byType')],['none',tr('grouping.none')]].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),jsx('label',{children:[tr('sort'),jsx('select',{value:sort,onChange:e=>{setSort(e.target.value);setLimit(PAGE)},children:[['recent',tr('sort.recent')],['title',tr('name')],['type',tr('type')]].map(([v,l])=>jsx('option',{value:v,children:l},v))})]})]}),!prefs.filterCollapsed&&jsxs('div',{className:'dsh-sam-options',children:[jsx('label',{children:[jsx('input',{type:'checkbox',checked:!!prefs.hideOneShot,onChange:()=>setPrefs(p=>({...p,hideOneShot:!p.hideOneShot}))}),tr('hideOneShot')]}),jsx('label',{children:[jsx('input',{type:'checkbox',checked:!!prefs.hideOld,onChange:()=>setPrefs(p=>({...p,hideOld:!p.hideOld}))}),tr('hideLongInactive')]}),jsxs('span',{className:'dsh-sam-bg-config',children:[jsx('label',{children:[jsx('input',{type:'checkbox',checked:prefs.customSubagentBg!==false,onChange:()=>setPrefs(p=>({...p,customSubagentBg:p.customSubagentBg===false}))}),tr('subagentBg')]}),prefs.customSubagentBg!==false&&jsxs(React.Fragment,{children:[jsx('label',{title:tr('subagentBgLightTitle'),children:[jsx('input',{type:'color',className:'dsh-sam-color-input',value:prefs.subagentBgLight||DEFAULT_LIGHT_BG,onChange:e=>setPrefs(p=>({...p,subagentBgLight:e.target.value}))}),tr('light')]}),jsx('label',{title:tr('subagentBgDarkTitle'),children:[jsx('input',{type:'color',className:'dsh-sam-color-input',value:prefs.subagentBgDark||DEFAULT_DARK_BG,onChange:e=>setPrefs(p=>({...p,subagentBgDark:e.target.value}))}),tr('dark')]})]})]}),jsx('button',{type:'button',onClick:()=>{setQuery('');setScope('currentWorkspace');setScopeDetail('');setSessionScope('all');setTab('all');setGrouping('session');setSort('recent');setLimit(PAGE)},children:tr('resetFilters')})]}),prefs.filterCollapsed&&jsxs('div',{className:'dsh-sam-collapsed-info',children:[jsxs('div',{className:'dsh-sam-collapsed-left',children:[jsx('span',{className:'dsh-sam-collapsed-tag',children:currentScopeName}),jsx('span',{children:'·'}),jsx('span',{className:'dsh-sam-collapsed-tag',children:currentSessionName}),jsx('span',{children:'·'}),jsx('span',{className:'dsh-sam-collapsed-tag',children:currentTabName})]}),jsxs('div',{className:'dsh-sam-collapsed-right',children:[jsx('span',{children:tr('sort.current',{name:currentSortName})}),jsx('span',{children:tr('grouping.current',{name:currentGroupName})})]})]}),jsxs('div',{className:'dsh-sam-summary-line',children:[jsxs('div',{className:'dsh-sam-summary-items',children:[jsx('span',{className:'dsh-sam-summary',children:tr('summary.showing',{shown:rows.length,total:allRows.length})}),jsx('label',{className:'dsh-sam-summary-hidden-toggle',children:[jsx('input',{type:'checkbox',checked:prefs.showDetails!==false,onChange:()=>setPrefs(p=>({...p,showDetails:p.showDetails===false}))}),tr('showDetails')]}),jsx('label',{className:'dsh-sam-summary-hidden-toggle',children:[jsx('input',{type:'checkbox',checked:!!prefs.showArchived,onChange:()=>setPrefs(p=>({...p,showArchived:!p.showArchived}))}),tr('showHidden')]}),jsx('span',{className:'dsh-sam-summary',style:{fontSize:'11px'},children:tr('hideNote')})]}),jsx('button',{type:'button',className:`dsh-sam-batch-btn ${batchMode?'dsh-sam-batch-done':''}`,onClick:()=>{setBatchMode(v=>!v);setSelectedIds(new Set)},children:batchMode?tr('done'):tr('batch')})]}),batchMode&&jsxs('div',{className:'dsh-sam-batch-bar',children:[jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set(allRows.map(r=>r.id))),children:tr('selectAll')}),jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set),children:tr('clear')}),jsx('button',{type:'button',onClick:selectOld,children:tr('selectOld')}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(false),title:tr('hideSelectedTitle'),children:tr('batch.hide',{count:selectedIds.size})}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(true),title:tr('unhideSelectedTitle'),children:tr('batchUnhide')}),jsx('button',{type:'button',onClick:()=>{if(!window.confirm(tr('confirmHideAll')))return;batchArchive(allRows.map(r=>r.id));setSelectedIds(new Set)},children:tr('hideAll')}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',disabled:!selectedIds.size,onClick:()=>batchDeleteSubagents([...selectedIds]),children:tr('batch.delete',{count:selectedIds.size})}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',onClick:()=>batchDeleteSubagents(allRows.map(r=>r.id)),children:tr('deleteAll')})]}),jsx('div',{className:'dsh-sam-list',onWheel:e=>e.stopPropagation(),children:Object.keys(groups).length===0?jsx('div',{className:'dsh-sam-empty',children:tr('empty')}):Object.entries(groups).map(([name,entries])=>jsxs('section',{className:'dsh-sam-group',children:[jsxs('div',{className:'dsh-sam-group-head',onClick:()=>name===tr('group.active')&&setActiveOpen(v=>!v),children:[jsx('span',{children:`${name}${name===tr('group.active')?(activeOpen?' ▾':' ▸'):''}`}),jsxs('div',{className:'dsh-sam-group-head-actions',children:[name===tr('group.active')&&activeGroupContinuableRows.length>0&&jsx('button',{type:'button',className:'dsh-sam-stop-all-btn',title:tr('pauseAllActive'),disabled:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id)),onClick:e=>{e.stopPropagation();stopAllAgents(activeGroupContinuableRows)},children:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id))?tr('pausing'):tr('pauseAll')}),jsx('span',{children:entries.length})]})]}),(name===tr('group.active')&&!activeOpen?[]:entries).map(row=>jsx('div',{className:`dsh-sam-row ${batchMode?'dsh-sam-row-batch':''}${selectedIds.has(row.id)?' dsh-sam-row-selected':''}${archived.has(row.id)?' dsh-sam-row-hidden':''}`,onClick:e=>{if(batchMode)toggleSelected(row,rows.indexOf(row),e);else openRow(row)},title:prefs.showDetails!==false?undefined:statsLine(tr,row),children:[jsx('span',{className:'dsh-sam-marker',children:[batchMode&&jsx('input',{type:'checkbox',checked:selectedIds.has(row.id),onChange:e=>toggleSelected(row,rows.indexOf(row),e),onClick:e=>e.stopPropagation(),'aria-label':tr('select.named',{name:row.name})}),archived.has(row.id)?jsx('span',{className:'dsh-sam-dot hidden-dot',title:tr('hidden'),children:'\u{1F648}'}):jsx('span',{className:`dsh-sam-dot ${row.running?'running':''}`})]}),jsx('button',{type:'button',className:'dsh-sam-row-open',style:{all:'unset',cursor:batchMode?'default':'pointer',minWidth:0},onClick:e=>{e.stopPropagation();if(batchMode)toggleSelected(row,rows.indexOf(row),e);else openRow(row)},title:prefs.showDetails!==false?`${row.name}\n${row.id}`:`${row.name}\n${statsLine(tr,row)}`,children:jsxs('span',{children:[jsx('div',{className:'dsh-sam-title',children:jsxs('span',{children:[highlight(row.name,query),row.mode==='one-shot'&&jsx('small',{className:'dsh-sam-one-shot',children:tr('oneShotBadge')}),jsx('small',{className:'dsh-sam-session-id',children:row.id})]})}),grouping==='session'?null:jsx('div',{className:'dsh-sam-meta',children:highlight(`${modeLabel(tr,row.mode)}${grouping==='session'?'':` · ${row.parentId?`${workspace(tr,state.byId[row.parentId]||row)} / ${title(state.byId[row.parentId]||row)}`:tr('noParent')}`}`,query)})]})}),jsx('span',{className:'dsh-sam-time',title:tr('lastActivity',{time:new Date(row.updatedAt).toLocaleString()}),children:age(tr,row.updatedAt)}),batchMode?(archived.has(row.id)&&jsx('span',{className:'dsh-sam-archived-label',children:tr('hidden')})):jsxs('span',{className:'dsh-sam-row-actions',children:[row.running&&row.mode!=='one-shot'&&jsx('button',{type:'button',className:'dsh-sam-stop-btn',disabled:stoppingIds.has(row.id),onClick:e=>{e.stopPropagation();stopAgent(row)},'aria-label':tr('pause.named',{name:row.name}),'title':tr('pauseSubagent'),children:stoppingIds.has(row.id)?tr('pausing'):tr('pause')}),jsx('button',{type:'button',className:'dsh-sam-hide-btn',onClick:e=>{e.stopPropagation();archive(row)},title:archived.has(row.id)?tr('unhide'):tr('hideTitle'),'aria-label':`${archived.has(row.id)?tr('unhide'):tr('hide')} ${row.name}`,children:archived.has(row.id)?tr('unhideShort'):tr('hideShort')}),jsx('button',{type:'button',className:'dsh-sam-delete-btn',onClick:e=>{e.stopPropagation();deleteSubagent(row)},title:tr('deleteForever'),'aria-label':tr('delete.named',{name:row.name}),children:tr('deleteTrash')})]}),prefs.showDetails!==false&&jsxs('div',{className:'dsh-sam-details',children:[jsx('div',{children:tr('statsLine',{input:fmt(tr,row.projectionValues?.tokenUsage?.uncachedInputTokens),output:fmt(tr,row.projectionValues?.tokenUsage?.outputTokens),cacheHit:row.projectionValues?.tokenUsage?.cacheReadTokens!=null&&tokenTotal(row)?Math.round(row.projectionValues.tokenUsage.cacheReadTokens/tokenTotal(row)*100):tr('unknown'),turns:row.projectionValues?.sessionStats?.turns??row.projectionValues?.turns??tr('unknown'),steps:row.projectionValues?.sessionStats?.steps??row.projectionValues?.steps??tr('unknown')})}),promptPreview(row)&&jsx('div',{children:tr('prompt.label',{prompt:promptPreview(row)})}),jsx(LiveOutput,{t:tr,parentId:row.parentId,childId:row.id,running:row.running,autoLoad:rows.slice(0,10).some(r=>r.id===row.id)||manualLoadedIds.has(row.id),live:(!row.running||(runningLiveIds?runningLiveIds.has(row.id):true)||manualLoadedIds.has(row.id)),onLoad:()=>setManualLoadedIds(prev=>new Set(prev).add(row.id))})]})]},row.id)),limit<allRows.length&&jsx('button',{type:'button',className:'dsh-sam-more',onClick:()=>setLimit(n=>n+PAGE),children:tr('loadMore',{remaining:allRows.length-limit})})]},name))})]})})]})
149
150
  }
150
151
 
151
152
  const NS='subagent-workspace-ui'
152
- const zh={"activeFloat.title": "活跃子代理 · {count}", "age.dAgo": "{d} 天前", "age.hmAgo": "{h} 小时 {m} 分钟前", "age.mAgo": "{m} 分钟前", "age.sAgo": "{s} 秒前", "batch": "批量操作", "batch.delete": "批量删除 ({count})", "batch.hide": "批量隐藏 ({count})", "batchDeleteFailed": "批量删除失败:", "batchDeleteRequestFailed": "批量删除请求失败:", "batchUnhide": "批量显示", "callTool": "⚙ 调用工具 ", "categoryNamePrompt": "分类名称", "chip.count": "子代理 {active}/{total}", "clear": "清空", "clearSearch": "清空搜索", "collapseFilters": "⚙ 折叠 ▴", "collapseFiltersFull": "折叠筛选与配置", "command": "命令", "command.named": "⌘ {name}", "confirm.deleteCategory": "确认删除分类“{name}”?", "confirm.deleteMany": "确认永久删除选中的 {count} 个子代理?删除后不可恢复!", "confirm.deleteOne": "确认永久删除子代理“{name}”?删除后不可恢复!", "confirm.deleteRunning": "子代理“{name}”正在运行中,删除将强制终止它。确认继续?", "confirm.pauseNamed": "确认暂停子代理“{name}”?", "confirm.pauseSelected": "确认暂停选中的 {count} 个子代理?", "confirmHideAll": "确认隐藏当前筛选出的全部子代理?", "contextInjection": "上下文注入 · {name}", "continuable": "可继续", "dark": "深色", "delete.named": "删除 {name}", "deleteAll": "一键删除全部", "deleteCategory.named": "删除分类“{name}”", "deleteFailed": "删除失败:", "deleteForever": "永久删除该子代理", "deleteRequestFailed": "删除请求失败:", "deleteTrash": "🗑 删除", "done": "完成", "elapsed.hm": "{h}时{m}分", "elapsed.ms": "{m}分{s}秒", "elapsed.s": "{s}秒", "empty": "没有符合条件的子代理。", "expandFilters": "⚙ 展开筛选 ▾", "expandFiltersFull": "展开筛选与配置", "filterSort": "筛选排序", "group.active": "活跃子代理", "group.allResults": "全部结果", "group.other": "其他", "group.otherSessions": "其他会话", "grouping": "分组", "grouping.byCategory": "按分类", "grouping.bySession": "按会话", "grouping.byType": "按类型", "grouping.byWorkspace": "按工作区", "grouping.current": "分组 · {name}", "grouping.none": "不分组", "grouping.optionCategory": "分组:按分类", "grouping.optionNone": "分组:不分组", "grouping.optionSession": "分组:按会话", "grouping.optionType": "分组:按类型", "grouping.optionWorkspace": "分组:按工作区", "head.summary": "当前会话 {session} 个 · 当前工作区 {workspace} 个 · 活跃 {active} 个", "hidden": "已隐藏", "hide": "隐藏", "hideActiveFloat": "隐藏活跃子代理浮窗", "hideAll": "一键全部隐藏", "hideLongInactive": "隐藏长期未活跃", "hideNote": "隐藏仅在列表不显示,不删除会话", "hideOneShot": "隐藏一次性", "hideSelectedTitle": "将选中的子代理隐藏", "hideShort": "⊘ 隐藏", "hideTitle": "隐藏(仅在列表隐藏,不删除会话)", "lastActivity": "最近活动:{time}", "light": "浅色", "liveOutput": "实时输出", "liveOutputPrefix": "实时输出:", "loadHistoryTitle": "加载该子代理的历史最新消息", "loadLatest": "📥 加载最新消息", "loadMore": "加载下一页(剩余 {remaining} 个)", "loading": "⏳ 加载中...", "managerTitle": "子代理管理", "name": "名字", "newAgent": "新子代理:{name}", "newCategory": "+ 新建分类", "noParent": "无父会话", "oneShot": "一次性", "oneShotBadge": "⚡ 一次性", "openManager": "打开子代理管理", "pause": "⏸ 暂停", "pause.named": "暂停 {name}", "pauseAll": "⏸ 一键暂停", "pauseAllActive": "一键暂停所有活跃可继续子代理", "pauseSubagent": "暂停子代理", "pausing": "暂停中", "prompt.label": "提示词:{prompt}", "regexPrompt": "匹配正则(例如:^审计|review)", "resetFilters": "重置筛选", "scope": "范围", "scope.allSessions": "全部会话", "scope.allWorkspaces": "全部工作区", "scope.currentSession": "当前会话", "scope.currentWorkspace": "当前工作区", "scope.custom": "自定义范围", "scopeAria": "显示范围", "searchPlaceholder": "搜索名称、标题或工作区;输入 id: 搜索 Session ID", "select.named": "选择 {name}", "selectAll": "全选", "selectHoursPrompt": "选择多少小时前的子代理?", "selectOld": "选择 N 小时前", "session.currentDot": "当前会话 · {name}", "session.currentParen": "当前会话 ({name})", "session.currentWorkspaceDot": "当前工作区 · {name}", "session.named": "会话 · {name}", "showActiveFloat": "显示活跃浮窗", "showDetails": "显示详情", "showHidden": "显示已隐藏", "sort": "排序", "sort.current": "排序 · {name}", "sort.name": "名字", "sort.optionName": "排序:名字", "sort.optionRecent": "排序:最近活跃", "sort.optionType": "排序:类型", "sort.recent": "最近活跃", "sort.type": "类型", "statsLine": "输入 {input} / 输出 {output} · 缓存命中 {cacheHit}% · 轮数 {turns} · 步数 {steps}", "subagentBg": "子代理背景色", "subagentBgDarkTitle": "深色主题下的子代理背景色", "subagentBgLightTitle": "浅色主题下的子代理背景色", "summary.showing": "显示 {shown}/{total} 个", "tab.all": "全部", "tab.audit": "审计", "tab.implement": "实现", "tab.other": "其他", "tab.planning": "规划", "tab.test": "测试", "thinking": "思考中…", "toolCall": "工具调用", "type": "类型", "typeLoading": "类型待加载", "uncategorized": "未分类", "unhide": "取消隐藏", "unhideSelectedTitle": "取消隐藏选中的子代理", "unhideShort": "👁 显示", "unknown": "未知", "unknownError": "未知错误", "unknownWorkspace": "未知工作区", "workspace.named": "工作区 · {name}"}
153
- const en={"activeFloat.title": "Active subagents · {count}", "age.dAgo": "{d}d ago", "age.hmAgo": "{h}h {m}m ago", "age.mAgo": "{m}m ago", "age.sAgo": "{s}s ago", "batch": "Batch", "batch.delete": "Delete ({count})", "batch.hide": "Hide ({count})", "batchDeleteFailed": "Batch delete failed: ", "batchDeleteRequestFailed": "Batch delete request failed: ", "batchUnhide": "Unhide", "callTool": "⚙ Call tool ", "categoryNamePrompt": "Category name", "chip.count": "Subagents {active}/{total}", "clear": "Clear", "clearSearch": "Clear search", "collapseFilters": "⚙ Collapse ▴", "collapseFiltersFull": "Collapse filters & options", "command": "Command", "command.named": "⌘ {name}", "confirm.deleteCategory": "Delete category \"{name}\"?", "confirm.deleteMany": "Permanently delete the selected {count} subagents? This cannot be undone!", "confirm.deleteOne": "Permanently delete subagent \"{name}\"? This cannot be undone!", "confirm.deleteRunning": "Subagent \"{name}\" is still running; deleting will force-terminate it. Continue?", "confirm.pauseNamed": "Pause subagent \"{name}\"?", "confirm.pauseSelected": "Pause the selected {count} subagents?", "confirmHideAll": "Hide ALL currently filtered subagents?", "contextInjection": "Context injection · {name}", "continuable": "continuable", "dark": "Dark", "delete.named": "Delete {name}", "deleteAll": "Delete all", "deleteCategory.named": "Delete category \"{name}\"", "deleteFailed": "Delete failed: ", "deleteForever": "Permanently delete this subagent", "deleteRequestFailed": "Delete request failed: ", "deleteTrash": "🗑 Delete", "done": "Done", "elapsed.hm": "{h}h{m}m", "elapsed.ms": "{m}m{s}s", "elapsed.s": "{s}s", "empty": "No subagents match the current filters.", "expandFilters": "⚙ Expand ▾", "expandFiltersFull": "Expand filters & options", "filterSort": "Filter & sort", "group.active": "Active subagents", "group.allResults": "All results", "group.other": "Other", "group.otherSessions": "Other sessions", "grouping": "Grouping", "grouping.byCategory": "by category", "grouping.bySession": "by session", "grouping.byType": "by type", "grouping.byWorkspace": "by workspace", "grouping.current": "Group · {name}", "grouping.none": "none", "grouping.optionCategory": "Group: by category", "grouping.optionNone": "Group: none", "grouping.optionSession": "Group: by session", "grouping.optionType": "Group: by type", "grouping.optionWorkspace": "Group: by workspace", "head.summary": "Current session {session} · Current workspace {workspace} · Active {active}", "hidden": "hidden", "hide": "Hide", "hideActiveFloat": "Hide the active-subagents float", "hideAll": "Hide all", "hideLongInactive": "Hide long-inactive", "hideNote": "Hiding only removes it from the list; the session is not deleted", "hideOneShot": "Hide one-shot", "hideSelectedTitle": "Hide the selected subagents", "hideShort": "⊘ Hide", "hideTitle": "Hide (hides from the list only; the session is not deleted)", "lastActivity": "Last activity: {time}", "light": "Light", "liveOutput": "Live output", "liveOutputPrefix": "Live output: ", "loadHistoryTitle": "Load the latest messages from this subagent’s history", "loadLatest": "📥 Load latest messages", "loadMore": "Load next page ({remaining} left)", "loading": "⏳ Loading...", "managerTitle": "Subagent manager", "name": "name", "newAgent": "New subagent: {name}", "newCategory": "+ New category", "noParent": "no parent session", "oneShot": "one-shot", "oneShotBadge": "⚡ one-shot", "openManager": "Open subagent manager", "pause": "⏸ Pause", "pause.named": "Pause {name}", "pauseAll": "⏸ Pause all", "pauseAllActive": "Pause all active continuable subagents", "pauseSubagent": "Pause subagent", "pausing": "Pausing…", "prompt.label": "Prompt: {prompt}", "regexPrompt": "Match regex (e.g. ^audit|review)", "resetFilters": "Reset filters", "scope": "Scope", "scope.allSessions": "All sessions", "scope.allWorkspaces": "All workspaces", "scope.currentSession": "Current session", "scope.currentWorkspace": "Current workspace", "scope.custom": "Custom scope", "scopeAria": "Scope", "searchPlaceholder": "Search names, titles, or workspaces; type id: to search Session IDs", "select.named": "Select {name}", "selectAll": "Select all", "selectHoursPrompt": "Select subagents from how many hours back?", "selectOld": "Select N hours ago", "session.currentDot": "Current session · {name}", "session.currentParen": "Current session ({name})", "session.currentWorkspaceDot": "Current workspace · {name}", "session.named": "Session · {name}", "showActiveFloat": "Show active float", "showDetails": "Show details", "showHidden": "Show hidden", "sort": "Sort", "sort.current": "Sort · {name}", "sort.name": "name", "sort.optionName": "Sort: name", "sort.optionRecent": "Sort: recent activity", "sort.optionType": "Sort: type", "sort.recent": "recent activity", "sort.type": "type", "statsLine": "in {input} / out {output} · cache hit {cacheHit}% · turns {turns} · steps {steps}", "subagentBg": "Subagent background color", "subagentBgDarkTitle": "Subagent background color in dark theme", "subagentBgLightTitle": "Subagent background color in light theme", "summary.showing": "Showing {shown}/{total}", "tab.all": "All", "tab.audit": "audit", "tab.implement": "implement", "tab.other": "Other", "tab.planning": "planning", "tab.test": "test", "thinking": "thinking…", "toolCall": "Tool call", "type": "type", "typeLoading": "type loading…", "uncategorized": "uncategorized", "unhide": "Unhide", "unhideSelectedTitle": "Unhide selected subagents", "unhideShort": "👁 Unhide", "unknown": "unknown", "unknownError": "unknown error", "unknownWorkspace": "Unknown workspace", "workspace.named": "Workspace · {name}"}
153
+ const zh={"activeFloat.title": "活跃子代理 · {count}", "age.dAgo": "{d} 天前", "age.hmAgo": "{h} 小时 {m} 分钟前", "age.mAgo": "{m} 分钟前", "age.sAgo": "{s} 秒前", "batch": "批量操作", "batch.delete": "批量删除 ({count})", "batch.hide": "批量隐藏 ({count})", "batchDeleteFailed": "批量删除失败:", "batchDeleteRequestFailed": "批量删除请求失败:", "batchUnhide": "批量显示", "callTool": "⚙ 调用工具 ", "categoryNamePrompt": "分类名称", "chip.count": "子代理 {active}/{total}", "clear": "清空", "clearSearch": "清空搜索", "collapseFilters": "⚙ 折叠 ▴", "collapseFiltersFull": "折叠筛选与配置", "command": "命令", "command.named": "⌘ {name}", "confirm.deleteCategory": "确认删除分类“{name}”?", "confirm.deleteMany": "确认永久删除选中的 {count} 个子代理?删除后不可恢复!", "confirm.deleteOne": "确认永久删除子代理“{name}”?删除后不可恢复!", "confirm.deleteRunning": "子代理“{name}”正在运行中,删除将强制终止它。确认继续?", "confirm.pauseNamed": "确认暂停子代理“{name}”?", "confirm.pauseSelected": "确认暂停选中的 {count} 个子代理?", "confirmHideAll": "确认隐藏当前筛选出的全部子代理?", "contextInjection": "上下文注入 · {name}", "continuable": "可继续", "dark": "深色", "delete.named": "删除 {name}", "deleteAll": "一键删除全部", "deleteCategory.named": "删除分类“{name}”", "deleteFailed": "删除失败:", "deleteForever": "永久删除该子代理", "deleteRequestFailed": "删除请求失败:", "deleteTrash": "🗑 删除", "done": "完成", "elapsed.hm": "{h}时{m}分", "elapsed.ms": "{m}分{s}秒", "elapsed.s": "{s}秒", "empty": "没有符合条件的子代理。", "expandFilters": "⚙ 展开筛选 ▾", "expandFiltersFull": "展开筛选与配置", "filterSort": "筛选排序", "group.active": "活跃子代理", "group.allResults": "全部结果", "group.other": "其他", "group.otherSessions": "其他会话", "grouping": "分组", "grouping.byCategory": "按分类", "grouping.bySession": "按会话", "grouping.byType": "按类型", "grouping.byWorkspace": "按工作区", "grouping.current": "分组 · {name}", "grouping.none": "不分组", "grouping.optionCategory": "分组:按分类", "grouping.optionNone": "分组:不分组", "grouping.optionSession": "分组:按会话", "grouping.optionType": "分组:按类型", "grouping.optionWorkspace": "分组:按工作区", "head.summary": "当前会话 {session} 个 · 当前工作区 {workspace} 个 · 活跃 {active} 个", "hidden": "已隐藏", "hide": "隐藏", "hideActiveFloat": "隐藏活跃子代理浮窗", "hideAll": "一键全部隐藏", "hideLongInactive": "隐藏长期未活跃", "hideNote": "隐藏仅在列表不显示,不删除会话", "hideOneShot": "隐藏一次性", "hideSelectedTitle": "将选中的子代理隐藏", "hideShort": "⊘ 隐藏", "hideTitle": "隐藏(仅在列表隐藏,不删除会话)", "lastActivity": "最近活动:{time}", "light": "浅色", "liveOutput": "实时输出", "liveOutputPrefix": "实时输出:", "loadHistoryTitle": "加载该子代理的历史最新消息", "loadLatest": "📥 加载最新消息", "loadMore": "加载下一页(剩余 {remaining} 个)", "loading": "⏳ 加载中...", "managerTitle": "子代理管理", "name": "名字", "newAgent": "新子代理:{name}", "newCategory": "+ 新建分类", "noParent": "无父会话", "oneShot": "一次性", "oneShotBadge": "⚡ 一次性", "openManager": "打开子代理管理", "openUnsupported": "当前 dsh 版本不支持打开子代理会话(缺少可用的会话导航接口)。", "pause": "⏸ 暂停", "pause.named": "暂停 {name}", "pauseAll": "⏸ 一键暂停", "pauseAllActive": "一键暂停所有活跃可继续子代理", "pauseSubagent": "暂停子代理", "pausing": "暂停中", "prompt.label": "提示词:{prompt}", "regexPrompt": "匹配正则(例如:^审计|review)", "resetFilters": "重置筛选", "scope": "范围", "scope.allSessions": "全部会话", "scope.allWorkspaces": "全部工作区", "scope.currentSession": "当前会话", "scope.currentWorkspace": "当前工作区", "scope.custom": "自定义范围", "scopeAria": "显示范围", "searchPlaceholder": "搜索名称、标题或工作区;输入 id: 搜索 Session ID", "select.named": "选择 {name}", "selectAll": "全选", "selectHoursPrompt": "选择多少小时前的子代理?", "selectOld": "选择 N 小时前", "session.currentDot": "当前会话 · {name}", "session.currentParen": "当前会话 ({name})", "session.currentWorkspaceDot": "当前工作区 · {name}", "session.named": "会话 · {name}", "showActiveFloat": "显示活跃浮窗", "showDetails": "显示详情", "showHidden": "显示已隐藏", "sort": "排序", "sort.current": "排序 · {name}", "sort.name": "名字", "sort.optionName": "排序:名字", "sort.optionRecent": "排序:最近活跃", "sort.optionType": "排序:类型", "sort.recent": "最近活跃", "sort.type": "类型", "statsLine": "输入 {input} / 输出 {output} · 缓存命中 {cacheHit}% · 轮数 {turns} · 步数 {steps}", "subagentBg": "子代理背景色", "subagentBgDarkTitle": "深色主题下的子代理背景色", "subagentBgLightTitle": "浅色主题下的子代理背景色", "summary.showing": "显示 {shown}/{total} 个", "tab.all": "全部", "tab.audit": "审计", "tab.implement": "实现", "tab.other": "其他", "tab.planning": "规划", "tab.test": "测试", "thinking": "思考中…", "toolCall": "工具调用", "type": "类型", "typeLoading": "类型待加载", "uncategorized": "未分类", "unhide": "取消隐藏", "unhideSelectedTitle": "取消隐藏选中的子代理", "unhideShort": "👁 显示", "unknown": "未知", "unknownError": "未知错误", "unknownWorkspace": "未知工作区", "workspace.named": "工作区 · {name}"}
154
+ const en={"activeFloat.title": "Active subagents · {count}", "age.dAgo": "{d}d ago", "age.hmAgo": "{h}h {m}m ago", "age.mAgo": "{m}m ago", "age.sAgo": "{s}s ago", "batch": "Batch", "batch.delete": "Delete ({count})", "batch.hide": "Hide ({count})", "batchDeleteFailed": "Batch delete failed: ", "batchDeleteRequestFailed": "Batch delete request failed: ", "batchUnhide": "Unhide", "callTool": "⚙ Call tool ", "categoryNamePrompt": "Category name", "chip.count": "Subagents {active}/{total}", "clear": "Clear", "clearSearch": "Clear search", "collapseFilters": "⚙ Collapse ▴", "collapseFiltersFull": "Collapse filters & options", "command": "Command", "command.named": "⌘ {name}", "confirm.deleteCategory": "Delete category \"{name}\"?", "confirm.deleteMany": "Permanently delete the selected {count} subagents? This cannot be undone!", "confirm.deleteOne": "Permanently delete subagent \"{name}\"? This cannot be undone!", "confirm.deleteRunning": "Subagent \"{name}\" is still running; deleting will force-terminate it. Continue?", "confirm.pauseNamed": "Pause subagent \"{name}\"?", "confirm.pauseSelected": "Pause the selected {count} subagents?", "confirmHideAll": "Hide ALL currently filtered subagents?", "contextInjection": "Context injection · {name}", "continuable": "continuable", "dark": "Dark", "delete.named": "Delete {name}", "deleteAll": "Delete all", "deleteCategory.named": "Delete category \"{name}\"", "deleteFailed": "Delete failed: ", "deleteForever": "Permanently delete this subagent", "deleteRequestFailed": "Delete request failed: ", "deleteTrash": "🗑 Delete", "done": "Done", "elapsed.hm": "{h}h{m}m", "elapsed.ms": "{m}m{s}s", "elapsed.s": "{s}s", "empty": "No subagents match the current filters.", "expandFilters": "⚙ Expand ▾", "expandFiltersFull": "Expand filters & options", "filterSort": "Filter & sort", "group.active": "Active subagents", "group.allResults": "All results", "group.other": "Other", "group.otherSessions": "Other sessions", "grouping": "Grouping", "grouping.byCategory": "by category", "grouping.bySession": "by session", "grouping.byType": "by type", "grouping.byWorkspace": "by workspace", "grouping.current": "Group · {name}", "grouping.none": "none", "grouping.optionCategory": "Group: by category", "grouping.optionNone": "Group: none", "grouping.optionSession": "Group: by session", "grouping.optionType": "Group: by type", "grouping.optionWorkspace": "Group: by workspace", "head.summary": "Current session {session} · Current workspace {workspace} · Active {active}", "hidden": "hidden", "hide": "Hide", "hideActiveFloat": "Hide the active-subagents float", "hideAll": "Hide all", "hideLongInactive": "Hide long-inactive", "hideNote": "Hiding only removes it from the list; the session is not deleted", "hideOneShot": "Hide one-shot", "hideSelectedTitle": "Hide the selected subagents", "hideShort": "⊘ Hide", "hideTitle": "Hide (hides from the list only; the session is not deleted)", "lastActivity": "Last activity: {time}", "light": "Light", "liveOutput": "Live output", "liveOutputPrefix": "Live output: ", "loadHistoryTitle": "Load the latest messages from this subagent’s history", "loadLatest": "📥 Load latest messages", "loadMore": "Load next page ({remaining} left)", "loading": "⏳ Loading...", "managerTitle": "Subagent manager", "name": "name", "newAgent": "New subagent: {name}", "newCategory": "+ New category", "noParent": "no parent session", "oneShot": "one-shot", "oneShotBadge": "⚡ one-shot", "openManager": "Open subagent manager", "openUnsupported": "This dsh version does not expose a session navigation API, so the subagent session cannot be opened.", "pause": "⏸ Pause", "pause.named": "Pause {name}", "pauseAll": "⏸ Pause all", "pauseAllActive": "Pause all active continuable subagents", "pauseSubagent": "Pause subagent", "pausing": "Pausing…", "prompt.label": "Prompt: {prompt}", "regexPrompt": "Match regex (e.g. ^audit|review)", "resetFilters": "Reset filters", "scope": "Scope", "scope.allSessions": "All sessions", "scope.allWorkspaces": "All workspaces", "scope.currentSession": "Current session", "scope.currentWorkspace": "Current workspace", "scope.custom": "Custom scope", "scopeAria": "Scope", "searchPlaceholder": "Search names, titles, or workspaces; type id: to search Session IDs", "select.named": "Select {name}", "selectAll": "Select all", "selectHoursPrompt": "Select subagents from how many hours back?", "selectOld": "Select N hours ago", "session.currentDot": "Current session · {name}", "session.currentParen": "Current session ({name})", "session.currentWorkspaceDot": "Current workspace · {name}", "session.named": "Session · {name}", "showActiveFloat": "Show active float", "showDetails": "Show details", "showHidden": "Show hidden", "sort": "Sort", "sort.current": "Sort · {name}", "sort.name": "name", "sort.optionName": "Sort: name", "sort.optionRecent": "Sort: recent activity", "sort.optionType": "Sort: type", "sort.recent": "recent activity", "sort.type": "type", "statsLine": "in {input} / out {output} · cache hit {cacheHit}% · turns {turns} · steps {steps}", "subagentBg": "Subagent background color", "subagentBgDarkTitle": "Subagent background color in dark theme", "subagentBgLightTitle": "Subagent background color in light theme", "summary.showing": "Showing {shown}/{total}", "tab.all": "All", "tab.audit": "audit", "tab.implement": "implement", "tab.other": "Other", "tab.planning": "planning", "tab.test": "test", "thinking": "thinking…", "toolCall": "Tool call", "type": "type", "typeLoading": "type loading…", "uncategorized": "uncategorized", "unhide": "Unhide", "unhideSelectedTitle": "Unhide selected subagents", "unhideShort": "👁 Unhide", "unknown": "unknown", "unknownError": "unknown error", "unknownWorkspace": "Unknown workspace", "workspace.named": "Workspace · {name}"}
154
155
 
155
- function apply(ctx){sessionsRt=ctx.sessions;ctx.effect(()=>ctx.locale.register(NS,{zh,en}),'subagent-workspace-ui: dictionaries');const actions={openChild:a=>ctx.sessions.openSubagent(a),openSession:id=>ctx.sessions.open(id),refresh:p=>ctx.sessions.refreshSubagents(p),setCatalogOpen:(p,o)=>ctx.sessions.setSubagentCatalogOpen(p,o)},face=()=>actions;ctx.slots.inject('conversation.session.header.actions',()=>ctx.slots.register({name:'conversation.session.header.actions',id:'subagent-workspace-manager',order:100,locale:NS,inject:face},Manager))}
156
+ const uiWorkspaceOf=ctx=>{try{const ws=ctx.get?.('uiWorkspace');return typeof ws?.openSession==='function'?ws:null}catch{return null}}
157
+ function apply(ctx){sessionsRt=ctx.sessions;ctx.effect(()=>ctx.locale.register(NS,{zh,en}),'subagent-workspace-ui: dictionaries');const actions={openChild:a=>{if(typeof ctx.sessions?.openSubagent==='function'){ctx.sessions.openSubagent(a);return true}const ws=uiWorkspaceOf(ctx);if(ws){ws.openSession(a);return true}if(a?.childSessionId)return actions.openSession(a.childSessionId);return false},openSession:id=>{if(typeof ctx.sessions?.open==='function'){ctx.sessions.open(id);return true}const ws=uiWorkspaceOf(ctx);if(ws){ws.openSession(id);return true}return false},refresh:p=>ctx.sessions.refreshSubagents(p),setCatalogOpen:(p,o)=>ctx.sessions.setSubagentCatalogOpen(p,o)},face=()=>actions;ctx.slots.inject('conversation.session.header.actions',()=>ctx.slots.register({name:'conversation.session.header.actions',id:'subagent-workspace-manager',order:100,locale:NS,inject:face},Manager))}
156
158
  return {inject:['sessions','slots','locale'],apply}
157
159
  }
158
160
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-subagent-workspace-ui",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "description": "Searchable workspace subagent manager for DeepSeek Harness Web",
6
6
  "license": "MIT",
@@ -29,7 +29,8 @@
29
29
  "inject": [
30
30
  "@deepseek-ai/dsh-client-locale",
31
31
  "@deepseek-ai/dsh-client-ui-conversation",
32
- "@deepseek-ai/dsh-client-ui-sidebar"
32
+ "@deepseek-ai/dsh-client-ui-sidebar",
33
+ "@deepseek-ai/dsh-client-ui-workspace"
33
34
  ],
34
35
  "platform": "web"
35
36
  }