zen-gitsync 2.18.18 → 2.18.19

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.
Files changed (39) hide show
  1. package/package.json +2 -1
  2. package/src/ui/public/assets/AgentView-CRkUXGCW.js +12 -0
  3. package/src/ui/public/assets/{AppVersionBadge-BfgAvMQg.js → AppVersionBadge-Dqca8Uoi.js} +2 -2
  4. package/src/ui/public/assets/{BranchSelector-B55Ta_HD.js → BranchSelector-CN2iCCAs.js} +1 -1
  5. package/src/ui/public/assets/{ChatSilenceBadge-BDltHrA2.js → ChatSilenceBadge-ltPjxE4-.js} +1 -1
  6. package/src/ui/public/assets/{CommitForm-C1Jql1he.js → CommitForm-mOWC0Zio.js} +3 -3
  7. package/src/ui/public/assets/{CommonDialog-lhBO3OFL.js → CommonDialog-D2f72EzI.js} +1 -1
  8. package/src/ui/public/assets/EditorView-D7tyqaAl.js +46 -0
  9. package/src/ui/public/assets/EditorView-cW_Ax-z8.css +1 -0
  10. package/src/ui/public/assets/{FlowExecutionViewer-BPMqArlZ.js → FlowExecutionViewer-4dAyrq6w.js} +1 -1
  11. package/src/ui/public/assets/{FlowOrchestrationWorkspace-Cq-1Knnp.js → FlowOrchestrationWorkspace-BYcu7GZu.js} +1 -1
  12. package/src/ui/public/assets/{LogList-Bk7GAfle.js → LogList-n-gSd_A8.js} +1 -1
  13. package/src/ui/public/assets/{MindmapView-CBOfycTa.js → MindmapView-msWKbkjo.js} +1 -1
  14. package/src/ui/public/assets/{MonitorView-3g87o1gD.js → MonitorView-D0mJlgEJ.js} +1 -1
  15. package/src/ui/public/assets/{ProjectManagerView-DgMq7Jed.js → ProjectManagerView-CuKtgxJg.js} +1 -1
  16. package/src/ui/public/assets/{ProjectStartupButton-CkJEFz-S.js → ProjectStartupButton-Cx0JvDzM.js} +1 -1
  17. package/src/ui/public/assets/{RecentDirectoriesChat-CQ6vjPkE.js → RecentDirectoriesChat-5OEF3wdB.js} +1 -1
  18. package/src/ui/public/assets/{RemoteManagerDialog-D9arrFOG.js → RemoteManagerDialog-ItxNmLvY.js} +1 -1
  19. package/src/ui/public/assets/{RemoteRepoCard-ZQ_SMlQZ.js → RemoteRepoCard-y-GzPZ7M.js} +1 -1
  20. package/src/ui/public/assets/{SourceMapView-1q3TRufj.js → SourceMapView-DXJUPkaX.js} +1 -1
  21. package/src/ui/public/assets/{SvgIcon-CfjWD31j.js → SvgIcon-DkU8Uro2.js} +1 -1
  22. package/src/ui/public/assets/{UserInputNode-BdU3sSVR.js → UserInputNode-unSg-ucz.js} +1 -1
  23. package/src/ui/public/assets/{WorkbenchView-D8WdRklc.js → WorkbenchView-C2-X3Ik_.js} +93 -93
  24. package/src/ui/public/assets/WorkbenchView-CVqXb__l.css +1 -0
  25. package/src/ui/public/assets/{_plugin-vue_export-helper-D4DL0jyB.js → _plugin-vue_export-helper-Dz34f-q7.js} +2 -2
  26. package/src/ui/public/assets/{agentConversations-DJ8rPauy.js → agentConversations-DLAC_0wI.js} +1 -1
  27. package/src/ui/public/assets/{configStore-BmWis0h4.js → configStore-BjNspgAX.js} +1 -1
  28. package/src/ui/public/assets/{index-DRDito6l.js → index-BybDOX1D.js} +79 -79
  29. package/src/ui/public/assets/{relativeTime-BpGKkKiW.js → relativeTime-DN4_NV-7.js} +1 -1
  30. package/src/ui/public/assets/{toolsStore-CmVXtAw_.js → toolsStore-C5a4cV7b.js} +1 -1
  31. package/src/ui/public/assets/{useOrchestrator-DKr4ShyB.js → useOrchestrator-Cd6p-ldI.js} +1 -1
  32. package/src/ui/public/assets/{useWorkbenchProjects-D169QQnx.js → useWorkbenchProjects-OkQTFYcp.js} +1 -1
  33. package/src/ui/public/index.html +6 -6
  34. package/src/ui/server/routes/fs.js +59 -4
  35. package/src/ui/server/routes/workbench/index.js +41 -1
  36. package/src/ui/public/assets/AgentView-fJbuH0N-.js +0 -12
  37. package/src/ui/public/assets/EditorView-Dvi9Js01.css +0 -1
  38. package/src/ui/public/assets/EditorView-nJTaLq6D.js +0 -46
  39. package/src/ui/public/assets/WorkbenchView-D6orzzEp.css +0 -1
@@ -1,13 +1,13 @@
1
- import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F as i,Ft as a,Gn as o,I as s,In as c,J as l,Kr as u,Lt as d,Mn as f,N as p,On as m,Ot as h,Pt as g,Qn as _,Qt as v,Rt as y,S as b,Sn as x,Tn as S,U as C,Un as ee,Wr as w,X as T,Xr as E,Y as te,Yn as D,Z as ne,_ as O,_n as k,a as re,ar as A,at as j,b as M,bt as ie,ct as ae,en as oe,et as se,fn as ce,ft as le,gn as N,gr as P,gt as ue,hn as F,i as I,ir as L,jr as R,kn as z,ln as B,lr as V,mn as H,mr as de,nr as U,on as W,pn as G,qn as K,r as fe,st as pe,ut as q,v as me,vt as he,w as ge,wn as J,xn as Y,xt as _e,y as ve,yn as ye,z as be}from"./element-plus-Bz6lYur-.js";import{c as xe,l as Se,n as Ce,s as we,t as Te}from"./vendor-C2k0GBzj.js";import{n as X,t as Z}from"./_plugin-vue_export-helper-D4DL0jyB.js";import{t as Ee}from"./SvgIcon-CfjWD31j.js";import{c as De,l as Oe,s as ke,t as Ae}from"./configStore-BmWis0h4.js";import{t as je}from"./toolsStore-CmVXtAw_.js";import{t as Me}from"./CommonDialog-lhBO3OFL.js";import{C as Ne,D as Pe,E as Fe,K as Ie,O as Le,S as Re,T as ze,V as Be,_ as Ve,b as Q,g as He,lt as $,tt as Ue,v as We,w as Ge,x as Ke}from"./index-DRDito6l.js";import{a as qe,c as Je,d as Ye,i as Xe,l as Ze,m as Qe,n as $e,o as et,r as tt,s as nt,t as rt,u as it}from"./agentConversations-DJ8rPauy.js";import{a as at,c as ot,d as st,i as ct,l as lt,n as ut,o as dt,r as ft,s as pt,t as mt,u as ht}from"./ChatSilenceBadge-BDltHrA2.js";import{t as gt}from"./useOrchestrator-DKr4ShyB.js";import{n as _t,r as vt,t as yt}from"./relativeTime-BpGKkKiW.js";import{n as bt,t as xt}from"./useWorkbenchProjects-D169QQnx.js";c(),V();var St=f({__name:`AttachmentZone`,props:{attachments:{type:Array,required:!0},isImage:{type:Function,required:!0},humanSize:{type:Function,required:!0},isUploading:{type:Boolean,required:!0},isPasteHover:{type:Boolean,required:!0},onPick:{type:Function,required:!0},onRemove:{type:Function,required:!0},rawBase:{type:String,required:!1}},emits:[`paste`,`drop`,`dragover`,`dragenter`,`dragleave`],setup(e,{expose:t,emit:n}){t();let r=e;function i(e){return`${r.rawBase||`/api/workbench/attachments`}/${e.id}/raw`}let a=n,o=Y(()=>r.attachments.filter(e=>r.isImage(e))),s=Y(()=>o.value.map(e=>i(e))),c=P(0),l=P(!1);function u(e){if(r.isImage(e)){let t=o.value.findIndex(t=>t.id===e.id);c.value=t>=0?t:0,l.value=!0}else window.open(i(e),`_blank`,`noopener`)}function d(){l.value=!1}let f=P({visible:!1,x:0,y:0,att:null}),p=P(!1);function m(e,t){if(!r.isImage(e))return;t.preventDefault();let n=window.innerWidth-180,i=window.innerHeight-120;f.value={visible:!0,x:Math.min(t.clientX,n),y:Math.min(t.clientY,i),att:e}}function h(){f.value.visible&&(f.value.visible=!1)}async function g(){let e=f.value.att;if(e&&!p.value){if(h(),!navigator.clipboard||typeof ClipboardItem>`u`){I({type:`warning`,message:X(`@WORKBENCH:当前浏览器不支持复制图片`)});return}p.value=!0;try{let t=await fetch(i(e),{credentials:`same-origin`});if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.blob(),r=[`image/png`,`image/jpeg`,`image/webp`,`image/gif`].includes(n.type)?n.type:`image/png`,a=new ClipboardItem({[r]:n});await navigator.clipboard.write([a]),I({type:`success`,message:X(`@WORKBENCH:图片已复制到剪贴板`),duration:1800})}catch(e){I({type:`error`,message:X(`@WORKBENCH:复制失败 {error}`,{error:e?.message||``})})}finally{p.value=!1}}}typeof window<`u`&&(window.addEventListener(`click`,h),window.addEventListener(`scroll`,h,!0),window.addEventListener(`blur`,h)),ee(()=>{typeof window>`u`||(window.removeEventListener(`click`,h),window.removeEventListener(`scroll`,h,!0),window.removeEventListener(`blur`,h))});let _={props:r,rawOf:i,emit:a,imageList:o,previewUrls:s,previewIndex:c,previewVisible:l,previewAttachment:u,closePreview:d,contextMenu:f,copyBusy:p,openContextMenu:m,closeContextMenu:h,copyImageToClipboard:g,get ElImageViewer(){return M},get $t(){return X}};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}});R(),c(),W();var Ct={class:`wb-attachments__head`},wt={class:`wb-attachments__label`},Tt={class:`wb-attachments__count`},Et=[`disabled`],Dt={key:0,class:`wb-attachments__paste-hint`},Ot={key:1,class:`wb-attachments__list`},kt=[`title`,`onClick`,`onContextmenu`],At=[`src`,`alt`],jt={key:1},Mt={class:`wb-attachment__meta`},Nt=[`title`],Pt=[`onClick`,`title`];function Ft(e,t,n,i,a,o){return K(),S(k,null,[x(`div`,{class:w([`wb-attachments`,{"is-paste-hover":n.isPasteHover}]),onPaste:t[1]||=e=>i.emit(`paste`,e),onDrop:t[2]||=N(e=>i.emit(`drop`,e),[`prevent`]),onDragover:t[3]||=N(e=>i.emit(`dragover`,e),[`prevent`]),onDragenter:t[4]||=N(e=>i.emit(`dragenter`,e),[`prevent`]),onDragleave:t[5]||=e=>i.emit(`dragleave`,e)},[x(`div`,Ct,[x(`span`,wt,[z(E(i.$t(`@WORKBENCH:附件`))+` `,1),J(` 只报个数:数量不设上限,写成 "N / 9" 会让人以为还剩几个能加 `),x(`span`,Tt,E(n.attachments.length),1)]),x(`button`,{class:`wb-attachments__add`,disabled:n.isUploading,onClick:t[0]||=(...e)=>n.onPick&&n.onPick(...e)},E(n.isUploading?i.$t(`@WORKBENCH:上传中…`):i.$t(`@WORKBENCH:添加附件`)),9,Et)]),n.isPasteHover?(K(),S(`div`,Dt,E(i.$t(`@WORKBENCH:粘贴图片以快速添加`)),1)):J(`v-if`,!0),n.attachments.length>0?(K(),S(`ul`,Ot,[(K(!0),S(k,null,D(n.attachments,e=>(K(),S(`li`,{key:e.id,class:`wb-attachment`},[x(`button`,{type:`button`,class:`wb-attachment__preview`,title:i.$t(`@WORKBENCH:点击预览`),onClick:t=>i.previewAttachment(e),onContextmenu:t=>i.openContextMenu(e,t)},[x(`div`,{class:w([`wb-attachment__icon`,{"wb-attachment__icon--img":n.isImage(e)}])},[n.isImage(e)?(K(),S(`img`,{key:0,src:i.rawOf(e),alt:e.originalName,loading:`lazy`},null,8,At)):(K(),S(`span`,jt,E(e.ext.toUpperCase()),1))],2),x(`div`,Mt,[x(`div`,{class:`wb-attachment__name`,title:`${e.originalName} (${n.humanSize(e.size)})`},E(e.originalName),9,Nt)])],40,kt),x(`button`,{class:`wb-attachment__del`,onClick:N(t=>n.onRemove(e),[`stop`]),title:i.$t(`@WORKBENCH:删除`)},`×`,8,Pt)]))),128))])):J(`v-if`,!0)],34),J(`
1
+ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F as i,Ft as a,Gn as o,I as s,In as c,J as l,Kr as u,Lt as d,Mn as f,N as p,On as m,Ot as h,Pt as g,Qn as _,Qt as v,Rt as y,S as b,Sn as x,Tn as S,U as C,Un as w,Wr as T,X as E,Xr as D,Y as ee,Yn as O,Z as te,_ as ne,_n as k,a as re,ar as A,at as j,b as M,bt as ie,ct as ae,en as oe,et as se,fn as ce,ft as le,gn as N,gr as P,gt as ue,hn as F,i as I,ir as L,jr as R,kn as z,ln as B,lr as V,mn as H,mr as de,nr as U,on as W,pn as G,qn as K,r as fe,st as pe,ut as q,v as me,vt as he,w as ge,wn as J,xn as Y,xt as _e,y as ve,yn as ye,z as be}from"./element-plus-Bz6lYur-.js";import{c as xe,l as Se,n as Ce,s as we,t as Te}from"./vendor-C2k0GBzj.js";import{n as X,t as Z}from"./_plugin-vue_export-helper-Dz34f-q7.js";import{t as Ee}from"./SvgIcon-DkU8Uro2.js";import{c as De,l as Oe,s as ke,t as Ae}from"./configStore-BjNspgAX.js";import{t as je}from"./toolsStore-C5a4cV7b.js";import{t as Me}from"./CommonDialog-D2f72EzI.js";import{C as Ne,D as Pe,E as Fe,K as Ie,O as Le,S as Re,T as ze,V as Be,_ as Ve,b as Q,ft as $,g as He,tt as Ue,v as We,w as Ge,x as Ke}from"./index-BybDOX1D.js";import{a as qe,c as Je,d as Ye,i as Xe,l as Ze,m as Qe,n as $e,o as et,r as tt,s as nt,t as rt,u as it}from"./agentConversations-DLAC_0wI.js";import{a as at,c as ot,d as st,i as ct,l as lt,n as ut,o as dt,r as ft,s as pt,t as mt,u as ht}from"./ChatSilenceBadge-ltPjxE4-.js";import{t as gt}from"./useOrchestrator-Cd6p-ldI.js";import{n as _t,r as vt,t as yt}from"./relativeTime-DN4_NV-7.js";import{n as bt,t as xt}from"./useWorkbenchProjects-OkQTFYcp.js";c(),V();var St=f({__name:`AttachmentZone`,props:{attachments:{type:Array,required:!0},isImage:{type:Function,required:!0},humanSize:{type:Function,required:!0},isUploading:{type:Boolean,required:!0},isPasteHover:{type:Boolean,required:!0},onPick:{type:Function,required:!0},onRemove:{type:Function,required:!0},rawBase:{type:String,required:!1}},emits:[`paste`,`drop`,`dragover`,`dragenter`,`dragleave`],setup(e,{expose:t,emit:n}){t();let r=e;function i(e){return`${r.rawBase||`/api/workbench/attachments`}/${e.id}/raw`}let a=n,o=Y(()=>r.attachments.filter(e=>r.isImage(e))),s=Y(()=>o.value.map(e=>i(e))),c=P(0),l=P(!1);function u(e){if(r.isImage(e)){let t=o.value.findIndex(t=>t.id===e.id);c.value=t>=0?t:0,l.value=!0}else window.open(i(e),`_blank`,`noopener`)}function d(){l.value=!1}let f=P({visible:!1,x:0,y:0,att:null}),p=P(!1);function m(e,t){if(!r.isImage(e))return;t.preventDefault();let n=window.innerWidth-180,i=window.innerHeight-120;f.value={visible:!0,x:Math.min(t.clientX,n),y:Math.min(t.clientY,i),att:e}}function h(){f.value.visible&&(f.value.visible=!1)}async function g(){let e=f.value.att;if(e&&!p.value){if(h(),!navigator.clipboard||typeof ClipboardItem>`u`){I({type:`warning`,message:X(`@WORKBENCH:当前浏览器不支持复制图片`)});return}p.value=!0;try{let t=await fetch(i(e),{credentials:`same-origin`});if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.blob(),r=[`image/png`,`image/jpeg`,`image/webp`,`image/gif`].includes(n.type)?n.type:`image/png`,a=new ClipboardItem({[r]:n});await navigator.clipboard.write([a]),I({type:`success`,message:X(`@WORKBENCH:图片已复制到剪贴板`),duration:1800})}catch(e){I({type:`error`,message:X(`@WORKBENCH:复制失败 {error}`,{error:e?.message||``})})}finally{p.value=!1}}}typeof window<`u`&&(window.addEventListener(`click`,h),window.addEventListener(`scroll`,h,!0),window.addEventListener(`blur`,h)),w(()=>{typeof window>`u`||(window.removeEventListener(`click`,h),window.removeEventListener(`scroll`,h,!0),window.removeEventListener(`blur`,h))});let _={props:r,rawOf:i,emit:a,imageList:o,previewUrls:s,previewIndex:c,previewVisible:l,previewAttachment:u,closePreview:d,contextMenu:f,copyBusy:p,openContextMenu:m,closeContextMenu:h,copyImageToClipboard:g,get ElImageViewer(){return M},get $t(){return X}};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}});R(),c(),W();var Ct={class:`wb-attachments__head`},wt={class:`wb-attachments__label`},Tt={class:`wb-attachments__count`},Et=[`disabled`],Dt={key:0,class:`wb-attachments__paste-hint`},Ot={key:1,class:`wb-attachments__list`},kt=[`title`,`onClick`,`onContextmenu`],At=[`src`,`alt`],jt={key:1},Mt={class:`wb-attachment__meta`},Nt=[`title`],Pt=[`onClick`,`title`];function Ft(e,t,n,i,a,o){return K(),S(k,null,[x(`div`,{class:T([`wb-attachments`,{"is-paste-hover":n.isPasteHover}]),onPaste:t[1]||=e=>i.emit(`paste`,e),onDrop:t[2]||=N(e=>i.emit(`drop`,e),[`prevent`]),onDragover:t[3]||=N(e=>i.emit(`dragover`,e),[`prevent`]),onDragenter:t[4]||=N(e=>i.emit(`dragenter`,e),[`prevent`]),onDragleave:t[5]||=e=>i.emit(`dragleave`,e)},[x(`div`,Ct,[x(`span`,wt,[z(D(i.$t(`@WORKBENCH:附件`))+` `,1),J(` 只报个数:数量不设上限,写成 "N / 9" 会让人以为还剩几个能加 `),x(`span`,Tt,D(n.attachments.length),1)]),x(`button`,{class:`wb-attachments__add`,disabled:n.isUploading,onClick:t[0]||=(...e)=>n.onPick&&n.onPick(...e)},D(n.isUploading?i.$t(`@WORKBENCH:上传中…`):i.$t(`@WORKBENCH:添加附件`)),9,Et)]),n.isPasteHover?(K(),S(`div`,Dt,D(i.$t(`@WORKBENCH:粘贴图片以快速添加`)),1)):J(`v-if`,!0),n.attachments.length>0?(K(),S(`ul`,Ot,[(K(!0),S(k,null,O(n.attachments,e=>(K(),S(`li`,{key:e.id,class:`wb-attachment`},[x(`button`,{type:`button`,class:`wb-attachment__preview`,title:i.$t(`@WORKBENCH:点击预览`),onClick:t=>i.previewAttachment(e),onContextmenu:t=>i.openContextMenu(e,t)},[x(`div`,{class:T([`wb-attachment__icon`,{"wb-attachment__icon--img":n.isImage(e)}])},[n.isImage(e)?(K(),S(`img`,{key:0,src:i.rawOf(e),alt:e.originalName,loading:`lazy`},null,8,At)):(K(),S(`span`,jt,D(e.ext.toUpperCase()),1))],2),x(`div`,Mt,[x(`div`,{class:`wb-attachment__name`,title:`${e.originalName} (${n.humanSize(e.size)})`},D(e.originalName),9,Nt)])],40,kt),x(`button`,{class:`wb-attachment__del`,onClick:N(t=>n.onRemove(e),[`stop`]),title:i.$t(`@WORKBENCH:删除`)},`×`,8,Pt)]))),128))])):J(`v-if`,!0)],34),J(`
2
2
  el-image-viewer 自己通过内部 <Teleport to="body" :disabled="!teleported"> 把遮罩渲染到 body。
3
3
  不要在外面再包一层 <teleport to="body"> —— 嵌套 Teleport 在 element-plus 2.11.x 下会让组件
4
4
  的 v-if 容器内残留占位、且内部 Teleport 因找不到正确锚点而不挂载,导致点击图片无反应。
5
5
  显式传 :teleported="true" 是为了保证内部 Teleport 启用(默认是 undefined 关闭)。
6
- `),i.previewVisible&&i.previewUrls.length>0?(K(),r(i.ElImageViewer,{key:0,"url-list":i.previewUrls,"initial-index":i.previewIndex,"hide-on-click-modal":!0,teleported:!0,onClose:i.closePreview},null,8,[`url-list`,`initial-index`])):J(`v-if`,!0),J(` 右键菜单:仅图片附件可用 `),(K(),r(ye,{to:`body`},[i.contextMenu.visible&&i.contextMenu.att&&n.isImage(i.contextMenu.att)?(K(),S(`ul`,{key:0,class:`wb-ctx-menu`,style:u({top:i.contextMenu.y+`px`,left:i.contextMenu.x+`px`}),onContextmenu:t[6]||=N(()=>{},[`prevent`])},[x(`li`,{class:w([`wb-ctx-menu__item`,{"is-disabled":i.copyBusy}]),onClick:i.copyImageToClipboard},[t[7]||=x(`span`,{class:`wb-ctx-menu__icon`,"aria-hidden":`true`},[x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[x(`rect`,{x:`9`,y:`9`,width:`11`,height:`11`,rx:`2`}),x(`path`,{d:`M5 15V5a2 2 0 0 1 2-2h10`})])],-1),x(`span`,null,E(i.$t(`@WORKBENCH:复制图片`)),1)],2)],36)):J(`v-if`,!0)]))],64)}var It=Z(St,[[`render`,Ft],[`__scopeId`,`data-v-d2df2361`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/AttachmentZone.vue`]]),Lt=Ce(`claude`),Rt=Ce(`opencode`),zt=Ce(`codex`),Bt=Le,Vt=Pe;function Ht(e){return e===`opencode`?Rt:e===`codex`?zt:e===`codebuddy`?Bt:e===`pi`?Vt:Lt}function Ut(e){if(typeof e!=`string`||!e)return;let t=Date.parse(e);return Number.isFinite(t)?t:void 0}function Wt(e){let t=Ut(e?.thinkingStartedAt);return t===void 0?{}:{reasoningStartedAt:t,reasoningEndedAt:Ut(e?.thinkingEndedAt)}}c(),V();var Gt=65536,Kt=f({__name:`JobLogDetails`,props:{job:{type:Object,required:!0}},emits:[`re-execute`],setup(e,{expose:n,emit:r}){n();let i=Ae(),a=e,o=r,s=P(!1);function c(){s.value=!s.value}let l=Y(()=>a.job.status===`running`||a.job.status===`pending`);U(()=>a.job.status,(e,t)=>{t!==`running`&&t!==`pending`&&(e===`running`||e===`pending`)&&(s.value=!1)});function u(){let e=a.job.output||``;if(!e)return``;let t=e.length<=Gt?e:`${X(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`;return Ye(t,a.job.id)}function d(){let e=a.job.thinking||``;return e?e.length<=Gt?e:`${X(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`:``}async function f(e){try{if(navigator?.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,t.style.left=`-9999px`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}async function p(){let e=[];if(a.job.prompt&&e.push(`## ${X(`@WORKBENCH:用户提示词`)}\n\n${a.job.prompt}`),a.job.thinking&&e.push(`## ${X(`@WORKBENCH:Claude 思考`)}\n\n${a.job.thinking}`),a.job.output&&e.push(`## ${X(`@WORKBENCH:模型返回`)}\n\n${a.job.output}`),!e.length){I.warning(X(`@WORKBENCH:暂无内容可复制`));return}await f(e.join(`
6
+ `),i.previewVisible&&i.previewUrls.length>0?(K(),r(i.ElImageViewer,{key:0,"url-list":i.previewUrls,"initial-index":i.previewIndex,"hide-on-click-modal":!0,teleported:!0,onClose:i.closePreview},null,8,[`url-list`,`initial-index`])):J(`v-if`,!0),J(` 右键菜单:仅图片附件可用 `),(K(),r(ye,{to:`body`},[i.contextMenu.visible&&i.contextMenu.att&&n.isImage(i.contextMenu.att)?(K(),S(`ul`,{key:0,class:`wb-ctx-menu`,style:u({top:i.contextMenu.y+`px`,left:i.contextMenu.x+`px`}),onContextmenu:t[6]||=N(()=>{},[`prevent`])},[x(`li`,{class:T([`wb-ctx-menu__item`,{"is-disabled":i.copyBusy}]),onClick:i.copyImageToClipboard},[t[7]||=x(`span`,{class:`wb-ctx-menu__icon`,"aria-hidden":`true`},[x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[x(`rect`,{x:`9`,y:`9`,width:`11`,height:`11`,rx:`2`}),x(`path`,{d:`M5 15V5a2 2 0 0 1 2-2h10`})])],-1),x(`span`,null,D(i.$t(`@WORKBENCH:复制图片`)),1)],2)],36)):J(`v-if`,!0)]))],64)}var It=Z(St,[[`render`,Ft],[`__scopeId`,`data-v-d2df2361`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/AttachmentZone.vue`]]),Lt=Ce(`claude`),Rt=Ce(`opencode`),zt=Ce(`codex`),Bt=Le,Vt=Pe;function Ht(e){return e===`opencode`?Rt:e===`codex`?zt:e===`codebuddy`?Bt:e===`pi`?Vt:Lt}function Ut(e){if(typeof e!=`string`||!e)return;let t=Date.parse(e);return Number.isFinite(t)?t:void 0}function Wt(e){let t=Ut(e?.thinkingStartedAt);return t===void 0?{}:{reasoningStartedAt:t,reasoningEndedAt:Ut(e?.thinkingEndedAt)}}c(),V();var Gt=65536,Kt=f({__name:`JobLogDetails`,props:{job:{type:Object,required:!0}},emits:[`re-execute`],setup(e,{expose:n,emit:r}){n();let i=Ae(),a=e,o=r,s=P(!1);function c(){s.value=!s.value}let l=Y(()=>a.job.status===`running`||a.job.status===`pending`);U(()=>a.job.status,(e,t)=>{t!==`running`&&t!==`pending`&&(e===`running`||e===`pending`)&&(s.value=!1)});function u(){let e=a.job.output||``;if(!e)return``;let t=e.length<=Gt?e:`${X(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`;return Ye(t,a.job.id)}function d(){let e=a.job.thinking||``;return e?e.length<=Gt?e:`${X(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`:``}async function f(e){try{if(navigator?.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,t.style.left=`-9999px`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}async function p(){let e=[];if(a.job.prompt&&e.push(`## ${X(`@WORKBENCH:用户提示词`)}\n\n${a.job.prompt}`),a.job.thinking&&e.push(`## ${X(`@WORKBENCH:Claude 思考`)}\n\n${a.job.thinking}`),a.job.output&&e.push(`## ${X(`@WORKBENCH:模型返回`)}\n\n${a.job.output}`),!e.length){I.warning(X(`@WORKBENCH:暂无内容可复制`));return}await f(e.join(`
7
7
 
8
8
  ---
9
9
 
10
- `))?I.success(X(`@WORKBENCH:已复制到剪贴板`)):I.error(X(`@WORKBENCH:复制失败`))}let m=Y(()=>{let e=a.job.status;return e===`done`||e===`error`||e===`cancelled`}),h=Y(()=>a.job.status===`cancelled`?`wb-log-summary__status--cancelled`:a.job.status===`error`?`wb-log-summary__status--error`:`wb-log-summary__status--done`),g=Y(()=>a.job.status===`cancelled`?`⏹`:a.job.status===`error`?`✗`:`✓`),_=Y(()=>a.job.status===`cancelled`?X(`@WORKBENCH:已停止`):a.job.status===`error`?X(`@WORKBENCH:执行出错`):X(`@WORKBENCH:执行完成`)),v=Y(()=>Oe(a.job?.agent)),y=Y(()=>Ht(a.job?.agent));function b(e,t){return e===`running`||e===`pending`?t?`streaming`:`pending`:e===`error`?`error`:`done`}let x=Y(()=>{let e=a.job,t=[],n=e.startedAt?new Date(e.startedAt).getTime():Date.now();if(e.prompt){let r=dt(e.prompt);r&&t.push({id:`${e.id}-u`,role:`user`,content:r,status:`done`,createdAt:n})}let r=u(),i=d(),o=!!r,s=!!i,c=pt(e),l=c.length>0,f=o||s||l,p=b(e.status,f);return t.push({id:`${e.id}-a`,role:`assistant`,content:r,reasoning:s?i:void 0,reasoningStatus:s?o?`done`:p===`streaming`?`streaming`:`done`:void 0,...Wt(e),toolCalls:l?c:void 0,status:p,error:p===`error`&&e.error||void 0,createdAt:n}),t}),S=P(null);U(()=>a.job.status,(e,t)=>{e===`running`&&t!==`running`&&(S.value=S.value??Date.now())});let C=Y(()=>{if(!S.value)return``;let e=S.value,t=a.job.endedAt?new Date(a.job.endedAt).getTime():Date.now(),n=Math.max(0,Math.floor((t-e)/1e3));return n<60?`${n}s`:`${Math.floor(n/60)}分${(n%60).toString().padStart(2,`0`)}秒`}),ee=P(!1),w=Y(()=>!!(a.job.output&&a.job.output.length)),T=Y(()=>Ye(a.job.output||``,a.job.id)),E=P(null);U(ee,async e=>{e&&(await t(),E.value&&(E.value.scrollTop=E.value.scrollHeight))}),U(()=>(a.job.output||``).length,async()=>{ee.value&&(await t(),E.value&&(E.value.scrollTop=E.value.scrollHeight))});function te(){}let D=Y(()=>m.value&&!!a.job.prompt);function ne(){o(`re-execute`,a.job)}let O={configStore:i,props:a,emit:o,isCollapsed:s,toggleOpen:c,isActive:l,MAX_LOG_DISPLAY:Gt,displayOutput:u,displayThinking:d,copyToClipboard:f,copyAll:p,isFinished:m,finishedStatusClass:h,finishedStatusIcon:g,finishedStatusLabel:_,assistantLabel:v,assistantAvatar:y,mapStatus:b,chatMessages:x,startedAt:S,elapsedLabel:C,fullscreenOpen:ee,hasOutput:w,fullscreenSource:T,fullscreenContainerRef:E,onFullscreenClosed:te,canReExecute:D,onReExecute:ne,get ChatContainer(){return xe},get MarkdownRenderer(){return we},get $t(){return X},CommonDialog:Me};return Object.defineProperty(O,"__isScriptSetup",{enumerable:!1,value:!0}),O}});R(),c(),W();var qt=[`aria-expanded`],Jt={class:`wb-log-summary__left`},Yt={key:0,class:`wb-log-summary__status wb-log-summary__status--running`},Xt={class:`wb-log-summary__label`},Zt={key:0,class:`wb-log-summary__elapsed`},Qt={key:1,class:`wb-log-summary__status wb-log-summary__status--pending`},$t={class:`wb-log-summary__label`},en={class:`wb-log-summary__icon`},tn={class:`wb-log-summary__label`},nn={key:0,class:`wb-log-summary__elapsed`},rn={key:3},an={class:`wb-log-summary__right`},on={class:`wb-log-summary__meta`},sn=[`title`,`aria-label`],cn={class:`wb-log-details__body`},ln={class:`wb-job-chat`},un={key:0,class:`wb-chat__foot`},dn=[`title`,`aria-label`],fn={ref:`fullscreenContainerRef`,class:`wb-log-fullscreen`},pn={key:1,class:`wb-log-fullscreen__empty`};function mn(t,n,i,a,o,s){return K(),S(`div`,{class:w([`wb-log-details`,{"is-running":a.isActive,"is-pending":i.job.status===`pending`,"is-finished":a.isFinished}])},[x(`div`,{class:`wb-log-summary`,onClick:a.toggleOpen,role:`button`,"aria-expanded":!a.isCollapsed},[x(`span`,Jt,[i.job.status===`running`?(K(),S(`span`,Yt,[x(`span`,Xt,E(a.$t(`@WORKBENCH:正在执行…`)),1),n[1]||=x(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[x(`span`,{class:`wb-log-dots__dot`}),x(`span`,{class:`wb-log-dots__dot`}),x(`span`,{class:`wb-log-dots__dot`})],-1),a.elapsedLabel?(K(),S(`span`,Zt,E(a.elapsedLabel),1)):J(`v-if`,!0)])):i.job.status===`pending`?(K(),S(`span`,Qt,[x(`span`,$t,E(a.$t(`@WORKBENCH:排队中…`)),1),n[2]||=x(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[x(`span`,{class:`wb-log-dots__dot`}),x(`span`,{class:`wb-log-dots__dot`}),x(`span`,{class:`wb-log-dots__dot`})],-1)])):a.isFinished?(K(),S(`span`,{key:2,class:w([`wb-log-summary__status`,a.finishedStatusClass])},[x(`span`,en,E(a.finishedStatusIcon),1),x(`span`,tn,E(a.finishedStatusLabel),1),a.elapsedLabel?(K(),S(`span`,nn,E(a.elapsedLabel),1)):J(`v-if`,!0)],2)):(K(),S(`span`,rn,E(a.$t(`@WORKBENCH:查看执行日志`)),1))]),x(`span`,an,[x(`span`,on,E((i.job.output||``).length)+` `+E(a.$t(`@WORKBENCH:字符`)),1),x(`button`,{type:`button`,class:`wb-log-copy`,title:a.$t(`@WORKBENCH:复制全部(含提示词与输出)`),"aria-label":a.$t(`@WORKBENCH:复制全部`),onClick:N(a.copyAll,[`stop`])},` ⧉ `,8,sn)])],8,qt),J(`
10
+ `))?I.success(X(`@WORKBENCH:已复制到剪贴板`)):I.error(X(`@WORKBENCH:复制失败`))}let m=Y(()=>{let e=a.job.status;return e===`done`||e===`error`||e===`cancelled`}),h=Y(()=>a.job.status===`cancelled`?`wb-log-summary__status--cancelled`:a.job.status===`error`?`wb-log-summary__status--error`:`wb-log-summary__status--done`),g=Y(()=>a.job.status===`cancelled`?`⏹`:a.job.status===`error`?`✗`:`✓`),_=Y(()=>a.job.status===`cancelled`?X(`@WORKBENCH:已停止`):a.job.status===`error`?X(`@WORKBENCH:执行出错`):X(`@WORKBENCH:执行完成`)),v=Y(()=>Oe(a.job?.agent)),y=Y(()=>Ht(a.job?.agent));function b(e,t){return e===`running`||e===`pending`?t?`streaming`:`pending`:e===`error`?`error`:`done`}let x=Y(()=>{let e=a.job,t=[],n=e.startedAt?new Date(e.startedAt).getTime():Date.now();if(e.prompt){let r=dt(e.prompt);r&&t.push({id:`${e.id}-u`,role:`user`,content:r,status:`done`,createdAt:n})}let r=u(),i=d(),o=!!r,s=!!i,c=pt(e),l=c.length>0,f=o||s||l,p=b(e.status,f);return t.push({id:`${e.id}-a`,role:`assistant`,content:r,reasoning:s?i:void 0,reasoningStatus:s?o?`done`:p===`streaming`?`streaming`:`done`:void 0,...Wt(e),toolCalls:l?c:void 0,status:p,error:p===`error`&&e.error||void 0,createdAt:n}),t}),S=P(null);U(()=>a.job.status,(e,t)=>{e===`running`&&t!==`running`&&(S.value=S.value??Date.now())});let C=Y(()=>{if(!S.value)return``;let e=S.value,t=a.job.endedAt?new Date(a.job.endedAt).getTime():Date.now(),n=Math.max(0,Math.floor((t-e)/1e3));return n<60?`${n}s`:`${Math.floor(n/60)}分${(n%60).toString().padStart(2,`0`)}秒`}),w=P(!1),T=Y(()=>!!(a.job.output&&a.job.output.length)),E=Y(()=>Ye(a.job.output||``,a.job.id)),D=P(null);U(w,async e=>{e&&(await t(),D.value&&(D.value.scrollTop=D.value.scrollHeight))}),U(()=>(a.job.output||``).length,async()=>{w.value&&(await t(),D.value&&(D.value.scrollTop=D.value.scrollHeight))});function ee(){}let O=Y(()=>m.value&&!!a.job.prompt);function te(){o(`re-execute`,a.job)}let ne={configStore:i,props:a,emit:o,isCollapsed:s,toggleOpen:c,isActive:l,MAX_LOG_DISPLAY:Gt,displayOutput:u,displayThinking:d,copyToClipboard:f,copyAll:p,isFinished:m,finishedStatusClass:h,finishedStatusIcon:g,finishedStatusLabel:_,assistantLabel:v,assistantAvatar:y,mapStatus:b,chatMessages:x,startedAt:S,elapsedLabel:C,fullscreenOpen:w,hasOutput:T,fullscreenSource:E,fullscreenContainerRef:D,onFullscreenClosed:ee,canReExecute:O,onReExecute:te,get ChatContainer(){return xe},get MarkdownRenderer(){return we},get $t(){return X},CommonDialog:Me};return Object.defineProperty(ne,"__isScriptSetup",{enumerable:!1,value:!0}),ne}});R(),c(),W();var qt=[`aria-expanded`],Jt={class:`wb-log-summary__left`},Yt={key:0,class:`wb-log-summary__status wb-log-summary__status--running`},Xt={class:`wb-log-summary__label`},Zt={key:0,class:`wb-log-summary__elapsed`},Qt={key:1,class:`wb-log-summary__status wb-log-summary__status--pending`},$t={class:`wb-log-summary__label`},en={class:`wb-log-summary__icon`},tn={class:`wb-log-summary__label`},nn={key:0,class:`wb-log-summary__elapsed`},rn={key:3},an={class:`wb-log-summary__right`},on={class:`wb-log-summary__meta`},sn=[`title`,`aria-label`],cn={class:`wb-log-details__body`},ln={class:`wb-job-chat`},un={key:0,class:`wb-chat__foot`},dn=[`title`,`aria-label`],fn={ref:`fullscreenContainerRef`,class:`wb-log-fullscreen`},pn={key:1,class:`wb-log-fullscreen__empty`};function mn(t,n,i,a,o,s){return K(),S(`div`,{class:T([`wb-log-details`,{"is-running":a.isActive,"is-pending":i.job.status===`pending`,"is-finished":a.isFinished}])},[x(`div`,{class:`wb-log-summary`,onClick:a.toggleOpen,role:`button`,"aria-expanded":!a.isCollapsed},[x(`span`,Jt,[i.job.status===`running`?(K(),S(`span`,Yt,[x(`span`,Xt,D(a.$t(`@WORKBENCH:正在执行…`)),1),n[1]||=x(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[x(`span`,{class:`wb-log-dots__dot`}),x(`span`,{class:`wb-log-dots__dot`}),x(`span`,{class:`wb-log-dots__dot`})],-1),a.elapsedLabel?(K(),S(`span`,Zt,D(a.elapsedLabel),1)):J(`v-if`,!0)])):i.job.status===`pending`?(K(),S(`span`,Qt,[x(`span`,$t,D(a.$t(`@WORKBENCH:排队中…`)),1),n[2]||=x(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[x(`span`,{class:`wb-log-dots__dot`}),x(`span`,{class:`wb-log-dots__dot`}),x(`span`,{class:`wb-log-dots__dot`})],-1)])):a.isFinished?(K(),S(`span`,{key:2,class:T([`wb-log-summary__status`,a.finishedStatusClass])},[x(`span`,en,D(a.finishedStatusIcon),1),x(`span`,tn,D(a.finishedStatusLabel),1),a.elapsedLabel?(K(),S(`span`,nn,D(a.elapsedLabel),1)):J(`v-if`,!0)],2)):(K(),S(`span`,rn,D(a.$t(`@WORKBENCH:查看执行日志`)),1))]),x(`span`,an,[x(`span`,on,D((i.job.output||``).length)+` `+D(a.$t(`@WORKBENCH:字符`)),1),x(`button`,{type:`button`,class:`wb-log-copy`,title:a.$t(`@WORKBENCH:复制全部(含提示词与输出)`),"aria-label":a.$t(`@WORKBENCH:复制全部`),onClick:N(a.copyAll,[`stop`])},` ⧉ `,8,sn)])],8,qt),J(`
11
11
  body 容器:用 zen-ai-chat-ui 的 ChatContainer 渲染单轮对话。
12
12
  关掉 ChatContainer 自带的输入框(show-input=false —— 续聊输入由父组件统一承载),
13
13
  下方保留"重新执行"footer。
@@ -17,38 +17,38 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
17
17
  就全成了死代码 —— 自带的输入框藏不住,背景/气泡密度也全是库默认值。
18
18
  2026-09-29 在 WorkbenchView 上就是这个坑(「已完成任务点开有 2 个输入框」)。
19
19
  所以外层套一个自己的 div 承载 class。
20
- `),A(x(`div`,cn,[x(`div`,ln,[e(a.ChatContainer,{messages:a.chatMessages,"assistant-name":a.assistantLabel,"assistant-avatar":a.assistantAvatar,"show-avatar":!0,theme:a.configStore.theme,"tool-calls-config":{group:!0,collapseThreshold:2},"plan-config":{labels:{title:a.$t(`@AGENT:计划`),raw:a.$t(`@AGENT:原始参数`)}},"show-input":!1},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`plan-config`])]),J(` footer:任务结束后显示"重新执行",运行中不显示 `),a.canReExecute?(K(),S(`footer`,un,[x(`button`,{type:`button`,class:`wb-chat__action`,title:a.$t(`@WORKBENCH:用相同的提示词重新执行此任务`),"aria-label":a.$t(`@WORKBENCH:重新执行`),onClick:a.onReExecute},` ↻ `,8,dn)])):J(`v-if`,!0),J(` 全屏查看 dialog `),e(a.CommonDialog,{modelValue:a.fullscreenOpen,"onUpdate:modelValue":n[0]||=e=>a.fullscreenOpen=e,title:a.$t(`@WORKBENCH:模型返回 - 全屏查看`),size:`fullscreen`,type:`flex`,"close-on-click-modal":!1,"custom-class":`wb-log-fullscreen-dialog`,onClosed:a.onFullscreenClosed},{default:L(()=>[x(`div`,fn,[a.hasOutput?(K(),r(a.MarkdownRenderer,{key:0,source:a.fullscreenSource,class:`wb-log-fullscreen__render`},null,8,[`source`])):(K(),S(`div`,pn,E(a.$t(`@WORKBENCH:(暂无输出)`)),1))],512)]),_:1},8,[`modelValue`,`title`])],512),[[H,!a.isCollapsed]]),J(` /.wb-log-details__body `)],2)}var hn=Z(Kt,[[`render`,mn],[`__scopeId`,`data-v-a4bb55c4`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/JobLogDetails.vue`]]);c(),V();var gn=50,_n=f({__name:`ExecutionLogManager`,setup(e,{expose:t}){t();function n(e){return e instanceof Error?e.message:String(e)}let r=P([]),i=P(0),a=de({count:0,sizeMB:0,byStatus:{}}),s=P(!1),c=P(new Set),l=de({q:``,status:``,page:1}),u=P({maxCount:500,maxSizeMB:256}),d=de({maxCount:500,maxSizeMB:256}),f=P(!1),p=[{value:`pending`,label:X(`@WORKBENCH:排队中`)},{value:`running`,label:X(`@WORKBENCH:执行中`)},{value:`done`,label:X(`@WORKBENCH:已完成`)},{value:`error`,label:X(`@WORKBENCH:出错`)},{value:`cancelled`,label:X(`@WORKBENCH:已取消`)}],m=Y(()=>r.value.length>0&&r.value.every(e=>c.value.has(e.id))),h=Y(()=>r.value.some(e=>c.value.has(e.id))&&!m.value);async function g(){s.value=!0;try{let e=new URLSearchParams;l.q&&e.set(`q`,l.q),l.status&&e.set(`status`,l.status),e.set(`limit`,String(gn)),e.set(`offset`,String((l.page-1)*gn));let t=await fetch(`/api/workbench/jobs/list?${e.toString()}`).then(e=>e.json());if(!t.success)throw Error(t.error||`list failed`);r.value=t.jobs,i.value=t.total,a.count=t.stats.count,a.sizeMB=t.stats.sizeMB,a.byStatus=t.stats.byStatus;let n=new Set(r.value.map(e=>e.id));for(let e of Array.from(c.value))n.has(e)||c.value.delete(e)}catch(e){I.error(X(`@WORKBENCH:加载失败`)+`: `+n(e))}finally{s.value=!1}}async function _(){try{let e=await fetch(`/api/workbench/jobs/config`).then(e=>e.json());e.success&&(u.value=e.config,d.maxCount=e.config.maxCount,d.maxSizeMB=e.config.maxSizeMB)}catch{}}async function v(){f.value=!0;try{let e=await fetch(`/api/workbench/jobs/config`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({maxCount:d.maxCount,maxSizeMB:d.maxSizeMB})}).then(e=>e.json());if(!e.success)throw Error(e.error||`save failed`);u.value=e.config,I.success(X(`@WORKBENCH:已保存策略`)),await g()}catch(e){I.error(X(`@WORKBENCH:保存失败`)+`: `+n(e))}finally{f.value=!1}}function b(){l.page=1,g()}function x(){l.q=``,l.status=``,l.page=1,g()}function S(e,t){t?c.value.add(e):c.value.delete(e),c.value=new Set(c.value)}function C(e){if(e)for(let e of r.value)c.value.add(e.id);else for(let e of r.value)c.value.delete(e.id);c.value=new Set(c.value)}function ee(e){I.info(X(`@WORKBENCH:请到工作台主面板的对应任务上点击「重新执行」`))}async function w(e){try{await fe.confirm(X(`@WORKBENCH:确定要删除所选的 {count} 条日志吗?`,{count:1}),X(`@WORKBENCH:删除`),{type:`warning`})}catch{return}try{let t=await fetch(`/api/workbench/jobs/${e}`,{method:`DELETE`}).then(e=>e.json());if(!t.success)throw Error(t.error||`delete failed`);c.value.delete(e),c.value=new Set(c.value),await g()}catch(e){I.error(X(`@WORKBENCH:保存失败`)+`: `+n(e))}}async function T(){let e=Array.from(c.value);if(e.length!==0){try{await fe.confirm(X(`@WORKBENCH:确定要删除所选的 {count} 条日志吗?`,{count:e.length}),X(`@WORKBENCH:批量删除`),{type:`warning`})}catch{return}try{let t=await fetch(`/api/workbench/jobs/batch-delete`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({ids:e})}).then(e=>e.json());if(!t.success)throw Error(t.error||`batch delete failed`);I.success(X(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e.length})),c.value=new Set,await g()}catch(e){I.error(X(`@WORKBENCH:保存失败`)+`: `+n(e))}}}async function E(){let e=a.count;if(e!==0){try{await fe.confirm(X(`@WORKBENCH:确定要清空所有 {count} 条执行日志吗?此操作不可恢复。`,{count:e}),X(`@WORKBENCH:清空全部`),{type:`warning`,confirmButtonText:X(`@WORKBENCH:清空全部`)})}catch{return}try{let t=await fetch(`/api/workbench/jobs/clear`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({confirm:!0})}).then(e=>e.json());if(!t.success)throw Error(t.error||`clear failed`);I.success(X(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e})),c.value=new Set,await g()}catch(e){I.error(X(`@WORKBENCH:保存失败`)+`: `+n(e))}}}function te(e,t){if(!e)return``;let n=new Date(e).getTime(),r=t?new Date(t).getTime():Date.now(),i=Math.max(0,r-n);return i<1e3?`${i}ms`:i<6e4?`${(i/1e3).toFixed(1)}s`:i<36e5?`${Math.floor(i/6e4)}m ${Math.floor(i%6e4/1e3)}s`:`${Math.floor(i/36e5)}h ${Math.floor(i%36e5/6e4)}m`}o(()=>{g(),_()});let D={errMsg:n,list:r,total:i,stats:a,loading:s,selectedIds:c,pageSize:gn,filter:l,config:u,configDraft:d,configSaving:f,STATUS_OPTIONS:p,isAllOnPageSelected:m,isSomeOnPageSelected:h,load:g,loadConfig:_,saveConfig:v,onFilterChange:b,resetFilter:x,toggleSelect:S,toggleSelectAllOnPage:C,onReExecuteInLog:ee,deleteOne:w,batchDelete:T,clearAll:E,formatDuration:te,get Document(){return le},get Refresh(){return y},get $t(){return X},get statusLabel(){return at},get statusColor(){return ct},JobLogDetails:hn};return Object.defineProperty(D,"__isScriptSetup",{enumerable:!1,value:!0}),D}});c(),R(),W();var vn={class:`exec-logs`},yn={class:`exec-logs__head`},bn={class:`exec-logs__title-block`},xn={class:`exec-logs__stats`},Sn={class:`exec-logs__head-actions`},Cn={class:`exec-logs__config`},wn={class:`exec-logs__config-label`},Tn={class:`exec-logs__config-field`},En={class:`exec-logs__config-name`},Dn={class:`exec-logs__config-field`},On={class:`exec-logs__config-name`},kn={class:`exec-logs__filter`},An={key:0,class:`exec-logs__batch-meta`},jn={key:0,class:`exec-logs__batch`},Mn={class:`exec-logs__list`},Nn={key:0,class:`exec-logs__empty`},Pn={class:`exec-logs__empty-art`,"aria-hidden":`true`},Fn={class:`exec-logs__empty-title`},In={class:`exec-logs__empty-hint`},Ln={class:`exec-card__head`},Rn=[`title`],zn={class:`exec-card__meta`},Bn={key:0,class:`exec-card__task`},Vn={key:1,class:`exec-card__time`},Hn={key:2,class:`exec-card__exit`},Un=[`title`,`onClick`],Wn={key:0,class:`exec-card__error`},Gn={key:1,class:`exec-logs__pager`};function Kn(t,n,r,a,o,c){let d=be,f=ve,m=C,h=i,g=s,_=p,v=l,y=me,b=re;return K(),S(`div`,vn,[J(` 头部:统计 + 刷新 + 清空。
21
- 标题已由外层 el-dialog 提供,这里不再重复 h2。 `),x(`header`,yn,[x(`div`,bn,[x(`span`,xn,E(a.$t(`@WORKBENCH:共 {count} 条,占 {size} MB`,{count:a.stats.count,size:a.stats.sizeMB})),1)]),x(`div`,Sn,[e(d,{icon:a.Refresh,size:`small`,loading:a.loading,onClick:a.load},{default:L(()=>[z(E(a.$t(`@WORKBENCH:刷新`)),1)]),_:1},8,[`icon`,`loading`]),e(d,{type:`danger`,plain:``,size:`small`,disabled:a.stats.count===0,onClick:a.clearAll},{default:L(()=>[z(E(a.$t(`@WORKBENCH:清空全部`)),1)]),_:1},8,[`disabled`])])]),J(` 保留策略 `),x(`div`,Cn,[x(`span`,wn,E(a.$t(`@WORKBENCH:保存策略`)),1),x(`span`,Tn,[x(`span`,En,E(a.$t(`@WORKBENCH:最大条数`)),1),e(f,{modelValue:a.configDraft.maxCount,"onUpdate:modelValue":n[0]||=e=>a.configDraft.maxCount=e,min:0,max:1e4,step:50,size:`small`,"controls-position":`right`,style:{width:`130px`}},null,8,[`modelValue`])]),x(`span`,Dn,[x(`span`,On,E(a.$t(`@WORKBENCH:最大体积 (MB)`)),1),e(f,{modelValue:a.configDraft.maxSizeMB,"onUpdate:modelValue":n[1]||=e=>a.configDraft.maxSizeMB=e,min:0,max:10240,step:32,size:`small`,"controls-position":`right`,style:{width:`140px`}},null,8,[`modelValue`])]),e(d,{type:`primary`,size:`small`,loading:a.configSaving,onClick:a.saveConfig},{default:L(()=>[z(E(a.$t(`@WORKBENCH:保存策略`)),1)]),_:1},8,[`loading`])]),J(` 过滤栏 `),x(`div`,kn,[e(m,{modelValue:a.filter.q,"onUpdate:modelValue":n[2]||=e=>a.filter.q=e,placeholder:a.$t(`@WORKBENCH:搜索标题 / 任务`),clearable:``,size:`small`,style:{width:`240px`},onKeyup:F(a.onFilterChange,[`enter`]),onClear:a.onFilterChange},null,8,[`modelValue`,`placeholder`]),e(g,{modelValue:a.filter.status,"onUpdate:modelValue":n[3]||=e=>a.filter.status=e,placeholder:a.$t(`@WORKBENCH:全部状态`),clearable:``,size:`small`,style:{width:`130px`},onChange:a.onFilterChange},{default:L(()=>[(K(),S(k,null,D(a.STATUS_OPTIONS,t=>e(h,{key:t.value,label:t.label,value:t.value},null,8,[`label`,`value`])),64))]),_:1},8,[`modelValue`,`placeholder`]),e(d,{size:`small`,onClick:a.resetFilter},{default:L(()=>[z(E(a.$t(`@WORKBENCH:重置`)),1)]),_:1}),n[5]||=x(`span`,{class:`exec-logs__filter-spacer`},null,-1),a.selectedIds.size>0?(K(),S(`span`,An,E(a.$t(`@WORKBENCH:已选择 {count} 项`,{count:a.selectedIds.size})),1)):J(`v-if`,!0)]),J(` 批量操作条 `),a.selectedIds.size>0?(K(),S(`div`,jn,[e(_,{"model-value":a.isAllOnPageSelected,indeterminate:a.isSomeOnPageSelected,onChange:a.toggleSelectAllOnPage},{default:L(()=>[z(E(a.isAllOnPageSelected?a.$t(`@WORKBENCH:取消全选`):a.$t(`@WORKBENCH:全选`)),1)]),_:1},8,[`model-value`,`indeterminate`]),e(d,{type:`danger`,size:`small`,onClick:a.batchDelete},{default:L(()=>[z(E(a.$t(`@WORKBENCH:批量删除`)),1)]),_:1})])):J(`v-if`,!0),J(` 列表 `),A((K(),S(`div`,Mn,[!a.loading&&a.list.length===0?(K(),S(`div`,Nn,[x(`div`,Pn,[e(v,null,{default:L(()=>[e(a.Document)]),_:1})]),x(`div`,Fn,E(a.$t(`@WORKBENCH:暂无执行日志`)),1),x(`div`,In,E(a.$t(`@WORKBENCH:点击「执行任务」开始一次执行,日志会出现在这里。`)),1)])):J(`v-if`,!0),(K(!0),S(k,null,D(a.list,t=>(K(),S(`article`,{key:t.id,class:w([`exec-card`,{"is-selected":a.selectedIds.has(t.id)}])},[x(`header`,Ln,[e(_,{"model-value":a.selectedIds.has(t.id),onChange:e=>a.toggleSelect(t.id,e)},null,8,[`model-value`,`onChange`]),x(`span`,{class:`exec-card__status`,style:u({color:a.statusColor(t.status),borderColor:a.statusColor(t.status)})},E(a.statusLabel(t.status)),5),x(`span`,{class:`exec-card__title`,title:t.title||a.$t(`@WORKBENCH:无标题`)},E(t.title||a.$t(`@WORKBENCH:无标题`)),9,Rn),n[6]||=x(`span`,{class:`exec-card__spacer`},null,-1),x(`span`,zn,[t.taskTitle?(K(),S(`span`,Bn,`📁 `+E(t.taskTitle),1)):J(`v-if`,!0),t.startedAt?(K(),S(`span`,Vn,`⏱ `+E(a.formatDuration(t.startedAt,t.endedAt)),1)):J(`v-if`,!0),t.exitCode===null?J(`v-if`,!0):(K(),S(`span`,Hn,`exit `+E(t.exitCode),1))]),x(`button`,{type:`button`,class:`exec-card__del`,title:a.$t(`@WORKBENCH:删除`),onClick:e=>a.deleteOne(t.id)},`×`,8,Un)]),t.error?(K(),S(`p`,Wn,`⚠ `+E(t.error),1)):J(`v-if`,!0),e(a.JobLogDetails,{job:t,onReExecute:a.onReExecuteInLog},null,8,[`job`])],2))),128))])),[[b,a.loading]]),J(` 分页 `),a.total>a.pageSize?(K(),S(`footer`,Gn,[e(y,{"current-page":a.filter.page,"onUpdate:currentPage":n[4]||=e=>a.filter.page=e,"page-size":a.pageSize,total:a.total,layout:`prev, pager, next, total`,background:``,small:``,onCurrentChange:a.load},null,8,[`current-page`,`total`])])):J(`v-if`,!0)])}var qn=Z(_n,[[`render`,Kn],[`__scopeId`,`data-v-d3ebe953`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/ExecutionLogManager.vue`]]);function Jn(e){return String(e.manualDoneAt||e.lastJobEndedAt||e.updatedAt||e.createdAt||``)}function Yn(e){return e.column===`done`?Jn(e):e.updatedAt||e.createdAt||``}function Xn(e){return e.live?``:_t(e.lastDurationMs)}function Zn(e){let t=Xn(e);return t?X(`@WORKBENCH:用时 {d}`,{d:t}):``}function Qn(e){return e.live?X(`@WORKBENCH:已运行 {elapsed}`,{elapsed:_t(e.live.elapsedMs)}):``}function $n(e){return Qn(e)||Zn(e)}function er(e){let t=Xn(e);if(!t)return``;let n=yt(e.lastJobStartedAt),r=yt(e.lastJobEndedAt);return!n||!r?t:`${t} · ${n} → ${r}`}V();var tr=new Set([`image/png`,`image/jpeg`,`image/jpg`,`image/gif`,`image/webp`,`image/bmp`,`image/svg+xml`,`application/pdf`,`text/plain`,`text/markdown`,`text/x-markdown`,`text/csv`,`application/json`,`text/json`,`text/x-log`]),nr=`.png,.jpg,.jpeg,.gif,.webp,.bmp,.svg,.pdf,.txt,.md,.csv,.json,.log`,rr=20971520,ir=3840,ar=new Set([`image/png`,`image/jpeg`,`image/jpg`,`image/webp`,`image/bmp`]);function or(e){if(e.size<=3670016)return!1;let t=String(e.type||``).toLowerCase();return t?ar.has(t):/\.(png|jpe?g|webp|bmp)$/i.test(e.name)}function sr(e,t){return`${String(e||`attachment`).replace(/\.[^./\\]+$/,``)}.${t}`}async function cr(e){if(typeof createImageBitmap==`function`)try{let t=await createImageBitmap(e);return{source:t,width:t.width,height:t.height,release:()=>t.close()}}catch{}return await new Promise(t=>{let n=URL.createObjectURL(e),r=new Image;r.onload=()=>t({source:r,width:r.naturalWidth,height:r.naturalHeight,release:()=>URL.revokeObjectURL(n)}),r.onerror=()=>{URL.revokeObjectURL(n),t(null)},r.src=n})}function lr(e,t,n){return new Promise(r=>{try{e.toBlob(e=>r(e&&e.type===t?e:null),t,n)}catch{r(null)}})}async function ur(e){let t=await cr(e);if(!t)return null;try{let n=[{edge:ir,quality:.95},{edge:ir,quality:.85},{edge:2560,quality:.85},{edge:1920,quality:.8}],r=null;for(let e of n){let n=Math.min(1,e.edge/Math.max(t.width,t.height)),i=Math.max(1,Math.round(t.width*n)),a=Math.max(1,Math.round(t.height*n)),o=document.createElement(`canvas`);o.width=i,o.height=a;let s=o.getContext(`2d`);if(!s)return null;s.drawImage(t.source,0,0,i,a);let c=await lr(o,`image/webp`,e.quality)||await lr(o,`image/jpeg`,e.quality);if(!c)return null;if((!r||c.size<r.size)&&(r=c),c.size<=3670016)break}return!r||r.size>=e.size?null:{blob:r,ext:r.type===`image/webp`?`webp`:`jpg`}}catch{return null}finally{t.release()}}function dr(){let e=P({}),t=P(null);function n(t){return!!e.value[t]}function r(e,t){if(e instanceof File)return e;let n=e.type||`application/octet-stream`;return new File([e],t,{type:n})}function i(e){return e.kind===`draft`?`draft`:`task-${e.task?.id??``}`}function a(e){if(e.kind===`draft`)return e.list;let t=e.task?.attachments;return Array.isArray(t)?t:[]}function o(e,t){if(e.kind===`draft`){e.replace(t);return}e.task&&(e.task.attachments=t)}function s(e){return e.kind===`draft`?`/api/workbench/orchestrator/attachments`:`/api/workbench/tasks/${e.task?.id??``}/attachments`}function c(e,t){return e.kind===`draft`?`/api/workbench/orchestrator/attachments/${t}`:`/api/workbench/tasks/${e.task?.id??``}/attachments/${t}`}function l(e,t){if(!e.clipboardData)return;let n=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&e.type.startsWith(`image/`));if(n.length>0){e.preventDefault();for(let e of n){let n=e.getAsFile();if(!n)continue;let i=(n.type.split(`/`)[1]||`png`).replace(`jpeg`,`jpg`);d(t,r(n,`paste-${new Date().toISOString().replace(/[:.]/g,`-`)}.${i}`))}return}let i=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&!e.type.startsWith(`image/`));if(i.length>0){e.preventDefault();for(let e of i){let n=e.getAsFile();n&&d(t,r(n,n.name||`pasted-file`))}}}function u(e,n){t.value=null,Array.from(e.dataTransfer?.files||[]).forEach(e=>d(n,e))}async function d(t,n){if(!tr.has(n.type)&&!n.name.match(/\.(png|jpg|jpeg|gif|webp|bmp|svg|pdf|txt|md|markdown|csv|json|log)$/i)){I.error(`${X(`@WORKBENCH:不支持的文件类型`)}(${n.name})`);return}if(a(t).find(e=>e.originalName===n.name&&e.size===n.size)){I.info(`${n.name} ${X(`@WORKBENCH:已存在,已复用`)}`);return}let c=i(t);e.value[c]=!0;try{let e=n;if(or(n)){let t=await ur(n);t&&(e=r(t.blob,sr(n.name,t.ext)),I.info(X(`@WORKBENCH:图片过大,已压缩后上传:{from} → {to}`,{from:g(n.size),to:g(e.size)})))}if(e.size>20971520){I.error(`「${n.name}」${X(`@WORKBENCH:超过 {size} 限制`,{size:g(rr)})}`);return}let i=await fetch(s(t),{method:`POST`,headers:{"Content-Type":`application/octet-stream`,"X-Original-Name":encodeURIComponent(e.name),"X-Mime-Type":e.type||`application/octet-stream`},body:e}).then(e=>e.json());if(i.success){let n=a(t);n.push(i.attachment),o(t,n),I.success(`${X(`@WORKBENCH:已添加:`)}${e.name}`)}else I.error(i.error||X(`@WORKBENCH:上传失败`))}catch(e){I.error(X(`@WORKBENCH:上传失败`)+`:`+(e&&e.message||e))}finally{e.value[c]=!1}}async function f(e,t){try{await fe.confirm(X(`@WORKBENCH:删除附件「{name}」?`,{name:t.originalName}),X(`@WORKBENCH:确认`),{type:`warning`})}catch{return}let n=await fetch(c(e,t.id),{method:`DELETE`}).then(e=>e.json());n.success?(o(e,a(e).filter(e=>e.id!==t.id)),I.success(X(`@WORKBENCH:已删除`))):I.error(n.error||X(`@WORKBENCH:删除失败`))}function p(e){let t=document.createElement(`input`);t.type=`file`,t.accept=nr,t.multiple=!0,t.onchange=()=>{Array.from(t.files||[]).forEach(t=>d(e,t))},t.click()}let m=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`bmp`,`svg`]);function h(e){let t=String(e?.ext||``).toLowerCase();if(t&&m.has(t)||String(e?.mimeType||``).toLowerCase().startsWith(`image/`))return!0;let n=String(e?.originalName||``).toLowerCase();return/\.(png|jpe?g|gif|webp|bmp|svg)$/.test(n)}function g(e){return e<1024?`${e} B`:e<1048576?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(2)} MB`}return{uploadingTargets:e,pasteHoverId:t,isUploading:n,ensureFile:r,isImageAttachment:h,humanSize:g,targetKey:i,targetAttachments:a,setTargetAttachments:o,targetUploadUrl:s,targetDeleteUrl:c,onAttachmentPaste:l,onAttachmentDrop:u,uploadAttachment:d,removeAttachment:f,pickAttachmentFile:p}}c();var fr=`__simple`,pr=65536;function mr(e,t){function n(t){if(!t)return[];let n=`${t.id}${fr}`;return e.value.filter(e=>e.subId===n||e.subId.startsWith(`${n}__r`)).sort((e,t)=>{let n=e.startedAt||``,r=t.startedAt||``;return n&&r?n.localeCompare(r):n?-1:+!!r})}function r(e){if(!e)return null;let t=n(e);return t.length>0?t[t.length-1]:null}function i(e){return e?e.status===`pending`||e.status===`running`?`running`:e.status===`done`?`done`:e.status===`cancelled`?`cancelled`:`error`:`idle`}return{simpleConversationMessages:Y(()=>{if(!t.value)return[];let e=n(t.value);if(e.length===0)return[];let r=[];return e.forEach((t,n)=>{let i=n===e.length-1,a=t.startedAt?new Date(t.startedAt).getTime():Date.now();if(t.prompt){let e=dt(t.prompt);e&&r.push({id:`${t.id}-u`,role:`user`,content:e,status:`done`,createdAt:a})}let o=t.output||``,s=t.thinking||``,c=o.length>pr?`\u2026(前文已截断)\n${o.slice(-65536)}`:o,l=s.length>pr?`\u2026(前文已截断)\n${s.slice(-65536)}`:s,u=!!c,d=!!l,f=pt(t),p=f.length>0,m=u||d||p,h;if(!i)h=`done`;else{let e=t.status;h=e===`running`||e===`pending`?m?`streaming`:`pending`:e===`error`?`error`:`done`}r.push({id:`${t.id}-a`,role:`assistant`,content:Ye(c,t.id),reasoning:d?l:void 0,reasoningStatus:d?!i&&u||u?`done`:h===`streaming`?`streaming`:`done`:void 0,...Wt(t),toolCalls:p?f:void 0,status:h,error:h===`error`&&t.error||void 0,createdAt:a})}),r}),simpleAllJobsFor:n,simpleJobFor:r,simpleJobState:i,SIMPLE_SUB_ID_SUFFIX:fr,MAX_LOG_DISPLAY_SIMPLE:pr}}c(),V();function hr(e,t,n,r){function i(){return{executor:r.getExecutor()}}async function a(e){if(!n.value||n.value.id!==e.id)return!0;let i=t.value.find(t=>t.id===e.id);return i&&i.title===n.value.title&&i.desc===n.value.desc?!0:await r.persistTask(!1)}async function o(e){if(!await a(e))return;await r.clearJobsByTask(e.id);let t=await fetch(`/api/workbench/tasks/${encodeURIComponent(e.id)}/run`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(i())}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));t.success?I.success(t.message||X(`@WORKBENCH:已加入执行队列`)):I.error(t.error||X(`@WORKBENCH:执行失败`))}async function s(t,n){let r=e.value.filter(e=>e.taskId===t.id).slice(-1)[0];if(!r)return I.error(X(`@WORKBENCH:没有可续接的会话`)),!1;let i=Array.isArray(t.attachments)?t.attachments:[],a=await fetch(`/api/workbench/jobs/${r.id}/continue`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({userMessage:n,attachments:i})}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));return a.success?(I.success(a.message||X(`@WORKBENCH:已加入续接队列`)),!0):(I.error(a.error||X(`@WORKBENCH:续接失败`)),!1)}let c=de({}),l=new Set,u=0;function d(t){return e.value.some(e=>e.taskId===t&&(e.status===`running`||e.status===`pending`))}function f(e){return c[e]??[]}function p(e,t,n=[]){(c[e.id]??(c[e.id]=[])).push({id:`q-${Date.now()}-${++u}`,text:t,files:n})}function m(e,t){let n=c[e];if(!n)return;let r=n.findIndex(e=>e.id===t);r<0||(n.splice(r,1),n.length||delete c[e])}async function h(e,t){for(let n of t.files)await r.uploadAttachment({kind:`task`,task:e},n.file);return await s(e,t.text)}async function g(e){if(l.has(e))return;let n=c[e];if(!n||n.length===0||d(e))return;let r=t.value.find(t=>t.id===e);if(!r){delete c[e];return}let i=n[0];l.add(e);try{await h(r,i)&&m(e,i.id)}finally{l.delete(e)}}let _=Y(()=>{let t=new Set;for(let n of e.value)(n.status===`running`||n.status===`pending`)&&t.add(n.taskId);return t});U(_,(t,n)=>{if(n)for(let r of n)t.has(r)||c[r]?.length&&e.value.some(e=>e.taskId===r)&&g(r)});async function v(e,t){let n=t.text.trim();if(n){if(d(e.id)){p(e,n,t.files);return}await h(e,{text:n,files:t.files})}}async function y(e){let n=t.value.find(t=>t.id===e.taskId)||t.value.find(t=>t.id===String(e.subId||``).replace(/__simple(?:__r\d+)?$/,``));if(!n){I.error(X(`@WORKBENCH:找不到对应任务,无法重新执行`));return}await o(n)}async function b(e){try{await fe.confirm(X(`@WORKBENCH:确认停止执行?已输出的内容会保留。`),X(`@WORKBENCH:停止执行`),{confirmButtonText:X(`@WORKBENCH:停止`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}let t=await fetch(`/api/workbench/jobs/${e.id}/cancel`,{method:`POST`}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));t.success?I.success(X(`@WORKBENCH:已发送停止信号`)):I.error(t.error||X(`@WORKBENCH:停止失败`))}async function x(){if(!n.value)return;let t=n.value,r=e.value.filter(e=>e.taskId===t.id),i=r.filter(e=>e.status===`running`||e.status===`pending`).length,a=r.length===0?X(`@WORKBENCH:当前任务还没有执行内容,确认仍要清空?`):X(`@WORKBENCH:将清空 {m} 条执行记录,任务描述/附件保留。`,{m:r.length});try{await fe.confirm(a,X(`@WORKBENCH:清空执行内容`),{confirmButtonText:X(`@WORKBENCH:清空`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}if(i>0){I.warning(X(`@WORKBENCH:任务正在执行,请先停止`));return}let o=await fetch(`/api/workbench/tasks/${encodeURIComponent(t.id)}/clear-execution`,{method:`POST`,headers:{"Content-Type":`application/json`}}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));o?.success?(e.value=e.value.filter(e=>e.taskId!==t.id),I.success(o.message||X(`@WORKBENCH:已清空执行内容`))):I.error(o?.error||X(`@WORKBENCH:清空失败`))}return{runTask:o,continueChat:s,onContinueSendFromChat:v,onReExecuteJob:y,cancelJob:b,clearExecutionForSelectedTask:x,isTaskRunning:d,queuedChatsOf:f,removeQueuedChat:m,flushNextQueued:g}}V();function gr(){let e=P([]),t=P([]),n=P({path:``,name:``});function r(n,r){if(n===`hello`){t.value=r.jobs||[];return}if(n===`job:update`){let e=r,n=t.value.findIndex(t=>t.id===e.id);if(n>=0){let r=t.value[n];!e.thinkingStartedAt&&r.thinkingStartedAt&&(e.thinkingStartedAt=r.thinkingStartedAt),!e.thinkingEndedAt&&r.thinkingEndedAt&&(e.thinkingEndedAt=r.thinkingEndedAt),t.value[n]=e}else t.value.push(e);return}if(n===`job:thinking-delta`||n===`job:output-delta`){let e=n===`job:thinking-delta`?`thinking`:`output`,i=r?.delta||``;if(!i)return;let a=t.value.findIndex(e=>e.id===r.id);if(a<0)return;let o=t.value[a];if(o[e]=(o[e]||``)+i,n===`job:thinking-delta`){let e=new Date().toISOString();o.thinkingStartedAt||=e,o.thinkingEndedAt=e}return}if(n===`job:toolcalls`){let e=Array.isArray(r?.updates)?r.updates:[];if(!e.length)return;let n=t.value.findIndex(e=>e.id===r.id);if(n<0)return;let i=t.value[n];for(let t of e){if(!t||!t.id)continue;Array.isArray(i.toolCalls)||(i.toolCalls=[]);let e=i.toolCalls.findIndex(e=>e.id===t.id);e>=0?i.toolCalls[e]={...i.toolCalls[e],...t}:i.toolCalls.push(t)}return}if(n===`task:update`){let t=e.value.findIndex(e=>e.id===r.id);t>=0&&(e.value[t]=r)}if(n===`tasks:reordered`){if(Array.isArray(r?.tasks)){if(r.tasks.length<e.value.length){console.warn(`[SSE tasks:reordered] 数据丢失风险:当前 ${e.value.length} 个任务,服务端只返回 ${r.tasks.length} 个,拒绝覆盖`);return}e.value=r.tasks}return}n===`task:error`&&I.error(r.error||X(`@WORKBENCH:执行出错`))}let i=null;function a(){i&&=(i.close(),null),i=new EventSource(`/api/workbench/events`),i.onmessage=e=>{try{let t=JSON.parse(e.data);r(t.event,t.payload)}catch{}},i.onerror=()=>{i&&=(i.close(),null),setTimeout(a,3e3)}}function o(){i&&=(i.close(),null)}async function s(t){let n=await fetch(`/api/workbench/tasks`).then(e=>e.json()).catch(()=>({tasks:[]}));e.value=n.tasks||[],t?.()}async function c(){let e=await fetch(`/api/workbench/current-project`).then(e=>e.json()).catch(()=>({}));e&&typeof e.projectPath==`string`&&(n.value={path:e.projectPath,name:e.projectName||``})}async function l(){let e=await fetch(`/api/workbench/jobs`).then(e=>e.json()).catch(()=>({jobs:[]}));t.value=e.jobs||[]}async function u(e){try{let n=await fetch(`/api/workbench/jobs/by-task/${encodeURIComponent(e)}`,{method:`DELETE`}).then(e=>e.json());return n?.success?(t.value=t.value.filter(t=>t.taskId!==e),n.removed||0):(console.warn(`[clearJobsByTask] failed:`,n?.error),0)}catch(e){return console.warn(`[clearJobsByTask] error:`,e),0}}async function d(e){let t={title:``,desc:``};e&&(t.projectPath=e);try{let e=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)}).then(e=>e.json());return e.success?e.task||null:(I.error(e.error||X(`@WORKBENCH:保存失败`)),null)}catch{return I.error(X(`@WORKBENCH:保存失败`)),null}}return{tasks:e,jobs:t,currentProject:n,applyJobEvent:r,connectSSE:a,disconnectSSE:o,loadTasks:s,loadCurrentProject:c,loadJobs:l,clearJobsByTask:u,createTask:d}}V(),c();var _r=`__no_project__`,vr=`wb.collapsedGroupPaths.v1`,yr=`wb.seenGroupPaths.v1`;function br(e){try{let t=localStorage.getItem(e);if(!t)return new Set;let n=JSON.parse(t);return new Set(Array.isArray(n)?n.filter(e=>typeof e==`string`):[])}catch{return new Set}}function xr(e,t){try{localStorage.setItem(e,JSON.stringify(Array.from(t)))}catch{}}function Sr(e,t){let n=P(br(vr)),r=P(br(yr));U(n,e=>xr(vr,e),{deep:!1}),U(r,e=>xr(yr,e),{deep:!1});function i(e){return n.value.has(e)}function a(e){n.value.has(e)?n.value.delete(e):n.value.add(e),n.value=new Set(n.value);let t=new Set(r.value);t.add(e),r.value=t}let o=Y(()=>{let r=e.value,i=new Map;for(let e of r){let t=$(e.projectPath)||_r;i.has(t)||i.set(t,[]),i.get(t).push(e)}let a=$(t.value.path),o=Array.from(i.keys()).sort((e,t)=>e===a?-1:t===a||e===_r?1:t===_r?-1:e.localeCompare(t));return{groups:o.map(e=>({path:e,label:e===_r?X(`@WORKBENCH:未关联项目`):e,tasks:i.get(e)})),hasMultiple:o.length>1||o.length===1&&n.value.has(o[0])}});function s(e){if(!e||e===_r)return e;let t=e.split(/[\\/]/).filter(Boolean);return t.length<=1?e:t.slice(-2).join(`/`)}let c=Y(()=>`${$(t.value.path)}|${o.value.groups.map(e=>e.path).join(`
22
- `)}`);return U(c,()=>{let e=$(t.value.path);if(!e)return;let i=new Set(n.value),a=new Set(r.value),s=!1;for(let t of o.value.groups)a.has(t.path)||(a.add(t.path),t.path!==e&&(i.add(t.path),s=!0));s&&(n.value=i),r.value=a},{immediate:!0}),{groupedTasksList:o,isGroupCollapsed:i,toggleGroupCollapsed:a,shortProjectLabel:s}}c(),V();var Cr=5,wr=f({__name:`WorkbenchSidebar`,props:{tasks:{type:Array,required:!0},selectedTaskId:{type:[String,null],required:!0},currentProject:{type:Object,required:!0},creatingTask:{type:Boolean,required:!0},isTaskRunning:{type:Function,required:!0}},emits:[`select-task`,`delete-task`,`copy-task`,`create-task`,`reorder-tasks`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,o=Y(()=>r.currentProject),s=Y(()=>r.tasks),{groupedTasksList:c,isGroupCollapsed:l,toggleGroupCollapsed:u,shortProjectLabel:d}=Sr(s,o),f=Y(()=>$(r.currentProject.path));function p(e){return!!e.projectPath&&$(e.projectPath)!==f.value}function m(e){return(e.title||``).trim()||(e.desc||``).replace(/\s+/g,` `).trim()}function h(e){let t=m(e),n=X(`@WORKBENCH:拖动排序提示`);return t?`${t} · ${n}`:n}function g(e){return r.isTaskRunning(e)}let _=P(null),v=P(null),y=P(null),b=P(null),x=P(null),S=null;function C(){_.value=null,v.value=null,y.value=null,b.value=null,x.value=null,S=null}function ee(e,t,n,r){e.button===0&&(S={pointerY:e.clientY,li:r,taskId:t.id,groupPath:n},window.addEventListener(`mousemove`,w),window.addEventListener(`mouseup`,T,{once:!0}))}function w(e){if(!S)return;if(_.value===null){if(Math.abs(e.clientY-S.pointerY)<Cr)return;_.value=S.taskId,v.value=S.groupPath,window.getSelection()?.removeAllRanges(),document.body.style.userSelect=`none`}let t=document.elementFromPoint(e.clientX,e.clientY);if(!t)return;let n=t.closest(`.wb-task-item`);if(!n){y.value=null,b.value=null,x.value=null;return}let r=n.getAttribute(`data-task-id`),i=n.getAttribute(`data-group-path`);if(!r||!i)return;if(i!==v.value){y.value=null,b.value=null,x.value=null;return}let a=n.getBoundingClientRect(),o=a.top+a.height/2;y.value=r,b.value=i,x.value=e.clientY<o?`before`:`after`}function T(e){if(window.removeEventListener(`mousemove`,w),document.body.style.userSelect=``,!S){C();return}let t=S.groupPath,n=S.taskId,r=y.value,a=x.value,o=b.value;if(C(),!r||!a||o!==t)return;let s=c.value.groups.find(e=>e.path===t);if(!s)return;let l=s.tasks.map(e=>e.id),u=l.indexOf(n);if(u<0)return;l.splice(u,1);let d=l.indexOf(r)+ +(a===`after`);l.splice(d,0,n),i(`reorder-tasks`,{groupPath:t,orderedIds:l})}let E={props:r,emit:i,currentProjectRef:o,tasksRef:s,groupedTasksList:c,isGroupCollapsed:l,toggleGroupCollapsed:u,shortProjectLabel:d,currentProjectKey:f,isOtherProject:p,taskDisplayName:m,taskTooltip:h,taskIsRunning:g,draggingTaskId:_,dragStartGroupPath:v,dragOverTaskId:y,dragOverGroupPath:b,dragPosition:x,get dragStart(){return S},set dragStart(e){S=e},DRAG_THRESHOLD_PX:Cr,resetDragState:C,onTaskMouseDown:ee,onWindowMouseMove:w,onWindowMouseUp:T,get $t(){return X},get Plus(){return a},get Close(){return j},get DocumentAdd(){return q},get Folder(){return ie},get ArrowDown(){return te},get ArrowRight(){return ne},get CopyDocument(){return pe}};return Object.defineProperty(E,"__isScriptSetup",{enumerable:!1,value:!0}),E}});c(),R(),W();var Tr={class:`wb-sidebar`},Er={class:`wb-section`},Dr=[`disabled`],Or=[`aria-expanded`,`title`,`onClick`,`onKeydown`],kr=[`title`],Ar={class:`wb-pill wb-task-group__count`},jr={key:1,class:`wb-task-group__list`},Mr=[`data-task-id`,`data-group-path`,`title`,`aria-pressed`,`onClick`,`onKeydown`,`onMousedown`],Nr={class:`wb-task-item__body`},Pr=[`title`],Fr=[`title`],Ir={class:`wb-task-item__action-group`},Lr=[`title`,`aria-label`,`onClick`],Rr=[`onClick`,`title`,`aria-label`],zr={key:0,class:`wb-empty wb-empty--rich`},Br={class:`wb-empty__art`,"aria-hidden":`true`},Vr={class:`wb-empty__title`},Hr={class:`wb-empty__hint`},Ur={class:`wb-empty__cta`};function Wr(t,n,i,a,o,s){let c=l,u=be;return K(),S(`aside`,Tr,[x(`section`,Er,[J(` 任务分组 header 已去掉:"任务"/"任务列表"/计数 三件套冗余,下方任务项本身已能自我说明。
23
- 提示词分组保留 header(含 + 新建按钮 + 计数),信息密度不一对齐,后续按需统一。 `),x(`button`,{class:`wb-new-btn`,disabled:i.creatingTask,onClick:n[0]||=e=>a.emit(`create-task`)},[e(c,{class:`wb-new-btn__icon`},{default:L(()=>[e(a.Plus)]),_:1}),x(`span`,null,E(a.$t(`@WORKBENCH:新建任务`)),1),n[4]||=x(`span`,{class:`wb-new-btn__shortcut`},`N`,-1)],8,Dr),J(` 一个项目 = 一个块(组头 + 组内任务列表),块内列表限高自滚,见样式里
24
- .wb-task-group__list 那段:单项目攒到几十条时不会把别的项目顶出可视区。 `),x(`ul`,{class:w([`wb-task-list`,{"is-grouped":a.groupedTasksList.hasMultiple}])},[(K(!0),S(k,null,D(a.groupedTasksList.groups,t=>(K(),S(`li`,{key:t.path,class:`wb-task-group`},[a.groupedTasksList.hasMultiple?(K(),S(`div`,{key:0,class:w([`wb-task-group__head`,{"is-current":t.path===a.currentProjectKey,"is-collapsed":a.isGroupCollapsed(t.path)}]),role:`button`,tabindex:`0`,"aria-expanded":!a.isGroupCollapsed(t.path),title:a.isGroupCollapsed(t.path)?a.$t(`@WORKBENCH:展开`):a.$t(`@WORKBENCH:收起`),onClick:e=>a.toggleGroupCollapsed(t.path),onKeydown:[F(N(e=>a.toggleGroupCollapsed(t.path),[`prevent`]),[`enter`]),F(N(e=>a.toggleGroupCollapsed(t.path),[`prevent`]),[`space`])]},[e(c,{class:`wb-task-group__caret`},{default:L(()=>[(K(),r(_(a.isGroupCollapsed(t.path)?a.ArrowRight:a.ArrowDown)))]),_:2},1024),e(c,{class:`wb-task-group__icon`},{default:L(()=>[e(a.Folder)]),_:1}),x(`span`,{class:`wb-task-group__name`,title:t.path===a.currentProjectKey?i.currentProject.path:t.label},E(t.path===a.currentProjectKey?i.currentProject.name:a.shortProjectLabel(t.label)),9,kr),x(`span`,Ar,E(t.tasks.length),1)],42,Or)):J(`v-if`,!0),a.isGroupCollapsed(t.path)?J(`v-if`,!0):(K(),S(`ul`,jr,[(K(!0),S(k,null,D(t.tasks,r=>(K(),S(`li`,{key:r.id,class:w([`wb-task-item`,{active:r.id===i.selectedTaskId,"is-other-project":a.isOtherProject(r),"is-running":a.taskIsRunning(r),"is-dragging":a.draggingTaskId===r.id,"is-drop-before":a.dragOverTaskId===r.id&&a.dragPosition===`before`,"is-drop-after":a.dragOverTaskId===r.id&&a.dragPosition===`after`}]),"data-task-id":r.id,"data-group-path":t.path,title:a.taskTooltip(r),role:`button`,tabindex:`0`,"aria-pressed":r.id===i.selectedTaskId,onClick:e=>a.emit(`select-task`,r),onKeydown:[F(N(e=>a.emit(`select-task`,r),[`prevent`]),[`enter`]),F(N(e=>a.emit(`select-task`,r),[`prevent`]),[`space`])],onMousedown:e=>a.onTaskMouseDown(e,r,t.path,e.currentTarget)},[J(` 单行展示:只显示标题;没写标题用任务描述压平后顶上(CSS ellipsis 截断)。
25
- 子任务数 / 附件数 等 meta 行已移除,降噪 `),x(`div`,Nr,[x(`div`,{class:`wb-task-item__title`,title:a.taskDisplayName(r)},E(a.taskDisplayName(r)),9,Pr)]),a.taskIsRunning(r)?(K(),S(`span`,{key:0,class:`wb-task-item__running-dot`,title:a.$t(`@WORKBENCH:执行中`),"aria-hidden":`true`},null,8,Fr)):J(`v-if`,!0),x(`div`,Ir,[x(`button`,{class:`wb-task-item__copy`,title:a.$t(`@WORKBENCH:复制任务`),"aria-label":a.$t(`@WORKBENCH:复制任务`),onClick:N(e=>a.emit(`copy-task`,r),[`stop`]),onKeydown:n[1]||=N(()=>{},[`stop`])},[e(c,null,{default:L(()=>[e(a.CopyDocument)]),_:1})],40,Lr),J(` 执行中不允许删除:避免误杀正在跑的实例(jobs 还在内存里,
20
+ `),A(x(`div`,cn,[x(`div`,ln,[e(a.ChatContainer,{messages:a.chatMessages,"assistant-name":a.assistantLabel,"assistant-avatar":a.assistantAvatar,"show-avatar":!0,theme:a.configStore.theme,"tool-calls-config":{group:!0,collapseThreshold:2},"plan-config":{labels:{title:a.$t(`@AGENT:计划`),raw:a.$t(`@AGENT:原始参数`)}},"show-input":!1},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`plan-config`])]),J(` footer:任务结束后显示"重新执行",运行中不显示 `),a.canReExecute?(K(),S(`footer`,un,[x(`button`,{type:`button`,class:`wb-chat__action`,title:a.$t(`@WORKBENCH:用相同的提示词重新执行此任务`),"aria-label":a.$t(`@WORKBENCH:重新执行`),onClick:a.onReExecute},` ↻ `,8,dn)])):J(`v-if`,!0),J(` 全屏查看 dialog `),e(a.CommonDialog,{modelValue:a.fullscreenOpen,"onUpdate:modelValue":n[0]||=e=>a.fullscreenOpen=e,title:a.$t(`@WORKBENCH:模型返回 - 全屏查看`),size:`fullscreen`,type:`flex`,"close-on-click-modal":!1,"custom-class":`wb-log-fullscreen-dialog`,onClosed:a.onFullscreenClosed},{default:L(()=>[x(`div`,fn,[a.hasOutput?(K(),r(a.MarkdownRenderer,{key:0,source:a.fullscreenSource,class:`wb-log-fullscreen__render`},null,8,[`source`])):(K(),S(`div`,pn,D(a.$t(`@WORKBENCH:(暂无输出)`)),1))],512)]),_:1},8,[`modelValue`,`title`])],512),[[H,!a.isCollapsed]]),J(` /.wb-log-details__body `)],2)}var hn=Z(Kt,[[`render`,mn],[`__scopeId`,`data-v-a4bb55c4`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/JobLogDetails.vue`]]);c(),V();var gn=50,_n=f({__name:`ExecutionLogManager`,setup(e,{expose:t}){t();function n(e){return e instanceof Error?e.message:String(e)}let r=P([]),i=P(0),a=de({count:0,sizeMB:0,byStatus:{}}),s=P(!1),c=P(new Set),l=de({q:``,status:``,page:1}),u=P({maxCount:500,maxSizeMB:256}),d=de({maxCount:500,maxSizeMB:256}),f=P(!1),p=[{value:`pending`,label:X(`@WORKBENCH:排队中`)},{value:`running`,label:X(`@WORKBENCH:执行中`)},{value:`done`,label:X(`@WORKBENCH:已完成`)},{value:`error`,label:X(`@WORKBENCH:出错`)},{value:`cancelled`,label:X(`@WORKBENCH:已取消`)}],m=Y(()=>r.value.length>0&&r.value.every(e=>c.value.has(e.id))),h=Y(()=>r.value.some(e=>c.value.has(e.id))&&!m.value);async function g(){s.value=!0;try{let e=new URLSearchParams;l.q&&e.set(`q`,l.q),l.status&&e.set(`status`,l.status),e.set(`limit`,String(gn)),e.set(`offset`,String((l.page-1)*gn));let t=await fetch(`/api/workbench/jobs/list?${e.toString()}`).then(e=>e.json());if(!t.success)throw Error(t.error||`list failed`);r.value=t.jobs,i.value=t.total,a.count=t.stats.count,a.sizeMB=t.stats.sizeMB,a.byStatus=t.stats.byStatus;let n=new Set(r.value.map(e=>e.id));for(let e of Array.from(c.value))n.has(e)||c.value.delete(e)}catch(e){I.error(X(`@WORKBENCH:加载失败`)+`: `+n(e))}finally{s.value=!1}}async function _(){try{let e=await fetch(`/api/workbench/jobs/config`).then(e=>e.json());e.success&&(u.value=e.config,d.maxCount=e.config.maxCount,d.maxSizeMB=e.config.maxSizeMB)}catch{}}async function v(){f.value=!0;try{let e=await fetch(`/api/workbench/jobs/config`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({maxCount:d.maxCount,maxSizeMB:d.maxSizeMB})}).then(e=>e.json());if(!e.success)throw Error(e.error||`save failed`);u.value=e.config,I.success(X(`@WORKBENCH:已保存策略`)),await g()}catch(e){I.error(X(`@WORKBENCH:保存失败`)+`: `+n(e))}finally{f.value=!1}}function b(){l.page=1,g()}function x(){l.q=``,l.status=``,l.page=1,g()}function S(e,t){t?c.value.add(e):c.value.delete(e),c.value=new Set(c.value)}function C(e){if(e)for(let e of r.value)c.value.add(e.id);else for(let e of r.value)c.value.delete(e.id);c.value=new Set(c.value)}function w(e){I.info(X(`@WORKBENCH:请到工作台主面板的对应任务上点击「重新执行」`))}async function T(e){try{await fe.confirm(X(`@WORKBENCH:确定要删除所选的 {count} 条日志吗?`,{count:1}),X(`@WORKBENCH:删除`),{type:`warning`})}catch{return}try{let t=await fetch(`/api/workbench/jobs/${e}`,{method:`DELETE`}).then(e=>e.json());if(!t.success)throw Error(t.error||`delete failed`);c.value.delete(e),c.value=new Set(c.value),await g()}catch(e){I.error(X(`@WORKBENCH:保存失败`)+`: `+n(e))}}async function E(){let e=Array.from(c.value);if(e.length!==0){try{await fe.confirm(X(`@WORKBENCH:确定要删除所选的 {count} 条日志吗?`,{count:e.length}),X(`@WORKBENCH:批量删除`),{type:`warning`})}catch{return}try{let t=await fetch(`/api/workbench/jobs/batch-delete`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({ids:e})}).then(e=>e.json());if(!t.success)throw Error(t.error||`batch delete failed`);I.success(X(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e.length})),c.value=new Set,await g()}catch(e){I.error(X(`@WORKBENCH:保存失败`)+`: `+n(e))}}}async function D(){let e=a.count;if(e!==0){try{await fe.confirm(X(`@WORKBENCH:确定要清空所有 {count} 条执行日志吗?此操作不可恢复。`,{count:e}),X(`@WORKBENCH:清空全部`),{type:`warning`,confirmButtonText:X(`@WORKBENCH:清空全部`)})}catch{return}try{let t=await fetch(`/api/workbench/jobs/clear`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({confirm:!0})}).then(e=>e.json());if(!t.success)throw Error(t.error||`clear failed`);I.success(X(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e})),c.value=new Set,await g()}catch(e){I.error(X(`@WORKBENCH:保存失败`)+`: `+n(e))}}}function ee(e,t){if(!e)return``;let n=new Date(e).getTime(),r=t?new Date(t).getTime():Date.now(),i=Math.max(0,r-n);return i<1e3?`${i}ms`:i<6e4?`${(i/1e3).toFixed(1)}s`:i<36e5?`${Math.floor(i/6e4)}m ${Math.floor(i%6e4/1e3)}s`:`${Math.floor(i/36e5)}h ${Math.floor(i%36e5/6e4)}m`}o(()=>{g(),_()});let O={errMsg:n,list:r,total:i,stats:a,loading:s,selectedIds:c,pageSize:gn,filter:l,config:u,configDraft:d,configSaving:f,STATUS_OPTIONS:p,isAllOnPageSelected:m,isSomeOnPageSelected:h,load:g,loadConfig:_,saveConfig:v,onFilterChange:b,resetFilter:x,toggleSelect:S,toggleSelectAllOnPage:C,onReExecuteInLog:w,deleteOne:T,batchDelete:E,clearAll:D,formatDuration:ee,get Document(){return le},get Refresh(){return y},get $t(){return X},get statusLabel(){return at},get statusColor(){return ct},JobLogDetails:hn};return Object.defineProperty(O,"__isScriptSetup",{enumerable:!1,value:!0}),O}});c(),R(),W();var vn={class:`exec-logs`},yn={class:`exec-logs__head`},bn={class:`exec-logs__title-block`},xn={class:`exec-logs__stats`},Sn={class:`exec-logs__head-actions`},Cn={class:`exec-logs__config`},wn={class:`exec-logs__config-label`},Tn={class:`exec-logs__config-field`},En={class:`exec-logs__config-name`},Dn={class:`exec-logs__config-field`},On={class:`exec-logs__config-name`},kn={class:`exec-logs__filter`},An={key:0,class:`exec-logs__batch-meta`},jn={key:0,class:`exec-logs__batch`},Mn={class:`exec-logs__list`},Nn={key:0,class:`exec-logs__empty`},Pn={class:`exec-logs__empty-art`,"aria-hidden":`true`},Fn={class:`exec-logs__empty-title`},In={class:`exec-logs__empty-hint`},Ln={class:`exec-card__head`},Rn=[`title`],zn={class:`exec-card__meta`},Bn={key:0,class:`exec-card__task`},Vn={key:1,class:`exec-card__time`},Hn={key:2,class:`exec-card__exit`},Un=[`title`,`onClick`],Wn={key:0,class:`exec-card__error`},Gn={key:1,class:`exec-logs__pager`};function Kn(t,n,r,a,o,c){let d=be,f=ve,m=C,h=i,g=s,_=p,v=l,y=me,b=re;return K(),S(`div`,vn,[J(` 头部:统计 + 刷新 + 清空。
21
+ 标题已由外层 el-dialog 提供,这里不再重复 h2。 `),x(`header`,yn,[x(`div`,bn,[x(`span`,xn,D(a.$t(`@WORKBENCH:共 {count} 条,占 {size} MB`,{count:a.stats.count,size:a.stats.sizeMB})),1)]),x(`div`,Sn,[e(d,{icon:a.Refresh,size:`small`,loading:a.loading,onClick:a.load},{default:L(()=>[z(D(a.$t(`@WORKBENCH:刷新`)),1)]),_:1},8,[`icon`,`loading`]),e(d,{type:`danger`,plain:``,size:`small`,disabled:a.stats.count===0,onClick:a.clearAll},{default:L(()=>[z(D(a.$t(`@WORKBENCH:清空全部`)),1)]),_:1},8,[`disabled`])])]),J(` 保留策略 `),x(`div`,Cn,[x(`span`,wn,D(a.$t(`@WORKBENCH:保存策略`)),1),x(`span`,Tn,[x(`span`,En,D(a.$t(`@WORKBENCH:最大条数`)),1),e(f,{modelValue:a.configDraft.maxCount,"onUpdate:modelValue":n[0]||=e=>a.configDraft.maxCount=e,min:0,max:1e4,step:50,size:`small`,"controls-position":`right`,style:{width:`130px`}},null,8,[`modelValue`])]),x(`span`,Dn,[x(`span`,On,D(a.$t(`@WORKBENCH:最大体积 (MB)`)),1),e(f,{modelValue:a.configDraft.maxSizeMB,"onUpdate:modelValue":n[1]||=e=>a.configDraft.maxSizeMB=e,min:0,max:10240,step:32,size:`small`,"controls-position":`right`,style:{width:`140px`}},null,8,[`modelValue`])]),e(d,{type:`primary`,size:`small`,loading:a.configSaving,onClick:a.saveConfig},{default:L(()=>[z(D(a.$t(`@WORKBENCH:保存策略`)),1)]),_:1},8,[`loading`])]),J(` 过滤栏 `),x(`div`,kn,[e(m,{modelValue:a.filter.q,"onUpdate:modelValue":n[2]||=e=>a.filter.q=e,placeholder:a.$t(`@WORKBENCH:搜索标题 / 任务`),clearable:``,size:`small`,style:{width:`240px`},onKeyup:F(a.onFilterChange,[`enter`]),onClear:a.onFilterChange},null,8,[`modelValue`,`placeholder`]),e(g,{modelValue:a.filter.status,"onUpdate:modelValue":n[3]||=e=>a.filter.status=e,placeholder:a.$t(`@WORKBENCH:全部状态`),clearable:``,size:`small`,style:{width:`130px`},onChange:a.onFilterChange},{default:L(()=>[(K(),S(k,null,O(a.STATUS_OPTIONS,t=>e(h,{key:t.value,label:t.label,value:t.value},null,8,[`label`,`value`])),64))]),_:1},8,[`modelValue`,`placeholder`]),e(d,{size:`small`,onClick:a.resetFilter},{default:L(()=>[z(D(a.$t(`@WORKBENCH:重置`)),1)]),_:1}),n[5]||=x(`span`,{class:`exec-logs__filter-spacer`},null,-1),a.selectedIds.size>0?(K(),S(`span`,An,D(a.$t(`@WORKBENCH:已选择 {count} 项`,{count:a.selectedIds.size})),1)):J(`v-if`,!0)]),J(` 批量操作条 `),a.selectedIds.size>0?(K(),S(`div`,jn,[e(_,{"model-value":a.isAllOnPageSelected,indeterminate:a.isSomeOnPageSelected,onChange:a.toggleSelectAllOnPage},{default:L(()=>[z(D(a.isAllOnPageSelected?a.$t(`@WORKBENCH:取消全选`):a.$t(`@WORKBENCH:全选`)),1)]),_:1},8,[`model-value`,`indeterminate`]),e(d,{type:`danger`,size:`small`,onClick:a.batchDelete},{default:L(()=>[z(D(a.$t(`@WORKBENCH:批量删除`)),1)]),_:1})])):J(`v-if`,!0),J(` 列表 `),A((K(),S(`div`,Mn,[!a.loading&&a.list.length===0?(K(),S(`div`,Nn,[x(`div`,Pn,[e(v,null,{default:L(()=>[e(a.Document)]),_:1})]),x(`div`,Fn,D(a.$t(`@WORKBENCH:暂无执行日志`)),1),x(`div`,In,D(a.$t(`@WORKBENCH:点击「执行任务」开始一次执行,日志会出现在这里。`)),1)])):J(`v-if`,!0),(K(!0),S(k,null,O(a.list,t=>(K(),S(`article`,{key:t.id,class:T([`exec-card`,{"is-selected":a.selectedIds.has(t.id)}])},[x(`header`,Ln,[e(_,{"model-value":a.selectedIds.has(t.id),onChange:e=>a.toggleSelect(t.id,e)},null,8,[`model-value`,`onChange`]),x(`span`,{class:`exec-card__status`,style:u({color:a.statusColor(t.status),borderColor:a.statusColor(t.status)})},D(a.statusLabel(t.status)),5),x(`span`,{class:`exec-card__title`,title:t.title||a.$t(`@WORKBENCH:无标题`)},D(t.title||a.$t(`@WORKBENCH:无标题`)),9,Rn),n[6]||=x(`span`,{class:`exec-card__spacer`},null,-1),x(`span`,zn,[t.taskTitle?(K(),S(`span`,Bn,`📁 `+D(t.taskTitle),1)):J(`v-if`,!0),t.startedAt?(K(),S(`span`,Vn,`⏱ `+D(a.formatDuration(t.startedAt,t.endedAt)),1)):J(`v-if`,!0),t.exitCode===null?J(`v-if`,!0):(K(),S(`span`,Hn,`exit `+D(t.exitCode),1))]),x(`button`,{type:`button`,class:`exec-card__del`,title:a.$t(`@WORKBENCH:删除`),onClick:e=>a.deleteOne(t.id)},`×`,8,Un)]),t.error?(K(),S(`p`,Wn,`⚠ `+D(t.error),1)):J(`v-if`,!0),e(a.JobLogDetails,{job:t,onReExecute:a.onReExecuteInLog},null,8,[`job`])],2))),128))])),[[b,a.loading]]),J(` 分页 `),a.total>a.pageSize?(K(),S(`footer`,Gn,[e(y,{"current-page":a.filter.page,"onUpdate:currentPage":n[4]||=e=>a.filter.page=e,"page-size":a.pageSize,total:a.total,layout:`prev, pager, next, total`,background:``,small:``,onCurrentChange:a.load},null,8,[`current-page`,`total`])])):J(`v-if`,!0)])}var qn=Z(_n,[[`render`,Kn],[`__scopeId`,`data-v-d3ebe953`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/ExecutionLogManager.vue`]]);function Jn(e){return String(e.manualDoneAt||e.lastJobEndedAt||e.updatedAt||e.createdAt||``)}function Yn(e){return e.column===`done`?Jn(e):e.updatedAt||e.createdAt||``}function Xn(e){return e.live?``:_t(e.lastDurationMs)}function Zn(e){let t=Xn(e);return t?X(`@WORKBENCH:用时 {d}`,{d:t}):``}function Qn(e){return e.live?X(`@WORKBENCH:已运行 {elapsed}`,{elapsed:_t(e.live.elapsedMs)}):``}function $n(e){return Qn(e)||Zn(e)}function er(e){let t=Xn(e);if(!t)return``;let n=yt(e.lastJobStartedAt),r=yt(e.lastJobEndedAt);return!n||!r?t:`${t} · ${n} → ${r}`}V();var tr=new Set([`image/png`,`image/jpeg`,`image/jpg`,`image/gif`,`image/webp`,`image/bmp`,`image/svg+xml`,`application/pdf`,`text/plain`,`text/markdown`,`text/x-markdown`,`text/csv`,`application/json`,`text/json`,`text/x-log`]),nr=`.png,.jpg,.jpeg,.gif,.webp,.bmp,.svg,.pdf,.txt,.md,.csv,.json,.log`,rr=20971520,ir=3840,ar=new Set([`image/png`,`image/jpeg`,`image/jpg`,`image/webp`,`image/bmp`]);function or(e){if(e.size<=3670016)return!1;let t=String(e.type||``).toLowerCase();return t?ar.has(t):/\.(png|jpe?g|webp|bmp)$/i.test(e.name)}function sr(e,t){return`${String(e||`attachment`).replace(/\.[^./\\]+$/,``)}.${t}`}async function cr(e){if(typeof createImageBitmap==`function`)try{let t=await createImageBitmap(e);return{source:t,width:t.width,height:t.height,release:()=>t.close()}}catch{}return await new Promise(t=>{let n=URL.createObjectURL(e),r=new Image;r.onload=()=>t({source:r,width:r.naturalWidth,height:r.naturalHeight,release:()=>URL.revokeObjectURL(n)}),r.onerror=()=>{URL.revokeObjectURL(n),t(null)},r.src=n})}function lr(e,t,n){return new Promise(r=>{try{e.toBlob(e=>r(e&&e.type===t?e:null),t,n)}catch{r(null)}})}async function ur(e){let t=await cr(e);if(!t)return null;try{let n=[{edge:ir,quality:.95},{edge:ir,quality:.85},{edge:2560,quality:.85},{edge:1920,quality:.8}],r=null;for(let e of n){let n=Math.min(1,e.edge/Math.max(t.width,t.height)),i=Math.max(1,Math.round(t.width*n)),a=Math.max(1,Math.round(t.height*n)),o=document.createElement(`canvas`);o.width=i,o.height=a;let s=o.getContext(`2d`);if(!s)return null;s.drawImage(t.source,0,0,i,a);let c=await lr(o,`image/webp`,e.quality)||await lr(o,`image/jpeg`,e.quality);if(!c)return null;if((!r||c.size<r.size)&&(r=c),c.size<=3670016)break}return!r||r.size>=e.size?null:{blob:r,ext:r.type===`image/webp`?`webp`:`jpg`}}catch{return null}finally{t.release()}}function dr(){let e=P({}),t=P(null);function n(t){return!!e.value[t]}function r(e,t){if(e instanceof File)return e;let n=e.type||`application/octet-stream`;return new File([e],t,{type:n})}function i(e){return e.kind===`draft`?`draft`:`task-${e.task?.id??``}`}function a(e){if(e.kind===`draft`)return e.list;let t=e.task?.attachments;return Array.isArray(t)?t:[]}function o(e,t){if(e.kind===`draft`){e.replace(t);return}e.task&&(e.task.attachments=t)}function s(e){return e.kind===`draft`?`/api/workbench/orchestrator/attachments`:`/api/workbench/tasks/${e.task?.id??``}/attachments`}function c(e,t){return e.kind===`draft`?`/api/workbench/orchestrator/attachments/${t}`:`/api/workbench/tasks/${e.task?.id??``}/attachments/${t}`}function l(e,t){if(!e.clipboardData)return;let n=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&e.type.startsWith(`image/`));if(n.length>0){e.preventDefault();for(let e of n){let n=e.getAsFile();if(!n)continue;let i=(n.type.split(`/`)[1]||`png`).replace(`jpeg`,`jpg`);d(t,r(n,`paste-${new Date().toISOString().replace(/[:.]/g,`-`)}.${i}`))}return}let i=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&!e.type.startsWith(`image/`));if(i.length>0){e.preventDefault();for(let e of i){let n=e.getAsFile();n&&d(t,r(n,n.name||`pasted-file`))}}}function u(e,n){t.value=null,Array.from(e.dataTransfer?.files||[]).forEach(e=>d(n,e))}async function d(t,n){if(!tr.has(n.type)&&!n.name.match(/\.(png|jpg|jpeg|gif|webp|bmp|svg|pdf|txt|md|markdown|csv|json|log)$/i)){I.error(`${X(`@WORKBENCH:不支持的文件类型`)}(${n.name})`);return}if(a(t).find(e=>e.originalName===n.name&&e.size===n.size)){I.info(`${n.name} ${X(`@WORKBENCH:已存在,已复用`)}`);return}let c=i(t);e.value[c]=!0;try{let e=n;if(or(n)){let t=await ur(n);t&&(e=r(t.blob,sr(n.name,t.ext)),I.info(X(`@WORKBENCH:图片过大,已压缩后上传:{from} → {to}`,{from:g(n.size),to:g(e.size)})))}if(e.size>20971520){I.error(`「${n.name}」${X(`@WORKBENCH:超过 {size} 限制`,{size:g(rr)})}`);return}let i=await fetch(s(t),{method:`POST`,headers:{"Content-Type":`application/octet-stream`,"X-Original-Name":encodeURIComponent(e.name),"X-Mime-Type":e.type||`application/octet-stream`},body:e}).then(e=>e.json());if(i.success){let n=a(t);n.push(i.attachment),o(t,n),I.success(`${X(`@WORKBENCH:已添加:`)}${e.name}`)}else I.error(i.error||X(`@WORKBENCH:上传失败`))}catch(e){I.error(X(`@WORKBENCH:上传失败`)+`:`+(e&&e.message||e))}finally{e.value[c]=!1}}async function f(e,t){try{await fe.confirm(X(`@WORKBENCH:删除附件「{name}」?`,{name:t.originalName}),X(`@WORKBENCH:确认`),{type:`warning`})}catch{return}let n=await fetch(c(e,t.id),{method:`DELETE`}).then(e=>e.json());n.success?(o(e,a(e).filter(e=>e.id!==t.id)),I.success(X(`@WORKBENCH:已删除`))):I.error(n.error||X(`@WORKBENCH:删除失败`))}function p(e){let t=document.createElement(`input`);t.type=`file`,t.accept=nr,t.multiple=!0,t.onchange=()=>{Array.from(t.files||[]).forEach(t=>d(e,t))},t.click()}let m=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`bmp`,`svg`]);function h(e){let t=String(e?.ext||``).toLowerCase();if(t&&m.has(t)||String(e?.mimeType||``).toLowerCase().startsWith(`image/`))return!0;let n=String(e?.originalName||``).toLowerCase();return/\.(png|jpe?g|gif|webp|bmp|svg)$/.test(n)}function g(e){return e<1024?`${e} B`:e<1048576?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(2)} MB`}return{uploadingTargets:e,pasteHoverId:t,isUploading:n,ensureFile:r,isImageAttachment:h,humanSize:g,targetKey:i,targetAttachments:a,setTargetAttachments:o,targetUploadUrl:s,targetDeleteUrl:c,onAttachmentPaste:l,onAttachmentDrop:u,uploadAttachment:d,removeAttachment:f,pickAttachmentFile:p}}c();var fr=`__simple`,pr=65536;function mr(e,t){function n(t){if(!t)return[];let n=`${t.id}${fr}`;return e.value.filter(e=>e.subId===n||e.subId.startsWith(`${n}__r`)).sort((e,t)=>{let n=e.startedAt||``,r=t.startedAt||``;return n&&r?n.localeCompare(r):n?-1:+!!r})}function r(e){if(!e)return null;let t=n(e);return t.length>0?t[t.length-1]:null}function i(e){return e?e.status===`pending`||e.status===`running`?`running`:e.status===`done`?`done`:e.status===`cancelled`?`cancelled`:`error`:`idle`}return{simpleConversationMessages:Y(()=>{if(!t.value)return[];let e=n(t.value);if(e.length===0)return[];let r=[];return e.forEach((t,n)=>{let i=n===e.length-1,a=t.startedAt?new Date(t.startedAt).getTime():Date.now();if(t.prompt){let e=dt(t.prompt);e&&r.push({id:`${t.id}-u`,role:`user`,content:e,status:`done`,createdAt:a})}let o=t.output||``,s=t.thinking||``,c=o.length>pr?`\u2026(前文已截断)\n${o.slice(-65536)}`:o,l=s.length>pr?`\u2026(前文已截断)\n${s.slice(-65536)}`:s,u=!!c,d=!!l,f=pt(t),p=f.length>0,m=u||d||p,h;if(!i)h=`done`;else{let e=t.status;h=e===`running`||e===`pending`?m?`streaming`:`pending`:e===`error`?`error`:`done`}r.push({id:`${t.id}-a`,role:`assistant`,content:Ye(c,t.id),reasoning:d?l:void 0,reasoningStatus:d?!i&&u||u?`done`:h===`streaming`?`streaming`:`done`:void 0,...Wt(t),toolCalls:p?f:void 0,status:h,error:h===`error`&&t.error||void 0,createdAt:a})}),r}),simpleAllJobsFor:n,simpleJobFor:r,simpleJobState:i,SIMPLE_SUB_ID_SUFFIX:fr,MAX_LOG_DISPLAY_SIMPLE:pr}}c(),V();function hr(e,t,n,r){function i(){return{executor:r.getExecutor()}}async function a(e){if(!n.value||n.value.id!==e.id)return!0;let i=t.value.find(t=>t.id===e.id);return i&&i.title===n.value.title&&i.desc===n.value.desc?!0:await r.persistTask(!1)}async function o(e){if(!await a(e))return;await r.clearJobsByTask(e.id);let t=await fetch(`/api/workbench/tasks/${encodeURIComponent(e.id)}/run`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(i())}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));t.success?I.success(t.message||X(`@WORKBENCH:已加入执行队列`)):I.error(t.error||X(`@WORKBENCH:执行失败`))}async function s(t,n){let r=e.value.filter(e=>e.taskId===t.id).slice(-1)[0];if(!r)return I.error(X(`@WORKBENCH:没有可续接的会话`)),!1;let i=Array.isArray(t.attachments)?t.attachments:[],a=await fetch(`/api/workbench/jobs/${r.id}/continue`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({userMessage:n,attachments:i})}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));return a.success?(I.success(a.message||X(`@WORKBENCH:已加入续接队列`)),!0):(I.error(a.error||X(`@WORKBENCH:续接失败`)),!1)}let c=de({}),l=new Set,u=0;function d(t){return e.value.some(e=>e.taskId===t&&(e.status===`running`||e.status===`pending`))}function f(e){return c[e]??[]}function p(e,t,n=[]){(c[e.id]??(c[e.id]=[])).push({id:`q-${Date.now()}-${++u}`,text:t,files:n})}function m(e,t){let n=c[e];if(!n)return;let r=n.findIndex(e=>e.id===t);r<0||(n.splice(r,1),n.length||delete c[e])}async function h(e,t){for(let n of t.files)await r.uploadAttachment({kind:`task`,task:e},n.file);return await s(e,t.text)}async function g(e){if(l.has(e))return;let n=c[e];if(!n||n.length===0||d(e))return;let r=t.value.find(t=>t.id===e);if(!r){delete c[e];return}let i=n[0];l.add(e);try{await h(r,i)&&m(e,i.id)}finally{l.delete(e)}}let _=Y(()=>{let t=new Set;for(let n of e.value)(n.status===`running`||n.status===`pending`)&&t.add(n.taskId);return t});U(_,(t,n)=>{if(n)for(let r of n)t.has(r)||c[r]?.length&&e.value.some(e=>e.taskId===r)&&g(r)});async function v(e,t){let n=t.text.trim();if(n){if(d(e.id)){p(e,n,t.files);return}await h(e,{text:n,files:t.files})}}async function y(e){let n=t.value.find(t=>t.id===e.taskId)||t.value.find(t=>t.id===String(e.subId||``).replace(/__simple(?:__r\d+)?$/,``));if(!n){I.error(X(`@WORKBENCH:找不到对应任务,无法重新执行`));return}await o(n)}async function b(e){try{await fe.confirm(X(`@WORKBENCH:确认停止执行?已输出的内容会保留。`),X(`@WORKBENCH:停止执行`),{confirmButtonText:X(`@WORKBENCH:停止`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}let t=await fetch(`/api/workbench/jobs/${e.id}/cancel`,{method:`POST`}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));t.success?I.success(X(`@WORKBENCH:已发送停止信号`)):I.error(t.error||X(`@WORKBENCH:停止失败`))}async function x(){if(!n.value)return;let t=n.value,r=e.value.filter(e=>e.taskId===t.id),i=r.filter(e=>e.status===`running`||e.status===`pending`).length,a=r.length===0?X(`@WORKBENCH:当前任务还没有执行内容,确认仍要清空?`):X(`@WORKBENCH:将清空 {m} 条执行记录,任务描述/附件保留。`,{m:r.length});try{await fe.confirm(a,X(`@WORKBENCH:清空执行内容`),{confirmButtonText:X(`@WORKBENCH:清空`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}if(i>0){I.warning(X(`@WORKBENCH:任务正在执行,请先停止`));return}let o=await fetch(`/api/workbench/tasks/${encodeURIComponent(t.id)}/clear-execution`,{method:`POST`,headers:{"Content-Type":`application/json`}}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));o?.success?(e.value=e.value.filter(e=>e.taskId!==t.id),I.success(o.message||X(`@WORKBENCH:已清空执行内容`))):I.error(o?.error||X(`@WORKBENCH:清空失败`))}return{runTask:o,continueChat:s,onContinueSendFromChat:v,onReExecuteJob:y,cancelJob:b,clearExecutionForSelectedTask:x,isTaskRunning:d,queuedChatsOf:f,removeQueuedChat:m,flushNextQueued:g}}V();function gr(){let e=P([]),t=P([]),n=P({path:``,name:``});function r(n,r){if(n===`hello`){t.value=r.jobs||[];return}if(n===`job:update`){let e=r,n=t.value.findIndex(t=>t.id===e.id);if(n>=0){let r=t.value[n];!e.thinkingStartedAt&&r.thinkingStartedAt&&(e.thinkingStartedAt=r.thinkingStartedAt),!e.thinkingEndedAt&&r.thinkingEndedAt&&(e.thinkingEndedAt=r.thinkingEndedAt),t.value[n]=e}else t.value.push(e);return}if(n===`job:thinking-delta`||n===`job:output-delta`){let e=n===`job:thinking-delta`?`thinking`:`output`,i=r?.delta||``;if(!i)return;let a=t.value.findIndex(e=>e.id===r.id);if(a<0)return;let o=t.value[a];if(o[e]=(o[e]||``)+i,n===`job:thinking-delta`){let e=new Date().toISOString();o.thinkingStartedAt||=e,o.thinkingEndedAt=e}return}if(n===`job:toolcalls`){let e=Array.isArray(r?.updates)?r.updates:[];if(!e.length)return;let n=t.value.findIndex(e=>e.id===r.id);if(n<0)return;let i=t.value[n];for(let t of e){if(!t||!t.id)continue;Array.isArray(i.toolCalls)||(i.toolCalls=[]);let e=i.toolCalls.findIndex(e=>e.id===t.id);e>=0?i.toolCalls[e]={...i.toolCalls[e],...t}:i.toolCalls.push(t)}return}if(n===`task:update`){let t=e.value.findIndex(e=>e.id===r.id);t>=0&&(e.value[t]=r)}if(n===`tasks:reordered`){if(Array.isArray(r?.tasks)){if(r.tasks.length<e.value.length){console.warn(`[SSE tasks:reordered] 数据丢失风险:当前 ${e.value.length} 个任务,服务端只返回 ${r.tasks.length} 个,拒绝覆盖`);return}e.value=r.tasks}return}n===`task:error`&&I.error(r.error||X(`@WORKBENCH:执行出错`))}let i=null;function a(){i&&=(i.close(),null),i=new EventSource(`/api/workbench/events`),i.onmessage=e=>{try{let t=JSON.parse(e.data);r(t.event,t.payload)}catch{}},i.onerror=()=>{i&&=(i.close(),null),setTimeout(a,3e3)}}function o(){i&&=(i.close(),null)}async function s(t){let n=await fetch(`/api/workbench/tasks`).then(e=>e.json()).catch(()=>({tasks:[]}));e.value=n.tasks||[],t?.()}async function c(){let e=await fetch(`/api/workbench/current-project`).then(e=>e.json()).catch(()=>({}));e&&typeof e.projectPath==`string`&&(n.value={path:e.projectPath,name:e.projectName||``})}async function l(){let e=await fetch(`/api/workbench/jobs`).then(e=>e.json()).catch(()=>({jobs:[]}));t.value=e.jobs||[]}async function u(e){try{let n=await fetch(`/api/workbench/jobs/by-task/${encodeURIComponent(e)}`,{method:`DELETE`}).then(e=>e.json());return n?.success?(t.value=t.value.filter(t=>t.taskId!==e),n.removed||0):(console.warn(`[clearJobsByTask] failed:`,n?.error),0)}catch(e){return console.warn(`[clearJobsByTask] error:`,e),0}}async function d(e){let t={title:``,desc:``};e&&(t.projectPath=e);try{let e=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)}).then(e=>e.json());return e.success?e.task||null:(I.error(e.error||X(`@WORKBENCH:保存失败`)),null)}catch{return I.error(X(`@WORKBENCH:保存失败`)),null}}return{tasks:e,jobs:t,currentProject:n,applyJobEvent:r,connectSSE:a,disconnectSSE:o,loadTasks:s,loadCurrentProject:c,loadJobs:l,clearJobsByTask:u,createTask:d}}V(),c();var _r=`__no_project__`,vr=`wb.collapsedGroupPaths.v1`,yr=`wb.seenGroupPaths.v1`;function br(e){try{let t=localStorage.getItem(e);if(!t)return new Set;let n=JSON.parse(t);return new Set(Array.isArray(n)?n.filter(e=>typeof e==`string`):[])}catch{return new Set}}function xr(e,t){try{localStorage.setItem(e,JSON.stringify(Array.from(t)))}catch{}}function Sr(e,t){let n=P(br(vr)),r=P(br(yr));U(n,e=>xr(vr,e),{deep:!1}),U(r,e=>xr(yr,e),{deep:!1});function i(e){return n.value.has(e)}function a(e){n.value.has(e)?n.value.delete(e):n.value.add(e),n.value=new Set(n.value);let t=new Set(r.value);t.add(e),r.value=t}let o=Y(()=>{let r=e.value,i=new Map;for(let e of r){let t=$(e.projectPath)||_r;i.has(t)||i.set(t,[]),i.get(t).push(e)}let a=$(t.value.path),o=Array.from(i.keys()).sort((e,t)=>e===a?-1:t===a||e===_r?1:t===_r?-1:e.localeCompare(t));return{groups:o.map(e=>({path:e,label:e===_r?X(`@WORKBENCH:未关联项目`):e,tasks:i.get(e)})),hasMultiple:o.length>1||o.length===1&&n.value.has(o[0])}});function s(e){if(!e||e===_r)return e;let t=e.split(/[\\/]/).filter(Boolean);return t.length<=1?e:t.slice(-2).join(`/`)}let c=Y(()=>`${$(t.value.path)}|${o.value.groups.map(e=>e.path).join(`
22
+ `)}`);return U(c,()=>{let e=$(t.value.path);if(!e)return;let i=new Set(n.value),a=new Set(r.value),s=!1;for(let t of o.value.groups)a.has(t.path)||(a.add(t.path),t.path!==e&&(i.add(t.path),s=!0));s&&(n.value=i),r.value=a},{immediate:!0}),{groupedTasksList:o,isGroupCollapsed:i,toggleGroupCollapsed:a,shortProjectLabel:s}}c(),V();var Cr=5,wr=f({__name:`WorkbenchSidebar`,props:{tasks:{type:Array,required:!0},selectedTaskId:{type:[String,null],required:!0},currentProject:{type:Object,required:!0},creatingTask:{type:Boolean,required:!0},isTaskRunning:{type:Function,required:!0}},emits:[`select-task`,`delete-task`,`copy-task`,`create-task`,`reorder-tasks`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,o=Y(()=>r.currentProject),s=Y(()=>r.tasks),{groupedTasksList:c,isGroupCollapsed:l,toggleGroupCollapsed:u,shortProjectLabel:d}=Sr(s,o),f=Y(()=>$(r.currentProject.path));function p(e){return!!e.projectPath&&$(e.projectPath)!==f.value}function m(e){return(e.title||``).trim()||(e.desc||``).replace(/\s+/g,` `).trim()}function h(e){let t=m(e),n=X(`@WORKBENCH:拖动排序提示`);return t?`${t} · ${n}`:n}function g(e){return r.isTaskRunning(e)}let _=P(null),v=P(null),y=P(null),b=P(null),x=P(null),S=null;function C(){_.value=null,v.value=null,y.value=null,b.value=null,x.value=null,S=null}function w(e,t,n,r){e.button===0&&(S={pointerY:e.clientY,li:r,taskId:t.id,groupPath:n},window.addEventListener(`mousemove`,T),window.addEventListener(`mouseup`,E,{once:!0}))}function T(e){if(!S)return;if(_.value===null){if(Math.abs(e.clientY-S.pointerY)<Cr)return;_.value=S.taskId,v.value=S.groupPath,window.getSelection()?.removeAllRanges(),document.body.style.userSelect=`none`}let t=document.elementFromPoint(e.clientX,e.clientY);if(!t)return;let n=t.closest(`.wb-task-item`);if(!n){y.value=null,b.value=null,x.value=null;return}let r=n.getAttribute(`data-task-id`),i=n.getAttribute(`data-group-path`);if(!r||!i)return;if(i!==v.value){y.value=null,b.value=null,x.value=null;return}let a=n.getBoundingClientRect(),o=a.top+a.height/2;y.value=r,b.value=i,x.value=e.clientY<o?`before`:`after`}function E(e){if(window.removeEventListener(`mousemove`,T),document.body.style.userSelect=``,!S){C();return}let t=S.groupPath,n=S.taskId,r=y.value,a=x.value,o=b.value;if(C(),!r||!a||o!==t)return;let s=c.value.groups.find(e=>e.path===t);if(!s)return;let l=s.tasks.map(e=>e.id),u=l.indexOf(n);if(u<0)return;l.splice(u,1);let d=l.indexOf(r)+ +(a===`after`);l.splice(d,0,n),i(`reorder-tasks`,{groupPath:t,orderedIds:l})}let D={props:r,emit:i,currentProjectRef:o,tasksRef:s,groupedTasksList:c,isGroupCollapsed:l,toggleGroupCollapsed:u,shortProjectLabel:d,currentProjectKey:f,isOtherProject:p,taskDisplayName:m,taskTooltip:h,taskIsRunning:g,draggingTaskId:_,dragStartGroupPath:v,dragOverTaskId:y,dragOverGroupPath:b,dragPosition:x,get dragStart(){return S},set dragStart(e){S=e},DRAG_THRESHOLD_PX:Cr,resetDragState:C,onTaskMouseDown:w,onWindowMouseMove:T,onWindowMouseUp:E,get $t(){return X},get Plus(){return a},get Close(){return j},get DocumentAdd(){return q},get Folder(){return ie},get ArrowDown(){return ee},get ArrowRight(){return te},get CopyDocument(){return pe}};return Object.defineProperty(D,"__isScriptSetup",{enumerable:!1,value:!0}),D}});c(),R(),W();var Tr={class:`wb-sidebar`},Er={class:`wb-section`},Dr=[`disabled`],Or=[`aria-expanded`,`title`,`onClick`,`onKeydown`],kr=[`title`],Ar={class:`wb-pill wb-task-group__count`},jr={key:1,class:`wb-task-group__list`},Mr=[`data-task-id`,`data-group-path`,`title`,`aria-pressed`,`onClick`,`onKeydown`,`onMousedown`],Nr={class:`wb-task-item__body`},Pr=[`title`],Fr=[`title`],Ir={class:`wb-task-item__action-group`},Lr=[`title`,`aria-label`,`onClick`],Rr=[`onClick`,`title`,`aria-label`],zr={key:0,class:`wb-empty wb-empty--rich`},Br={class:`wb-empty__art`,"aria-hidden":`true`},Vr={class:`wb-empty__title`},Hr={class:`wb-empty__hint`},Ur={class:`wb-empty__cta`};function Wr(t,n,i,a,o,s){let c=l,u=be;return K(),S(`aside`,Tr,[x(`section`,Er,[J(` 任务分组 header 已去掉:"任务"/"任务列表"/计数 三件套冗余,下方任务项本身已能自我说明。
23
+ 提示词分组保留 header(含 + 新建按钮 + 计数),信息密度不一对齐,后续按需统一。 `),x(`button`,{class:`wb-new-btn`,disabled:i.creatingTask,onClick:n[0]||=e=>a.emit(`create-task`)},[e(c,{class:`wb-new-btn__icon`},{default:L(()=>[e(a.Plus)]),_:1}),x(`span`,null,D(a.$t(`@WORKBENCH:新建任务`)),1),n[4]||=x(`span`,{class:`wb-new-btn__shortcut`},`N`,-1)],8,Dr),J(` 一个项目 = 一个块(组头 + 组内任务列表),块内列表限高自滚,见样式里
24
+ .wb-task-group__list 那段:单项目攒到几十条时不会把别的项目顶出可视区。 `),x(`ul`,{class:T([`wb-task-list`,{"is-grouped":a.groupedTasksList.hasMultiple}])},[(K(!0),S(k,null,O(a.groupedTasksList.groups,t=>(K(),S(`li`,{key:t.path,class:`wb-task-group`},[a.groupedTasksList.hasMultiple?(K(),S(`div`,{key:0,class:T([`wb-task-group__head`,{"is-current":t.path===a.currentProjectKey,"is-collapsed":a.isGroupCollapsed(t.path)}]),role:`button`,tabindex:`0`,"aria-expanded":!a.isGroupCollapsed(t.path),title:a.isGroupCollapsed(t.path)?a.$t(`@WORKBENCH:展开`):a.$t(`@WORKBENCH:收起`),onClick:e=>a.toggleGroupCollapsed(t.path),onKeydown:[F(N(e=>a.toggleGroupCollapsed(t.path),[`prevent`]),[`enter`]),F(N(e=>a.toggleGroupCollapsed(t.path),[`prevent`]),[`space`])]},[e(c,{class:`wb-task-group__caret`},{default:L(()=>[(K(),r(_(a.isGroupCollapsed(t.path)?a.ArrowRight:a.ArrowDown)))]),_:2},1024),e(c,{class:`wb-task-group__icon`},{default:L(()=>[e(a.Folder)]),_:1}),x(`span`,{class:`wb-task-group__name`,title:t.path===a.currentProjectKey?i.currentProject.path:t.label},D(t.path===a.currentProjectKey?i.currentProject.name:a.shortProjectLabel(t.label)),9,kr),x(`span`,Ar,D(t.tasks.length),1)],42,Or)):J(`v-if`,!0),a.isGroupCollapsed(t.path)?J(`v-if`,!0):(K(),S(`ul`,jr,[(K(!0),S(k,null,O(t.tasks,r=>(K(),S(`li`,{key:r.id,class:T([`wb-task-item`,{active:r.id===i.selectedTaskId,"is-other-project":a.isOtherProject(r),"is-running":a.taskIsRunning(r),"is-dragging":a.draggingTaskId===r.id,"is-drop-before":a.dragOverTaskId===r.id&&a.dragPosition===`before`,"is-drop-after":a.dragOverTaskId===r.id&&a.dragPosition===`after`}]),"data-task-id":r.id,"data-group-path":t.path,title:a.taskTooltip(r),role:`button`,tabindex:`0`,"aria-pressed":r.id===i.selectedTaskId,onClick:e=>a.emit(`select-task`,r),onKeydown:[F(N(e=>a.emit(`select-task`,r),[`prevent`]),[`enter`]),F(N(e=>a.emit(`select-task`,r),[`prevent`]),[`space`])],onMousedown:e=>a.onTaskMouseDown(e,r,t.path,e.currentTarget)},[J(` 单行展示:只显示标题;没写标题用任务描述压平后顶上(CSS ellipsis 截断)。
25
+ 子任务数 / 附件数 等 meta 行已移除,降噪 `),x(`div`,Nr,[x(`div`,{class:`wb-task-item__title`,title:a.taskDisplayName(r)},D(a.taskDisplayName(r)),9,Pr)]),a.taskIsRunning(r)?(K(),S(`span`,{key:0,class:`wb-task-item__running-dot`,title:a.$t(`@WORKBENCH:执行中`),"aria-hidden":`true`},null,8,Fr)):J(`v-if`,!0),x(`div`,Ir,[x(`button`,{class:`wb-task-item__copy`,title:a.$t(`@WORKBENCH:复制任务`),"aria-label":a.$t(`@WORKBENCH:复制任务`),onClick:N(e=>a.emit(`copy-task`,r),[`stop`]),onKeydown:n[1]||=N(()=>{},[`stop`])},[e(c,null,{default:L(()=>[e(a.CopyDocument)]),_:1})],40,Lr),J(` 执行中不允许删除:避免误杀正在跑的实例(jobs 还在内存里,
26
26
  任务从 tasks.json 消失后,runSingleSubtask 读不到 task
27
- 会留一堆孤儿 job)。后端 DELETE 路由也加了同样的 live-job 守卫兜底 `),a.taskIsRunning(r)?J(`v-if`,!0):(K(),S(`button`,{key:0,class:`wb-task-item__del`,onClick:N(e=>a.emit(`delete-task`,r),[`stop`]),onKeydown:n[2]||=N(()=>{},[`stop`]),title:a.$t(`@WORKBENCH:删除`),"aria-label":a.$t(`@WORKBENCH:删除`)},[e(c,null,{default:L(()=>[e(a.Close)]),_:1})],40,Rr))])],42,Mr))),128))]))]))),128)),i.tasks.length===0?(K(),S(`li`,zr,[x(`div`,Br,[e(c,null,{default:L(()=>[e(a.DocumentAdd)]),_:1})]),x(`div`,Vr,E(a.$t(`@WORKBENCH:暂无任务`)),1),x(`div`,Hr,E(a.$t(`@WORKBENCH:点击上方按钮新建`)),1),x(`div`,Ur,[e(u,{type:`primary`,size:`small`,icon:a.Plus,loading:i.creatingTask,onClick:n[3]||=e=>a.emit(`create-task`)},{default:L(()=>[z(E(a.$t(`@WORKBENCH:新建任务`)),1)]),_:1},8,[`icon`,`loading`])])])):J(`v-if`,!0)],2)])])}var Gr=Z(wr,[[`render`,Wr],[`__scopeId`,`data-v-458e9455`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchSidebar.vue`]]);c(),V();var Kr=f({__name:`WorkbenchProjectPanel`,props:{projects:{type:Array,required:!0},selectedKey:{type:String,required:!0},loading:{type:Boolean,required:!0}},emits:[`select`,`remove`],setup(e,{expose:n,emit:r}){n();let i=e,a=r,s=Y(()=>[...i.projects].sort((e,t)=>{if(e.stats.runningJobs>0!=t.stats.runningJobs>0)return e.stats.runningJobs>0?-1:1;let n=e.stats.lastActiveAt||``,r=t.stats.lastActiveAt||``;return n===r?e.name.localeCompare(t.name):r.localeCompare(n)})),c=P(``),l=P(!1),u=P(!1),d=Y(()=>!!c.value.trim()||l.value||u.value),f=Y(()=>l.value||u.value),p=Y(()=>{let e=c.value.trim().toLowerCase();return s.value.filter(t=>l.value&&t.stats.total===0||u.value&&t.git&&t.git.isGitRepo===!1?!1:!e||t.name.toLowerCase().includes(e)||t.path.toLowerCase().includes(e))});function m(){c.value=``,l.value=!1,u.value=!1}let h=P(!1),_=P(null);function v(){h.value=!h.value,h.value&&t(()=>_.value?.focus())}function y(){c.value.trim()||(h.value=!1)}let b=Y(()=>i.projects.reduce((e,t)=>({running:e.running+t.stats.runningJobs,done:e.done+t.stats.done,total:e.total+t.stats.total}),{running:0,done:0,total:0}));function x(e){return e.git?e.git.isGitRepo===null?X(`@WORKBENCH:未知`):e.git.isGitRepo?e.git.detached?X(`@WORKBENCH:游离 HEAD`):e.git.branch||X(`@WORKBENCH:未知`):``:``}function S(e){return!!(e.git&&e.git.isGitRepo&&(e.git.detached||e.git.branch))}let{isIconBroken:C,markIconFailed:w}=Ie(),T=P(null),E=P(null);function te(e,t){if(T.value===e.key){T.value=null;return}E.value=t.currentTarget,T.value=e.key}function D(){T.value=null}function ne(e){if(!T.value)return;let t=e.target;if(t&&!E.value?.contains(t)){for(let e of Array.from(document.querySelectorAll(`.proj-open-menu`)))if(e.contains(t))return;T.value=null}}o(()=>document.addEventListener(`mousedown`,ne,!0)),ee(()=>document.removeEventListener(`mousedown`,ne,!0));async function O(e){D();let t=await Be(e.path);t.success?I.success(t.message||X(`@WORKBENCH:已在文件管理器中打开文件夹`)):I.error(t.error||X(`@WORKBENCH:打开文件夹失败`))}async function k(e){let t=e.name||e.path,n=e.stats.total>0?X(`@WORKBENCH:移除项目「{name}」?会从常用目录和项目列表中去掉它。该项目的 {n} 条任务不会被删除,仍可在「全部项目」下查看。`,{name:t,n:e.stats.total}):X(`@WORKBENCH:移除项目「{name}」?会从常用目录和项目列表中去掉它。`,{name:t});try{await fe.confirm(n,X(`@WORKBENCH:移除项目`),{confirmButtonText:X(`@WORKBENCH:移除`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}a(`remove`,e)}let re={props:i,emit:a,ordered:s,query:c,onlyWithTasks:l,hideNonGit:u,filtering:d,filtersActive:f,visible:p,clearFilters:m,searchOpen:h,searchInputRef:_,toggleSearch:v,onSearchBlur:y,totals:b,gitLine:x,hasBranchIcon:S,isIconBroken:C,markIconFailed:w,openMenuKey:T,menuTriggerEl:E,toggleOpenMenu:te,closeOpenMenu:D,onDocumentMouseDown:ne,openInFileManager:O,confirmRemove:k,get $t(){return X},get Delete(){return ae},get FolderOpened(){return _e},get MoreFilled(){return g},SvgIcon:Ee,ProjectOpenMenuList:bt,get relativeTimeFromIso(){return vt}};return Object.defineProperty(re,"__isScriptSetup",{enumerable:!1,value:!0}),re}});R(),c(),W();var qr={class:`proj`},Jr={class:`proj__head`},Yr={class:`proj__title`},Xr=[`aria-label`,`title`],Zr={class:`proj__toggles`},Qr=[`aria-pressed`],$r={key:0,class:`proj__toggle-check`,viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},ei=[`aria-pressed`],ti={key:0,class:`proj__toggle-check`,viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},ni=[`placeholder`,`aria-label`],ri={key:0,class:`proj__search-meta`},ii=[`title`,`aria-label`],ai={class:`proj__list`},oi=[`title`],si={class:`proj-item__body`},ci={class:`proj-item__icon-slot`},li={class:`proj-item__row1`},ui={class:`proj-item__name`},di={key:0,class:`proj-item__running`,"aria-hidden":`true`},fi={class:`proj-item__num`},pi={key:0,class:`proj-item__row2`},mi={class:`proj-item__running-text`},hi=[`title`],gi={class:`proj-item__progress-text`},_i=[`title`,`onClick`,`onKeydown`],vi={class:`proj-item__body`},yi={class:`proj-item__icon-slot`},bi=[`src`,`onError`],xi={class:`proj-item__row1`},Si={class:`proj-item__name`},Ci={class:`proj-item__signals`},wi={key:0,class:`proj-item__running`,"aria-hidden":`true`},Ti={key:1,class:`proj-item__badge`},Ei={class:`proj-item__row2`},Di={key:0,class:`proj-chip proj-chip--missing`},Oi={key:0,class:`proj-item__branch`},ki={class:`proj-item__branch-name`},Ai={key:1,class:`proj-chip proj-chip--ahead`},ji={key:2,class:`proj-chip proj-chip--behind`},Mi={key:3,class:`proj-chip proj-chip--dirty`},Ni={class:`proj-item__time`},Pi={key:0,class:`proj-item__row3`},Fi={class:`proj-item__progress-text`},Ii={class:`proj-item__actions`},Li=[`title`,`aria-label`,`onClick`],Ri=[`title`,`aria-label`,`onClick`],zi=[`title`,`aria-label`,`aria-expanded`,`onClick`],Bi={key:0,class:`proj-empty`},Vi={class:`proj-empty__title`},Hi={class:`proj-empty__hint`},Ui={key:1,class:`proj-empty`},Wi={class:`proj-empty__title`};function Gi(t,n,i,a,o,s){let c=O,u=l;return K(),S(`section`,qr,[x(`header`,Jr,[x(`h3`,Yr,E(a.$t(`@WORKBENCH:项目列表`)),1),J(` 过滤入口(2026-10-16 用户要求):漏斗图标 + 点击展开下拉,
27
+ 会留一堆孤儿 job)。后端 DELETE 路由也加了同样的 live-job 守卫兜底 `),a.taskIsRunning(r)?J(`v-if`,!0):(K(),S(`button`,{key:0,class:`wb-task-item__del`,onClick:N(e=>a.emit(`delete-task`,r),[`stop`]),onKeydown:n[2]||=N(()=>{},[`stop`]),title:a.$t(`@WORKBENCH:删除`),"aria-label":a.$t(`@WORKBENCH:删除`)},[e(c,null,{default:L(()=>[e(a.Close)]),_:1})],40,Rr))])],42,Mr))),128))]))]))),128)),i.tasks.length===0?(K(),S(`li`,zr,[x(`div`,Br,[e(c,null,{default:L(()=>[e(a.DocumentAdd)]),_:1})]),x(`div`,Vr,D(a.$t(`@WORKBENCH:暂无任务`)),1),x(`div`,Hr,D(a.$t(`@WORKBENCH:点击上方按钮新建`)),1),x(`div`,Ur,[e(u,{type:`primary`,size:`small`,icon:a.Plus,loading:i.creatingTask,onClick:n[3]||=e=>a.emit(`create-task`)},{default:L(()=>[z(D(a.$t(`@WORKBENCH:新建任务`)),1)]),_:1},8,[`icon`,`loading`])])])):J(`v-if`,!0)],2)])])}var Gr=Z(wr,[[`render`,Wr],[`__scopeId`,`data-v-458e9455`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchSidebar.vue`]]);c(),V();var Kr=f({__name:`WorkbenchProjectPanel`,props:{projects:{type:Array,required:!0},selectedKey:{type:String,required:!0},loading:{type:Boolean,required:!0}},emits:[`select`,`remove`],setup(e,{expose:n,emit:r}){n();let i=e,a=r,s=Y(()=>[...i.projects].sort((e,t)=>{if(e.stats.runningJobs>0!=t.stats.runningJobs>0)return e.stats.runningJobs>0?-1:1;let n=e.stats.lastActiveAt||``,r=t.stats.lastActiveAt||``;return n===r?e.name.localeCompare(t.name):r.localeCompare(n)})),c=P(``),l=P(!1),u=P(!1),d=Y(()=>!!c.value.trim()||l.value||u.value),f=Y(()=>l.value||u.value),p=Y(()=>{let e=c.value.trim().toLowerCase();return s.value.filter(t=>l.value&&t.stats.total===0||u.value&&t.git&&t.git.isGitRepo===!1?!1:!e||t.name.toLowerCase().includes(e)||t.path.toLowerCase().includes(e))});function m(){c.value=``,l.value=!1,u.value=!1}let h=P(!1),_=P(null);function v(){h.value=!h.value,h.value&&t(()=>_.value?.focus())}function y(){c.value.trim()||(h.value=!1)}let b=Y(()=>i.projects.reduce((e,t)=>({running:e.running+t.stats.runningJobs,done:e.done+t.stats.done,total:e.total+t.stats.total}),{running:0,done:0,total:0}));function x(e){return e.git?e.git.isGitRepo===null?X(`@WORKBENCH:未知`):e.git.isGitRepo?e.git.detached?X(`@WORKBENCH:游离 HEAD`):e.git.branch||X(`@WORKBENCH:未知`):``:``}function S(e){return!!(e.git&&e.git.isGitRepo&&(e.git.detached||e.git.branch))}let{isIconBroken:C,markIconFailed:T}=Ie(),E=P(null),D=P(null);function ee(e,t){if(E.value===e.key){E.value=null;return}D.value=t.currentTarget,E.value=e.key}function O(){E.value=null}function te(e){if(!E.value)return;let t=e.target;if(t&&!D.value?.contains(t)){for(let e of Array.from(document.querySelectorAll(`.proj-open-menu`)))if(e.contains(t))return;E.value=null}}o(()=>document.addEventListener(`mousedown`,te,!0)),w(()=>document.removeEventListener(`mousedown`,te,!0));async function ne(e){O();let t=await Be(e.path);t.success?I.success(t.message||X(`@WORKBENCH:已在文件管理器中打开文件夹`)):I.error(t.error||X(`@WORKBENCH:打开文件夹失败`))}async function k(e){let t=e.name||e.path,n=e.stats.total>0?X(`@WORKBENCH:移除项目「{name}」?会从常用目录和项目列表中去掉它。该项目的 {n} 条任务不会被删除,仍可在「全部项目」下查看。`,{name:t,n:e.stats.total}):X(`@WORKBENCH:移除项目「{name}」?会从常用目录和项目列表中去掉它。`,{name:t});try{await fe.confirm(n,X(`@WORKBENCH:移除项目`),{confirmButtonText:X(`@WORKBENCH:移除`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}a(`remove`,e)}let re={props:i,emit:a,ordered:s,query:c,onlyWithTasks:l,hideNonGit:u,filtering:d,filtersActive:f,visible:p,clearFilters:m,searchOpen:h,searchInputRef:_,toggleSearch:v,onSearchBlur:y,totals:b,gitLine:x,hasBranchIcon:S,isIconBroken:C,markIconFailed:T,openMenuKey:E,menuTriggerEl:D,toggleOpenMenu:ee,closeOpenMenu:O,onDocumentMouseDown:te,openInFileManager:ne,confirmRemove:k,get $t(){return X},get Delete(){return ae},get FolderOpened(){return _e},get MoreFilled(){return g},SvgIcon:Ee,ProjectOpenMenuList:bt,get relativeTimeFromIso(){return vt}};return Object.defineProperty(re,"__isScriptSetup",{enumerable:!1,value:!0}),re}});R(),c(),W();var qr={class:`proj`},Jr={class:`proj__head`},Yr={class:`proj__title`},Xr=[`aria-label`,`title`],Zr={class:`proj__toggles`},Qr=[`aria-pressed`],$r={key:0,class:`proj__toggle-check`,viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},ei=[`aria-pressed`],ti={key:0,class:`proj__toggle-check`,viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},ni=[`placeholder`,`aria-label`],ri={key:0,class:`proj__search-meta`},ii=[`title`,`aria-label`],ai={class:`proj__list`},oi=[`title`],si={class:`proj-item__body`},ci={class:`proj-item__icon-slot`},li={class:`proj-item__row1`},ui={class:`proj-item__name`},di={key:0,class:`proj-item__running`,"aria-hidden":`true`},fi={class:`proj-item__num`},pi={key:0,class:`proj-item__row2`},mi={class:`proj-item__running-text`},hi=[`title`],gi={class:`proj-item__progress-text`},_i=[`title`,`onClick`,`onKeydown`],vi={class:`proj-item__body`},yi={class:`proj-item__icon-slot`},bi=[`src`,`onError`],xi={class:`proj-item__row1`},Si={class:`proj-item__name`},Ci={class:`proj-item__signals`},wi={key:0,class:`proj-item__running`,"aria-hidden":`true`},Ti={key:1,class:`proj-item__badge`},Ei={class:`proj-item__row2`},Di={key:0,class:`proj-chip proj-chip--missing`},Oi={key:0,class:`proj-item__branch`},ki={class:`proj-item__branch-name`},Ai={key:1,class:`proj-chip proj-chip--ahead`},ji={key:2,class:`proj-chip proj-chip--behind`},Mi={key:3,class:`proj-chip proj-chip--dirty`},Ni={class:`proj-item__time`},Pi={key:0,class:`proj-item__row3`},Fi={class:`proj-item__progress-text`},Ii={class:`proj-item__actions`},Li=[`title`,`aria-label`,`onClick`],Ri=[`title`,`aria-label`,`onClick`],zi=[`title`,`aria-label`,`aria-expanded`,`onClick`],Bi={key:0,class:`proj-empty`},Vi={class:`proj-empty__title`},Hi={class:`proj-empty__hint`},Ui={key:1,class:`proj-empty`},Wi={class:`proj-empty__title`};function Gi(t,n,i,a,o,s){let c=ne,u=l;return K(),S(`section`,qr,[x(`header`,Jr,[x(`h3`,Yr,D(a.$t(`@WORKBENCH:项目列表`)),1),J(` 过滤入口(2026-10-16 用户要求):漏斗图标 + 点击展开下拉,
28
28
  原来的「只看有任务 / 隐藏非 Git」两个开关从卡片下方那行搬进下拉 ——
29
29
  那一行只剩两个按钮纯占位。开关收进下拉后靠漏斗图标的 is-on 变色提示
30
- "有筛选在生效"(下拉藏了状态,入口必须自己会说话)。 `),i.projects.length>0?(K(),r(c,{key:0,trigger:`click`,placement:`bottom-end`,width:168,"show-arrow":!1,offset:6,teleported:!0,"popper-class":`proj-filter-popper`},{reference:L(()=>[x(`button`,{type:`button`,class:w([`proj__filter-btn`,{"is-on":a.filtersActive}]),"aria-label":a.$t(`@WORKBENCH:筛选项目`),title:a.$t(`@WORKBENCH:筛选项目`)},[J(` filter.svg(Tabler icons,MIT):漏斗 = 过滤 `),n[8]||=x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},[x(`path`,{d:`M4 4h16v2.172a2 2 0 0 1-.586 1.414l-4.414 4.414v7l-6 2v-8.5l-4.48-4.928a2 2 0 0 1-.52-1.345v-2.227`})],-1)],10,Xr)]),default:L(()=>[x(`div`,Zr,[x(`button`,{type:`button`,class:w([`proj__toggle`,{"is-on":a.onlyWithTasks}]),"aria-pressed":a.onlyWithTasks,onClick:n[0]||=e=>a.onlyWithTasks=!a.onlyWithTasks},[x(`span`,null,E(a.$t(`@WORKBENCH:只看有任务`)),1),J(` check.svg(Tabler icons,MIT):选中打勾 `),a.onlyWithTasks?(K(),S(`svg`,$r,[...n[9]||=[x(`path`,{d:`M5 12l5 5l10-10`},null,-1)]])):J(`v-if`,!0)],10,Qr),x(`button`,{type:`button`,class:w([`proj__toggle`,{"is-on":a.hideNonGit}]),"aria-pressed":a.hideNonGit,onClick:n[1]||=e=>a.hideNonGit=!a.hideNonGit},[x(`span`,null,E(a.$t(`@WORKBENCH:隐藏非 Git`)),1),a.hideNonGit?(K(),S(`svg`,ti,[...n[10]||=[x(`path`,{d:`M5 12l5 5l10-10`},null,-1)]])):J(`v-if`,!0)],10,ei)])]),_:1})):J(`v-if`,!0),J(` 搜索(2026-10-16 从下面的筛选条搬到这里):默认只露一枚放大镜,
30
+ "有筛选在生效"(下拉藏了状态,入口必须自己会说话)。 `),i.projects.length>0?(K(),r(c,{key:0,trigger:`click`,placement:`bottom-end`,width:168,"show-arrow":!1,offset:6,teleported:!0,"popper-class":`proj-filter-popper`},{reference:L(()=>[x(`button`,{type:`button`,class:T([`proj__filter-btn`,{"is-on":a.filtersActive}]),"aria-label":a.$t(`@WORKBENCH:筛选项目`),title:a.$t(`@WORKBENCH:筛选项目`)},[J(` filter.svg(Tabler icons,MIT):漏斗 = 过滤 `),n[8]||=x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},[x(`path`,{d:`M4 4h16v2.172a2 2 0 0 1-.586 1.414l-4.414 4.414v7l-6 2v-8.5l-4.48-4.928a2 2 0 0 1-.52-1.345v-2.227`})],-1)],10,Xr)]),default:L(()=>[x(`div`,Zr,[x(`button`,{type:`button`,class:T([`proj__toggle`,{"is-on":a.onlyWithTasks}]),"aria-pressed":a.onlyWithTasks,onClick:n[0]||=e=>a.onlyWithTasks=!a.onlyWithTasks},[x(`span`,null,D(a.$t(`@WORKBENCH:只看有任务`)),1),J(` check.svg(Tabler icons,MIT):选中打勾 `),a.onlyWithTasks?(K(),S(`svg`,$r,[...n[9]||=[x(`path`,{d:`M5 12l5 5l10-10`},null,-1)]])):J(`v-if`,!0)],10,Qr),x(`button`,{type:`button`,class:T([`proj__toggle`,{"is-on":a.hideNonGit}]),"aria-pressed":a.hideNonGit,onClick:n[1]||=e=>a.hideNonGit=!a.hideNonGit},[x(`span`,null,D(a.$t(`@WORKBENCH:隐藏非 Git`)),1),a.hideNonGit?(K(),S(`svg`,ti,[...n[10]||=[x(`path`,{d:`M5 12l5 5l10-10`},null,-1)]])):J(`v-if`,!0)],10,ei)])]),_:1})):J(`v-if`,!0),J(` 搜索(2026-10-16 从下面的筛选条搬到这里):默认只露一枚放大镜,
31
31
  点开输入框才展开。原标题右侧那枚常驻项目数(.proj__count)去掉 ——
32
32
  同一个数字顶栏、左栏「全部项目」行各还有一份;筛选中的匹配数
33
- 不跟着常驻,改成展开态下输入框右边一枚小字(.proj__search-meta)。 `),i.projects.length>0?(K(),S(`div`,{key:1,class:w([`proj__search`,{"is-open":a.searchOpen}])},[A(x(`input`,{ref:`searchInputRef`,"onUpdate:modelValue":n[2]||=e=>a.query=e,class:`proj__search-input`,type:`search`,placeholder:a.$t(`@WORKBENCH:搜索项目名称或路径`),"aria-label":a.$t(`@WORKBENCH:搜索项目名称或路径`),onKeydown:n[3]||=F(e=>a.query=``,[`esc`]),onBlur:a.onSearchBlur},null,40,ni),[[H,a.searchOpen],[G,a.query]]),J(` ⚠️ 必须带 searchOpen:只写 filtering 的话,"开关开着 + 搜索收起"时
33
+ 不跟着常驻,改成展开态下输入框右边一枚小字(.proj__search-meta)。 `),i.projects.length>0?(K(),S(`div`,{key:1,class:T([`proj__search`,{"is-open":a.searchOpen}])},[A(x(`input`,{ref:`searchInputRef`,"onUpdate:modelValue":n[2]||=e=>a.query=e,class:`proj__search-input`,type:`search`,placeholder:a.$t(`@WORKBENCH:搜索项目名称或路径`),"aria-label":a.$t(`@WORKBENCH:搜索项目名称或路径`),onKeydown:n[3]||=F(e=>a.query=``,[`esc`]),onBlur:a.onSearchBlur},null,40,ni),[[H,a.searchOpen],[G,a.query]]),J(` ⚠️ 必须带 searchOpen:只写 filtering 的话,"开关开着 + 搜索收起"时
34
34
  这枚小字会挤进 34px 的收起容器,把放大镜顶出框外(实测按出 6px)。
35
- 原设计意图就是"展开态下"才显示,这里是补上漏掉的条件。 `),a.filtering&&a.searchOpen?(K(),S(`span`,ri,E(a.visible.length)+`/`+E(i.projects.length),1)):J(`v-if`,!0),J(` mousedown.prevent:不让这一下先把输入框焦点弄丢,否则"点开 → 再点图标
35
+ 原设计意图就是"展开态下"才显示,这里是补上漏掉的条件。 `),a.filtering&&a.searchOpen?(K(),S(`span`,ri,D(a.visible.length)+`/`+D(i.projects.length),1)):J(`v-if`,!0),J(` mousedown.prevent:不让这一下先把输入框焦点弄丢,否则"点开 → 再点图标
36
36
  想收起"会变成 blur 收起 + click 又重新展开(同看板标题行那枚) `),x(`button`,{type:`button`,class:`proj__search-btn`,title:a.$t(`@WORKBENCH:搜索项目名称或路径`),"aria-label":a.$t(`@WORKBENCH:搜索项目名称或路径`),onMousedown:n[4]||=N(()=>{},[`prevent`]),onClick:a.toggleSearch},[J(` search.svg(Tabler icons,MIT)。2026-10-16 从 EP <Search/> 换成 Tabler:
37
37
  EP 图标是**实心填充**风,与左边漏斗(Tabler 描边)并排"颜色深浅不一样"
38
- (用户反馈)——同为 14px / 描边 2 后两者才是一对。 `),n[11]||=x(`svg`,{class:`proj__search-icon`,viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M3 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0`}),x(`path`,{d:`M21 21l-6 -6`})],-1)],40,ii)],2)):J(`v-if`,!0)]),x(`ul`,ai,[x(`li`,{class:w([`proj-item proj-item--all`,{"is-active":i.selectedKey===``,"is-running":a.totals.running>0,"is-complete":a.totals.total>0&&a.totals.done>=a.totals.total}]),role:`button`,tabindex:`0`,title:a.$t(`@WORKBENCH:全部项目`),onClick:n[5]||=e=>a.emit(`select`,null),onKeydown:[n[6]||=F(N(e=>a.emit(`select`,null),[`prevent`]),[`enter`]),n[7]||=F(N(e=>a.emit(`select`,null),[`prevent`]),[`space`])]},[x(`div`,si,[x(`span`,ci,[e(u,{class:`proj-item__icon`},{default:L(()=>[J(` layout-grid(Tabler icons,MIT):全部项目 = 四方格。
38
+ (用户反馈)——同为 14px / 描边 2 后两者才是一对。 `),n[11]||=x(`svg`,{class:`proj__search-icon`,viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M3 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0`}),x(`path`,{d:`M21 21l-6 -6`})],-1)],40,ii)],2)):J(`v-if`,!0)]),x(`ul`,ai,[x(`li`,{class:T([`proj-item proj-item--all`,{"is-active":i.selectedKey===``,"is-running":a.totals.running>0,"is-complete":a.totals.total>0&&a.totals.done>=a.totals.total}]),role:`button`,tabindex:`0`,title:a.$t(`@WORKBENCH:全部项目`),onClick:n[5]||=e=>a.emit(`select`,null),onKeydown:[n[6]||=F(N(e=>a.emit(`select`,null),[`prevent`]),[`enter`]),n[7]||=F(N(e=>a.emit(`select`,null),[`prevent`]),[`space`])]},[x(`div`,si,[x(`span`,ci,[e(u,{class:`proj-item__icon`},{default:L(()=>[J(` layout-grid(Tabler icons,MIT):全部项目 = 四方格。
39
39
  2026-10-16 从 EP <Grid/> 换成 Tabler —— 与回退文件夹、行内其余
40
- 图标同族;EP 实心填充与 Tabler 描边混排会有"色差感"。 `),n[12]||=x(`svg`,{viewBox:`0 0 24 24`,width:`20`,height:`20`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M4 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`}),x(`path`,{d:`M14 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`}),x(`path`,{d:`M4 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`}),x(`path`,{d:`M14 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`})],-1)]),_:1})]),x(`div`,li,[x(`span`,ui,E(a.$t(`@WORKBENCH:全部项目`)),1),a.totals.running>0?(K(),S(`span`,di)):J(`v-if`,!0),x(`span`,fi,E(i.projects.length),1)]),J(` 第二行只在真有内容时说。原来这里写「{n} 个项目」,而同一个 28 就在上面
40
+ 图标同族;EP 实心填充与 Tabler 描边混排会有"色差感"。 `),n[12]||=x(`svg`,{viewBox:`0 0 24 24`,width:`20`,height:`20`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M4 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`}),x(`path`,{d:`M14 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`}),x(`path`,{d:`M4 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`}),x(`path`,{d:`M14 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`})],-1)]),_:1})]),x(`div`,li,[x(`span`,ui,D(a.$t(`@WORKBENCH:全部项目`)),1),a.totals.running>0?(K(),S(`span`,di)):J(`v-if`,!0),x(`span`,fi,D(i.projects.length),1)]),J(` 第二行只在真有内容时说。原来这里写「{n} 个项目」,而同一个 28 就在上面
41
41
  那枚 proj-item__num chip 里、面板标题和顶栏也各写了一遍 —— 一屏四个 28。
42
- 真正只有这一行能说的是"有几个在跑"。 `),a.totals.running>0?(K(),S(`div`,pi,[x(`span`,mi,E(a.$t(`@WORKBENCH:{n} 个执行中`,{n:a.totals.running})),1)])):J(`v-if`,!0),J(` 只留数字不给进度条(用户 2026-10-13:数字有用,彩条占地方)。
42
+ 真正只有这一行能说的是"有几个在跑"。 `),a.totals.running>0?(K(),S(`div`,pi,[x(`span`,mi,D(a.$t(`@WORKBENCH:{n} 个执行中`,{n:a.totals.running})),1)])):J(`v-if`,!0),J(` 只留数字不给进度条(用户 2026-10-13:数字有用,彩条占地方)。
43
43
  title 交代口径:这里只加列表里这些项目的任务,与顶栏「全部任务」不等
44
- (实测差 10 条:9 条属于一个已从列表移除的项目 + 1 条属于容器目录)。 `),a.totals.total>0?(K(),S(`div`,{key:1,class:`proj-item__row3`,title:a.$t(`@WORKBENCH:只统计项目列表里这些项目名下的任务`)},[x(`span`,gi,E(a.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:a.totals.done,total:a.totals.total})),1)],8,hi)):J(`v-if`,!0)])],42,oi),(K(!0),S(k,null,D(a.visible,t=>(K(),S(`li`,{key:t.key,class:w([`proj-item`,{"is-active":t.key===i.selectedKey,"is-running":t.stats.runningJobs>0,"is-complete":t.stats.total>0&&t.stats.done>=t.stats.total&&t.stats.runningJobs===0,"is-missing":t.exists===!1}]),role:`button`,tabindex:`0`,title:t.path,onClick:e=>a.emit(`select`,t),onKeydown:[F(N(e=>a.emit(`select`,t),[`self`,`prevent`]),[`enter`]),F(N(e=>a.emit(`select`,t),[`self`,`prevent`]),[`space`])]},[x(`div`,vi,[J(` 图标位跨 row1 + row2(见 .proj-item__icon-slot):项目自己的 favicon 是
44
+ (实测差 10 条:9 条属于一个已从列表移除的项目 + 1 条属于容器目录)。 `),a.totals.total>0?(K(),S(`div`,{key:1,class:`proj-item__row3`,title:a.$t(`@WORKBENCH:只统计项目列表里这些项目名下的任务`)},[x(`span`,gi,D(a.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:a.totals.done,total:a.totals.total})),1)],8,hi)):J(`v-if`,!0)])],42,oi),(K(!0),S(k,null,O(a.visible,t=>(K(),S(`li`,{key:t.key,class:T([`proj-item`,{"is-active":t.key===i.selectedKey,"is-running":t.stats.runningJobs>0,"is-complete":t.stats.total>0&&t.stats.done>=t.stats.total&&t.stats.runningJobs===0,"is-missing":t.exists===!1}]),role:`button`,tabindex:`0`,title:t.path,onClick:e=>a.emit(`select`,t),onKeydown:[F(N(e=>a.emit(`select`,t),[`self`,`prevent`]),[`enter`]),F(N(e=>a.emit(`select`,t),[`self`,`prevent`]),[`space`])]},[x(`div`,vi,[J(` 图标位跨 row1 + row2(见 .proj-item__icon-slot):项目自己的 favicon 是
45
45
  32px 的方块,占两行文字的高度;没有 / 加载失败就退回一枚文件夹字形。
46
46
  失败要记一笔:服务端重启过、或图标文件被删掉时,不记的话每次重渲染都会
47
47
  再发一次注定失败的请求,行上还一直挂着个破图。 `),x(`span`,yi,[t.iconUrl&&!a.isIconBroken(t.iconUrl)?(K(),S(`img`,{key:0,class:`proj-item__icon proj-item__icon--img`,src:t.iconUrl,alt:``,onError:e=>a.markIconFailed(t.iconUrl)},null,40,bi)):(K(),r(u,{key:1,class:`proj-item__icon proj-item__icon--folder`,"aria-hidden":`true`},{default:L(()=>[J(` folder-filled.svg(Tabler icons,MIT):回退 = **直接一枚主色实心文件夹**。
48
48
  2026-10-16 晚用户连提两轮"再大一点":不要"外框方块 + 小文件夹"两层套,
49
49
  字形一路调大 20 → 24 → 32(顶满槽;字形自带边距,实际形宽 ≈24px)。
50
- 承载的 el-icon 仍是 32px 的透明槽(几何契约不变)。 `),n[13]||=x(`svg`,{viewBox:`0 0 24 24`,width:`32`,height:`32`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[x(`path`,{d:`M9 3a1 1 0 0 1 .608 .206l.1 .087l2.706 2.707h6.586a3 3 0 0 1 2.995 2.824l.005 .176v8a3 3 0 0 1 -2.824 2.995l-.176 .005h-14a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-11a3 3 0 0 1 2.824 -2.995l.176 -.005h4z`})],-1)]),_:1}))]),x(`div`,xi,[x(`span`,Si,E(t.name),1),J(` 运行中 / 当前 这两个信号与 hover 才出现的操作按钮锚在同一个右端点:
51
- hover 时整组淡出让位给按钮,而不是让图标压在徽标上 `),x(`span`,Ci,[t.stats.runningJobs>0?(K(),S(`span`,wi)):J(`v-if`,!0),t.isCurrent?(K(),S(`span`,Ti,E(a.$t(`@WORKBENCH:当前`)),1)):J(`v-if`,!0)])]),x(`div`,Ei,[t.exists===!1?(K(),S(`span`,Di,E(a.$t(`@WORKBENCH:目录不存在`)),1)):(K(),S(k,{key:1},[J(` gitLine 为空即"不是 Git 仓库":不给文字,也不给图标 `),a.gitLine(t)?(K(),S(`span`,Oi,[a.hasBranchIcon(t)?(K(),r(a.SvgIcon,{key:0,"icon-class":`git-branch`,"class-name":`proj-item__branch-icon`})):J(`v-if`,!0),x(`span`,ki,E(a.gitLine(t)),1)])):J(`v-if`,!0),t.git&&t.git.ahead>0?(K(),S(`span`,Ai,`↑`+E(t.git.ahead),1)):J(`v-if`,!0),t.git&&t.git.behind>0?(K(),S(`span`,ji,`↓`+E(t.git.behind),1)):J(`v-if`,!0),t.git&&t.git.changed>0?(K(),S(`span`,Mi,`●`+E(t.git.changed),1)):J(`v-if`,!0)],64)),x(`span`,Ni,E(a.relativeTimeFromIso(t.stats.lastActiveAt)),1)]),J(` 同上:这个项目一个任务都没有就不给进度行 `),t.stats.total>0?(K(),S(`div`,Pi,[x(`span`,Fi,E(a.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:t.stats.done,total:t.stats.total})),1)])):J(`v-if`,!0)]),J(` 打开动作:与行主体平级,绝对定位锚在 row1 右端(不占位,否则「当前」徽标
50
+ 承载的 el-icon 仍是 32px 的透明槽(几何契约不变)。 `),n[13]||=x(`svg`,{viewBox:`0 0 24 24`,width:`32`,height:`32`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[x(`path`,{d:`M9 3a1 1 0 0 1 .608 .206l.1 .087l2.706 2.707h6.586a3 3 0 0 1 2.995 2.824l.005 .176v8a3 3 0 0 1 -2.824 2.995l-.176 .005h-14a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-11a3 3 0 0 1 2.824 -2.995l.176 -.005h4z`})],-1)]),_:1}))]),x(`div`,xi,[x(`span`,Si,D(t.name),1),J(` 运行中 / 当前 这两个信号与 hover 才出现的操作按钮锚在同一个右端点:
51
+ hover 时整组淡出让位给按钮,而不是让图标压在徽标上 `),x(`span`,Ci,[t.stats.runningJobs>0?(K(),S(`span`,wi)):J(`v-if`,!0),t.isCurrent?(K(),S(`span`,Ti,D(a.$t(`@WORKBENCH:当前`)),1)):J(`v-if`,!0)])]),x(`div`,Ei,[t.exists===!1?(K(),S(`span`,Di,D(a.$t(`@WORKBENCH:目录不存在`)),1)):(K(),S(k,{key:1},[J(` gitLine 为空即"不是 Git 仓库":不给文字,也不给图标 `),a.gitLine(t)?(K(),S(`span`,Oi,[a.hasBranchIcon(t)?(K(),r(a.SvgIcon,{key:0,"icon-class":`git-branch`,"class-name":`proj-item__branch-icon`})):J(`v-if`,!0),x(`span`,ki,D(a.gitLine(t)),1)])):J(`v-if`,!0),t.git&&t.git.ahead>0?(K(),S(`span`,Ai,`↑`+D(t.git.ahead),1)):J(`v-if`,!0),t.git&&t.git.behind>0?(K(),S(`span`,ji,`↓`+D(t.git.behind),1)):J(`v-if`,!0),t.git&&t.git.changed>0?(K(),S(`span`,Mi,`●`+D(t.git.changed),1)):J(`v-if`,!0)],64)),x(`span`,Ni,D(a.relativeTimeFromIso(t.stats.lastActiveAt)),1)]),J(` 同上:这个项目一个任务都没有就不给进度行 `),t.stats.total>0?(K(),S(`div`,Pi,[x(`span`,Fi,D(a.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:t.stats.done,total:t.stats.total})),1)])):J(`v-if`,!0)]),J(` 打开动作:与行主体平级,绝对定位锚在 row1 右端(不占位,否则「当前」徽标
52
52
  永远离右边缘一条);.stop 阻止冒泡到行的选中逻辑。目录都不存在时**一个打开
53
53
  动作都不给** —— 点了只会弹一个「无法打开目录」的报错 —— 只留一颗「从清单移除」:
54
54
  那一行存在的唯一理由就是提醒这里有个没了的目录,能做的也只有把它清掉。
@@ -57,15 +57,15 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
57
57
  而项目名被挤成省略号比多点一次更难受。
58
58
  ⚠️ 行上的 keydown 必须带 .self:事件从按钮冒泡上来,不带 .self 时
59
59
  焦点在按钮上按回车会「选中该行 + preventDefault 掉按钮自己的激活」,
60
- 键盘用户反而打不开文件夹。 `),x(`div`,Ii,[t.exists===!1?(K(),S(`button`,{key:0,type:`button`,class:`proj-item__action proj-item__action--danger`,title:a.$t(`@WORKBENCH:从清单移除`),"aria-label":`${a.$t(`@WORKBENCH:从清单移除`)} ${t.name}`,onClick:N(e=>a.confirmRemove(t),[`stop`])},[e(u,{"aria-hidden":`true`},{default:L(()=>[e(a.Delete)]),_:1})],8,Li)):(K(),S(`button`,{key:1,type:`button`,class:`proj-item__action`,title:a.$t(`@WORKBENCH:打开文件夹`),"aria-label":`${a.$t(`@WORKBENCH:打开文件夹`)} ${t.name}`,onClick:N(e=>a.openInFileManager(t),[`stop`])},[e(u,{"aria-hidden":`true`},{default:L(()=>[e(a.FolderOpened)]),_:1})],8,Ri)),t.exists===!1?J(`v-if`,!0):(K(),r(c,{key:2,visible:a.openMenuKey===t.key,trigger:`manual`,placement:`right-start`,width:272,"show-arrow":!1,offset:6,"popper-class":`proj-open-menu`},{reference:L(()=>[x(`button`,{type:`button`,class:w([`proj-item__action`,{"is-open":a.openMenuKey===t.key}]),title:a.$t(`@WORKBENCH:打开方式`),"aria-label":`${a.$t(`@WORKBENCH:打开方式`)} ${t.name}`,"aria-expanded":a.openMenuKey===t.key,"aria-haspopup":`menu`,onClick:N(e=>a.toggleOpenMenu(t,e),[`stop`])},[e(u,{"aria-hidden":`true`},{default:L(()=>[e(a.MoreFilled)]),_:1})],10,zi)]),default:L(()=>[a.openMenuKey===t.key?(K(),r(a.ProjectOpenMenuList,{key:0,path:t.path,name:t.name,onDone:a.closeOpenMenu},null,8,[`path`,`name`])):J(`v-if`,!0)]),_:2},1032,[`visible`]))])],42,_i))),128)),!i.loading&&i.projects.length===0?(K(),S(`li`,Bi,[x(`p`,Vi,E(a.$t(`@WORKBENCH:尚无项目`)),1),x(`p`,Hi,E(a.$t(`@WORKBENCH:常用目录与建过任务的目录都会出现在这里`)),1)])):J(`v-if`,!0),J(` 有项目、只是被筛没了:这必须说出来。
60
+ 键盘用户反而打不开文件夹。 `),x(`div`,Ii,[t.exists===!1?(K(),S(`button`,{key:0,type:`button`,class:`proj-item__action proj-item__action--danger`,title:a.$t(`@WORKBENCH:从清单移除`),"aria-label":`${a.$t(`@WORKBENCH:从清单移除`)} ${t.name}`,onClick:N(e=>a.confirmRemove(t),[`stop`])},[e(u,{"aria-hidden":`true`},{default:L(()=>[e(a.Delete)]),_:1})],8,Li)):(K(),S(`button`,{key:1,type:`button`,class:`proj-item__action`,title:a.$t(`@WORKBENCH:打开文件夹`),"aria-label":`${a.$t(`@WORKBENCH:打开文件夹`)} ${t.name}`,onClick:N(e=>a.openInFileManager(t),[`stop`])},[e(u,{"aria-hidden":`true`},{default:L(()=>[e(a.FolderOpened)]),_:1})],8,Ri)),t.exists===!1?J(`v-if`,!0):(K(),r(c,{key:2,visible:a.openMenuKey===t.key,trigger:`manual`,placement:`right-start`,width:272,"show-arrow":!1,offset:6,"popper-class":`proj-open-menu`},{reference:L(()=>[x(`button`,{type:`button`,class:T([`proj-item__action`,{"is-open":a.openMenuKey===t.key}]),title:a.$t(`@WORKBENCH:打开方式`),"aria-label":`${a.$t(`@WORKBENCH:打开方式`)} ${t.name}`,"aria-expanded":a.openMenuKey===t.key,"aria-haspopup":`menu`,onClick:N(e=>a.toggleOpenMenu(t,e),[`stop`])},[e(u,{"aria-hidden":`true`},{default:L(()=>[e(a.MoreFilled)]),_:1})],10,zi)]),default:L(()=>[a.openMenuKey===t.key?(K(),r(a.ProjectOpenMenuList,{key:0,path:t.path,name:t.name,onDone:a.closeOpenMenu},null,8,[`path`,`name`])):J(`v-if`,!0)]),_:2},1032,[`visible`]))])],42,_i))),128)),!i.loading&&i.projects.length===0?(K(),S(`li`,Bi,[x(`p`,Vi,D(a.$t(`@WORKBENCH:尚无项目`)),1),x(`p`,Hi,D(a.$t(`@WORKBENCH:常用目录与建过任务的目录都会出现在这里`)),1)])):J(`v-if`,!0),J(` 有项目、只是被筛没了:这必须说出来。
61
61
  空着会让人以为项目列表坏了,而"没有匹配"和"一个项目都没有"是两件事。
62
62
  刻意写成两个互斥的 v-if(而不是 v-else-if):条件里带上了 projects.length,
63
- 读代码时不用回头找上一段才敢确定它们不重叠。 `),!i.loading&&i.projects.length>0&&a.visible.length===0?(K(),S(`li`,Ui,[x(`p`,Wi,E(a.$t(`@WORKBENCH:没有匹配的项目`)),1),x(`button`,{type:`button`,class:`proj-empty__clear`,onClick:a.clearFilters},E(a.$t(`@WORKBENCH:清除筛选`)),1)])):J(`v-if`,!0)])])}var Ki=Z(Kr,[[`render`,Gi],[`__scopeId`,`data-v-de1af726`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchProjectPanel.vue`]]),qi=[140,170,200,230,260,290,320,350];function Ji(e){return(e||``).replace(/\\/g,`/`).trim().toLowerCase()}function Yi(e){let t=Ji(e),n=2166136261;for(let e=0;e<t.length;e++)n^=t.charCodeAt(e),n=Math.imul(n,16777619);return n^=n>>>16,n=Math.imul(n,2246822507),n^=n>>>13,n=Math.imul(n,3266489909),n^=n>>>16,qi[(n>>>0)%qi.length]}function Xi(e){return{"--tag-hue":String(Yi(e))}}c(),V();var Zi=30,Qi=f({__name:`WorkbenchKanban`,props:{tasks:{type:Array,required:!0},projectLabels:{type:Object,required:!0},taskPercents:{type:Object,required:!1},showProjectLabel:{type:Boolean,required:!0},view:{type:String,required:!0},search:{type:String,required:!0},openedTaskId:{type:[String,null],required:!0}},emits:[`open-task`,`run-task`,`stop-task`,`complete-task`,`reopen-task`,`delete-task`,`create-task`,`update:view`,`update:search`],setup(e,{expose:n,emit:r}){n();let i=e,a=r,s=[{key:`todo`,labelKey:`@WORKBENCH:待处理`},{key:`doing`,labelKey:`@WORKBENCH:进行中`},{key:`done`,labelKey:`@WORKBENCH:已完成`}],c=Y(()=>{let e=i.search.trim().toLowerCase();return i.tasks.filter(t=>!e||(t.title||``).toLowerCase().includes(e)||(t.desc||``).toLowerCase().includes(e))}),l=P(Zi);U(()=>i.search,()=>{l.value=Zi});let u=Y(()=>{let e=s.map(e=>{let t=e.key===`done`?c.value.filter(t=>t.column===e.key).sort(m):c.value.filter(t=>t.column===e.key);return{...e,all:t}}),t=e.some(e=>e.all.length>0);return e.map(e=>({key:e.key,labelKey:e.labelKey,total:e.all.length,hidden:e.key===`done`?Math.max(0,e.all.length-l.value):0,tasks:e.key===`done`?e.all.slice(0,l.value):e.all,collapsed:t&&e.all.length===0&&e.key!==`todo`}))}),d=Y(()=>({gridTemplateColumns:u.value.map(e=>e.collapsed?`minmax(0, 0fr)`:`minmax(0, 1fr)`).join(` `)})),f=P(!1);o(()=>{requestAnimationFrame(()=>requestAnimationFrame(()=>{f.value=!0}))}),U(()=>i.openedTaskId,e=>{e&&t(()=>{document.querySelector(`.kb-card[data-task-id="${e}"]`)?.scrollIntoView({block:`nearest`,inline:`nearest`})})});function p(e){return Jn(e)}function m(e,t){return p(t).localeCompare(p(e))}function h(e){return Yn(e)}function g(e){return Xn(e)}function _(e){return er(e)}function v(e){let t=(e.autoCompleted?.reason||``).trim(),n=X(`@WORKBENCH:静默超时后由 AI 核对,判定这条任务已经完成`);return t?`${n}\n${t}`:n}let y=Y(()=>[...c.value].sort((e,t)=>h(t).localeCompare(h(e))));function b(e){let t=(e.title||``).trim();if(t)return t;let n=(e.desc||``).replace(/\s+/g,` `).trim();return(/^[a-zA-Z]:[\\/]/.test(n)||n.startsWith(`\\\\`))&&n.split(/[\\/]/).filter(Boolean).pop()||n}function x(e){return i.projectLabels[e.projectPath]||``}function S(e){return e.lastJobStatus===`error`}function C(e){return e.live?.agent||e.lastJobAgent||``}function ee(e){if(!e.live)return null;let t=i.taskPercents?.[e.id];return typeof t==`number`?t:null}function w(e){let t=e.live;if(!t)return``;let n=Qn(e),r=t.lastLine||t.lastThought||t.lastTool;return r?`${n} · ${r}`:n}function T(e){return Array.isArray(e.images)?e.images:[]}let E=P(new Set);function te(e){E.value=new Set(E.value).add(e)}function D(e){let t=T(e);return E.value.size===0?t:t.filter(e=>!E.value.has(e.id))}function ne(e){return`/api/workbench/attachments/${e}/raw`}let O=P(null);function k(e,t=0){let n=D(e);n.length!==0&&(O.value={urls:n.map(e=>ne(e.id)),index:t})}function re(){O.value=null}function A(e){return e.originalName?`${X(`@WORKBENCH:查看图片`)} · ${e.originalName}`:X(`@WORKBENCH:查看图片`)}let j={props:i,emit:a,COLUMNS:s,filtered:c,DONE_PAGE:Zi,doneLimit:l,columns:u,columnsStyle:d,animateCollapse:f,doneAt:p,byDoneAtDesc:m,cardTime:h,cardDuration:g,cardTimeTitle:_,autoDoneTitle:v,listRows:y,cardTitle:b,projectLabel:x,hasError:S,cardAgent:C,cardPercent:ee,liveSummary:w,cardImages:T,brokenCoverIds:E,onCoverError:te,coverImages:D,imageRawUrl:ne,imageViewer:O,openImages:k,closeImages:re,coverTitle:A,get $t(){return X},TaskExecutorIcon:Fe,get taskExecutorName(){return Oe},get projectTagStyle(){return Xi},get formatDurationMs(){return _t},get relativeTimeFromIso(){return vt},get taskLiveText(){return Qn},get taskSpentText(){return Zn},get REPORT_PERCENT_HINT_KEY(){return Ve},get REPORT_PERCENT_LABEL_KEY(){return We},get reportSilentMs(){return Ge}};return Object.defineProperty(j,"__isScriptSetup",{enumerable:!1,value:!0}),j}});c(),R(),W();var $i={class:`kb`},ea=[`aria-hidden`],ta={class:`kb-col__head`},na={class:`kb-col__title`},ra={class:`kb-col__count`},ia={class:`kb-col__list`},aa=[`data-task-id`,`aria-current`,`onClick`,`onKeydown`],oa=[`title`,`aria-label`,`onClick`],sa=[`src`,`alt`,`onError`],ca={key:0,class:`kb-card__cover-more`,"aria-hidden":`true`},la={class:`kb-card__row1`},ua=[`title`],da=[`title`],fa={class:`kb-card__time`},pa=[`title`],ma=[`title`],ha={key:3,class:`kb-card__live`},ga={class:`kb-card__live-meta`},_a=[`title`],va=[`title`],ya={key:2,class:`kb-card__live-pid`},ba={key:3,class:`kb-card__live-silent`},xa=[`title`],Sa=[`aria-valuenow`,`aria-label`],Ca={class:`kb-card__live-pct`},wa={class:`kb-card__live-pct-tag`},Ta=[`title`],Ea=[`title`],Da={class:`kb-card__live-tag`},Oa=[`title`],ka={class:`kb-card__live-tag`},Aa=[`title`],ja=[`title`],Ma={class:`kb-card__reply-text`},Na=[`title`,`onClick`],Pa={class:`kb-card__actions`},Fa=[`title`,`onClick`],Ia=[`title`,`aria-label`,`onClick`],La=[`title`,`aria-label`,`onClick`],Ra=[`title`,`aria-label`,`onClick`],za=[`title`,`aria-label`,`onClick`],Ba={key:0,class:`kb-col__add`},Va={key:1,class:`kb-col__empty`},Ha={key:2,class:`kb-col__more`},Ua={class:`kb__table-wrap`},Wa={class:`kb-table`},Ga={class:`kb-table__th`},Ka={class:`kb-table__th kb-table__th--narrow`},qa={class:`kb-table__th kb-table__th--time`},Ja=[`onClick`,`onKeydown`],Ya={class:`kb-table__td`},Xa=[`title`,`onClick`],Za={class:`kb-table__name`},Qa=[`title`],$a={key:2,class:`kb-table__live`},eo=[`title`],to=[`title`],no={key:2,class:`kb-table__live-silent`},ro={class:`kb-table__live kb-table__live--reply`},io=[`title`],ao={class:`kb-table__td`},oo={class:`kb-table__td kb-table__td--num`},so=[`title`],co={class:`kb-table__dur`},lo=[`title`],uo={key:0},fo={class:`kb-table__td kb-table__empty`,colspan:`3`};function po(t,n,i,a,o,s){let c=M;return K(),S(`div`,$i,[J(` 看板视图。
63
+ 读代码时不用回头找上一段才敢确定它们不重叠。 `),!i.loading&&i.projects.length>0&&a.visible.length===0?(K(),S(`li`,Ui,[x(`p`,Wi,D(a.$t(`@WORKBENCH:没有匹配的项目`)),1),x(`button`,{type:`button`,class:`proj-empty__clear`,onClick:a.clearFilters},D(a.$t(`@WORKBENCH:清除筛选`)),1)])):J(`v-if`,!0)])])}var Ki=Z(Kr,[[`render`,Gi],[`__scopeId`,`data-v-de1af726`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchProjectPanel.vue`]]);c(),V();var qi=f({__name:`WorkbenchTaskMoveMenu`,props:{visible:{type:Boolean,required:!0},x:{type:Number,required:!0},y:{type:Number,required:!0},task:{type:[Object,null],required:!0},projects:{type:Array,required:!0}},emits:[`move`,`close`],setup(e,{expose:n,emit:r}){n();let i=e,a=r,o=Y(()=>{let e=$(i.task?.projectPath);return i.projects.filter(t=>$(t.path)!==e)}),s=P(null),c=P({x:0,y:0});U(()=>i.visible,async e=>{if(!e)return;await t();let n=s.value;if(!n)return;let r=n.getBoundingClientRect();c.value={x:Math.min(Math.max(8,i.x),Math.max(8,window.innerWidth-r.width-8)),y:Math.min(Math.max(8,i.y),Math.max(8,window.innerHeight-r.height-8))}});function l(e){let t=s.value;t&&e.target instanceof Node&&t.contains(e.target)||a(`close`)}function u(){a(`close`)}function d(e){e.key===`Escape`&&(e.stopPropagation(),a(`close`))}U(()=>i.visible,e=>{e&&(window.addEventListener(`pointerdown`,l,!0),window.addEventListener(`scroll`,u,!0),window.addEventListener(`keydown`,d,!0))},{immediate:!0}),U(()=>i.visible,e=>{e||(window.removeEventListener(`pointerdown`,l,!0),window.removeEventListener(`scroll`,u,!0),window.removeEventListener(`keydown`,d,!0))}),w(()=>{window.removeEventListener(`pointerdown`,l,!0),window.removeEventListener(`scroll`,u,!0),window.removeEventListener(`keydown`,d,!0)});function f(e){a(`move`,e.path)}let p={props:i,emit:a,options:o,menuRef:s,pos:c,onPointerDown:l,onScroll:u,onKeydown:d,onPick:f,get $t(){return X}};return Object.defineProperty(p,"__isScriptSetup",{enumerable:!1,value:!0}),p}});R(),c(),W();var Ji={class:`kb-move-menu__head`},Yi={class:`kb-move-menu__list`},Xi=[`title`,`onClick`],Zi={class:`kb-move-menu__name`},Qi={key:0,class:`kb-move-menu__warn`},$i={key:0,class:`kb-move-menu__empty`};function ea(e,t,n,i,a,o){return K(),r(ye,{to:`body`},[n.visible&&n.task?(K(),S(`div`,{key:0,ref:`menuRef`,class:`kb-move-menu`,role:`menu`,style:u({top:i.pos.y+`px`,left:i.pos.x+`px`}),onContextmenu:t[0]||=N(()=>{},[`prevent`])},[x(`p`,Ji,D(i.$t(`@WORKBENCH:移动到其他项目`)),1),x(`div`,Yi,[(K(!0),S(k,null,O(i.options,e=>(K(),S(`button`,{key:e.key,type:`button`,class:`kb-move-menu__item`,role:`menuitem`,title:e.path,onClick:t=>i.onPick(e)},[x(`span`,Zi,D(e.name),1),e.exists===!1?(K(),S(`span`,Qi,D(i.$t(`@WORKBENCH:目录不存在`)),1)):J(`v-if`,!0)],8,Xi))),128)),i.options.length===0?(K(),S(`p`,$i,D(i.$t(`@WORKBENCH:没有其他项目`)),1)):J(`v-if`,!0)])],36)):J(`v-if`,!0)])}var ta=Z(qi,[[`render`,ea],[`__scopeId`,`data-v-c9596078`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchTaskMoveMenu.vue`]]),na=[140,170,200,230,260,290,320,350];function ra(e){return(e||``).replace(/\\/g,`/`).trim().toLowerCase()}function ia(e){let t=ra(e),n=2166136261;for(let e=0;e<t.length;e++)n^=t.charCodeAt(e),n=Math.imul(n,16777619);return n^=n>>>16,n=Math.imul(n,2246822507),n^=n>>>13,n=Math.imul(n,3266489909),n^=n>>>16,na[(n>>>0)%na.length]}function aa(e){return{"--tag-hue":String(ia(e))}}c(),V();var oa=30,sa=f({__name:`WorkbenchKanban`,props:{tasks:{type:Array,required:!0},projectLabels:{type:Object,required:!0},projects:{type:Array,required:!0},taskPercents:{type:Object,required:!1},showProjectLabel:{type:Boolean,required:!0},view:{type:String,required:!0},search:{type:String,required:!0},openedTaskId:{type:[String,null],required:!0}},emits:[`open-task`,`run-task`,`stop-task`,`complete-task`,`reopen-task`,`delete-task`,`move-task`,`create-task`,`update:view`,`update:search`],setup(e,{expose:n,emit:r}){n();let i=e,a=r,s=[{key:`todo`,labelKey:`@WORKBENCH:待处理`},{key:`doing`,labelKey:`@WORKBENCH:进行中`},{key:`done`,labelKey:`@WORKBENCH:已完成`}],c=P({visible:!1,x:0,y:0,task:null});function l(e,t,n){t===`todo`&&(n.preventDefault(),c.value={visible:!0,x:n.clientX,y:n.clientY,task:e})}function u(e){let t=c.value.task;c.value={...c.value,visible:!1},t&&a(`move-task`,t,e)}let d=Y(()=>{let e=i.search.trim().toLowerCase();return i.tasks.filter(t=>!e||(t.title||``).toLowerCase().includes(e)||(t.desc||``).toLowerCase().includes(e))}),f=P(oa);U(()=>i.search,()=>{f.value=oa});let p=Y(()=>{let e=s.map(e=>{let t=e.key===`done`?d.value.filter(t=>t.column===e.key).sort(_):d.value.filter(t=>t.column===e.key);return{...e,all:t}}),t=e.some(e=>e.all.length>0);return e.map(e=>({key:e.key,labelKey:e.labelKey,total:e.all.length,hidden:e.key===`done`?Math.max(0,e.all.length-f.value):0,tasks:e.key===`done`?e.all.slice(0,f.value):e.all,collapsed:t&&e.all.length===0&&e.key!==`todo`}))}),m=Y(()=>({gridTemplateColumns:p.value.map(e=>e.collapsed?`minmax(0, 0fr)`:`minmax(0, 1fr)`).join(` `)})),h=P(!1);o(()=>{requestAnimationFrame(()=>requestAnimationFrame(()=>{h.value=!0}))}),U(()=>i.openedTaskId,e=>{e&&t(()=>{document.querySelector(`.kb-card[data-task-id="${e}"]`)?.scrollIntoView({block:`nearest`,inline:`nearest`})})});function g(e){return Jn(e)}function _(e,t){return g(t).localeCompare(g(e))}function v(e){return Yn(e)}function y(e){return Xn(e)}function b(e){return er(e)}function x(e){let t=(e.autoCompleted?.reason||``).trim(),n=X(`@WORKBENCH:静默超时后由 AI 核对,判定这条任务已经完成`);return t?`${n}\n${t}`:n}let S=Y(()=>[...d.value].sort((e,t)=>v(t).localeCompare(v(e))));function C(e){let t=(e.title||``).trim();if(t)return t;let n=(e.desc||``).replace(/\s+/g,` `).trim();return(/^[a-zA-Z]:[\\/]/.test(n)||n.startsWith(`\\\\`))&&n.split(/[\\/]/).filter(Boolean).pop()||n}function w(e){return i.projectLabels[e.projectPath]||``}function T(e){return e.lastJobStatus===`error`}function E(e){return e.live?.agent||e.lastJobAgent||``}function D(e){if(!e.live)return null;let t=i.taskPercents?.[e.id];return typeof t==`number`?t:null}function ee(e){let t=e.live;if(!t)return``;let n=Qn(e),r=t.lastLine||t.lastThought||t.lastTool;return r?`${n} · ${r}`:n}function O(e){return Array.isArray(e.images)?e.images:[]}let te=P(new Set);function ne(e){te.value=new Set(te.value).add(e)}function k(e){let t=O(e);return te.value.size===0?t:t.filter(e=>!te.value.has(e.id))}function re(e){return`/api/workbench/attachments/${e}/raw`}let A=P(null);function j(e,t=0){let n=k(e);n.length!==0&&(A.value={urls:n.map(e=>re(e.id)),index:t})}function M(){A.value=null}function ie(e){return e.originalName?`${X(`@WORKBENCH:查看图片`)} · ${e.originalName}`:X(`@WORKBENCH:查看图片`)}let ae={props:i,emit:a,COLUMNS:s,moveMenu:c,onCardContextMenu:l,onMoveToProject:u,filtered:d,DONE_PAGE:oa,doneLimit:f,columns:p,columnsStyle:m,animateCollapse:h,doneAt:g,byDoneAtDesc:_,cardTime:v,cardDuration:y,cardTimeTitle:b,autoDoneTitle:x,listRows:S,cardTitle:C,projectLabel:w,hasError:T,cardAgent:E,cardPercent:D,liveSummary:ee,cardImages:O,brokenCoverIds:te,onCoverError:ne,coverImages:k,imageRawUrl:re,imageViewer:A,openImages:j,closeImages:M,coverTitle:ie,get $t(){return X},TaskExecutorIcon:Fe,WorkbenchTaskMoveMenu:ta,get taskExecutorName(){return Oe},get projectTagStyle(){return aa},get formatDurationMs(){return _t},get relativeTimeFromIso(){return vt},get taskLiveText(){return Qn},get taskSpentText(){return Zn},get REPORT_PERCENT_HINT_KEY(){return Ve},get REPORT_PERCENT_LABEL_KEY(){return We},get reportSilentMs(){return Ge}};return Object.defineProperty(ae,"__isScriptSetup",{enumerable:!1,value:!0}),ae}});c(),R(),W();var ca={class:`kb`},la=[`aria-hidden`],ua={class:`kb-col__head`},da={class:`kb-col__title`},fa={class:`kb-col__count`},pa={class:`kb-col__list`},ma=[`data-task-id`,`aria-current`,`onClick`,`onKeydown`,`onContextmenu`],ha=[`title`,`aria-label`,`onClick`],ga=[`src`,`alt`,`onError`],_a={key:0,class:`kb-card__cover-more`,"aria-hidden":`true`},va={class:`kb-card__row1`},ya=[`title`],ba=[`title`],xa={class:`kb-card__time`},Sa=[`title`],Ca=[`title`],wa={key:3,class:`kb-card__live`},Ta={class:`kb-card__live-meta`},Ea=[`title`],Da=[`title`],Oa={key:2,class:`kb-card__live-pid`},ka={key:3,class:`kb-card__live-silent`},Aa=[`title`],ja=[`aria-valuenow`,`aria-label`],Ma={class:`kb-card__live-pct`},Na={class:`kb-card__live-pct-tag`},Pa=[`title`],Fa=[`title`],Ia={class:`kb-card__live-tag`},La=[`title`],Ra={class:`kb-card__live-tag`},za=[`title`],Ba=[`title`],Va={class:`kb-card__reply-text`},Ha=[`title`,`onClick`],Ua={class:`kb-card__actions`},Wa=[`title`,`onClick`],Ga=[`title`,`aria-label`,`onClick`],Ka=[`title`,`aria-label`,`onClick`],qa=[`title`,`aria-label`,`onClick`],Ja=[`title`,`aria-label`,`onClick`],Ya={key:0,class:`kb-col__add`},Xa={key:1,class:`kb-col__empty`},Za={key:2,class:`kb-col__more`},Qa={class:`kb__table-wrap`},$a={class:`kb-table`},eo={class:`kb-table__th`},to={class:`kb-table__th kb-table__th--narrow`},no={class:`kb-table__th kb-table__th--time`},ro=[`onClick`,`onKeydown`],io={class:`kb-table__td`},ao=[`title`,`onClick`],oo={class:`kb-table__name`},so=[`title`],co={key:2,class:`kb-table__live`},lo=[`title`],uo=[`title`],fo={key:2,class:`kb-table__live-silent`},po={class:`kb-table__live kb-table__live--reply`},mo=[`title`],ho={class:`kb-table__td`},go={class:`kb-table__td kb-table__td--num`},_o=[`title`],vo={class:`kb-table__dur`},yo=[`title`],bo={key:0},xo={class:`kb-table__td kb-table__empty`,colspan:`3`};function So(t,n,i,a,o,s){let c=M;return K(),S(`div`,ca,[J(` 看板视图。
64
64
  空列的宽度由 columnsStyle 给 0fr、由 .kb-col.is-collapsed 负责裁掉内容,
65
- 轨道宽度本身走 .kb__columns 的 transition(is-animated 挡住首屏那次抖动)。 `),i.view===`kanban`?(K(),S(`div`,{key:0,class:w([`kb__columns`,{"is-animated":a.animateCollapse}]),style:u(a.columnsStyle)},[(K(!0),S(k,null,D(a.columns,t=>(K(),S(`section`,{key:t.key,class:w([`kb-col`,[`kb-col--`+t.key,{"is-collapsed":t.collapsed}]]),"aria-hidden":t.collapsed?`true`:void 0},[x(`header`,ta,[J(` 脉冲只在列里真有东西时打:0 条的列上闪着"活着"的点,是这一屏唯一的装饰性假信号 `),x(`span`,{class:w([`kb-col__dot`,{"is-live":t.total>0}]),"aria-hidden":`true`},null,2),x(`h3`,na,E(a.$t(t.labelKey)),1),J(` 计数报**总数**而不是当前渲染条数:已完成列默认只铺最近 30 条,
66
- 写 30 会让"一共完成了多少"这件事从界面上消失 `),x(`span`,ra,E(t.total),1)]),J(` 列表**始终渲染**(空列也渲染):塌缩是靠轨道宽度 + overflow 裁的,
65
+ 轨道宽度本身走 .kb__columns 的 transition(is-animated 挡住首屏那次抖动)。 `),i.view===`kanban`?(K(),S(`div`,{key:0,class:T([`kb__columns`,{"is-animated":a.animateCollapse}]),style:u(a.columnsStyle)},[(K(!0),S(k,null,O(a.columns,t=>(K(),S(`section`,{key:t.key,class:T([`kb-col`,[`kb-col--`+t.key,{"is-collapsed":t.collapsed}]]),"aria-hidden":t.collapsed?`true`:void 0},[x(`header`,ua,[J(` 脉冲只在列里真有东西时打:0 条的列上闪着"活着"的点,是这一屏唯一的装饰性假信号 `),x(`span`,{class:T([`kb-col__dot`,{"is-live":t.total>0}]),"aria-hidden":`true`},null,2),x(`h3`,da,D(a.$t(t.labelKey)),1),J(` 计数报**总数**而不是当前渲染条数:已完成列默认只铺最近 30 条,
66
+ 写 30 会让"一共完成了多少"这件事从界面上消失 `),x(`span`,fa,D(t.total),1)]),J(` 列表**始终渲染**(空列也渲染):塌缩是靠轨道宽度 + overflow 裁的,
67
67
  内容得留在 DOM 里,收起那一瞬间才有东西可以跟着一起淡出。
68
- 空列本来就没有卡片,这里最坏也只是多渲染一条「暂无任务」。 `),x(`ul`,ia,[(K(!0),S(k,null,D(t.tasks,t=>(K(),S(`li`,{key:t.id,class:w([`kb-card`,{"is-running":t.runningJobs>0,"has-error":a.hasError(t),"is-opened":t.id===i.openedTaskId}]),"data-task-id":t.id,"aria-current":t.id===i.openedTaskId?`true`:void 0,role:`button`,tabindex:`0`,onClick:e=>a.emit(`open-task`,t),onKeydown:[F(N(e=>a.emit(`open-task`,t),[`prevent`]),[`enter`]),F(N(e=>a.emit(`open-task`,t),[`prevent`]),[`space`])]},[J(`
68
+ 空列本来就没有卡片,这里最坏也只是多渲染一条「暂无任务」。 `),x(`ul`,pa,[(K(!0),S(k,null,O(t.tasks,r=>(K(),S(`li`,{key:r.id,class:T([`kb-card`,{"is-running":r.runningJobs>0,"has-error":a.hasError(r),"is-opened":r.id===i.openedTaskId}]),"data-task-id":r.id,"aria-current":r.id===i.openedTaskId?`true`:void 0,role:`button`,tabindex:`0`,onClick:e=>a.emit(`open-task`,r),onKeydown:[F(N(e=>a.emit(`open-task`,r),[`prevent`]),[`enter`]),F(N(e=>a.emit(`open-task`,r),[`prevent`]),[`space`])],onContextmenu:e=>a.onCardContextMenu(r,t.key,e)},[J(`
69
69
  首行 = 所属项目色标 + 标题 + 时间,三样同一行。
70
70
  · 色标原先自己占一行(一枚 60px 的胶囊推着标题和活动区往下走),
71
71
  现在跟标题并排:卡片窄,能省一行是一行。
@@ -87,7 +87,7 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
87
87
  点开之后看图器能左右翻完整组(见 openImages)。
88
88
  @click.stop / @keydown.stop:卡片整块是"打开任务"的可点区域,
89
89
  封面得把自己摘出来 —— 否则点图会变成打开任务,看不成图。
90
- `),a.coverImages(t).length>0?(K(),S(`button`,{key:0,type:`button`,class:`kb-card__cover`,title:a.coverTitle(a.coverImages(t)[0]),"aria-label":a.coverTitle(a.coverImages(t)[0]),onClick:N(e=>a.openImages(t),[`stop`]),onKeydown:n[0]||=N(()=>{},[`stop`])},[x(`img`,{class:`kb-card__cover-img`,src:a.imageRawUrl(a.coverImages(t)[0].id),alt:a.coverImages(t)[0].originalName,loading:`lazy`,decoding:`async`,onError:e=>a.onCoverError(a.coverImages(t)[0].id)},null,40,sa),a.coverImages(t).length>1?(K(),S(`span`,ca,` +`+E(a.coverImages(t).length-1),1)):J(`v-if`,!0)],40,oa)):J(`v-if`,!0),x(`div`,la,[i.showProjectLabel&&a.projectLabel(t)?(K(),S(`span`,{key:0,class:`kb-card__project-chip`,style:u(a.projectTagStyle(t.projectPath)),title:t.projectPath},E(a.projectLabel(t)),13,ua)):J(`v-if`,!0),x(`p`,{class:`kb-card__title`,title:a.cardTitle(t)},E(a.cardTitle(t)||a.$t(`@WORKBENCH:未命名任务`)),9,da),x(`span`,fa,E(a.relativeTimeFromIso(a.cardTime(t))),1)]),J(`
90
+ `),a.coverImages(r).length>0?(K(),S(`button`,{key:0,type:`button`,class:`kb-card__cover`,title:a.coverTitle(a.coverImages(r)[0]),"aria-label":a.coverTitle(a.coverImages(r)[0]),onClick:N(e=>a.openImages(r),[`stop`]),onKeydown:n[0]||=N(()=>{},[`stop`])},[x(`img`,{class:`kb-card__cover-img`,src:a.imageRawUrl(a.coverImages(r)[0].id),alt:a.coverImages(r)[0].originalName,loading:`lazy`,decoding:`async`,onError:e=>a.onCoverError(a.coverImages(r)[0].id)},null,40,ga),a.coverImages(r).length>1?(K(),S(`span`,_a,` +`+D(a.coverImages(r).length-1),1)):J(`v-if`,!0)],40,ha)):J(`v-if`,!0),x(`div`,va,[i.showProjectLabel&&a.projectLabel(r)?(K(),S(`span`,{key:0,class:`kb-card__project-chip`,style:u(a.projectTagStyle(r.projectPath)),title:r.projectPath},D(a.projectLabel(r)),13,ya)):J(`v-if`,!0),x(`p`,{class:`kb-card__title`,title:a.cardTitle(r)},D(a.cardTitle(r)||a.$t(`@WORKBENCH:未命名任务`)),9,ba),x(`span`,xa,D(a.relativeTimeFromIso(a.cardTime(r))),1)]),J(`
91
91
  跑完的任务:用时**独占一行**,不挤进上面那个时间位。
92
92
  实测首行(项目色标 + 标题 + 时间)在真实数据上已经排满,
93
93
  再塞一串「用时 30 分 0 秒」会把项目色标压出 1px 的省略号
@@ -95,7 +95,7 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
95
95
  竖着放只多一行 16px,横向一个字节都不占;而且「什么时候跑的」与
96
96
  「跑了多久」本来就是两个维度,分两行读比挤在一行清楚 ——
97
97
  同理它也没去挤活动区那行"已运行 x · 工具 n 次"。
98
- `),a.cardDuration(t)?(K(),S(`p`,{key:1,class:`kb-card__spent`,title:a.cardTimeTitle(t)},E(a.taskSpentText(t)),9,pa)):J(`v-if`,!0),J(`
98
+ `),a.cardDuration(r)?(K(),S(`p`,{key:1,class:`kb-card__spent`,title:a.cardTimeTitle(r)},D(a.taskSpentText(r)),9,Sa)):J(`v-if`,!0),J(`
99
99
  「这条不是跑完的,是**判**完的」—— 紧跟在那行用时下面(它修饰的就是上面那个时长)。
100
100
 
101
101
  为什么**另起一行**、而不是挂在那行用时后面:那行有探针按逐字相等断言
@@ -108,7 +108,7 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
108
108
  前者是**模型读了它的思考与最后那段话,认为活已经干完**。不标的话,
109
109
  用户看到的就是一条任务不声不响换了列,而模型给的依据(悬停可见)
110
110
  只躺在 jobs.json 里没人看得到。
111
- `),t.autoCompleted?(K(),S(`p`,{key:2,class:`kb-card__auto-done`,title:a.autoDoneTitle(t)},E(a.$t(`@WORKBENCH:AI 判定完成`)),9,ma)):J(`v-if`,!0),J(`
111
+ `),r.autoCompleted?(K(),S(`p`,{key:2,class:`kb-card__auto-done`,title:a.autoDoneTitle(r)},D(a.$t(`@WORKBENCH:AI 判定完成`)),9,Ca)):J(`v-if`,!0),J(`
112
112
  正在跑的任务:把"现在在干嘛"直接写在卡片上。
113
113
  在此之前卡片只有右上角一个圆点 —— 一次跑二十分钟的任务,
114
114
  用户盯着看只知道"还在跑",是在改代码还是卡住了完全看不出来,
@@ -116,15 +116,15 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
116
116
  (decorateTaskForBoard 的 live,与右栏进度报告同一份实现)。
117
117
  证据顺序沿用进度报告面板:工具调用(正在做什么)→ 思考(为什么)
118
118
  → 最新回复;每一行没有内容就整行不渲染,不写"暂无"。
119
- `),t.live?(K(),S(`div`,ha,[x(`p`,ga,[J(` 执行器只留图标 + 悬停提示:卡片这一行本来就窄(已运行 x 分 y 秒 · 工具 n 次),
119
+ `),r.live?(K(),S(`div`,wa,[x(`p`,Ta,[J(` 执行器只留图标 + 悬停提示:卡片这一行本来就窄(已运行 x 分 y 秒 · 工具 n 次),
120
120
  再钉一个 "Claude Code" 文本会把工具次数挤到第二行去。
121
- v-if 挡住的是"认不出"(老记录没写 agent 字段)——那时宁可不画 `),a.cardAgent(t)?(K(),S(`span`,{key:0,class:`kb-card__live-agent`,title:a.taskExecutorName(a.cardAgent(t))},[e(a.TaskExecutorIcon,{executor:a.cardAgent(t),class:`kb-card__live-agent-icon`},null,8,[`executor`])],8,_a)):J(`v-if`,!0),x(`span`,null,E(a.taskLiveText(t)),1),J(` 次数看总数,鼠标停上去看分布:119 次里 118 次都是 Bash,
122
- 和"改了三处代码"是完全不同的两件事 `),t.live.toolCallCount?(K(),S(`span`,{key:1,title:t.live.toolMix||``},E(a.$t(`@WORKBENCH:工具 {n} 次`,{n:t.live.toolCallCount})),9,va)):J(`v-if`,!0),J(`
121
+ v-if 挡住的是"认不出"(老记录没写 agent 字段)——那时宁可不画 `),a.cardAgent(r)?(K(),S(`span`,{key:0,class:`kb-card__live-agent`,title:a.taskExecutorName(a.cardAgent(r))},[e(a.TaskExecutorIcon,{executor:a.cardAgent(r),class:`kb-card__live-agent-icon`},null,8,[`executor`])],8,Ea)):J(`v-if`,!0),x(`span`,null,D(a.taskLiveText(r)),1),J(` 次数看总数,鼠标停上去看分布:119 次里 118 次都是 Bash,
122
+ 和"改了三处代码"是完全不同的两件事 `),r.live.toolCallCount?(K(),S(`span`,{key:1,title:r.live.toolMix||``},D(a.$t(`@WORKBENCH:工具 {n} 次`,{n:r.live.toolCallCount})),9,Da)):J(`v-if`,!0),J(`
123
123
  PID:左栏那个「执行监控」面板去掉了,它的字段里只有这一个卡片上没有,
124
124
  所以并到这一行来(面板其余字段卡片本来就都有,且比它更全)。
125
125
  不走 $t:PID 是中英文都这么写的通用缩写,没有可翻译的余地。
126
126
  放静默之前:静默是"它可能卡住了"的信号,该留在行尾最显眼。
127
- `),t.live.pid?(K(),S(`span`,ya,`PID `+E(t.live.pid),1)):J(`v-if`,!0),J(` 静默只在**显然静默**时才有值(服务端有阈值);0 不画(reportSilentMs) `),a.reportSilentMs(t.live.silentMs)===null?J(`v-if`,!0):(K(),S(`span`,ba,E(a.$t(`@WORKBENCH:静默 {elapsed}`,{elapsed:a.formatDurationMs(a.reportSilentMs(t.live.silentMs))})),1))]),J(`
127
+ `),r.live.pid?(K(),S(`span`,Oa,`PID `+D(r.live.pid),1)):J(`v-if`,!0),J(` 静默只在**显然静默**时才有值(服务端有阈值);0 不画(reportSilentMs) `),a.reportSilentMs(r.live.silentMs)===null?J(`v-if`,!0):(K(),S(`span`,ka,D(a.$t(`@WORKBENCH:静默 {elapsed}`,{elapsed:a.formatDurationMs(a.reportSilentMs(r.live.silentMs))})),1))]),J(`
128
128
  这条任务现在几成(主 Agent 估的)。2026-10-14 从右栏「任务事实」搬过来:
129
129
  那一区列的就是这几行事实(工具 / 思考 / 回复 + 时长),与卡片几乎逐字重合,
130
130
  两处并排显示时用户看到的是同一件事说两遍(用户截图反馈"左右都有,有点重叠")。
@@ -137,8 +137,8 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
137
137
 
138
138
  不画的情况全部交给 cardPercent 判(没在跑 / 报告里没提到它 / 模型没给数字),
139
139
  绝不画一条 0% 的实心条 —— 那等于替模型说它没说过的话。
140
- `),a.cardPercent(t)===null?J(`v-if`,!0):(K(),S(`p`,{key:0,class:`kb-card__live-progress`,title:a.$t(a.REPORT_PERCENT_HINT_KEY)},[x(`span`,{class:`kb-card__live-bar`,role:`progressbar`,"aria-valuenow":a.cardPercent(t),"aria-valuemin":`0`,"aria-valuemax":`100`,"aria-label":a.cardTitle(t)||a.$t(`@WORKBENCH:未命名任务`)},[x(`i`,{class:`kb-card__live-bar-fill`,style:u({width:a.cardPercent(t)+`%`})},null,4)],8,Sa),J(` 「AI 估计」四个字不能省(与右栏整体那条同一取舍):卡片上再没有别的
141
- 地方交代这个数字是怎么来的,光甩一个 22% 会被当成实测进度 `),x(`span`,Ca,[x(`span`,wa,E(a.$t(a.REPORT_PERCENT_LABEL_KEY)),1),z(E(a.cardPercent(t))+`% `,1)])],8,xa)),t.live.lastTool?(K(),S(`p`,{key:1,class:`kb-card__live-line is-tool`,title:t.live.lastTool},E(t.live.lastTool),9,Ta)):J(`v-if`,!0),t.live.lastThought?(K(),S(`p`,{key:2,class:`kb-card__live-line is-thought`,title:t.live.lastThought},[x(`span`,Da,E(a.$t(`@WORKBENCH:最近思考`)),1),z(E(t.live.lastThought),1)],8,Ea)):J(`v-if`,!0),t.live.lastLine?(K(),S(`p`,{key:3,class:`kb-card__live-line`,title:t.live.lastLine},[x(`span`,ka,E(a.$t(`@WORKBENCH:最新回复`)),1),z(E(t.live.lastLine),1)],8,Oa)):J(`v-if`,!0)])):t.lastReply?(K(),S(k,{key:4},[J(`
140
+ `),a.cardPercent(r)===null?J(`v-if`,!0):(K(),S(`p`,{key:0,class:`kb-card__live-progress`,title:a.$t(a.REPORT_PERCENT_HINT_KEY)},[x(`span`,{class:`kb-card__live-bar`,role:`progressbar`,"aria-valuenow":a.cardPercent(r),"aria-valuemin":`0`,"aria-valuemax":`100`,"aria-label":a.cardTitle(r)||a.$t(`@WORKBENCH:未命名任务`)},[x(`i`,{class:`kb-card__live-bar-fill`,style:u({width:a.cardPercent(r)+`%`})},null,4)],8,ja),J(` 「AI 估计」四个字不能省(与右栏整体那条同一取舍):卡片上再没有别的
141
+ 地方交代这个数字是怎么来的,光甩一个 22% 会被当成实测进度 `),x(`span`,Ma,[x(`span`,Na,D(a.$t(a.REPORT_PERCENT_LABEL_KEY)),1),z(D(a.cardPercent(r))+`% `,1)])],8,Aa)),r.live.lastTool?(K(),S(`p`,{key:1,class:`kb-card__live-line is-tool`,title:r.live.lastTool},D(r.live.lastTool),9,Pa)):J(`v-if`,!0),r.live.lastThought?(K(),S(`p`,{key:2,class:`kb-card__live-line is-thought`,title:r.live.lastThought},[x(`span`,Ia,D(a.$t(`@WORKBENCH:最近思考`)),1),z(D(r.live.lastThought),1)],8,Fa)):J(`v-if`,!0),r.live.lastLine?(K(),S(`p`,{key:3,class:`kb-card__live-line`,title:r.live.lastLine},[x(`span`,Ra,D(a.$t(`@WORKBENCH:最新回复`)),1),z(D(r.live.lastLine),1)],8,La)):J(`v-if`,!0)])):r.lastReply?(K(),S(k,{key:4},[J(`
142
142
  已经跑完的任务:留下"它最后说了什么"。
143
143
  卡片过去只有标题 + 时间,而模型收尾时常常反问一句「要 push 吗?」——
144
144
  这类任务看着是完成了,其实在等用户回话,用户却只能点进去翻日志才知道。
@@ -149,7 +149,7 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
149
149
 
150
150
  执行器图标(有才渲染)摆在引文开头:这句收尾的话是**它**说的,
151
151
  图标就贴着它,比跑到卡片别处去找更直接。
152
- `),x(`p`,{class:`kb-card__reply`,title:t.lastReply},[a.cardAgent(t)?(K(),S(`span`,{key:0,class:`kb-card__quote-agent`,title:a.taskExecutorName(a.cardAgent(t))},[e(a.TaskExecutorIcon,{executor:a.cardAgent(t),class:`kb-card__quote-agent-icon`},null,8,[`executor`])],8,ja)):J(`v-if`,!0),x(`span`,Ma,E(t.lastReply),1)],8,Aa)],2112)):J(`v-if`,!0),J(`
152
+ `),x(`p`,{class:`kb-card__reply`,title:r.lastReply},[a.cardAgent(r)?(K(),S(`span`,{key:0,class:`kb-card__quote-agent`,title:a.taskExecutorName(a.cardAgent(r))},[e(a.TaskExecutorIcon,{executor:a.cardAgent(r),class:`kb-card__quote-agent-icon`},null,8,[`executor`])],8,Ba)):J(`v-if`,!0),x(`span`,Va,D(r.lastReply),1)],8,za)],2112)):J(`v-if`,!0),J(`
153
153
  出错卡上「重试」常驻。
154
154
  卡片其余动作住在 hover 遮罩里(那是刻意的,见文件头:看板不是操作面板),
155
155
  但出错是**跨列状态**里唯一需要立刻决策的一种:静态屏上那张红卡只有一句
@@ -157,7 +157,7 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
157
157
  单独一颗按钮、**不并进 .kb-card__actions** —— 那一组的宽度被
158
158
  verify-wb-card-fade-band 按 96px 常数反推过渐隐距离,往里塞第三颗要连带改遮罩;
159
159
  位置也必须在动作组**之前**,因为动作组是遮罩的锚点(卡片最后一行)。
160
- `),a.hasError(t)&&t.runningJobs===0?(K(),S(`button`,{key:5,type:`button`,class:`kb-card__retry`,title:a.$t(`@WORKBENCH:重新执行这条任务`),onClick:N(e=>a.emit(`run-task`,t),[`stop`]),onKeydown:n[1]||=N(()=>{},[`stop`])},E(a.$t(`@WORKBENCH:重试`)),41,Na)):J(`v-if`,!0),x(`div`,Pa,[J(`
160
+ `),a.hasError(r)&&r.runningJobs===0?(K(),S(`button`,{key:5,type:`button`,class:`kb-card__retry`,title:a.$t(`@WORKBENCH:重新执行这条任务`),onClick:N(e=>a.emit(`run-task`,r),[`stop`]),onKeydown:n[1]||=N(()=>{},[`stop`])},D(a.$t(`@WORKBENCH:重试`)),41,Ha)):J(`v-if`,!0),x(`div`,Ua,[J(`
161
161
  这一格是「对这条任务现在能做什么」。头两颗互斥、**不并排**:
162
162
  空闲时能做的只有"跑一轮",在跑时能做的只有"停掉这一轮",
163
163
  两个按钮同时摆着会让人以为"在跑也能再跑一轮"(服务端也确实拒绝)。
@@ -165,14 +165,14 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
165
165
  操作组宽度因此**一个像素都不变** —— 下面那段按组宽反推的渐隐距离不用跟着改。
166
166
  (2026-10-01 加的「完成 / 撤销」也是 2 个汉字、且每张卡上最多出现一颗,
167
167
  组宽仍是常数:96px。改动组宽就必须同步改那两组数字,否则按钮会露出半截字形。)
168
- `),t.runningJobs===0?(K(),S(`button`,{key:0,type:`button`,class:`kb-card__btn`,title:a.$t(`@WORKBENCH:执行`),onClick:N(e=>a.emit(`run-task`,t),[`stop`]),onKeydown:n[2]||=N(()=>{},[`stop`])},E(a.$t(`@WORKBENCH:执行`)),41,Fa)):(K(),S(k,{key:1},[J(`
168
+ `),r.runningJobs===0?(K(),S(`button`,{key:0,type:`button`,class:`kb-card__btn`,title:a.$t(`@WORKBENCH:执行`),onClick:N(e=>a.emit(`run-task`,r),[`stop`]),onKeydown:n[2]||=N(()=>{},[`stop`])},D(a.$t(`@WORKBENCH:执行`)),41,Wa)):(K(),S(k,{key:1},[J(`
169
169
  停止:只有真在跑(runningJobs > 0 ⟺ 服务端推导出的「进行中」列)时才在。
170
170
  条件用 runningJobs 而不是 \`!!t.live\`:两者在服务端同源(都是"有 running/pending
171
171
  的 job"),但 runningJobs 是这张卡片列归属的判据本身,跟着它走不会出现
172
172
  "卡片在待处理列却带个停止按钮"这种自相矛盾的状态。
173
173
  点了做什么(确认弹窗、调哪个接口、jobId 从哪来)全在上层 —— 卡片只管发出意图,
174
174
  与 run / delete 一致。
175
- `),x(`button`,{type:`button`,class:`kb-card__btn kb-card__btn--stop`,title:a.$t(`@WORKBENCH:停止`),"aria-label":a.$t(`@WORKBENCH:停止`),onClick:N(e=>a.emit(`stop-task`,t),[`stop`]),onKeydown:n[3]||=N(()=>{},[`stop`])},E(a.$t(`@WORKBENCH:停止`)),41,Ia)],2112)),J(`
175
+ `),x(`button`,{type:`button`,class:`kb-card__btn kb-card__btn--stop`,title:a.$t(`@WORKBENCH:停止`),"aria-label":a.$t(`@WORKBENCH:停止`),onClick:N(e=>a.emit(`stop-task`,r),[`stop`]),onKeydown:n[3]||=N(()=>{},[`stop`])},D(a.$t(`@WORKBENCH:停止`)),41,Ga)],2112)),J(`
176
176
  手动「完成」:这颗按钮是看板上唯一一个**不由执行事实决定**的动作源头
177
177
  (列仍然是推导的,只是推导时多听一句人话 —— 详见文件头那段)。
178
178
  待处理 / 进行中都给:待处理里那条可能早在别处干完了,
@@ -185,28 +185,28 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
185
185
 
186
186
  在跑的那张卡上点「完成」会连这一轮一起停掉(一张卡不能既已完成又在跑),
187
187
  代价说明与确认弹窗在上层 —— 卡片只管发出意图,与 run / stop / delete 一致。
188
- `),t.column===`done`?t.manualDoneAt?(K(),S(`button`,{key:3,type:`button`,class:`kb-card__btn`,title:a.$t(`@WORKBENCH:撤销完成标记,退回待处理`),"aria-label":a.$t(`@WORKBENCH:撤销完成标记`),onClick:N(e=>a.emit(`reopen-task`,t),[`stop`]),onKeydown:n[5]||=N(()=>{},[`stop`])},E(a.$t(`@WORKBENCH:撤销`)),41,Ra)):J(`v-if`,!0):(K(),S(`button`,{key:2,type:`button`,class:`kb-card__btn kb-card__btn--done`,title:a.$t(`@WORKBENCH:标记为已完成`),"aria-label":a.$t(`@WORKBENCH:标记为已完成`),onClick:N(e=>a.emit(`complete-task`,t),[`stop`]),onKeydown:n[4]||=N(()=>{},[`stop`])},E(a.$t(`@WORKBENCH:完成`)),41,La)),x(`button`,{type:`button`,class:`kb-card__btn kb-card__btn--danger`,title:a.$t(`@WORKBENCH:删除`),"aria-label":a.$t(`@WORKBENCH:删除`),onClick:N(e=>a.emit(`delete-task`,t),[`stop`]),onKeydown:n[6]||=N(()=>{},[`stop`])},`×`,40,za)])],42,aa))),128)),J(`
188
+ `),r.column===`done`?r.manualDoneAt?(K(),S(`button`,{key:3,type:`button`,class:`kb-card__btn`,title:a.$t(`@WORKBENCH:撤销完成标记,退回待处理`),"aria-label":a.$t(`@WORKBENCH:撤销完成标记`),onClick:N(e=>a.emit(`reopen-task`,r),[`stop`]),onKeydown:n[5]||=N(()=>{},[`stop`])},D(a.$t(`@WORKBENCH:撤销`)),41,qa)):J(`v-if`,!0):(K(),S(`button`,{key:2,type:`button`,class:`kb-card__btn kb-card__btn--done`,title:a.$t(`@WORKBENCH:标记为已完成`),"aria-label":a.$t(`@WORKBENCH:标记为已完成`),onClick:N(e=>a.emit(`complete-task`,r),[`stop`]),onKeydown:n[4]||=N(()=>{},[`stop`])},D(a.$t(`@WORKBENCH:完成`)),41,Ka)),x(`button`,{type:`button`,class:`kb-card__btn kb-card__btn--danger`,title:a.$t(`@WORKBENCH:删除`),"aria-label":a.$t(`@WORKBENCH:删除`),onClick:N(e=>a.emit(`delete-task`,r),[`stop`]),onKeydown:n[6]||=N(()=>{},[`stop`])},`×`,40,Ja)])],42,ma))),128)),J(`
189
189
  「新建任务」常驻待处理列末尾,不再只在列空时出现。
190
190
  之前入口和空状态是同一个 \`v-if="col.tasks.length === 0"\`:列里一有卡片,
191
191
  新建入口就整块消失,用户只能绕到左侧栏去建(看板里无处可点)。
192
192
  两件事本来就无关——空状态说的是"这列没有卡片",新建入口说的是"能往这儿加卡片"。
193
193
  列空时它顺带兼任空状态(--solo 撑高),所以待处理列不会再渲染下面的 kb-col__empty。
194
194
  位置沿用 Trello「Add a card」的做法:跟着列表滚(不吸底),长列表滚到底就是它。
195
- `),t.key===`todo`?(K(),S(`li`,Ba,[x(`button`,{type:`button`,class:w([`kb-col__add-btn`,{"kb-col__add-btn--solo":t.tasks.length===0}]),onClick:n[7]||=e=>a.emit(`create-task`)},[n[10]||=x(`span`,{class:`kb-col__add-plus`,"aria-hidden":`true`},`+`,-1),x(`span`,null,E(a.$t(`@WORKBENCH:新建任务`)),1)],2)])):t.tasks.length===0?(K(),S(`li`,Va,[x(`span`,null,E(a.$t(`@WORKBENCH:暂无任务`)),1)])):J(`v-if`,!0),J(` 「再多给我一点」:已完成列默认只铺最近 30 条(实测满载态 159 条约 20 屏滚动)。
196
- 不是分页 —— 点一次在当前列表尾巴上续一批,不打断滚动位置。 `),t.hidden>0?(K(),S(`li`,Ha,[x(`button`,{type:`button`,class:`kb-col__more-btn`,onClick:n[8]||=e=>a.doneLimit+=a.DONE_PAGE},E(a.$t(`@WORKBENCH:显示更早的 {n} 条`,{n:Math.min(a.DONE_PAGE,t.hidden)})),1)])):J(`v-if`,!0)])],10,ea))),128))],6)):(K(),S(k,{key:1},[J(` 列表视图 `),x(`div`,Ua,[x(`table`,Wa,[x(`thead`,null,[x(`tr`,null,[x(`th`,Ga,E(a.$t(`@WORKBENCH:任务`)),1),x(`th`,Ka,E(a.$t(`@WORKBENCH:状态`)),1),x(`th`,qa,E(a.$t(`@WORKBENCH:时间`)),1)])]),x(`tbody`,null,[(K(!0),S(k,null,D(a.listRows,t=>(K(),S(`tr`,{key:t.id,class:`kb-table__row`,tabindex:`0`,onClick:e=>a.emit(`open-task`,t),onKeydown:[F(N(e=>a.emit(`open-task`,t),[`prevent`]),[`enter`]),F(N(e=>a.emit(`open-task`,t),[`prevent`]),[`space`])]},[x(`td`,Ya,[J(` 列表视图这边的"这条带图":与看板卡片的封面同一份数据、同一层含义。
195
+ `),t.key===`todo`?(K(),S(`li`,Ya,[x(`button`,{type:`button`,class:T([`kb-col__add-btn`,{"kb-col__add-btn--solo":t.tasks.length===0}]),onClick:n[7]||=e=>a.emit(`create-task`)},[n[11]||=x(`span`,{class:`kb-col__add-plus`,"aria-hidden":`true`},`+`,-1),x(`span`,null,D(a.$t(`@WORKBENCH:新建任务`)),1)],2)])):t.tasks.length===0?(K(),S(`li`,Xa,[x(`span`,null,D(a.$t(`@WORKBENCH:暂无任务`)),1)])):J(`v-if`,!0),J(` 「再多给我一点」:已完成列默认只铺最近 30 条(实测满载态 159 条约 20 屏滚动)。
196
+ 不是分页 —— 点一次在当前列表尾巴上续一批,不打断滚动位置。 `),t.hidden>0?(K(),S(`li`,Za,[x(`button`,{type:`button`,class:`kb-col__more-btn`,onClick:n[8]||=e=>a.doneLimit+=a.DONE_PAGE},D(a.$t(`@WORKBENCH:显示更早的 {n} 条`,{n:Math.min(a.DONE_PAGE,t.hidden)})),1)])):J(`v-if`,!0)])],10,la))),128))],6)):(K(),S(k,{key:1},[J(` 列表视图 `),x(`div`,Qa,[x(`table`,$a,[x(`thead`,null,[x(`tr`,null,[x(`th`,eo,D(a.$t(`@WORKBENCH:任务`)),1),x(`th`,to,D(a.$t(`@WORKBENCH:状态`)),1),x(`th`,no,D(a.$t(`@WORKBENCH:时间`)),1)])]),x(`tbody`,null,[(K(!0),S(k,null,O(a.listRows,t=>(K(),S(`tr`,{key:t.id,class:`kb-table__row`,tabindex:`0`,onClick:e=>a.emit(`open-task`,t),onKeydown:[F(N(e=>a.emit(`open-task`,t),[`prevent`]),[`enter`]),F(N(e=>a.emit(`open-task`,t),[`prevent`]),[`space`])]},[x(`td`,io,[J(` 列表视图这边的"这条带图":与看板卡片的封面同一份数据、同一层含义。
197
197
  看板默认视图是卡片,所以那边可以铺一张封面;这一格是一行密排的正文
198
198
  (整格 width 按 table-layout: fixed 平分),塞缩略图会把行高顶出去 ——
199
199
  .kb-table__time 那边有探针按"整格只有一行"断言,这一格没理由比它松。
200
200
  所以退成**纯文字的计数标**:零字号变化、零内边距,行高一个像素不动,
201
201
  但仍然是个按钮(点了看图)——"有图"这件事在两处视图里都消失不了。
202
- 同 .kb-table__auto-done:只给颜色,不给框。 `),a.coverImages(t).length>0?(K(),S(`button`,{key:0,type:`button`,class:`kb-table__shots`,title:a.coverTitle(a.coverImages(t)[0]),onClick:N(e=>a.openImages(t),[`stop`]),onKeydown:n[9]||=N(()=>{},[`stop`])},E(a.$t(`@WORKBENCH:{n} 张图`,{n:a.coverImages(t).length})),41,Xa)):J(`v-if`,!0),x(`span`,Za,E(a.cardTitle(t)||a.$t(`@WORKBENCH:未命名任务`)),1),J(` 项目色标:与看板卡片同一枚(见 .kb-card__project-chip 的样式注释),
203
- 列表视图是同一批任务的另一种画法,两处长得不一样会让人以为是两份数据 `),i.showProjectLabel&&a.projectLabel(t)?(K(),S(`span`,{key:1,class:`kb-table__project`,style:u(a.projectTagStyle(t.projectPath)),title:t.projectPath},E(a.projectLabel(t)),13,Qa)):J(`v-if`,!0),J(` 状态列的"进行中"太粗,跑起来之后一眼看不出进度:这里补一行
202
+ 同 .kb-table__auto-done:只给颜色,不给框。 `),a.coverImages(t).length>0?(K(),S(`button`,{key:0,type:`button`,class:`kb-table__shots`,title:a.coverTitle(a.coverImages(t)[0]),onClick:N(e=>a.openImages(t),[`stop`]),onKeydown:n[9]||=N(()=>{},[`stop`])},D(a.$t(`@WORKBENCH:{n} 张图`,{n:a.coverImages(t).length})),41,ao)):J(`v-if`,!0),x(`span`,oo,D(a.cardTitle(t)||a.$t(`@WORKBENCH:未命名任务`)),1),J(` 项目色标:与看板卡片同一枚(见 .kb-card__project-chip 的样式注释),
203
+ 列表视图是同一批任务的另一种画法,两处长得不一样会让人以为是两份数据 `),i.showProjectLabel&&a.projectLabel(t)?(K(),S(`span`,{key:1,class:`kb-table__project`,style:u(a.projectTagStyle(t.projectPath)),title:t.projectPath},D(a.projectLabel(t)),13,so)):J(`v-if`,!0),J(` 状态列的"进行中"太粗,跑起来之后一眼看不出进度:这里补一行
204
204
  最新回复 / 思考 / 工具(与卡片上的 live 同一份数据)。
205
- 执行器图标摆最前(与看板卡片同一个位置:整块执行事实的开头) `),t.live?(K(),S(`span`,$a,[a.cardAgent(t)?(K(),S(`span`,{key:0,class:`kb-table__agent`,title:a.taskExecutorName(a.cardAgent(t))},[e(a.TaskExecutorIcon,{executor:a.cardAgent(t),class:`kb-table__agent-icon`},null,8,[`executor`])],8,eo)):J(`v-if`,!0),z(` `+E(a.liveSummary(t))+` `,1),J(` 进度与看板卡片同一份数据(同一张表):两种画法一边有一边没有,
206
- 会让人以为是两份数据。列表这行只有一行,所以只给数字不给条 `),a.cardPercent(t)===null?J(`v-if`,!0):(K(),S(`span`,{key:1,class:`kb-table__pct`,title:a.$t(a.REPORT_PERCENT_HINT_KEY)},E(a.$t(a.REPORT_PERCENT_LABEL_KEY))+` `+E(a.cardPercent(t))+`% `,9,to)),a.reportSilentMs(t.live.silentMs)===null?J(`v-if`,!0):(K(),S(`span`,no,E(a.$t(`@WORKBENCH:静默 {elapsed}`,{elapsed:a.formatDurationMs(a.reportSilentMs(t.live.silentMs))})),1))])):t.lastReply?(K(),S(k,{key:3},[J(` 跑完的任务同理给一行"最后说了什么":列表视图与看板卡片是同一批任务的
207
- 两种画法,一边有、一边没有会让人以为是两份数据 `),x(`span`,ro,[a.cardAgent(t)?(K(),S(`span`,{key:0,class:`kb-table__agent`,title:a.taskExecutorName(a.cardAgent(t))},[e(a.TaskExecutorIcon,{executor:a.cardAgent(t),class:`kb-table__agent-icon`},null,8,[`executor`])],8,io)):J(`v-if`,!0),z(E(t.lastReply),1)])],2112)):J(`v-if`,!0)]),x(`td`,ao,[x(`span`,{class:w([`kb-table__status`,`is-`+t.column])},E(a.$t(a.COLUMNS.find(e=>e.key===t.column).labelKey)),3)]),x(`td`,oo,[J(` 与看板卡片首行同一个口径:同一批任务的两种画法,一边有一边没有
208
- 会让人以为是两份数据 `),x(`span`,{class:`kb-table__time`,title:a.cardTimeTitle(t)},[a.cardDuration(t)?(K(),S(k,{key:0},[x(`span`,co,E(a.taskSpentText(t)),1),n[11]||=x(`span`,{class:`kb-table__time-sep`,"aria-hidden":`true`},`·`,-1)],64)):J(`v-if`,!0),J(` 「AI 判定完成」在列表视图里也得有:同一批任务的两种画法,
209
- 一边有一边没有会让人以为是两份数据(卡片那边见 .kb-card__spent 的注释) `),t.autoCompleted?(K(),S(k,{key:1},[x(`span`,{class:`kb-table__auto-done`,title:a.autoDoneTitle(t)},E(a.$t(`@WORKBENCH:AI 判定完成`)),9,lo),n[12]||=x(`span`,{class:`kb-table__time-sep`,"aria-hidden":`true`},`·`,-1)],64)):J(`v-if`,!0),x(`span`,null,E(a.relativeTimeFromIso(a.cardTime(t))),1)],8,so)])],40,Ja))),128)),a.listRows.length===0?(K(),S(`tr`,uo,[x(`td`,fo,E(a.$t(`@WORKBENCH:暂无任务`)),1)])):J(`v-if`,!0)])])])],2112)),J(`
205
+ 执行器图标摆最前(与看板卡片同一个位置:整块执行事实的开头) `),t.live?(K(),S(`span`,co,[a.cardAgent(t)?(K(),S(`span`,{key:0,class:`kb-table__agent`,title:a.taskExecutorName(a.cardAgent(t))},[e(a.TaskExecutorIcon,{executor:a.cardAgent(t),class:`kb-table__agent-icon`},null,8,[`executor`])],8,lo)):J(`v-if`,!0),z(` `+D(a.liveSummary(t))+` `,1),J(` 进度与看板卡片同一份数据(同一张表):两种画法一边有一边没有,
206
+ 会让人以为是两份数据。列表这行只有一行,所以只给数字不给条 `),a.cardPercent(t)===null?J(`v-if`,!0):(K(),S(`span`,{key:1,class:`kb-table__pct`,title:a.$t(a.REPORT_PERCENT_HINT_KEY)},D(a.$t(a.REPORT_PERCENT_LABEL_KEY))+` `+D(a.cardPercent(t))+`% `,9,uo)),a.reportSilentMs(t.live.silentMs)===null?J(`v-if`,!0):(K(),S(`span`,fo,D(a.$t(`@WORKBENCH:静默 {elapsed}`,{elapsed:a.formatDurationMs(a.reportSilentMs(t.live.silentMs))})),1))])):t.lastReply?(K(),S(k,{key:3},[J(` 跑完的任务同理给一行"最后说了什么":列表视图与看板卡片是同一批任务的
207
+ 两种画法,一边有、一边没有会让人以为是两份数据 `),x(`span`,po,[a.cardAgent(t)?(K(),S(`span`,{key:0,class:`kb-table__agent`,title:a.taskExecutorName(a.cardAgent(t))},[e(a.TaskExecutorIcon,{executor:a.cardAgent(t),class:`kb-table__agent-icon`},null,8,[`executor`])],8,mo)):J(`v-if`,!0),z(D(t.lastReply),1)])],2112)):J(`v-if`,!0)]),x(`td`,ho,[x(`span`,{class:T([`kb-table__status`,`is-`+t.column])},D(a.$t(a.COLUMNS.find(e=>e.key===t.column).labelKey)),3)]),x(`td`,go,[J(` 与看板卡片首行同一个口径:同一批任务的两种画法,一边有一边没有
208
+ 会让人以为是两份数据 `),x(`span`,{class:`kb-table__time`,title:a.cardTimeTitle(t)},[a.cardDuration(t)?(K(),S(k,{key:0},[x(`span`,vo,D(a.taskSpentText(t)),1),n[12]||=x(`span`,{class:`kb-table__time-sep`,"aria-hidden":`true`},`·`,-1)],64)):J(`v-if`,!0),J(` 「AI 判定完成」在列表视图里也得有:同一批任务的两种画法,
209
+ 一边有一边没有会让人以为是两份数据(卡片那边见 .kb-card__spent 的注释) `),t.autoCompleted?(K(),S(k,{key:1},[x(`span`,{class:`kb-table__auto-done`,title:a.autoDoneTitle(t)},D(a.$t(`@WORKBENCH:AI 判定完成`)),9,yo),n[13]||=x(`span`,{class:`kb-table__time-sep`,"aria-hidden":`true`},`·`,-1)],64)):J(`v-if`,!0),x(`span`,null,D(a.relativeTimeFromIso(a.cardTime(t))),1)],8,_o)])],40,ro))),128)),a.listRows.length===0?(K(),S(`tr`,bo,[x(`td`,xo,D(a.$t(`@WORKBENCH:暂无任务`)),1)])):J(`v-if`,!0)])])])],2112)),J(`
210
210
  看图器(点封面 / 列表里那枚「N 张图」打开)。
211
211
 
212
212
  复用 element-plus 的 el-image-viewer,而不是自己糊一个遮罩:
@@ -222,8 +222,8 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
222
222
  默认 undefined = 关闭 —— 关掉的话遮罩会嵌在 .kb 里,被看板的滚动容器裁掉。
223
223
  也不要再在外面套一层 <teleport to="body">:嵌套 Teleport 在 2.11.x 下会让
224
224
  组件挂不上(AttachmentZone 那边踩过并留了注释)。
225
- `),a.imageViewer?(K(),r(c,{key:2,"url-list":a.imageViewer.urls,"initial-index":a.imageViewer.index,"hide-on-click-modal":!0,teleported:!0,onClose:a.closeImages},null,8,[`url-list`,`initial-index`])):J(`v-if`,!0)])}var mo=Z(Qi,[[`render`,po],[`__scopeId`,`data-v-0b8fc27c`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchKanban.vue`]]);c();var ho=f({__name:`TaskExecutorPicker`,props:{title:{type:String,required:!1}},setup(e,{expose:t}){t();let n=e,{active:r,availability:i,choose:a,executorModelText:s,executorModelTitle:c}=lt(),l=je();o(()=>{l.fetchExecutorModels()});function u(){return[n.title,c(r.value)].filter(Boolean).join(` · `)}let d={props:n,active:r,availability:i,choose:a,executorModelText:s,executorModelTitle:c,toolsStore:l,btnTitle:u,get ArrowDown(){return te},get Check(){return se},get $t(){return X},TaskExecutorIcon:Fe,get TASK_EXECUTOR_OPTIONS(){return ke},get taskExecutorName(){return Oe}};return Object.defineProperty(d,"__isScriptSetup",{enumerable:!1,value:!0}),d}});c(),R();var go=[`title`,`aria-label`],_o={class:`tep__btn-name`},vo={class:`tep__item`},yo={class:`tep__item-name`},bo=[`title`],xo={key:2,class:`tep__item-missing`};function So(t,i,a,o,s,c){let u=l,d=n,f=ge,p=b;return K(),r(p,{trigger:`click`,class:`tep`,onCommand:o.choose},{dropdown:L(()=>[e(f,null,{default:L(()=>[(K(!0),S(k,null,D(o.TASK_EXECUTOR_OPTIONS,t=>(K(),r(d,{key:t.id,command:t.id,disabled:!o.availability[t.id]},{default:L(()=>[x(`span`,vo,[e(o.TaskExecutorIcon,{executor:t.id,class:`tep__item-icon`},null,8,[`executor`]),x(`span`,yo,E(t.name),1),o.executorModelText(t.id)?(K(),S(`span`,{key:0,class:`tep__item-model`,title:o.executorModelTitle(t.id)},E(o.executorModelText(t.id)),9,bo)):J(`v-if`,!0),o.active===t.id?(K(),r(u,{key:1,class:`tep__item-check`},{default:L(()=>[e(o.Check)]),_:1})):o.availability[t.id]?J(`v-if`,!0):(K(),S(`span`,xo,E(o.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`,`disabled`]))),128))]),_:1})]),default:L(()=>[x(`button`,{type:`button`,class:`tep__btn`,title:o.btnTitle(),"aria-label":o.$t(`@WORKBENCH:任务执行器`)},[e(o.TaskExecutorIcon,{executor:o.active,class:`tep__btn-icon`},null,8,[`executor`]),x(`span`,_o,E(o.taskExecutorName(o.active)),1),e(u,{class:`tep__btn-caret`},{default:L(()=>[e(o.ArrowDown)]),_:1})],8,go)]),_:1},8,[`onCommand`])}var Co=Z(ho,[[`render`,So],[`__scopeId`,`data-v-7674ee77`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/TaskExecutorPicker.vue`]]);c(),V();var wo=f({__name:`AgentChatSurface`,props:{title:{type:String,required:!1},active:{type:Boolean,required:!1},allowDispatch:{type:Boolean,required:!1},dispatchUseDefaultPrompt:{type:Boolean,required:!1},placeholder:{type:String,required:!1},gitBranch:{type:[String,null],required:!1}},setup(e,{expose:n}){n();let r=e,{active:i}=lt(),a=Ae(),{theme:s}=Ue(),c=Y(()=>s.value===`dark`?`dark`:`light`),{sessions:l,sessionsLoading:u,currentSessionId:d,messages:f,displayMessages:p,isStreaming:m,questionPanel:h,answeringQuestion:g,isSessionGenerating:_,currentEngine:v,pendingEngine:y,isEngineLocked:b,pickEngine:x,loadSessions:S,loadSession:C,deleteSession:ee,renameSession:w,newSession:T,sendMessage:E,retryTurn:te,answerQuestion:D,stop:ne,inputContextUsage:O,queuedMessages:k,queuePaused:re,removeQueuedMessage:A,flushQueued:j,silentMs:M}=it(),ie=Y(()=>b.value?v.value:y.value);function ae(e){b.value||x(e)}let oe=Y(()=>{let e=a.models.find(e=>e.isDefault);return e&&(e.name||e.model)||``}),se=Y(()=>r.allowDispatch!==!1&&ie.value!==`gai`),ce=Y(()=>Je(l.value,_)),le=qe(),N=et(),ue=nt(),F=Y(()=>ce.value.find(e=>e.id===d.value)?.title||``),L=P(null),{width:R,narrow:z}=st(L),B=P(`chat`),{convListCollapsed:V,setConvListCollapsed:H}=ht(),de=Y(()=>!z.value&&V.value),W=P(null);function G(e=!0){W.value?.scrollToBottom?.(e)}async function K(e){let n=a.aiRequestBudget?.maxUserChars||0;n>0&&e.text.length>n&&I.warning(X(`@WORKBENCH:消息较长({n} 字符),超出部分会被省略后进入上下文 —— 大材料建议存成文件,在消息里给出文件路径`,{n:e.text.length.toLocaleString()})),await E(e.text,e.files,{allowDispatch:r.allowDispatch===!0,dispatchExecutor:i.value,dispatchUseDefaultPrompt:r.dispatchUseDefaultPrompt!==!1}),await t(),G()}function fe(e){C(e),B.value=`chat`}function pe(){T(),B.value=`chat`}U(()=>f.value.length,()=>{t(()=>G(!1))}),U(()=>r.active,e=>{e&&(S().catch(()=>{}),t(()=>G(!1)))}),U(z,e=>{e||(B.value=`chat`)}),o(()=>{S().catch(()=>{}),t(()=>G(!1))});let q={props:r,executor:i,configStore:a,theme:s,chatTheme:c,sessions:l,sessionsLoading:u,currentSessionId:d,messages:f,displayMessages:p,isStreaming:m,questionPanel:h,answeringQuestion:g,isSessionGenerating:_,currentEngine:v,pendingEngine:y,isEngineLocked:b,pickEngine:x,loadSessions:S,loadSession:C,deleteSession:ee,renameSession:w,newSession:T,sendMessage:E,retryTurn:te,answerQuestion:D,stop:ne,inputContextUsage:O,queuedMessages:k,queuePaused:re,removeQueuedMessage:A,flushQueued:j,silentMs:M,displayEngine:ie,onEngineSelect:ae,inputModelName:oe,engineCantDispatch:se,conversationItems:ce,conversationLabels:le,questionLabels:N,queueLabels:ue,currentSessionTitle:F,rootRef:L,width:R,narrow:z,page:B,convListCollapsed:V,setConvListCollapsed:H,convsCollapsed:de,chatRef:W,scrollToBottom:G,onSend:K,onSelectSession:fe,onNewSession:pe,get $t(){return X},get ChatContainer(){return xe},get ChatInput(){return Se},get ConversationList(){return Te},get AGENT_UPLOAD_ACCEPT(){return Ze},get agentEngineName(){return Qe},get AGENT_ASSISTANT_NAME(){return $e},get AGENT_ASSISTANT_AVATAR(){return rt},get MESSAGE_RAIL_CONFIG(){return Xe},get MESSAGE_META_CONFIG(){return tt},AgentEngineSelector:ot,TaskExecutorPicker:Co,CopySessionButton:ut,ChatSilenceBadge:mt};return Object.defineProperty(q,"__isScriptSetup",{enumerable:!1,value:!0}),q}});c(),R(),W();var To={ref:`rootRef`,class:`acs`},Eo={class:`acs__head`},Do=[`title`,`aria-label`],Oo={class:`acs__title`},ko=[`title`,`aria-label`],Ao={class:`acs__convs`},jo={class:`acs__chat`},Mo=[`data-theme`],No={key:0,class:`acs__foot`},Po={key:0,class:`acs__notice`},Fo={class:`acs__foot-label`},Io={class:`acs__foot-hint`};function Lo(t,n,i,a,o,s){return K(),S(`div`,To,[x(`div`,Eo,[J(` 窄屏的列表页:整条头让给「返回对话 + 标题」 `),a.narrow&&a.page===`list`?(K(),S(`button`,{key:0,type:`button`,class:`acs__icon-btn`,title:a.$t(`@EDITOR:返回对话`),"aria-label":a.$t(`@EDITOR:返回对话`),onClick:n[0]||=e=>a.page=`chat`},[...n[2]||=[x(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[x(`line`,{x1:`19`,y1:`12`,x2:`5`,y2:`12`}),x(`polyline`,{points:`12 19 5 12 12 5`})],-1)]],8,Do)):J(`v-if`,!0),x(`span`,Oo,E(i.title||a.$t(`@WORKBENCH:g ai 对话`)),1),n[4]||=x(`span`,{class:`acs__spacer`},null,-1),J(` 本轮静默:与「智能体」页头部同一枚(等回答时不算静默,见组件文件头) `),e(a.ChatSilenceBadge,{class:`acs__silence`,"silent-ms":a.silentMs,streaming:a.isStreaming&&!a.questionPanel},null,8,[`silent-ms`,`streaming`]),J(` 引擎切换:与「智能体」视图 / 编辑器面板同一个选择器(唯一那份实现)。
226
- 宽屏对话区一直在,所以常驻;窄屏只在对话页出现 —— 列表页摆它只会挤占标题。 `),!a.narrow||a.page===`chat`?(K(),r(a.AgentEngineSelector,{key:1,class:`acs__engine`,engine:a.displayEngine,locked:a.isEngineLocked,onSelect:a.onEngineSelect},null,8,[`engine`,`locked`])):J(`v-if`,!0),J(` 复制整条会话:只有对话页才有"当前这条会话"可复制(列表页连引擎选择器都不摆) `),!a.narrow||a.page===`chat`?(K(),r(a.CopySessionButton,{key:2,class:`acs__copy`,messages:a.messages,title:a.currentSessionTitle,engine:a.agentEngineName(a.displayEngine)},null,8,[`messages`,`title`,`engine`])):J(`v-if`,!0),J(` 会话列表按钮:只有"列表是独立一页"时才需要它(宽屏列表就在旁边) `),a.narrow&&a.page===`chat`?(K(),S(`button`,{key:3,type:`button`,class:`acs__icon-btn`,title:a.$t(`@EDITOR:会话列表`),"aria-label":a.$t(`@EDITOR:会话列表`),onClick:n[1]||=e=>a.page=`list`},[...n[3]||=[m(`<svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" data-v-9e75d420><line x1="8" y1="6" x2="21" y2="6" data-v-9e75d420></line><line x1="8" y1="12" x2="21" y2="12" data-v-9e75d420></line><line x1="8" y1="18" x2="21" y2="18" data-v-9e75d420></line><line x1="3" y1="6" x2="3.01" y2="6" data-v-9e75d420></line><line x1="3" y1="12" x2="3.01" y2="12" data-v-9e75d420></line><line x1="3" y1="18" x2="3.01" y2="18" data-v-9e75d420></line></svg>`,1)]],8,ko)):J(`v-if`,!0)]),x(`div`,{class:w([`acs__body`,{"is-wide":!a.narrow,"is-convs-collapsed":a.convsCollapsed}])},[J(` 会话历史:宽屏是常驻左列(可收起),窄屏是独享整页 `),A(x(`div`,Ao,[e(a.ConversationList,{"show-search":!0,items:a.conversationItems,"active-id":a.currentSessionId,loading:a.sessionsLoading,labels:a.conversationLabels,collapsible:!a.narrow,collapsed:a.convsCollapsed,"onUpdate:collapsed":a.setConvListCollapsed,onSelect:a.onSelectSession,onNew:a.onNewSession,onRename:a.renameSession,onDelete:a.deleteSession},null,8,[`items`,`active-id`,`loading`,`labels`,`collapsible`,`collapsed`,`onUpdate:collapsed`,`onRename`,`onDelete`])],512),[[H,!a.narrow||a.page===`list`]]),J(` 气泡区:输入框已经不在这里了(show-input=false),见下面常驻的那一条 `),A(x(`div`,jo,[e(a.ChatContainer,{ref:`chatRef`,"show-input":!1,messages:a.displayMessages,"assistant-name":a.AGENT_ASSISTANT_NAME,"assistant-avatar":a.AGENT_ASSISTANT_AVATAR,theme:a.chatTheme,question:a.questionPanel,"question-submitting":a.answeringQuestion,"question-labels":a.questionLabels,"plan-config":{labels:{title:a.$t(`@AGENT:计划`),raw:a.$t(`@AGENT:原始参数`)}},"message-rail-config":a.MESSAGE_RAIL_CONFIG,"message-meta-config":a.MESSAGE_META_CONFIG,onAnswer:a.answerQuestion,onRetry:a.retryTurn},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`question`,`question-submitting`,`question-labels`,`plan-config`,`message-rail-config`,`message-meta-config`,`onAnswer`,`onRetry`])],512),[[H,!a.narrow||a.page===`chat`]]),J(`
225
+ `),a.imageViewer?(K(),r(c,{key:2,"url-list":a.imageViewer.urls,"initial-index":a.imageViewer.index,"hide-on-click-modal":!0,teleported:!0,onClose:a.closeImages},null,8,[`url-list`,`initial-index`])):J(`v-if`,!0),J(` 右键「移动到其他项目」:全局一份,teleport 到 body(不被看板滚动容器裁掉) `),e(a.WorkbenchTaskMoveMenu,{visible:a.moveMenu.visible,x:a.moveMenu.x,y:a.moveMenu.y,task:a.moveMenu.task,projects:i.projects,onMove:a.onMoveToProject,onClose:n[10]||=e=>a.moveMenu.visible=!1},null,8,[`visible`,`x`,`y`,`task`,`projects`])])}var Co=Z(sa,[[`render`,So],[`__scopeId`,`data-v-0b8fc27c`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchKanban.vue`]]);c();var wo=f({__name:`TaskExecutorPicker`,props:{title:{type:String,required:!1}},setup(e,{expose:t}){t();let n=e,{active:r,availability:i,choose:a,executorModelText:s,executorModelTitle:c}=lt(),l=je();o(()=>{l.fetchExecutorModels()});function u(){return[n.title,c(r.value)].filter(Boolean).join(` · `)}let d={props:n,active:r,availability:i,choose:a,executorModelText:s,executorModelTitle:c,toolsStore:l,btnTitle:u,get ArrowDown(){return ee},get Check(){return se},get $t(){return X},TaskExecutorIcon:Fe,get TASK_EXECUTOR_OPTIONS(){return ke},get taskExecutorName(){return Oe}};return Object.defineProperty(d,"__isScriptSetup",{enumerable:!1,value:!0}),d}});c(),R();var To=[`title`,`aria-label`],Eo={class:`tep__btn-name`},Do={class:`tep__item`},Oo={class:`tep__item-name`},ko=[`title`],Ao={key:2,class:`tep__item-missing`};function jo(t,i,a,o,s,c){let u=l,d=n,f=ge,p=b;return K(),r(p,{trigger:`click`,class:`tep`,onCommand:o.choose},{dropdown:L(()=>[e(f,null,{default:L(()=>[(K(!0),S(k,null,O(o.TASK_EXECUTOR_OPTIONS,t=>(K(),r(d,{key:t.id,command:t.id,disabled:!o.availability[t.id]},{default:L(()=>[x(`span`,Do,[e(o.TaskExecutorIcon,{executor:t.id,class:`tep__item-icon`},null,8,[`executor`]),x(`span`,Oo,D(t.name),1),o.executorModelText(t.id)?(K(),S(`span`,{key:0,class:`tep__item-model`,title:o.executorModelTitle(t.id)},D(o.executorModelText(t.id)),9,ko)):J(`v-if`,!0),o.active===t.id?(K(),r(u,{key:1,class:`tep__item-check`},{default:L(()=>[e(o.Check)]),_:1})):o.availability[t.id]?J(`v-if`,!0):(K(),S(`span`,Ao,D(o.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`,`disabled`]))),128))]),_:1})]),default:L(()=>[x(`button`,{type:`button`,class:`tep__btn`,title:o.btnTitle(),"aria-label":o.$t(`@WORKBENCH:任务执行器`)},[e(o.TaskExecutorIcon,{executor:o.active,class:`tep__btn-icon`},null,8,[`executor`]),x(`span`,Eo,D(o.taskExecutorName(o.active)),1),e(u,{class:`tep__btn-caret`},{default:L(()=>[e(o.ArrowDown)]),_:1})],8,To)]),_:1},8,[`onCommand`])}var Mo=Z(wo,[[`render`,jo],[`__scopeId`,`data-v-7674ee77`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/TaskExecutorPicker.vue`]]);c(),V();var No=f({__name:`AgentChatSurface`,props:{title:{type:String,required:!1},active:{type:Boolean,required:!1},allowDispatch:{type:Boolean,required:!1},dispatchUseDefaultPrompt:{type:Boolean,required:!1},placeholder:{type:String,required:!1},gitBranch:{type:[String,null],required:!1}},setup(e,{expose:n}){n();let r=e,{active:i}=lt(),a=Ae(),{theme:s}=Ue(),c=Y(()=>s.value===`dark`?`dark`:`light`),{sessions:l,sessionsLoading:u,currentSessionId:d,messages:f,displayMessages:p,isStreaming:m,questionPanel:h,answeringQuestion:g,isSessionGenerating:_,currentEngine:v,pendingEngine:y,isEngineLocked:b,pickEngine:x,loadSessions:S,loadSession:C,deleteSession:w,renameSession:T,newSession:E,sendMessage:D,retryTurn:ee,answerQuestion:O,stop:te,inputContextUsage:ne,queuedMessages:k,queuePaused:re,removeQueuedMessage:A,flushQueued:j,silentMs:M}=it(),ie=Y(()=>b.value?v.value:y.value);function ae(e){b.value||x(e)}let oe=Y(()=>{let e=a.models.find(e=>e.isDefault);return e&&(e.name||e.model)||``}),se=Y(()=>r.allowDispatch!==!1&&ie.value!==`gai`),ce=Y(()=>Je(l.value,_)),le=qe(),N=et(),ue=nt(),F=Y(()=>ce.value.find(e=>e.id===d.value)?.title||``),L=P(null),{width:R,narrow:z}=st(L),B=P(`chat`),{convListCollapsed:V,setConvListCollapsed:H}=ht(),de=Y(()=>!z.value&&V.value),W=P(null);function G(e=!0){W.value?.scrollToBottom?.(e)}async function K(e){let n=a.aiRequestBudget?.maxUserChars||0;n>0&&e.text.length>n&&I.warning(X(`@WORKBENCH:消息较长({n} 字符),超出部分会被省略后进入上下文 —— 大材料建议存成文件,在消息里给出文件路径`,{n:e.text.length.toLocaleString()})),await D(e.text,e.files,{allowDispatch:r.allowDispatch===!0,dispatchExecutor:i.value,dispatchUseDefaultPrompt:r.dispatchUseDefaultPrompt!==!1}),await t(),G()}function fe(e){C(e),B.value=`chat`}function pe(){E(),B.value=`chat`}U(()=>f.value.length,()=>{t(()=>G(!1))}),U(()=>r.active,e=>{e&&(S().catch(()=>{}),t(()=>G(!1)))}),U(z,e=>{e||(B.value=`chat`)}),o(()=>{S().catch(()=>{}),t(()=>G(!1))});let q={props:r,executor:i,configStore:a,theme:s,chatTheme:c,sessions:l,sessionsLoading:u,currentSessionId:d,messages:f,displayMessages:p,isStreaming:m,questionPanel:h,answeringQuestion:g,isSessionGenerating:_,currentEngine:v,pendingEngine:y,isEngineLocked:b,pickEngine:x,loadSessions:S,loadSession:C,deleteSession:w,renameSession:T,newSession:E,sendMessage:D,retryTurn:ee,answerQuestion:O,stop:te,inputContextUsage:ne,queuedMessages:k,queuePaused:re,removeQueuedMessage:A,flushQueued:j,silentMs:M,displayEngine:ie,onEngineSelect:ae,inputModelName:oe,engineCantDispatch:se,conversationItems:ce,conversationLabels:le,questionLabels:N,queueLabels:ue,currentSessionTitle:F,rootRef:L,width:R,narrow:z,page:B,convListCollapsed:V,setConvListCollapsed:H,convsCollapsed:de,chatRef:W,scrollToBottom:G,onSend:K,onSelectSession:fe,onNewSession:pe,get $t(){return X},get ChatContainer(){return xe},get ChatInput(){return Se},get ConversationList(){return Te},get AGENT_UPLOAD_ACCEPT(){return Ze},get agentEngineName(){return Qe},get AGENT_ASSISTANT_NAME(){return $e},get AGENT_ASSISTANT_AVATAR(){return rt},get MESSAGE_RAIL_CONFIG(){return Xe},get MESSAGE_META_CONFIG(){return tt},AgentEngineSelector:ot,TaskExecutorPicker:Mo,CopySessionButton:ut,ChatSilenceBadge:mt};return Object.defineProperty(q,"__isScriptSetup",{enumerable:!1,value:!0}),q}});c(),R(),W();var Po={ref:`rootRef`,class:`acs`},Fo={class:`acs__head`},Io=[`title`,`aria-label`],Lo={class:`acs__title`},Ro=[`title`,`aria-label`],zo={class:`acs__convs`},Bo={class:`acs__chat`},Vo=[`data-theme`],Ho={key:0,class:`acs__foot`},Uo={key:0,class:`acs__notice`},Wo={class:`acs__foot-label`},Go={class:`acs__foot-hint`};function Ko(t,n,i,a,o,s){return K(),S(`div`,Po,[x(`div`,Fo,[J(` 窄屏的列表页:整条头让给「返回对话 + 标题」 `),a.narrow&&a.page===`list`?(K(),S(`button`,{key:0,type:`button`,class:`acs__icon-btn`,title:a.$t(`@EDITOR:返回对话`),"aria-label":a.$t(`@EDITOR:返回对话`),onClick:n[0]||=e=>a.page=`chat`},[...n[2]||=[x(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[x(`line`,{x1:`19`,y1:`12`,x2:`5`,y2:`12`}),x(`polyline`,{points:`12 19 5 12 12 5`})],-1)]],8,Io)):J(`v-if`,!0),x(`span`,Lo,D(i.title||a.$t(`@WORKBENCH:g ai 对话`)),1),n[4]||=x(`span`,{class:`acs__spacer`},null,-1),J(` 本轮静默:与「智能体」页头部同一枚(等回答时不算静默,见组件文件头) `),e(a.ChatSilenceBadge,{class:`acs__silence`,"silent-ms":a.silentMs,streaming:a.isStreaming&&!a.questionPanel},null,8,[`silent-ms`,`streaming`]),J(` 引擎切换:与「智能体」视图 / 编辑器面板同一个选择器(唯一那份实现)。
226
+ 宽屏对话区一直在,所以常驻;窄屏只在对话页出现 —— 列表页摆它只会挤占标题。 `),!a.narrow||a.page===`chat`?(K(),r(a.AgentEngineSelector,{key:1,class:`acs__engine`,engine:a.displayEngine,locked:a.isEngineLocked,onSelect:a.onEngineSelect},null,8,[`engine`,`locked`])):J(`v-if`,!0),J(` 复制整条会话:只有对话页才有"当前这条会话"可复制(列表页连引擎选择器都不摆) `),!a.narrow||a.page===`chat`?(K(),r(a.CopySessionButton,{key:2,class:`acs__copy`,messages:a.messages,title:a.currentSessionTitle,engine:a.agentEngineName(a.displayEngine)},null,8,[`messages`,`title`,`engine`])):J(`v-if`,!0),J(` 会话列表按钮:只有"列表是独立一页"时才需要它(宽屏列表就在旁边) `),a.narrow&&a.page===`chat`?(K(),S(`button`,{key:3,type:`button`,class:`acs__icon-btn`,title:a.$t(`@EDITOR:会话列表`),"aria-label":a.$t(`@EDITOR:会话列表`),onClick:n[1]||=e=>a.page=`list`},[...n[3]||=[m(`<svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" data-v-9e75d420><line x1="8" y1="6" x2="21" y2="6" data-v-9e75d420></line><line x1="8" y1="12" x2="21" y2="12" data-v-9e75d420></line><line x1="8" y1="18" x2="21" y2="18" data-v-9e75d420></line><line x1="3" y1="6" x2="3.01" y2="6" data-v-9e75d420></line><line x1="3" y1="12" x2="3.01" y2="12" data-v-9e75d420></line><line x1="3" y1="18" x2="3.01" y2="18" data-v-9e75d420></line></svg>`,1)]],8,Ro)):J(`v-if`,!0)]),x(`div`,{class:T([`acs__body`,{"is-wide":!a.narrow,"is-convs-collapsed":a.convsCollapsed}])},[J(` 会话历史:宽屏是常驻左列(可收起),窄屏是独享整页 `),A(x(`div`,zo,[e(a.ConversationList,{"show-search":!0,items:a.conversationItems,"active-id":a.currentSessionId,loading:a.sessionsLoading,labels:a.conversationLabels,collapsible:!a.narrow,collapsed:a.convsCollapsed,"onUpdate:collapsed":a.setConvListCollapsed,onSelect:a.onSelectSession,onNew:a.onNewSession,onRename:a.renameSession,onDelete:a.deleteSession},null,8,[`items`,`active-id`,`loading`,`labels`,`collapsible`,`collapsed`,`onUpdate:collapsed`,`onRename`,`onDelete`])],512),[[H,!a.narrow||a.page===`list`]]),J(` 气泡区:输入框已经不在这里了(show-input=false),见下面常驻的那一条 `),A(x(`div`,Bo,[e(a.ChatContainer,{ref:`chatRef`,"show-input":!1,messages:a.displayMessages,"assistant-name":a.AGENT_ASSISTANT_NAME,"assistant-avatar":a.AGENT_ASSISTANT_AVATAR,theme:a.chatTheme,question:a.questionPanel,"question-submitting":a.answeringQuestion,"question-labels":a.questionLabels,"plan-config":{labels:{title:a.$t(`@AGENT:计划`),raw:a.$t(`@AGENT:原始参数`)}},"message-rail-config":a.MESSAGE_RAIL_CONFIG,"message-meta-config":a.MESSAGE_META_CONFIG,onAnswer:a.answerQuestion,onRetry:a.retryTurn},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`question`,`question-submitting`,`question-labels`,`plan-config`,`message-rail-config`,`message-meta-config`,`onAnswer`,`onRetry`])],512),[[H,!a.narrow||a.page===`chat`]]),J(`
227
227
  输入框常驻:两种形态、两个页面都在最下方。
228
228
  它被拆到 ChatContainer 外面,所以 acu-root 与 data-theme 得自己套上:
229
229
  库把盒模型重置限定在 .acu-root 子树里,而 ChatInput 根节点是 div(不是 button),
@@ -234,27 +234,27 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
234
234
  容器还没宽度,占位文案被折成十几行,textarea 直接顶到 200px 上限并一直卡在那里
235
235
  (切走再切回才对)。宽度是 useNarrowPane 在 onMounted 里同步量到的,所以这里
236
236
  晚的只是一次重渲染,同一帧内就补上了,看不到闪烁。
237
- `),a.width>0?(K(),S(`div`,{key:0,class:`acs__composer acu-root`,"data-theme":a.chatTheme},[e(a.ChatInput,{generating:a.isStreaming,"allow-queue":!0,queued:a.queuedMessages,"queue-paused":a.queuePaused,"queue-labels":a.queueLabels,placeholder:i.placeholder||(a.isStreaming?a.$t(`@AGENT:生成中,发送后会排队,等本轮跑完自动接上…`):a.$t(`@AGENT:输入消息,Enter 发送`)),"upload-config":{accept:a.AGENT_UPLOAD_ACCEPT},"context-usage":a.inputContextUsage,"git-branch":a.props.gitBranch||void 0,model:a.inputModelName||void 0,onSend:a.onSend,onStop:a.stop,onUnqueue:a.removeQueuedMessage,onFlushQueued:a.flushQueued},null,8,[`generating`,`queued`,`queue-paused`,`queue-labels`,`placeholder`,`upload-config`,`context-usage`,`git-branch`,`model`,`onStop`,`onUnqueue`,`onFlushQueued`])],8,Mo)):J(`v-if`,!0)],2),J(` 底部:派发执行器。放在输入框下面而不是头部 —— 它修饰的是"派出去的活谁跑",
238
- 不是"我在跟谁聊",和引擎选择器挤在一行会让人分不清哪个管哪件事 `),i.allowDispatch&&a.page===`chat`?(K(),S(`div`,No,[a.engineCantDispatch?(K(),S(`p`,Po,E(a.$t(`@WORKBENCH:当前引擎「{name}」只能对话,不能派发任务 —— 切到内置 g ai 才能派活`,{name:a.agentEngineName(a.displayEngine)})),1)):(K(),S(k,{key:1},[x(`span`,Fo,E(a.$t(`@WORKBENCH:派发执行器`)),1),e(a.TaskExecutorPicker,{title:a.$t(`@WORKBENCH:它派出去的任务由这个执行器跑(与执行按钮的临时切换共用)`)},null,8,[`title`]),x(`span`,Io,E(a.$t(`@WORKBENCH:任务会落到看板,跑完有完成提示`)),1)],64))])):J(`v-if`,!0)],512)}var Ro=Z(wo,[[`render`,Lo],[`__scopeId`,`data-v-9e75d420`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/AgentChatSurface.vue`]]);c(),V();var zo=`wb.ocMode.v2`,Bo=`/api/workbench/orchestrator/attachments`,Vo=`wb.ocInputHeight.v2`,Ho=76,Uo=20,Wo=f({__name:`OrchestratorConsole`,props:{running:{type:Array,required:!0},selectedProject:{type:[Object,null],required:!0},dispatching:{type:Boolean,required:!0},todayDone:{type:Number,required:!0},collapsed:{type:Boolean,required:!1},defaultPrompt:{type:String,required:!1},projectPrompts:{type:Object,required:!1},reports:{type:Array,required:!1},reportIntervalMs:{type:Number,required:!1},generatingReport:{type:Boolean,required:!1},maxInstructionChars:{type:Number,required:!1}},emits:[`toggle-collapse`,`open-prompt-settings`,`generate-report`,`set-report-interval`,`locate-task`,`dispatch`],setup(e,{expose:n,emit:r}){let i=e,a=r,s=P(``),c=P(!0),l=P(!0),{active:u}=lt(),f=P((()=>{try{return localStorage.getItem(zo)===`chat`?`chat`:`command`}catch{return`command`}})());function p(e){f.value=e;try{localStorage.setItem(zo,e)}catch{}}let m=P([]),g=Y(()=>({kind:`draft`,list:m.value,replace:e=>{m.value=e}})),{isUploading:_,isImageAttachment:v,humanSize:b,onAttachmentPaste:x,onAttachmentDrop:S,removeAttachment:C,pickAttachmentFile:w}=dr(),T=Y(()=>_(`draft`)),E=P(!1);function D(e){e.stopPropagation(),x(e,g.value)}function O(e){E.value=!1,S(e,g.value)}function k(){w(g.value)}function re(e){C(g.value,e)}function A(){m.value=[]}function j(){s.value=``}n({clearAttachments:A,clearDraft:j});let M=Y(()=>i.selectedProject?.key||``),ie=Y(()=>(i.defaultPrompt||``).trim()),ae=Y(()=>{let e=M.value;return e?(i.projectPrompts?.[e]?.prompt||``).trim():``}),oe=Y(()=>Object.values(i.projectPrompts||{}).some(e=>(e?.prompt||``).trim().length>0)),se=Y(()=>!!ie.value||oe.value),ce=Y(()=>{let e=!!ie.value,t=M.value?ae.value?`project`:`none`:oe.value?`target`:`none`;return X(e&&t===`project`?`@WORKBENCH:全局 + 本项目`:e&&t===`target`?`@WORKBENCH:全局 + 落点项目`:e?`@WORKBENCH:全局`:t===`project`?`@WORKBENCH:本项目`:t===`target`?`@WORKBENCH:落点项目`:`@WORKBENCH:未设置`)}),le=Y(()=>s.value.trim().length),N=Y(()=>i.maxInstructionChars||1e5),F=Y(()=>le.value>N.value),I=Y(()=>!F.value&&le.value>=N.value*.9),L=Y(()=>s.value.trim().length>0&&!i.dispatching&&!T.value&&!F.value);function R(){L.value&&a(`dispatch`,{text:s.value.trim(),autoRun:c.value,attachments:m.value,projectPath:i.selectedProject?i.selectedProject.path:``,useDefaultPrompt:l.value,executor:u.value})}function z(e){e.isComposing||e.keyCode===229||e.key!==`Enter`||e.shiftKey||(e.preventDefault(),R())}function B(){try{let e=localStorage.getItem(Vo);if(!e)return null;let t=Number(e);return Number.isFinite(t)&&t>=Ho?Math.round(t):null}catch{return null}}let V=P(null),H=P(B()),de=Y(()=>{let e={};return H.value&&(e.height=`${H.value}px`),e}),W=null,G=!1,K=!0;function fe(e){let t=V.value;if(!t)return;let n=t.getBoundingClientRect();G=n.right-e.clientX<=Uo&&n.bottom-e.clientY<=Uo}function pe(){G=!1}function q(e){let t=Math.round(e.offsetHeight);if(!(t<Ho||t===H.value)){H.value=t;try{localStorage.setItem(Vo,String(t))}catch{}}}o(()=>{let e=V.value;e&&(window.addEventListener(`mouseup`,pe),!(typeof ResizeObserver>`u`)&&(W=new ResizeObserver(()=>{if(K){K=!1;return}let t=parseFloat(getComputedStyle(e).maxHeight),n=Number.isFinite(t)&&e.offsetHeight>=t-1;(G||!n)&&q(e)}),W.observe(e)))}),ee(()=>{window.removeEventListener(`mouseup`,pe),W?.disconnect(),W=null});let me=P(null),ge=Y(()=>(i.running||[]).length),J=Y(()=>{let e=i.running||[];return{job:new Set(e.map(e=>e.jobId).filter(Boolean)),task:new Set(e.map(e=>e.taskId).filter(Boolean))}});function _e(e){if(!e)return!1;let t=J.value;return(e.tasks||[]).some(e=>e.jobId&&t.job.has(e.jobId)||!e.jobId&&!!e.taskId&&t.task.has(e.taskId))}let ve=Y(()=>(i.reports||[]).find(_e)||null),ye=Y(()=>{let e=be.value;if(!e)return null;let t=e.tasks||[],n=J.value;return(t.find(e=>e.jobId&&n.job.has(e.jobId)||!e.jobId&&!!e.taskId&&n.task.has(e.taskId))||t.find(e=>!!e.taskId))?.taskId||null}),be=Y(()=>{let e=i.reports||[];if(!e.length)return null;if(me.value){let t=e.find(e=>e.id===me.value);if(t)return t}return ve.value}),xe=Y(()=>!!be.value&&!_e(be.value)),Se=Y(()=>(i.reports||[]).length?ge.value>0?X(`@WORKBENCH:这批任务还没有进度报告`):X(`@WORKBENCH:当前没有正在执行的任务`):X(`@WORKBENCH:暂无进度报告`)),Ce=Y(()=>(i.reports||[]).length?X(`@WORKBENCH:最新那份报告讲的任务已经跑完了,要回看可以从历史报告里点开`):``);function we(e){me.value=e.id}let Te=P(null),Z=P(!0),Ee=P(!1);function De(){let e=Te.value;e&&!Z.value&&(Ee.value=e.scrollHeight-e.clientHeight>2)}function Oe(){Z.value=!Z.value,Z.value||t(De)}let ke=null;U(Te,e=>{ke?.disconnect(),ke=null,e&&(ke=new ResizeObserver(()=>De()),ke.observe(e))}),ee(()=>{ke?.disconnect(),ke=null}),U(()=>be.value?.id,()=>{Z.value=!0,Ee.value=!1,t(De)});function Ae(e){let t=Ne(e.percent);return t===null?``:t+`%`}let je=Y(()=>Ne(be.value?.percent));function Me(e){let t=String(e.text||``).replace(/\s+/g,` `).trim();return t?t.length>42?t.slice(0,42)+`…`:t:e.errorCode?X(Q(e.errorCode)):X(`@WORKBENCH:当时没有任务在执行`)}function Pe(e){return e.errorCode?X(Q(e.errorCode)):e.tasks.length?X(`@WORKBENCH:模型没有返回内容`):X(`@WORKBENCH:生成这份报告时没有任务在执行`)}function Fe(e){let t=e.target,n=Number(t.value);He.includes(n)&&a(`set-report-interval`,n)}let Ie=Y(()=>{let e=i.selectedProject;if(!e)return[];let t=[];if(e.exists===!1)return t.push({label:X(`@WORKBENCH:工作区`),value:X(`@WORKBENCH:目录不存在`),tone:`danger`}),t;let n=e.git;return!n||n.isGitRepo===null?(t.push({label:X(`@WORKBENCH:Git 状态`),value:X(`@WORKBENCH:未知`),tone:``}),t):n.isGitRepo?(t.push({label:X(`@WORKBENCH:分支`),value:n.detached?X(`@WORKBENCH:游离 HEAD`):n.branch||X(`@WORKBENCH:未知`),tone:``}),t.push({label:X(`@WORKBENCH:工作区`),value:n.changed>0?X(`@WORKBENCH:未提交 {n} 项`,{n:n.changed}):X(`@WORKBENCH:干净`),tone:n.changed>0?`warn`:``}),n.hasUpstream&&(n.ahead>0||n.behind>0)&&t.push({label:X(`@WORKBENCH:与上游`),value:X(`@WORKBENCH:领先 {ahead} / 落后 {behind}`,{ahead:n.ahead,behind:n.behind}),tone:n.behind>0?`warn`:``}),t):(t.push({label:X(`@WORKBENCH:Git 状态`),value:X(`@WORKBENCH:不是 Git 仓库`),tone:``}),t)}),Le={history:`wb.ocHistoryOpen.v1`,git:`wb.ocGitOpen.v1`};function ze(e){try{return localStorage.getItem(e)===`1`}catch{return!1}}let Be=P(ze(Le.history)),$=P(ze(Le.git));function Ue(e){let t=e===`history`?Be:$;t.value=!t.value;try{localStorage.setItem(Le[e],t.value?`1`:`0`)}catch{}}function Ge(){Be.value||Ue(`history`)}let qe={props:i,emit:a,draft:s,autoRun:c,useDefaultPrompt:l,selectedExecutor:u,MODE_KEY:zo,mode:f,setMode:p,draftAttachments:m,DRAFT_RAW_BASE:Bo,attachTarget:g,isUploading:_,isImageAttachment:v,humanSize:b,onAttachmentPaste:x,onAttachmentDrop:S,removeAttachment:C,pickAttachmentFile:w,attachBusy:T,attachDragging:E,onPaste:D,onDrop:O,onPickAttachment:k,onRemoveAttachment:re,clearAttachments:A,clearDraft:j,projectKey:M,globalPromptText:ie,projectPromptText:ae,anyProjectPrompt:oe,anyPromptConfigured:se,promptStateLabel:ce,draftChars:le,charLimit:N,overLimit:F,nearLimit:I,canSend:L,send:R,onInputKeydown:z,INPUT_H_KEY:Vo,OC_INPUT_MIN_H:Ho,readInputH:B,inputRef:V,inputH:H,inputStyle:de,get inputRO(){return W},set inputRO(e){W=e},get inputDragging(){return G},set inputDragging(e){G=e},get inputROFirst(){return K},set inputROFirst(e){K=e},INPUT_GRIP_PX:Uo,onInputMouseDown:fe,onWindowMouseUp:pe,commitInputH:q,selectedReportId:me,runningCount:ge,runningIds:J,reportIsLive:_e,liveReport:ve,locateTaskId:ye,currentReport:be,currentReportStale:xe,idleHint:Se,idleHintTitle:Ce,pickReport:we,textEl:Te,textExpanded:Z,textClamped:Ee,measureText:De,toggleText:Oe,get textRO(){return ke},set textRO(e){ke=e},historyPct:Ae,currentPercent:je,reportBrief:Me,reportNotice:Pe,onIntervalChange:Fe,gitSummary:Ie,SECT_KEY:Le,readSectOpen:ze,historyOpen:Be,gitOpen:$,toggleSect:Ue,reviewHistory:Ge,gitBrief:Y(()=>Ie.value.slice(0,2).map(e=>e.value).join(` · `)),get $t(){return X},get Promotion(){return d},get Expand(){return ue},get Fold(){return he},get Refresh(){return y},get ArrowDown(){return te},get ArrowRight(){return ne},get LocationInformation(){return h},get clockFromIso(){return yt},get relativeTimeFromIso(){return vt},get REPORT_INTERVAL_OPTIONS_MS(){return He},get REPORT_PERCENT_HINT_KEY(){return Ve},get REPORT_PERCENT_LABEL_KEY(){return We},get reportIntervalLabelKey(){return Ke},get reportIntervalLabelParams(){return Re},AttachmentZone:It,AgentChatSurface:Ro,TaskExecutorPicker:Co};return Object.defineProperty(qe,"__isScriptSetup",{enumerable:!1,value:!0}),qe}});c(),R(),W();var Go=[`title`,`aria-label`],Ko={class:`oc__rail-text`},qo={class:`oc__head`},Jo={class:`oc__title`},Yo=[`title`,`aria-label`],Xo=[`aria-label`],Zo=[`aria-selected`],Qo=[`aria-selected`],$o={class:`oc__report-head`},es={class:`oc__panel-title`},ts=[`value`,`title`,`aria-label`],ns=[`value`],rs=[`disabled`,`title`],is={class:`oc__report-list`},as={key:0,class:`rp`},os={class:`rp__head`},ss=[`title`],cs={class:`rp__count`},ls={class:`rp__time`},us=[`title`,`aria-label`],ds=[`title`],fs=[`aria-valuenow`,`aria-label`],ps={class:`rp__percent`},ms={class:`rp__percent-tag`},hs={key:1,class:`rp__body`},gs=[`title`],_s=[`title`],vs={class:`oc-empty__text`},ys=[`aria-expanded`,`title`],bs={class:`oc__sect-title`},xs={class:`oc__sect-meta`},Ss={class:`oc__sect-brief`},Cs={class:`oc__history-list`},ws=[`onClick`],Ts={class:`oc__history-time`},Es={class:`oc__history-pct`},Ds={class:`oc__history-sum`},Os=[`aria-expanded`,`title`],ks={class:`oc__sect-title`},As={class:`oc__sect-meta`},js={class:`oc__git-name`},Ms={key:0,class:`oc__sect-brief`},Ns={class:`oc__git-list`},Ps={class:`oc__git-label`},Fs={class:`oc__git-label`},Is={class:`oc__git-value`},Ls={class:`oc__git-label`},Rs={class:`oc__git-value`},zs=[`placeholder`],Bs={key:0},Vs={key:1},Hs={class:`oc__compose-foot`},Us=[`disabled`,`title`,`aria-label`],Ws=[`title`,`aria-label`],Gs=[`title`],Ks=[`title`],qs={class:`oc__foot-label`},Js=[`disabled`],Ys={class:`oc__hint`};function Xs(t,n,i,a,o,s){let c=l;return K(),S(`aside`,{class:w([`oc`,{"is-collapsed":i.collapsed,"is-report-empty":a.mode===`command`&&!i.collapsed&&!a.currentReport}])},[J(` 折叠后的收纳条:只剩一枚展开按钮 + 竖排标题,宽度收到 32px。
239
- 折叠不是"把宽度压成 0"—— 那样就再没有能点回来的地方了。 `),i.collapsed?(K(),S(`button`,{key:0,type:`button`,class:`oc__rail`,title:a.$t(`@WORKBENCH:展开主 Agent 控制台`),"aria-label":a.$t(`@WORKBENCH:展开主 Agent 控制台`),"aria-expanded":!1,onClick:n[0]||=e=>a.emit(`toggle-collapse`)},[e(c,{class:`oc__rail-icon`},{default:L(()=>[e(a.Fold)]),_:1}),x(`span`,Ko,E(a.$t(`@WORKBENCH:主 Agent 控制台`)),1)],8,Go)):J(`v-if`,!0),J(` 折叠时这几块整体隐藏而不是销毁(v-show 而不是 v-if):
240
- 草稿指令和已贴的附件都还留着,展开回来能接着发 `),A(x(`header`,qo,[x(`h3`,Jo,E(a.$t(`@WORKBENCH:主 Agent 控制台`)),1),x(`button`,{type:`button`,class:`oc__collapse`,title:a.$t(`@WORKBENCH:收起主 Agent 控制台`),"aria-label":a.$t(`@WORKBENCH:收起主 Agent 控制台`),"aria-expanded":!0,onClick:n[1]||=e=>a.emit(`toggle-collapse`)},[e(c,null,{default:L(()=>[e(a.Expand)]),_:1})],8,Yo)],512),[[H,!i.collapsed]]),J(` 工作方式:对话 = g ai 边聊边派(可以多轮、可以反问你);指令 = 你自己敲一句话派一条。
237
+ `),a.width>0?(K(),S(`div`,{key:0,class:`acs__composer acu-root`,"data-theme":a.chatTheme},[e(a.ChatInput,{generating:a.isStreaming,"allow-queue":!0,queued:a.queuedMessages,"queue-paused":a.queuePaused,"queue-labels":a.queueLabels,placeholder:i.placeholder||(a.isStreaming?a.$t(`@AGENT:生成中,发送后会排队,等本轮跑完自动接上…`):a.$t(`@AGENT:输入消息,Enter 发送`)),"upload-config":{accept:a.AGENT_UPLOAD_ACCEPT},"context-usage":a.inputContextUsage,"git-branch":a.props.gitBranch||void 0,model:a.inputModelName||void 0,onSend:a.onSend,onStop:a.stop,onUnqueue:a.removeQueuedMessage,onFlushQueued:a.flushQueued},null,8,[`generating`,`queued`,`queue-paused`,`queue-labels`,`placeholder`,`upload-config`,`context-usage`,`git-branch`,`model`,`onStop`,`onUnqueue`,`onFlushQueued`])],8,Vo)):J(`v-if`,!0)],2),J(` 底部:派发执行器。放在输入框下面而不是头部 —— 它修饰的是"派出去的活谁跑",
238
+ 不是"我在跟谁聊",和引擎选择器挤在一行会让人分不清哪个管哪件事 `),i.allowDispatch&&a.page===`chat`?(K(),S(`div`,Ho,[a.engineCantDispatch?(K(),S(`p`,Uo,D(a.$t(`@WORKBENCH:当前引擎「{name}」只能对话,不能派发任务 —— 切到内置 g ai 才能派活`,{name:a.agentEngineName(a.displayEngine)})),1)):(K(),S(k,{key:1},[x(`span`,Wo,D(a.$t(`@WORKBENCH:派发执行器`)),1),e(a.TaskExecutorPicker,{title:a.$t(`@WORKBENCH:它派出去的任务由这个执行器跑(与执行按钮的临时切换共用)`)},null,8,[`title`]),x(`span`,Go,D(a.$t(`@WORKBENCH:任务会落到看板,跑完有完成提示`)),1)],64))])):J(`v-if`,!0)],512)}var qo=Z(No,[[`render`,Ko],[`__scopeId`,`data-v-9e75d420`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/AgentChatSurface.vue`]]);c(),V();var Jo=`wb.ocMode.v2`,Yo=`/api/workbench/orchestrator/attachments`,Xo=`wb.ocInputHeight.v2`,Zo=76,Qo=20,$o=f({__name:`OrchestratorConsole`,props:{running:{type:Array,required:!0},selectedProject:{type:[Object,null],required:!0},dispatching:{type:Boolean,required:!0},todayDone:{type:Number,required:!0},collapsed:{type:Boolean,required:!1},defaultPrompt:{type:String,required:!1},projectPrompts:{type:Object,required:!1},reports:{type:Array,required:!1},reportIntervalMs:{type:Number,required:!1},generatingReport:{type:Boolean,required:!1},maxInstructionChars:{type:Number,required:!1}},emits:[`toggle-collapse`,`open-prompt-settings`,`generate-report`,`set-report-interval`,`locate-task`,`dispatch`],setup(e,{expose:n,emit:r}){let i=e,a=r,s=P(``),c=P(!0),l=P(!0),{active:u}=lt(),f=P((()=>{try{return localStorage.getItem(Jo)===`chat`?`chat`:`command`}catch{return`command`}})());function p(e){f.value=e;try{localStorage.setItem(Jo,e)}catch{}}let m=P([]),g=Y(()=>({kind:`draft`,list:m.value,replace:e=>{m.value=e}})),{isUploading:_,isImageAttachment:v,humanSize:b,onAttachmentPaste:x,onAttachmentDrop:S,removeAttachment:C,pickAttachmentFile:T}=dr(),E=Y(()=>_(`draft`)),D=P(!1);function O(e){e.stopPropagation(),x(e,g.value)}function ne(e){D.value=!1,S(e,g.value)}function k(){T(g.value)}function re(e){C(g.value,e)}function A(){m.value=[]}function j(){s.value=``}n({clearAttachments:A,clearDraft:j});let M=Y(()=>i.selectedProject?.key||``),ie=Y(()=>(i.defaultPrompt||``).trim()),ae=Y(()=>{let e=M.value;return e?(i.projectPrompts?.[e]?.prompt||``).trim():``}),oe=Y(()=>Object.values(i.projectPrompts||{}).some(e=>(e?.prompt||``).trim().length>0)),se=Y(()=>!!ie.value||oe.value),ce=Y(()=>{let e=!!ie.value,t=M.value?ae.value?`project`:`none`:oe.value?`target`:`none`;return X(e&&t===`project`?`@WORKBENCH:全局 + 本项目`:e&&t===`target`?`@WORKBENCH:全局 + 落点项目`:e?`@WORKBENCH:全局`:t===`project`?`@WORKBENCH:本项目`:t===`target`?`@WORKBENCH:落点项目`:`@WORKBENCH:未设置`)}),le=Y(()=>s.value.trim().length),N=Y(()=>i.maxInstructionChars||1e5),F=Y(()=>le.value>N.value),I=Y(()=>!F.value&&le.value>=N.value*.9),L=Y(()=>s.value.trim().length>0&&!i.dispatching&&!E.value&&!F.value);function R(){L.value&&a(`dispatch`,{text:s.value.trim(),autoRun:c.value,attachments:m.value,projectPath:i.selectedProject?i.selectedProject.path:``,useDefaultPrompt:l.value,executor:u.value})}function z(e){e.isComposing||e.keyCode===229||e.key!==`Enter`||e.shiftKey||(e.preventDefault(),R())}function B(){try{let e=localStorage.getItem(Xo);if(!e)return null;let t=Number(e);return Number.isFinite(t)&&t>=Zo?Math.round(t):null}catch{return null}}let V=P(null),H=P(B()),de=Y(()=>{let e={};return H.value&&(e.height=`${H.value}px`),e}),W=null,G=!1,K=!0;function fe(e){let t=V.value;if(!t)return;let n=t.getBoundingClientRect();G=n.right-e.clientX<=Qo&&n.bottom-e.clientY<=Qo}function pe(){G=!1}function q(e){let t=Math.round(e.offsetHeight);if(!(t<Zo||t===H.value)){H.value=t;try{localStorage.setItem(Xo,String(t))}catch{}}}o(()=>{let e=V.value;e&&(window.addEventListener(`mouseup`,pe),!(typeof ResizeObserver>`u`)&&(W=new ResizeObserver(()=>{if(K){K=!1;return}let t=parseFloat(getComputedStyle(e).maxHeight),n=Number.isFinite(t)&&e.offsetHeight>=t-1;(G||!n)&&q(e)}),W.observe(e)))}),w(()=>{window.removeEventListener(`mouseup`,pe),W?.disconnect(),W=null});let me=P(null),ge=Y(()=>(i.running||[]).length),J=Y(()=>{let e=i.running||[];return{job:new Set(e.map(e=>e.jobId).filter(Boolean)),task:new Set(e.map(e=>e.taskId).filter(Boolean))}});function _e(e){if(!e)return!1;let t=J.value;return(e.tasks||[]).some(e=>e.jobId&&t.job.has(e.jobId)||!e.jobId&&!!e.taskId&&t.task.has(e.taskId))}let ve=Y(()=>(i.reports||[]).find(_e)||null),ye=Y(()=>{let e=be.value;if(!e)return null;let t=e.tasks||[],n=J.value;return(t.find(e=>e.jobId&&n.job.has(e.jobId)||!e.jobId&&!!e.taskId&&n.task.has(e.taskId))||t.find(e=>!!e.taskId))?.taskId||null}),be=Y(()=>{let e=i.reports||[];if(!e.length)return null;if(me.value){let t=e.find(e=>e.id===me.value);if(t)return t}return ve.value}),xe=Y(()=>!!be.value&&!_e(be.value)),Se=Y(()=>(i.reports||[]).length?ge.value>0?X(`@WORKBENCH:这批任务还没有进度报告`):X(`@WORKBENCH:当前没有正在执行的任务`):X(`@WORKBENCH:暂无进度报告`)),Ce=Y(()=>(i.reports||[]).length?X(`@WORKBENCH:最新那份报告讲的任务已经跑完了,要回看可以从历史报告里点开`):``);function we(e){me.value=e.id}let Te=P(null),Z=P(!0),Ee=P(!1);function De(){let e=Te.value;e&&!Z.value&&(Ee.value=e.scrollHeight-e.clientHeight>2)}function Oe(){Z.value=!Z.value,Z.value||t(De)}let ke=null;U(Te,e=>{ke?.disconnect(),ke=null,e&&(ke=new ResizeObserver(()=>De()),ke.observe(e))}),w(()=>{ke?.disconnect(),ke=null}),U(()=>be.value?.id,()=>{Z.value=!0,Ee.value=!1,t(De)});function Ae(e){let t=Ne(e.percent);return t===null?``:t+`%`}let je=Y(()=>Ne(be.value?.percent));function Me(e){let t=String(e.text||``).replace(/\s+/g,` `).trim();return t?t.length>42?t.slice(0,42)+`…`:t:e.errorCode?X(Q(e.errorCode)):X(`@WORKBENCH:当时没有任务在执行`)}function Pe(e){return e.errorCode?X(Q(e.errorCode)):e.tasks.length?X(`@WORKBENCH:模型没有返回内容`):X(`@WORKBENCH:生成这份报告时没有任务在执行`)}function Fe(e){let t=e.target,n=Number(t.value);He.includes(n)&&a(`set-report-interval`,n)}let Ie=Y(()=>{let e=i.selectedProject;if(!e)return[];let t=[];if(e.exists===!1)return t.push({label:X(`@WORKBENCH:工作区`),value:X(`@WORKBENCH:目录不存在`),tone:`danger`}),t;let n=e.git;return!n||n.isGitRepo===null?(t.push({label:X(`@WORKBENCH:Git 状态`),value:X(`@WORKBENCH:未知`),tone:``}),t):n.isGitRepo?(t.push({label:X(`@WORKBENCH:分支`),value:n.detached?X(`@WORKBENCH:游离 HEAD`):n.branch||X(`@WORKBENCH:未知`),tone:``}),t.push({label:X(`@WORKBENCH:工作区`),value:n.changed>0?X(`@WORKBENCH:未提交 {n} 项`,{n:n.changed}):X(`@WORKBENCH:干净`),tone:n.changed>0?`warn`:``}),n.hasUpstream&&(n.ahead>0||n.behind>0)&&t.push({label:X(`@WORKBENCH:与上游`),value:X(`@WORKBENCH:领先 {ahead} / 落后 {behind}`,{ahead:n.ahead,behind:n.behind}),tone:n.behind>0?`warn`:``}),t):(t.push({label:X(`@WORKBENCH:Git 状态`),value:X(`@WORKBENCH:不是 Git 仓库`),tone:``}),t)}),Le={history:`wb.ocHistoryOpen.v1`,git:`wb.ocGitOpen.v1`};function ze(e){try{return localStorage.getItem(e)===`1`}catch{return!1}}let Be=P(ze(Le.history)),$=P(ze(Le.git));function Ue(e){let t=e===`history`?Be:$;t.value=!t.value;try{localStorage.setItem(Le[e],t.value?`1`:`0`)}catch{}}function Ge(){Be.value||Ue(`history`)}let qe={props:i,emit:a,draft:s,autoRun:c,useDefaultPrompt:l,selectedExecutor:u,MODE_KEY:Jo,mode:f,setMode:p,draftAttachments:m,DRAFT_RAW_BASE:Yo,attachTarget:g,isUploading:_,isImageAttachment:v,humanSize:b,onAttachmentPaste:x,onAttachmentDrop:S,removeAttachment:C,pickAttachmentFile:T,attachBusy:E,attachDragging:D,onPaste:O,onDrop:ne,onPickAttachment:k,onRemoveAttachment:re,clearAttachments:A,clearDraft:j,projectKey:M,globalPromptText:ie,projectPromptText:ae,anyProjectPrompt:oe,anyPromptConfigured:se,promptStateLabel:ce,draftChars:le,charLimit:N,overLimit:F,nearLimit:I,canSend:L,send:R,onInputKeydown:z,INPUT_H_KEY:Xo,OC_INPUT_MIN_H:Zo,readInputH:B,inputRef:V,inputH:H,inputStyle:de,get inputRO(){return W},set inputRO(e){W=e},get inputDragging(){return G},set inputDragging(e){G=e},get inputROFirst(){return K},set inputROFirst(e){K=e},INPUT_GRIP_PX:Qo,onInputMouseDown:fe,onWindowMouseUp:pe,commitInputH:q,selectedReportId:me,runningCount:ge,runningIds:J,reportIsLive:_e,liveReport:ve,locateTaskId:ye,currentReport:be,currentReportStale:xe,idleHint:Se,idleHintTitle:Ce,pickReport:we,textEl:Te,textExpanded:Z,textClamped:Ee,measureText:De,toggleText:Oe,get textRO(){return ke},set textRO(e){ke=e},historyPct:Ae,currentPercent:je,reportBrief:Me,reportNotice:Pe,onIntervalChange:Fe,gitSummary:Ie,SECT_KEY:Le,readSectOpen:ze,historyOpen:Be,gitOpen:$,toggleSect:Ue,reviewHistory:Ge,gitBrief:Y(()=>Ie.value.slice(0,2).map(e=>e.value).join(` · `)),get $t(){return X},get Promotion(){return d},get Expand(){return ue},get Fold(){return he},get Refresh(){return y},get ArrowDown(){return ee},get ArrowRight(){return te},get LocationInformation(){return h},get clockFromIso(){return yt},get relativeTimeFromIso(){return vt},get REPORT_INTERVAL_OPTIONS_MS(){return He},get REPORT_PERCENT_HINT_KEY(){return Ve},get REPORT_PERCENT_LABEL_KEY(){return We},get reportIntervalLabelKey(){return Ke},get reportIntervalLabelParams(){return Re},AttachmentZone:It,AgentChatSurface:qo,TaskExecutorPicker:Mo};return Object.defineProperty(qe,"__isScriptSetup",{enumerable:!1,value:!0}),qe}});c(),R(),W();var es=[`title`,`aria-label`],ts={class:`oc__rail-text`},ns={class:`oc__head`},rs={class:`oc__title`},is=[`title`,`aria-label`],as=[`aria-label`],os=[`aria-selected`],ss=[`aria-selected`],cs={class:`oc__report-head`},ls={class:`oc__panel-title`},us=[`value`,`title`,`aria-label`],ds=[`value`],fs=[`disabled`,`title`],ps={class:`oc__report-list`},ms={key:0,class:`rp`},hs={class:`rp__head`},gs=[`title`],_s={class:`rp__count`},vs={class:`rp__time`},ys=[`title`,`aria-label`],bs=[`title`],xs=[`aria-valuenow`,`aria-label`],Ss={class:`rp__percent`},Cs={class:`rp__percent-tag`},ws={key:1,class:`rp__body`},Ts=[`title`],Es=[`title`],Ds={class:`oc-empty__text`},Os=[`aria-expanded`,`title`],ks={class:`oc__sect-title`},As={class:`oc__sect-meta`},js={class:`oc__sect-brief`},Ms={class:`oc__history-list`},Ns=[`onClick`],Ps={class:`oc__history-time`},Fs={class:`oc__history-pct`},Is={class:`oc__history-sum`},Ls=[`aria-expanded`,`title`],Rs={class:`oc__sect-title`},zs={class:`oc__sect-meta`},Bs={class:`oc__git-name`},Vs={key:0,class:`oc__sect-brief`},Hs={class:`oc__git-list`},Us={class:`oc__git-label`},Ws={class:`oc__git-label`},Gs={class:`oc__git-value`},Ks={class:`oc__git-label`},qs={class:`oc__git-value`},Js=[`placeholder`],Ys={key:0},Xs={key:1},Zs={class:`oc__compose-foot`},Qs=[`disabled`,`title`,`aria-label`],$s=[`title`,`aria-label`],ec=[`title`],tc=[`title`],nc={class:`oc__foot-label`},rc=[`disabled`],ic={class:`oc__hint`};function ac(t,n,i,a,o,s){let c=l;return K(),S(`aside`,{class:T([`oc`,{"is-collapsed":i.collapsed,"is-report-empty":a.mode===`command`&&!i.collapsed&&!a.currentReport}])},[J(` 折叠后的收纳条:只剩一枚展开按钮 + 竖排标题,宽度收到 32px。
239
+ 折叠不是"把宽度压成 0"—— 那样就再没有能点回来的地方了。 `),i.collapsed?(K(),S(`button`,{key:0,type:`button`,class:`oc__rail`,title:a.$t(`@WORKBENCH:展开主 Agent 控制台`),"aria-label":a.$t(`@WORKBENCH:展开主 Agent 控制台`),"aria-expanded":!1,onClick:n[0]||=e=>a.emit(`toggle-collapse`)},[e(c,{class:`oc__rail-icon`},{default:L(()=>[e(a.Fold)]),_:1}),x(`span`,ts,D(a.$t(`@WORKBENCH:主 Agent 控制台`)),1)],8,es)):J(`v-if`,!0),J(` 折叠时这几块整体隐藏而不是销毁(v-show 而不是 v-if):
240
+ 草稿指令和已贴的附件都还留着,展开回来能接着发 `),A(x(`header`,ns,[x(`h3`,rs,D(a.$t(`@WORKBENCH:主 Agent 控制台`)),1),x(`button`,{type:`button`,class:`oc__collapse`,title:a.$t(`@WORKBENCH:收起主 Agent 控制台`),"aria-label":a.$t(`@WORKBENCH:收起主 Agent 控制台`),"aria-expanded":!0,onClick:n[1]||=e=>a.emit(`toggle-collapse`)},[e(c,null,{default:L(()=>[e(a.Expand)]),_:1})],8,is)],512),[[H,!i.collapsed]]),J(` 工作方式:对话 = g ai 边聊边派(可以多轮、可以反问你);指令 = 你自己敲一句话派一条。
241
241
  两种方式落到的是**同一条派发链路、同一条指令流水**,变的只是"谁决定派什么"。
242
242
  (标题行下方原来还有一条「{n} 个执行中」状态栏,2026-10-16 删掉 ——
243
- 执行数看板「进行中」列与左栏「全部项目」行各有,用户要求这里不再重复。) `),A(x(`div`,{class:`oc__mode`,role:`tablist`,"aria-label":a.$t(`@WORKBENCH:切换主 Agent 控制台的工作方式`)},[x(`button`,{type:`button`,role:`tab`,class:w([`oc__mode-btn`,{"is-active":a.mode===`chat`}]),"aria-selected":a.mode===`chat`,onClick:n[2]||=e=>a.setMode(`chat`)},E(a.$t(`@WORKBENCH:对话`)),11,Zo),x(`button`,{type:`button`,role:`tab`,class:w([`oc__mode-btn`,{"is-active":a.mode===`command`}]),"aria-selected":a.mode===`command`,onClick:n[3]||=e=>a.setMode(`command`)},E(a.$t(`@WORKBENCH:指令`)),11,Qo)],8,Xo),[[H,!i.collapsed]]),A(e(a.AgentChatSurface,{class:`oc__chat`,active:!i.collapsed&&a.mode===`chat`,"allow-dispatch":``,"dispatch-use-default-prompt":a.useDefaultPrompt,title:a.$t(`@WORKBENCH:g ai 对话`),"git-branch":i.selectedProject?.git?.branch??null},null,8,[`active`,`dispatch-use-default-prompt`,`title`,`git-branch`]),[[H,!i.collapsed&&a.mode===`chat`]]),J(` 进度报告:主 Agent 隔一会儿读一遍正在跑的 job,写一段"现在到哪一步了"。
243
+ 执行数看板「进行中」列与左栏「全部项目」行各有,用户要求这里不再重复。) `),A(x(`div`,{class:`oc__mode`,role:`tablist`,"aria-label":a.$t(`@WORKBENCH:切换主 Agent 控制台的工作方式`)},[x(`button`,{type:`button`,role:`tab`,class:T([`oc__mode-btn`,{"is-active":a.mode===`chat`}]),"aria-selected":a.mode===`chat`,onClick:n[2]||=e=>a.setMode(`chat`)},D(a.$t(`@WORKBENCH:对话`)),11,os),x(`button`,{type:`button`,role:`tab`,class:T([`oc__mode-btn`,{"is-active":a.mode===`command`}]),"aria-selected":a.mode===`command`,onClick:n[3]||=e=>a.setMode(`command`)},D(a.$t(`@WORKBENCH:指令`)),11,ss)],8,as),[[H,!i.collapsed]]),A(e(a.AgentChatSurface,{class:`oc__chat`,active:!i.collapsed&&a.mode===`chat`,"allow-dispatch":``,"dispatch-use-default-prompt":a.useDefaultPrompt,title:a.$t(`@WORKBENCH:g ai 对话`),"git-branch":i.selectedProject?.git?.branch??null},null,8,[`active`,`dispatch-use-default-prompt`,`title`,`git-branch`]),[[H,!i.collapsed&&a.mode===`chat`]]),J(` 进度报告:主 Agent 隔一会儿读一遍正在跑的 job,写一段"现在到哪一步了"。
244
244
  报告由服务端生成(自动那份由服务端定时器产生),这里只渲染 + 两个入口:
245
- 改间隔、立即报告。 `),A(x(`div`,{class:w([`oc__report`,{"is-empty":!a.currentReport}])},[x(`div`,$o,[x(`p`,es,E(a.$t(`@WORKBENCH:进度报告`)),1),J(` 间隔设置。做成下拉而不是输入框:这个值直接决定每多久烧一次模型额度,
246
- 自由填一个 5(分钟写成了秒)会让额度很快见底,而用户不会立刻意识到 `),x(`select`,{class:`oc__interval`,value:String(i.reportIntervalMs??0),title:a.$t(`@WORKBENCH:自动报告的间隔(关掉后仍可随时点「立即报告」)`),"aria-label":a.$t(`@WORKBENCH:自动报告间隔`),onChange:a.onIntervalChange},[(K(!0),S(k,null,D(a.REPORT_INTERVAL_OPTIONS_MS,e=>(K(),S(`option`,{key:e,value:String(e)},E(a.$t(a.reportIntervalLabelKey(e),a.reportIntervalLabelParams(e))),9,ns))),128))],40,ts),x(`button`,{type:`button`,class:`oc__report-run`,disabled:i.generatingReport,title:a.$t(`@WORKBENCH:让主 Agent 现在汇报一次正在执行的任务进度`),onClick:n[4]||=e=>a.emit(`generate-report`)},[e(c,{class:w([`oc__report-run-icon`,{"is-spin":i.generatingReport}])},{default:L(()=>[e(a.Refresh)]),_:1},8,[`class`]),x(`span`,null,E(i.generatingReport?a.$t(`@WORKBENCH:生成中…`):a.$t(`@WORKBENCH:立即报告`)),1)],8,rs)]),x(`ul`,is,[a.currentReport?(K(),S(`li`,as,[x(`div`,os,[x(`span`,{class:w([`rp__trigger`,{"is-auto":a.currentReport.trigger===`auto`}])},E(a.currentReport.trigger===`auto`?a.$t(`@WORKBENCH:自动`):a.$t(`@WORKBENCH:手动`)),3),J(` 用户从历史里点开一份已经过期的报告时标一下:下面那句「N 个任务进行中」
247
- 是生成那一刻的事实,现在早就跑完了,不标会看着像还在跑 `),a.currentReportStale?(K(),S(`span`,{key:0,class:`rp__stale`,title:a.$t(`@WORKBENCH:这份报告讲的任务已经跑完了,内容只反映生成那一刻的情况`)},E(a.$t(`@WORKBENCH:已结束`)),9,ss)):J(`v-if`,!0),x(`span`,cs,E(a.$t(`@WORKBENCH:{n} 个任务进行中`,{n:a.currentReport.tasks.length})),1),x(`span`,ls,E(a.clockFromIso(a.currentReport.at)),1),J(` 定位:这份报告讲的任务就在看板上,但右栏看不见它在哪一列。
245
+ 改间隔、立即报告。 `),A(x(`div`,{class:T([`oc__report`,{"is-empty":!a.currentReport}])},[x(`div`,cs,[x(`p`,ls,D(a.$t(`@WORKBENCH:进度报告`)),1),J(` 间隔设置。做成下拉而不是输入框:这个值直接决定每多久烧一次模型额度,
246
+ 自由填一个 5(分钟写成了秒)会让额度很快见底,而用户不会立刻意识到 `),x(`select`,{class:`oc__interval`,value:String(i.reportIntervalMs??0),title:a.$t(`@WORKBENCH:自动报告的间隔(关掉后仍可随时点「立即报告」)`),"aria-label":a.$t(`@WORKBENCH:自动报告间隔`),onChange:a.onIntervalChange},[(K(!0),S(k,null,O(a.REPORT_INTERVAL_OPTIONS_MS,e=>(K(),S(`option`,{key:e,value:String(e)},D(a.$t(a.reportIntervalLabelKey(e),a.reportIntervalLabelParams(e))),9,ds))),128))],40,us),x(`button`,{type:`button`,class:`oc__report-run`,disabled:i.generatingReport,title:a.$t(`@WORKBENCH:让主 Agent 现在汇报一次正在执行的任务进度`),onClick:n[4]||=e=>a.emit(`generate-report`)},[e(c,{class:T([`oc__report-run-icon`,{"is-spin":i.generatingReport}])},{default:L(()=>[e(a.Refresh)]),_:1},8,[`class`]),x(`span`,null,D(i.generatingReport?a.$t(`@WORKBENCH:生成中…`):a.$t(`@WORKBENCH:立即报告`)),1)],8,fs)]),x(`ul`,ps,[a.currentReport?(K(),S(`li`,ms,[x(`div`,hs,[x(`span`,{class:T([`rp__trigger`,{"is-auto":a.currentReport.trigger===`auto`}])},D(a.currentReport.trigger===`auto`?a.$t(`@WORKBENCH:自动`):a.$t(`@WORKBENCH:手动`)),3),J(` 用户从历史里点开一份已经过期的报告时标一下:下面那句「N 个任务进行中」
247
+ 是生成那一刻的事实,现在早就跑完了,不标会看着像还在跑 `),a.currentReportStale?(K(),S(`span`,{key:0,class:`rp__stale`,title:a.$t(`@WORKBENCH:这份报告讲的任务已经跑完了,内容只反映生成那一刻的情况`)},D(a.$t(`@WORKBENCH:已结束`)),9,gs)):J(`v-if`,!0),x(`span`,_s,D(a.$t(`@WORKBENCH:{n} 个任务进行中`,{n:a.currentReport.tasks.length})),1),x(`span`,vs,D(a.clockFromIso(a.currentReport.at)),1),J(` 定位:这份报告讲的任务就在看板上,但右栏看不见它在哪一列。
248
248
  一键滚过去 + 标记,不用去三列里找(2026-10-14 评审:左右两栏
249
- 说同一批事,用"跳过去"消重,而不是把任务卡搬回来) `),a.locateTaskId?(K(),S(`button`,{key:1,type:`button`,class:`rp__locate`,title:a.$t(`@WORKBENCH:在面板中定位这份报告讲的任务`),"aria-label":a.$t(`@WORKBENCH:在面板中定位这份报告讲的任务`),onClick:n[5]||=e=>a.emit(`locate-task`,a.locateTaskId)},[e(c,null,{default:L(()=>[e(a.LocationInformation)]),_:1})],8,us)):J(`v-if`,!0)]),J(` 进度条:主 Agent 自己给的百分比(不是我们拿时长算的 —— 跑多久跟还剩多少活
249
+ 说同一批事,用"跳过去"消重,而不是把任务卡搬回来) `),a.locateTaskId?(K(),S(`button`,{key:1,type:`button`,class:`rp__locate`,title:a.$t(`@WORKBENCH:在面板中定位这份报告讲的任务`),"aria-label":a.$t(`@WORKBENCH:在面板中定位这份报告讲的任务`),onClick:n[5]||=e=>a.emit(`locate-task`,a.locateTaskId)},[e(c,null,{default:L(()=>[e(a.LocationInformation)]),_:1})],8,ys)):J(`v-if`,!0)]),J(` 进度条:主 Agent 自己给的百分比(不是我们拿时长算的 —— 跑多久跟还剩多少活
250
250
  没有固定关系)。它没给就不画这一行,见 currentPercent。
251
251
  形状与左栏项目列表的进度条同一套(4px / pill / --gradient-progress),
252
- 两处的"进度"看起来得是一个东西 `),a.currentPercent===null?J(`v-if`,!0):(K(),S(`div`,{key:0,class:`rp__progress`,title:a.$t(a.REPORT_PERCENT_HINT_KEY)},[x(`span`,{class:`rp__bar`,role:`progressbar`,"aria-valuenow":a.currentPercent,"aria-valuemin":`0`,"aria-valuemax":`100`,"aria-label":a.$t(a.REPORT_PERCENT_LABEL_KEY)},[x(`i`,{class:`rp__bar-fill`,style:u({width:a.currentPercent+`%`})},null,4)],8,fs),J(` 「AI 估计」四个字不能省:这个数字是模型看着思考与工具调用估的,
253
- 光甩一个 62% 会被当成实测值 `),x(`span`,ps,[x(`span`,ms,E(a.$t(a.REPORT_PERCENT_LABEL_KEY)),1),z(E(a.currentPercent)+`% `,1)])],8,ds)),J(` 正文:主 Agent 写的**判断**。默认只露 6 行 —— 右栏只有 ~300px 宽,
252
+ 两处的"进度"看起来得是一个东西 `),a.currentPercent===null?J(`v-if`,!0):(K(),S(`div`,{key:0,class:`rp__progress`,title:a.$t(a.REPORT_PERCENT_HINT_KEY)},[x(`span`,{class:`rp__bar`,role:`progressbar`,"aria-valuenow":a.currentPercent,"aria-valuemin":`0`,"aria-valuemax":`100`,"aria-label":a.$t(a.REPORT_PERCENT_LABEL_KEY)},[x(`i`,{class:`rp__bar-fill`,style:u({width:a.currentPercent+`%`})},null,4)],8,xs),J(` 「AI 估计」四个字不能省:这个数字是模型看着思考与工具调用估的,
253
+ 光甩一个 62% 会被当成实测值 `),x(`span`,Ss,[x(`span`,Cs,D(a.$t(a.REPORT_PERCENT_LABEL_KEY)),1),z(D(a.currentPercent)+`% `,1)])],8,bs)),J(` 正文:主 Agent 写的**判断**。默认只露 6 行 —— 右栏只有 ~300px 宽,
254
254
  模型那种"任务1…任务2…任务3…"连着几段的汇报不截一下会独占整张卡。
255
255
  折起来时底下压一层渐隐(不是硬切),配一个「展开全文」,
256
- 不用拖滚动条去找结尾。 `),a.currentReport.text?(K(),S(`div`,hs,[x(`p`,{ref:`textEl`,class:w([`rp__text`,{"is-clamped":a.textClamped&&!a.textExpanded,"is-expanded":a.textExpanded}])},E(a.currentReport.text),3),a.textClamped||a.textExpanded?(K(),S(`button`,{key:0,type:`button`,class:`rp__more`,onClick:a.toggleText},E(a.textExpanded?a.$t(`@WORKBENCH:收起`):a.$t(`@WORKBENCH:展开全文`)),1)):J(`v-if`,!0)])):(K(),S(k,{key:2},[J(` 没有正文时给的是**实话**:没任务 / 没配模型 / 模型没返回内容,
257
- 三种情况的处理办法完全不同,一律写"暂无"会让人白等 `),x(`p`,{class:`rp__notice`,title:a.currentReport.errorDetail},E(a.reportNotice(a.currentReport)),9,gs)],2112)),J(`
256
+ 不用拖滚动条去找结尾。 `),a.currentReport.text?(K(),S(`div`,ws,[x(`p`,{ref:`textEl`,class:T([`rp__text`,{"is-clamped":a.textClamped&&!a.textExpanded,"is-expanded":a.textExpanded}])},D(a.currentReport.text),3),a.textClamped||a.textExpanded?(K(),S(`button`,{key:0,type:`button`,class:`rp__more`,onClick:a.toggleText},D(a.textExpanded?a.$t(`@WORKBENCH:收起`):a.$t(`@WORKBENCH:展开全文`)),1)):J(`v-if`,!0)])):(K(),S(k,{key:2},[J(` 没有正文时给的是**实话**:没任务 / 没配模型 / 模型没返回内容,
257
+ 三种情况的处理办法完全不同,一律写"暂无"会让人白等 `),x(`p`,{class:`rp__notice`,title:a.currentReport.errorDetail},D(a.reportNotice(a.currentReport)),9,Ts)],2112)),J(`
258
258
  这里原来还有一区「任务事实」(每个在跑的任务一张卡:标题 + 自己的进度条 +
259
259
  工具 / 思考 / 回复三行证据)。2026-10-14 整块下掉 —— 那些字段中间看板
260
260
  「进行中」的卡片本来就逐字有(服务端同一份 jobActivity 实现),两处并排
@@ -262,51 +262,51 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
262
262
  唯一卡片上没有的是**每个任务自己的百分比**,它跟着这次搬迁挪到了卡片上
263
263
  (WorkbenchKanban 的 .kb-card__live-progress)。所以这一栏现在只留
264
264
  主 Agent 的**判断**(正文 + 整体进度),依据去卡片上看。
265
- `)])):(K(),S(`li`,{key:1,class:`oc-empty`,title:a.idleHintTitle},[x(`span`,vs,E(a.idleHint),1),J(` 2026-10-14 评审轮:空态别做死胡同。悬停一直写着"要回看可以从历史报告里
266
- 点开",但历史区默认折着、还在面板更下方 —— 有历史就直接给一键展开 `),(i.reports||[]).length>1?(K(),S(`button`,{key:0,type:`button`,class:`oc-empty__action`,onClick:a.reviewHistory},E(a.$t(`@WORKBENCH:回看历史报告`)),1)):J(`v-if`,!0)],8,_s))]),J(` 历史:一行一份,点一条就把它换到上面看。只在有两份以上时出现 ——
265
+ `)])):(K(),S(`li`,{key:1,class:`oc-empty`,title:a.idleHintTitle},[x(`span`,Ds,D(a.idleHint),1),J(` 2026-10-14 评审轮:空态别做死胡同。悬停一直写着"要回看可以从历史报告里
266
+ 点开",但历史区默认折着、还在面板更下方 —— 有历史就直接给一键展开 `),(i.reports||[]).length>1?(K(),S(`button`,{key:0,type:`button`,class:`oc-empty__action`,onClick:a.reviewHistory},D(a.$t(`@WORKBENCH:回看历史报告`)),1)):J(`v-if`,!0)],8,Es))]),J(` 历史:一行一份,点一条就把它换到上面看。只在有两份以上时出现 ——
267
267
  只有一份时这个列表纯粹是噪音。
268
- 默认折起来:它是"回看",不该跟正在看的那份抢高度(见 script 里 SECT_KEY 的注释) `),(i.reports||[]).length>1?(K(),S(`div`,{key:0,class:w([`oc__history`,{"is-collapsed":!a.historyOpen}])},[x(`button`,{type:`button`,class:`oc__sect`,"aria-expanded":a.historyOpen,title:a.historyOpen?a.$t(`@WORKBENCH:收起`):a.$t(`@WORKBENCH:展开`),onClick:n[6]||=e=>a.toggleSect(`history`)},[e(c,{class:`oc__sect-caret`},{default:L(()=>[(K(),r(_(a.historyOpen?a.ArrowDown:a.ArrowRight)))]),_:1}),x(`span`,bs,E(a.$t(`@WORKBENCH:历史报告`)),1),J(` 折起来时这一行就是全部内容:份数是它唯一值得一眼看到的信息 `),x(`span`,xs,[x(`span`,Ss,E(a.$t(`@WORKBENCH:共 {n} 份`,{n:(i.reports||[]).length})),1)])],8,ys),A(x(`ul`,Cs,[(K(!0),S(k,null,D(i.reports,e=>(K(),S(`li`,{key:e.id},[x(`button`,{type:`button`,class:w([`oc__history-item`,{"is-active":e.id===a.currentReport?.id}]),onClick:t=>a.pickReport(e)},[x(`span`,Ts,E(a.clockFromIso(e.at)),1),J(` 历史里也带上进度:一眼看出"这条是 20 分钟前那会儿 40%,现在 70%"。
269
- 没有进度的那几条这一格是空的但**占着位**(见 historyPct) `),x(`span`,Es,E(a.historyPct(e)),1),x(`span`,Ds,E(a.reportBrief(e)),1)],10,ws)]))),128))],512),[[H,a.historyOpen]])],2)):J(`v-if`,!0)],2),[[H,!i.collapsed&&a.mode===`command`]]),A(x(`div`,{class:w([`oc__git`,{"is-collapsed":!a.gitOpen}])},[x(`button`,{type:`button`,class:`oc__sect`,"aria-expanded":a.gitOpen,title:a.gitOpen?a.$t(`@WORKBENCH:收起`):a.$t(`@WORKBENCH:展开`),onClick:n[7]||=e=>a.toggleSect(`git`)},[e(c,{class:`oc__sect-caret`},{default:L(()=>[(K(),r(_(a.gitOpen?a.ArrowDown:a.ArrowRight)))]),_:1}),x(`span`,ks,E(a.$t(`@WORKBENCH:项目概览`)),1),x(`span`,As,[J(` 无选中项目即「全部项目」:显式标出来,否则底下只剩「今日完成」一行,看着像数据没加载出来 `),x(`span`,js,E(i.selectedProject?i.selectedProject.name:a.$t(`@WORKBENCH:全部项目`)),1),J(` 折起来时再补上"这个仓库现在什么状态":分支 + 工作区。
270
- 不补的话,收起等于把这块唯一要扫的信息也一起收了 `),!a.gitOpen&&a.gitBrief?(K(),S(`span`,Ms,E(a.gitBrief),1)):J(`v-if`,!0)])],8,Os),A(x(`dl`,Ns,[(K(!0),S(k,null,D(a.gitSummary,e=>(K(),S(k,{key:e.label},[x(`dt`,Ps,E(e.label),1),x(`dd`,{class:w([`oc__git-value`,{"is-warn":e.tone===`warn`,"is-danger":e.tone===`danger`}])},E(e.value),3)],64))),128)),x(`dt`,Fs,E(a.$t(`@WORKBENCH:今日完成`)),1),x(`dd`,Is,E(i.todayDone),1),x(`dt`,Ls,E(a.$t(`@WORKBENCH:最后活跃`)),1),x(`dd`,Rs,E(i.selectedProject&&a.relativeTimeFromIso(i.selectedProject.stats.lastActiveAt)||`—`),1)],512),[[H,a.gitOpen]])],2),[[H,!i.collapsed&&a.mode===`command`]]),A(x(`div`,{class:`oc__compose`,onPaste:a.onPaste,onDrop:N(a.onDrop,[`prevent`]),onDragover:n[15]||=N(e=>a.attachDragging=!0,[`prevent`]),onDragleave:n[16]||=e=>a.attachDragging=!1},[J(` 粘贴事件必须同时挂在 textarea 上:在输入框里按 Ctrl+V 时事件只到 textarea,
271
- 不会冒泡经过下面的附件区 `),A(x(`textarea`,{ref:`inputRef`,class:w([`oc__input`,{"is-over":a.overLimit}]),"onUpdate:modelValue":n[8]||=e=>a.draft=e,style:u(a.inputStyle),rows:`3`,placeholder:a.$t(`@WORKBENCH:给主 Agent 下一条指令,例如:把登录模块的错误处理重构一遍`),onKeydown:a.onInputKeydown,onPaste:a.onPaste,onMousedown:a.onInputMouseDown},null,46,zs),[[G,a.draft]]),a.draftAttachments.length>0||a.attachBusy?(K(),r(a.AttachmentZone,{key:0,attachments:a.draftAttachments,"is-image":a.isImageAttachment,"human-size":a.humanSize,"is-uploading":a.attachBusy,"is-paste-hover":a.attachDragging,"on-pick":a.onPickAttachment,"on-remove":a.onRemoveAttachment,"raw-base":a.DRAFT_RAW_BASE,onPaste:a.onPaste,onDrop:a.onDrop,onDragover:n[9]||=N(e=>a.attachDragging=!0,[`prevent`]),onDragenter:n[10]||=N(e=>a.attachDragging=!0,[`prevent`]),onDragleave:n[11]||=e=>a.attachDragging=!1},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`])):J(`v-if`,!0),J(`
268
+ 默认折起来:它是"回看",不该跟正在看的那份抢高度(见 script 里 SECT_KEY 的注释) `),(i.reports||[]).length>1?(K(),S(`div`,{key:0,class:T([`oc__history`,{"is-collapsed":!a.historyOpen}])},[x(`button`,{type:`button`,class:`oc__sect`,"aria-expanded":a.historyOpen,title:a.historyOpen?a.$t(`@WORKBENCH:收起`):a.$t(`@WORKBENCH:展开`),onClick:n[6]||=e=>a.toggleSect(`history`)},[e(c,{class:`oc__sect-caret`},{default:L(()=>[(K(),r(_(a.historyOpen?a.ArrowDown:a.ArrowRight)))]),_:1}),x(`span`,ks,D(a.$t(`@WORKBENCH:历史报告`)),1),J(` 折起来时这一行就是全部内容:份数是它唯一值得一眼看到的信息 `),x(`span`,As,[x(`span`,js,D(a.$t(`@WORKBENCH:共 {n} 份`,{n:(i.reports||[]).length})),1)])],8,Os),A(x(`ul`,Ms,[(K(!0),S(k,null,O(i.reports,e=>(K(),S(`li`,{key:e.id},[x(`button`,{type:`button`,class:T([`oc__history-item`,{"is-active":e.id===a.currentReport?.id}]),onClick:t=>a.pickReport(e)},[x(`span`,Ps,D(a.clockFromIso(e.at)),1),J(` 历史里也带上进度:一眼看出"这条是 20 分钟前那会儿 40%,现在 70%"。
269
+ 没有进度的那几条这一格是空的但**占着位**(见 historyPct) `),x(`span`,Fs,D(a.historyPct(e)),1),x(`span`,Is,D(a.reportBrief(e)),1)],10,Ns)]))),128))],512),[[H,a.historyOpen]])],2)):J(`v-if`,!0)],2),[[H,!i.collapsed&&a.mode===`command`]]),A(x(`div`,{class:T([`oc__git`,{"is-collapsed":!a.gitOpen}])},[x(`button`,{type:`button`,class:`oc__sect`,"aria-expanded":a.gitOpen,title:a.gitOpen?a.$t(`@WORKBENCH:收起`):a.$t(`@WORKBENCH:展开`),onClick:n[7]||=e=>a.toggleSect(`git`)},[e(c,{class:`oc__sect-caret`},{default:L(()=>[(K(),r(_(a.gitOpen?a.ArrowDown:a.ArrowRight)))]),_:1}),x(`span`,Rs,D(a.$t(`@WORKBENCH:项目概览`)),1),x(`span`,zs,[J(` 无选中项目即「全部项目」:显式标出来,否则底下只剩「今日完成」一行,看着像数据没加载出来 `),x(`span`,Bs,D(i.selectedProject?i.selectedProject.name:a.$t(`@WORKBENCH:全部项目`)),1),J(` 折起来时再补上"这个仓库现在什么状态":分支 + 工作区。
270
+ 不补的话,收起等于把这块唯一要扫的信息也一起收了 `),!a.gitOpen&&a.gitBrief?(K(),S(`span`,Vs,D(a.gitBrief),1)):J(`v-if`,!0)])],8,Ls),A(x(`dl`,Hs,[(K(!0),S(k,null,O(a.gitSummary,e=>(K(),S(k,{key:e.label},[x(`dt`,Us,D(e.label),1),x(`dd`,{class:T([`oc__git-value`,{"is-warn":e.tone===`warn`,"is-danger":e.tone===`danger`}])},D(e.value),3)],64))),128)),x(`dt`,Ws,D(a.$t(`@WORKBENCH:今日完成`)),1),x(`dd`,Gs,D(i.todayDone),1),x(`dt`,Ks,D(a.$t(`@WORKBENCH:最后活跃`)),1),x(`dd`,qs,D(i.selectedProject&&a.relativeTimeFromIso(i.selectedProject.stats.lastActiveAt)||`—`),1)],512),[[H,a.gitOpen]])],2),[[H,!i.collapsed&&a.mode===`command`]]),A(x(`div`,{class:`oc__compose`,onPaste:a.onPaste,onDrop:N(a.onDrop,[`prevent`]),onDragover:n[15]||=N(e=>a.attachDragging=!0,[`prevent`]),onDragleave:n[16]||=e=>a.attachDragging=!1},[J(` 粘贴事件必须同时挂在 textarea 上:在输入框里按 Ctrl+V 时事件只到 textarea,
271
+ 不会冒泡经过下面的附件区 `),A(x(`textarea`,{ref:`inputRef`,class:T([`oc__input`,{"is-over":a.overLimit}]),"onUpdate:modelValue":n[8]||=e=>a.draft=e,style:u(a.inputStyle),rows:`3`,placeholder:a.$t(`@WORKBENCH:给主 Agent 下一条指令,例如:把登录模块的错误处理重构一遍`),onKeydown:a.onInputKeydown,onPaste:a.onPaste,onMousedown:a.onInputMouseDown},null,46,Js),[[G,a.draft]]),a.draftAttachments.length>0||a.attachBusy?(K(),r(a.AttachmentZone,{key:0,attachments:a.draftAttachments,"is-image":a.isImageAttachment,"human-size":a.humanSize,"is-uploading":a.attachBusy,"is-paste-hover":a.attachDragging,"on-pick":a.onPickAttachment,"on-remove":a.onRemoveAttachment,"raw-base":a.DRAFT_RAW_BASE,onPaste:a.onPaste,onDrop:a.onDrop,onDragover:n[9]||=N(e=>a.attachDragging=!0,[`prevent`]),onDragenter:n[10]||=N(e=>a.attachDragging=!0,[`prevent`]),onDragleave:n[11]||=e=>a.attachDragging=!1},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`])):J(`v-if`,!0),J(`
272
272
  字数:单独占输入框下方一行,不挤底部那一排按钮。
273
273
  空草稿时不渲染("0 / 100000" 是噪音),接近上限转黄、超了转红 ——
274
274
  目的是让"粘太长发不出去"在**点之前**看得见,而不是点完等服务端 400 才知道
275
275
  (而超长恰恰是最容易失败的那一类,必须能改一改再发)。
276
- `),a.draftChars>0?(K(),S(`p`,{key:1,class:w([`oc__count`,{"is-warn":a.nearLimit,"is-over":a.overLimit}])},[a.overLimit?(K(),S(`span`,Bs,E(a.$t(`@WORKBENCH:超出上限 {max} 字,请精简后再派发(超出的部分不会被发出)`,{max:a.charLimit})),1)):(K(),S(`span`,Vs,E(a.draftChars)+` / `+E(a.charLimit),1))],2)):J(`v-if`,!0),x(`div`,Hs,[x(`button`,{type:`button`,class:`oc__attach`,disabled:a.attachBusy,title:a.$t(`@WORKBENCH:添加附件(也可直接粘贴或拖入文件)`),"aria-label":a.$t(`@WORKBENCH:添加附件`),onClick:a.onPickAttachment},[J(` paperclip.svg(Tabler icons,MIT) `),e(c,null,{default:L(()=>[...n[17]||=[x(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},[x(`path`,{d:`M15 7l-6.5 6.5a1.5 1.5 0 0 0 3 3l6.5-6.5a3 3 0 0 0-6-6l-6.5 6.5a4.5 4.5 0 0 0 9 9l6.5-6.5`})],-1)]]),_:1})],8,Us),J(` 预设提示词设置入口:图标按钮按项目惯例不加底色,
277
- 有没有设过看右侧"附加预设提示词"那个勾选(它是真实生效状态,这个只是入口) `),x(`button`,{type:`button`,class:w([`oc__attach`,{"is-on":a.anyPromptConfigured}]),title:a.$t(`@WORKBENCH:设置派发时自动附加的预设提示词(全局 / 各项目)`),"aria-label":a.$t(`@WORKBENCH:预设提示词设置`),onClick:n[12]||=e=>a.emit(`open-prompt-settings`)},[J(` settings.svg(Tabler icons,MIT) `),e(c,null,{default:L(()=>[...n[18]||=[x(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},[x(`path`,{d:`M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 0 0-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 0 0-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.94-1.543.826-3.31 2.37-2.37c1 .608 2.296.07 2.572-1.065`}),x(`path`,{d:`M9 12a3 3 0 1 0 6 0a3 3 0 0 0-6 0`})],-1)]]),_:1})],10,Ws),x(`label`,{class:`oc__autorn`,title:a.$t(`@WORKBENCH:取消勾选则只建任务草稿,不自动执行`)},[A(x(`input`,{type:`checkbox`,"onUpdate:modelValue":n[13]||=e=>a.autoRun=e},null,512),[[B,a.autoRun]]),x(`span`,null,E(a.$t(`@WORKBENCH:立即执行`)),1)],8,Gs),J(` 一条都没设过时不出现:一个永远勾着、点了也没区别的开关只会占地方 `),a.anyPromptConfigured?(K(),S(`label`,{key:0,class:`oc__autorn`,title:a.$t(`@WORKBENCH:取消勾选则本次派发的任务不带预设提示词(设置本身不受影响)`)},[A(x(`input`,{type:`checkbox`,"onUpdate:modelValue":n[14]||=e=>a.useDefaultPrompt=e},null,512),[[B,a.useDefaultPrompt]]),J(` 2026-10-14 评审轮改名:旧文案「预设提示词(全局)」没说清这个勾选
278
- 干什么(用户原话:语义不清)。它勾的是"这次派发带上预设提示词" `),x(`span`,null,E(a.$t(`@WORKBENCH:附带预设提示词({state})`,{state:a.promptStateLabel})),1)],8,Ks)):J(`v-if`,!0),J(` 执行器标签:picker 本体只显示品牌名(「Claude Code」),
279
- 不标明身份会被当成模型选择(2026-10-14 评审) `),x(`span`,qs,E(a.$t(`@WORKBENCH:任务执行器`)),1),J(` 执行器:与工作台执行按钮、看板「执行」共用同一份选择。
276
+ `),a.draftChars>0?(K(),S(`p`,{key:1,class:T([`oc__count`,{"is-warn":a.nearLimit,"is-over":a.overLimit}])},[a.overLimit?(K(),S(`span`,Ys,D(a.$t(`@WORKBENCH:超出上限 {max} 字,请精简后再派发(超出的部分不会被发出)`,{max:a.charLimit})),1)):(K(),S(`span`,Xs,D(a.draftChars)+` / `+D(a.charLimit),1))],2)):J(`v-if`,!0),x(`div`,Zs,[x(`button`,{type:`button`,class:`oc__attach`,disabled:a.attachBusy,title:a.$t(`@WORKBENCH:添加附件(也可直接粘贴或拖入文件)`),"aria-label":a.$t(`@WORKBENCH:添加附件`),onClick:a.onPickAttachment},[J(` paperclip.svg(Tabler icons,MIT) `),e(c,null,{default:L(()=>[...n[17]||=[x(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},[x(`path`,{d:`M15 7l-6.5 6.5a1.5 1.5 0 0 0 3 3l6.5-6.5a3 3 0 0 0-6-6l-6.5 6.5a4.5 4.5 0 0 0 9 9l6.5-6.5`})],-1)]]),_:1})],8,Qs),J(` 预设提示词设置入口:图标按钮按项目惯例不加底色,
277
+ 有没有设过看右侧"附加预设提示词"那个勾选(它是真实生效状态,这个只是入口) `),x(`button`,{type:`button`,class:T([`oc__attach`,{"is-on":a.anyPromptConfigured}]),title:a.$t(`@WORKBENCH:设置派发时自动附加的预设提示词(全局 / 各项目)`),"aria-label":a.$t(`@WORKBENCH:预设提示词设置`),onClick:n[12]||=e=>a.emit(`open-prompt-settings`)},[J(` settings.svg(Tabler icons,MIT) `),e(c,null,{default:L(()=>[...n[18]||=[x(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`},[x(`path`,{d:`M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 0 0-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 0 0-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.94-1.543.826-3.31 2.37-2.37c1 .608 2.296.07 2.572-1.065`}),x(`path`,{d:`M9 12a3 3 0 1 0 6 0a3 3 0 0 0-6 0`})],-1)]]),_:1})],10,$s),x(`label`,{class:`oc__autorn`,title:a.$t(`@WORKBENCH:取消勾选则只建任务草稿,不自动执行`)},[A(x(`input`,{type:`checkbox`,"onUpdate:modelValue":n[13]||=e=>a.autoRun=e},null,512),[[B,a.autoRun]]),x(`span`,null,D(a.$t(`@WORKBENCH:立即执行`)),1)],8,ec),J(` 一条都没设过时不出现:一个永远勾着、点了也没区别的开关只会占地方 `),a.anyPromptConfigured?(K(),S(`label`,{key:0,class:`oc__autorn`,title:a.$t(`@WORKBENCH:取消勾选则本次派发的任务不带预设提示词(设置本身不受影响)`)},[A(x(`input`,{type:`checkbox`,"onUpdate:modelValue":n[14]||=e=>a.useDefaultPrompt=e},null,512),[[B,a.useDefaultPrompt]]),J(` 2026-10-14 评审轮改名:旧文案「预设提示词(全局)」没说清这个勾选
278
+ 干什么(用户原话:语义不清)。它勾的是"这次派发带上预设提示词" `),x(`span`,null,D(a.$t(`@WORKBENCH:附带预设提示词({state})`,{state:a.promptStateLabel})),1)],8,tc)):J(`v-if`,!0),J(` 执行器标签:picker 本体只显示品牌名(「Claude Code」),
279
+ 不标明身份会被当成模型选择(2026-10-14 评审) `),x(`span`,nc,D(a.$t(`@WORKBENCH:任务执行器`)),1),J(` 执行器:与工作台执行按钮、看板「执行」共用同一份选择。
280
280
  下拉本体收口在 TaskExecutorPicker(对话模式底下那个也是它),
281
- 它自己读 composable 的共享状态,这里不用再传 v-model `),e(a.TaskExecutorPicker,{title:a.$t(`@WORKBENCH:本次派发使用的执行器(与执行按钮的临时切换共用)`)},null,8,[`title`]),x(`button`,{type:`button`,class:`oc__send`,disabled:!a.canSend,onClick:a.send},[e(c,{class:`oc__send-icon`},{default:L(()=>[e(a.Promotion)]),_:1}),x(`span`,null,E(i.dispatching?a.$t(`@WORKBENCH:派发中…`):a.$t(`@WORKBENCH:派发`)),1)],8,Js)]),x(`p`,Ys,[i.selectedProject?(K(),S(k,{key:0},[z(E(a.$t(`@WORKBENCH:指令会在「{name}」下新建一个任务;Enter 派发,Shift+Enter 换行`,{name:i.selectedProject.name})),1)],64)):(K(),S(k,{key:1},[z(E(a.$t(`@WORKBENCH:指令落到哪个项目由主 Agent 判断;Enter 派发,Shift+Enter 换行`)),1)],64))])],544),[[H,!i.collapsed&&a.mode===`command`]])],2)}var Zs=Z(Wo,[[`render`,Xs],[`__scopeId`,`data-v-4c030231`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/OrchestratorConsole.vue`]]);c(),V();var Qs=4e3,$s=f({__name:`WorkbenchDefaultPromptDialog`,props:{modelValue:{type:Boolean,required:!0},defaultPrompt:{type:String,required:!0},projectPath:{type:String,required:!0},projectName:{type:String,required:!0},projectPrompt:{type:String,required:!0},saving:{type:Boolean,required:!0}},emits:[`update:modelValue`,`save`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,a=P(``),o=P(``);U(()=>r.modelValue,e=>{e&&(a.value=r.defaultPrompt||``,o.value=r.projectPrompt||``)});let s=Y(()=>!!r.projectPath),c=Y(()=>a.value.trim()!==(r.defaultPrompt||``).trim()||s.value&&o.value.trim()!==(r.projectPrompt||``).trim());function l(){r.saving||i(`save`,{globalPrompt:a.value,projectPrompt:o.value})}function u(){i(`update:modelValue`,!1)}let d={props:r,emit:i,MAX_CHARS:Qs,globalDraft:a,projectDraft:o,hasProject:s,dirty:c,submit:l,close:u,get $t(){return X},CommonDialog:Me};return Object.defineProperty(d,"__isScriptSetup",{enumerable:!1,value:!0}),d}});R(),c(),W();var ec={class:`pd`},tc={class:`pd__intro`},nc={class:`pd__field`},rc={class:`pd__head`},ic={class:`pd__label`,for:`pd-global`},ac={class:`pd__count`},oc=[`placeholder`],sc={class:`pd__field`},cc={class:`pd__head`},lc={class:`pd__label`,for:`pd-project`},uc={key:0,class:`pd__count`},dc=[`disabled`,`placeholder`],fc={class:`pd__hint`},pc={class:`pd__foot`},mc=[`disabled`];function hc(e,t,n,i,a,o){return K(),r(i.CommonDialog,{"model-value":n.modelValue,title:i.$t(`@WORKBENCH:预设提示词`),width:`min(640px, 94vw)`,"close-on-click-modal":!1,"onUpdate:modelValue":t[2]||=e=>i.emit(`update:modelValue`,e)},{footer:L(()=>[x(`div`,pc,[x(`button`,{type:`button`,class:`pd__btn`,onClick:i.close},E(i.$t(`@WORKBENCH:取消`)),1),t[3]||=x(`span`,{class:`pd__foot-spacer`},null,-1),x(`button`,{type:`button`,class:`pd__btn pd__btn--primary`,disabled:n.saving||!i.dirty,onClick:i.submit},E(n.saving?i.$t(`@WORKBENCH:保存中…`):i.$t(`@WORKBENCH:保存`)),9,mc)])]),default:L(()=>[x(`div`,ec,[x(`p`,tc,E(i.$t(`@WORKBENCH:派发指令时自动附加在指令之前,让每个任务都带上这些约束。只影响之后派发的任务,不会改动已经建好的任务。`)),1),x(`div`,nc,[x(`div`,rc,[x(`label`,ic,E(i.$t(`@WORKBENCH:全局提示词`)),1),x(`span`,ac,E(i.globalDraft.length)+` / `+E(i.MAX_CHARS),1)]),A(x(`textarea`,{id:`pd-global`,"onUpdate:modelValue":t[0]||=e=>i.globalDraft=e,class:`pd__area`,rows:`5`,maxlength:i.MAX_CHARS,placeholder:i.$t(`@WORKBENCH:对所有项目生效。例如:回答用中文;改完代码必须跑一遍测试;不要动 dist 目录`)},null,8,oc),[[G,i.globalDraft]])]),x(`div`,sc,[x(`div`,cc,[x(`label`,lc,E(i.hasProject?i.$t(`@WORKBENCH:「{name}」的项目提示词`,{name:n.projectName}):i.$t(`@WORKBENCH:项目提示词`)),1),i.hasProject?(K(),S(`span`,uc,E(i.projectDraft.length)+` / `+E(i.MAX_CHARS),1)):J(`v-if`,!0)]),A(x(`textarea`,{id:`pd-project`,"onUpdate:modelValue":t[1]||=e=>i.projectDraft=e,class:`pd__area`,rows:`5`,maxlength:i.MAX_CHARS,disabled:!i.hasProject,placeholder:i.hasProject?i.$t(`@WORKBENCH:只在这个项目派发时附加。例如:包管理器用 pnpm;改动集中在 src/ui 下`):i.$t(`@WORKBENCH:先在左侧选中一个具体项目,才能设置它的提示词`)},null,8,dc),[[G,i.projectDraft]]),x(`p`,fc,E(i.hasProject?i.$t(`@WORKBENCH:项目提示词追加在全局提示词之后(不覆盖全局),派发到「{name}」时一起带上`,{name:n.projectName}):i.$t(`@WORKBENCH:选中的是「全部项目」,落点由主 Agent 判断 —— 想给某个项目单设提示词,先选中它`)),1)])])]),_:1},8,[`model-value`,`title`])}var gc=Z($s,[[`render`,hc],[`__scopeId`,`data-v-766f470f`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchDefaultPromptDialog.vue`]]);c(),V();var _c=`/api/workbench/orchestrator/attachments`,vc=f({__name:`WorkbenchTaskCreateDialog`,props:{modelValue:{type:Boolean,required:!0},projects:{type:Array,required:!0},defaultProjectPath:{type:String,required:!0}},emits:[`update:modelValue`,`created`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,a=P(``),o=P(``),s=P(``),c=P(!1),l=P(``),u=P([]),d=P(!1),f=!1,p=Y(()=>({kind:`draft`,list:u.value,replace:e=>{u.value=e}})),{isUploading:m,isImageAttachment:h,humanSize:g,onAttachmentPaste:_,onAttachmentDrop:v,removeAttachment:y,pickAttachmentFile:b}=dr(),x=Y(()=>m(`draft`));function S(e){e.stopPropagation(),_(e,p.value)}function C(e){d.value=!1,v(e,p.value)}function ee(){b(p.value)}function w(e){y(p.value,e)}function T(){let e=u.value;if(u.value=[],!(f||e.length===0))for(let t of e)fetch(`${_c}/${encodeURIComponent(t.id)}`,{method:`DELETE`}).catch(()=>{})}function E(e){let t=$(e);if(!t)return``;let n=r.projects.find(e=>$(e.path)===t);return n?n.path:``}U(()=>r.modelValue,e=>{if(!e){T();return}a.value=``,o.value=``,u.value=[],d.value=!1,f=!1,s.value=E(r.defaultProjectPath),l.value=``,c.value=!1});let te=Y(()=>r.projects),D=Y(()=>!c.value&&!x.value&&(a.value.trim().length>0||o.value.trim().length>0)),ne=Y(()=>{let e=$(s.value);if(!e)return``;let t=te.value.find(t=>$(t.path)===e);return t?t.name:``});async function O(e){if(D.value){c.value=!0,l.value=``;try{let t={title:a.value.trim(),desc:o.value};s.value&&(t.projectPath=s.value),u.value.length>0&&(t.stagedAttachments=u.value.map(e=>({id:e.id,ext:e.ext,originalName:e.originalName})));let n=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)}).then(e=>e.json()).catch(()=>null);if(!n?.success){l.value=n?.error||X(`@WORKBENCH:保存失败`);return}f=!0,i(`update:modelValue`,!1),i(`created`,{task:n.task,openEditor:e})}finally{c.value=!1}}}let k={props:r,emit:i,title:a,desc:o,projectPath:s,submitting:c,error:l,drafts:u,dragging:d,DRAFT_RAW_BASE:_c,get committed(){return f},set committed(e){f=e},attachTarget:p,isUploading:m,isImageAttachment:h,humanSize:g,onAttachmentPaste:_,onAttachmentDrop:v,removeAttachment:y,pickAttachmentFile:b,attachBusy:x,onPaste:S,onDrop:C,onPickAttachment:ee,onRemoveAttachment:w,discardDrafts:T,matchOptionPath:E,projectOptions:te,canSubmit:D,projectName:ne,submit:O,get $t(){return X},CommonDialog:Me,AttachmentZone:It};return Object.defineProperty(k,"__isScriptSetup",{enumerable:!1,value:!0}),k}});R(),c(),W();var yc={class:`nc__field`},bc={class:`nc__label`,for:`nc-project`},xc={value:``},Sc=[`value`],Cc=[`title`],wc={class:`nc__field`},Tc={class:`nc__label`,for:`nc-title`},Ec=[`placeholder`],Dc={class:`nc__field`},Oc={class:`nc__label`,for:`nc-desc`},kc=[`placeholder`],Ac={class:`nc__field`},jc={class:`nc__hint`},Mc={key:0,class:`nc__error`},Nc={class:`nc__foot`},Pc=[`disabled`],Fc=[`disabled`];function Ic(t,n,i,a,o,s){return K(),r(a.CommonDialog,{"model-value":i.modelValue,title:a.$t(`@WORKBENCH:新建开发任务`),width:`min(600px, 94vw)`,"close-on-click-modal":!1,"onUpdate:modelValue":n[15]||=e=>a.emit(`update:modelValue`,e)},{footer:L(()=>[x(`div`,Nc,[x(`button`,{type:`button`,class:`nc__btn`,onClick:n[12]||=e=>a.emit(`update:modelValue`,!1)},E(a.$t(`@WORKBENCH:取消`)),1),n[16]||=x(`span`,{class:`nc__foot-spacer`},null,-1),x(`button`,{type:`button`,class:`nc__btn`,disabled:!a.canSubmit,onClick:n[13]||=e=>a.submit(!0)},E(a.$t(`@WORKBENCH:创建并打开编辑器`)),9,Pc),x(`button`,{type:`button`,class:`nc__btn nc__btn--primary`,disabled:!a.canSubmit,onClick:n[14]||=e=>a.submit(!1)},E(a.submitting?a.$t(`@WORKBENCH:创建中…`):a.$t(`@WORKBENCH:创建`)),9,Fc)])]),default:L(()=>[x(`div`,{class:`nc`,onPaste:a.onPaste,onDrop:N(a.onDrop,[`prevent`]),onDragover:n[9]||=N(e=>a.dragging=!0,[`prevent`]),onDragenter:n[10]||=N(e=>a.dragging=!0,[`prevent`]),onDragleave:n[11]||=e=>a.dragging=!1},[x(`div`,yc,[x(`label`,bc,E(a.$t(`@WORKBENCH:项目`)),1),A(x(`select`,{id:`nc-project`,"onUpdate:modelValue":n[0]||=e=>a.projectPath=e,class:`nc__select`},[x(`option`,xc,E(a.$t(`@WORKBENCH:跟随当前项目`)),1),(K(!0),S(k,null,D(a.projectOptions,e=>(K(),S(`option`,{key:e.key,value:e.path},E(e.name)+E(e.exists===!1?` · ${a.$t(`@WORKBENCH:目录不存在`)}`:``),9,Sc))),128))],512),[[ce,a.projectPath]]),x(`p`,{class:`nc__hint`,title:a.projectPath},E(a.projectName?a.$t(`@WORKBENCH:任务会在「{name}」目录下执行`,{name:a.projectName}):a.$t(`@WORKBENCH:任务会跟随应用当前的工作目录`)),9,Cc)]),x(`div`,wc,[x(`label`,Tc,E(a.$t(`@WORKBENCH:标题`)),1),A(x(`input`,{id:`nc-title`,"onUpdate:modelValue":n[1]||=e=>a.title=e,class:`nc__input`,type:`text`,maxlength:`200`,placeholder:a.$t(`@WORKBENCH:一句话说清要做什么`),onKeydown:n[2]||=F(N(e=>a.submit(!1),[`prevent`]),[`enter`])},null,40,Ec),[[G,a.title]])]),x(`div`,Dc,[x(`label`,Oc,E(a.$t(`@WORKBENCH:描述`)),1),A(x(`textarea`,{id:`nc-desc`,"onUpdate:modelValue":n[3]||=e=>a.desc=e,class:`nc__input nc__input--area`,rows:`6`,placeholder:a.$t(`@WORKBENCH:把背景、验收标准、相关文件路径写进来,执行时用它当上下文`),onKeydown:[n[4]||=F(N(e=>a.submit(!1),[`ctrl`,`prevent`]),[`enter`]),n[5]||=F(N(e=>a.submit(!1),[`meta`,`prevent`]),[`enter`])]},null,40,kc),[[G,a.desc]])]),J(`
281
+ 它自己读 composable 的共享状态,这里不用再传 v-model `),e(a.TaskExecutorPicker,{title:a.$t(`@WORKBENCH:本次派发使用的执行器(与执行按钮的临时切换共用)`)},null,8,[`title`]),x(`button`,{type:`button`,class:`oc__send`,disabled:!a.canSend,onClick:a.send},[e(c,{class:`oc__send-icon`},{default:L(()=>[e(a.Promotion)]),_:1}),x(`span`,null,D(i.dispatching?a.$t(`@WORKBENCH:派发中…`):a.$t(`@WORKBENCH:派发`)),1)],8,rc)]),x(`p`,ic,[i.selectedProject?(K(),S(k,{key:0},[z(D(a.$t(`@WORKBENCH:指令会在「{name}」下新建一个任务;Enter 派发,Shift+Enter 换行`,{name:i.selectedProject.name})),1)],64)):(K(),S(k,{key:1},[z(D(a.$t(`@WORKBENCH:指令落到哪个项目由主 Agent 判断;Enter 派发,Shift+Enter 换行`)),1)],64))])],544),[[H,!i.collapsed&&a.mode===`command`]])],2)}var oc=Z($o,[[`render`,ac],[`__scopeId`,`data-v-4c030231`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/OrchestratorConsole.vue`]]);c(),V();var sc=4e3,cc=f({__name:`WorkbenchDefaultPromptDialog`,props:{modelValue:{type:Boolean,required:!0},defaultPrompt:{type:String,required:!0},projectPath:{type:String,required:!0},projectName:{type:String,required:!0},projectPrompt:{type:String,required:!0},saving:{type:Boolean,required:!0}},emits:[`update:modelValue`,`save`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,a=P(``),o=P(``);U(()=>r.modelValue,e=>{e&&(a.value=r.defaultPrompt||``,o.value=r.projectPrompt||``)});let s=Y(()=>!!r.projectPath),c=Y(()=>a.value.trim()!==(r.defaultPrompt||``).trim()||s.value&&o.value.trim()!==(r.projectPrompt||``).trim());function l(){r.saving||i(`save`,{globalPrompt:a.value,projectPrompt:o.value})}function u(){i(`update:modelValue`,!1)}let d={props:r,emit:i,MAX_CHARS:sc,globalDraft:a,projectDraft:o,hasProject:s,dirty:c,submit:l,close:u,get $t(){return X},CommonDialog:Me};return Object.defineProperty(d,"__isScriptSetup",{enumerable:!1,value:!0}),d}});R(),c(),W();var lc={class:`pd`},uc={class:`pd__intro`},dc={class:`pd__field`},fc={class:`pd__head`},pc={class:`pd__label`,for:`pd-global`},mc={class:`pd__count`},hc=[`placeholder`],gc={class:`pd__field`},_c={class:`pd__head`},vc={class:`pd__label`,for:`pd-project`},yc={key:0,class:`pd__count`},bc=[`disabled`,`placeholder`],xc={class:`pd__hint`},Sc={class:`pd__foot`},Cc=[`disabled`];function wc(e,t,n,i,a,o){return K(),r(i.CommonDialog,{"model-value":n.modelValue,title:i.$t(`@WORKBENCH:预设提示词`),width:`min(640px, 94vw)`,"close-on-click-modal":!1,"onUpdate:modelValue":t[2]||=e=>i.emit(`update:modelValue`,e)},{footer:L(()=>[x(`div`,Sc,[x(`button`,{type:`button`,class:`pd__btn`,onClick:i.close},D(i.$t(`@WORKBENCH:取消`)),1),t[3]||=x(`span`,{class:`pd__foot-spacer`},null,-1),x(`button`,{type:`button`,class:`pd__btn pd__btn--primary`,disabled:n.saving||!i.dirty,onClick:i.submit},D(n.saving?i.$t(`@WORKBENCH:保存中…`):i.$t(`@WORKBENCH:保存`)),9,Cc)])]),default:L(()=>[x(`div`,lc,[x(`p`,uc,D(i.$t(`@WORKBENCH:派发指令时自动附加在指令之前,让每个任务都带上这些约束。只影响之后派发的任务,不会改动已经建好的任务。`)),1),x(`div`,dc,[x(`div`,fc,[x(`label`,pc,D(i.$t(`@WORKBENCH:全局提示词`)),1),x(`span`,mc,D(i.globalDraft.length)+` / `+D(i.MAX_CHARS),1)]),A(x(`textarea`,{id:`pd-global`,"onUpdate:modelValue":t[0]||=e=>i.globalDraft=e,class:`pd__area`,rows:`5`,maxlength:i.MAX_CHARS,placeholder:i.$t(`@WORKBENCH:对所有项目生效。例如:回答用中文;改完代码必须跑一遍测试;不要动 dist 目录`)},null,8,hc),[[G,i.globalDraft]])]),x(`div`,gc,[x(`div`,_c,[x(`label`,vc,D(i.hasProject?i.$t(`@WORKBENCH:「{name}」的项目提示词`,{name:n.projectName}):i.$t(`@WORKBENCH:项目提示词`)),1),i.hasProject?(K(),S(`span`,yc,D(i.projectDraft.length)+` / `+D(i.MAX_CHARS),1)):J(`v-if`,!0)]),A(x(`textarea`,{id:`pd-project`,"onUpdate:modelValue":t[1]||=e=>i.projectDraft=e,class:`pd__area`,rows:`5`,maxlength:i.MAX_CHARS,disabled:!i.hasProject,placeholder:i.hasProject?i.$t(`@WORKBENCH:只在这个项目派发时附加。例如:包管理器用 pnpm;改动集中在 src/ui 下`):i.$t(`@WORKBENCH:先在左侧选中一个具体项目,才能设置它的提示词`)},null,8,bc),[[G,i.projectDraft]]),x(`p`,xc,D(i.hasProject?i.$t(`@WORKBENCH:项目提示词追加在全局提示词之后(不覆盖全局),派发到「{name}」时一起带上`,{name:n.projectName}):i.$t(`@WORKBENCH:选中的是「全部项目」,落点由主 Agent 判断 —— 想给某个项目单设提示词,先选中它`)),1)])])]),_:1},8,[`model-value`,`title`])}var Tc=Z(cc,[[`render`,wc],[`__scopeId`,`data-v-766f470f`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchDefaultPromptDialog.vue`]]);c(),V();var Ec=`/api/workbench/orchestrator/attachments`,Dc=f({__name:`WorkbenchTaskCreateDialog`,props:{modelValue:{type:Boolean,required:!0},projects:{type:Array,required:!0},defaultProjectPath:{type:String,required:!0}},emits:[`update:modelValue`,`created`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,a=P(``),o=P(``),s=P(``),c=P(!1),l=P(``),u=P([]),d=P(!1),f=!1,p=Y(()=>({kind:`draft`,list:u.value,replace:e=>{u.value=e}})),{isUploading:m,isImageAttachment:h,humanSize:g,onAttachmentPaste:_,onAttachmentDrop:v,removeAttachment:y,pickAttachmentFile:b}=dr(),x=Y(()=>m(`draft`));function S(e){e.stopPropagation(),_(e,p.value)}function C(e){d.value=!1,v(e,p.value)}function w(){b(p.value)}function T(e){y(p.value,e)}function E(){let e=u.value;if(u.value=[],!(f||e.length===0))for(let t of e)fetch(`${Ec}/${encodeURIComponent(t.id)}`,{method:`DELETE`}).catch(()=>{})}function D(e){let t=$(e);if(!t)return``;let n=r.projects.find(e=>$(e.path)===t);return n?n.path:``}U(()=>r.modelValue,e=>{if(!e){E();return}a.value=``,o.value=``,u.value=[],d.value=!1,f=!1,s.value=D(r.defaultProjectPath),l.value=``,c.value=!1});let ee=Y(()=>r.projects),O=Y(()=>!c.value&&!x.value&&(a.value.trim().length>0||o.value.trim().length>0)),te=Y(()=>{let e=$(s.value);if(!e)return``;let t=ee.value.find(t=>$(t.path)===e);return t?t.name:``});async function ne(e){if(O.value){c.value=!0,l.value=``;try{let t={title:a.value.trim(),desc:o.value};s.value&&(t.projectPath=s.value),u.value.length>0&&(t.stagedAttachments=u.value.map(e=>({id:e.id,ext:e.ext,originalName:e.originalName})));let n=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)}).then(e=>e.json()).catch(()=>null);if(!n?.success){l.value=n?.error||X(`@WORKBENCH:保存失败`);return}f=!0,i(`update:modelValue`,!1),i(`created`,{task:n.task,openEditor:e})}finally{c.value=!1}}}let k={props:r,emit:i,title:a,desc:o,projectPath:s,submitting:c,error:l,drafts:u,dragging:d,DRAFT_RAW_BASE:Ec,get committed(){return f},set committed(e){f=e},attachTarget:p,isUploading:m,isImageAttachment:h,humanSize:g,onAttachmentPaste:_,onAttachmentDrop:v,removeAttachment:y,pickAttachmentFile:b,attachBusy:x,onPaste:S,onDrop:C,onPickAttachment:w,onRemoveAttachment:T,discardDrafts:E,matchOptionPath:D,projectOptions:ee,canSubmit:O,projectName:te,submit:ne,get $t(){return X},CommonDialog:Me,AttachmentZone:It};return Object.defineProperty(k,"__isScriptSetup",{enumerable:!1,value:!0}),k}});R(),c(),W();var Oc={class:`nc__field`},kc={class:`nc__label`,for:`nc-project`},Ac={value:``},jc=[`value`],Mc=[`title`],Nc={class:`nc__field`},Pc={class:`nc__label`,for:`nc-title`},Fc=[`placeholder`],Ic={class:`nc__field`},Lc={class:`nc__label`,for:`nc-desc`},Rc=[`placeholder`],zc={class:`nc__field`},Bc={class:`nc__hint`},Vc={key:0,class:`nc__error`},Hc={class:`nc__foot`},Uc=[`disabled`],Wc=[`disabled`];function Gc(t,n,i,a,o,s){return K(),r(a.CommonDialog,{"model-value":i.modelValue,title:a.$t(`@WORKBENCH:新建开发任务`),width:`min(600px, 94vw)`,"close-on-click-modal":!1,"onUpdate:modelValue":n[15]||=e=>a.emit(`update:modelValue`,e)},{footer:L(()=>[x(`div`,Hc,[x(`button`,{type:`button`,class:`nc__btn`,onClick:n[12]||=e=>a.emit(`update:modelValue`,!1)},D(a.$t(`@WORKBENCH:取消`)),1),n[16]||=x(`span`,{class:`nc__foot-spacer`},null,-1),x(`button`,{type:`button`,class:`nc__btn`,disabled:!a.canSubmit,onClick:n[13]||=e=>a.submit(!0)},D(a.$t(`@WORKBENCH:创建并打开编辑器`)),9,Uc),x(`button`,{type:`button`,class:`nc__btn nc__btn--primary`,disabled:!a.canSubmit,onClick:n[14]||=e=>a.submit(!1)},D(a.submitting?a.$t(`@WORKBENCH:创建中…`):a.$t(`@WORKBENCH:创建`)),9,Wc)])]),default:L(()=>[x(`div`,{class:`nc`,onPaste:a.onPaste,onDrop:N(a.onDrop,[`prevent`]),onDragover:n[9]||=N(e=>a.dragging=!0,[`prevent`]),onDragenter:n[10]||=N(e=>a.dragging=!0,[`prevent`]),onDragleave:n[11]||=e=>a.dragging=!1},[x(`div`,Oc,[x(`label`,kc,D(a.$t(`@WORKBENCH:项目`)),1),A(x(`select`,{id:`nc-project`,"onUpdate:modelValue":n[0]||=e=>a.projectPath=e,class:`nc__select`},[x(`option`,Ac,D(a.$t(`@WORKBENCH:跟随当前项目`)),1),(K(!0),S(k,null,O(a.projectOptions,e=>(K(),S(`option`,{key:e.key,value:e.path},D(e.name)+D(e.exists===!1?` · ${a.$t(`@WORKBENCH:目录不存在`)}`:``),9,jc))),128))],512),[[ce,a.projectPath]]),x(`p`,{class:`nc__hint`,title:a.projectPath},D(a.projectName?a.$t(`@WORKBENCH:任务会在「{name}」目录下执行`,{name:a.projectName}):a.$t(`@WORKBENCH:任务会跟随应用当前的工作目录`)),9,Mc)]),x(`div`,Nc,[x(`label`,Pc,D(a.$t(`@WORKBENCH:标题`)),1),A(x(`input`,{id:`nc-title`,"onUpdate:modelValue":n[1]||=e=>a.title=e,class:`nc__input`,type:`text`,maxlength:`200`,placeholder:a.$t(`@WORKBENCH:一句话说清要做什么`),onKeydown:n[2]||=F(N(e=>a.submit(!1),[`prevent`]),[`enter`])},null,40,Fc),[[G,a.title]])]),x(`div`,Ic,[x(`label`,Lc,D(a.$t(`@WORKBENCH:描述`)),1),A(x(`textarea`,{id:`nc-desc`,"onUpdate:modelValue":n[3]||=e=>a.desc=e,class:`nc__input nc__input--area`,rows:`6`,placeholder:a.$t(`@WORKBENCH:把背景、验收标准、相关文件路径写进来,执行时用它当上下文`),onKeydown:[n[4]||=F(N(e=>a.submit(!1),[`ctrl`,`prevent`]),[`enter`]),n[5]||=F(N(e=>a.submit(!1),[`meta`,`prevent`]),[`enter`])]},null,40,Rc),[[G,a.desc]])]),J(`
282
282
  附件:任务还不存在,所以先落暂存区,创建时由服务端认领进 \`_task-{id}/\`。
283
283
  刻意**常驻**渲染(控制台那边是"有附件才出现"+ 一枚回形针按钮):
284
284
  弹窗里没有别的入口能挂"添加附件",空态只有一行 "附件 0 [添加附件]",
285
285
  这也是唯一能让"可以粘图"这件事被看见的地方 —— 没发现这个能力等于没有。
286
- `),x(`div`,Ac,[e(a.AttachmentZone,{attachments:a.drafts,"is-image":a.isImageAttachment,"human-size":a.humanSize,"is-uploading":a.attachBusy,"is-paste-hover":a.dragging,"on-pick":a.onPickAttachment,"on-remove":a.onRemoveAttachment,"raw-base":a.DRAFT_RAW_BASE,onDragover:n[6]||=N(e=>a.dragging=!0,[`prevent`]),onDragenter:n[7]||=N(e=>a.dragging=!0,[`prevent`]),onDragleave:n[8]||=e=>a.dragging=!1},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`]),x(`p`,jc,E(a.$t(`@WORKBENCH:粘贴图片以快速添加`)),1)]),a.error?(K(),S(`p`,Mc,E(a.error),1)):J(`v-if`,!0)],32)]),_:1},8,[`model-value`,`title`])}var Lc=Z(vc,[[`render`,Ic],[`__scopeId`,`data-v-c60e660a`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchTaskCreateDialog.vue`]]);c(),V();var Rc=`wb.boardProject.v1`,zc=`wb.boardView.v1`,Bc=5e3,Vc=3e4,Hc=`wb.boardLayout.v1`,Uc=180,Wc=420,Gc=260,Kc=900,qc=.26,Jc=.46,Yc=f({__name:`WorkbenchBoard`,props:{openedTaskId:{type:[String,null],required:!0}},emits:[`open-task`,`board-tasks`,`locate-task`],setup(e,{expose:n,emit:r}){n();let i=e,a=r,{projects:s,boardTasks:c,currentProjectPath:l,loading:u,loadProjects:d,removeProject:f}=xt();U(c,e=>a(`board-tasks`,e),{immediate:!0});let{activity:p,running:m,dispatching:h,maxInstructionChars:g,defaultPrompt:_,projectPrompts:v,reports:y,generatingReport:b,reportIntervalMs:x,loadOrchestrator:S,dispatch:C,saveDefaultPrompt:w,saveProjectPrompt:T,loadReports:E,generateReport:te,setReportInterval:D}=gt(),{active:ne}=lt(),O=(()=>{try{return localStorage.getItem(Rc)}catch{return null}})(),k=P(O||``);U(k,e=>{try{localStorage.setItem(Rc,e)}catch{}});let re=P((()=>{try{return localStorage.getItem(zc)===`list`?`list`:`kanban`}catch{return`kanban`}})());U(re,e=>{try{localStorage.setItem(zc,e)}catch{}});let A=P(``),j=P(!1),M=P(null);function ie(){j.value=!j.value,j.value&&t(()=>M.value?.focus())}function ae(){j.value=!1}function oe(){A.value.trim()||(j.value=!1)}let se=Y(()=>k.value&&s.value.find(e=>e.key===k.value)||null),{isIconBroken:ce,markIconFailed:le}=Ie();U(s,e=>{k.value&&(e.some(e=>e.key===k.value)||(k.value=``))});let N=!1;function F(){if(N||(N=!0,O!==null))return;let e=l.value?$(l.value):``;e&&s.value.some(t=>t.key===e)&&(k.value=e)}let L=Y(()=>{let e=new Map(s.value.map(e=>[e.key,e.name])),t={};for(let n of c.value)n.projectPath&&(t[n.projectPath]=e.get($(n.projectPath))||``);return t}),R=Y(()=>{if(!k.value)return c.value;let e=k.value;return c.value.filter(t=>$(t.projectPath)===e)}),z=Y(()=>ze(y.value,c.value)),B=Y(()=>{let e=new Date;e.setHours(0,0,0,0);let t=e.getTime();return{projects:s.value.length,tasks:c.value.length,running:m.value.length,todayDone:p.value.filter(e=>e.kind===`done`&&e.at&&new Date(e.at).getTime()>=t).length}});function V(e){a(`open-task`,{taskId:e.id,projectPath:e.projectPath})}let H=null,W=!1,G=null;async function K(e=!0){if(!W){W=!0;try{await Promise.all([d(e),S(e)])}finally{W=!1}}}function pe(){document.hidden||(K(!0),E(!0))}o(async()=>{window.addEventListener(`resize`,_e),await K(!1),E(!0),F(),H=setInterval(()=>{document.hidden||K(!0)},Bc),G=setInterval(()=>{document.hidden||E(!0)},Vc),document.addEventListener(`visibilitychange`,pe)}),ee(()=>{window.removeEventListener(`resize`,_e),H&&=(clearInterval(H),null),G&&=(clearInterval(G),null),document.removeEventListener(`visibilitychange`,pe)});let q=de({left:null,right:null,leftCollapsed:!1,rightCollapsed:!1});function me(){try{let e=localStorage.getItem(Hc);if(!e)return;let t=JSON.parse(e);typeof t.left==`number`&&Number.isFinite(t.left)&&(q.left=t.left),typeof t.right==`number`&&Number.isFinite(t.right)&&(q.right=t.right),q.leftCollapsed=t.leftCollapsed===!0,q.rightCollapsed=t.rightCollapsed===!0}catch{}}me();function ge(){try{localStorage.setItem(Hc,JSON.stringify(q))}catch{}}let J=P(typeof window>`u`?1920:window.innerWidth);function _e(){J.value=window.innerWidth}let ve=Y(()=>J.value<=1024),ye=Y(()=>J.value<=860);function be(e,t){let n=e===`left`?Uc:Gc,r=Math.min(e===`left`?Wc:Kc,J.value*(e===`left`?qc:Jc));return Math.round(Math.min(Math.max(t,n),Math.max(n,r)))}let xe=Y(()=>{let e={};return q.left!=null&&(e[`--wb-left-w`]=be(`left`,q.left)+`px`),q.right!=null&&!ye.value&&(e[`--wb-right-w`]=be(`right`,q.right)+`px`),e}),Se=P(null),Ce=P(null);function we(e){return Se.value?.querySelector(e===`left`?`.board__left`:`.oc`)}function Te(e){window.removeEventListener(`mousemove`,e),document.body.style.userSelect=``,document.body.style.cursor=``,Ce.value=null,ge()}function Z(e,t){if(e===`left`?ve.value:ye.value)return;let n=we(e);if(!n)return;t.preventDefault();let r=t.clientX,i=n.getBoundingClientRect().width;Ce.value=e,document.body.style.userSelect=`none`,document.body.style.cursor=`col-resize`;let a=t=>{let n=(t.clientX-r)*(e===`left`?1:-1);q[e]=be(e,i+n)};window.addEventListener(`mousemove`,a),window.addEventListener(`mouseup`,()=>Te(a),{once:!0})}function Ee(e){q[e]=null,ge()}let De=P(!1),Oe=Y(()=>ve.value?!De.value:q.leftCollapsed);function ke(){if(ve.value){De.value=!De.value;return}q.leftCollapsed=!q.leftCollapsed,ge()}function Ae(){ve.value&&(De.value=!1)}let je=Y(()=>q.rightCollapsed&&!ye.value);function Me(){q.rightCollapsed=!q.rightCollapsed,ge()}function Ne(e){k.value=e?e.key:``,De.value=!1}let Pe=P(!1);function Fe(){Pe.value=!0}async function Le(e){if(await K(!0),e.openEditor){a(`open-task`,{taskId:e.task.id,projectPath:e.task.projectPath||``});return}I.success(X(`@WORKBENCH:已创建任务`))}async function Re(e){if(e.runningJobs>0)return;let t=`/api/workbench/tasks/${encodeURIComponent(e.id)}/run`,n=await fetch(t,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({executor:ne.value})}).then(e=>e.json()).catch(()=>null);if(!n?.success){I.error(n?.error||X(`@WORKBENCH:执行失败`));return}I.success(X(`@WORKBENCH:已开始执行`)),await K(!0)}let Be=new Set;async function Ve(e){if(Be.has(e.id))return;let t=e.live?.jobId;if(!t){I.error(X(`@WORKBENCH:停止失败`));return}try{await fe.confirm(X(`@WORKBENCH:确认停止执行?已输出的内容会保留。`),X(`@WORKBENCH:停止执行`),{confirmButtonText:X(`@WORKBENCH:停止`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}Be.add(e.id);try{let e=await fetch(`/api/workbench/jobs/${encodeURIComponent(t)}/cancel`,{method:`POST`}).then(e=>e.json()).catch(()=>null);if(!e?.success){I.error(e?.error||X(`@WORKBENCH:停止失败`));return}I.success(X(`@WORKBENCH:已发送停止信号`)),await K(!0)}finally{Be.delete(e.id)}}let Q=new Set;async function He(e){if(!Q.has(e.id)){if(e.runningJobs>0)try{await fe.confirm(X(`@WORKBENCH:这条任务还在执行,标记完成会同时把它停掉。已输出的内容会保留。`),X(`@WORKBENCH:标记为已完成`),{confirmButtonText:X(`@WORKBENCH:标记完成`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}Q.add(e.id);try{let t=await fetch(`/api/workbench/tasks/${encodeURIComponent(e.id)}/done`,{method:`POST`}).then(e=>e.json()).catch(()=>null);if(!t?.success){I.error(t?.error||X(`@WORKBENCH:标记失败`));return}I.success(X(`@WORKBENCH:已标记为已完成`)),await K(!0)}finally{Q.delete(e.id)}}}async function Ue(e){if(!Q.has(e.id)){Q.add(e.id);try{let t=await fetch(`/api/workbench/tasks/${encodeURIComponent(e.id)}/done`,{method:`DELETE`}).then(e=>e.json()).catch(()=>null);if(!t?.success){I.error(t?.error||X(`@WORKBENCH:撤销失败`));return}I.success(X(`@WORKBENCH:已撤销完成标记`)),await K(!0)}finally{Q.delete(e.id)}}}async function We(e){let{ok:t,keptTasks:n}=await f(e.path);t&&(I.success(n>0?X(`@WORKBENCH:已移除项目,{n} 条任务仍保留在「全部项目」下`,{n}):X(`@WORKBENCH:已移除项目`)),await K(!0))}async function Ge(e){let t=(e.title||``).trim()||X(`@WORKBENCH:未命名任务`);try{await fe.confirm(X(`@WORKBENCH:删除任务「{title}」?`,{title:t}),X(`@WORKBENCH:确认`),{type:`warning`})}catch{return}let n=await fetch(`/api/workbench/tasks/${encodeURIComponent(e.id)}`,{method:`DELETE`}).then(e=>e.json()).catch(()=>null);if(n&&n.success===!1){I.error(n.error||X(`@WORKBENCH:删除失败`));return}await K(!0)}let Ke=P(null),qe=Y(()=>se.value?.path||l.value);async function Je(e){let t=await C({text:e.text,projectPath:e.projectPath,autoRun:e.autoRun,attachments:e.attachments,useDefaultPrompt:e.useDefaultPrompt,executor:e.executor});t&&(Ke.value?.clearAttachments(),Ke.value?.clearDraft(),I.success(t.ran?X(`@WORKBENCH:已派发并开始执行`):X(`@WORKBENCH:已派发(只建任务未执行)`)),await K(!0))}let Ye=P(!1),Xe=P(!1),Ze=Y(()=>{let e=se.value?.key;return e&&v.value?.[e]?.prompt||``});async function Qe(e){if(Xe.value)return;let t=e.globalPrompt.trim(),n=e.projectPrompt.trim(),r=se.value;Xe.value=!0;try{let e=!0;t!==(_.value||``).trim()&&(e=await w(t)),e&&r&&n!==Ze.value.trim()&&(e=await T(r.path,n)),e&&(Ye.value=!1)}finally{Xe.value=!1}}let $e={props:i,emit:a,projects:s,boardTasks:c,currentProjectPath:l,loading:u,loadProjects:d,removeProject:f,activity:p,running:m,dispatching:h,maxInstructionChars:g,defaultPrompt:_,projectPrompts:v,reports:y,generatingReport:b,reportIntervalMs:x,loadOrchestrator:S,dispatch:C,saveDefaultPrompt:w,saveProjectPrompt:T,loadReports:E,generateReport:te,setReportInterval:D,boardExecutor:ne,SELECTED_KEY:Rc,savedSelection:O,selectedKey:k,VIEW_KEY:zc,view:re,search:A,searchOpen:j,searchInputRef:M,toggleSearch:ie,closeSearch:ae,onSearchBlur:oe,selectedProject:se,isIconBroken:ce,markIconFailed:le,get defaultSelectionApplied(){return N},set defaultSelectionApplied(e){N=e},applyDefaultSelection:F,projectLabels:L,visibleTasks:R,taskPercents:z,headerStats:B,onOpenTask:V,POLL_MS:Bc,get pollTimer(){return H},set pollTimer(e){H=e},get inFlight(){return W},set inFlight(e){W=e},REPORT_POLL_MS:Vc,get reportPollTimer(){return G},set reportPollTimer(e){G=e},refresh:K,onVisibilityChange:pe,LAYOUT_KEY:Hc,LEFT_W_MIN:Uc,LEFT_W_MAX:Wc,RIGHT_W_MIN:Gc,RIGHT_W_MAX:Kc,LEFT_W_SHARE:qc,RIGHT_W_SHARE:Jc,layout:q,readLayout:me,saveLayout:ge,viewportW:J,onWindowResize:_e,isNarrow:ve,isStacked:ye,clampWidth:be,boardStyle:xe,colsRef:Se,dragging:Ce,panelEl:we,endDrag:Te,onSplitterMouseDown:Z,onSplitterDblClick:Ee,leftDrawerOpen:De,leftHidden:Oe,toggleLeft:ke,onLeftEsc:Ae,rightHidden:je,toggleRight:Me,onSelectProject:Ne,createOpen:Pe,onCreateClick:Fe,onTaskCreated:Le,runTask:Re,stoppingTaskIds:Be,stopTask:Ve,completingTaskIds:Q,completeTask:He,reopenTask:Ue,onRemoveProject:We,deleteTask:Ge,consoleRef:Ke,defaultProjectPath:qe,onDispatch:Je,promptDialogOpen:Ye,savingPrompt:Xe,selectedProjectPrompt:Ze,onSavePromptDraft:Qe,get $t(){return X},get Fold(){return he},get Expand(){return ue},WorkbenchProjectPanel:Ki,WorkbenchKanban:mo,OrchestratorConsole:Zs,WorkbenchDefaultPromptDialog:gc,WorkbenchTaskCreateDialog:Lc};return Object.defineProperty($e,"__isScriptSetup",{enumerable:!1,value:!0}),$e}});c(),R(),W();var Xc={class:`board__top`},Zc=[`title`,`aria-label`,`aria-expanded`],Qc={class:`board__brand`},$c={class:`board__brand-text`},el={class:`board__title`},tl={class:`board__stats`},nl={class:`board__stat`},rl={class:`board__stat-label`},il=[`title`],al={class:`board__stat-label`},ol={class:`board__stat`},sl={class:`board__stat-label`},cl={class:`board__stat`},ll={class:`board__stat-label`},ul=[`title`],dl={class:`board__main`},fl={class:`board__main-head`},pl={class:`board__project-icon-slot`,"aria-hidden":`true`},ml=[`src`],hl={key:0,viewBox:`0 0 24 24`,width:`16`,height:`16`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},gl={key:1,viewBox:`0 0 24 24`,width:`16`,height:`16`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},_l={class:`board__main-title`},vl={class:`board__project-name`},yl=[`title`],bl={key:1,class:`board__project-path`},xl={class:`board__head-actions`},Sl={class:`board__view-switch`,role:`tablist`},Cl=[`aria-selected`,`aria-label`,`title`],wl=[`aria-selected`,`aria-label`,`title`],Tl=[`placeholder`,`aria-label`],El=[`aria-label`,`title`],Dl=[`title`];function Ol(t,n,i,a,o,s){let c=l;return K(),S(`div`,{class:`board`,style:u(a.boardStyle)},[x(`header`,Xc,[J(` 左栏的开合。宽屏=收起/展开常驻那一栏;窄屏=抽屉 `),x(`button`,{type:`button`,class:w([`board__icon-btn board__fold-btn`,{"is-on":!a.leftHidden}]),title:a.leftHidden?a.$t(`@WORKBENCH:展开项目列表`):a.$t(`@WORKBENCH:收起项目列表`),"aria-label":a.leftHidden?a.$t(`@WORKBENCH:展开项目列表`):a.$t(`@WORKBENCH:收起项目列表`),"aria-expanded":!a.leftHidden,onClick:a.toggleLeft},[a.leftHidden?(K(),r(c,{key:1},{default:L(()=>[e(a.Expand)]),_:1})):(K(),r(c,{key:0},{default:L(()=>[e(a.Fold)]),_:1}))],10,Zc),x(`div`,Qc,[x(`div`,$c,[x(`h1`,el,E(a.$t(`@WORKBENCH:多项目编排台`)),1)])]),x(`div`,tl,[x(`span`,nl,[x(`span`,rl,E(a.$t(`@WORKBENCH:项目`)),1),J(` is-zero:2026-10-14 评审轮。四项统计同权重视觉上抢不出主次,
287
- 0 是"此刻没有"的信号,该退到跟标签同一档,让非零值成为主角 `),x(`strong`,{class:w([`board__stat-value`,{"is-zero":a.headerStats.projects===0}])},E(a.headerStats.projects),3)]),x(`span`,{class:`board__stat`,title:a.$t(`@WORKBENCH:看板上全部任务(含已从项目列表移除的项目)`)},[x(`span`,al,E(a.$t(`@WORKBENCH:全部任务`)),1),x(`strong`,{class:w([`board__stat-value`,{"is-zero":a.headerStats.tasks===0}])},E(a.headerStats.tasks),3)],8,il),x(`span`,ol,[x(`span`,sl,E(a.$t(`@WORKBENCH:活跃执行`)),1),x(`strong`,{class:w([`board__stat-value`,{"is-live":a.headerStats.running>0,"is-zero":a.headerStats.running===0}])},E(a.headerStats.running),3)]),x(`span`,cl,[x(`span`,ll,E(a.$t(`@WORKBENCH:今日完成`)),1),x(`strong`,{class:w([`board__stat-value`,{"is-zero":a.headerStats.todayDone===0}])},E(a.headerStats.todayDone),3)])])]),x(`div`,{ref:`colsRef`,class:w([`board__cols`,{"is-resizing":a.dragging!==null}])},[J(` 抽屉打开时的点击捕获层:点空白处收起。
286
+ `),x(`div`,zc,[e(a.AttachmentZone,{attachments:a.drafts,"is-image":a.isImageAttachment,"human-size":a.humanSize,"is-uploading":a.attachBusy,"is-paste-hover":a.dragging,"on-pick":a.onPickAttachment,"on-remove":a.onRemoveAttachment,"raw-base":a.DRAFT_RAW_BASE,onDragover:n[6]||=N(e=>a.dragging=!0,[`prevent`]),onDragenter:n[7]||=N(e=>a.dragging=!0,[`prevent`]),onDragleave:n[8]||=e=>a.dragging=!1},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`]),x(`p`,Bc,D(a.$t(`@WORKBENCH:粘贴图片以快速添加`)),1)]),a.error?(K(),S(`p`,Vc,D(a.error),1)):J(`v-if`,!0)],32)]),_:1},8,[`model-value`,`title`])}var Kc=Z(Dc,[[`render`,Gc],[`__scopeId`,`data-v-c60e660a`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchTaskCreateDialog.vue`]]);c(),V();var qc=`wb.boardProject.v1`,Jc=`wb.boardView.v1`,Yc=5e3,Xc=3e4,Zc=`wb.boardLayout.v1`,Qc=180,$c=420,el=260,tl=900,nl=.26,rl=.46,il=f({__name:`WorkbenchBoard`,props:{openedTaskId:{type:[String,null],required:!0}},emits:[`open-task`,`board-tasks`,`locate-task`],setup(e,{expose:n,emit:r}){n();let i=e,a=r,{projects:s,boardTasks:c,currentProjectPath:l,loading:u,loadProjects:d,removeProject:f}=xt();U(c,e=>a(`board-tasks`,e),{immediate:!0});let{activity:p,running:m,dispatching:h,maxInstructionChars:g,defaultPrompt:_,projectPrompts:v,reports:y,generatingReport:b,reportIntervalMs:x,loadOrchestrator:S,dispatch:C,saveDefaultPrompt:T,saveProjectPrompt:E,loadReports:D,generateReport:ee,setReportInterval:O}=gt(),{active:te}=lt(),ne=(()=>{try{return localStorage.getItem(qc)}catch{return null}})(),k=P(ne||``);U(k,e=>{try{localStorage.setItem(qc,e)}catch{}});let re=P((()=>{try{return localStorage.getItem(Jc)===`list`?`list`:`kanban`}catch{return`kanban`}})());U(re,e=>{try{localStorage.setItem(Jc,e)}catch{}});let A=P(``),j=P(!1),M=P(null);function ie(){j.value=!j.value,j.value&&t(()=>M.value?.focus())}function ae(){j.value=!1}function oe(){A.value.trim()||(j.value=!1)}let se=Y(()=>k.value&&s.value.find(e=>e.key===k.value)||null),{isIconBroken:ce,markIconFailed:le}=Ie();U(s,e=>{k.value&&(e.some(e=>e.key===k.value)||(k.value=``))});let N=!1;function F(){if(N||(N=!0,ne!==null))return;let e=l.value?$(l.value):``;e&&s.value.some(t=>t.key===e)&&(k.value=e)}let L=Y(()=>{let e=new Map(s.value.map(e=>[e.key,e.name])),t={};for(let n of c.value)n.projectPath&&(t[n.projectPath]=e.get($(n.projectPath))||``);return t}),R=Y(()=>{if(!k.value)return c.value;let e=k.value;return c.value.filter(t=>$(t.projectPath)===e)}),z=Y(()=>ze(y.value,c.value)),B=Y(()=>{let e=new Date;e.setHours(0,0,0,0);let t=e.getTime();return{projects:s.value.length,tasks:c.value.length,running:m.value.length,todayDone:p.value.filter(e=>e.kind===`done`&&e.at&&new Date(e.at).getTime()>=t).length}});function V(e){a(`open-task`,{taskId:e.id,projectPath:e.projectPath})}let H=null,W=!1,G=null;async function K(e=!0){if(!W){W=!0;try{await Promise.all([d(e),S(e)])}finally{W=!1}}}function pe(){document.hidden||(K(!0),D(!0))}o(async()=>{window.addEventListener(`resize`,_e),await K(!1),D(!0),F(),H=setInterval(()=>{document.hidden||K(!0)},Yc),G=setInterval(()=>{document.hidden||D(!0)},Xc),document.addEventListener(`visibilitychange`,pe)}),w(()=>{window.removeEventListener(`resize`,_e),H&&=(clearInterval(H),null),G&&=(clearInterval(G),null),document.removeEventListener(`visibilitychange`,pe)});let q=de({left:null,right:null,leftCollapsed:!1,rightCollapsed:!1});function me(){try{let e=localStorage.getItem(Zc);if(!e)return;let t=JSON.parse(e);typeof t.left==`number`&&Number.isFinite(t.left)&&(q.left=t.left),typeof t.right==`number`&&Number.isFinite(t.right)&&(q.right=t.right),q.leftCollapsed=t.leftCollapsed===!0,q.rightCollapsed=t.rightCollapsed===!0}catch{}}me();function ge(){try{localStorage.setItem(Zc,JSON.stringify(q))}catch{}}let J=P(typeof window>`u`?1920:window.innerWidth);function _e(){J.value=window.innerWidth}let ve=Y(()=>J.value<=1024),ye=Y(()=>J.value<=860);function be(e,t){let n=e===`left`?Qc:el,r=Math.min(e===`left`?$c:tl,J.value*(e===`left`?nl:rl));return Math.round(Math.min(Math.max(t,n),Math.max(n,r)))}let xe=Y(()=>{let e={};return q.left!=null&&(e[`--wb-left-w`]=be(`left`,q.left)+`px`),q.right!=null&&!ye.value&&(e[`--wb-right-w`]=be(`right`,q.right)+`px`),e}),Se=P(null),Ce=P(null);function we(e){return Se.value?.querySelector(e===`left`?`.board__left`:`.oc`)}function Te(e){window.removeEventListener(`mousemove`,e),document.body.style.userSelect=``,document.body.style.cursor=``,Ce.value=null,ge()}function Z(e,t){if(e===`left`?ve.value:ye.value)return;let n=we(e);if(!n)return;t.preventDefault();let r=t.clientX,i=n.getBoundingClientRect().width;Ce.value=e,document.body.style.userSelect=`none`,document.body.style.cursor=`col-resize`;let a=t=>{let n=(t.clientX-r)*(e===`left`?1:-1);q[e]=be(e,i+n)};window.addEventListener(`mousemove`,a),window.addEventListener(`mouseup`,()=>Te(a),{once:!0})}function Ee(e){q[e]=null,ge()}let De=P(!1),Oe=Y(()=>ve.value?!De.value:q.leftCollapsed);function ke(){if(ve.value){De.value=!De.value;return}q.leftCollapsed=!q.leftCollapsed,ge()}function Ae(){ve.value&&(De.value=!1)}let je=Y(()=>q.rightCollapsed&&!ye.value);function Me(){q.rightCollapsed=!q.rightCollapsed,ge()}function Ne(e){k.value=e?e.key:``,De.value=!1}let Pe=P(!1);function Fe(){Pe.value=!0}async function Le(e){if(await K(!0),e.openEditor){a(`open-task`,{taskId:e.task.id,projectPath:e.task.projectPath||``});return}I.success(X(`@WORKBENCH:已创建任务`))}async function Re(e){if(e.runningJobs>0)return;let t=`/api/workbench/tasks/${encodeURIComponent(e.id)}/run`,n=await fetch(t,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({executor:te.value})}).then(e=>e.json()).catch(()=>null);if(!n?.success){I.error(n?.error||X(`@WORKBENCH:执行失败`));return}I.success(X(`@WORKBENCH:已开始执行`)),await K(!0)}let Be=new Set;async function Ve(e){if(Be.has(e.id))return;let t=e.live?.jobId;if(!t){I.error(X(`@WORKBENCH:停止失败`));return}try{await fe.confirm(X(`@WORKBENCH:确认停止执行?已输出的内容会保留。`),X(`@WORKBENCH:停止执行`),{confirmButtonText:X(`@WORKBENCH:停止`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}Be.add(e.id);try{let e=await fetch(`/api/workbench/jobs/${encodeURIComponent(t)}/cancel`,{method:`POST`}).then(e=>e.json()).catch(()=>null);if(!e?.success){I.error(e?.error||X(`@WORKBENCH:停止失败`));return}I.success(X(`@WORKBENCH:已发送停止信号`)),await K(!0)}finally{Be.delete(e.id)}}let Q=new Set;async function He(e){if(!Q.has(e.id)){if(e.runningJobs>0)try{await fe.confirm(X(`@WORKBENCH:这条任务还在执行,标记完成会同时把它停掉。已输出的内容会保留。`),X(`@WORKBENCH:标记为已完成`),{confirmButtonText:X(`@WORKBENCH:标记完成`),cancelButtonText:X(`@WORKBENCH:取消`),type:`warning`})}catch{return}Q.add(e.id);try{let t=await fetch(`/api/workbench/tasks/${encodeURIComponent(e.id)}/done`,{method:`POST`}).then(e=>e.json()).catch(()=>null);if(!t?.success){I.error(t?.error||X(`@WORKBENCH:标记失败`));return}I.success(X(`@WORKBENCH:已标记为已完成`)),await K(!0)}finally{Q.delete(e.id)}}}async function Ue(e){if(!Q.has(e.id)){Q.add(e.id);try{let t=await fetch(`/api/workbench/tasks/${encodeURIComponent(e.id)}/done`,{method:`DELETE`}).then(e=>e.json()).catch(()=>null);if(!t?.success){I.error(t?.error||X(`@WORKBENCH:撤销失败`));return}I.success(X(`@WORKBENCH:已撤销完成标记`)),await K(!0)}finally{Q.delete(e.id)}}}async function We(e){let{ok:t,keptTasks:n}=await f(e.path);t&&(I.success(n>0?X(`@WORKBENCH:已移除项目,{n} 条任务仍保留在「全部项目」下`,{n}):X(`@WORKBENCH:已移除项目`)),await K(!0))}async function Ge(e){let t=(e.title||``).trim()||X(`@WORKBENCH:未命名任务`);try{await fe.confirm(X(`@WORKBENCH:删除任务「{title}」?`,{title:t}),X(`@WORKBENCH:确认`),{type:`warning`})}catch{return}let n=await fetch(`/api/workbench/tasks/${encodeURIComponent(e.id)}`,{method:`DELETE`}).then(e=>e.json()).catch(()=>null);if(n&&n.success===!1){I.error(n.error||X(`@WORKBENCH:删除失败`));return}await K(!0)}async function Ke(e,t){let n=await fetch(`/api/workbench/tasks/${encodeURIComponent(e.id)}/move`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({projectPath:t})}).then(e=>e.json()).catch(()=>null);if(!n?.success){I.error(n?.error||X(`@WORKBENCH:移动失败`));return}let r=s.value.find(e=>$(e.path)===$(t))?.name||t;I.success(X(`@WORKBENCH:已移动到「{name}」`,{name:r})),await K(!0)}let qe=P(null),Je=Y(()=>se.value?.path||l.value);async function Ye(e){let t=await C({text:e.text,projectPath:e.projectPath,autoRun:e.autoRun,attachments:e.attachments,useDefaultPrompt:e.useDefaultPrompt,executor:e.executor});t&&(qe.value?.clearAttachments(),qe.value?.clearDraft(),I.success(t.ran?X(`@WORKBENCH:已派发并开始执行`):X(`@WORKBENCH:已派发(只建任务未执行)`)),await K(!0))}let Xe=P(!1),Ze=P(!1),Qe=Y(()=>{let e=se.value?.key;return e&&v.value?.[e]?.prompt||``});async function $e(e){if(Ze.value)return;let t=e.globalPrompt.trim(),n=e.projectPrompt.trim(),r=se.value;Ze.value=!0;try{let e=!0;t!==(_.value||``).trim()&&(e=await T(t)),e&&r&&n!==Qe.value.trim()&&(e=await E(r.path,n)),e&&(Xe.value=!1)}finally{Ze.value=!1}}let et={props:i,emit:a,projects:s,boardTasks:c,currentProjectPath:l,loading:u,loadProjects:d,removeProject:f,activity:p,running:m,dispatching:h,maxInstructionChars:g,defaultPrompt:_,projectPrompts:v,reports:y,generatingReport:b,reportIntervalMs:x,loadOrchestrator:S,dispatch:C,saveDefaultPrompt:T,saveProjectPrompt:E,loadReports:D,generateReport:ee,setReportInterval:O,boardExecutor:te,SELECTED_KEY:qc,savedSelection:ne,selectedKey:k,VIEW_KEY:Jc,view:re,search:A,searchOpen:j,searchInputRef:M,toggleSearch:ie,closeSearch:ae,onSearchBlur:oe,selectedProject:se,isIconBroken:ce,markIconFailed:le,get defaultSelectionApplied(){return N},set defaultSelectionApplied(e){N=e},applyDefaultSelection:F,projectLabels:L,visibleTasks:R,taskPercents:z,headerStats:B,onOpenTask:V,POLL_MS:Yc,get pollTimer(){return H},set pollTimer(e){H=e},get inFlight(){return W},set inFlight(e){W=e},REPORT_POLL_MS:Xc,get reportPollTimer(){return G},set reportPollTimer(e){G=e},refresh:K,onVisibilityChange:pe,LAYOUT_KEY:Zc,LEFT_W_MIN:Qc,LEFT_W_MAX:$c,RIGHT_W_MIN:el,RIGHT_W_MAX:tl,LEFT_W_SHARE:nl,RIGHT_W_SHARE:rl,layout:q,readLayout:me,saveLayout:ge,viewportW:J,onWindowResize:_e,isNarrow:ve,isStacked:ye,clampWidth:be,boardStyle:xe,colsRef:Se,dragging:Ce,panelEl:we,endDrag:Te,onSplitterMouseDown:Z,onSplitterDblClick:Ee,leftDrawerOpen:De,leftHidden:Oe,toggleLeft:ke,onLeftEsc:Ae,rightHidden:je,toggleRight:Me,onSelectProject:Ne,createOpen:Pe,onCreateClick:Fe,onTaskCreated:Le,runTask:Re,stoppingTaskIds:Be,stopTask:Ve,completingTaskIds:Q,completeTask:He,reopenTask:Ue,onRemoveProject:We,deleteTask:Ge,moveTask:Ke,consoleRef:qe,defaultProjectPath:Je,onDispatch:Ye,promptDialogOpen:Xe,savingPrompt:Ze,selectedProjectPrompt:Qe,onSavePromptDraft:$e,get $t(){return X},get Fold(){return he},get Expand(){return ue},WorkbenchProjectPanel:Ki,WorkbenchKanban:Co,OrchestratorConsole:oc,WorkbenchDefaultPromptDialog:Tc,WorkbenchTaskCreateDialog:Kc};return Object.defineProperty(et,"__isScriptSetup",{enumerable:!1,value:!0}),et}});c(),R(),W();var al={class:`board__top`},ol=[`title`,`aria-label`,`aria-expanded`],sl={class:`board__brand`},cl={class:`board__brand-text`},ll={class:`board__title`},ul={class:`board__stats`},dl={class:`board__stat`},fl={class:`board__stat-label`},pl=[`title`],ml={class:`board__stat-label`},hl={class:`board__stat`},gl={class:`board__stat-label`},_l={class:`board__stat`},vl={class:`board__stat-label`},yl=[`title`],bl={class:`board__main`},xl={class:`board__main-head`},Sl={class:`board__project-icon-slot`,"aria-hidden":`true`},Cl=[`src`],wl={key:0,viewBox:`0 0 24 24`,width:`16`,height:`16`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},Tl={key:1,viewBox:`0 0 24 24`,width:`16`,height:`16`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},El={class:`board__main-title`},Dl={class:`board__project-name`},Ol=[`title`],kl={key:1,class:`board__project-path`},Al={class:`board__head-actions`},jl={class:`board__view-switch`,role:`tablist`},Ml=[`aria-selected`,`aria-label`,`title`],Nl=[`aria-selected`,`aria-label`,`title`],Pl=[`placeholder`,`aria-label`],Fl=[`aria-label`,`title`],Il=[`title`];function Ll(t,n,i,a,o,s){let c=l;return K(),S(`div`,{class:`board`,style:u(a.boardStyle)},[x(`header`,al,[J(` 左栏的开合。宽屏=收起/展开常驻那一栏;窄屏=抽屉 `),x(`button`,{type:`button`,class:T([`board__icon-btn board__fold-btn`,{"is-on":!a.leftHidden}]),title:a.leftHidden?a.$t(`@WORKBENCH:展开项目列表`):a.$t(`@WORKBENCH:收起项目列表`),"aria-label":a.leftHidden?a.$t(`@WORKBENCH:展开项目列表`):a.$t(`@WORKBENCH:收起项目列表`),"aria-expanded":!a.leftHidden,onClick:a.toggleLeft},[a.leftHidden?(K(),r(c,{key:1},{default:L(()=>[e(a.Expand)]),_:1})):(K(),r(c,{key:0},{default:L(()=>[e(a.Fold)]),_:1}))],10,ol),x(`div`,sl,[x(`div`,cl,[x(`h1`,ll,D(a.$t(`@WORKBENCH:多项目编排台`)),1)])]),x(`div`,ul,[x(`span`,dl,[x(`span`,fl,D(a.$t(`@WORKBENCH:项目`)),1),J(` is-zero:2026-10-14 评审轮。四项统计同权重视觉上抢不出主次,
287
+ 0 是"此刻没有"的信号,该退到跟标签同一档,让非零值成为主角 `),x(`strong`,{class:T([`board__stat-value`,{"is-zero":a.headerStats.projects===0}])},D(a.headerStats.projects),3)]),x(`span`,{class:`board__stat`,title:a.$t(`@WORKBENCH:看板上全部任务(含已从项目列表移除的项目)`)},[x(`span`,ml,D(a.$t(`@WORKBENCH:全部任务`)),1),x(`strong`,{class:T([`board__stat-value`,{"is-zero":a.headerStats.tasks===0}])},D(a.headerStats.tasks),3)],8,pl),x(`span`,hl,[x(`span`,gl,D(a.$t(`@WORKBENCH:活跃执行`)),1),x(`strong`,{class:T([`board__stat-value`,{"is-live":a.headerStats.running>0,"is-zero":a.headerStats.running===0}])},D(a.headerStats.running),3)]),x(`span`,_l,[x(`span`,vl,D(a.$t(`@WORKBENCH:今日完成`)),1),x(`strong`,{class:T([`board__stat-value`,{"is-zero":a.headerStats.todayDone===0}])},D(a.headerStats.todayDone),3)])])]),x(`div`,{ref:`colsRef`,class:T([`board__cols`,{"is-resizing":a.dragging!==null}])},[J(` 抽屉打开时的点击捕获层:点空白处收起。
288
288
  只在窄屏 + 打开时才 display:block(见媒体查询),宽屏下是个不占位的空 div。
289
289
  不加遮罩底色而是全透明 —— 只是为了接住点击,不是为了压暗看板;
290
- 真要压暗就得处理深色主题下半透明背景叠不实的老问题(见 NOTES §2)。 `),x(`div`,{class:w([`board__scrim`,{"is-on":a.leftDrawerOpen}]),"aria-hidden":`true`,onClick:n[0]||=e=>a.leftDrawerOpen=!1},null,2),x(`aside`,{class:w([`board__left`,{"is-collapsed":a.leftHidden}]),onKeydown:F(a.onLeftEsc,[`esc`])},[e(a.WorkbenchProjectPanel,{projects:a.projects,"selected-key":a.selectedKey,loading:a.loading,onSelect:a.onSelectProject,onRemove:a.onRemoveProject},null,8,[`projects`,`selected-key`,`loading`])],34),J(` 左栏分隔条:左栏收起 / 窄屏抽屉模式下不占位(不渲染 / 媒体查询里 display:none) `),a.leftHidden?J(`v-if`,!0):(K(),S(`div`,{key:0,class:`board__splitter board__splitter--left`,role:`separator`,"aria-orientation":`vertical`,title:a.$t(`@WORKBENCH:拖动调整项目列表宽度,双击恢复默认`),onMousedown:n[1]||=e=>a.onSplitterMouseDown(`left`,e),onDblclick:n[2]||=e=>a.onSplitterDblClick(`left`)},null,40,ul)),x(`main`,dl,[x(`div`,fl,[J(` 项目图标槽:和左栏项目行、顶栏目录胶囊同一个形态契约 ——
290
+ 真要压暗就得处理深色主题下半透明背景叠不实的老问题(见 NOTES §2)。 `),x(`div`,{class:T([`board__scrim`,{"is-on":a.leftDrawerOpen}]),"aria-hidden":`true`,onClick:n[0]||=e=>a.leftDrawerOpen=!1},null,2),x(`aside`,{class:T([`board__left`,{"is-collapsed":a.leftHidden}]),onKeydown:F(a.onLeftEsc,[`esc`])},[e(a.WorkbenchProjectPanel,{projects:a.projects,"selected-key":a.selectedKey,loading:a.loading,onSelect:a.onSelectProject,onRemove:a.onRemoveProject},null,8,[`projects`,`selected-key`,`loading`])],34),J(` 左栏分隔条:左栏收起 / 窄屏抽屉模式下不占位(不渲染 / 媒体查询里 display:none) `),a.leftHidden?J(`v-if`,!0):(K(),S(`div`,{key:0,class:`board__splitter board__splitter--left`,role:`separator`,"aria-orientation":`vertical`,title:a.$t(`@WORKBENCH:拖动调整项目列表宽度,双击恢复默认`),onMousedown:n[1]||=e=>a.onSplitterMouseDown(`left`,e),onDblclick:n[2]||=e=>a.onSplitterDblClick(`left`)},null,40,yl)),x(`main`,bl,[x(`div`,xl,[J(` 项目图标槽:和左栏项目行、顶栏目录胶囊同一个形态契约 ——
291
291
  有 favicon 画 <img>,加载失败 / 没有就退回字形(folder / layout-grid,
292
- 均已 Tabler 化);「全部项目」没有单一项目可画,退回宫格字形。 `),x(`span`,pl,[a.selectedProject&&a.selectedProject.iconUrl&&!a.isIconBroken(a.selectedProject.iconUrl)?(K(),S(`img`,{key:0,class:`board__project-icon-img`,src:a.selectedProject.iconUrl,alt:``,onError:n[3]||=e=>a.markIconFailed(a.selectedProject.iconUrl)},null,40,ml)):(K(),r(c,{key:1,class:`board__project-icon-glyph`},{default:L(()=>[J(` folder / layout-grid(Tabler icons,MIT)。2026-10-16 从 EP <Folder/>
292
+ 均已 Tabler 化);「全部项目」没有单一项目可画,退回宫格字形。 `),x(`span`,Sl,[a.selectedProject&&a.selectedProject.iconUrl&&!a.isIconBroken(a.selectedProject.iconUrl)?(K(),S(`img`,{key:0,class:`board__project-icon-img`,src:a.selectedProject.iconUrl,alt:``,onError:n[3]||=e=>a.markIconFailed(a.selectedProject.iconUrl)},null,40,Cl)):(K(),r(c,{key:1,class:`board__project-icon-glyph`},{default:L(()=>[J(` folder / layout-grid(Tabler icons,MIT)。2026-10-16 从 EP <Folder/>
293
293
  <Grid/> 换 Tabler:这一行(槽 + 标题 + 视图切换 + 搜索)现在全部同族。
294
- 字形尺寸保持 16px(槽 24px,比槽小一档的"身份轻档",不跟 32px 行看齐)。 `),a.selectedProject?(K(),S(`svg`,hl,[...n[16]||=[x(`path`,{d:`M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2`},null,-1)]])):(K(),S(`svg`,gl,[...n[17]||=[x(`path`,{d:`M4 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`},null,-1),x(`path`,{d:`M14 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`},null,-1),x(`path`,{d:`M4 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`},null,-1),x(`path`,{d:`M14 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`},null,-1)]]))]),_:1}))]),x(`div`,_l,[x(`h2`,vl,E(a.selectedProject?a.selectedProject.name:a.$t(`@WORKBENCH:全部项目`)),1),a.selectedProject?(K(),S(`span`,{key:0,class:`board__project-path`,title:a.selectedProject.path},E(a.selectedProject.path),9,yl)):(K(),S(`span`,bl,E(a.$t(`@WORKBENCH:共 {n} 个项目的任务`,{n:a.projects.length})),1))]),J(` 头部右侧动作区:视图切换 + 搜索。
294
+ 字形尺寸保持 16px(槽 24px,比槽小一档的"身份轻档",不跟 32px 行看齐)。 `),a.selectedProject?(K(),S(`svg`,wl,[...n[16]||=[x(`path`,{d:`M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2`},null,-1)]])):(K(),S(`svg`,Tl,[...n[17]||=[x(`path`,{d:`M4 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`},null,-1),x(`path`,{d:`M14 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`},null,-1),x(`path`,{d:`M4 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`},null,-1),x(`path`,{d:`M14 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4`},null,-1)]]))]),_:1}))]),x(`div`,El,[x(`h2`,Dl,D(a.selectedProject?a.selectedProject.name:a.$t(`@WORKBENCH:全部项目`)),1),a.selectedProject?(K(),S(`span`,{key:0,class:`board__project-path`,title:a.selectedProject.path},D(a.selectedProject.path),9,Ol)):(K(),S(`span`,kl,D(a.$t(`@WORKBENCH:共 {n} 个项目的任务`,{n:a.projects.length})),1))]),J(` 头部右侧动作区:视图切换 + 搜索。
295
295
  2026-10-16 从看板自己的工具条(原 .kb__toolbar)搬上来的 ——
296
296
  那一行原来只有一枚「80/82 任务完成」徽章(已去掉),
297
297
  位置正好,视图与筛选从此贴着项目名,不再单独占一行。
298
- 形态收成图标:切换两枚(aria-label 说话),搜索默认只露一枚放大镜。 `),x(`div`,xl,[x(`div`,Sl,[x(`button`,{type:`button`,role:`tab`,class:w([`board__view-btn`,{"is-active":a.view===`kanban`}]),"aria-selected":a.view===`kanban`,"aria-label":a.$t(`@WORKBENCH:看板视图`),title:a.$t(`@WORKBENCH:看板视图`),onClick:n[4]||=e=>a.view=`kanban`},[e(c,null,{default:L(()=>[J(` layout-kanban(Tabler icons,MIT)。2026-10-16 从 EP <Grid/> 换 Tabler:
299
- 与同排的列表/搜索/左侧漏斗同族(EP 实心 vs Tabler 描边混排有"色差感") `),n[18]||=x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M4 4l6 0`}),x(`path`,{d:`M14 4l6 0`}),x(`path`,{d:`M4 10a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -8`}),x(`path`,{d:`M14 10a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v2a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -2`})],-1)]),_:1})],10,Cl),x(`button`,{type:`button`,role:`tab`,class:w([`board__view-btn`,{"is-active":a.view===`list`}]),"aria-selected":a.view===`list`,"aria-label":a.$t(`@WORKBENCH:列表视图`),title:a.$t(`@WORKBENCH:列表视图`),onClick:n[5]||=e=>a.view=`list`},[e(c,null,{default:L(()=>[J(` list(Tabler icons,MIT):从 EP <Menu/> 换 Tabler `),n[19]||=x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M9 6l11 0`}),x(`path`,{d:`M9 12l11 0`}),x(`path`,{d:`M9 18l11 0`}),x(`path`,{d:`M5 6l0 .01`}),x(`path`,{d:`M5 12l0 .01`}),x(`path`,{d:`M5 18l0 .01`})],-1)]),_:1})],10,wl)]),x(`div`,{class:w([`board__head-search`,{"is-open":a.searchOpen}])},[A(x(`input`,{ref:`searchInputRef`,class:`board__search-input`,type:`search`,"onUpdate:modelValue":n[6]||=e=>a.search=e,placeholder:a.$t(`@WORKBENCH:搜索任务标题或描述`),"aria-label":a.$t(`@WORKBENCH:搜索任务标题或描述`),onBlur:a.onSearchBlur,onKeydown:F(a.closeSearch,[`esc`])},null,40,Tl),[[G,a.search]]),J(` mousedown.prevent:不让这一下先把输入框的焦点弄丢,
298
+ 形态收成图标:切换两枚(aria-label 说话),搜索默认只露一枚放大镜。 `),x(`div`,Al,[x(`div`,jl,[x(`button`,{type:`button`,role:`tab`,class:T([`board__view-btn`,{"is-active":a.view===`kanban`}]),"aria-selected":a.view===`kanban`,"aria-label":a.$t(`@WORKBENCH:看板视图`),title:a.$t(`@WORKBENCH:看板视图`),onClick:n[4]||=e=>a.view=`kanban`},[e(c,null,{default:L(()=>[J(` layout-kanban(Tabler icons,MIT)。2026-10-16 从 EP <Grid/> 换 Tabler:
299
+ 与同排的列表/搜索/左侧漏斗同族(EP 实心 vs Tabler 描边混排有"色差感") `),n[18]||=x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M4 4l6 0`}),x(`path`,{d:`M14 4l6 0`}),x(`path`,{d:`M4 10a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -8`}),x(`path`,{d:`M14 10a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v2a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -2`})],-1)]),_:1})],10,Ml),x(`button`,{type:`button`,role:`tab`,class:T([`board__view-btn`,{"is-active":a.view===`list`}]),"aria-selected":a.view===`list`,"aria-label":a.$t(`@WORKBENCH:列表视图`),title:a.$t(`@WORKBENCH:列表视图`),onClick:n[5]||=e=>a.view=`list`},[e(c,null,{default:L(()=>[J(` list(Tabler icons,MIT):从 EP <Menu/> 换 Tabler `),n[19]||=x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M9 6l11 0`}),x(`path`,{d:`M9 12l11 0`}),x(`path`,{d:`M9 18l11 0`}),x(`path`,{d:`M5 6l0 .01`}),x(`path`,{d:`M5 12l0 .01`}),x(`path`,{d:`M5 18l0 .01`})],-1)]),_:1})],10,Nl)]),x(`div`,{class:T([`board__head-search`,{"is-open":a.searchOpen}])},[A(x(`input`,{ref:`searchInputRef`,class:`board__search-input`,type:`search`,"onUpdate:modelValue":n[6]||=e=>a.search=e,placeholder:a.$t(`@WORKBENCH:搜索任务标题或描述`),"aria-label":a.$t(`@WORKBENCH:搜索任务标题或描述`),onBlur:a.onSearchBlur,onKeydown:F(a.closeSearch,[`esc`])},null,40,Pl),[[G,a.search]]),J(` mousedown.prevent:不让这一下先把输入框的焦点弄丢,
300
300
  否则"点开 → 再点图标想收起"会变成 blur 收起 + click 又重新展开 `),x(`button`,{type:`button`,class:`board__search-btn`,"aria-label":a.$t(`@WORKBENCH:搜索任务标题或描述`),title:a.$t(`@WORKBENCH:搜索任务标题或描述`),onMousedown:n[7]||=N(()=>{},[`prevent`]),onClick:a.toggleSearch},[e(c,null,{default:L(()=>[J(` search(Tabler icons,MIT):从 EP <Search/> 换 Tabler,与左栏项目列表
301
- 那枚同一形状(14/描边 2)—— 用户 2026-10-16 反馈「这个也改一下」 `),n[20]||=x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M3 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0`}),x(`path`,{d:`M21 21l-6 -6`})],-1)]),_:1})],40,El)],2)])]),e(a.WorkbenchKanban,{tasks:a.visibleTasks,"project-labels":a.projectLabels,"task-percents":a.taskPercents,"show-project-label":!a.selectedProject,"opened-task-id":a.props.openedTaskId,view:a.view,"onUpdate:view":n[8]||=e=>a.view=e,search:a.search,"onUpdate:search":n[9]||=e=>a.search=e,onOpenTask:a.onOpenTask,onRunTask:a.runTask,onStopTask:a.stopTask,onCompleteTask:a.completeTask,onReopenTask:a.reopenTask,onDeleteTask:a.deleteTask,onCreateTask:a.onCreateClick},null,8,[`tasks`,`project-labels`,`task-percents`,`show-project-label`,`opened-task-id`,`view`,`search`])]),J(` 右栏分隔条:右栏收起 / 竖排(≤860)时不占位 `),!a.rightHidden&&!a.isStacked?(K(),S(`div`,{key:1,class:`board__splitter board__splitter--right`,role:`separator`,"aria-orientation":`vertical`,title:a.$t(`@WORKBENCH:拖动调整主 Agent 控制台宽度,双击恢复默认`),onMousedown:n[10]||=e=>a.onSplitterMouseDown(`right`,e),onDblclick:n[11]||=e=>a.onSplitterDblClick(`right`)},null,40,Dl)):J(`v-if`,!0),e(a.OrchestratorConsole,{ref:`consoleRef`,running:a.running,"selected-project":a.selectedProject,dispatching:a.dispatching,"today-done":a.headerStats.todayDone,collapsed:a.rightHidden,"default-prompt":a.defaultPrompt,"project-prompts":a.projectPrompts,reports:a.reports,"report-interval-ms":a.reportIntervalMs,"generating-report":a.generatingReport,"max-instruction-chars":a.maxInstructionChars,onToggleCollapse:a.toggleRight,onDispatch:a.onDispatch,onGenerateReport:a.generateReport,onSetReportInterval:a.setReportInterval,onOpenPromptSettings:n[12]||=e=>a.promptDialogOpen=!0,onLocateTask:n[13]||=e=>a.emit(`locate-task`,e)},null,8,[`running`,`selected-project`,`dispatching`,`today-done`,`collapsed`,`default-prompt`,`project-prompts`,`reports`,`report-interval-ms`,`generating-report`,`max-instruction-chars`,`onGenerateReport`,`onSetReportInterval`])],2),J(` 派发预设提示词:全局一条 + 选中项目一条,写完即生效于之后的派发 `),e(a.WorkbenchDefaultPromptDialog,{modelValue:a.promptDialogOpen,"onUpdate:modelValue":n[14]||=e=>a.promptDialogOpen=e,"default-prompt":a.defaultPrompt,"project-path":a.selectedProject?.path||``,"project-name":a.selectedProject?.name||``,"project-prompt":a.selectedProjectPrompt,saving:a.savingPrompt,onSave:a.onSavePromptDraft},null,8,[`modelValue`,`default-prompt`,`project-path`,`project-name`,`project-prompt`,`saving`]),J(` 新建任务:弹窗里问清字段,建完就关 `),e(a.WorkbenchTaskCreateDialog,{modelValue:a.createOpen,"onUpdate:modelValue":n[15]||=e=>a.createOpen=e,projects:a.projects,"default-project-path":a.defaultProjectPath,onCreated:a.onTaskCreated},null,8,[`modelValue`,`projects`,`default-project-path`])],4)}var kl=Z(Yc,[[`render`,Ol],[`__scopeId`,`data-v-dd2dc7b4`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchBoard.vue`]]);c(),V();var Al=`wb.lastTaskByProject.v1`,jl=`__no_project__`,Ml=`wb.sidebarWidth.v1`,Nl=200,Pl=480,Fl=268,Il=3e3,Ll=52,Rl=320,zl=500,Bl=f({__name:`WorkbenchView`,setup(e,{expose:n}){n();let r=Ae(),i=je(),a=P((()=>{try{let e=parseInt(localStorage.getItem(Ml)||``,10);return Number.isFinite(e)?Math.min(Pl,Math.max(Nl,e)):Fl}catch{return Fl}})());function s(e){e.preventDefault();let t=e.clientX,n=a.value;document.body.style.userSelect=`none`,document.body.style.cursor=`col-resize`;let r=e=>{a.value=Math.min(Pl,Math.max(Nl,n+e.clientX-t))};window.addEventListener(`mousemove`,r),window.addEventListener(`mouseup`,()=>{window.removeEventListener(`mousemove`,r),document.body.style.userSelect=``,document.body.style.cursor=``;try{localStorage.setItem(Ml,String(a.value))}catch{}},{once:!0})}function c(e){a.value=Math.min(Pl,Math.max(Nl,a.value+e));try{localStorage.setItem(Ml,String(a.value))}catch{}}function l(){try{let e=localStorage.getItem(Al),t=e?JSON.parse(e):{};return t&&typeof t==`object`&&!Array.isArray(t)?t:{}}catch{return{}}}function u(e){try{localStorage.setItem(Al,JSON.stringify(e))}catch{}}function d(e,t){let n=l();n[e||jl]=t,u(n)}let f=P(!1);function p(){f.value=!1}let m=P(null);async function h(e){await D(),j.value=e.taskId,m.value=e.taskId,z(),M.value&&d($(b.value.path),e.taskId),f.value=!0}function g(e){if(!ie.value.some(t=>t.id===e)){I.info(X(`@WORKBENCH:该任务不在当前视图(可能在别的项目下)`));return}m.value=e}let{tasks:_,jobs:y,currentProject:b,connectSSE:x,disconnectSSE:S,loadCurrentProject:C,loadJobs:w,clearJobsByTask:E,loadTasks:D}=gr();function O(){let e=$(b.value.path),t=_.value.filter(t=>!t.projectPath||$(t.projectPath)===e),n=l(),r=e&&n[e]||!e&&n[jl]||``,i=r?_.value.find(e=>e.id===r):null,a=t[0]||_.value[0]||null,o=i&&i.projectPath&&$(i.projectPath)!==e?null:i?i.id:a?a.id:null;j.value=o,z()}async function k(){let e=j.value;if(await D(),e&&_.value.some(t=>t.id===e)){z();return}O()}async function re(){await D(),O()}let A=P(!1),j=P(null),M=Y(()=>_.value.find(e=>e.id===j.value)||null),ie=P([]),ce=Y(()=>ie.value.find(e=>e.id===j.value)||null),N=Y(()=>ce.value?vt(Yn(ce.value)):``),ue=Y(()=>ce.value?$n(ce.value):``),F=Y(()=>ce.value?er(ce.value):``),L=Y(()=>{let e=M.value?.projectPath||``;return!e||$(e)===$(b.value.path)?null:{name:e.replace(/[\\/]+$/,``).split(/[\\/]/).pop()||e,path:e}}),R=P({title:``,desc:``});function z(){M.value?R.value={title:M.value.title,desc:M.value.desc}:R.value={title:``,desc:``}}let B=P(`idle`),V=P(0),H=null,de=Y(()=>{if(!M.value)return!1;let e=M.value;return R.value.title!==e.title||R.value.desc!==e.desc});function W(){H!==null&&(clearTimeout(H),H=null)}function G(e){return!(!e||(e.title||``).trim()||(e.desc||``).trim()||(e.simpleOverride||``).trim()||Array.isArray(e.attachments)&&e.attachments.length>0)}async function K(e){try{await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`})}catch{}let t=_.value.findIndex(t=>t.id===e.id);t!==-1&&_.value.splice(t,1)}async function q(){let e=_.value.filter(e=>e.id!==j.value&&G(e));for(let t of e)await K(t)}async function me(){if(!M.value)return!1;if(!de.value)return!0;if(B.value=`saving`,await dt(!1))return V.value=Date.now(),B.value=`saved`,setTimeout(()=>{B.value===`saved`&&Date.now()-V.value>=4e3&&(B.value=`idle`)},4e3),!0;B.value=`error`;let e=Date.now();return setTimeout(()=>{B.value===`error`&&Date.now()-e>=4e3&&(B.value=`idle`)},4e3),!1}U(()=>M.value?{id:M.value.id,title:M.value.title,desc:M.value.desc}:null,(e,t)=>{e&&t&&e.id===t.id&&(H!==null&&clearTimeout(H),H=window.setTimeout(()=>{me()},1500))},{deep:!0}),U(j,async(e,t)=>{W(),M.value&&de.value&&await me()}),U(b,async e=>{if(!e.path)return;let t=$(e.path),n=M.value;n&&n.projectPath&&$(n.projectPath)!==t&&await re()});function he(e){try{let t=new Blob([JSON.stringify(e)],{type:`application/json`});navigator.sendBeacon?.(`/api/workbench/tasks`,t)}catch{}}function ge(){M.value&&de.value&&!G(M.value)&&he(M.value)}let J=P(!1);async function _e(e){try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.left=`-9999px`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}let ve=P(null),ye=P(null);async function be(e){if(e){if(!await _e((e.title||``).trim()||X(`@WORKBENCH:未命名任务`))){I.error(X(`@WORKBENCH:复制失败`));return}ve.value=e.id,I.success(X(`@WORKBENCH:已复制任务标题`)),window.setTimeout(()=>{ve.value===e.id&&(ve.value=null)},1500)}}async function Ce(e){if(!e)return;let t=(e.desc||``).trim();if(!t){I.warning(X(`@WORKBENCH:任务描述为空,无需复制`));return}if(!await _e(t)){I.error(X(`@WORKBENCH:复制失败`));return}ye.value=e.id,I.success(X(`@WORKBENCH:已复制任务描述`)),window.setTimeout(()=>{ye.value===e.id&&(ye.value=null)},1500)}let{simpleConversationMessages:we,simpleAllJobsFor:Te,simpleJobFor:Z,simpleJobState:Ee}=mr(y,M);function Ne(e){let t=String(e?.id||``).replace(/-a$/,``),n=y.value.find(e=>e.id===t);return n?Dt(n):!1}let Pe=P(null);function Ie(e){let t=(e?.projectPath||``).trim().replace(/[\\/]+$/,``);return t?t.split(/[\\/]/).pop()||t:b.value.name||``}async function Le(e,t=`brief`){if(!e)return;let n=ft(Te(e),{title:e.title,projectName:Ie(e)},{scope:t});if(!n){I.warning(X(`@WORKBENCH:暂无执行内容可复制`));return}if(!await _e(n)){I.error(X(`@WORKBENCH:复制失败`));return}Pe.value=e.id,I.success(X(`@WORKBENCH:已复制执行内容`)),window.setTimeout(()=>{Pe.value===e.id&&(Pe.value=null)},1500)}function Re(e){Le(M.value,e===`full`?`full`:`brief`)}let ze=[`wheel`,`touchstart`,`pointerdown`,`keydown`],Be=P(null),Ve=P(null),Q=null,He=null,Ue=null;function We(){if(Q&&=(Q.disconnect(),null),He!==null&&(clearTimeout(He),He=null),Ue){for(let e of ze)Ue.removeEventListener(e,We);Ue=null}}function Ge(){We();let e=Be.value;if(!e)return;e.scrollToBottom?.(!1);let t=Ve.value?.querySelector(`.acu-message-list`);if(!(!t||typeof ResizeObserver>`u`)){Ue=t;for(let e of ze)t.addEventListener(e,We,{passive:!0});Q=new ResizeObserver(()=>Be.value?.scrollToBottom?.(!1)),Q.observe(t),t.firstElementChild&&Q.observe(t.firstElementChild),He=setTimeout(We,Il)}}let Ke=Y(()=>f.value&&M.value&&Te(M.value).length>0?M.value.id:``);U(Ke,async e=>{We(),e&&(await t(),Ge())}),ee(We);function qe(e){return e?Ot(e.id):!1}let Je=Y(()=>Te(M.value).length>0),Ye=Y(()=>qe(M.value)),Ze=Y(()=>M.value?Ye.value?X(`@WORKBENCH:正在执行中,请先「停止」再重新执行`):Je.value?X(`@WORKBENCH:重新跑一轮:上一轮的执行记录会被清空`):``:``),Qe=Y(()=>{if(!M.value)return null;let e=ce.value;if(Ye.value||e&&e.runningJobs>0)return{key:`running`,label:X(`@WORKBENCH:执行中`),title:X(`@WORKBENCH:这条任务正在执行`)};if(e)return e.column===`done`?{key:`done`,label:X(`@WORKBENCH:已完成`),title:e.autoCompleted?X(`@WORKBENCH:静默超时后由 AI 核对,判定这条任务已经完成`):e.manualDoneAt?X(`@WORKBENCH:已标记为已完成`):``}:e.lastJobStatus===`error`?{key:`error`,label:X(`@WORKBENCH:执行失败`),title:X(`@WORKBENCH:上一次执行报错,点开对话流查看原因`)}:{key:`todo`,label:X(`@WORKBENCH:待处理`),title:``};switch(Ee(Z(M.value))){case`done`:return{key:`done`,label:X(`@WORKBENCH:已完成`),title:``};case`error`:return{key:`error`,label:X(`@WORKBENCH:执行失败`),title:``};case`cancelled`:return{key:`todo`,label:X(`@WORKBENCH:已取消`),title:``};default:return{key:`todo`,label:X(`@WORKBENCH:待处理`),title:``}}}),$e=Y(()=>{let e=M.value;if(!e)return[];let t=e.promptParts;if(t&&(t.global||t.project)){let e=[];return t.global&&e.push({key:`global`,label:X(`@WORKBENCH:全局提示词`),text:t.global}),t.project&&e.push({key:`project`,label:X(`@WORKBENCH:项目提示词`),text:t.project}),e}let n=(e.simpleOverride||``).trim();return n?[{key:`legacy`,label:X(`@WORKBENCH:提示词`),text:n}]:[]}),et=P(!1),tt=P(null),nt=P(null);function rt(e){let t=e?.currentTarget||nt.value;if(!t)return;t.style.height=`auto`;let n=document.activeElement===t?zl:Rl,r=Math.min(Math.max(t.scrollHeight,Ll),n);t.style.height=`${r}px`,t.style.overflowY=t.scrollHeight>n?`auto`:`hidden`}U(J,async e=>{e&&(await t(),rt())}),U(()=>M.value?.id,async()=>{J.value&&(await t(),rt())});async function it(){if(et.value)return;et.value=!0;let e={title:``,desc:``};b.value.path&&(e.projectPath=b.value.path);try{let n=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}).then(e=>e.json());if(!n.success){I.error(n.error||X(`@WORKBENCH:保存失败`));return}W(),M.value&&G(M.value)?await K(M.value):M.value&&de.value&&await me(),await re(),n.task?.id&&(j.value=n.task.id,z(),I.success(X(`@WORKBENCH:已新建任务`)),await t(),tt.value?.focus())}finally{et.value=!1}}async function at(e){await fe.confirm(X(`@WORKBENCH:删除任务「{title}」?`,{title:e.title}),X(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`}),j.value===e.id&&(j.value=null),re()}async function ot(e){let t=(e.title||X(`@WORKBENCH:未命名任务`)).trim(),n={title:X(`@WORKBENCH:{title} (副本)`,{title:t}),desc:e.desc||``,simpleOverride:e.simpleOverride||``};e.promptParts&&(e.promptParts.global||e.promptParts.project)&&(n.promptParts=e.promptParts),b.value.path&&(n.projectPath=b.value.path);try{let e=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(n)}).then(e=>e.json());if(!e.success){I.error(e.error||X(`@WORKBENCH:复制失败`));return}await re(),e.task?.id&&(j.value=e.task.id,z()),I.success(X(`@WORKBENCH:已复制任务`))}catch(e){I.error(X(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}}async function st(e){if(j.value===e.id)return;W();let t=M.value;t&&G(t)?await K(t):t&&de.value&&await me(),j.value=e.id,z(),d($(b.value.path),e.id)}async function ct(e){let{groupPath:t,orderedIds:n}=e;if(!Array.isArray(n)||n.length===0)return;let r=_.value.slice(),i=ut(_.value,t,n);if(i!==_.value){_.value=i;try{let e=await fetch(`/api/workbench/tasks/reorder`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({orderedIds:n,groupPath:t})}).then(e=>e.json()).catch(()=>({success:!1,error:X(`@WORKBENCH:排序保存失败`)}));e?.success||(_.value=r,I.error(e?.error||X(`@WORKBENCH:排序保存失败`)))}catch(e){_.value=r,I.error(X(`@WORKBENCH:排序保存失败`)+`: `+(e?.message||e))}}}function ut(e,t,n){let r=e=>$(e)||jl,i=e.filter(e=>r(e.projectPath)===t).map(e=>e.id),a=new Set(i);if(n.length!==a.size||n.some(e=>!a.has(e)))return e;let o=new Map(e.map(e=>[e.id,e])),s=n.map(e=>o.get(e)).filter(Boolean),c=[],l=0;for(let n of e)r(n.projectPath)===t?c.push(s[l++]):c.push(n);return c}async function dt(e){if(!M.value)return!1;let t=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(M.value)}).then(e=>e.json());return t.success?(e&&I.success(X(`@WORKBENCH:已保存`)),await k(),!0):(I.error(t.error||X(`@WORKBENCH:保存失败`)),!1)}o(async()=>{await Promise.all([re(),C(),w()]),await q(),x(),window.addEventListener(`beforeunload`,ge),i.fetchExecutorModels()}),ee(()=>{S(),window.removeEventListener(`beforeunload`,ge),M.value&&de.value&&!G(M.value)&&he(M.value)});let{pasteHoverId:pt,isUploading:mt,isImageAttachment:ht,humanSize:gt,onAttachmentPaste:_t,onAttachmentDrop:yt,uploadAttachment:bt,removeAttachment:xt,pickAttachmentFile:St}=dr(),{runTask:Ct,onContinueSendFromChat:wt,cancelJob:Tt,clearExecutionForSelectedTask:Et,onReExecuteJob:Dt,isTaskRunning:Ot,queuedChatsOf:kt,removeQueuedChat:At,flushNextQueued:jt}=hr(y,_,M,{clearJobsByTask:E,persistTask:dt,uploadAttachment:bt,getExecutor:()=>Mt.value}),{active:Mt,availability:Nt,hasAnyExecutor:Pt,choose:Ft,executorModelText:Lt,executorModelTitle:Rt}=lt();function zt(e){return Oe(e)}let Bt=Y(()=>Te(M.value).slice(-1)[0]),Vt=Y(()=>Oe(Bt.value?.agent)),Ut=Y(()=>Ht(Bt.value?.agent)),Wt=Y(()=>De(Bt.value?.agent)?Bt.value.agent:`claude`),Gt={configStore:r,toolsStore:i,LAST_TASK_BY_PROJECT_KEY:Al,NO_PROJECT_KEY:jl,SIDEBAR_WIDTH_KEY:Ml,SIDEBAR_MIN_W:Nl,SIDEBAR_MAX_W:Pl,SIDEBAR_DEFAULT_W:Fl,sidebarWidth:a,onSidebarSplitterMouseDown:s,nudgeSidebarWidth:c,readLastTaskMap:l,writeLastTaskMap:u,rememberLastTask:d,editorOpen:f,closeEditor:p,boardOpenedTaskId:m,openTaskFromBoard:h,locateTaskFromBoard:g,tasks:_,jobs:y,currentProject:b,connectSSE:x,disconnectSSE:S,loadCurrentProject:C,loadJobs:w,clearJobsByTask:E,_loadDataTasks:D,applyRestoredSelection:O,refreshTasks:k,loadTasks:re,logsDialogVisible:A,selectedTaskId:j,selectedTask:M,boardTasks:ie,selectedBoardTask:ce,barTimeText:N,barDurationText:ue,barTimeTitle:F,foreignRepo:L,metaSnapshot:R,captureSnapshot:z,metaSaveState:B,metaSavedAt:V,get metaSaveTimer(){return H},set metaSaveTimer(e){H=e},metaDirty:de,clearMetaSaveTimers:W,isTaskBlank:G,discardBlankTask:K,pruneBlankTasks:q,flushMetaSave:me,beaconPersist:he,onBeforeUnloadPersist:ge,taskDescExpanded:J,copyToClipboard:_e,copyTitleFlashId:ve,copyDescFlashId:ye,copyTaskTitle:be,copyTaskDesc:Ce,simpleConversationMessages:we,simpleAllJobsFor:Te,simpleJobFor:Z,simpleJobState:Ee,onChatRetry:Ne,copyExecFlashId:Pe,taskRepoName:Ie,copyTaskExecution:Le,onCopyExecCommand:Re,CHAT_PIN_WINDOW_MS:Il,CHAT_PIN_USER_EVENTS:ze,chatRef:Be,chatWrapRef:Ve,get chatPinRO(){return Q},set chatPinRO(e){Q=e},get chatPinTimer(){return He},set chatPinTimer(e){He=e},get chatPinEl(){return Ue},set chatPinEl(e){Ue=e},stopChatPin:We,pinChatToBottom:Ge,chatRenderKey:Ke,isTaskRunning:qe,selectedTaskHasRun:Je,selectedTaskRunning:Ye,runButtonTitle:Ze,barStatus:Qe,selectedTaskPromptParts:$e,creatingTask:et,titleInputRef:tt,taskDescTextareaRef:nt,DESC_TEXTAREA_MIN_PX:Ll,DESC_TEXTAREA_MAX_PX:Rl,DESC_TEXTAREA_MAX_PX_FOCUS:zl,autoGrowTextarea:rt,createTaskDirect:it,deleteTask:at,copyTask:ot,selectTask:st,reorderTasks:ct,applyLocalReorder:ut,persistTask:dt,pasteHoverId:pt,isUploading:mt,isImageAttachment:ht,humanSize:gt,onAttachmentPaste:_t,onAttachmentDrop:yt,uploadAttachment:bt,removeAttachment:xt,pickAttachmentFile:St,runTask:Ct,onContinueSendFromChat:wt,cancelJob:Tt,clearExecutionForSelectedTask:Et,onReExecuteJob:Dt,isTaskRunningById:Ot,queuedChatsOf:kt,removeQueuedChat:At,flushNextQueued:jt,selectedTaskExecutor:Mt,executorAvailability:Nt,hasAnyExecutor:Pt,pickExecutor:Ft,executorModelText:Lt,executorModelTitle:Rt,executorLabel:zt,lastSimpleJob:Bt,simpleAssistantLabel:Vt,simpleAssistantAvatar:Ut,lastJobExecutorId:Wt,lastSimpleJobRunning:Y(()=>Ee(Bt.value)===`running`),lastRunExecutorTitle:Y(()=>{let e=Rt(Wt.value),t=X(`@WORKBENCH:本轮实际使用的执行器;上方按钮选的是下一次执行用谁`);return e?`${e} · ${t}`:t}),selectedTaskQueue:Y(()=>M.value?kt(M.value.id):[]),get $t(){return X},get ArrowDown(){return te},get ArrowLeft(){return T},get ArrowRight(){return ne},get Check(){return se},get Document(){return le},get Delete(){return ae},get CopyDocument(){return pe},get VideoPlay(){return v},get Warning(){return oe},AttachmentZone:It,get ChatInput(){return Se},get ChatContainer(){return xe},get MESSAGE_RAIL_CONFIG(){return Xe},ExecutionLogManager:qn,get ALLOWED_EXT_HINT(){return nr},get MAX_ATTACHMENT_BYTES(){return rr},get TASK_EXECUTOR_OPTIONS(){return ke},TaskExecutorIcon:Fe,WorkbenchSidebar:Gr,WorkbenchBoard:kl,CommonDialog:Me};return Object.defineProperty(Gt,"__isScriptSetup",{enumerable:!1,value:!0}),Gt}});c(),R(),W();var Vl={class:`workbench`},Hl={class:`wb-editor`},Ul={class:`wb-editor-bar`},Wl=[`title`],Gl=[`title`],Kl=[`data-status`,`title`],ql={class:`wb-editor-bar__status-pill`},Jl={class:`wb-editor-bar__status-label`},Yl=[`title`],Xl={key:2,class:`wb-editor-bar__time`},Zl=[`title`],Ql={key:1,class:`wb-editor-bar__sep`,"aria-hidden":`true`},$l={key:2,class:`wb-editor-bar__spent`},eu={class:`wb-editor-bar__hint`},tu={class:`workbench__editor-row`},nu=[`aria-label`,`aria-valuenow`,`title`],ru={class:`wb-split`},iu={key:0,class:`wb-placeholder`},au={class:`wb-split__header`},ou={class:`wb-split__title-wrap`},su=[`placeholder`,`aria-label`],cu=[`title`,`aria-label`],lu=[`title`],uu={key:0,class:`wb-meta-save__dot`},du={key:1,class:`wb-meta-save__check`},fu={key:2,class:`wb-meta-save__bang`},pu={key:3,class:`wb-meta-save__dot`},mu=[`data-executor`,`title`],hu={class:`wb-run-executor__text`},gu=[`title`],_u={class:`sr-only`},vu={class:`sr-only`},yu={class:`wb-executor-item`},bu={class:`wb-executor-item__name`},xu=[`title`],Su={key:2,class:`wb-executor-item__missing`},Cu={key:3,class:`wb-no-claude-hint`,role:`status`},wu={class:`wb-no-claude-hint__text`},Tu={class:`wb-no-claude-hint__link`,href:`https://docs.claude.com/en/docs/claude-code/setup`,target:`_blank`,rel:`noopener noreferrer`},Eu={class:`wb-copy-exec`},Du=[`title`,`aria-label`],Ou={class:`sr-only`},ku=[`title`,`aria-label`],Au=[`title`,`aria-label`],ju={class:`sr-only`},Mu=[`title`,`aria-label`],Nu={class:`sr-only`},Pu=[`open`],Fu={class:`wb-task-desc__summary`},Iu={class:`wb-task-desc__label`},Lu=[`title`,`aria-label`],Ru={key:0,class:`wb-task-desc__tag`},zu={key:0},Bu={key:1,class:`wb-task-desc__tag-attachment`},Vu=[`placeholder`,`aria-label`],Hu={class:`wb-execution-body`},Uu={class:`wb-exec-detail`},Wu={class:`wb-form-item__label wb-task-prompt__summary`},Gu={key:0,class:`wb-task-prompt__tag`},Ku={key:0,class:`wb-task-prompt__parts`},qu={class:`wb-task-prompt__label`},Ju={class:`wb-task-prompt__text`},Yu={key:1,class:`wb-task-prompt__empty`},Xu={key:0,class:`wb-simple-chat-wrap`,ref:`chatWrapRef`},Zu={class:`wb-simple-chat`},Qu={class:`wb-simple-chat__footer`},$u={key:0,class:`wb-chat-queue`},ed={class:`wb-chat-queue__head`},td={class:`wb-chat-queue__label`},nd={class:`wb-chat-queue__count`},rd={class:`wb-chat-queue__hint`},id={class:`wb-chat-queue__index`},ad=[`title`],od={key:0,class:`wb-chat-queue__atts`},sd=[`title`,`aria-label`,`onClick`];function cd(t,i,a,o,s,c){let d=l,f=n,p=ge,m=b;return K(),S(`div`,Vl,[J(` L1:多项目编排台 —— **常驻底图**,不再与编辑器互斥 `),e(o.WorkbenchBoard,{"opened-task-id":o.boardOpenedTaskId,onOpenTask:o.openTaskFromBoard,onBoardTasks:i[0]||=e=>o.boardTasks=e,onLocateTask:o.locateTaskFromBoard},null,8,[`opened-task-id`]),J(` L2:单任务编辑器 —— 默认整屏铺开(原来是 1520px 居中浮层),关掉即回到看板,全程无跳转。
301
+ 那枚同一形状(14/描边 2)—— 用户 2026-10-16 反馈「这个也改一下」 `),n[20]||=x(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,xmlns:`http://www.w3.org/2000/svg`,"aria-hidden":`true`},[x(`path`,{d:`M3 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0`}),x(`path`,{d:`M21 21l-6 -6`})],-1)]),_:1})],40,Fl)],2)])]),e(a.WorkbenchKanban,{tasks:a.visibleTasks,"project-labels":a.projectLabels,projects:a.projects,"task-percents":a.taskPercents,"show-project-label":!a.selectedProject,"opened-task-id":a.props.openedTaskId,view:a.view,"onUpdate:view":n[8]||=e=>a.view=e,search:a.search,"onUpdate:search":n[9]||=e=>a.search=e,onOpenTask:a.onOpenTask,onRunTask:a.runTask,onStopTask:a.stopTask,onCompleteTask:a.completeTask,onReopenTask:a.reopenTask,onDeleteTask:a.deleteTask,onMoveTask:a.moveTask,onCreateTask:a.onCreateClick},null,8,[`tasks`,`project-labels`,`projects`,`task-percents`,`show-project-label`,`opened-task-id`,`view`,`search`])]),J(` 右栏分隔条:右栏收起 / 竖排(≤860)时不占位 `),!a.rightHidden&&!a.isStacked?(K(),S(`div`,{key:1,class:`board__splitter board__splitter--right`,role:`separator`,"aria-orientation":`vertical`,title:a.$t(`@WORKBENCH:拖动调整主 Agent 控制台宽度,双击恢复默认`),onMousedown:n[10]||=e=>a.onSplitterMouseDown(`right`,e),onDblclick:n[11]||=e=>a.onSplitterDblClick(`right`)},null,40,Il)):J(`v-if`,!0),e(a.OrchestratorConsole,{ref:`consoleRef`,running:a.running,"selected-project":a.selectedProject,dispatching:a.dispatching,"today-done":a.headerStats.todayDone,collapsed:a.rightHidden,"default-prompt":a.defaultPrompt,"project-prompts":a.projectPrompts,reports:a.reports,"report-interval-ms":a.reportIntervalMs,"generating-report":a.generatingReport,"max-instruction-chars":a.maxInstructionChars,onToggleCollapse:a.toggleRight,onDispatch:a.onDispatch,onGenerateReport:a.generateReport,onSetReportInterval:a.setReportInterval,onOpenPromptSettings:n[12]||=e=>a.promptDialogOpen=!0,onLocateTask:n[13]||=e=>a.emit(`locate-task`,e)},null,8,[`running`,`selected-project`,`dispatching`,`today-done`,`collapsed`,`default-prompt`,`project-prompts`,`reports`,`report-interval-ms`,`generating-report`,`max-instruction-chars`,`onGenerateReport`,`onSetReportInterval`])],2),J(` 派发预设提示词:全局一条 + 选中项目一条,写完即生效于之后的派发 `),e(a.WorkbenchDefaultPromptDialog,{modelValue:a.promptDialogOpen,"onUpdate:modelValue":n[14]||=e=>a.promptDialogOpen=e,"default-prompt":a.defaultPrompt,"project-path":a.selectedProject?.path||``,"project-name":a.selectedProject?.name||``,"project-prompt":a.selectedProjectPrompt,saving:a.savingPrompt,onSave:a.onSavePromptDraft},null,8,[`modelValue`,`default-prompt`,`project-path`,`project-name`,`project-prompt`,`saving`]),J(` 新建任务:弹窗里问清字段,建完就关 `),e(a.WorkbenchTaskCreateDialog,{modelValue:a.createOpen,"onUpdate:modelValue":n[15]||=e=>a.createOpen=e,projects:a.projects,"default-project-path":a.defaultProjectPath,onCreated:a.onTaskCreated},null,8,[`modelValue`,`projects`,`default-project-path`])],4)}var Rl=Z(il,[[`render`,Ll],[`__scopeId`,`data-v-dd2dc7b4`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchBoard.vue`]]);c(),V();var zl=`wb.lastTaskByProject.v1`,Bl=`__no_project__`,Vl=`wb.sidebarWidth.v1`,Hl=200,Ul=480,Wl=268,Gl=3e3,Kl=52,ql=320,Jl=500,Yl=f({__name:`WorkbenchView`,setup(e,{expose:n}){n();let r=Ae(),i=je(),a=P((()=>{try{let e=parseInt(localStorage.getItem(Vl)||``,10);return Number.isFinite(e)?Math.min(Ul,Math.max(Hl,e)):Wl}catch{return Wl}})());function s(e){e.preventDefault();let t=e.clientX,n=a.value;document.body.style.userSelect=`none`,document.body.style.cursor=`col-resize`;let r=e=>{a.value=Math.min(Ul,Math.max(Hl,n+e.clientX-t))};window.addEventListener(`mousemove`,r),window.addEventListener(`mouseup`,()=>{window.removeEventListener(`mousemove`,r),document.body.style.userSelect=``,document.body.style.cursor=``;try{localStorage.setItem(Vl,String(a.value))}catch{}},{once:!0})}function c(e){a.value=Math.min(Ul,Math.max(Hl,a.value+e));try{localStorage.setItem(Vl,String(a.value))}catch{}}function l(){try{let e=localStorage.getItem(zl),t=e?JSON.parse(e):{};return t&&typeof t==`object`&&!Array.isArray(t)?t:{}}catch{return{}}}function u(e){try{localStorage.setItem(zl,JSON.stringify(e))}catch{}}function d(e,t){let n=l();n[e||Bl]=t,u(n)}let f=P(!1);function p(){f.value=!1}let m=P(null);async function h(e){await O(),j.value=e.taskId,m.value=e.taskId,z(),M.value&&d($(b.value.path),e.taskId),f.value=!0}function g(e){if(!ie.value.some(t=>t.id===e)){I.info(X(`@WORKBENCH:该任务不在当前视图(可能在别的项目下)`));return}m.value=e}let{tasks:_,jobs:y,currentProject:b,connectSSE:x,disconnectSSE:S,loadCurrentProject:C,loadJobs:T,clearJobsByTask:D,loadTasks:O}=gr();function ne(){let e=$(b.value.path),t=_.value.filter(t=>!t.projectPath||$(t.projectPath)===e),n=l(),r=e&&n[e]||!e&&n[Bl]||``,i=r?_.value.find(e=>e.id===r):null,a=t[0]||_.value[0]||null,o=i&&i.projectPath&&$(i.projectPath)!==e?null:i?i.id:a?a.id:null;j.value=o,z()}async function k(){let e=j.value;if(await O(),e&&_.value.some(t=>t.id===e)){z();return}ne()}async function re(){await O(),ne()}let A=P(!1),j=P(null),M=Y(()=>_.value.find(e=>e.id===j.value)||null),ie=P([]),ce=Y(()=>ie.value.find(e=>e.id===j.value)||null),N=Y(()=>ce.value?vt(Yn(ce.value)):``),ue=Y(()=>ce.value?$n(ce.value):``),F=Y(()=>ce.value?er(ce.value):``),L=Y(()=>{let e=M.value?.projectPath||``;return!e||$(e)===$(b.value.path)?null:{name:e.replace(/[\\/]+$/,``).split(/[\\/]/).pop()||e,path:e}}),R=P({title:``,desc:``});function z(){M.value?R.value={title:M.value.title,desc:M.value.desc}:R.value={title:``,desc:``}}let B=P(`idle`),V=P(0),H=null,de=Y(()=>{if(!M.value)return!1;let e=M.value;return R.value.title!==e.title||R.value.desc!==e.desc});function W(){H!==null&&(clearTimeout(H),H=null)}function G(e){return!(!e||(e.title||``).trim()||(e.desc||``).trim()||(e.simpleOverride||``).trim()||Array.isArray(e.attachments)&&e.attachments.length>0)}async function K(e){try{await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`})}catch{}let t=_.value.findIndex(t=>t.id===e.id);t!==-1&&_.value.splice(t,1)}async function q(){let e=_.value.filter(e=>e.id!==j.value&&G(e));for(let t of e)await K(t)}async function me(){if(!M.value)return!1;if(!de.value)return!0;if(B.value=`saving`,await dt(!1))return V.value=Date.now(),B.value=`saved`,setTimeout(()=>{B.value===`saved`&&Date.now()-V.value>=4e3&&(B.value=`idle`)},4e3),!0;B.value=`error`;let e=Date.now();return setTimeout(()=>{B.value===`error`&&Date.now()-e>=4e3&&(B.value=`idle`)},4e3),!1}U(()=>M.value?{id:M.value.id,title:M.value.title,desc:M.value.desc}:null,(e,t)=>{e&&t&&e.id===t.id&&(H!==null&&clearTimeout(H),H=window.setTimeout(()=>{me()},1500))},{deep:!0}),U(j,async(e,t)=>{W(),M.value&&de.value&&await me()}),U(b,async e=>{if(!e.path)return;let t=$(e.path),n=M.value;n&&n.projectPath&&$(n.projectPath)!==t&&await re()});function he(e){try{let t=new Blob([JSON.stringify(e)],{type:`application/json`});navigator.sendBeacon?.(`/api/workbench/tasks`,t)}catch{}}function ge(){M.value&&de.value&&!G(M.value)&&he(M.value)}let J=P(!1);async function _e(e){try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.left=`-9999px`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}let ve=P(null),ye=P(null);async function be(e){if(e){if(!await _e((e.title||``).trim()||X(`@WORKBENCH:未命名任务`))){I.error(X(`@WORKBENCH:复制失败`));return}ve.value=e.id,I.success(X(`@WORKBENCH:已复制任务标题`)),window.setTimeout(()=>{ve.value===e.id&&(ve.value=null)},1500)}}async function Ce(e){if(!e)return;let t=(e.desc||``).trim();if(!t){I.warning(X(`@WORKBENCH:任务描述为空,无需复制`));return}if(!await _e(t)){I.error(X(`@WORKBENCH:复制失败`));return}ye.value=e.id,I.success(X(`@WORKBENCH:已复制任务描述`)),window.setTimeout(()=>{ye.value===e.id&&(ye.value=null)},1500)}let{simpleConversationMessages:we,simpleAllJobsFor:Te,simpleJobFor:Z,simpleJobState:Ee}=mr(y,M);function Ne(e){let t=String(e?.id||``).replace(/-a$/,``),n=y.value.find(e=>e.id===t);return n?Dt(n):!1}let Pe=P(null);function Ie(e){let t=(e?.projectPath||``).trim().replace(/[\\/]+$/,``);return t?t.split(/[\\/]/).pop()||t:b.value.name||``}async function Le(e,t=`brief`){if(!e)return;let n=ft(Te(e),{title:e.title,projectName:Ie(e)},{scope:t});if(!n){I.warning(X(`@WORKBENCH:暂无执行内容可复制`));return}if(!await _e(n)){I.error(X(`@WORKBENCH:复制失败`));return}Pe.value=e.id,I.success(X(`@WORKBENCH:已复制执行内容`)),window.setTimeout(()=>{Pe.value===e.id&&(Pe.value=null)},1500)}function Re(e){Le(M.value,e===`full`?`full`:`brief`)}let ze=[`wheel`,`touchstart`,`pointerdown`,`keydown`],Be=P(null),Ve=P(null),Q=null,He=null,Ue=null;function We(){if(Q&&=(Q.disconnect(),null),He!==null&&(clearTimeout(He),He=null),Ue){for(let e of ze)Ue.removeEventListener(e,We);Ue=null}}function Ge(){We();let e=Be.value;if(!e)return;e.scrollToBottom?.(!1);let t=Ve.value?.querySelector(`.acu-message-list`);if(!(!t||typeof ResizeObserver>`u`)){Ue=t;for(let e of ze)t.addEventListener(e,We,{passive:!0});Q=new ResizeObserver(()=>Be.value?.scrollToBottom?.(!1)),Q.observe(t),t.firstElementChild&&Q.observe(t.firstElementChild),He=setTimeout(We,Gl)}}let Ke=Y(()=>f.value&&M.value&&Te(M.value).length>0?M.value.id:``);U(Ke,async e=>{We(),e&&(await t(),Ge())}),w(We);function qe(e){return e?Ot(e.id):!1}let Je=Y(()=>Te(M.value).length>0),Ye=Y(()=>qe(M.value)),Ze=Y(()=>M.value?Ye.value?X(`@WORKBENCH:正在执行中,请先「停止」再重新执行`):Je.value?X(`@WORKBENCH:重新跑一轮:上一轮的执行记录会被清空`):``:``),Qe=Y(()=>{if(!M.value)return null;let e=ce.value;if(Ye.value||e&&e.runningJobs>0)return{key:`running`,label:X(`@WORKBENCH:执行中`),title:X(`@WORKBENCH:这条任务正在执行`)};if(e)return e.column===`done`?{key:`done`,label:X(`@WORKBENCH:已完成`),title:e.autoCompleted?X(`@WORKBENCH:静默超时后由 AI 核对,判定这条任务已经完成`):e.manualDoneAt?X(`@WORKBENCH:已标记为已完成`):``}:e.lastJobStatus===`error`?{key:`error`,label:X(`@WORKBENCH:执行失败`),title:X(`@WORKBENCH:上一次执行报错,点开对话流查看原因`)}:{key:`todo`,label:X(`@WORKBENCH:待处理`),title:``};switch(Ee(Z(M.value))){case`done`:return{key:`done`,label:X(`@WORKBENCH:已完成`),title:``};case`error`:return{key:`error`,label:X(`@WORKBENCH:执行失败`),title:``};case`cancelled`:return{key:`todo`,label:X(`@WORKBENCH:已取消`),title:``};default:return{key:`todo`,label:X(`@WORKBENCH:待处理`),title:``}}}),$e=Y(()=>{let e=M.value;if(!e)return[];let t=e.promptParts;if(t&&(t.global||t.project)){let e=[];return t.global&&e.push({key:`global`,label:X(`@WORKBENCH:全局提示词`),text:t.global}),t.project&&e.push({key:`project`,label:X(`@WORKBENCH:项目提示词`),text:t.project}),e}let n=(e.simpleOverride||``).trim();return n?[{key:`legacy`,label:X(`@WORKBENCH:提示词`),text:n}]:[]}),et=P(!1),tt=P(null),nt=P(null);function rt(e){let t=e?.currentTarget||nt.value;if(!t)return;t.style.height=`auto`;let n=document.activeElement===t?Jl:ql,r=Math.min(Math.max(t.scrollHeight,Kl),n);t.style.height=`${r}px`,t.style.overflowY=t.scrollHeight>n?`auto`:`hidden`}U(J,async e=>{e&&(await t(),rt())}),U(()=>M.value?.id,async()=>{J.value&&(await t(),rt())});async function it(){if(et.value)return;et.value=!0;let e={title:``,desc:``};b.value.path&&(e.projectPath=b.value.path);try{let n=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}).then(e=>e.json());if(!n.success){I.error(n.error||X(`@WORKBENCH:保存失败`));return}W(),M.value&&G(M.value)?await K(M.value):M.value&&de.value&&await me(),await re(),n.task?.id&&(j.value=n.task.id,z(),I.success(X(`@WORKBENCH:已新建任务`)),await t(),tt.value?.focus())}finally{et.value=!1}}async function at(e){await fe.confirm(X(`@WORKBENCH:删除任务「{title}」?`,{title:e.title}),X(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`}),j.value===e.id&&(j.value=null),re()}async function ot(e){let t=(e.title||X(`@WORKBENCH:未命名任务`)).trim(),n={title:X(`@WORKBENCH:{title} (副本)`,{title:t}),desc:e.desc||``,simpleOverride:e.simpleOverride||``};e.promptParts&&(e.promptParts.global||e.promptParts.project)&&(n.promptParts=e.promptParts),b.value.path&&(n.projectPath=b.value.path);try{let e=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(n)}).then(e=>e.json());if(!e.success){I.error(e.error||X(`@WORKBENCH:复制失败`));return}await re(),e.task?.id&&(j.value=e.task.id,z()),I.success(X(`@WORKBENCH:已复制任务`))}catch(e){I.error(X(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}}async function st(e){if(j.value===e.id)return;W();let t=M.value;t&&G(t)?await K(t):t&&de.value&&await me(),j.value=e.id,z(),d($(b.value.path),e.id)}async function ct(e){let{groupPath:t,orderedIds:n}=e;if(!Array.isArray(n)||n.length===0)return;let r=_.value.slice(),i=ut(_.value,t,n);if(i!==_.value){_.value=i;try{let e=await fetch(`/api/workbench/tasks/reorder`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({orderedIds:n,groupPath:t})}).then(e=>e.json()).catch(()=>({success:!1,error:X(`@WORKBENCH:排序保存失败`)}));e?.success||(_.value=r,I.error(e?.error||X(`@WORKBENCH:排序保存失败`)))}catch(e){_.value=r,I.error(X(`@WORKBENCH:排序保存失败`)+`: `+(e?.message||e))}}}function ut(e,t,n){let r=e=>$(e)||Bl,i=e.filter(e=>r(e.projectPath)===t).map(e=>e.id),a=new Set(i);if(n.length!==a.size||n.some(e=>!a.has(e)))return e;let o=new Map(e.map(e=>[e.id,e])),s=n.map(e=>o.get(e)).filter(Boolean),c=[],l=0;for(let n of e)r(n.projectPath)===t?c.push(s[l++]):c.push(n);return c}async function dt(e){if(!M.value)return!1;let t=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(M.value)}).then(e=>e.json());return t.success?(e&&I.success(X(`@WORKBENCH:已保存`)),await k(),!0):(I.error(t.error||X(`@WORKBENCH:保存失败`)),!1)}o(async()=>{await Promise.all([re(),C(),T()]),await q(),x(),window.addEventListener(`beforeunload`,ge),i.fetchExecutorModels()}),w(()=>{S(),window.removeEventListener(`beforeunload`,ge),M.value&&de.value&&!G(M.value)&&he(M.value)});let{pasteHoverId:pt,isUploading:mt,isImageAttachment:ht,humanSize:gt,onAttachmentPaste:_t,onAttachmentDrop:yt,uploadAttachment:bt,removeAttachment:xt,pickAttachmentFile:St}=dr(),{runTask:Ct,onContinueSendFromChat:wt,cancelJob:Tt,clearExecutionForSelectedTask:Et,onReExecuteJob:Dt,isTaskRunning:Ot,queuedChatsOf:kt,removeQueuedChat:At,flushNextQueued:jt}=hr(y,_,M,{clearJobsByTask:D,persistTask:dt,uploadAttachment:bt,getExecutor:()=>Mt.value}),{active:Mt,availability:Nt,hasAnyExecutor:Pt,choose:Ft,executorModelText:Lt,executorModelTitle:Rt}=lt();function zt(e){return Oe(e)}let Bt=Y(()=>Te(M.value).slice(-1)[0]),Vt=Y(()=>Oe(Bt.value?.agent)),Ut=Y(()=>Ht(Bt.value?.agent)),Wt=Y(()=>De(Bt.value?.agent)?Bt.value.agent:`claude`),Gt={configStore:r,toolsStore:i,LAST_TASK_BY_PROJECT_KEY:zl,NO_PROJECT_KEY:Bl,SIDEBAR_WIDTH_KEY:Vl,SIDEBAR_MIN_W:Hl,SIDEBAR_MAX_W:Ul,SIDEBAR_DEFAULT_W:Wl,sidebarWidth:a,onSidebarSplitterMouseDown:s,nudgeSidebarWidth:c,readLastTaskMap:l,writeLastTaskMap:u,rememberLastTask:d,editorOpen:f,closeEditor:p,boardOpenedTaskId:m,openTaskFromBoard:h,locateTaskFromBoard:g,tasks:_,jobs:y,currentProject:b,connectSSE:x,disconnectSSE:S,loadCurrentProject:C,loadJobs:T,clearJobsByTask:D,_loadDataTasks:O,applyRestoredSelection:ne,refreshTasks:k,loadTasks:re,logsDialogVisible:A,selectedTaskId:j,selectedTask:M,boardTasks:ie,selectedBoardTask:ce,barTimeText:N,barDurationText:ue,barTimeTitle:F,foreignRepo:L,metaSnapshot:R,captureSnapshot:z,metaSaveState:B,metaSavedAt:V,get metaSaveTimer(){return H},set metaSaveTimer(e){H=e},metaDirty:de,clearMetaSaveTimers:W,isTaskBlank:G,discardBlankTask:K,pruneBlankTasks:q,flushMetaSave:me,beaconPersist:he,onBeforeUnloadPersist:ge,taskDescExpanded:J,copyToClipboard:_e,copyTitleFlashId:ve,copyDescFlashId:ye,copyTaskTitle:be,copyTaskDesc:Ce,simpleConversationMessages:we,simpleAllJobsFor:Te,simpleJobFor:Z,simpleJobState:Ee,onChatRetry:Ne,copyExecFlashId:Pe,taskRepoName:Ie,copyTaskExecution:Le,onCopyExecCommand:Re,CHAT_PIN_WINDOW_MS:Gl,CHAT_PIN_USER_EVENTS:ze,chatRef:Be,chatWrapRef:Ve,get chatPinRO(){return Q},set chatPinRO(e){Q=e},get chatPinTimer(){return He},set chatPinTimer(e){He=e},get chatPinEl(){return Ue},set chatPinEl(e){Ue=e},stopChatPin:We,pinChatToBottom:Ge,chatRenderKey:Ke,isTaskRunning:qe,selectedTaskHasRun:Je,selectedTaskRunning:Ye,runButtonTitle:Ze,barStatus:Qe,selectedTaskPromptParts:$e,creatingTask:et,titleInputRef:tt,taskDescTextareaRef:nt,DESC_TEXTAREA_MIN_PX:Kl,DESC_TEXTAREA_MAX_PX:ql,DESC_TEXTAREA_MAX_PX_FOCUS:Jl,autoGrowTextarea:rt,createTaskDirect:it,deleteTask:at,copyTask:ot,selectTask:st,reorderTasks:ct,applyLocalReorder:ut,persistTask:dt,pasteHoverId:pt,isUploading:mt,isImageAttachment:ht,humanSize:gt,onAttachmentPaste:_t,onAttachmentDrop:yt,uploadAttachment:bt,removeAttachment:xt,pickAttachmentFile:St,runTask:Ct,onContinueSendFromChat:wt,cancelJob:Tt,clearExecutionForSelectedTask:Et,onReExecuteJob:Dt,isTaskRunningById:Ot,queuedChatsOf:kt,removeQueuedChat:At,flushNextQueued:jt,selectedTaskExecutor:Mt,executorAvailability:Nt,hasAnyExecutor:Pt,pickExecutor:Ft,executorModelText:Lt,executorModelTitle:Rt,executorLabel:zt,lastSimpleJob:Bt,simpleAssistantLabel:Vt,simpleAssistantAvatar:Ut,lastJobExecutorId:Wt,lastSimpleJobRunning:Y(()=>Ee(Bt.value)===`running`),lastRunExecutorTitle:Y(()=>{let e=Rt(Wt.value),t=X(`@WORKBENCH:本轮实际使用的执行器;上方按钮选的是下一次执行用谁`);return e?`${e} · ${t}`:t}),selectedTaskQueue:Y(()=>M.value?kt(M.value.id):[]),get $t(){return X},get ArrowDown(){return ee},get ArrowLeft(){return E},get ArrowRight(){return te},get Check(){return se},get Document(){return le},get Delete(){return ae},get CopyDocument(){return pe},get VideoPlay(){return v},get Warning(){return oe},AttachmentZone:It,get ChatInput(){return Se},get ChatContainer(){return xe},get MESSAGE_RAIL_CONFIG(){return Xe},ExecutionLogManager:qn,get ALLOWED_EXT_HINT(){return nr},get MAX_ATTACHMENT_BYTES(){return rr},get TASK_EXECUTOR_OPTIONS(){return ke},TaskExecutorIcon:Fe,WorkbenchSidebar:Gr,WorkbenchBoard:Rl,CommonDialog:Me};return Object.defineProperty(Gt,"__isScriptSetup",{enumerable:!1,value:!0}),Gt}});c(),R(),W();var Xl={class:`workbench`},Zl={class:`wb-editor`},Ql={class:`wb-editor-bar`},$l=[`title`],eu=[`title`],tu=[`data-status`,`title`],nu={class:`wb-editor-bar__status-pill`},ru={class:`wb-editor-bar__status-label`},iu=[`title`],au={key:2,class:`wb-editor-bar__time`},ou=[`title`],su={key:1,class:`wb-editor-bar__sep`,"aria-hidden":`true`},cu={key:2,class:`wb-editor-bar__spent`},lu={class:`wb-editor-bar__hint`},uu={class:`workbench__editor-row`},du=[`aria-label`,`aria-valuenow`,`title`],fu={class:`wb-split`},pu={key:0,class:`wb-placeholder`},mu={class:`wb-split__header`},hu={class:`wb-split__title-wrap`},gu=[`placeholder`,`aria-label`],_u=[`title`,`aria-label`],vu=[`title`],yu={key:0,class:`wb-meta-save__dot`},bu={key:1,class:`wb-meta-save__check`},xu={key:2,class:`wb-meta-save__bang`},Su={key:3,class:`wb-meta-save__dot`},Cu=[`data-executor`,`title`],wu={class:`wb-run-executor__text`},Tu=[`title`],Eu={class:`sr-only`},Du={class:`sr-only`},Ou={class:`wb-executor-item`},ku={class:`wb-executor-item__name`},Au=[`title`],ju={key:2,class:`wb-executor-item__missing`},Mu={key:3,class:`wb-no-claude-hint`,role:`status`},Nu={class:`wb-no-claude-hint__text`},Pu={class:`wb-no-claude-hint__link`,href:`https://docs.claude.com/en/docs/claude-code/setup`,target:`_blank`,rel:`noopener noreferrer`},Fu={class:`wb-copy-exec`},Iu=[`title`,`aria-label`],Lu={class:`sr-only`},Ru=[`title`,`aria-label`],zu=[`title`,`aria-label`],Bu={class:`sr-only`},Vu=[`title`,`aria-label`],Hu={class:`sr-only`},Uu=[`open`],Wu={class:`wb-task-desc__summary`},Gu={class:`wb-task-desc__label`},Ku=[`title`,`aria-label`],qu={key:0,class:`wb-task-desc__tag`},Ju={key:0},Yu={key:1,class:`wb-task-desc__tag-attachment`},Xu=[`placeholder`,`aria-label`],Zu={class:`wb-execution-body`},Qu={class:`wb-exec-detail`},$u={class:`wb-form-item__label wb-task-prompt__summary`},ed={key:0,class:`wb-task-prompt__tag`},td={key:0,class:`wb-task-prompt__parts`},nd={class:`wb-task-prompt__label`},rd={class:`wb-task-prompt__text`},id={key:1,class:`wb-task-prompt__empty`},ad={key:0,class:`wb-simple-chat-wrap`,ref:`chatWrapRef`},od={class:`wb-simple-chat`},sd={class:`wb-simple-chat__footer`},cd={key:0,class:`wb-chat-queue`},ld={class:`wb-chat-queue__head`},ud={class:`wb-chat-queue__label`},dd={class:`wb-chat-queue__count`},fd={class:`wb-chat-queue__hint`},pd={class:`wb-chat-queue__index`},md=[`title`],hd={key:0,class:`wb-chat-queue__atts`},gd=[`title`,`aria-label`,`onClick`];function _d(t,i,a,o,s,c){let d=l,f=n,p=ge,m=b;return K(),S(`div`,Xl,[J(` L1:多项目编排台 —— **常驻底图**,不再与编辑器互斥 `),e(o.WorkbenchBoard,{"opened-task-id":o.boardOpenedTaskId,onOpenTask:o.openTaskFromBoard,onBoardTasks:i[0]||=e=>o.boardTasks=e,onLocateTask:o.locateTaskFromBoard},null,8,[`opened-task-id`]),J(` L2:单任务编辑器 —— 默认整屏铺开(原来是 1520px 居中浮层),关掉即回到看板,全程无跳转。
302
302
  custom-class 是给文件末尾那段非 scoped 样式用的:全屏下要抹掉圆角 / 单线边框,
303
- 并把 el-dialog__body 变成撑满剩余高度的 flex 容器。 `),e(o.CommonDialog,{modelValue:o.editorOpen,"onUpdate:modelValue":i[24]||=e=>o.editorOpen=e,title:o.$t(`@WORKBENCH:任务执行`),size:`fullscreen`,type:`flex`,"custom-class":`wb-task-dialog`},{default:L(()=>[x(`div`,Hl,[J(` 顶部细栏:关闭入口做成独立一条,而不是塞进任务头 ——
304
- 没选中任务时(右侧是空态占位)也需要它,塞进任务头就会出现"进了编辑器却关不掉"的死角。 `),x(`div`,Ul,[x(`button`,{type:`button`,class:`wb-back-btn`,title:o.$t(`@WORKBENCH:返回看板`),onClick:o.closeEditor},[e(d,{class:`wb-back-btn__icon`},{default:L(()=>[e(o.ArrowLeft)]),_:1}),x(`span`,null,E(o.$t(`@WORKBENCH:返回看板`)),1)],8,Wl),x(`span`,{class:`wb-editor-bar__project`,title:o.currentProject.path},E(o.currentProject.name),9,Gl),J(`
303
+ 并把 el-dialog__body 变成撑满剩余高度的 flex 容器。 `),e(o.CommonDialog,{modelValue:o.editorOpen,"onUpdate:modelValue":i[24]||=e=>o.editorOpen=e,title:o.$t(`@WORKBENCH:任务执行`),size:`fullscreen`,type:`flex`,"custom-class":`wb-task-dialog`},{default:L(()=>[x(`div`,Zl,[J(` 顶部细栏:关闭入口做成独立一条,而不是塞进任务头 ——
304
+ 没选中任务时(右侧是空态占位)也需要它,塞进任务头就会出现"进了编辑器却关不掉"的死角。 `),x(`div`,Ql,[x(`button`,{type:`button`,class:`wb-back-btn`,title:o.$t(`@WORKBENCH:返回看板`),onClick:o.closeEditor},[e(d,{class:`wb-back-btn__icon`},{default:L(()=>[e(o.ArrowLeft)]),_:1}),x(`span`,null,D(o.$t(`@WORKBENCH:返回看板`)),1)],8,$l),x(`span`,{class:`wb-editor-bar__project`,title:o.currentProject.path},D(o.currentProject.name),9,eu),J(`
305
305
  任务状态徽标(见脚本里 barStatus 那段为什么要有它):
306
306
  紧挨项目名 —— 它和"我在哪 / 打开的是谁"同属"这条任务是什么"的上下文,
307
307
  比挤到右端的时间块旁边更好找。色相走角色色,在跑时圆点脉动。
308
308
  data-status 给探针一个稳定钩子(值 = running / done / error / todo)。
309
- `),o.barStatus?(K(),S(`span`,{key:0,class:w([`wb-editor-bar__status`,`is-`+o.barStatus.key]),"data-status":o.barStatus.key,title:o.barStatus.title||void 0},[x(`span`,ql,[i[26]||=x(`span`,{class:`wb-editor-bar__status-dot`,"aria-hidden":`true`},null,-1),x(`span`,Jl,E(o.barStatus.label),1)])],10,Kl)):J(`v-if`,!0),o.foreignRepo?(K(),S(`span`,{key:1,class:`wb-editor-bar__repo`,title:o.foreignRepo.path},E(o.$t(`@WORKBENCH:执行于 {name}`,{name:o.foreignRepo.name})),9,Yl)):J(`v-if`,!0),J(`
309
+ `),o.barStatus?(K(),S(`span`,{key:0,class:T([`wb-editor-bar__status`,`is-`+o.barStatus.key]),"data-status":o.barStatus.key,title:o.barStatus.title||void 0},[x(`span`,nu,[i[26]||=x(`span`,{class:`wb-editor-bar__status-dot`,"aria-hidden":`true`},null,-1),x(`span`,ru,D(o.barStatus.label),1)])],10,tu)):J(`v-if`,!0),o.foreignRepo?(K(),S(`span`,{key:1,class:`wb-editor-bar__repo`,title:o.foreignRepo.path},D(o.$t(`@WORKBENCH:执行于 {name}`,{name:o.foreignRepo.name})),9,iu)):J(`v-if`,!0),J(`
310
310
  当前任务的时间 / 用时 —— 与看板卡片右上角的相对时间、卡片那行「用时 x」同一口径
311
311
  (值直接取自看板轮询下来的同一条 BoardTask,所以是逐字一致,不是"两边写法对齐")。
312
312
 
@@ -318,7 +318,7 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
318
318
  一路收到 0),「返回看板 / 项目名 / 执行于 xxx」的宽度全程不变
319
319
  (±1px 是 flex 按比例分摊缺口的取整,见样式那段)。
320
320
  悬停提示只挂在相对时间上:绝对值区间解释的是"什么时候",用时本身不用再解释。
321
- `),o.barTimeText||o.barDurationText?(K(),S(`span`,Xl,[o.barTimeText?(K(),S(`span`,{key:0,class:`wb-editor-bar__ago`,title:o.barTimeTitle},E(o.barTimeText),9,Zl)):J(`v-if`,!0),o.barTimeText&&o.barDurationText?(K(),S(`span`,Ql,`·`)):J(`v-if`,!0),o.barDurationText?(K(),S(`span`,$l,E(o.barDurationText),1)):J(`v-if`,!0)])):J(`v-if`,!0),x(`span`,eu,E(o.$t(`@WORKBENCH:任务执行`)),1)]),x(`div`,tu,[e(o.WorkbenchSidebar,{style:u({width:o.sidebarWidth+`px`}),tasks:o.tasks,"selected-task-id":o.selectedTaskId,"current-project":o.currentProject,"creating-task":o.creatingTask,"is-task-running":o.isTaskRunning,onSelectTask:o.selectTask,onDeleteTask:o.deleteTask,onCopyTask:o.copyTask,onCreateTask:o.createTaskDirect,onReorderTasks:o.reorderTasks},null,8,[`style`,`tasks`,`selected-task-id`,`current-project`,`creating-task`]),x(`div`,{class:`wb-splitter`,role:`separator`,tabindex:`0`,"aria-orientation":`vertical`,"aria-label":o.$t(`@WORKBENCH:拖动调整侧边栏宽度`),"aria-valuenow":o.sidebarWidth,"aria-valuemin":o.SIDEBAR_MIN_W,"aria-valuemax":o.SIDEBAR_MAX_W,title:o.$t(`@WORKBENCH:拖动调整侧边栏宽度`),onMousedown:o.onSidebarSplitterMouseDown,onKeydown:[i[1]||=F(N(e=>o.nudgeSidebarWidth(-16),[`prevent`]),[`left`]),i[2]||=F(N(e=>o.nudgeSidebarWidth(16),[`prevent`]),[`right`])]},null,40,nu),J(` 中:单任务编辑区 `),x(`section`,ru,[o.selectedTask?(K(),S(k,{key:1},[x(`div`,au,[x(`div`,ou,[A(x(`input`,{ref:`titleInputRef`,class:`wb-input wb-input--title`,"onUpdate:modelValue":i[3]||=e=>o.selectedTask.title=e,placeholder:o.$t(`@WORKBENCH:任务标题`),"aria-label":o.$t(`@WORKBENCH:任务标题`)},null,8,su),[[G,o.selectedTask.title]]),x(`button`,{type:`button`,class:w([`wb-copy-btn`,{"is-flash":o.copyTitleFlashId===o.selectedTask.id}]),title:o.$t(`@WORKBENCH:复制任务标题`),"aria-label":o.$t(`@WORKBENCH:复制任务标题`),onClick:i[4]||=e=>o.copyTaskTitle(o.selectedTask)},[o.copyTitleFlashId===o.selectedTask.id?(K(),r(d,{key:1,class:`wb-copy-btn__icon wb-copy-btn__icon--check`},{default:L(()=>[...i[27]||=[z(`✓`,-1)]]),_:1})):(K(),r(d,{key:0,class:`wb-copy-btn__icon`},{default:L(()=>[e(o.CopyDocument)]),_:1}))],10,cu)]),o.metaSaveState!==`idle`||o.metaDirty?(K(),S(`span`,{key:0,class:w([`wb-meta-save`,{"is-saving":o.metaSaveState===`saving`,"is-saved":o.metaSaveState===`saved`,"is-error":o.metaSaveState===`error`,"is-dirty":o.metaDirty&&o.metaSaveState===`idle`}]),title:o.metaSaveState===`saving`?o.$t(`@WORKBENCH:保存中…`):o.metaSaveState===`error`?o.$t(`@WORKBENCH:保存失败`):o.metaSaveState===`saved`?o.$t(`@WORKBENCH:已保存`):``},[o.metaSaveState===`saving`?(K(),S(`span`,uu)):o.metaSaveState===`saved`?(K(),S(`span`,du,`✓`)):o.metaSaveState===`error`?(K(),S(`span`,fu,`!`)):(K(),S(`span`,pu)),z(` `+E(o.metaSaveState===`saving`?o.$t(`@WORKBENCH:保存中…`):o.metaSaveState===`saved`?o.$t(`@WORKBENCH:已保存`):o.metaSaveState===`error`?o.$t(`@WORKBENCH:保存失败`):o.$t(`@WORKBENCH:有未保存的更改`)),1)],10,lu)):J(`v-if`,!0),J(`
321
+ `),o.barTimeText||o.barDurationText?(K(),S(`span`,au,[o.barTimeText?(K(),S(`span`,{key:0,class:`wb-editor-bar__ago`,title:o.barTimeTitle},D(o.barTimeText),9,ou)):J(`v-if`,!0),o.barTimeText&&o.barDurationText?(K(),S(`span`,su,`·`)):J(`v-if`,!0),o.barDurationText?(K(),S(`span`,cu,D(o.barDurationText),1)):J(`v-if`,!0)])):J(`v-if`,!0),x(`span`,lu,D(o.$t(`@WORKBENCH:任务执行`)),1)]),x(`div`,uu,[e(o.WorkbenchSidebar,{style:u({width:o.sidebarWidth+`px`}),tasks:o.tasks,"selected-task-id":o.selectedTaskId,"current-project":o.currentProject,"creating-task":o.creatingTask,"is-task-running":o.isTaskRunning,onSelectTask:o.selectTask,onDeleteTask:o.deleteTask,onCopyTask:o.copyTask,onCreateTask:o.createTaskDirect,onReorderTasks:o.reorderTasks},null,8,[`style`,`tasks`,`selected-task-id`,`current-project`,`creating-task`]),x(`div`,{class:`wb-splitter`,role:`separator`,tabindex:`0`,"aria-orientation":`vertical`,"aria-label":o.$t(`@WORKBENCH:拖动调整侧边栏宽度`),"aria-valuenow":o.sidebarWidth,"aria-valuemin":o.SIDEBAR_MIN_W,"aria-valuemax":o.SIDEBAR_MAX_W,title:o.$t(`@WORKBENCH:拖动调整侧边栏宽度`),onMousedown:o.onSidebarSplitterMouseDown,onKeydown:[i[1]||=F(N(e=>o.nudgeSidebarWidth(-16),[`prevent`]),[`left`]),i[2]||=F(N(e=>o.nudgeSidebarWidth(16),[`prevent`]),[`right`])]},null,40,du),J(` 中:单任务编辑区 `),x(`section`,fu,[o.selectedTask?(K(),S(k,{key:1},[x(`div`,mu,[x(`div`,hu,[A(x(`input`,{ref:`titleInputRef`,class:`wb-input wb-input--title`,"onUpdate:modelValue":i[3]||=e=>o.selectedTask.title=e,placeholder:o.$t(`@WORKBENCH:任务标题`),"aria-label":o.$t(`@WORKBENCH:任务标题`)},null,8,gu),[[G,o.selectedTask.title]]),x(`button`,{type:`button`,class:T([`wb-copy-btn`,{"is-flash":o.copyTitleFlashId===o.selectedTask.id}]),title:o.$t(`@WORKBENCH:复制任务标题`),"aria-label":o.$t(`@WORKBENCH:复制任务标题`),onClick:i[4]||=e=>o.copyTaskTitle(o.selectedTask)},[o.copyTitleFlashId===o.selectedTask.id?(K(),r(d,{key:1,class:`wb-copy-btn__icon wb-copy-btn__icon--check`},{default:L(()=>[...i[27]||=[z(`✓`,-1)]]),_:1})):(K(),r(d,{key:0,class:`wb-copy-btn__icon`},{default:L(()=>[e(o.CopyDocument)]),_:1}))],10,_u)]),o.metaSaveState!==`idle`||o.metaDirty?(K(),S(`span`,{key:0,class:T([`wb-meta-save`,{"is-saving":o.metaSaveState===`saving`,"is-saved":o.metaSaveState===`saved`,"is-error":o.metaSaveState===`error`,"is-dirty":o.metaDirty&&o.metaSaveState===`idle`}]),title:o.metaSaveState===`saving`?o.$t(`@WORKBENCH:保存中…`):o.metaSaveState===`error`?o.$t(`@WORKBENCH:保存失败`):o.metaSaveState===`saved`?o.$t(`@WORKBENCH:已保存`):``},[o.metaSaveState===`saving`?(K(),S(`span`,yu)):o.metaSaveState===`saved`?(K(),S(`span`,bu,`✓`)):o.metaSaveState===`error`?(K(),S(`span`,xu,`!`)):(K(),S(`span`,Su)),z(` `+D(o.metaSaveState===`saving`?o.$t(`@WORKBENCH:保存中…`):o.metaSaveState===`saved`?o.$t(`@WORKBENCH:已保存`):o.metaSaveState===`error`?o.$t(`@WORKBENCH:保存失败`):o.$t(`@WORKBENCH:有未保存的更改`)),1)],10,vu)):J(`v-if`,!0),J(`
322
322
  「本轮实际是谁跑的」常驻徽标:对话流左侧那颗执行器头像会随滚动跑掉,而它才是
323
323
  "这一轮用什么执行"的事实;旁边 split button 上挂的 hint 是**下次**用谁
324
324
  (selectedTaskExecutor,用户临时选择),两者经常不一致 —— 切了执行器还没重跑、
@@ -328,33 +328,33 @@ import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Bn as t,C as n,Cn as r,F a
328
328
  (老 job 没有这个字段,按 claude 兜底,与 taskExecutorName 口径一致)。
329
329
  从没跑过的任务不渲染(没有"本轮"可言)。
330
330
  data-executor 给探针一个稳定钩子(值 = claude / opencode / codex / codebuddy / pi)。
331
- `),o.lastSimpleJob?(K(),S(`span`,{key:1,class:w([`wb-run-executor`,{"is-running":o.lastSimpleJobRunning}]),"data-executor":o.lastJobExecutorId,title:o.lastRunExecutorTitle},[e(o.TaskExecutorIcon,{executor:o.lastJobExecutorId,class:`wb-run-executor__icon`},null,8,[`executor`]),x(`span`,hu,E(o.lastSimpleJobRunning?o.$t(`@WORKBENCH:正在由 {name} 执行`,{name:o.simpleAssistantLabel}):o.$t(`@WORKBENCH:本轮由 {name} 执行`,{name:o.simpleAssistantLabel})),1)],10,mu)):J(`v-if`,!0),J(`
331
+ `),o.lastSimpleJob?(K(),S(`span`,{key:1,class:T([`wb-run-executor`,{"is-running":o.lastSimpleJobRunning}]),"data-executor":o.lastJobExecutorId,title:o.lastRunExecutorTitle},[e(o.TaskExecutorIcon,{executor:o.lastJobExecutorId,class:`wb-run-executor__icon`},null,8,[`executor`]),x(`span`,wu,D(o.lastSimpleJobRunning?o.$t(`@WORKBENCH:正在由 {name} 执行`,{name:o.simpleAssistantLabel}):o.$t(`@WORKBENCH:本轮由 {name} 执行`,{name:o.simpleAssistantLabel})),1)],10,Cu)):J(`v-if`,!0),J(`
332
332
  执行:split button —— 主体按当前选中执行器直接跑,下拉临时切换执行器。
333
333
  文案随执行状态变(2026-10-01):这条任务已经有执行记录时改叫「重新执行任务」,
334
334
  因为 runTask 会先清掉旧 job 再开新一轮 —— 挂着「执行任务」会让人以为是接着上一轮跑。
335
335
  在跑的时候直接禁用:服务端本来就拒(400 该任务已有正在执行的 job),
336
336
  点了只是白跑一趟,还想让人误以为新起了一轮。
337
- `),o.hasAnyExecutor?(K(),r(m,{key:2,"split-button":``,type:`primary`,class:`wb-executor-split`,trigger:`click`,disabled:o.selectedTaskRunning,title:o.runButtonTitle,onClick:i[5]||=e=>o.runTask(o.selectedTask),onCommand:o.pickExecutor},{dropdown:L(()=>[e(p,null,{default:L(()=>[(K(!0),S(k,null,D(o.TASK_EXECUTOR_OPTIONS,t=>(K(),r(f,{key:t.id,command:t.id,disabled:!o.executorAvailability[t.id]},{default:L(()=>[x(`span`,yu,[e(o.TaskExecutorIcon,{executor:t.id,class:`wb-executor-item__icon`},null,8,[`executor`]),x(`span`,bu,E(t.name),1),o.executorModelText(t.id)?(K(),S(`span`,{key:0,class:`wb-executor-item__model`,title:o.executorModelTitle(t.id)},E(o.executorModelText(t.id)),9,xu)):J(`v-if`,!0),o.selectedTaskExecutor===t.id?(K(),r(d,{key:1,class:`wb-executor-item__check`},{default:L(()=>[e(o.Check)]),_:1})):o.executorAvailability[t.id]?J(`v-if`,!0):(K(),S(`span`,Su,E(o.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`,`disabled`]))),128))]),_:1})]),default:L(()=>[e(d,{class:`wb-executor-split__play`,"aria-hidden":`true`},{default:L(()=>[e(o.VideoPlay)]),_:1}),x(`span`,{class:`wb-executor-split__hint`,title:o.executorModelTitle(o.selectedTaskExecutor)},[e(o.TaskExecutorIcon,{executor:o.selectedTaskExecutor,class:`wb-executor-split__hint-icon`},null,8,[`executor`]),x(`span`,_u,E(o.executorLabel(o.selectedTaskExecutor)),1)],8,gu),x(`span`,vu,E(o.selectedTaskHasRun?o.$t(`@WORKBENCH:重新执行任务`):o.$t(`@WORKBENCH:执行任务`)),1)]),_:1},8,[`disabled`,`title`,`onCommand`])):(K(),S(`div`,Cu,[e(d,{class:`wb-no-claude-hint__icon`},{default:L(()=>[e(o.Warning)]),_:1}),x(`span`,wu,E(o.$t(`@WORKBENCH:未检测到本地可用的 CLI 执行器,无法执行任务`)),1),x(`a`,Tu,E(o.$t(`@WORKBENCH:查看安装指引`)),1)])),J(` 一键复制执行内容:非破坏性动作,排在最前;「清空执行」这种危险动作留在后面。
338
- 主按钮直接点 = 精简范围(提示词 + 模型回复);右边的箭标展开菜单选「全量」 `),x(`div`,Eu,[x(`button`,{type:`button`,class:w([`wb-logs-inline-btn wb-logs-inline-btn--copy wb-copy-exec__main`,{"is-flash":o.copyExecFlashId===o.selectedTask.id}]),title:o.$t(`@WORKBENCH:复制本任务的对话流(默认精简:仅提示词 + 模型回复)`),"aria-label":o.$t(`@WORKBENCH:复制执行内容`),onClick:i[6]||=e=>o.copyTaskExecution(o.selectedTask,`brief`)},[o.copyExecFlashId===o.selectedTask.id?(K(),r(d,{key:1,class:`wb-logs-inline-btn__icon`},{default:L(()=>[...i[28]||=[z(`✓`,-1)]]),_:1})):(K(),r(d,{key:0,class:`wb-logs-inline-btn__icon`},{default:L(()=>[e(o.CopyDocument)]),_:1})),x(`span`,Ou,E(o.$t(`@WORKBENCH:复制执行内容`)),1)],10,Du),e(m,{trigger:`click`,placement:`bottom-end`,onCommand:o.onCopyExecCommand},{dropdown:L(()=>[e(p,null,{default:L(()=>[e(f,{command:`brief`},{default:L(()=>[z(E(o.$t(`@WORKBENCH:精简:提示词 + 模型回复`)),1)]),_:1}),e(f,{command:`full`},{default:L(()=>[z(E(o.$t(`@WORKBENCH:全量:提示词 / 思考 / 工具调用 / 模型回复`)),1)]),_:1})]),_:1})]),default:L(()=>[x(`button`,{type:`button`,class:`wb-logs-inline-btn wb-copy-exec__caret`,title:o.$t(`@WORKBENCH:选择复制范围`),"aria-label":o.$t(`@WORKBENCH:选择复制范围`)},[e(d,{class:`wb-logs-inline-btn__icon`},{default:L(()=>[e(o.ArrowDown)]),_:1})],8,ku)]),_:1})]),x(`button`,{type:`button`,class:`wb-logs-inline-btn wb-logs-inline-btn--danger`,title:o.$t(`@WORKBENCH:清空当前任务的所有执行内容`),"aria-label":o.$t(`@WORKBENCH:清空当前任务的所有执行内容`),onClick:i[7]||=(...e)=>o.clearExecutionForSelectedTask&&o.clearExecutionForSelectedTask(...e)},[e(d,{class:`wb-logs-inline-btn__icon`},{default:L(()=>[e(o.Delete)]),_:1}),x(`span`,ju,E(o.$t(`@WORKBENCH:清空执行`)),1)],8,Au),x(`button`,{type:`button`,class:`wb-logs-inline-btn`,title:o.$t(`@WORKBENCH:执行日志`),"aria-label":o.$t(`@WORKBENCH:执行日志`),onClick:i[8]||=e=>o.logsDialogVisible=!0},[e(d,{class:`wb-logs-inline-btn__icon`},{default:L(()=>[e(o.Document)]),_:1}),x(`span`,Nu,E(o.$t(`@WORKBENCH:执行日志`)),1)],8,Mu)]),J(` 任务描述区域:默认折叠,节省首屏空间;展开后可编辑/上传附件 `),x(`details`,{class:`wb-task-desc`,open:o.taskDescExpanded,onToggle:i[20]||=e=>o.taskDescExpanded=e.target.open},[x(`summary`,Fu,[e(d,{class:`wb-task-desc__caret`},{default:L(()=>[(K(),r(_(o.taskDescExpanded?o.ArrowDown:o.ArrowRight)))]),_:1}),x(`span`,Iu,E(o.$t(`@WORKBENCH:任务描述(可选)`)),1),x(`button`,{type:`button`,class:w([`wb-copy-btn wb-copy-btn--inline`,{"is-flash":o.copyDescFlashId===o.selectedTask.id}]),title:o.selectedTask.desc&&o.selectedTask.desc.trim()?o.$t(`@WORKBENCH:复制任务描述`):o.$t(`@WORKBENCH:任务描述为空,无需复制`),"aria-label":o.$t(`@WORKBENCH:复制任务描述`),onClick:i[9]||=N(e=>o.copyTaskDesc(o.selectedTask),[`stop`,`prevent`])},[o.copyDescFlashId===o.selectedTask.id?(K(),r(d,{key:1,class:`wb-copy-btn__icon wb-copy-btn__icon--check`},{default:L(()=>[...i[29]||=[z(`✓`,-1)]]),_:1})):(K(),r(d,{key:0,class:`wb-copy-btn__icon`},{default:L(()=>[e(o.CopyDocument)]),_:1}))],10,Lu),o.selectedTask.desc&&o.selectedTask.desc.length>0||o.selectedTask.attachments&&o.selectedTask.attachments.length>0?(K(),S(`span`,Ru,[o.selectedTask.desc&&o.selectedTask.desc.length>0?(K(),S(`span`,zu,E(o.$t(`@WORKBENCH:已填写`)),1)):J(`v-if`,!0),o.selectedTask.attachments&&o.selectedTask.attachments.length>0?(K(),S(`span`,Bu,E(o.selectedTask.attachments.length),1)):J(`v-if`,!0)])):J(`v-if`,!0)]),A(x(`textarea`,{ref:`taskDescTextareaRef`,class:`wb-textarea wb-textarea--autogrow`,"onUpdate:modelValue":i[10]||=e=>o.selectedTask.desc=e,placeholder:o.$t(`@WORKBENCH:任务描述(可选)`),"aria-label":o.$t(`@WORKBENCH:任务描述(可选)`),onInput:i[11]||=e=>o.autoGrowTextarea(e),onFocus:i[12]||=e=>o.autoGrowTextarea(e),onBlur:i[13]||=e=>o.autoGrowTextarea(e),onPaste:i[14]||=e=>o.onAttachmentPaste(e,{kind:`task`,task:o.selectedTask})},null,40,Vu),[[G,o.selectedTask.desc]]),e(o.AttachmentZone,{attachments:o.selectedTask.attachments||[],"is-image":o.isImageAttachment,"human-size":o.humanSize,"is-uploading":o.isUploading(`task-`+o.selectedTask.id),"is-paste-hover":o.pasteHoverId===`task-`+o.selectedTask.id,"on-pick":()=>o.pickAttachmentFile({kind:`task`,task:o.selectedTask}),"on-remove":e=>o.removeAttachment({kind:`task`,task:o.selectedTask},e),onPaste:i[15]||=e=>o.onAttachmentPaste(e,{kind:`task`,task:o.selectedTask}),onDrop:i[16]||=N(e=>o.onAttachmentDrop(e,{kind:`task`,task:o.selectedTask}),[`prevent`]),onDragover:i[17]||=N(e=>o.pasteHoverId=`task-`+o.selectedTask.id,[`prevent`]),onDragenter:i[18]||=N(e=>o.pasteHoverId=`task-`+o.selectedTask.id,[`prevent`]),onDragleave:i[19]||=e=>o.pasteHoverId=o.pasteHoverId===`task-`+o.selectedTask.id?null:o.pasteHoverId},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`,`on-pick`,`on-remove`])],40,Pu),J(` ── 执行主体:一条任务 = 一次会话,详情面板占满整行 ── `),x(`div`,Hu,[J(` 详情面板(执行内容区) `),x(`div`,Uu,[J(` ⚠️ 这一层**不要**用裸 <template> 包起来(踩过,2026-09-22):
337
+ `),o.hasAnyExecutor?(K(),r(m,{key:2,"split-button":``,type:`primary`,class:`wb-executor-split`,trigger:`click`,disabled:o.selectedTaskRunning,title:o.runButtonTitle,onClick:i[5]||=e=>o.runTask(o.selectedTask),onCommand:o.pickExecutor},{dropdown:L(()=>[e(p,null,{default:L(()=>[(K(!0),S(k,null,O(o.TASK_EXECUTOR_OPTIONS,t=>(K(),r(f,{key:t.id,command:t.id,disabled:!o.executorAvailability[t.id]},{default:L(()=>[x(`span`,Ou,[e(o.TaskExecutorIcon,{executor:t.id,class:`wb-executor-item__icon`},null,8,[`executor`]),x(`span`,ku,D(t.name),1),o.executorModelText(t.id)?(K(),S(`span`,{key:0,class:`wb-executor-item__model`,title:o.executorModelTitle(t.id)},D(o.executorModelText(t.id)),9,Au)):J(`v-if`,!0),o.selectedTaskExecutor===t.id?(K(),r(d,{key:1,class:`wb-executor-item__check`},{default:L(()=>[e(o.Check)]),_:1})):o.executorAvailability[t.id]?J(`v-if`,!0):(K(),S(`span`,ju,D(o.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`,`disabled`]))),128))]),_:1})]),default:L(()=>[e(d,{class:`wb-executor-split__play`,"aria-hidden":`true`},{default:L(()=>[e(o.VideoPlay)]),_:1}),x(`span`,{class:`wb-executor-split__hint`,title:o.executorModelTitle(o.selectedTaskExecutor)},[e(o.TaskExecutorIcon,{executor:o.selectedTaskExecutor,class:`wb-executor-split__hint-icon`},null,8,[`executor`]),x(`span`,Eu,D(o.executorLabel(o.selectedTaskExecutor)),1)],8,Tu),x(`span`,Du,D(o.selectedTaskHasRun?o.$t(`@WORKBENCH:重新执行任务`):o.$t(`@WORKBENCH:执行任务`)),1)]),_:1},8,[`disabled`,`title`,`onCommand`])):(K(),S(`div`,Mu,[e(d,{class:`wb-no-claude-hint__icon`},{default:L(()=>[e(o.Warning)]),_:1}),x(`span`,Nu,D(o.$t(`@WORKBENCH:未检测到本地可用的 CLI 执行器,无法执行任务`)),1),x(`a`,Pu,D(o.$t(`@WORKBENCH:查看安装指引`)),1)])),J(` 一键复制执行内容:非破坏性动作,排在最前;「清空执行」这种危险动作留在后面。
338
+ 主按钮直接点 = 精简范围(提示词 + 模型回复);右边的箭标展开菜单选「全量」 `),x(`div`,Fu,[x(`button`,{type:`button`,class:T([`wb-logs-inline-btn wb-logs-inline-btn--copy wb-copy-exec__main`,{"is-flash":o.copyExecFlashId===o.selectedTask.id}]),title:o.$t(`@WORKBENCH:复制本任务的对话流(默认精简:仅提示词 + 模型回复)`),"aria-label":o.$t(`@WORKBENCH:复制执行内容`),onClick:i[6]||=e=>o.copyTaskExecution(o.selectedTask,`brief`)},[o.copyExecFlashId===o.selectedTask.id?(K(),r(d,{key:1,class:`wb-logs-inline-btn__icon`},{default:L(()=>[...i[28]||=[z(`✓`,-1)]]),_:1})):(K(),r(d,{key:0,class:`wb-logs-inline-btn__icon`},{default:L(()=>[e(o.CopyDocument)]),_:1})),x(`span`,Lu,D(o.$t(`@WORKBENCH:复制执行内容`)),1)],10,Iu),e(m,{trigger:`click`,placement:`bottom-end`,onCommand:o.onCopyExecCommand},{dropdown:L(()=>[e(p,null,{default:L(()=>[e(f,{command:`brief`},{default:L(()=>[z(D(o.$t(`@WORKBENCH:精简:提示词 + 模型回复`)),1)]),_:1}),e(f,{command:`full`},{default:L(()=>[z(D(o.$t(`@WORKBENCH:全量:提示词 / 思考 / 工具调用 / 模型回复`)),1)]),_:1})]),_:1})]),default:L(()=>[x(`button`,{type:`button`,class:`wb-logs-inline-btn wb-copy-exec__caret`,title:o.$t(`@WORKBENCH:选择复制范围`),"aria-label":o.$t(`@WORKBENCH:选择复制范围`)},[e(d,{class:`wb-logs-inline-btn__icon`},{default:L(()=>[e(o.ArrowDown)]),_:1})],8,Ru)]),_:1})]),x(`button`,{type:`button`,class:`wb-logs-inline-btn wb-logs-inline-btn--danger`,title:o.$t(`@WORKBENCH:清空当前任务的所有执行内容`),"aria-label":o.$t(`@WORKBENCH:清空当前任务的所有执行内容`),onClick:i[7]||=(...e)=>o.clearExecutionForSelectedTask&&o.clearExecutionForSelectedTask(...e)},[e(d,{class:`wb-logs-inline-btn__icon`},{default:L(()=>[e(o.Delete)]),_:1}),x(`span`,Bu,D(o.$t(`@WORKBENCH:清空执行`)),1)],8,zu),x(`button`,{type:`button`,class:`wb-logs-inline-btn`,title:o.$t(`@WORKBENCH:执行日志`),"aria-label":o.$t(`@WORKBENCH:执行日志`),onClick:i[8]||=e=>o.logsDialogVisible=!0},[e(d,{class:`wb-logs-inline-btn__icon`},{default:L(()=>[e(o.Document)]),_:1}),x(`span`,Hu,D(o.$t(`@WORKBENCH:执行日志`)),1)],8,Vu)]),J(` 任务描述区域:默认折叠,节省首屏空间;展开后可编辑/上传附件 `),x(`details`,{class:`wb-task-desc`,open:o.taskDescExpanded,onToggle:i[20]||=e=>o.taskDescExpanded=e.target.open},[x(`summary`,Wu,[e(d,{class:`wb-task-desc__caret`},{default:L(()=>[(K(),r(_(o.taskDescExpanded?o.ArrowDown:o.ArrowRight)))]),_:1}),x(`span`,Gu,D(o.$t(`@WORKBENCH:任务描述(可选)`)),1),x(`button`,{type:`button`,class:T([`wb-copy-btn wb-copy-btn--inline`,{"is-flash":o.copyDescFlashId===o.selectedTask.id}]),title:o.selectedTask.desc&&o.selectedTask.desc.trim()?o.$t(`@WORKBENCH:复制任务描述`):o.$t(`@WORKBENCH:任务描述为空,无需复制`),"aria-label":o.$t(`@WORKBENCH:复制任务描述`),onClick:i[9]||=N(e=>o.copyTaskDesc(o.selectedTask),[`stop`,`prevent`])},[o.copyDescFlashId===o.selectedTask.id?(K(),r(d,{key:1,class:`wb-copy-btn__icon wb-copy-btn__icon--check`},{default:L(()=>[...i[29]||=[z(`✓`,-1)]]),_:1})):(K(),r(d,{key:0,class:`wb-copy-btn__icon`},{default:L(()=>[e(o.CopyDocument)]),_:1}))],10,Ku),o.selectedTask.desc&&o.selectedTask.desc.length>0||o.selectedTask.attachments&&o.selectedTask.attachments.length>0?(K(),S(`span`,qu,[o.selectedTask.desc&&o.selectedTask.desc.length>0?(K(),S(`span`,Ju,D(o.$t(`@WORKBENCH:已填写`)),1)):J(`v-if`,!0),o.selectedTask.attachments&&o.selectedTask.attachments.length>0?(K(),S(`span`,Yu,D(o.selectedTask.attachments.length),1)):J(`v-if`,!0)])):J(`v-if`,!0)]),A(x(`textarea`,{ref:`taskDescTextareaRef`,class:`wb-textarea wb-textarea--autogrow`,"onUpdate:modelValue":i[10]||=e=>o.selectedTask.desc=e,placeholder:o.$t(`@WORKBENCH:任务描述(可选)`),"aria-label":o.$t(`@WORKBENCH:任务描述(可选)`),onInput:i[11]||=e=>o.autoGrowTextarea(e),onFocus:i[12]||=e=>o.autoGrowTextarea(e),onBlur:i[13]||=e=>o.autoGrowTextarea(e),onPaste:i[14]||=e=>o.onAttachmentPaste(e,{kind:`task`,task:o.selectedTask})},null,40,Xu),[[G,o.selectedTask.desc]]),e(o.AttachmentZone,{attachments:o.selectedTask.attachments||[],"is-image":o.isImageAttachment,"human-size":o.humanSize,"is-uploading":o.isUploading(`task-`+o.selectedTask.id),"is-paste-hover":o.pasteHoverId===`task-`+o.selectedTask.id,"on-pick":()=>o.pickAttachmentFile({kind:`task`,task:o.selectedTask}),"on-remove":e=>o.removeAttachment({kind:`task`,task:o.selectedTask},e),onPaste:i[15]||=e=>o.onAttachmentPaste(e,{kind:`task`,task:o.selectedTask}),onDrop:i[16]||=N(e=>o.onAttachmentDrop(e,{kind:`task`,task:o.selectedTask}),[`prevent`]),onDragover:i[17]||=N(e=>o.pasteHoverId=`task-`+o.selectedTask.id,[`prevent`]),onDragenter:i[18]||=N(e=>o.pasteHoverId=`task-`+o.selectedTask.id,[`prevent`]),onDragleave:i[19]||=e=>o.pasteHoverId=o.pasteHoverId===`task-`+o.selectedTask.id?null:o.pasteHoverId},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`,`on-pick`,`on-remove`])],40,Uu),J(` ── 执行主体:一条任务 = 一次会话,详情面板占满整行 ── `),x(`div`,Zu,[J(` 详情面板(执行内容区) `),x(`div`,Qu,[J(` ⚠️ 这一层**不要**用裸 <template> 包起来(踩过,2026-09-22):
339
339
  Vue 3 只把带 v-if / v-else / v-for / v-slot 的 <template> 编译成片段,
340
340
  裸 <template> 会被当成真的 <template> 元素渲染 —— 浏览器把子节点全塞进
341
341
  template.content(inert DocumentFragment),不产生任何布局盒。
342
342
  症状:任务在跑、看板「执行中」,但对话区一片空白,
343
343
  而 innerText 里明明有内容(元素 0×0)。重构移除子任务概念时留下的空壳。 `),J(` 提示词:派发时冻结的只读快照(全局 + 项目两段),改设置不影响历史任务。
344
- 任务级不可编辑 —— 编辑入口只有主 Agent 控制台的「预设提示词」设置。 `),x(`details`,{class:w([`wb-task-prompt`,{"has-content":o.selectedTaskPromptParts.length>0}])},[x(`summary`,Wu,[e(d,{class:`wb-task-prompt__caret`},{default:L(()=>[e(o.ArrowRight)]),_:1}),x(`span`,null,E(o.$t(`@WORKBENCH:提示词`)),1),o.selectedTaskPromptParts.length>0?(K(),S(`span`,Gu,E(o.$t(`@WORKBENCH:已填写`)),1)):J(`v-if`,!0),o.simpleJobState(o.simpleJobFor(o.selectedTask))===`running`&&o.simpleJobFor(o.selectedTask)?(K(),S(`button`,{key:1,class:`wb-simple__stop`,onClick:i[21]||=N(e=>o.cancelJob(o.simpleJobFor(o.selectedTask)),[`stop`])},E(o.$t(`@WORKBENCH:停止`)),1)):J(`v-if`,!0)]),o.selectedTaskPromptParts.length>0?(K(),S(`div`,Ku,[(K(!0),S(k,null,D(o.selectedTaskPromptParts,e=>(K(),S(`div`,{key:e.key,class:`wb-task-prompt__part`},[x(`div`,qu,E(e.label),1),x(`pre`,Ju,E(e.text),1)]))),128))])):(K(),S(`p`,Yu,E(o.$t(`@WORKBENCH:这条任务没有附加提示词`)),1))],2),J(` 任务对话流:所有轮次合并到单个 ChatContainer `),o.simpleAllJobsFor(o.selectedTask).length>0?(K(),S(`div`,Xu,[J(` ⚠️ 这层 div 不是多余的,class 也**不要**挪回 ChatContainer 上(2026-09-29 踩过):
344
+ 任务级不可编辑 —— 编辑入口只有主 Agent 控制台的「预设提示词」设置。 `),x(`details`,{class:T([`wb-task-prompt`,{"has-content":o.selectedTaskPromptParts.length>0}])},[x(`summary`,$u,[e(d,{class:`wb-task-prompt__caret`},{default:L(()=>[e(o.ArrowRight)]),_:1}),x(`span`,null,D(o.$t(`@WORKBENCH:提示词`)),1),o.selectedTaskPromptParts.length>0?(K(),S(`span`,ed,D(o.$t(`@WORKBENCH:已填写`)),1)):J(`v-if`,!0),o.simpleJobState(o.simpleJobFor(o.selectedTask))===`running`&&o.simpleJobFor(o.selectedTask)?(K(),S(`button`,{key:1,class:`wb-simple__stop`,onClick:i[21]||=N(e=>o.cancelJob(o.simpleJobFor(o.selectedTask)),[`stop`])},D(o.$t(`@WORKBENCH:停止`)),1)):J(`v-if`,!0)]),o.selectedTaskPromptParts.length>0?(K(),S(`div`,td,[(K(!0),S(k,null,O(o.selectedTaskPromptParts,e=>(K(),S(`div`,{key:e.key,class:`wb-task-prompt__part`},[x(`div`,nd,D(e.label),1),x(`pre`,rd,D(e.text),1)]))),128))])):(K(),S(`p`,id,D(o.$t(`@WORKBENCH:这条任务没有附加提示词`)),1))],2),J(` 任务对话流:所有轮次合并到单个 ChatContainer `),o.simpleAllJobsFor(o.selectedTask).length>0?(K(),S(`div`,ad,[J(` ⚠️ 这层 div 不是多余的,class 也**不要**挪回 ChatContainer 上(2026-09-29 踩过):
345
345
  传给 zen-ai-chat-ui 组件的 class 在**生产构建**里不会落到组件根节点上
346
346
  (同一份源码 dev 会落、prod 静默丢掉,实测 class 与父级 data-v-* 双双消失),
347
347
  于是 \`.wb-simple-chat :deep(.acu-*)\` 这一组样式钩子在生产 bundle 里全是死的。
348
348
  症状之一就是「已完成的任务点开后有 2 个输入框」:原来靠
349
349
  \`.acu-chat-footer{display:none}\` 藏 ChatContainer 自带输入框,prod 里那条规则
350
350
  根本没匹配上,lib 自带输入框与下面常驻的 ChatInput 同时显示。
351
- 把 class 挂在自己的 div 上,样式钩子才在 dev / prod 都成立。 `),x(`div`,Zu,[(K(),r(o.ChatContainer,{ref:`chatRef`,key:o.selectedTask.id,messages:o.simpleConversationMessages,"assistant-name":o.simpleAssistantLabel,"assistant-avatar":o.simpleAssistantAvatar,"show-avatar":!0,theme:o.configStore.theme,"tool-calls-config":{group:!0,collapseThreshold:2},"plan-config":{labels:{title:o.$t(`@AGENT:计划`),raw:o.$t(`@AGENT:原始参数`)}},"message-rail-config":o.MESSAGE_RAIL_CONFIG,"show-input":!1,onRetry:o.onChatRetry},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`plan-config`,`message-rail-config`]))]),J(` 输入区:**任务在跑的时候也常驻**。
351
+ 把 class 挂在自己的 div 上,样式钩子才在 dev / prod 都成立。 `),x(`div`,od,[(K(),r(o.ChatContainer,{ref:`chatRef`,key:o.selectedTask.id,messages:o.simpleConversationMessages,"assistant-name":o.simpleAssistantLabel,"assistant-avatar":o.simpleAssistantAvatar,"show-avatar":!0,theme:o.configStore.theme,"tool-calls-config":{group:!0,collapseThreshold:2},"plan-config":{labels:{title:o.$t(`@AGENT:计划`),raw:o.$t(`@AGENT:原始参数`)}},"message-rail-config":o.MESSAGE_RAIL_CONFIG,"show-input":!1,onRetry:o.onChatRetry},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`plan-config`,`message-rail-config`]))]),J(` 输入区:**任务在跑的时候也常驻**。
352
352
  - 空闲:发送 = 立刻续接一轮
353
353
  - 执行中:发送 = 排队,等这一轮 job 进终态自动接上(见 useWorkbenchExecution)
354
- 停止按钮不在这里 —— 它一直在上方「提示词」那一行的右侧。 `),x(`div`,Qu,[o.selectedTaskQueue.length?(K(),S(`div`,$u,[x(`div`,ed,[x(`span`,td,E(o.$t(`@WORKBENCH:排队中`)),1),x(`span`,nd,E(o.selectedTaskQueue.length),1),x(`span`,rd,E(o.selectedTaskRunning?o.$t(`@WORKBENCH:等这一轮跑完自动发送`):o.$t(`@WORKBENCH:当前没有在跑的轮次`)),1)]),(K(!0),S(k,null,D(o.selectedTaskQueue,(e,t)=>(K(),S(`div`,{key:e.id,class:`wb-chat-queue__item`},[x(`span`,id,E(t+1),1),x(`span`,{class:`wb-chat-queue__text`,title:e.text},E(e.text),9,ad),e.files.length?(K(),S(`span`,od,[i[30]||=x(`span`,{"aria-hidden":`true`},`📎`,-1),z(` `+E(e.files.map(e=>e.file.name).join(`、`)),1)])):J(`v-if`,!0),J(` 队首 + 没在跑 = 上一笔发失败了(正常情况终态一到就自动发了),
355
- 给个手动重试;其余情况点它没意义,所以只在队首出现 `),t===0&&!o.selectedTaskRunning?(K(),S(`button`,{key:1,type:`button`,class:`wb-chat-queue__btn`,onClick:i[22]||=e=>o.flushNextQueued(o.selectedTask.id)},E(o.$t(`@WORKBENCH:立即发送`)),1)):J(`v-if`,!0),x(`button`,{type:`button`,class:`wb-chat-queue__btn is-remove`,title:o.$t(`@WORKBENCH:移出队列`),"aria-label":o.$t(`@WORKBENCH:移出队列`),onClick:t=>o.removeQueuedChat(o.selectedTask.id,e.id)},`✕`,8,sd)]))),128))])):J(`v-if`,!0),(K(),r(o.ChatInput,{key:`input-`+o.selectedTask.id,placeholder:o.selectedTaskRunning?o.$t(`@WORKBENCH:执行中,发送后会排队,等这一轮跑完自动接上…`):o.$t(`@WORKBENCH:输入后续问题继续对话…(Ctrl+Enter 发送)`),"upload-config":{enabled:!0,accept:o.ALLOWED_EXT_HINT,multiple:!0,maxCount:0,maxSize:o.MAX_ATTACHMENT_BYTES},class:`wb-simple-chat__input`,onSend:i[23]||=e=>o.onContinueSendFromChat(o.selectedTask,e)},null,8,[`placeholder`,`upload-config`]))])],512)):J(`v-if`,!0)])])],64)):(K(),S(`div`,iu,[x(`p`,null,E(o.$t(`@WORKBENCH:左侧选择任务,或新建一个任务开始`)),1)]))])])])]),_:1},8,[`modelValue`,`title`]),J(` 执行日志管理:弹窗形式承载,原本独立 tab 切换会占用首屏。
354
+ 停止按钮不在这里 —— 它一直在上方「提示词」那一行的右侧。 `),x(`div`,sd,[o.selectedTaskQueue.length?(K(),S(`div`,cd,[x(`div`,ld,[x(`span`,ud,D(o.$t(`@WORKBENCH:排队中`)),1),x(`span`,dd,D(o.selectedTaskQueue.length),1),x(`span`,fd,D(o.selectedTaskRunning?o.$t(`@WORKBENCH:等这一轮跑完自动发送`):o.$t(`@WORKBENCH:当前没有在跑的轮次`)),1)]),(K(!0),S(k,null,O(o.selectedTaskQueue,(e,t)=>(K(),S(`div`,{key:e.id,class:`wb-chat-queue__item`},[x(`span`,pd,D(t+1),1),x(`span`,{class:`wb-chat-queue__text`,title:e.text},D(e.text),9,md),e.files.length?(K(),S(`span`,hd,[i[30]||=x(`span`,{"aria-hidden":`true`},`📎`,-1),z(` `+D(e.files.map(e=>e.file.name).join(`、`)),1)])):J(`v-if`,!0),J(` 队首 + 没在跑 = 上一笔发失败了(正常情况终态一到就自动发了),
355
+ 给个手动重试;其余情况点它没意义,所以只在队首出现 `),t===0&&!o.selectedTaskRunning?(K(),S(`button`,{key:1,type:`button`,class:`wb-chat-queue__btn`,onClick:i[22]||=e=>o.flushNextQueued(o.selectedTask.id)},D(o.$t(`@WORKBENCH:立即发送`)),1)):J(`v-if`,!0),x(`button`,{type:`button`,class:`wb-chat-queue__btn is-remove`,title:o.$t(`@WORKBENCH:移出队列`),"aria-label":o.$t(`@WORKBENCH:移出队列`),onClick:t=>o.removeQueuedChat(o.selectedTask.id,e.id)},`✕`,8,gd)]))),128))])):J(`v-if`,!0),(K(),r(o.ChatInput,{key:`input-`+o.selectedTask.id,placeholder:o.selectedTaskRunning?o.$t(`@WORKBENCH:执行中,发送后会排队,等这一轮跑完自动接上…`):o.$t(`@WORKBENCH:输入后续问题继续对话…(Ctrl+Enter 发送)`),"upload-config":{enabled:!0,accept:o.ALLOWED_EXT_HINT,multiple:!0,maxCount:0,maxSize:o.MAX_ATTACHMENT_BYTES},class:`wb-simple-chat__input`,onSend:i[23]||=e=>o.onContinueSendFromChat(o.selectedTask,e)},null,8,[`placeholder`,`upload-config`]))])],512)):J(`v-if`,!0)])])],64)):(K(),S(`div`,pu,[x(`p`,null,D(o.$t(`@WORKBENCH:左侧选择任务,或新建一个任务开始`)),1)]))])])])]),_:1},8,[`modelValue`,`title`]),J(` 执行日志管理:弹窗形式承载,原本独立 tab 切换会占用首屏。
356
356
 
357
357
  ⚠️ 必须 append-to-body。app shell 的 main.main-container 是 position:fixed + z-index:1001,
358
358
  它自成一个层叠上下文:留在这里面的弹窗 z-index 再高,也只是跟"同一个上下文里的兄弟"比,
359
359
  永远压不过挂在 body 下的 L2 编辑器弹窗(它 escape 了 1001 那层)。
360
- 现象就是点了「执行日志」没反应 —— 其实弹窗开了,只是被编辑器整个盖住。 `),e(o.CommonDialog,{modelValue:o.logsDialogVisible,"onUpdate:modelValue":i[25]||=e=>o.logsDialogVisible=e,title:o.$t(`@WORKBENCH:执行日志`),width:`1080px`,"close-on-click-modal":!1,top:`6vh`,type:`flex`,"custom-class":`wb-logs-dialog`,"append-to-body":``},{default:L(()=>[e(o.ExecutionLogManager)]),_:1},8,[`modelValue`,`title`])])}var ld=Z(Bl,[[`render`,cd],[`__scopeId`,`data-v-28f2e82b`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/WorkbenchView.vue`]]);export{ld as default};
360
+ 现象就是点了「执行日志」没反应 —— 其实弹窗开了,只是被编辑器整个盖住。 `),e(o.CommonDialog,{modelValue:o.logsDialogVisible,"onUpdate:modelValue":i[25]||=e=>o.logsDialogVisible=e,title:o.$t(`@WORKBENCH:执行日志`),width:`1080px`,"close-on-click-modal":!1,top:`6vh`,type:`flex`,"custom-class":`wb-logs-dialog`,"append-to-body":``},{default:L(()=>[e(o.ExecutionLogManager)]),_:1},8,[`modelValue`,`title`])])}var vd=Z(Yl,[[`render`,_d],[`__scopeId`,`data-v-28f2e82b`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/WorkbenchView.vue`]]);export{vd as default};