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 +6 -0
- package/README.zh.md +10 -1
- package/lib/client.js +11 -11
- package/package.json +1 -1
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.
|
|
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(!
|
|
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(!
|
|
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
|
|
50
|
-
const activeRows=React.useMemo(()=>
|
|
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
|
|
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=
|
|
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}
|