dsh-subagent-workspace-ui 1.3.1 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,6 +55,12 @@ A full persistent workspace-wide archive view requires a host-side catalog RPC (
55
55
 
56
56
  v1.3.1 is compatible with dsh **0.1.2-alpha.2** (new `binding.eventSource` live-output path) and **0.1.1-rc.2** (legacy `chat.legacy` snapshot path). Live output is selected by capability detection, so older hosts behave as before.
57
57
 
58
+ ## v1.3.2
59
+
60
+ - **Performance**: the manager now does one base scan (`subagentRows`) and derives `allRows`/`activeRows`/`tabCounts` from it (no repeated full scans or `modeMap` merges), `tabCounts` is computed from a deferred value and is skipped while the panel is closed, and `useSessions` subscribes only the fields the manager reads. Live output is capped to a few simultaneous subagents (`liveCap`, default 3, `0` = unlimited) and fully releases its subscriptions when live display is off or the float/panel is closed.
61
+ - **UX**: opening a subagent now auto-switches the session to the Chat tab.
62
+ - **Fix**: the batch "select N hours ago" now selects the truly-old subagents in the current view (accurate count) and no longer overwrites or re-selects your manual changes.
63
+
58
64
  ## Validation
59
65
 
60
66
  ```bash
package/README.zh.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  面向 DeepSeek Harness Web 的子代理管理插件。插件在会话标题栏提供一个紧凑的 `🧩 子代理 active/total` 入口,用于搜索、筛选、分组、排序、查看和批量归档当前运行时已发现的子代理。
4
4
 
5
- 当前发布版本:**v1.3.1**
5
+ 当前发布版本:**v1.3.2**
6
6
 
7
7
  ## 主要功能
8
8
 
@@ -237,6 +237,15 @@ DSH_VERSION=0.1.1-rc.2 ./test.sh # 用 pnpx 拉取指定 dsh 版本跑 web(
237
237
 
238
238
  - 子代理永久删除、会话生命周期清理及快照刷新机制的设计参考并致谢开源项目:[@heiheiha798/dsh-plugin-subagent-delete](https://github.com/heiheiha798/dsh-plugin-subagent-delete)。
239
239
 
240
+ ## v1.3.2 发布说明
241
+
242
+ - **性能优化(显著降低卡顿)**:
243
+ - 子代理管理器改为单次基础扫描(`subagentRows`),`allRows`/`activeRows`/`tabCounts` 不再各自全表扫描并重复合并 `modeMap`;`tabCounts` 用延迟值计算、面板关闭时不计算。
244
+ - `useSessions` 细粒度订阅(只订阅 `byId`/`subagentsByParent`/`current` 三字段并浅比较),无关的会话帧不再触发整组重渲染。
245
+ - 活跃浮窗/面板**限制同时实时订阅的子代理数**(`liveCap`,默认 3,`0`=不设限);关闭实时显示或关闭浮窗/面板时**完全停止 live 订阅并释放资源**,而非仅隐藏。
246
+ - **点击子代理自动切换到「对话」选项卡**:进入子代理时自动落到对话视图。
247
+ - **修复:批量「选择 N 小时前」**:按当前视图一次性选中真正超过 N 小时的子代理(数量准确),可正常增减,取消后不会自动勾回。
248
+
240
249
  ## v1.3.1 发布说明
241
250
 
242
251
  - **兼容 dsh 0.1.2-alpha.2 与 0.1.1-rc.2**:实时输出按能力探测自动切换两条链路——新版本(0.1.2-alpha.2)走 `binding.eventSource` 原始事件流推导;旧版本(0.1.1-rc.2 及更早)回退 `chat.legacy` 对话快照。老版本行为不变,向前兼容。
package/lib/client.js CHANGED
@@ -31,23 +31,23 @@ body[data-ds-dark-theme] .dsh-sam-row-hidden{background:rgba(255,255,255,0.03)!i
31
31
  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)}
32
32
  let sessionsRt=null
33
33
  const NOOP=()=>()=>{}
34
- function LiveOutput({parentId,childId,running,prefix=true,autoLoad=true,onLoad}){
35
- const [loading,setLoading]=React.useState(false),[,bump]=React.useState(0),[lastText,setLastText]=React.useState(''),binding=React.useMemo(()=>{if(!running&&!autoLoad)return null;try{return sessionsRt?.binding?.(childId)||null}catch{return null}},[childId,running,autoLoad]),session=binding?.session||null,feed=binding?.eventSource||null
34
+ function LiveOutput({parentId,childId,running,prefix=true,autoLoad=true,onLoad,live=true}){
35
+ 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
36
36
  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])
37
37
  let text='';if(feed){const win=feed.getSnapshot?.();if(win&&win.entries){const out=liveFromEvents(win.entries,running);if(out.pendingCount)text=out.activity.join('\n');else if(running&&out.streamText)text=out.streamText;else if(out.activity.length)text=out.activity.join('\n');else text=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||'工具调用'}${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(`上下文注入 · ${n.provenance?.label||n.form||'context'}`);else if(n.kind==='tool-result')activity.push(`${n.isError?'✖':'✓'} ${n.call?.name||'工具调用'}${n.call?.argsRaw?` · ${toolDetail(n.call.argsRaw)}`:''}`);else activity.push(`⌘ ${n.name||'命令'}`)});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='⚙ 调用工具 '+b.name;break}}}
38
38
  React.useEffect(()=>{if(text)setLastText(text)},[text])
39
- if(!running&&!autoLoad){return jsx('button',{type:'button',className:'dsh-sam-load-live-btn',onClick:e=>{e.stopPropagation();setLoading(true);onLoad?.()},title:'加载该子代理的历史最新消息',children:loading?'⏳ 加载中...':'📥 加载最新消息'})}
39
+ if(!wantLive){return jsx('button',{type:'button',className:'dsh-sam-load-live-btn',onClick:e=>{e.stopPropagation();setLoading(true);onLoad?.()},title:'加载该子代理的历史最新消息',children:loading?'⏳ 加载中...':'📥 加载最新消息'})}
40
40
  if(!session)return null
41
41
  const shown=text||lastText,lines=shown.slice(-400).split('\n').filter(Boolean);return shown?jsx('div',{className:`dsh-sam-live ${running?'dsh-sam-live-running':'dsh-sam-live-final'}`,children:[prefix&&jsx('span',{className:'dsh-sam-live-prefix',children:'实时输出:'}),lines.map((line,index)=>jsx('span',{className:index===lines.length-1?'dsh-sam-live-latest':'dsh-sam-live-old',children:line},index))]}):null
42
42
  }
43
43
  const elapsed=t=>{const seconds=Math.max(0,Math.floor((Date.now()-(t||Date.now()))/1000));return seconds>=3600?`${Math.floor(seconds/3600)}时${Math.floor(seconds%3600/60)}分`:seconds>=60?`${Math.floor(seconds/60)}分${seconds%60}秒`:`${seconds}秒`},compactPath=v=>{const value=String(v).replace(/\\/g,'/'),max=72;if(value.length<=max)return value;const parts=value.split('/').filter(Boolean);let result=parts.pop()||value;while(parts.length&&(`.../${parts[parts.length-1]}/${result}`).length<=max)result=`${parts.pop()}/${result}`;return `.../${result}`},toolDetail=v=>{if(!v)return '';try{const value=JSON.parse(v),key=value.description!=null?'description':value.command!=null?'command':value.file_path!=null?'file_path':value.path!=null?'path':value.prompt!=null?'prompt':null,preferred=key?value[key]:undefined;if(preferred)return (key==='file_path'||key==='path'?compactPath: String)(String(preferred).split('\n')[0].slice(0,100));const first=Object.values(value).find(x=>typeof x==='string');return first?first.split('\n')[0].slice(0,100):String(v).slice(0,100)}catch{return String(v).split('\n')[0].slice(0,100)}}
44
44
  const liveFromEvents=(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 '⚙ 调用工具 '+b.name}return ''};let text='',reasoning='',finalText='',hasStream=false,lastKind='text';const pending=[],done=[],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||'工具调用',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||'工具调用',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 '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||'工具调用',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||'工具调用'}${r.complete&&r.args?` · ${toolDetail(r.args)}`:''}`),...done.slice(-2).map(r=>`${r.isError?'✖':'✓'} ${r.name||'工具调用'}${r.complete&&r.args?` · ${toolDetail(r.args)}`:''}`)],streamText:hasStream?((lastKind==='reasoning'?'💭 ':'')+tail(lastKind==='reasoning'?reasoning:text)):'',finalText}}
45
- function ActiveFloat({rows,openRow,onHide,stopAgent,stopAllAgents,stoppingIds,liveEnabled,onLiveChange}){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:`活跃子代理 · ${rows.length}`}),jsxs('div',{className:'dsh-sam-active-actions',children:[continuableRows.length>0&&jsx('button',{type:'button',className:'dsh-sam-stop-all-btn',title:'一键暂停所有活跃可继续子代理',disabled:continuableRows.some(r=>stoppingIds.has(r.id)),onClick:e=>{e.stopPropagation();stopAllAgents(continuableRows)},children:continuableRows.some(r=>stoppingIds.has(r.id))?'暂停中':'⏸ 一键暂停'}),jsx('label',{className:'dsh-sam-active-live-toggle',children:[jsx('input',{type:'checkbox',checked:liveEnabled,onChange:e=>onLiveChange(e.target.checked)}),'实时输出']}),jsx('button',{type:'button',className:'dsh-sam-active-close',onClick:e=>{e.stopPropagation();onHide()},'aria-label':'隐藏活跃子代理浮窗',children:'×'})]})]}),rows.map(row=>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(row.createdAt||row.updatedAt)}),row.mode!=='one-shot'&&jsx('button',{type:'button',className:'dsh-sam-stop-btn',disabled:stoppingIds.has(row.id),onClick:e=>{e.stopPropagation();stopAgent(row)},'aria-label':`暂停 ${row.name}`,'title':'暂停子代理',children:stoppingIds.has(row.id)?'暂停中':'⏸ 暂停'})]}),liveEnabled&&jsx(LiveOutput,{parentId:row.parentId,childId:row.id,running:true,prefix:false}),jsx('div',{className:'dsh-sam-active-stats',children:`输入 ${fmt(row.projectionValues?.tokenUsage?.uncachedInputTokens)} / 输出 ${fmt(row.projectionValues?.tokenUsage?.outputTokens)} · 缓存命中 ${row.projectionValues?.tokenUsage?.cacheReadTokens!=null&&tokenTotal(row)?Math.round(row.projectionValues.tokenUsage.cacheReadTokens/tokenTotal(row)*100):'未知'}% · 轮数 ${row.projectionValues?.sessionStats?.turns??row.projectionValues?.turns??'未知'} · 步数 ${row.projectionValues?.sessionStats?.steps??row.projectionValues?.steps??'未知'}`})]},row.id))]})}
46
- function Manager({useSessions,openChild,openSession,refresh,setCatalogOpen,sessionId}){
47
- const state=useSessions(s=>s),[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)
45
+ function ActiveFloat({rows,openRow,onHide,stopAgent,stopAllAgents,stoppingIds,liveEnabled,onLiveChange,liveCap}){const [,tick]=React.useState(0),[position,setPosition]=React.useState(null),drag=React.useRef(null);React.useEffect(()=>{const timer=setInterval(()=>tick(v=>v+1),1000);return()=>clearInterval(timer)},[]);const move=e=>{if(!drag.current)return;const {offsetX,offsetY,width,height}=drag.current;setPosition({x:Math.max(8,Math.min(window.innerWidth-width-8,e.clientX-offsetX)),y:Math.max(8,Math.min(window.innerHeight-height-8,e.clientY-offsetY))})},startDrag=e=>{if(e.button!==0||e.target.closest('button,input,label'))return;const rect=e.currentTarget.parentElement.getBoundingClientRect();drag.current={offsetX:e.clientX-rect.left,offsetY:e.clientY-rect.top,width:rect.width,height:rect.height};e.currentTarget.setPointerCapture?.(e.pointerId)},stopDrag=()=>{drag.current=null},dragStyle=position?{left:position.x,top:position.y,right:'auto'}:undefined;const continuableRows=rows.filter(r=>r.mode!=='one-shot');return jsx('aside',{className:'dsh-sam-active-float',style:dragStyle,onPointerMove:move,onPointerUp:stopDrag,onPointerCancel:stopDrag,role:'status',children:[jsxs('div',{className:'dsh-sam-active-head dsh-sam-active-drag-handle',onPointerDown:startDrag,children: [jsx('span',{children:`活跃子代理 · ${rows.length}`}),jsxs('div',{className:'dsh-sam-active-actions',children:[continuableRows.length>0&&jsx('button',{type:'button',className:'dsh-sam-stop-all-btn',title:'一键暂停所有活跃可继续子代理',disabled:continuableRows.some(r=>stoppingIds.has(r.id)),onClick:e=>{e.stopPropagation();stopAllAgents(continuableRows)},children:continuableRows.some(r=>stoppingIds.has(r.id))?'暂停中':'⏸ 一键暂停'}),jsx('label',{className:'dsh-sam-active-live-toggle',children:[jsx('input',{type:'checkbox',checked:liveEnabled,onChange:e=>onLiveChange(e.target.checked)}),'实时输出']}),jsx('button',{type:'button',className:'dsh-sam-active-close',onClick:e=>{e.stopPropagation();onHide()},'aria-label':'隐藏活跃子代理浮窗',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(row.createdAt||row.updatedAt)}),row.mode!=='one-shot'&&jsx('button',{type:'button',className:'dsh-sam-stop-btn',disabled:stoppingIds.has(row.id),onClick:e=>{e.stopPropagation();stopAgent(row)},'aria-label':`暂停 ${row.name}`,'title':'暂停子代理',children:stoppingIds.has(row.id)?'暂停中':'⏸ 暂停'})]}),liveEnabled&&(liveCap<=0||idx<liveCap)&&jsx(LiveOutput,{parentId:row.parentId,childId:row.id,running:true,prefix:false}),jsx('div',{className:'dsh-sam-active-stats',children:`输入 ${fmt(row.projectionValues?.tokenUsage?.uncachedInputTokens)} / 输出 ${fmt(row.projectionValues?.tokenUsage?.outputTokens)} · 缓存命中 ${row.projectionValues?.tokenUsage?.cacheReadTokens!=null&&tokenTotal(row)?Math.round(row.projectionValues.tokenUsage.cacheReadTokens/tokenTotal(row)*100):'未知'}% · 轮数 ${row.projectionValues?.sessionStats?.turns??row.projectionValues?.turns??'未知'} · 步数 ${row.projectionValues?.sessionStats?.steps??row.projectionValues?.steps??'未知'}`})]},row.id))]})}
46
+ function Manager({useSessions,openChild,openSession,refresh,setCatalogOpen,sessionId,actions}){
47
+ 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)
48
48
  const 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
49
- const allRows=React.useMemo(()=>{const modes=modeMap(state.subagentsByParent),rawTerm=query.trim().toLocaleLowerCase(),idOnly=rawTerm.startsWith('id:'),term=idOnly?rawTerm.slice(3).trim():rawTerm;return Object.values(state.byId).filter(s=>s.origin==='subagent').map(s=>({...s,...modes[s.id],name:modes[s.id]?.label||title(s)})).filter(s=>{const parent=s.parentId?state.byId[s.parentId]:undefined;if(workspaceKey&&parent?.cwd!==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(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(a.mode).localeCompare(modeLabel(b.mode)):b.updatedAt-a.updatedAt})},[state,query,sort,prefs,scope,currentCwd,currentId,scopeDetail,workspaceKey,selectedSession,tab,tabs,recentIds])
50
- const activeRows=React.useMemo(()=>{const modes=modeMap(state.subagentsByParent);return Object.values(state.byId).filter(s=>s.origin==='subagent'&&s.running).map(s=>({...s,...modes[s.id],name:modes[s.id]?.label||title(s)})).filter(s=>{const parent=s.parentId?state.byId[s.parentId]:undefined;return(!currentCwd||parent?.cwd===currentCwd)&&(prefs.showArchived||!archived.has(s.id))&&(!prefs.hideOneShot||s.mode!=='one-shot')}).sort((a,b)=>b.updatedAt-a.updatedAt)},[state,currentCwd,prefs,archived])
49
+ const modes=React.useMemo(()=>modeMap(state.subagentsByParent),[state.subagentsByParent]),subagentRows=React.useMemo(()=>{const byId=state.byId;return Object.values(byId).filter(s=>s.origin==='subagent').map(s=>({...s,...modes[s.id],name:modes[s.id]?.label||title(s),parentCwd:byId[s.parentId]?.cwd}))},[state.byId,modes]),allRows=React.useMemo(()=>{if(!open)return [];const rawTerm=query.trim().toLocaleLowerCase(),idOnly=rawTerm.startsWith('id:'),term=idOnly?rawTerm.slice(3).trim():rawTerm;return subagentRows.filter(s=>{if(workspaceKey&&s.parentCwd!==workspaceKey)return false;if(selectedSession!=='all'&&s.parentId!==selectedSession)return false;const unfiltered=tab==='all';if(!prefs.showArchived&&archived.has(s.id))return false;if(prefs.hideOneShot&&s.mode==='one-shot')return false;if(!unfiltered&&prefs.hideOld&&!s.running&&Date.now()-s.updatedAt>(prefs.oldDays||30)*DAY)return false;const custom=tabs.find(t=>t.id===tab);if(custom?.regex==='__OTHER__'){const matched=tabs.some(t=>!['filtered','all','other'].includes(t.id)&&t.regex&&(()=>{try{return new RegExp(t.regex,'i').test(s.name)}catch{return false}})());if(matched)return false}else if(custom?.regex&&custom.regex!=='__ALL__'){try{if(!new RegExp(custom.regex,'i').test(s.name))return false}catch{return false}}return !term||`${idOnly?`${s.id} ${s.parentId||''}`:`${s.name} ${title(s)} ${workspace(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(a.mode).localeCompare(modeLabel(b.mode)):b.updatedAt-a.updatedAt})},[open,subagentRows,query,sort,prefs,scope,currentCwd,currentId,scopeDetail,workspaceKey,selectedSession,tab,tabs,recentIds])
50
+ 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])
51
51
  const stopAgent=async row=>{if(row.mode==='one-shot'||stoppingIds.has(row.id))return;if(!window.confirm(`确认暂停子代理“${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})}}
52
52
  const stopAllAgents=async rowsToStop=>{const targetRows=rowsToStop.filter(r=>r.mode!=='one-shot'&&!stoppingIds.has(r.id));if(!targetRows.length)return;if(!window.confirm(`确认暂停选中的 ${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})}}
53
53
 
@@ -114,13 +114,13 @@ body[data-ds-dark-theme] .dsh-sam-row-hidden{background:rgba(255,255,255,0.03)!i
114
114
  currentSortName=sort==='recent'?'最近活跃':sort==='title'?'名字':'类型',
115
115
  currentGroupName=grouping==='session'?'按会话':grouping==='workspace'?'按工作区':grouping==='category'?'按分类':grouping==='type'?'按类型':'不分组'
116
116
 
117
- const tabCounts=React.useMemo(()=>{const modes=modeMap(state.subagentsByParent),candidates=Object.values(state.byId).filter(s=>s.origin==='subagent').map(s=>({...s,...modes[s.id],name:modes[s.id]?.label||title(s)})).filter(s=>{const parent=s.parentId?state.byId[s.parentId]:undefined;return(!workspaceKey||parent?.cwd===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},[state,workspaceKey,selectedSession,prefs,tabs]),rows=allRows.slice(0,limit),currentSessionRows=Object.values(state.byId).filter(r=>r.origin==='subagent'&&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
117
+ 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
118
118
  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?'活跃子代理':grouping==='session'?`${workspace(parent||row)} · ${title(parent||current)}`:grouping==='type'?modeLabel(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?hit.name:'其他'})():grouping==='workspace'?workspace(parent||row):grouping==='none'?'全部结果':sameSession?'当前会话':sameWorkspace?`当前工作区 · ${workspace(parent||row)}`:(parent?`${workspace(parent)} · ${title(parent)}`:'其他会话');(out[bucket]||=[]).push(row)}return out},[rows,grouping,state.byId,sessionId,state.current,currentCwd])
119
119
  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])
120
- React.useEffect(()=>{const runningIds=allRows.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})},[allRows]);React.useEffect(()=>{if(!allRows.length)return;const runningIds=allRows.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:allRows.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)})},[allRows]);React.useEffect(()=>()=>{noticeTimers.current.forEach(timer=>clearTimeout(timer));noticeTimers.current.clear()},[]);React.useEffect(()=>{if(oldHours==null)return;const cutoff=Date.now()-oldHours*3600000;setSelectedIds(prev=>{const next=new Set(allRows.filter(r=>r.updatedAt<=cutoff).slice(0,1000).map(r=>r.id));return next.size===prev.size&&[...next].every(id=>prev.has(id))?prev:next})},[allRows,oldHours]);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('选择多少小时前的子代理?','24'));if(!Number.isFinite(hours)||hours<0)return;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);setOpen(false);setBatchMode(false)}catch(e){console.warn('Unable to open subagent',e)}}
120
+ 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('选择多少小时前的子代理?','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);actions?.setView?.('chat');setOpen(false);setBatchMode(false)}catch(e){console.warn('Unable to open subagent',e)}}
121
121
  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])
122
122
  const activeGroupContinuableRows=groups['活跃子代理']?.filter(r=>r.mode!=='one-shot')||[]
123
- return jsxs(React.Fragment,{children:[(!open&&prefs.activeFloat!==false&&Boolean(activeRows.length)&&!floatHidden)?jsx(ActiveFloat,{rows:activeRows,openRow,onHide:()=>setFloatHidden(true),stopAgent,stopAllAgents,stoppingIds,liveEnabled:prefs.activeFloatLive!==false,onLiveChange:value=>setPrefs(p=>({...p,activeFloatLive:value}))}):null,jsxs('div',{className:'dsh-sam-trigger-wrap',children:[jsx('button',{type:'button',className:'dsh-sam-trigger',onClick:()=>{setLimit(PAGE);setOpen(true)},title:'打开子代理管理',children:[jsx('span',{className:`dsh-sam-icon ${active>0?'dsh-sam-pulse':''}`,children:'🧩'}),jsx('span',{children:`子代理 ${active}/${currentCount}`})]}),!open&&newAgents.map((item,index)=>jsx('div',{className:'dsh-sam-new-agent',style:{top:`calc(100% + ${6+index*34}px)`},role:'status',children:`新子代理:${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:'子代理管理'}),jsxs('div',{className:'dsh-sam-head-sub',children:[jsx('div',{className:'dsh-sam-summary',children:`当前会话 ${allRows.filter(r=>r.parentId===currentId).length} 个 · 当前工作区 ${allRows.filter(r=>currentCwd&&state.byId[r.parentId]?.cwd===currentCwd).length} 个 · 活跃 ${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}))}}),'显示活跃浮窗']})]})]}),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:[t.name,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:`删除分类“${t.name}”`,'aria-label':`删除分类“${t.name}”`,onClick:e=>{e.stopPropagation();if(!window.confirm(`确认删除分类“${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('分类名称');if(!name)return;const regex=window.prompt('匹配正则(例如:^审计|review)');if(!regex)return;setPrefs(p=>({...p,tabs:[...(p.tabs||defaultTabs),{id:`tab-${Date.now()}`,name,regex}]}))},children:'+ 新建分类'})]}),jsxs('div',{className:'dsh-sam-controls',children:[jsx('button',{type:'button',className:'dsh-sam-filter-btn',onClick:()=>setFilterOpen(v=>!v),children:`⚙ 筛选排序 · ${scope==='currentWorkspace'?'当前工作区':scope==='currentSession'?'当前会话':'自定义范围'} · ${sort==='recent'?'最近活跃':sort==='title'?'名字':'类型'}`}),!prefs.filterCollapsed&&jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},'aria-label':'显示范围',children:[jsx('option',{value:'currentWorkspace',children:'当前工作区'}),jsx('option',{value:'all',children:'全部工作区'}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:workspace({cwd:c})},c))]}),!prefs.filterCollapsed&&jsx('select',{value:selectedSession,onChange:e=>setSessionScope(e.target.value),children:[jsx('option',{value:'all',children:'全部会话'}),...availableSessions.map(s=>jsx('option',{value:s.id,children:s.id===currentId?`当前会话 · ${title(s)}`:title(s)},s.id))]}),jsxs('div',{className:'dsh-sam-search-wrap',children:[jsx('input',{autoFocus:true,value:query,placeholder:'搜索名称、标题或工作区;输入 id: 搜索 Session ID',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:'清空搜索',onClick:()=>setQuery(''),children:'×'}),jsx('button',{type:'button',className:'dsh-sam-filter-toggle',title:prefs.filterCollapsed?'展开筛选与配置':'折叠筛选与配置',onClick:()=>setPrefs(p=>({...p,filterCollapsed:!p.filterCollapsed})),children:prefs.filterCollapsed?'⚙ 展开筛选 ▾':'⚙ 折叠 ▴'})]})]}),!prefs.filterCollapsed&&jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session','分组:按会话'],['workspace','分组:按工作区'],['category','分组:按分类'],['type','分组:按类型'],['none','分组:不分组']].map(([v,l])=>jsx('option',{value:v,children:l},v))}),!prefs.filterCollapsed&&jsx('select',{value:sort,onChange:e=>setSort(e.target.value),children:[['recent','排序:最近活跃'],['title','排序:名字'],['type','排序:类型']].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),filterOpen&&jsxs('div',{className:'dsh-sam-filter-popover',children:[jsx('label',{children:['范围',jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},children:[jsx('option',{value:'currentWorkspace',children:'当前工作区'}),jsx('option',{value:'currentSession',children:'当前会话'}),jsx('option',{value:'all',children:'全部工作区'}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:`工作区 · ${workspace({cwd:c})}`},c)),...parentRows.map(s=>jsx('option',{value:`session:${s.id}`,children:`会话 · ${workspace(s)} / ${title(s)}`},s.id))]})]}),jsx('label',{children:['分组',jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session','按会话'],['workspace','按工作区'],['category','按分类'],['type','按类型'],['none','不分组']].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),jsx('label',{children:['排序',jsx('select',{value:sort,onChange:e=>{setSort(e.target.value);setLimit(PAGE)},children:[['recent','最近活跃'],['title','名字'],['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}))}),'隐藏一次性']}),jsx('label',{children:[jsx('input',{type:'checkbox',checked:!!prefs.hideOld,onChange:()=>setPrefs(p=>({...p,hideOld:!p.hideOld}))}),'隐藏长期未活跃']}),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}))}),'子代理背景色']}),prefs.customSubagentBg!==false&&jsxs(React.Fragment,{children:[jsx('label',{title:'浅色主题下的子代理背景色',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}))}),'浅色']}),jsx('label',{title:'深色主题下的子代理背景色',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}))}),'深色']})]})]}),jsx('button',{type:'button',onClick:()=>{setQuery('');setScope('currentWorkspace');setScopeDetail('');setSessionScope('all');setTab('all');setGrouping('session');setSort('recent');setLimit(PAGE)},children:'重置筛选'})]}),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:`排序 · ${currentSortName}`}),jsx('span',{children:`分组 · ${currentGroupName}`})]})]}),jsxs('div',{className:'dsh-sam-summary-line',children:[jsxs('div',{className:'dsh-sam-summary-items',children:[jsx('span',{className:'dsh-sam-summary',children:`显示 ${rows.length}/${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}))}),'显示详情']}),jsx('label',{className:'dsh-sam-summary-hidden-toggle',children:[jsx('input',{type:'checkbox',checked:!!prefs.showArchived,onChange:()=>setPrefs(p=>({...p,showArchived:!p.showArchived}))}),'显示已隐藏']}),jsx('span',{className:'dsh-sam-summary',style:{fontSize:'11px'},children:'隐藏仅在列表不显示,不删除会话'})]}),jsx('button',{type:'button',className:`dsh-sam-batch-btn ${batchMode?'dsh-sam-batch-done':''}`,onClick:()=>{setBatchMode(v=>!v);setSelectedIds(new Set)},children:batchMode?'完成':'批量操作'})]}),batchMode&&jsxs('div',{className:'dsh-sam-batch-bar',children:[jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set(allRows.map(r=>r.id))),children:'全选'}),jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set),children:'清空'}),jsx('button',{type:'button',onClick:selectOld,children:'选择 N 小时前'}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(false),title:'将选中的子代理隐藏',children:`批量隐藏 (${selectedIds.size})`}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(true),title:'取消隐藏选中的子代理',children:'批量显示'}),jsx('button',{type:'button',onClick:()=>{if(!window.confirm('确认隐藏当前筛选出的全部子代理?'))return;batchArchive(allRows.map(r=>r.id));setSelectedIds(new Set)},children:'一键全部隐藏'}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',disabled:!selectedIds.size,onClick:()=>batchDeleteSubagents([...selectedIds]),children:`批量删除 (${selectedIds.size})`}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',onClick:()=>batchDeleteSubagents(allRows.map(r=>r.id)),children:'一键删除全部'})]}),jsx('div',{className:'dsh-sam-list',onWheel:e=>e.stopPropagation(),children:Object.keys(groups).length===0?jsx('div',{className:'dsh-sam-empty',children:'没有符合条件的子代理。'}):Object.entries(groups).map(([name,entries])=>jsxs('section',{className:'dsh-sam-group',children:[jsxs('div',{className:'dsh-sam-group-head',onClick:()=>name==='活跃子代理'&&setActiveOpen(v=>!v),children:[jsx('span',{children:`${name}${name==='活跃子代理'?(activeOpen?' ▾':' ▸'):''}`}),jsxs('div',{className:'dsh-sam-group-head-actions',children:[name==='活跃子代理'&&activeGroupContinuableRows.length>0&&jsx('button',{type:'button',className:'dsh-sam-stop-all-btn',title:'一键暂停所有活跃可继续子代理',disabled:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id)),onClick:e=>{e.stopPropagation();stopAllAgents(activeGroupContinuableRows)},children:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id))?'暂停中':'⏸ 一键暂停'}),jsx('span',{children:entries.length})]})]}),(name==='活跃子代理'&&!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)},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':`选择 ${row.name}`}),archived.has(row.id)?jsx('span',{className:'dsh-sam-dot hidden-dot',title:'已隐藏',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:`${row.name}\n${row.id}`,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:'⚡ 一次性'}),jsx('small',{className:'dsh-sam-session-id',children:row.id})]})}),grouping==='session'?null:jsx('div',{className:'dsh-sam-meta',children:highlight(`${modeLabel(row.mode)}${grouping==='session'?'':` · ${row.parentId?`${workspace(state.byId[row.parentId]||row)} / ${title(state.byId[row.parentId]||row)}`:'无父会话'}`}`,query)})]})}),jsx('span',{className:'dsh-sam-time',title:`最近活动:${new Date(row.updatedAt).toLocaleString()}`,children:age(row.updatedAt)}),batchMode?(archived.has(row.id)&&jsx('span',{className:'dsh-sam-archived-label',children:'已隐藏'})):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':`暂停 ${row.name}`,'title':'暂停子代理',children:stoppingIds.has(row.id)?'暂停中':'⏸ 暂停'}),jsx('button',{type:'button',className:'dsh-sam-hide-btn',onClick:e=>{e.stopPropagation();archive(row)},title:archived.has(row.id)?'取消隐藏':'隐藏(仅在列表隐藏,不删除会话)','aria-label':`${archived.has(row.id)?'取消隐藏':'隐藏'} ${row.name}`,children:archived.has(row.id)?'👁 显示':'⊘ 隐藏'}),jsx('button',{type:'button',className:'dsh-sam-delete-btn',onClick:e=>{e.stopPropagation();deleteSubagent(row)},title:'永久删除该子代理','aria-label':`删除 ${row.name}`,children:'\u{1F5D1} 删除'})]}),prefs.showDetails!==false&&jsxs('div',{className:'dsh-sam-details',children:[jsx('div',{children:`输入 ${fmt(row.projectionValues?.tokenUsage?.uncachedInputTokens)} / 输出 ${fmt(row.projectionValues?.tokenUsage?.outputTokens)} · 缓存命中 ${row.projectionValues?.tokenUsage?.cacheReadTokens!=null&&tokenTotal(row)?Math.round(row.projectionValues.tokenUsage.cacheReadTokens/tokenTotal(row)*100):'未知'}% · 轮数 ${row.projectionValues?.sessionStats?.turns??row.projectionValues?.turns??'未知'} · 步数 ${row.projectionValues?.sessionStats?.steps??row.projectionValues?.steps??'未知'}`}),promptPreview(row)&&jsx('div',{children:`提示词:${promptPreview(row)}`}),jsx(LiveOutput,{parentId:row.parentId,childId:row.id,running:row.running,autoLoad:rows.slice(0,10).some(r=>r.id===row.id)||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:`加载下一页(剩余 ${allRows.length-limit} 个)`})]},name))})]})})]})
123
+ return jsxs(React.Fragment,{children:[(!open&&prefs.activeFloat!==false&&Boolean(activeRows.length)&&!floatHidden)?jsx(ActiveFloat,{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:'打开子代理管理',children:[jsx('span',{className:`dsh-sam-icon ${active>0?'dsh-sam-pulse':''}`,children:'🧩'}),jsx('span',{children:`子代理 ${active}/${currentCount}`})]}),!open&&newAgents.map((item,index)=>jsx('div',{className:'dsh-sam-new-agent',style:{top:`calc(100% + ${6+index*34}px)`},role:'status',children:`新子代理:${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:'子代理管理'}),jsxs('div',{className:'dsh-sam-head-sub',children:[jsx('div',{className:'dsh-sam-summary',children:`当前会话 ${allRows.filter(r=>r.parentId===currentId).length} 个 · 当前工作区 ${allRows.filter(r=>currentCwd&&state.byId[r.parentId]?.cwd===currentCwd).length} 个 · 活跃 ${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}))}}),'显示活跃浮窗']})]})]}),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:[t.name,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:`删除分类“${t.name}”`,'aria-label':`删除分类“${t.name}”`,onClick:e=>{e.stopPropagation();if(!window.confirm(`确认删除分类“${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('分类名称');if(!name)return;const regex=window.prompt('匹配正则(例如:^审计|review)');if(!regex)return;setPrefs(p=>({...p,tabs:[...(p.tabs||defaultTabs),{id:`tab-${Date.now()}`,name,regex}]}))},children:'+ 新建分类'})]}),jsxs('div',{className:'dsh-sam-controls',children:[jsx('button',{type:'button',className:'dsh-sam-filter-btn',onClick:()=>setFilterOpen(v=>!v),children:`⚙ 筛选排序 · ${scope==='currentWorkspace'?'当前工作区':scope==='currentSession'?'当前会话':'自定义范围'} · ${sort==='recent'?'最近活跃':sort==='title'?'名字':'类型'}`}),!prefs.filterCollapsed&&jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},'aria-label':'显示范围',children:[jsx('option',{value:'currentWorkspace',children:'当前工作区'}),jsx('option',{value:'all',children:'全部工作区'}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:workspace({cwd:c})},c))]}),!prefs.filterCollapsed&&jsx('select',{value:selectedSession,onChange:e=>setSessionScope(e.target.value),children:[jsx('option',{value:'all',children:'全部会话'}),...availableSessions.map(s=>jsx('option',{value:s.id,children:s.id===currentId?`当前会话 · ${title(s)}`:title(s)},s.id))]}),jsxs('div',{className:'dsh-sam-search-wrap',children:[jsx('input',{autoFocus:true,value:query,placeholder:'搜索名称、标题或工作区;输入 id: 搜索 Session ID',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:'清空搜索',onClick:()=>setQuery(''),children:'×'}),jsx('button',{type:'button',className:'dsh-sam-filter-toggle',title:prefs.filterCollapsed?'展开筛选与配置':'折叠筛选与配置',onClick:()=>setPrefs(p=>({...p,filterCollapsed:!p.filterCollapsed})),children:prefs.filterCollapsed?'⚙ 展开筛选 ▾':'⚙ 折叠 ▴'})]})]}),!prefs.filterCollapsed&&jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session','分组:按会话'],['workspace','分组:按工作区'],['category','分组:按分类'],['type','分组:按类型'],['none','分组:不分组']].map(([v,l])=>jsx('option',{value:v,children:l},v))}),!prefs.filterCollapsed&&jsx('select',{value:sort,onChange:e=>setSort(e.target.value),children:[['recent','排序:最近活跃'],['title','排序:名字'],['type','排序:类型']].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),filterOpen&&jsxs('div',{className:'dsh-sam-filter-popover',children:[jsx('label',{children:['范围',jsx('select',{value:scope,onChange:e=>{setScope(e.target.value);setSessionScope('all');setLimit(PAGE)},children:[jsx('option',{value:'currentWorkspace',children:'当前工作区'}),jsx('option',{value:'currentSession',children:'当前会话'}),jsx('option',{value:'all',children:'全部工作区'}),...scopeOptions.map(c=>jsx('option',{value:`workspace:${c}`,children:`工作区 · ${workspace({cwd:c})}`},c)),...parentRows.map(s=>jsx('option',{value:`session:${s.id}`,children:`会话 · ${workspace(s)} / ${title(s)}`},s.id))]})]}),jsx('label',{children:['分组',jsx('select',{value:grouping,onChange:e=>{setGrouping(e.target.value);setLimit(PAGE)},children:[['session','按会话'],['workspace','按工作区'],['category','按分类'],['type','按类型'],['none','不分组']].map(([v,l])=>jsx('option',{value:v,children:l},v))})]}),jsx('label',{children:['排序',jsx('select',{value:sort,onChange:e=>{setSort(e.target.value);setLimit(PAGE)},children:[['recent','最近活跃'],['title','名字'],['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}))}),'隐藏一次性']}),jsx('label',{children:[jsx('input',{type:'checkbox',checked:!!prefs.hideOld,onChange:()=>setPrefs(p=>({...p,hideOld:!p.hideOld}))}),'隐藏长期未活跃']}),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}))}),'子代理背景色']}),prefs.customSubagentBg!==false&&jsxs(React.Fragment,{children:[jsx('label',{title:'浅色主题下的子代理背景色',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}))}),'浅色']}),jsx('label',{title:'深色主题下的子代理背景色',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}))}),'深色']})]})]}),jsx('button',{type:'button',onClick:()=>{setQuery('');setScope('currentWorkspace');setScopeDetail('');setSessionScope('all');setTab('all');setGrouping('session');setSort('recent');setLimit(PAGE)},children:'重置筛选'})]}),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:`排序 · ${currentSortName}`}),jsx('span',{children:`分组 · ${currentGroupName}`})]})]}),jsxs('div',{className:'dsh-sam-summary-line',children:[jsxs('div',{className:'dsh-sam-summary-items',children:[jsx('span',{className:'dsh-sam-summary',children:`显示 ${rows.length}/${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}))}),'显示详情']}),jsx('label',{className:'dsh-sam-summary-hidden-toggle',children:[jsx('input',{type:'checkbox',checked:!!prefs.showArchived,onChange:()=>setPrefs(p=>({...p,showArchived:!p.showArchived}))}),'显示已隐藏']}),jsx('span',{className:'dsh-sam-summary',style:{fontSize:'11px'},children:'隐藏仅在列表不显示,不删除会话'})]}),jsx('button',{type:'button',className:`dsh-sam-batch-btn ${batchMode?'dsh-sam-batch-done':''}`,onClick:()=>{setBatchMode(v=>!v);setSelectedIds(new Set)},children:batchMode?'完成':'批量操作'})]}),batchMode&&jsxs('div',{className:'dsh-sam-batch-bar',children:[jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set(allRows.map(r=>r.id))),children:'全选'}),jsx('button',{type:'button',onClick:()=>setSelectedIds(new Set),children:'清空'}),jsx('button',{type:'button',onClick:selectOld,children:'选择 N 小时前'}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(false),title:'将选中的子代理隐藏',children:`批量隐藏 (${selectedIds.size})`}),jsx('button',{type:'button',disabled:!selectedIds.size,onClick:()=>archiveSelected(true),title:'取消隐藏选中的子代理',children:'批量显示'}),jsx('button',{type:'button',onClick:()=>{if(!window.confirm('确认隐藏当前筛选出的全部子代理?'))return;batchArchive(allRows.map(r=>r.id));setSelectedIds(new Set)},children:'一键全部隐藏'}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',disabled:!selectedIds.size,onClick:()=>batchDeleteSubagents([...selectedIds]),children:`批量删除 (${selectedIds.size})`}),jsx('button',{type:'button',className:'dsh-sam-batch-delete-btn',onClick:()=>batchDeleteSubagents(allRows.map(r=>r.id)),children:'一键删除全部'})]}),jsx('div',{className:'dsh-sam-list',onWheel:e=>e.stopPropagation(),children:Object.keys(groups).length===0?jsx('div',{className:'dsh-sam-empty',children:'没有符合条件的子代理。'}):Object.entries(groups).map(([name,entries])=>jsxs('section',{className:'dsh-sam-group',children:[jsxs('div',{className:'dsh-sam-group-head',onClick:()=>name==='活跃子代理'&&setActiveOpen(v=>!v),children:[jsx('span',{children:`${name}${name==='活跃子代理'?(activeOpen?' ▾':' ▸'):''}`}),jsxs('div',{className:'dsh-sam-group-head-actions',children:[name==='活跃子代理'&&activeGroupContinuableRows.length>0&&jsx('button',{type:'button',className:'dsh-sam-stop-all-btn',title:'一键暂停所有活跃可继续子代理',disabled:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id)),onClick:e=>{e.stopPropagation();stopAllAgents(activeGroupContinuableRows)},children:activeGroupContinuableRows.some(r=>stoppingIds.has(r.id))?'暂停中':'⏸ 一键暂停'}),jsx('span',{children:entries.length})]})]}),(name==='活跃子代理'&&!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)},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':`选择 ${row.name}`}),archived.has(row.id)?jsx('span',{className:'dsh-sam-dot hidden-dot',title:'已隐藏',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:`${row.name}\n${row.id}`,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:'⚡ 一次性'}),jsx('small',{className:'dsh-sam-session-id',children:row.id})]})}),grouping==='session'?null:jsx('div',{className:'dsh-sam-meta',children:highlight(`${modeLabel(row.mode)}${grouping==='session'?'':` · ${row.parentId?`${workspace(state.byId[row.parentId]||row)} / ${title(state.byId[row.parentId]||row)}`:'无父会话'}`}`,query)})]})}),jsx('span',{className:'dsh-sam-time',title:`最近活动:${new Date(row.updatedAt).toLocaleString()}`,children:age(row.updatedAt)}),batchMode?(archived.has(row.id)&&jsx('span',{className:'dsh-sam-archived-label',children:'已隐藏'})):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':`暂停 ${row.name}`,'title':'暂停子代理',children:stoppingIds.has(row.id)?'暂停中':'⏸ 暂停'}),jsx('button',{type:'button',className:'dsh-sam-hide-btn',onClick:e=>{e.stopPropagation();archive(row)},title:archived.has(row.id)?'取消隐藏':'隐藏(仅在列表隐藏,不删除会话)','aria-label':`${archived.has(row.id)?'取消隐藏':'隐藏'} ${row.name}`,children:archived.has(row.id)?'👁 显示':'⊘ 隐藏'}),jsx('button',{type:'button',className:'dsh-sam-delete-btn',onClick:e=>{e.stopPropagation();deleteSubagent(row)},title:'永久删除该子代理','aria-label':`删除 ${row.name}`,children:'\u{1F5D1} 删除'})]}),prefs.showDetails!==false&&jsxs('div',{className:'dsh-sam-details',children:[jsx('div',{children:`输入 ${fmt(row.projectionValues?.tokenUsage?.uncachedInputTokens)} / 输出 ${fmt(row.projectionValues?.tokenUsage?.outputTokens)} · 缓存命中 ${row.projectionValues?.tokenUsage?.cacheReadTokens!=null&&tokenTotal(row)?Math.round(row.projectionValues.tokenUsage.cacheReadTokens/tokenTotal(row)*100):'未知'}% · 轮数 ${row.projectionValues?.sessionStats?.turns??row.projectionValues?.turns??'未知'} · 步数 ${row.projectionValues?.sessionStats?.steps??row.projectionValues?.steps??'未知'}`}),promptPreview(row)&&jsx('div',{children:`提示词:${promptPreview(row)}`}),jsx(LiveOutput,{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:`加载下一页(剩余 ${allRows.length-limit} 个)`})]},name))})]})})]})
124
124
  }
125
125
  function apply(ctx){sessionsRt=ctx.sessions;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,inject:face},Manager))}
126
126
  return {inject:['sessions','slots'],apply}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-subagent-workspace-ui",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "type": "module",
5
5
  "description": "Searchable workspace subagent manager for DeepSeek Harness Web",
6
6
  "license": "MIT",