zen-gitsync 2.17.27 → 2.17.28

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 (83) hide show
  1. package/README.md +4 -2
  2. package/package.json +2 -1
  3. package/src/config.js +8 -0
  4. package/src/ui/public/assets/AgentEngineSelector-D8iaDrev.js +2 -0
  5. package/src/ui/public/assets/AgentView-BQz9h_Qi.js +10 -0
  6. package/src/ui/public/assets/AppVersionBadge-Mx8QwTA1.js +2 -0
  7. package/src/ui/public/assets/BranchSelector-CTrTouMm.js +1 -0
  8. package/src/ui/public/assets/CommitForm-DsfySGI2.js +6 -0
  9. package/src/ui/public/assets/CommonDialog-Bwj--3EO.js +1 -0
  10. package/src/ui/public/assets/EditorView-DiyJWwAk.js +37 -0
  11. package/src/ui/public/assets/FileDiffViewer-DFFyUPF2.js +15 -0
  12. package/src/ui/public/assets/{FlowExecutionViewer-Dp3ZiatT.js → FlowExecutionViewer-awWx7pMb.js} +1 -1
  13. package/src/ui/public/assets/FlowOrchestrationWorkspace-Brq0M2sZ.js +21 -0
  14. package/src/ui/public/assets/IconButton-IoukQQts.js +1 -0
  15. package/src/ui/public/assets/LogList-Ca0hE-S0.js +7 -0
  16. package/src/ui/public/assets/MindmapView-BO_PG-mg.js +2 -0
  17. package/src/ui/public/assets/MonitorView-BXlLpzYU.js +1 -0
  18. package/src/ui/public/assets/ProjectStartupButton-C8OZPgjM.js +1 -0
  19. package/src/ui/public/assets/{RecentDirectoriesChat-6OG0eOqz.js → RecentDirectoriesChat-DFGIm3ab.js} +2 -2
  20. package/src/ui/public/assets/RemoteManagerDialog-DFtZmhn4.js +4 -0
  21. package/src/ui/public/assets/RemoteRepoCard-HV8oHZL_.js +7 -0
  22. package/src/ui/public/assets/SourceMapView-ByGif9Z8.js +3 -0
  23. package/src/ui/public/assets/{SvgIcon-22vrNtgL.js → SvgIcon-Cv-Ewpj-.js} +1 -1
  24. package/src/ui/public/assets/TemplateManager-DBuPZE4y.js +1 -0
  25. package/src/ui/public/assets/UserInputNode-CVKtLvHE.js +1 -0
  26. package/src/ui/public/assets/WorkbenchView-5K0toOqC.js +143 -0
  27. package/src/ui/public/assets/WorkbenchView-BA7mKIr4.css +1 -0
  28. package/src/ui/public/assets/{_plugin-vue_export-helper-DRfZJqP7.js → _plugin-vue_export-helper-BP5VbhV0.js} +3 -3
  29. package/src/ui/public/assets/{agentConversations-17Pw5IQJ.js → agentConversations-CDIB8kgC.js} +5 -5
  30. package/src/ui/public/assets/configStore-eQKYDKzd.js +1 -0
  31. package/src/ui/public/assets/{css.worker-DFdt6_zu.js → css.worker-BDCmgL4U.js} +9 -9
  32. package/src/ui/public/assets/editor.worker-GCPm6rMv.js +26 -0
  33. package/src/ui/public/assets/{element-plus-Qexo5hiM.css → element-plus-C1xzgNSR.css} +1 -1
  34. package/src/ui/public/assets/element-plus-D7LDHcAn.js +48 -0
  35. package/src/ui/public/assets/{flow-mindmap-C22NSZc1.js → flow-mindmap-B3900Z4K.js} +52 -52
  36. package/src/ui/public/assets/gitStore-8MMG-kBB.js +6 -0
  37. package/src/ui/public/assets/{html.worker-JUzsMP-j.js → html.worker-DG8hnSJR.js} +8 -8
  38. package/src/ui/public/assets/index-DBOS6HZF.js +148 -0
  39. package/src/ui/public/assets/index-DVpFh9xE.css +1 -0
  40. package/src/ui/public/assets/json.worker-CxwlJRnL.js +58 -0
  41. package/src/ui/public/assets/{monaco-DkJuNcCr.js → monaco-BScz9v63.js} +6 -6
  42. package/src/ui/public/assets/{office-docx-CJ6JSCs6.js → office-docx-C8sYW8O1.js} +6 -6
  43. package/src/ui/public/assets/{office-excel-BOjWK-1x.js → office-excel-DpZn5My2.js} +1 -1
  44. package/src/ui/public/assets/{office-pptx-CF43ZwXE.js → office-pptx-BnYBTwT7.js} +3 -3
  45. package/src/ui/public/assets/previewSandbox-C-BRP5dF.js +9 -0
  46. package/src/ui/public/assets/toolsStore-C4B7BL-O.js +1 -0
  47. package/src/ui/public/assets/{ts.worker-CmEKzkmF.js → ts.worker-DgFMIcEs.js} +49 -49
  48. package/src/ui/public/assets/{useThemeObserver-CiUpR4zj.js → useThemeObserver-CGbhdyNi.js} +1 -1
  49. package/src/ui/public/assets/{vendor-viKaN257.js → vendor-CUTaFm6P.js} +13 -13
  50. package/src/ui/public/assets/vue-flow-CxnoC7Uq.js +39 -0
  51. package/src/ui/public/index.html +19 -19
  52. package/src/ui/server/routes/workbench/executorModels.test.js +326 -326
  53. package/src/ui/public/assets/AgentEngineSelector-BUZYAFe-.js +0 -2
  54. package/src/ui/public/assets/AgentView-BFSmHCq7.js +0 -10
  55. package/src/ui/public/assets/AppVersionBadge-BVZKGETC.js +0 -2
  56. package/src/ui/public/assets/BranchSelector-DHWPodUA.js +0 -1
  57. package/src/ui/public/assets/CommitForm-OhIAOaq7.js +0 -6
  58. package/src/ui/public/assets/CommonDialog-BXR1wKBq.js +0 -1
  59. package/src/ui/public/assets/EditorView-8SLDYcaH.js +0 -37
  60. package/src/ui/public/assets/FileDiffViewer-CfMdcN2j.js +0 -15
  61. package/src/ui/public/assets/FlowOrchestrationWorkspace-D97DHgyy.js +0 -21
  62. package/src/ui/public/assets/IconButton-BburHRSR.js +0 -1
  63. package/src/ui/public/assets/LogList-gFCt4Zlu.js +0 -7
  64. package/src/ui/public/assets/MindmapView-N67x62Qk.js +0 -2
  65. package/src/ui/public/assets/MonitorView-BQr56ZSC.js +0 -1
  66. package/src/ui/public/assets/ProjectStartupButton-DuWf9Z0m.js +0 -1
  67. package/src/ui/public/assets/RemoteManagerDialog-DrR79IRj.js +0 -4
  68. package/src/ui/public/assets/RemoteRepoCard-BU6qOfoG.js +0 -7
  69. package/src/ui/public/assets/SourceMapView-Ba73NVs8.js +0 -3
  70. package/src/ui/public/assets/TemplateManager-C9CzSc6Y.js +0 -1
  71. package/src/ui/public/assets/UserInputNode-4m8zpMv9.js +0 -1
  72. package/src/ui/public/assets/WorkbenchView-B4F_TeL5.css +0 -1
  73. package/src/ui/public/assets/WorkbenchView-CcqEZ_GQ.js +0 -142
  74. package/src/ui/public/assets/configStore-Gzz89_z_.js +0 -1
  75. package/src/ui/public/assets/editor.worker-O-CH8JUO.js +0 -26
  76. package/src/ui/public/assets/element-plus-AaVXaSqv.js +0 -48
  77. package/src/ui/public/assets/gitStore--fzrTf_y.js +0 -6
  78. package/src/ui/public/assets/index-C7Ad5BGO.css +0 -1
  79. package/src/ui/public/assets/index-EJrJOx7s.js +0 -142
  80. package/src/ui/public/assets/json.worker-B4dEhy0e.js +0 -58
  81. package/src/ui/public/assets/previewSandbox-BOIpC6hW.js +0 -9
  82. package/src/ui/public/assets/toolsStore-B3bFcRXP.js +0 -1
  83. package/src/ui/public/assets/vue-flow-DwYB6Myr.js +0 -39
@@ -0,0 +1,143 @@
1
+ import"./rolldown-runtime-C0FnF6B9.js";import{$ as e,An as t,At as n,Bt as r,C as i,Cn as a,Dn as o,En as s,F as c,Ft as l,Gn as u,Hn as d,It as f,J as p,Jr as m,K as h,Kr as g,Kt as _,L as v,Lt as y,M as b,Mn as x,Nr as S,Nt as C,P as w,Pn as T,Qr as E,Rn as D,S as O,Tn as k,U as ee,Ut as te,V as ne,W as A,Y as re,Yn as j,Zn as M,_ as N,_n as P,_t as ie,a as ae,b as oe,bt as se,dr as F,dt as ce,er as I,fn as le,gn as L,gr as ue,hn as R,ht as de,i as z,ir as B,it as fe,jn as V,ln as H,lt as U,mn as W,or as G,ot as pe,q as me,qn as he,r as ge,rn as _e,sr as K,st as ve,v as ye,vn as q,vr as J,w as be,wn as Y,wt as xe,xn as Se,xt as Ce,y as we,yn as X,zt as Te}from"./element-plus-D7LDHcAn.js";import{i as Ee,n as De,o as Oe,r as ke,s as Ae}from"./vendor-CUTaFm6P.js";import{n as Z,t as Q}from"./_plugin-vue_export-helper-BP5VbhV0.js";import{t as je}from"./SvgIcon-Cv-Ewpj-.js";import{a as Me,i as Ne,o as Pe,t as Fe}from"./configStore-eQKYDKzd.js";import{t as Ie}from"./toolsStore-C4B7BL-O.js";import{t as Le}from"./useThemeObserver-CGbhdyNi.js";import{t as Re}from"./CommonDialog-Bwj--3EO.js";import{E as $,_ as ze,d as Be,f as Ve,g as He,h as Ue,m as We,o as Ge,p as Ke,s as qe,u as Je,v as Ye}from"./index-DBOS6HZF.js";import{a as Xe,i as Ze,n as Qe,o as $e,r as et,s as tt,t as nt,u as rt}from"./agentConversations-CDIB8kgC.js";import{n as it,t as at}from"./AgentEngineSelector-D8iaDrev.js";D(),F();var ot=T({__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 o=n,s=a(()=>r.attachments.filter(e=>r.isImage(e))),c=a(()=>s.value.map(e=>i(e))),l=J(0),d=J(!1);function f(e){if(r.isImage(e)){let t=s.value.findIndex(t=>t.id===e.id);l.value=t>=0?t:0,d.value=!0}else window.open(i(e),`_blank`,`noopener`)}function p(){d.value=!1}let m=J({visible:!1,x:0,y:0,att:null}),h=J(!1);function g(e,t){if(!r.isImage(e))return;t.preventDefault();let n=window.innerWidth-180,i=window.innerHeight-120;m.value={visible:!0,x:Math.min(t.clientX,n),y:Math.min(t.clientY,i),att:e}}function _(){m.value.visible&&(m.value.visible=!1)}async function v(){let e=m.value.att;if(e&&!h.value){if(_(),!navigator.clipboard||typeof ClipboardItem>`u`){z({type:`warning`,message:Z(`@WORKBENCH:当前浏览器不支持复制图片`)});return}h.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]),z({type:`success`,message:Z(`@WORKBENCH:图片已复制到剪贴板`),duration:1800})}catch(e){z({type:`error`,message:Z(`@WORKBENCH:复制失败 {error}`,{error:e?.message||``})})}finally{h.value=!1}}}typeof window<`u`&&(window.addEventListener(`click`,_),window.addEventListener(`scroll`,_,!0),window.addEventListener(`blur`,_)),u(()=>{typeof window>`u`||(window.removeEventListener(`click`,_),window.removeEventListener(`scroll`,_,!0),window.removeEventListener(`blur`,_))});let y={props:r,rawOf:i,emit:o,imageList:s,previewUrls:c,previewIndex:l,previewVisible:d,previewAttachment:f,closePreview:p,contextMenu:m,copyBusy:h,openContextMenu:g,closeContextMenu:_,copyImageToClipboard:v,get ElImageViewer(){return oe},get $t(){return Z}};return Object.defineProperty(y,"__isScriptSetup",{enumerable:!1,value:!0}),y}});S(),D(),H();var st={class:`wb-attachments__head`},ct={class:`wb-attachments__label`},lt={class:`wb-attachments__count`},ut=[`disabled`],dt={key:0,class:`wb-attachments__paste-hint`},ft={key:1,class:`wb-attachments__list`},pt=[`title`,`onClick`,`onContextmenu`],mt=[`src`,`alt`],ht={key:1},gt={class:`wb-attachment__meta`},_t=[`title`],vt=[`onClick`,`title`];function yt(e,t,n,r,i,a){return j(),o(X,null,[Y(`div`,{class:g([`wb-attachments`,{"is-paste-hover":n.isPasteHover}]),onPaste:t[1]||=e=>r.emit(`paste`,e),onDrop:t[2]||=q(e=>r.emit(`drop`,e),[`prevent`]),onDragover:t[3]||=q(e=>r.emit(`dragover`,e),[`prevent`]),onDragenter:t[4]||=q(e=>r.emit(`dragenter`,e),[`prevent`]),onDragleave:t[5]||=e=>r.emit(`dragleave`,e)},[Y(`div`,st,[Y(`span`,ct,[V(E(r.$t(`@WORKBENCH:附件`))+` `,1),s(` 只报个数:数量不设上限,写成 "N / 9" 会让人以为还剩几个能加 `),Y(`span`,lt,E(n.attachments.length),1)]),Y(`button`,{class:`wb-attachments__add wb-soft-btn`,disabled:n.isUploading,onClick:t[0]||=(...e)=>n.onPick&&n.onPick(...e)},E(n.isUploading?r.$t(`@WORKBENCH:上传中…`):r.$t(`@WORKBENCH:添加附件`)),9,ut)]),n.isPasteHover?(j(),o(`div`,dt,E(r.$t(`@WORKBENCH:粘贴图片以快速添加`)),1)):s(`v-if`,!0),n.attachments.length>0?(j(),o(`ul`,ft,[(j(!0),o(X,null,M(n.attachments,e=>(j(),o(`li`,{key:e.id,class:`wb-attachment`},[Y(`button`,{type:`button`,class:`wb-attachment__preview`,title:r.$t(`@WORKBENCH:点击预览`),onClick:t=>r.previewAttachment(e),onContextmenu:t=>r.openContextMenu(e,t)},[Y(`div`,{class:g([`wb-attachment__icon`,{"wb-attachment__icon--img":n.isImage(e)}])},[n.isImage(e)?(j(),o(`img`,{key:0,src:r.rawOf(e),alt:e.originalName,loading:`lazy`},null,8,mt)):(j(),o(`span`,ht,E(e.ext.toUpperCase()),1))],2),Y(`div`,gt,[Y(`div`,{class:`wb-attachment__name`,title:`${e.originalName} (${n.humanSize(e.size)})`},E(e.originalName),9,_t)])],40,pt),Y(`button`,{class:`wb-attachment__del`,onClick:q(t=>n.onRemove(e),[`stop`]),title:r.$t(`@WORKBENCH:删除`)},`×`,8,vt)]))),128))])):s(`v-if`,!0)],34),s(`
2
+ el-image-viewer 自己通过内部 <Teleport to="body" :disabled="!teleported"> 把遮罩渲染到 body。
3
+ 不要在外面再包一层 <teleport to="body"> —— 嵌套 Teleport 在 element-plus 2.11.x 下会让组件
4
+ 的 v-if 容器内残留占位、且内部 Teleport 因找不到正确锚点而不挂载,导致点击图片无反应。
5
+ 显式传 :teleported="true" 是为了保证内部 Teleport 启用(默认是 undefined 关闭)。
6
+ `),r.previewVisible&&r.previewUrls.length>0?(j(),k(r.ElImageViewer,{key:0,"url-list":r.previewUrls,"initial-index":r.previewIndex,"hide-on-click-modal":!0,teleported:!0,onClose:r.closePreview},null,8,[`url-list`,`initial-index`])):s(`v-if`,!0),s(` 右键菜单:仅图片附件可用 `),(j(),k(Se,{to:`body`},[r.contextMenu.visible&&r.contextMenu.att&&n.isImage(r.contextMenu.att)?(j(),o(`ul`,{key:0,class:`wb-ctx-menu`,style:m({top:r.contextMenu.y+`px`,left:r.contextMenu.x+`px`}),onContextmenu:t[6]||=q(()=>{},[`prevent`])},[Y(`li`,{class:g([`wb-ctx-menu__item`,{"is-disabled":r.copyBusy}]),onClick:r.copyImageToClipboard},[t[7]||=Y(`span`,{class:`wb-ctx-menu__icon`,"aria-hidden":`true`},[Y(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[Y(`rect`,{x:`9`,y:`9`,width:`11`,height:`11`,rx:`2`}),Y(`path`,{d:`M5 15V5a2 2 0 0 1 2-2h10`})])],-1),Y(`span`,null,E(r.$t(`@WORKBENCH:复制图片`)),1)],2)],36)):s(`v-if`,!0)]))],64)}var bt=Q(ot,[[`render`,yt],[`__scopeId`,`data-v-d2df2361`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/AttachmentZone.vue`]]),xt=ke(`claude`),St=ke(`opencode`),Ct=ke(`codex`);function wt(e){return e===`opencode`?St:e===`codex`?Ct:xt}function Tt(e){switch(e){case`todo`:return Z(`@WORKBENCH:待执行`);case`running`:return Z(`@WORKBENCH:执行中`);case`done`:return Z(`@WORKBENCH:已完成`);case`error`:return Z(`@WORKBENCH:出错`);case`cancelled`:return Z(`@WORKBENCH:已取消`);case`pending`:return Z(`@WORKBENCH:排队中`);default:return e}}function Et(e){switch(e){case`running`:return`var(--color-primary)`;case`done`:return`#22c55e`;case`error`:return`#ef4444`;case`cancelled`:return`#9ca3af`;case`pending`:return`#f59e0b`;default:return`var(--text-tertiary)`}}var Dt=8192;function Ot(e,t){return e.length>t?`…(前文已截断)\n${e.slice(-t)}`:e}function kt(e,t){let n=e||`done`;return n!==`pending`&&n!==`running`||t===`running`||t===`pending`?n:t===`cancelled`||t===`error`?`error`:`done`}function At(e){let t=e?.toolCalls;if(!Array.isArray(t)||t.length===0)return[];let n=e?.status||`done`,r=[];for(let e=0;e<t.length;e++){let i=t[e];if(!i||typeof i!=`object`)continue;let a=kt(i.status,n),o=typeof i.result==`string`?i.result:``;r.push({id:typeof i.id==`string`&&i.id?i.id:`tool-${e}`,name:typeof i.name==`string`?i.name:``,argsPreview:typeof i.argsPreview==`string`?i.argsPreview:``,arguments:typeof i.arguments==`string`?i.arguments:``,result:o?Ot(o,Dt):``,status:a,error:typeof i.error==`string`&&i.error?i.error:void 0})}return r}D(),F();var jt=65536,Mt=T({__name:`JobLogDetails`,props:{job:{type:Object,required:!0}},emits:[`re-execute`],setup(e,{expose:t,emit:n}){t();let r=Fe(),i=e,o=n,s=J(!1);function c(){s.value=!s.value}let l=a(()=>i.job.status===`running`||i.job.status===`pending`);B(()=>i.job.status,(e,t)=>{t!==`running`&&t!==`pending`&&(e===`running`||e===`pending`)&&(s.value=!1)});function u(){let e=i.job.output||``;return e?e.length<=jt?e:`${Z(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`:``}function f(){let e=i.job.thinking||``;return e?e.length<=jt?e:`${Z(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`:``}async function p(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 m(){let e=[];if(i.job.prompt&&e.push(`## ${Z(`@WORKBENCH:用户提示词`)}\n\n${i.job.prompt}`),i.job.thinking&&e.push(`## ${Z(`@WORKBENCH:Claude 思考`)}\n\n${i.job.thinking}`),i.job.output&&e.push(`## ${Z(`@WORKBENCH:模型返回`)}\n\n${i.job.output}`),!e.length){z.warning(Z(`@WORKBENCH:暂无内容可复制`));return}await p(e.join(`
7
+
8
+ ---
9
+
10
+ `))?z.success(Z(`@WORKBENCH:已复制到剪贴板`)):z.error(Z(`@WORKBENCH:复制失败`))}let h=a(()=>{let e=i.job.status;return e===`done`||e===`error`||e===`cancelled`}),g=a(()=>i.job.status===`cancelled`?`wb-log-summary__status--cancelled`:i.job.status===`error`?`wb-log-summary__status--error`:`wb-log-summary__status--done`),_=a(()=>i.job.status===`cancelled`?`⏹`:i.job.status===`error`?`✗`:`✓`),v=a(()=>i.job.status===`cancelled`?Z(`@WORKBENCH:已停止`):i.job.status===`error`?Z(`@WORKBENCH:执行出错`):Z(`@WORKBENCH:执行完成`)),y=a(()=>Pe(i.job?.agent)),b=a(()=>wt(i.job?.agent));function x(e,t){return e===`running`||e===`pending`?t?`streaming`:`pending`:e===`error`?`error`:`done`}let S=a(()=>{let e=i.job,t=[],n=e.startedAt?new Date(e.startedAt).getTime():Date.now();e.prompt&&t.push({id:`${e.id}-u`,role:`user`,content:e.prompt,status:`done`,createdAt:n});let r=u(),a=f(),o=!!r,s=!!a,c=At(e),l=c.length>0,d=o||s||l,p=x(e.status,d);return t.push({id:`${e.id}-a`,role:`assistant`,content:r,reasoning:s?a:void 0,reasoningStatus:s?o?`done`:p===`streaming`?`streaming`:`done`:void 0,toolCalls:l?c:void 0,status:p,error:p===`error`&&e.error||void 0,createdAt:n}),t}),C=J(null);B(()=>i.job.status,(e,t)=>{e===`running`&&t!==`running`&&(C.value=C.value??Date.now())});let w=a(()=>{if(!C.value)return``;let e=C.value,t=i.job.endedAt?new Date(i.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`)}秒`}),T=J(!1),E=a(()=>!!(i.job.output&&i.job.output.length)),D=a(()=>i.job.output||``),O=J(null);B(T,async e=>{e&&(await d(),O.value&&(O.value.scrollTop=O.value.scrollHeight))}),B(()=>(i.job.output||``).length,async()=>{T.value&&(await d(),O.value&&(O.value.scrollTop=O.value.scrollHeight))});function k(){}let ee=a(()=>h.value&&!!i.job.prompt);function te(){o(`re-execute`,i.job)}let ne={configStore:r,props:i,emit:o,isCollapsed:s,toggleOpen:c,isActive:l,MAX_LOG_DISPLAY:jt,displayOutput:u,displayThinking:f,copyToClipboard:p,copyAll:m,isFinished:h,finishedStatusClass:g,finishedStatusIcon:_,finishedStatusLabel:v,assistantLabel:y,assistantAvatar:b,mapStatus:x,chatMessages:S,startedAt:C,elapsedLabel:w,fullscreenOpen:T,hasOutput:E,fullscreenSource:D,fullscreenContainerRef:O,onFullscreenClosed:k,canReExecute:ee,onReExecute:te,get ChatContainer(){return Ae},get MarkdownRenderer(){return De},get $t(){return Z},CommonDialog:Re};return Object.defineProperty(ne,"__isScriptSetup",{enumerable:!1,value:!0}),ne}});S(),D(),H();var Nt=[`aria-expanded`],Pt={class:`wb-log-summary__left`},Ft={key:0,class:`wb-log-summary__status wb-log-summary__status--running`},It={class:`wb-log-summary__label`},Lt={key:0,class:`wb-log-summary__elapsed`},Rt={key:1,class:`wb-log-summary__status wb-log-summary__status--pending`},zt={class:`wb-log-summary__label`},Bt={class:`wb-log-summary__icon`},Vt={class:`wb-log-summary__label`},Ht={key:0,class:`wb-log-summary__elapsed`},Ut={key:3},Wt={class:`wb-log-summary__right`},Gt={class:`wb-log-summary__meta`},Kt=[`title`,`aria-label`],qt={class:`wb-log-details__body`},Jt={class:`wb-job-chat`},Yt={key:0,class:`wb-chat__foot`},Xt=[`title`,`aria-label`],Zt={ref:`fullscreenContainerRef`,class:`wb-log-fullscreen`},Qt={key:1,class:`wb-log-fullscreen__empty`};function $t(e,t,n,r,i,a){return j(),o(`div`,{class:g([`wb-log-details`,{"is-running":r.isActive,"is-pending":n.job.status===`pending`,"is-finished":r.isFinished}])},[Y(`div`,{class:`wb-log-summary`,onClick:r.toggleOpen,role:`button`,"aria-expanded":!r.isCollapsed},[Y(`span`,Pt,[n.job.status===`running`?(j(),o(`span`,Ft,[Y(`span`,It,E(r.$t(`@WORKBENCH:正在执行…`)),1),t[1]||=Y(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[Y(`span`,{class:`wb-log-dots__dot`}),Y(`span`,{class:`wb-log-dots__dot`}),Y(`span`,{class:`wb-log-dots__dot`})],-1),r.elapsedLabel?(j(),o(`span`,Lt,E(r.elapsedLabel),1)):s(`v-if`,!0)])):n.job.status===`pending`?(j(),o(`span`,Rt,[Y(`span`,zt,E(r.$t(`@WORKBENCH:排队中…`)),1),t[2]||=Y(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[Y(`span`,{class:`wb-log-dots__dot`}),Y(`span`,{class:`wb-log-dots__dot`}),Y(`span`,{class:`wb-log-dots__dot`})],-1)])):r.isFinished?(j(),o(`span`,{key:2,class:g([`wb-log-summary__status`,r.finishedStatusClass])},[Y(`span`,Bt,E(r.finishedStatusIcon),1),Y(`span`,Vt,E(r.finishedStatusLabel),1),r.elapsedLabel?(j(),o(`span`,Ht,E(r.elapsedLabel),1)):s(`v-if`,!0)],2)):(j(),o(`span`,Ut,E(r.$t(`@WORKBENCH:查看执行日志`)),1))]),Y(`span`,Wt,[Y(`span`,Gt,E((n.job.output||``).length)+` `+E(r.$t(`@WORKBENCH:字符`)),1),Y(`button`,{type:`button`,class:`wb-log-copy`,title:r.$t(`@WORKBENCH:复制全部(含提示词与输出)`),"aria-label":r.$t(`@WORKBENCH:复制全部`),onClick:q(r.copyAll,[`stop`])},` ⧉ `,8,Kt)])],8,Nt),s(`
11
+ body 容器:用 zen-ai-chat-ui 的 ChatContainer 渲染单轮对话。
12
+ 关掉 ChatContainer 自带的输入框(show-input=false —— 续聊输入由父组件统一承载),
13
+ 下方保留"重新执行"footer。
14
+
15
+ ⚠️ 别改回「class 挂到 ChatContainer 上 + CSS 隐藏」:传给 zen-ai-chat-ui 组件的 class
16
+ 在**生产构建**里不会落到组件根节点上(dev 会落、prod 静默丢),\`.wb-job-chat :deep(.acu-*)\`
17
+ 就全成了死代码 —— 自带的输入框藏不住,背景/气泡密度也全是库默认值。
18
+ 2026-09-29 在 WorkbenchView 上就是这个坑(「已完成任务点开有 2 个输入框」)。
19
+ 所以外层套一个自己的 div 承载 class。
20
+ `),K(Y(`div`,qt,[Y(`div`,Jt,[x(r.ChatContainer,{messages:r.chatMessages,"assistant-name":r.assistantLabel,"assistant-avatar":r.assistantAvatar,"show-avatar":!0,theme:r.configStore.theme,"tool-calls-config":{group:!0,collapseThreshold:2},"plan-config":{labels:{title:r.$t(`@AGENT:计划`),raw:r.$t(`@AGENT:原始参数`)}},"show-input":!1},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`plan-config`])]),s(` footer:任务结束后显示"重新执行",运行中不显示 `),r.canReExecute?(j(),o(`footer`,Yt,[Y(`button`,{type:`button`,class:`wb-chat__action`,title:r.$t(`@WORKBENCH:用相同的提示词重新执行此任务`),"aria-label":r.$t(`@WORKBENCH:重新执行`),onClick:r.onReExecute},` ↻ `,8,Xt)])):s(`v-if`,!0),s(` 全屏查看 dialog `),x(r.CommonDialog,{modelValue:r.fullscreenOpen,"onUpdate:modelValue":t[0]||=e=>r.fullscreenOpen=e,title:r.$t(`@WORKBENCH:模型返回 - 全屏查看`),size:`fullscreen`,type:`flex`,"close-on-click-modal":!1,"custom-class":`wb-log-fullscreen-dialog`,onClosed:r.onFullscreenClosed},{default:G(()=>[Y(`div`,Zt,[r.hasOutput?(j(),k(r.MarkdownRenderer,{key:0,source:r.fullscreenSource,class:`wb-log-fullscreen__render`},null,8,[`source`])):(j(),o(`div`,Qt,E(r.$t(`@WORKBENCH:(暂无输出)`)),1))],512)]),_:1},8,[`modelValue`,`title`])],512),[[L,!r.isCollapsed]]),s(` /.wb-log-details__body `)],2)}var en=Q(Mt,[[`render`,$t],[`__scopeId`,`data-v-a4bb55c4`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/JobLogDetails.vue`]]);D(),F();var tn=50,nn=T({__name:`ExecutionLogManager`,setup(e,{expose:t}){t();function n(e){return e instanceof Error?e.message:String(e)}let i=J([]),o=J(0),s=ue({count:0,sizeMB:0,byStatus:{}}),c=J(!1),l=J(new Set),u=ue({q:``,status:``,page:1}),d=J({maxCount:500,maxSizeMB:256}),f=ue({maxCount:500,maxSizeMB:256}),p=J(!1),m=[{value:`pending`,label:Z(`@WORKBENCH:排队中`)},{value:`running`,label:Z(`@WORKBENCH:执行中`)},{value:`done`,label:Z(`@WORKBENCH:已完成`)},{value:`error`,label:Z(`@WORKBENCH:出错`)},{value:`cancelled`,label:Z(`@WORKBENCH:已取消`)}],h=a(()=>i.value.length>0&&i.value.every(e=>l.value.has(e.id))),g=a(()=>i.value.some(e=>l.value.has(e.id))&&!h.value);async function _(){c.value=!0;try{let e=new URLSearchParams;u.q&&e.set(`q`,u.q),u.status&&e.set(`status`,u.status),e.set(`limit`,String(tn)),e.set(`offset`,String((u.page-1)*tn));let t=await fetch(`/api/workbench/jobs/list?${e.toString()}`).then(e=>e.json());if(!t.success)throw Error(t.error||`list failed`);i.value=t.jobs,o.value=t.total,s.count=t.stats.count,s.sizeMB=t.stats.sizeMB,s.byStatus=t.stats.byStatus;let n=new Set(i.value.map(e=>e.id));for(let e of Array.from(l.value))n.has(e)||l.value.delete(e)}catch(e){z.error(Z(`@WORKBENCH:加载失败`)+`: `+n(e))}finally{c.value=!1}}async function v(){try{let e=await fetch(`/api/workbench/jobs/config`).then(e=>e.json());e.success&&(d.value=e.config,f.maxCount=e.config.maxCount,f.maxSizeMB=e.config.maxSizeMB)}catch{}}async function y(){p.value=!0;try{let e=await fetch(`/api/workbench/jobs/config`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({maxCount:f.maxCount,maxSizeMB:f.maxSizeMB})}).then(e=>e.json());if(!e.success)throw Error(e.error||`save failed`);d.value=e.config,z.success(Z(`@WORKBENCH:已保存策略`)),await _()}catch(e){z.error(Z(`@WORKBENCH:保存失败`)+`: `+n(e))}finally{p.value=!1}}function b(){u.page=1,_()}function x(){u.q=``,u.status=``,u.page=1,_()}function S(e,t){t?l.value.add(e):l.value.delete(e),l.value=new Set(l.value)}function C(e){if(e)for(let e of i.value)l.value.add(e.id);else for(let e of i.value)l.value.delete(e.id);l.value=new Set(l.value)}function w(e){z.info(Z(`@WORKBENCH:请到工作台主面板的对应任务上点击「重新执行」`))}async function T(e){try{await ge.confirm(Z(`@WORKBENCH:确定要删除所选的 {count} 条日志吗?`,{count:1}),Z(`@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`);l.value.delete(e),l.value=new Set(l.value),await _()}catch(e){z.error(Z(`@WORKBENCH:保存失败`)+`: `+n(e))}}async function E(){let e=Array.from(l.value);if(e.length!==0){try{await ge.confirm(Z(`@WORKBENCH:确定要删除所选的 {count} 条日志吗?`,{count:e.length}),Z(`@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`);z.success(Z(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e.length})),l.value=new Set,await _()}catch(e){z.error(Z(`@WORKBENCH:保存失败`)+`: `+n(e))}}}async function D(){let e=s.count;if(e!==0){try{await ge.confirm(Z(`@WORKBENCH:确定要清空所有 {count} 条执行日志吗?此操作不可恢复。`,{count:e}),Z(`@WORKBENCH:清空全部`),{type:`warning`,confirmButtonText:Z(`@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`);z.success(Z(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e})),l.value=new Set,await _()}catch(e){z.error(Z(`@WORKBENCH:保存失败`)+`: `+n(e))}}}function O(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`}he(()=>{_(),v()});let k={errMsg:n,list:i,total:o,stats:s,loading:c,selectedIds:l,pageSize:tn,filter:u,config:d,configDraft:f,configSaving:p,STATUS_OPTIONS:m,isAllOnPageSelected:h,isSomeOnPageSelected:g,load:_,loadConfig:v,saveConfig:y,onFilterChange:b,resetFilter:x,toggleSelect:S,toggleSelectAllOnPage:C,onReExecuteInLog:w,deleteOne:T,batchDelete:E,clearAll:D,formatDuration:O,get Document(){return ce},get Refresh(){return r},get $t(){return Z},get statusLabel(){return Tt},get statusColor(){return Et},JobLogDetails:en};return Object.defineProperty(k,"__isScriptSetup",{enumerable:!1,value:!0}),k}});D(),S(),H();var rn={class:`exec-logs`},an={class:`exec-logs__head`},on={class:`exec-logs__title-block`},sn={class:`exec-logs__stats`},cn={class:`exec-logs__head-actions`},ln={class:`exec-logs__config`},un={class:`exec-logs__config-label`},dn={class:`exec-logs__config-field`},fn={class:`exec-logs__config-name`},pn={class:`exec-logs__config-field`},mn={class:`exec-logs__config-name`},hn={class:`exec-logs__filter`},gn={key:0,class:`exec-logs__batch-meta`},_n={key:0,class:`exec-logs__batch`},vn={class:`exec-logs__list`},yn={key:0,class:`exec-logs__empty`},bn={class:`exec-logs__empty-art`,"aria-hidden":`true`},xn={class:`exec-logs__empty-title`},Sn={class:`exec-logs__empty-hint`},Cn={class:`exec-card__head`},wn=[`title`],Tn={class:`exec-card__meta`},En={key:0,class:`exec-card__task`},Dn={key:1,class:`exec-card__time`},On={key:2,class:`exec-card__exit`},kn=[`title`,`onClick`],An={key:0,class:`exec-card__error`},jn={key:1,class:`exec-logs__pager`};function Mn(e,t,n,r,i,a){let l=v,u=we,d=ne,f=w,p=c,_=b,y=h,S=ye,C=ae;return j(),o(`div`,rn,[s(` 头部:统计 + 刷新 + 清空。
21
+ 标题已由外层 el-dialog 提供,这里不再重复 h2。 `),Y(`header`,an,[Y(`div`,on,[Y(`span`,sn,E(r.$t(`@WORKBENCH:共 {count} 条,占 {size} MB`,{count:r.stats.count,size:r.stats.sizeMB})),1)]),Y(`div`,cn,[x(l,{icon:r.Refresh,size:`small`,loading:r.loading,onClick:r.load},{default:G(()=>[V(E(r.$t(`@WORKBENCH:刷新`)),1)]),_:1},8,[`icon`,`loading`]),x(l,{type:`danger`,plain:``,size:`small`,disabled:r.stats.count===0,onClick:r.clearAll},{default:G(()=>[V(E(r.$t(`@WORKBENCH:清空全部`)),1)]),_:1},8,[`disabled`])])]),s(` 保留策略 `),Y(`div`,ln,[Y(`span`,un,E(r.$t(`@WORKBENCH:保存策略`)),1),Y(`span`,dn,[Y(`span`,fn,E(r.$t(`@WORKBENCH:最大条数`)),1),x(u,{modelValue:r.configDraft.maxCount,"onUpdate:modelValue":t[0]||=e=>r.configDraft.maxCount=e,min:0,max:1e4,step:50,size:`small`,"controls-position":`right`,style:{width:`130px`}},null,8,[`modelValue`])]),Y(`span`,pn,[Y(`span`,mn,E(r.$t(`@WORKBENCH:最大体积 (MB)`)),1),x(u,{modelValue:r.configDraft.maxSizeMB,"onUpdate:modelValue":t[1]||=e=>r.configDraft.maxSizeMB=e,min:0,max:10240,step:32,size:`small`,"controls-position":`right`,style:{width:`140px`}},null,8,[`modelValue`])]),x(l,{type:`primary`,size:`small`,loading:r.configSaving,onClick:r.saveConfig},{default:G(()=>[V(E(r.$t(`@WORKBENCH:保存策略`)),1)]),_:1},8,[`loading`])]),s(` 过滤栏 `),Y(`div`,hn,[x(d,{modelValue:r.filter.q,"onUpdate:modelValue":t[2]||=e=>r.filter.q=e,placeholder:r.$t(`@WORKBENCH:搜索标题 / 任务`),clearable:``,size:`small`,style:{width:`240px`},onKeyup:P(r.onFilterChange,[`enter`]),onClear:r.onFilterChange},null,8,[`modelValue`,`placeholder`]),x(p,{modelValue:r.filter.status,"onUpdate:modelValue":t[3]||=e=>r.filter.status=e,placeholder:r.$t(`@WORKBENCH:全部状态`),clearable:``,size:`small`,style:{width:`130px`},onChange:r.onFilterChange},{default:G(()=>[(j(),o(X,null,M(r.STATUS_OPTIONS,e=>x(f,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`])),64))]),_:1},8,[`modelValue`,`placeholder`]),x(l,{size:`small`,onClick:r.resetFilter},{default:G(()=>[V(E(r.$t(`@WORKBENCH:重置`)),1)]),_:1}),t[5]||=Y(`span`,{class:`exec-logs__filter-spacer`},null,-1),r.selectedIds.size>0?(j(),o(`span`,gn,E(r.$t(`@WORKBENCH:已选择 {count} 项`,{count:r.selectedIds.size})),1)):s(`v-if`,!0)]),s(` 批量操作条 `),r.selectedIds.size>0?(j(),o(`div`,_n,[x(_,{"model-value":r.isAllOnPageSelected,indeterminate:r.isSomeOnPageSelected,onChange:r.toggleSelectAllOnPage},{default:G(()=>[V(E(r.isAllOnPageSelected?r.$t(`@WORKBENCH:取消全选`):r.$t(`@WORKBENCH:全选`)),1)]),_:1},8,[`model-value`,`indeterminate`]),x(l,{type:`danger`,size:`small`,onClick:r.batchDelete},{default:G(()=>[V(E(r.$t(`@WORKBENCH:批量删除`)),1)]),_:1})])):s(`v-if`,!0),s(` 列表 `),K((j(),o(`div`,vn,[!r.loading&&r.list.length===0?(j(),o(`div`,yn,[Y(`div`,bn,[x(y,null,{default:G(()=>[x(r.Document)]),_:1})]),Y(`div`,xn,E(r.$t(`@WORKBENCH:暂无执行日志`)),1),Y(`div`,Sn,E(r.$t(`@WORKBENCH:点击「执行任务」开始一次执行,日志会出现在这里。`)),1)])):s(`v-if`,!0),(j(!0),o(X,null,M(r.list,e=>(j(),o(`article`,{key:e.id,class:g([`exec-card`,{"is-selected":r.selectedIds.has(e.id)}])},[Y(`header`,Cn,[x(_,{"model-value":r.selectedIds.has(e.id),onChange:t=>r.toggleSelect(e.id,t)},null,8,[`model-value`,`onChange`]),Y(`span`,{class:`exec-card__status`,style:m({color:r.statusColor(e.status),borderColor:r.statusColor(e.status)})},E(r.statusLabel(e.status)),5),Y(`span`,{class:`exec-card__title`,title:e.title||r.$t(`@WORKBENCH:无标题`)},E(e.title||r.$t(`@WORKBENCH:无标题`)),9,wn),t[6]||=Y(`span`,{class:`exec-card__spacer`},null,-1),Y(`span`,Tn,[e.taskTitle?(j(),o(`span`,En,`📁 `+E(e.taskTitle),1)):s(`v-if`,!0),e.startedAt?(j(),o(`span`,Dn,`⏱ `+E(r.formatDuration(e.startedAt,e.endedAt)),1)):s(`v-if`,!0),e.exitCode===null?s(`v-if`,!0):(j(),o(`span`,On,`exit `+E(e.exitCode),1))]),Y(`button`,{type:`button`,class:`exec-card__del`,title:r.$t(`@WORKBENCH:删除`),onClick:t=>r.deleteOne(e.id)},`×`,8,kn)]),e.error?(j(),o(`p`,An,`⚠ `+E(e.error),1)):s(`v-if`,!0),x(r.JobLogDetails,{job:e,onReExecute:r.onReExecuteInLog},null,8,[`job`])],2))),128))])),[[C,r.loading]]),s(` 分页 `),r.total>r.pageSize?(j(),o(`footer`,jn,[x(S,{"current-page":r.filter.page,"onUpdate:currentPage":t[4]||=e=>r.filter.page=e,"page-size":r.pageSize,total:r.total,layout:`prev, pager, next, total`,background:``,small:``,onCurrentChange:r.load},null,8,[`current-page`,`total`])])):s(`v-if`,!0)])}var Nn=Q(nn,[[`render`,Mn],[`__scopeId`,`data-v-d3ebe953`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/ExecutionLogManager.vue`]]);F();var Pn=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`]),Fn=`.png,.jpg,.jpeg,.gif,.webp,.bmp,.svg,.pdf,.txt,.md,.csv,.json,.log`,In=20971520,Ln=3840,Rn=new Set([`image/png`,`image/jpeg`,`image/jpg`,`image/webp`,`image/bmp`]);function zn(e){if(e.size<=3670016)return!1;let t=String(e.type||``).toLowerCase();return t?Rn.has(t):/\.(png|jpe?g|webp|bmp)$/i.test(e.name)}function Bn(e,t){return`${String(e||`attachment`).replace(/\.[^./\\]+$/,``)}.${t}`}async function Vn(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 Hn(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 Un(e){let t=await Vn(e);if(!t)return null;try{let n=[{edge:Ln,quality:.95},{edge:Ln,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 Hn(o,`image/webp`,e.quality)||await Hn(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 Wn(){let e=J({}),t=J(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(!Pn.has(n.type)&&!n.name.match(/\.(png|jpg|jpeg|gif|webp|bmp|svg|pdf|txt|md|markdown|csv|json|log)$/i)){z.error(`${Z(`@WORKBENCH:不支持的文件类型`)}(${n.name})`);return}if(a(t).find(e=>e.originalName===n.name&&e.size===n.size)){z.info(`${n.name} ${Z(`@WORKBENCH:已存在,已复用`)}`);return}let c=i(t);e.value[c]=!0;try{let e=n;if(zn(n)){let t=await Un(n);t&&(e=r(t.blob,Bn(n.name,t.ext)),z.info(Z(`@WORKBENCH:图片过大,已压缩后上传:{from} → {to}`,{from:g(n.size),to:g(e.size)})))}if(e.size>20971520){z.error(`「${n.name}」${Z(`@WORKBENCH:超过 {size} 限制`,{size:g(In)})}`);return}let i=await fetch(s(t),{method:`POST`,headers:{"Content-Type":`application/octet-stream`,"X-Original-Name":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),z.success(`${Z(`@WORKBENCH:已添加:`)}${e.name}`)}else z.error(i.error||Z(`@WORKBENCH:上传失败`))}catch(e){z.error(Z(`@WORKBENCH:上传失败`)+`:`+(e&&e.message||e))}finally{e.value[c]=!1}}async function f(e,t){try{await ge.confirm(Z(`@WORKBENCH:删除附件「{name}」?`,{name:t.originalName}),Z(`@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)),z.success(Z(`@WORKBENCH:已删除`))):z.error(n.error||Z(`@WORKBENCH:删除失败`))}function p(e){let t=document.createElement(`input`);t.type=`file`,t.accept=Fn,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}}D();var Gn=`__simple`,Kn=65536;function qn(e,t){function n(t){if(!t)return[];let n=`${t.id}${Gn}`;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:a(()=>{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();t.prompt&&r.push({id:`${t.id}-u`,role:`user`,content:t.prompt,status:`done`,createdAt:a});let o=t.output||``,s=t.thinking||``,c=o.length>Kn?`\u2026(前文已截断)\n${o.slice(-65536)}`:o,l=s.length>Kn?`\u2026(前文已截断)\n${s.slice(-65536)}`:s,u=!!c,d=!!l,f=At(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:c,reasoning:d?l:void 0,reasoningStatus:d?!i&&u||u?`done`:h===`streaming`?`streaming`:`done`:void 0,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:Gn,MAX_LOG_DISPLAY_SIMPLE:Kn}}function Jn(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&&i.promptId===n.value.promptId&&(i.simpleOverride||``)===(n.value.simpleOverride||``)?!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?z.success(t.message||Z(`@WORKBENCH:已加入执行队列`)):z.error(t.error||Z(`@WORKBENCH:执行失败`))}async function s(t,n){let r=e.value.filter(e=>e.taskId===t.id).slice(-1)[0];if(!r){z.error(Z(`@WORKBENCH:没有可续接的会话`));return}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)}));a.success?z.success(a.message||Z(`@WORKBENCH:已加入续接队列`)):z.error(a.error||Z(`@WORKBENCH:续接失败`))}async function c(e,t){let n=t.text.trim();if(n){for(let n of t.files)await r.uploadAttachment({kind:`task`,task:e},n.file);await s(e,n)}}async function l(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){z.error(Z(`@WORKBENCH:找不到对应任务,无法重新执行`));return}await o(n)}async function u(e){try{await ge.confirm(Z(`@WORKBENCH:确认停止执行?已输出的内容会保留。`),Z(`@WORKBENCH:停止执行`),{confirmButtonText:Z(`@WORKBENCH:停止`),cancelButtonText:Z(`@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?z.success(Z(`@WORKBENCH:已发送停止信号`)):z.error(t.error||Z(`@WORKBENCH:停止失败`))}async function d(){if(!n.value)return;let t=n.value,i=e.value.filter(e=>e.taskId===t.id),a=i.filter(e=>e.status===`running`||e.status===`pending`).length,o=i.length===0?Z(`@WORKBENCH:当前任务还没有执行内容,确认仍要清空?`):Z(`@WORKBENCH:将清空 {m} 条执行记录,任务描述/附件保留。`,{m:i.length});try{await ge.confirm(o,Z(`@WORKBENCH:清空执行内容`),{confirmButtonText:Z(`@WORKBENCH:清空`),cancelButtonText:Z(`@WORKBENCH:取消`),type:`warning`})}catch{return}if(a>0){z.warning(Z(`@WORKBENCH:任务正在执行,请先停止`));return}let s=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)}));s?.success?(e.value=e.value.filter(e=>e.taskId!==t.id),r.syncRunningCount(),z.success(s.message||Z(`@WORKBENCH:已清空执行内容`))):z.error(s?.error||Z(`@WORKBENCH:清空失败`))}return{runTask:o,continueChat:s,onContinueSendFromChat:c,onReExecuteJob:l,cancelJob:u,clearExecutionForSelectedTask:d}}D();function Yn(){let e=Fe(),t=Ie(),n=a({get:()=>e.resolvedTaskExecutor,set:t=>{Me(t)&&e.setLastTaskExecutor(t)}}),r=a(()=>({claude:t.claudeAvailable,opencode:t.opencodeAvailable,codex:t.codexAvailable})),i=a(()=>Ne.some(e=>r.value[e.id])),o=a(()=>r.value[n.value]?n.value:Object.keys(r.value).find(e=>r.value[e])??n.value);function s(e){r.value[e]&&(n.value=e)}function c(e){return t.executorModelText(e)}function l(e){return[c(e),t.executorModelDetail(e)].filter(Boolean).join(` · `)}return{selected:n,active:o,availability:r,hasAnyExecutor:i,choose:s,executorModelText:c,executorModelTitle:l}}F();function Xn(){let e=J([]),t=J([]),n=J([]),r=J({path:``,name:``}),i=Ge();function a(){i.setRunning(n.value.filter(e=>e.status===`running`).length)}function o(e,r){if(e===`hello`){n.value=r.jobs||[],a();return}if(e===`job:update`){let e=r,t=n.value.findIndex(t=>t.id===e.id);t>=0?n.value[t]=e:n.value.push(e),a();return}if(e===`job:thinking-delta`||e===`job:output-delta`){let t=e===`job:thinking-delta`?`thinking`:`output`,i=r?.delta||``;if(!i)return;let a=n.value.findIndex(e=>e.id===r.id);if(a<0)return;let o=n.value[a][t]||``;n.value[a][t]=o+i;return}if(e===`job:toolcalls`){let e=Array.isArray(r?.updates)?r.updates:[];if(!e.length)return;let t=n.value.findIndex(e=>e.id===r.id);if(t<0)return;let i=n.value[t];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(e===`task:update`){let e=t.value.findIndex(e=>e.id===r.id);e>=0&&(t.value[e]=r)}if(e===`tasks:reordered`){if(Array.isArray(r?.tasks)){if(r.tasks.length<t.value.length){console.warn(`[SSE tasks:reordered] 数据丢失风险:当前 ${t.value.length} 个任务,服务端只返回 ${r.tasks.length} 个,拒绝覆盖`);return}t.value=r.tasks}return}e===`task:error`&&z.error(r.error||Z(`@WORKBENCH:执行出错`))}let s=null;function c(){s&&=(s.close(),null),s=new EventSource(`/api/workbench/events`),s.onmessage=e=>{try{let t=JSON.parse(e.data);o(t.event,t.payload)}catch{}},s.onerror=()=>{s&&=(s.close(),null),setTimeout(c,3e3)}}function l(){s&&=(s.close(),null)}async function u(){let t=await fetch(`/api/workbench/prompts`).then(e=>e.json()).catch(()=>({prompts:[]}));e.value=t.prompts||[]}async function d(e){let n=await fetch(`/api/workbench/tasks`).then(e=>e.json()).catch(()=>({tasks:[]}));t.value=n.tasks||[],e?.()}async function f(){let e=await fetch(`/api/workbench/current-project`).then(e=>e.json()).catch(()=>({}));e&&typeof e.projectPath==`string`&&(r.value={path:e.projectPath,name:e.projectName||``})}async function p(){let e=await fetch(`/api/workbench/jobs`).then(e=>e.json()).catch(()=>({jobs:[]}));n.value=e.jobs||[],a()}async function m(e){try{let t=await fetch(`/api/workbench/jobs/by-task/${encodeURIComponent(e)}`,{method:`DELETE`}).then(e=>e.json());return t?.success?(n.value=n.value.filter(t=>t.taskId!==e),a(),t.removed||0):(console.warn(`[clearJobsByTask] failed:`,t?.error),0)}catch(e){return console.warn(`[clearJobsByTask] error:`,e),0}}async function h(e){let t={title:``,desc:``,promptId:null,simpleOverride:``};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:(z.error(e.error||Z(`@WORKBENCH:保存失败`)),null)}catch{return z.error(Z(`@WORKBENCH:保存失败`)),null}}return{prompts:e,tasks:t,jobs:n,currentProject:r,syncRunningCount:a,applyJobEvent:o,connectSSE:c,disconnectSSE:l,loadPrompts:u,loadTasks:d,loadCurrentProject:f,loadJobs:p,clearJobsByTask:m,createTask:h}}F(),D();var Zn=`__no_project__`,Qn=`wb.collapsedGroupPaths.v1`,$n=`wb.seenGroupPaths.v1`;function er(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 tr(e,t){try{localStorage.setItem(e,JSON.stringify(Array.from(t)))}catch{}}function nr(e,t){let n=J(er(Qn)),r=J(er($n));B(n,e=>tr(Qn,e),{deep:!1}),B(r,e=>tr($n,e),{deep:!1});function i(e){return n.value.has(e)}function o(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 s=a(()=>{let r=e.value,i=new Map;for(let e of r){let t=$(e.projectPath)||Zn;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===Zn?1:t===Zn?-1:e.localeCompare(t));return{groups:o.map(e=>({path:e,label:e===Zn?Z(`@WORKBENCH:未关联项目`):e,tasks:i.get(e)})),hasMultiple:o.length>1||o.length===1&&n.value.has(o[0])}});function c(e){if(!e||e===Zn)return e;let t=e.split(/[\\/]/).filter(Boolean);return t.length<=1?e:t.slice(-2).join(`/`)}let l=a(()=>`${$(t.value.path)}|${s.value.groups.map(e=>e.path).join(`
22
+ `)}`);return B(l,()=>{let e=$(t.value.path);if(!e)return;let i=new Set(n.value),a=new Set(r.value),o=!1;for(let t of s.value.groups)a.has(t.path)||(a.add(t.path),t.path!==e&&(i.add(t.path),o=!0));o&&(n.value=i),r.value=a},{immediate:!0}),{groupedTasksList:s,isGroupCollapsed:i,toggleGroupCollapsed:o,shortProjectLabel:c}}D(),F();var rr=5,ir=T({__name:`WorkbenchSidebar`,props:{tasks:{type:Array,required:!0},prompts:{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`,`open-create-prompt`,`open-edit-prompt`,`delete-prompt`,`reorder-tasks`],setup(e,{expose:t,emit:r}){t();let i=e,o=r,s=a(()=>i.currentProject),c=a(()=>i.tasks),{groupedTasksList:l,isGroupCollapsed:u,toggleGroupCollapsed:d,shortProjectLabel:f}=nr(c,s),p=a(()=>$(i.currentProject.path));function m(e){return!!e.projectPath&&$(e.projectPath)!==p.value}let h=a(()=>{let e=p.value;return i.prompts.filter(t=>!t.projectPath||$(t.projectPath)===e)});function g(e){return(e.title||``).trim()||(e.desc||``).replace(/\s+/g,` `).trim()}function _(e){let t=g(e),n=Z(`@WORKBENCH:拖动排序提示`);return t?`${t} · ${n}`:n}function v(e){return i.isTaskRunning(e)}let b=J(null),x=J(null),S=J(null),C=J(null),w=J(null),T=null;function E(){b.value=null,x.value=null,S.value=null,C.value=null,w.value=null,T=null}function D(e,t,n,r){e.button===0&&(T={pointerY:e.clientY,li:r,taskId:t.id,groupPath:n},window.addEventListener(`mousemove`,O),window.addEventListener(`mouseup`,k,{once:!0}))}function O(e){if(!T)return;if(b.value===null){if(Math.abs(e.clientY-T.pointerY)<rr)return;b.value=T.taskId,x.value=T.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){S.value=null,C.value=null,w.value=null;return}let r=n.getAttribute(`data-task-id`),i=n.getAttribute(`data-group-path`);if(!r||!i)return;if(i!==x.value){S.value=null,C.value=null,w.value=null;return}let a=n.getBoundingClientRect(),o=a.top+a.height/2;S.value=r,C.value=i,w.value=e.clientY<o?`before`:`after`}function k(e){if(window.removeEventListener(`mousemove`,O),document.body.style.userSelect=``,!T){E();return}let t=T.groupPath,n=T.taskId,r=S.value,i=w.value,a=C.value;if(E(),!r||!i||a!==t)return;let s=l.value.groups.find(e=>e.path===t);if(!s)return;let c=s.tasks.map(e=>e.id),u=c.indexOf(n);if(u<0)return;c.splice(u,1);let d=c.indexOf(r)+ +(i===`after`);c.splice(d,0,n),o(`reorder-tasks`,{groupPath:t,orderedIds:c})}let ee={props:i,emit:o,currentProjectRef:s,tasksRef:c,groupedTasksList:l,isGroupCollapsed:u,toggleGroupCollapsed:d,shortProjectLabel:f,currentProjectKey:p,isOtherProject:m,availablePrompts:h,taskDisplayName:g,taskTooltip:_,taskIsRunning:v,draggingTaskId:b,dragStartGroupPath:x,dragOverTaskId:S,dragOverGroupPath:C,dragPosition:w,get dragStart(){return T},set dragStart(e){T=e},DRAG_THRESHOLD_PX:rr,resetDragState:E,onTaskMouseDown:D,onWindowMouseMove:O,onWindowMouseUp:k,get $t(){return Z},get Plus(){return y},get Close(){return fe},get DocumentAdd(){return U},get Memo(){return n},get Folder(){return se},get ArrowDown(){return me},get ArrowRight(){return re},get CopyDocument(){return pe}};return Object.defineProperty(ee,"__isScriptSetup",{enumerable:!1,value:!0}),ee}});D(),S(),H();var ar={class:`wb-sidebar`},or={class:`wb-section`},sr=[`disabled`],cr=[`aria-expanded`,`title`,`onClick`,`onKeydown`],lr=[`title`],ur={class:`wb-pill wb-task-group__count`},dr=[`data-task-id`,`data-group-path`,`title`,`aria-pressed`,`onClick`,`onKeydown`,`onMousedown`],fr={class:`wb-task-item__body`},pr=[`title`],mr=[`title`],hr={class:`wb-task-item__action-group`},gr=[`title`,`aria-label`,`onClick`],_r=[`onClick`,`title`,`aria-label`],vr={key:0,class:`wb-empty wb-empty--rich`},yr={class:`wb-empty__art`,"aria-hidden":`true`},br={class:`wb-empty__title`},xr={class:`wb-empty__hint`},Sr={class:`wb-empty__cta`},Cr={class:`wb-section`},wr={class:`wb-section__head`},Tr={class:`wb-section__tag wb-section__tag--accent`},Er={class:`wb-section__title`},Dr={class:`wb-pill wb-section__count`},Or=[`title`,`aria-label`],kr={class:`wb-prompt-list`},Ar={class:`wb-prompt-item__icon`},jr=[`onClick`,`title`],Mr=[`title`],Nr=[`title`],Pr=[`onClick`,`title`,`aria-label`],Fr={key:0,class:`wb-empty wb-empty--compact`};function Ir(e,t,n,r,i,a){let c=h,l=v;return j(),o(`aside`,ar,[Y(`section`,or,[s(` 任务分组 header 已去掉:"任务"/"任务列表"/计数 三件套冗余,下方任务项本身已能自我说明。
23
+ 提示词分组保留 header(含 + 新建按钮 + 计数),信息密度不一对齐,后续按需统一。 `),Y(`button`,{class:`wb-new-btn`,disabled:n.creatingTask,onClick:t[0]||=e=>r.emit(`create-task`)},[x(c,{class:`wb-new-btn__icon`},{default:G(()=>[x(r.Plus)]),_:1}),Y(`span`,null,E(r.$t(`@WORKBENCH:新建任务`)),1),t[5]||=Y(`span`,{class:`wb-new-btn__shortcut`},`N`,-1)],8,sr),Y(`ul`,{class:g([`wb-task-list`,{"is-grouped":r.groupedTasksList.hasMultiple}])},[(j(!0),o(X,null,M(r.groupedTasksList.groups,e=>(j(),o(X,{key:e.path},[r.groupedTasksList.hasMultiple?(j(),o(`li`,{key:0,class:g([`wb-task-group__head`,{"is-current":e.path===r.currentProjectKey,"is-collapsed":r.isGroupCollapsed(e.path)}]),role:`button`,tabindex:`0`,"aria-expanded":!r.isGroupCollapsed(e.path),title:r.isGroupCollapsed(e.path)?r.$t(`@WORKBENCH:展开`):r.$t(`@WORKBENCH:收起`),onClick:t=>r.toggleGroupCollapsed(e.path),onKeydown:[P(q(t=>r.toggleGroupCollapsed(e.path),[`prevent`]),[`enter`]),P(q(t=>r.toggleGroupCollapsed(e.path),[`prevent`]),[`space`])]},[x(c,{class:`wb-task-group__caret`},{default:G(()=>[(j(),k(I(r.isGroupCollapsed(e.path)?r.ArrowRight:r.ArrowDown)))]),_:2},1024),x(c,{class:`wb-task-group__icon`},{default:G(()=>[x(r.Folder)]),_:1}),Y(`span`,{class:`wb-task-group__name`,title:e.path===r.currentProjectKey?n.currentProject.path:e.label},E(e.path===r.currentProjectKey?n.currentProject.name:r.shortProjectLabel(e.label)),9,lr),Y(`span`,ur,E(e.tasks.length),1)],42,cr)):s(`v-if`,!0),r.isGroupCollapsed(e.path)?s(`v-if`,!0):(j(!0),o(X,{key:1},M(e.tasks,i=>(j(),o(`li`,{key:i.id,class:g([`wb-task-item`,{active:i.id===n.selectedTaskId,"is-other-project":r.isOtherProject(i),"is-running":r.taskIsRunning(i),"is-dragging":r.draggingTaskId===i.id,"is-drop-before":r.dragOverTaskId===i.id&&r.dragPosition===`before`,"is-drop-after":r.dragOverTaskId===i.id&&r.dragPosition===`after`}]),"data-task-id":i.id,"data-group-path":e.path,title:r.taskTooltip(i),role:`button`,tabindex:`0`,"aria-pressed":i.id===n.selectedTaskId,onClick:e=>r.emit(`select-task`,i),onKeydown:[P(q(e=>r.emit(`select-task`,i),[`prevent`]),[`enter`]),P(q(e=>r.emit(`select-task`,i),[`prevent`]),[`space`])],onMousedown:t=>r.onTaskMouseDown(t,i,e.path,t.currentTarget)},[s(` 单行展示:只显示标题;没写标题用任务描述压平后顶上(CSS ellipsis 截断)。
24
+ 子任务数 / 附件数 等 meta 行已移除,降噪 `),Y(`div`,fr,[Y(`div`,{class:`wb-task-item__title`,title:r.taskDisplayName(i)},E(r.taskDisplayName(i)),9,pr)]),r.taskIsRunning(i)?(j(),o(`span`,{key:0,class:`wb-task-item__running-dot`,title:r.$t(`@WORKBENCH:执行中`),"aria-hidden":`true`},null,8,mr)):s(`v-if`,!0),Y(`div`,hr,[Y(`button`,{class:`wb-task-item__copy`,title:r.$t(`@WORKBENCH:复制任务`),"aria-label":r.$t(`@WORKBENCH:复制任务`),onClick:q(e=>r.emit(`copy-task`,i),[`stop`]),onKeydown:t[1]||=q(()=>{},[`stop`])},[x(c,null,{default:G(()=>[x(r.CopyDocument)]),_:1})],40,gr),s(` 执行中不允许删除:避免误杀正在跑的实例(jobs 还在内存里,
25
+ 任务从 tasks.json 消失后,runSingleSubtask 读不到 task
26
+ 会留一堆孤儿 job)。后端 DELETE 路由也加了同样的 live-job 守卫兜底 `),r.taskIsRunning(i)?s(`v-if`,!0):(j(),o(`button`,{key:0,class:`wb-task-item__del`,onClick:q(e=>r.emit(`delete-task`,i),[`stop`]),onKeydown:t[2]||=q(()=>{},[`stop`]),title:r.$t(`@WORKBENCH:删除`),"aria-label":r.$t(`@WORKBENCH:删除`)},[x(c,null,{default:G(()=>[x(r.Close)]),_:1})],40,_r))])],42,dr))),128))],64))),128)),n.tasks.length===0?(j(),o(`li`,vr,[Y(`div`,yr,[x(c,null,{default:G(()=>[x(r.DocumentAdd)]),_:1})]),Y(`div`,br,E(r.$t(`@WORKBENCH:暂无任务`)),1),Y(`div`,xr,E(r.$t(`@WORKBENCH:点击上方按钮新建`)),1),Y(`div`,Sr,[x(l,{type:`primary`,size:`small`,icon:r.Plus,loading:n.creatingTask,onClick:t[3]||=e=>r.emit(`create-task`)},{default:G(()=>[V(E(r.$t(`@WORKBENCH:新建任务`)),1)]),_:1},8,[`icon`,`loading`])])])):s(`v-if`,!0)],2)]),Y(`section`,Cr,[Y(`header`,wr,[Y(`span`,Tr,E(r.$t(`@WORKBENCH:提示`)),1),Y(`h3`,Er,E(r.$t(`@WORKBENCH:预置提示词`)),1),Y(`span`,Dr,E(r.availablePrompts.length),1),Y(`button`,{class:`wb-section__action`,onClick:t[4]||=e=>r.emit(`open-create-prompt`),title:r.$t(`@WORKBENCH:新建提示词`),"aria-label":r.$t(`@WORKBENCH:新建提示词`)},[x(c,null,{default:G(()=>[x(r.Plus)]),_:1})],8,Or)]),Y(`ul`,kr,[(j(!0),o(X,null,M(r.availablePrompts,e=>(j(),o(`li`,{key:e.id,class:`wb-prompt-item`},[Y(`div`,Ar,[x(c,null,{default:G(()=>[x(r.Memo)]),_:1})]),Y(`button`,{type:`button`,class:`wb-prompt-item__name`,onClick:t=>r.emit(`open-edit-prompt`,e),title:e.content},E(e.name),9,jr),e.projectPath?(j(),o(`span`,{key:1,class:`wb-prompt-item__tag wb-prompt-item__tag--project`,title:e.projectPath},E(r.shortProjectLabel(e.projectPath)),9,Nr)):(j(),o(`span`,{key:0,class:`wb-prompt-item__tag`,title:r.$t(`@WORKBENCH:全局(所有项目可用)`)},E(r.$t(`@WORKBENCH:全局(所有项目可用)`)),9,Mr)),Y(`button`,{class:`wb-prompt-item__del`,onClick:t=>r.emit(`delete-prompt`,e),title:r.$t(`@WORKBENCH:删除`),"aria-label":r.$t(`@WORKBENCH:删除`)},[x(c,null,{default:G(()=>[x(r.Close)]),_:1})],8,Pr)]))),128)),r.availablePrompts.length===0?(j(),o(`li`,Fr,E(r.$t(`@WORKBENCH:暂无提示词`)),1)):s(`v-if`,!0)])])])}var Lr=Q(ir,[[`render`,Ir],[`__scopeId`,`data-v-458e9455`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchSidebar.vue`]]);F();function Rr(){let e=J([]),t=J([]),n=J(``),r=J(!1),i=J(!1);async function a(a=!1){a||(r.value=!0);try{let r=await fetch(`/api/workbench/projects`,{cache:`no-store`}).then(e=>e.json());return r?.success?(e.value=Array.isArray(r.projects)?r.projects:[],t.value=Array.isArray(r.tasks)?r.tasks:[],n.value=r.currentProjectPath||``,i.value=!0,!0):(a||z.error(r?.error||Z(`@WORKBENCH:读取项目列表失败`)),!1)}catch(e){return a||z.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),!1}finally{r.value=!1}}return{projects:e,boardTasks:t,currentProjectPath:n,loading:r,loaded:i,loadProjects:a}}var zr=[0,5,10,15,30,60].map(e=>e*60*1e3),Br=6e5;function Vr(e){let t=Number(e);return zr.includes(t)?t:Br}function Hr(e){return e?e>=36e5?`@WORKBENCH:每 {n} 小时报告`:`@WORKBENCH:每 {n} 分钟报告`:`@WORKBENCH:关闭自动报告`}function Ur(e){return e?{n:Math.round(e>=36e5?e/36e5:e/6e4)}:{}}function Wr(e){switch(e){case`NO_MODEL`:return`@WORKBENCH:没有可用的 AI 模型,只记录了任务事实`;case`LLM_TIMEOUT`:return`@WORKBENCH:生成超时,只记录了任务事实`;case`LLM_FAILED`:return`@WORKBENCH:生成失败,只记录了任务事实`;default:return`@WORKBENCH:生成失败,只记录了任务事实`}}F();var Gr=1e5;function Kr(){let e=J(!0),t=J([]),n=J([]),r=J(Gr),i=J([]),a=J(null),o=J(!1),s=J(!1),c=J(!1),l=J(``),u=J({}),d=J([]),f=J(!1),p=J(!1),m=J(Br);async function h(s=!1){try{let c=await fetch(`/api/workbench/orchestrator`,{cache:`no-store`}).then(e=>e.json());return c?.success?(e.value=c.active!==!1,Number.isInteger(c.maxInstructionChars)&&c.maxInstructionChars>0&&(r.value=c.maxInstructionChars),t.value=Array.isArray(c.instructions)?c.instructions:[],n.value=Array.isArray(c.activity)?c.activity:[],i.value=Array.isArray(c.running)?c.running:[],a.value=c.updatedAt||null,l.value=typeof c.defaultPrompt==`string`?c.defaultPrompt:``,u.value=c.projectPrompts&&typeof c.projectPrompts==`object`?c.projectPrompts:{},m.value=Vr(c.reportIntervalMs),o.value=!0,!0):(s||z.error(c?.error||Z(`@WORKBENCH:读取编排状态失败`)),!1)}catch(e){return s||z.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),!1}}async function g(e=!1){if(f.value)return!1;f.value=!0;try{let t=await fetch(`/api/workbench/orchestrator/reports`,{cache:`no-store`}).then(e=>e.json());return t?.success?(d.value=Array.isArray(t.reports)?t.reports:[],!0):(e||z.error(t?.error||Z(`@WORKBENCH:读取进度报告失败`)),!1)}catch(t){return e||z.error(Z(`@WORKBENCH:网络错误: `)+(t?.message||t)),!1}finally{f.value=!1}}async function _(){if(p.value)return null;p.value=!0;try{let e=String(Fe().locale||``).startsWith(`en`)?`en`:`zh`,t=await fetch(`/api/workbench/orchestrator/report`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({locale:e})}).then(e=>e.json());return t?.success?t.report?(d.value=[t.report,...d.value].slice(0,20),t.report):(z.info(Z(`@WORKBENCH:当前没有正在执行的任务,没有可汇报的进度`)),null):(z.error(t?.error||Z(`@WORKBENCH:生成进度报告失败`)),null)}catch(e){return z.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),null}finally{p.value=!1}}async function v(e){try{let t=await fetch(`/api/workbench/orchestrator/report-interval`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({intervalMs:e})}).then(e=>e.json());return t?.success?(m.value=Vr(t.reportIntervalMs),!0):(z.error(t?.error||Z(`@WORKBENCH:保存失败`)),!1)}catch(e){return z.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),!1}}async function y(e){try{let t=await fetch(`/api/workbench/orchestrator/default-prompt`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({prompt:e})}).then(e=>e.json());return t?.success?(l.value=typeof t.defaultPrompt==`string`?t.defaultPrompt:``,z.success(Z(`@WORKBENCH:已保存全局默认提示词`)),!0):(z.error(t?.error||Z(`@WORKBENCH:保存失败`)),!1)}catch(e){return z.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),!1}}async function b(e,t){try{let n=await fetch(`/api/workbench/orchestrator/project-prompt`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({projectPath:e,prompt:t})}).then(e=>e.json());return n?.success?(u.value=n.projectPrompts&&typeof n.projectPrompts==`object`?n.projectPrompts:{},z.success(Z(`@WORKBENCH:已保存项目默认提示词`)),!0):(z.error(n?.error||Z(`@WORKBENCH:保存失败`)),!1)}catch(e){return z.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),!1}}async function x(t){if(s.value)return!1;let n=e.value;e.value=t,s.value=!0;try{let r=await fetch(`/api/workbench/orchestrator/state`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({active:t})}).then(e=>e.json());return r?.success?(e.value=r.active!==!1,z.success(e.value?Z(`@WORKBENCH:已恢复调度`):Z(`@WORKBENCH:已暂停调度,派发将只建任务不执行`)),!0):(e.value=n,z.error(r?.error||Z(`@WORKBENCH:切换调度状态失败`)),!1)}catch(t){return e.value=n,z.error(Z(`@WORKBENCH:网络错误: `)+(t?.message||t)),!1}finally{s.value=!1}}async function S(e){if(c.value)return null;c.value=!0;try{let t=await fetch(`/api/workbench/orchestrator/dispatch`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({text:e.text,projectPath:e.projectPath||``,autoRun:e.autoRun!==!1,useDefaultPrompt:e.useDefaultPrompt!==!1,executor:e.executor,attachments:(e.attachments||[]).map(e=>({id:e.id,ext:e.ext,originalName:e.originalName}))})}).then(e=>e.json());return t?.success?(await h(!0),{task:t.task||null,ran:!!t.ran}):(z.error(t?.error||Z(`@WORKBENCH:派发失败`)),null)}catch(e){return z.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),null}finally{c.value=!1}}return{active:e,instructions:t,activity:n,running:i,updatedAt:a,loaded:o,togglingSchedule:s,dispatching:c,maxInstructionChars:r,defaultPrompt:l,projectPrompts:u,reports:d,loadingReports:f,generatingReport:p,reportIntervalMs:m,loadOrchestrator:h,setSchedulingActive:x,dispatch:S,saveDefaultPrompt:y,saveProjectPrompt:b,loadReports:g,generateReport:_,setReportInterval:v}}var qr=6e4,Jr=60*qr,Yr=24*Jr;function Xr(e,t=Date.now()){if(!e)return``;let n=new Date(e).getTime();if(Number.isNaN(n))return``;let r=Math.max(0,t-n);return r<qr?Z(`@WORKBENCH:刚刚`):r<Jr?Z(`@WORKBENCH:N 分钟前`,{n:Math.floor(r/qr)}):r<Yr?Z(`@WORKBENCH:N 小时前`,{n:Math.floor(r/Jr)}):r<30*Yr?Z(`@WORKBENCH:N 天前`,{n:Math.floor(r/Yr)}):new Date(n).toLocaleDateString()}function Zr(e){let t=Number(e);if(!Number.isFinite(t)||t<0)return``;let n=Math.floor(t/1e3),r=Math.floor(n/3600),i=Math.floor(n%3600/60),a=n%60;return r>0?Z(`@WORKBENCH:N 小时 M 分`,{n:r,m:i}):i>0?Z(`@WORKBENCH:N 分 M 秒`,{n:i,m:a}):Z(`@WORKBENCH:N 秒`,{n:a})}function Qr(e,t){return e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate()}function $r(e,t=Date.now()){if(!e)return``;let n=new Date(e);if(Number.isNaN(n.getTime()))return``;let r=e=>String(e).padStart(2,`0`),i=`${r(n.getHours())}:${r(n.getMinutes())}:${r(n.getSeconds())}`,a=new Date(t);if(Qr(n,a))return i;if(Qr(n,new Date(a.getFullYear(),a.getMonth(),a.getDate()-1)))return Z(`@WORKBENCH:昨天 {time}`,{time:i});let o=`${n.getMonth()+1}/${n.getDate()}`;return n.getFullYear()===a.getFullYear()?`${o} ${i}`:`${n.getFullYear()}/${o} ${i}`}D(),F();var ei=T({__name:`WorkbenchProjectPanel`,props:{projects:{type:Array,required:!0},selectedKey:{type:String,required:!0},loading:{type:Boolean,required:!0}},emits:[`select`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,o=a(()=>[...r.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)})),s=J(``),c=J(!1),d=J(!1),f=a(()=>!!s.value.trim()||c.value||d.value),p=a(()=>{let e=s.value.trim().toLowerCase();return o.value.filter(t=>c.value&&t.stats.total===0||d.value&&t.git&&t.git.isGitRepo===!1?!1:!e||t.name.toLowerCase().includes(e)||t.path.toLowerCase().includes(e))});function m(){s.value=``,c.value=!1,d.value=!1}let h=a(()=>r.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})),g=a(()=>h.value.total>0?Math.round(h.value.done/h.value.total*100):0);function _(e){return e.git?e.git.isGitRepo===null?Z(`@WORKBENCH:未知`):e.git.isGitRepo?e.git.detached?Z(`@WORKBENCH:游离 HEAD`):e.git.branch||Z(`@WORKBENCH:未知`):``:``}function v(e){return!!(e.git&&e.git.isGitRepo&&(e.git.detached||e.git.branch))}let y=J(null),b=J(null);function x(e,t){if(y.value===e.key){y.value=null;return}b.value=t.currentTarget,y.value=e.key}function S(){y.value=null}function w(e){if(!y.value)return;let t=e.target;if(t&&!b.value?.contains(t)){for(let e of Array.from(document.querySelectorAll(`.proj-open-menu`)))if(e.contains(t))return;y.value=null}}he(()=>document.addEventListener(`mousedown`,w,!0)),u(()=>document.removeEventListener(`mousedown`,w,!0));let T=Ie(),E=J(!1),D=J(null);function O(e){return T.lastCheckedAt!==null&&!T.isToolAvailable(e)}async function k(e){S();let t=await We(e.path);t.success?z.success(t.message||Z(`@WORKBENCH:已在文件管理器中打开文件夹`)):z.error(t.error||Z(`@WORKBENCH:打开文件夹失败`))}async function ee(e){S();let t=await Ue(e.path);t.success?z.success(t.message||Z(`@67CE7:已在终端中打开目录`)):z.error(t.error||Z(`@WORKBENCH:打开终端失败`))}async function ne(e){S();let t=await Ke(e.path);t.success?z.success(Z(`@WORKBENCH:已在新标签页启动 g ui`)):z.error(t.error||Z(`@WORKBENCH:启动 g ui 失败`))}async function A(e){if(S(),e.name)try{await navigator.clipboard.writeText(e.name),z.success(Z(`@67CE7:已复制文件夹名称`))}catch{z.error(Z(`@67CE7:复制失败`))}}async function re(e,t,n){if(S(),!await Ve()){z.warning(Z(`@67CE7:工具检测失败,请稍后重试`));return}if(!T.isToolAvailable(t)){D.value=t,E.value=!0;return}let r=await He(t,e.path,n);r.success?z.success(r.message||Z(`@67CE7:已用 {tool} 打开目录`,{tool:Be[t]})):z.error(`${Z(`@67CE7:打开失败: `)}${r.error??``}`)}let j={props:r,emit:i,ordered:o,query:s,onlyWithTasks:c,hideNonGit:d,filtering:f,visible:p,clearFilters:m,totals:h,overallProgress:g,gitLine:_,hasBranchIcon:v,openMenuKey:y,menuTriggerEl:b,toggleOpenMenu:x,closeOpenMenu:S,onDocumentMouseDown:w,toolsStore:T,installVisible:E,installTool:D,toolMissing:O,openInFileManager:k,openInTerminal:ee,launchGui:ne,copyFolderName:A,openWithTool:re,get $t(){return Z},get CopyDocument(){return pe},get Folder(){return se},get FolderOpened(){return Ce},get Grid(){return xe},get Monitor(){return C},get MoreFilled(){return l},get Promotion(){return Te},get Search(){return te},SvgIcon:je,ToolInstallDialog:Ye,get claudeCodeIcon(){return ze},get OPEN_WITH_TOOLS(){return Je},get relativeTimeFromIso(){return Xr}};return Object.defineProperty(j,"__isScriptSetup",{enumerable:!1,value:!0}),j}});S(),D(),H();var ti={class:`proj`},ni={class:`proj__head`},ri={class:`proj__title`},ii={class:`proj__count`},ai={key:0,class:`proj__tools`},oi={class:`proj__search`},si=[`placeholder`,`aria-label`],ci={class:`proj__toggles`},li=[`aria-pressed`,`title`],ui=[`aria-pressed`,`title`],di={class:`proj__list`},fi=[`title`],pi={class:`proj-item__row1`},mi={class:`proj-item__name`},hi={key:0,class:`proj-item__running`,"aria-hidden":`true`},gi={class:`proj-item__num`},_i={class:`proj-item__row2`},vi={key:0,class:`proj-item__running-text`},yi={key:0,class:`proj-item__row3`},bi={class:`proj-item__bar`,"aria-hidden":`true`},xi={class:`proj-item__progress-text`},Si=[`title`,`onClick`,`onKeydown`],Ci={class:`proj-item__row1`},wi={class:`proj-item__name`},Ti={class:`proj-item__signals`},Ei={key:0,class:`proj-item__running`,"aria-hidden":`true`},Di={key:1,class:`proj-item__badge`},Oi={class:`proj-item__row2`},ki={key:0,class:`proj-chip proj-chip--missing`},Ai={key:0,class:`proj-item__branch`},ji={class:`proj-item__branch-name`},Mi={key:1,class:`proj-chip proj-chip--ahead`},Ni={key:2,class:`proj-chip proj-chip--behind`},Pi={key:3,class:`proj-chip proj-chip--dirty`},Fi={class:`proj-item__time`},Ii={key:0,class:`proj-item__row3`},Li={class:`proj-item__bar`,"aria-hidden":`true`},Ri={class:`proj-item__progress-text`},zi={key:1,class:`proj-item__actions`},Bi=[`title`,`aria-label`,`onClick`],Vi=[`title`,`aria-label`,`aria-expanded`,`onClick`],Hi=[`aria-label`],Ui=[`onClick`,`onKeydown`],Wi={class:`proj-menu__icon`},Gi={class:`proj-menu__label`},Ki=[`onClick`,`onKeydown`],qi={class:`proj-menu__icon`},Ji={class:`proj-menu__label`},Yi=[`onClick`,`onKeydown`],Xi={class:`proj-menu__icon`},Zi={class:`proj-menu__label`},Qi=[`onClick`,`onKeydown`],$i={class:`proj-menu__icon`},ea={class:`proj-menu__label`},ta={class:`proj-menu__title`,role:`presentation`},na=[`onClick`,`onKeydown`],ra={class:`proj-menu__icon`},ia={class:`proj-menu__label`},aa={key:0,class:`proj-menu__hint`},oa=[`onClick`,`onKeydown`],sa={class:`proj-menu__icon`},ca=[`src`],la={class:`proj-menu__label`},ua={class:`proj-menu__hint`},da=[`onClick`,`onKeydown`],fa={class:`proj-menu__icon`},pa=[`src`],ma={class:`proj-menu__label`},ha=[`onClick`,`onKeydown`],ga={class:`proj-menu__icon`},_a={class:`proj-menu__label`},va=[`onClick`,`onKeydown`],ya={class:`proj-menu__icon`},ba={class:`proj-menu__label`},xa={key:0,class:`proj-menu__hint`},Sa={key:1,class:`proj-menu__hint`},Ca=[`onClick`,`onKeydown`],wa={class:`proj-menu__icon`},Ta={class:`proj-menu__label`},Ea={key:0,class:`proj-empty`},Da={class:`proj-empty__title`},Oa={class:`proj-empty__hint`},ka={key:1,class:`proj-empty`},Aa={class:`proj-empty__title`};function ja(e,t,n,r,i,a){let c=h,l=N;return j(),o(`section`,ti,[Y(`header`,ni,[Y(`h3`,ri,E(r.$t(`@WORKBENCH:项目列表`)),1),Y(`span`,ii,[r.filtering?(j(),o(X,{key:0},[V(E(r.$t(`@WORKBENCH:匹配 {n}/{total} 个项目`,{n:r.visible.length,total:n.projects.length})),1)],64)):(j(),o(X,{key:1},[V(E(n.projects.length),1)],64))])]),s(` 一个项目都没有时不渲染筛选条:没有可筛的东西,这一行只是占位 `),n.projects.length>0?(j(),o(`div`,ai,[Y(`div`,oi,[x(c,{class:`proj__search-icon`,"aria-hidden":`true`},{default:G(()=>[x(r.Search)]),_:1}),K(Y(`input`,{"onUpdate:modelValue":t[0]||=e=>r.query=e,class:`proj__search-input`,type:`search`,placeholder:r.$t(`@WORKBENCH:搜索项目名称或路径`),"aria-label":r.$t(`@WORKBENCH:搜索项目名称或路径`),onKeydown:t[1]||=P(e=>r.query=``,[`esc`])},null,40,si),[[R,r.query]])]),Y(`div`,ci,[Y(`button`,{type:`button`,class:g([`proj__toggle`,{"is-on":r.onlyWithTasks}]),"aria-pressed":r.onlyWithTasks,title:r.$t(`@WORKBENCH:只显示有任务的项目`),onClick:t[2]||=e=>r.onlyWithTasks=!r.onlyWithTasks},[Y(`span`,null,E(r.$t(`@WORKBENCH:只看有任务`)),1)],10,li),Y(`button`,{type:`button`,class:g([`proj__toggle`,{"is-on":r.hideNonGit}]),"aria-pressed":r.hideNonGit,title:r.$t(`@WORKBENCH:只显示 Git 仓库`),onClick:t[3]||=e=>r.hideNonGit=!r.hideNonGit},[Y(`span`,null,E(r.$t(`@WORKBENCH:隐藏非 Git`)),1)],10,ui)])])):s(`v-if`,!0),Y(`ul`,di,[Y(`li`,{class:g([`proj-item proj-item--all`,{"is-active":n.selectedKey===``}]),role:`button`,tabindex:`0`,title:r.$t(`@WORKBENCH:全部项目`),onClick:t[4]||=e=>r.emit(`select`,null),onKeydown:[t[5]||=P(q(e=>r.emit(`select`,null),[`prevent`]),[`enter`]),t[6]||=P(q(e=>r.emit(`select`,null),[`prevent`]),[`space`])]},[Y(`div`,pi,[x(c,{class:`proj-item__icon`},{default:G(()=>[x(r.Grid)]),_:1}),Y(`span`,mi,E(r.$t(`@WORKBENCH:全部项目`)),1),r.totals.running>0?(j(),o(`span`,hi)):s(`v-if`,!0),Y(`span`,gi,E(n.projects.length),1)]),Y(`div`,_i,[Y(`span`,null,E(r.$t(`@WORKBENCH:{n} 个项目`,{n:n.projects.length})),1),r.totals.running>0?(j(),o(`span`,vi,E(r.$t(`@WORKBENCH:{n} 个执行中`,{n:r.totals.running})),1)):s(`v-if`,!0)]),s(` 一个任务都没有时整行不渲染(「0/0 任务完成」+ 空进度条是纯噪声) `),r.totals.total>0?(j(),o(`div`,yi,[Y(`span`,bi,[Y(`i`,{class:`proj-item__bar-fill`,style:m({width:r.overallProgress+`%`})},null,4)]),Y(`span`,xi,E(r.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:r.totals.done,total:r.totals.total})),1)])):s(`v-if`,!0)],42,fi),(j(!0),o(X,null,M(r.visible,e=>(j(),o(`li`,{key:e.key,class:g([`proj-item`,{"is-active":e.key===n.selectedKey,"is-running":e.stats.runningJobs>0,"is-missing":e.exists===!1}]),role:`button`,tabindex:`0`,title:e.path,onClick:t=>r.emit(`select`,e),onKeydown:[P(q(t=>r.emit(`select`,e),[`self`,`prevent`]),[`enter`]),P(q(t=>r.emit(`select`,e),[`self`,`prevent`]),[`space`])]},[Y(`div`,Ci,[x(c,{class:`proj-item__icon`},{default:G(()=>[x(r.Folder)]),_:1}),Y(`span`,wi,E(e.name),1),s(` 运行中 / 当前 这两个信号与 hover 才出现的操作按钮锚在同一个右端点:
27
+ hover 时整组淡出让位给按钮,而不是让图标压在徽标上 `),Y(`span`,Ti,[e.stats.runningJobs>0?(j(),o(`span`,Ei)):s(`v-if`,!0),e.isCurrent?(j(),o(`span`,Di,E(r.$t(`@WORKBENCH:当前`)),1)):s(`v-if`,!0)])]),Y(`div`,Oi,[e.exists===!1?(j(),o(`span`,ki,E(r.$t(`@WORKBENCH:目录不存在`)),1)):(j(),o(X,{key:1},[s(` gitLine 为空即"不是 Git 仓库":不给文字,也不给图标 `),r.gitLine(e)?(j(),o(`span`,Ai,[r.hasBranchIcon(e)?(j(),k(r.SvgIcon,{key:0,"icon-class":`git-branch`,"class-name":`proj-item__branch-icon`})):s(`v-if`,!0),Y(`span`,ji,E(r.gitLine(e)),1)])):s(`v-if`,!0),e.git&&e.git.ahead>0?(j(),o(`span`,Mi,`↑`+E(e.git.ahead),1)):s(`v-if`,!0),e.git&&e.git.behind>0?(j(),o(`span`,Ni,`↓`+E(e.git.behind),1)):s(`v-if`,!0),e.git&&e.git.changed>0?(j(),o(`span`,Pi,`●`+E(e.git.changed),1)):s(`v-if`,!0)],64)),Y(`span`,Fi,E(r.relativeTimeFromIso(e.stats.lastActiveAt)),1)]),s(` 同上:这个项目一个任务都没有就不给进度行 `),e.stats.total>0?(j(),o(`div`,Ii,[Y(`span`,Li,[Y(`i`,{class:`proj-item__bar-fill`,style:m({width:e.stats.progress+`%`})},null,4)]),Y(`span`,Ri,E(r.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:e.stats.done,total:e.stats.total})),1)])):s(`v-if`,!0),s(` 打开动作:与行主体平级,绝对定位锚在 row1 右端(不占位,否则「当前」徽标
28
+ 永远离右边缘一条);.stop 阻止冒泡到行的选中逻辑。目录都不存在了就不渲染——
29
+ 点了只会弹一个「无法打开目录」的报错。
30
+ 两个按钮:最常用的「打开文件夹」留一键直达,其余打开方式(终端 / 编辑器 /
31
+ AI 工具 / 新标签页跑 g ui)收进「打开方式」菜单 —— 一行放不下七个图标,
32
+ 而项目名被挤成省略号比多点一次更难受。
33
+ ⚠️ 行上的 keydown 必须带 .self:事件从按钮冒泡上来,不带 .self 时
34
+ 焦点在按钮上按回车会「选中该行 + preventDefault 掉按钮自己的激活」,
35
+ 键盘用户反而打不开文件夹。 `),e.exists===!1?s(`v-if`,!0):(j(),o(`div`,zi,[Y(`button`,{type:`button`,class:`proj-item__action`,title:r.$t(`@WORKBENCH:打开文件夹`),"aria-label":`${r.$t(`@WORKBENCH:打开文件夹`)} ${e.name}`,onClick:q(t=>r.openInFileManager(e),[`stop`])},[x(c,{"aria-hidden":`true`},{default:G(()=>[x(r.FolderOpened)]),_:1})],8,Bi),x(l,{visible:r.openMenuKey===e.key,trigger:`manual`,placement:`right-start`,width:272,"show-arrow":!1,offset:6,"popper-class":`proj-open-menu`},{reference:G(()=>[Y(`button`,{type:`button`,class:g([`proj-item__action`,{"is-open":r.openMenuKey===e.key}]),title:r.$t(`@WORKBENCH:打开方式`),"aria-label":`${r.$t(`@WORKBENCH:打开方式`)} ${e.name}`,"aria-expanded":r.openMenuKey===e.key,"aria-haspopup":`menu`,onClick:q(t=>r.toggleOpenMenu(e,t),[`stop`])},[x(c,{"aria-hidden":`true`},{default:G(()=>[x(r.MoreFilled)]),_:1})],10,Vi)]),default:G(()=>[r.openMenuKey===e.key?(j(),o(`ul`,{key:0,class:`proj-menu`,role:`menu`,"aria-label":r.$t(`@WORKBENCH:打开方式`)},[Y(`li`,{class:`proj-menu__item`,role:`menuitem`,tabindex:`-1`,onClick:t=>r.openInFileManager(e),onKeydown:[P(q(t=>r.openInFileManager(e),[`prevent`]),[`enter`]),P(q(t=>r.openInFileManager(e),[`prevent`]),[`space`])]},[Y(`span`,Wi,[x(c,{"aria-hidden":`true`},{default:G(()=>[x(r.FolderOpened)]),_:1})]),Y(`span`,Gi,E(r.$t(`@WORKBENCH:在文件管理器中打开`)),1)],40,Ui),Y(`li`,{class:`proj-menu__item`,role:`menuitem`,tabindex:`-1`,onClick:t=>r.openInTerminal(e),onKeydown:[P(q(t=>r.openInTerminal(e),[`prevent`]),[`enter`]),P(q(t=>r.openInTerminal(e),[`prevent`]),[`space`])]},[Y(`span`,qi,[x(c,{"aria-hidden":`true`},{default:G(()=>[x(r.Monitor)]),_:1})]),Y(`span`,Ji,E(r.$t(`@WORKBENCH:在终端中打开`)),1)],40,Ki),Y(`li`,{class:`proj-menu__item`,role:`menuitem`,tabindex:`-1`,onClick:t=>r.launchGui(e),onKeydown:[P(q(t=>r.launchGui(e),[`prevent`]),[`enter`]),P(q(t=>r.launchGui(e),[`prevent`]),[`space`])]},[Y(`span`,Xi,[x(c,{"aria-hidden":`true`},{default:G(()=>[x(r.Promotion)]),_:1})]),Y(`span`,Zi,E(r.$t(`@WORKBENCH:在新标签页启动 g ui`)),1)],40,Yi),s(` 复制文件夹名称:放在"打开"这一组里,因为它操作的是项目目录本身,
36
+ 而不是"用哪个工具打开"(下面那组有独立标题)。 `),Y(`li`,{class:`proj-menu__item`,role:`menuitem`,tabindex:`-1`,onClick:t=>r.copyFolderName(e),onKeydown:[P(q(t=>r.copyFolderName(e),[`prevent`]),[`enter`]),P(q(t=>r.copyFolderName(e),[`prevent`]),[`space`])]},[Y(`span`,$i,[x(c,{"aria-hidden":`true`},{default:G(()=>[x(r.CopyDocument)]),_:1})]),Y(`span`,ea,E(r.$t(`@67CE7:复制文件夹名称`)),1)],40,Qi),t[8]||=Y(`li`,{class:`proj-menu__sep`,role:`separator`},null,-1),Y(`li`,ta,E(r.$t(`@WORKBENCH:用工具打开`)),1),(j(!0),o(X,null,M(r.OPEN_WITH_TOOLS,t=>(j(),o(`li`,{key:t.id,class:g([`proj-menu__item`,{"is-missing":r.toolMissing(t.id)}]),role:`menuitem`,tabindex:`-1`,onClick:n=>r.openWithTool(e,t.id),onKeydown:[P(q(n=>r.openWithTool(e,t.id),[`prevent`]),[`enter`]),P(q(n=>r.openWithTool(e,t.id),[`prevent`]),[`space`])]},[Y(`span`,ra,[x(r.SvgIcon,{"icon-class":t.icon},null,8,[`icon-class`])]),Y(`span`,ia,E(r.$t(t.labelKey)),1),r.toolMissing(t.id)?(j(),o(`span`,aa,E(r.$t(`@67CE7:未安装`)),1)):s(`v-if`,!0)],42,na))),128)),s(` claude 有两种权限模式,不混进上面的工具列表(顶栏也是单独排布的) `),Y(`li`,{class:g([`proj-menu__item`,{"is-missing":r.toolMissing(`claude`)}]),role:`menuitem`,tabindex:`-1`,onClick:t=>r.openWithTool(e,`claude`),onKeydown:[P(q(t=>r.openWithTool(e,`claude`),[`prevent`]),[`enter`]),P(q(t=>r.openWithTool(e,`claude`),[`prevent`]),[`space`])]},[Y(`span`,sa,[Y(`img`,{src:r.claudeCodeIcon,alt:``,class:`proj-menu__img`},null,8,ca)]),Y(`span`,la,E(r.$t(`@67CE7:用 Claude Code 打开`)),1),Y(`span`,ua,E(r.toolMissing(`claude`)?r.$t(`@67CE7:未安装`):r.$t(`@67CE7:默认权限`)),1)],42,oa),Y(`li`,{class:g([`proj-menu__item proj-menu__item--danger`,{"is-missing":r.toolMissing(`claude`)}]),role:`menuitem`,tabindex:`-1`,onClick:t=>r.openWithTool(e,`claude`,`bypassPermissions`),onKeydown:[P(q(t=>r.openWithTool(e,`claude`,`bypassPermissions`),[`prevent`]),[`enter`]),P(q(t=>r.openWithTool(e,`claude`,`bypassPermissions`),[`prevent`]),[`space`])]},[Y(`span`,fa,[Y(`img`,{src:r.claudeCodeIcon,alt:``,class:`proj-menu__img`},null,8,pa)]),Y(`span`,ma,E(r.$t(`@67CE7:用 Claude Code 打开(完全批准)`)),1)],42,da),s(` opencode 的「完全批准」(\`--auto\`)与 claude 的 bypass 档并列收在末尾:
37
+ 它带警示色,混进上面的普通工具列表会把"一行一个工具"的节奏打乱,
38
+ 而它又确实得单独成项(默认档已经在上面那条 v-for 里了)。 `),Y(`li`,{class:g([`proj-menu__item proj-menu__item--danger`,{"is-missing":r.toolMissing(`opencode`)}]),role:`menuitem`,tabindex:`-1`,onClick:t=>r.openWithTool(e,`opencode`,`auto`),onKeydown:[P(q(t=>r.openWithTool(e,`opencode`,`auto`),[`prevent`]),[`enter`]),P(q(t=>r.openWithTool(e,`opencode`,`auto`),[`prevent`]),[`space`])]},[Y(`span`,ga,[x(r.SvgIcon,{"icon-class":`opencode`})]),Y(`span`,_a,E(r.$t(`@67CE7:用 OpenCode 打开(完全批准)`)),1)],42,ha),s(` codex 天然有三档(默认档已在上面那条 v-for 里):自动批准但仍有沙箱 →
39
+ 免批准 + 免沙箱。两档都单独成项,理由同 claude / opencode 那两项。 `),Y(`li`,{class:g([`proj-menu__item`,{"is-missing":r.toolMissing(`codex`)}]),role:`menuitem`,tabindex:`-1`,onClick:t=>r.openWithTool(e,`codex`,`sandboxed`),onKeydown:[P(q(t=>r.openWithTool(e,`codex`,`sandboxed`),[`prevent`]),[`enter`]),P(q(t=>r.openWithTool(e,`codex`,`sandboxed`),[`prevent`]),[`space`])]},[Y(`span`,ya,[x(r.SvgIcon,{"icon-class":`codex`})]),Y(`span`,ba,E(r.$t(`@67CE7:用 Codex 打开(自动批准)`)),1),r.toolMissing(`codex`)?(j(),o(`span`,Sa,E(r.$t(`@67CE7:未安装`)),1)):(j(),o(`span`,xa,E(r.$t(`@67CE7:沙箱内`)),1))],42,va),Y(`li`,{class:g([`proj-menu__item proj-menu__item--danger`,{"is-missing":r.toolMissing(`codex`)}]),role:`menuitem`,tabindex:`-1`,onClick:t=>r.openWithTool(e,`codex`,`bypass`),onKeydown:[P(q(t=>r.openWithTool(e,`codex`,`bypass`),[`prevent`]),[`enter`]),P(q(t=>r.openWithTool(e,`codex`,`bypass`),[`prevent`]),[`space`])]},[Y(`span`,wa,[x(r.SvgIcon,{"icon-class":`codex`})]),Y(`span`,Ta,E(r.$t(`@67CE7:用 Codex 打开(完全批准)`)),1)],42,Ca)],8,Hi)):s(`v-if`,!0)]),_:2},1032,[`visible`])]))],42,Si))),128)),!n.loading&&n.projects.length===0?(j(),o(`li`,Ea,[Y(`p`,Da,E(r.$t(`@WORKBENCH:尚无项目`)),1),Y(`p`,Oa,E(r.$t(`@WORKBENCH:常用目录与建过任务的目录都会出现在这里`)),1)])):s(`v-if`,!0),s(` 有项目、只是被筛没了:这必须说出来。
40
+ 空着会让人以为项目列表坏了,而"没有匹配"和"一个项目都没有"是两件事。
41
+ 刻意写成两个互斥的 v-if(而不是 v-else-if):条件里带上了 projects.length,
42
+ 读代码时不用回头找上一段才敢确定它们不重叠。 `),!n.loading&&n.projects.length>0&&r.visible.length===0?(j(),o(`li`,ka,[Y(`p`,Aa,E(r.$t(`@WORKBENCH:没有匹配的项目`)),1),Y(`button`,{type:`button`,class:`proj-empty__clear`,onClick:r.clearFilters},E(r.$t(`@WORKBENCH:清除筛选`)),1)])):s(`v-if`,!0)]),s(` 未安装的工具:复用顶栏那套安装引导(同一个组件),不在这里另写一份说明。
43
+ 挂在面板根上只渲染一份,而不是每行一个 —— 同时最多只可能开一个。 `),x(r.ToolInstallDialog,{modelValue:r.installVisible,"onUpdate:modelValue":t[7]||=e=>r.installVisible=e,tool:r.installTool},null,8,[`modelValue`,`tool`])])}var Ma=Q(ei,[[`render`,ja],[`__scopeId`,`data-v-de1af726`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchProjectPanel.vue`]]),Na=[140,170,200,230,260,290,320,350];function Pa(e){return(e||``).replace(/\\/g,`/`).trim().toLowerCase()}function Fa(e){let t=Pa(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 Ia(e){return{"--tag-hue":String(Fa(e))}}D(),F();var La=`wb.boardView.v1`,Ra=T({__name:`WorkbenchKanban`,props:{tasks:{type:Array,required:!0},projectLabels:{type:Object,required:!0},showProjectLabel:{type:Boolean,required:!0},openedTaskId:{type:[String,null],required:!0}},emits:[`open-task`,`run-task`,`delete-task`,`create-task`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,o=J((()=>{try{return localStorage.getItem(La)===`list`?`list`:`kanban`}catch{return`kanban`}})());B(o,e=>{try{localStorage.setItem(La,e)}catch{}});let s=J(``),c=[{key:`todo`,labelKey:`@WORKBENCH:待处理`},{key:`doing`,labelKey:`@WORKBENCH:进行中`},{key:`done`,labelKey:`@WORKBENCH:已完成`}],l=a(()=>{let e=s.value.trim().toLowerCase();return r.tasks.filter(t=>!e||(t.title||``).toLowerCase().includes(e)||(t.desc||``).toLowerCase().includes(e))}),u=a(()=>c.map(e=>e.key===`done`?{...e,tasks:l.value.filter(t=>t.column===e.key).sort(f)}:{...e,tasks:l.value.filter(t=>t.column===e.key)}));function d(e){return String(e.lastJobEndedAt||e.updatedAt||e.createdAt||``)}function f(e,t){return d(t).localeCompare(d(e))}function p(e){return e.column===`done`?d(e):e.updatedAt||e.createdAt||``}let m=a(()=>({gridTemplateColumns:`repeat(${u.value.length}, minmax(0, 1fr))`}));function h(e){return(e.title||``).trim()||(e.desc||``).replace(/\s+/g,` `).trim()}function g(e){return r.projectLabels[e.projectPath]||``}function _(e){return e.lastJobStatus===`error`}function v(e){return e.live?.agent||e.lastJobAgent||``}function y(e){let t=Z(`@WORKBENCH:已运行 {elapsed}`,{elapsed:Zr(e.elapsedMs)}),n=e.lastLine||e.lastThought||e.lastTool;return n?`${t} · ${n}`:t}let b={props:r,emit:i,VIEW_KEY:La,view:o,search:s,COLUMNS:c,filtered:l,columns:u,doneAt:d,byDoneAtDesc:f,cardTime:p,columnsStyle:m,cardTitle:h,projectLabel:g,hasError:_,cardAgent:v,liveSummary:y,get $t(){return Z},get Search(){return te},TaskExecutorIcon:qe,get taskExecutorName(){return Pe},get projectTagStyle(){return Ia},get formatDurationMs(){return Zr},get relativeTimeFromIso(){return Xr}};return Object.defineProperty(b,"__isScriptSetup",{enumerable:!1,value:!0}),b}});S(),D(),H();var za={class:`kb`},Ba={class:`kb__toolbar`},Va={class:`kb__views`,role:`tablist`},Ha=[`aria-selected`],Ua=[`aria-selected`],Wa={class:`kb__filters`},Ga={class:`kb__search`},Ka=[`placeholder`,`aria-label`],qa={class:`kb-col__head`},Ja={class:`kb-col__title`},Ya={class:`kb-col__count`},Xa={class:`kb-col__list`},Za=[`data-task-id`,`aria-current`,`onClick`,`onKeydown`],Qa={class:`kb-card__row1`},$a=[`title`],eo=[`title`],to={class:`kb-card__time`},no={key:0,class:`kb-card__live`},ro={class:`kb-card__live-meta`},io=[`title`],ao=[`title`],oo={key:2,class:`kb-card__live-pid`},so={key:3,class:`kb-card__live-silent`},co=[`title`],lo=[`title`],uo={class:`kb-card__live-tag`},fo=[`title`],po={class:`kb-card__live-tag`},mo=[`title`],ho=[`title`],go={class:`kb-card__reply-text`},_o={class:`kb-card__actions`},vo=[`title`,`onClick`],yo=[`title`,`aria-label`,`onClick`],bo={key:0,class:`kb-col__add`},xo={key:1,class:`kb-col__empty`},So={class:`kb__table-wrap`},Co={class:`kb-table`},wo={class:`kb-table__th`},To={class:`kb-table__th kb-table__th--narrow`},Eo={class:`kb-table__th kb-table__th--narrow`},Do=[`onClick`,`onKeydown`],Oo={class:`kb-table__td`},ko={class:`kb-table__name`},Ao=[`title`],jo={key:1,class:`kb-table__live`},Mo=[`title`],No={key:1,class:`kb-table__live-silent`},Po={class:`kb-table__live kb-table__live--reply`},Fo=[`title`],Io={class:`kb-table__td`},Lo={class:`kb-table__td kb-table__td--num`},Ro={key:0},zo={class:`kb-table__td kb-table__empty`,colspan:`3`};function Bo(e,t,n,r,i,a){let c=h;return j(),o(`div`,za,[Y(`div`,Ba,[Y(`div`,Va,[Y(`button`,{type:`button`,role:`tab`,class:g([`kb__view-btn`,{"is-active":r.view===`kanban`}]),"aria-selected":r.view===`kanban`,onClick:t[0]||=e=>r.view=`kanban`},E(r.$t(`@WORKBENCH:看板视图`)),11,Ha),Y(`button`,{type:`button`,role:`tab`,class:g([`kb__view-btn`,{"is-active":r.view===`list`}]),"aria-selected":r.view===`list`,onClick:t[1]||=e=>r.view=`list`},E(r.$t(`@WORKBENCH:列表视图`)),11,Ua)]),Y(`div`,Wa,[Y(`div`,Ga,[x(c,{class:`kb__search-icon`},{default:G(()=>[x(r.Search)]),_:1}),K(Y(`input`,{class:`kb__search-input`,type:`search`,"onUpdate:modelValue":t[2]||=e=>r.search=e,placeholder:r.$t(`@WORKBENCH:搜索任务标题或描述`),"aria-label":r.$t(`@WORKBENCH:搜索任务标题或描述`)},null,8,Ka),[[R,r.search]])])])]),s(` 看板视图 `),r.view===`kanban`?(j(),o(`div`,{key:0,class:`kb__columns`,style:m(r.columnsStyle)},[(j(!0),o(X,null,M(r.columns,e=>(j(),o(`section`,{key:e.key,class:g([`kb-col`,`kb-col--`+e.key])},[Y(`header`,qa,[t[6]||=Y(`span`,{class:`kb-col__dot`,"aria-hidden":`true`},null,-1),Y(`h3`,Ja,E(r.$t(e.labelKey)),1),Y(`span`,Ya,E(e.tasks.length),1)]),Y(`ul`,Xa,[(j(!0),o(X,null,M(e.tasks,e=>(j(),o(`li`,{key:e.id,class:g([`kb-card`,{"is-running":e.runningJobs>0,"has-error":r.hasError(e),"is-opened":e.id===n.openedTaskId}]),"data-task-id":e.id,"aria-current":e.id===n.openedTaskId?`true`:void 0,role:`button`,tabindex:`0`,onClick:t=>r.emit(`open-task`,e),onKeydown:[P(q(t=>r.emit(`open-task`,e),[`prevent`]),[`enter`]),P(q(t=>r.emit(`open-task`,e),[`prevent`]),[`space`])]},[s(`
44
+ 首行 = 所属项目色标 + 标题 + 时间,三样同一行。
45
+ · 色标原先自己占一行(一枚 60px 的胶囊推着标题和活动区往下走),
46
+ 现在跟标题并排:卡片窄,能省一行是一行。
47
+ · 进行中那枚黄点去掉了 —— "在跑"由列本身 + 卡片上的活动区表达,
48
+ 再来一枚一闪一闪的圆点属于重复编码,而且它是这张卡上唯一的纯装饰动效。
49
+ · 标题不再单独占行,跟着一起上移。
50
+ title 给完整路径:项目名可能重名(两个都叫 notebook),路径才是唯一答案。
51
+ `),Y(`div`,Qa,[n.showProjectLabel&&r.projectLabel(e)?(j(),o(`span`,{key:0,class:`kb-card__project-chip`,style:m(r.projectTagStyle(e.projectPath)),title:e.projectPath},E(r.projectLabel(e)),13,$a)):s(`v-if`,!0),Y(`p`,{class:`kb-card__title`,title:r.cardTitle(e)},E(r.cardTitle(e)||r.$t(`@WORKBENCH:未命名任务`)),9,eo),Y(`span`,to,E(r.relativeTimeFromIso(r.cardTime(e))),1)]),s(`
52
+ 正在跑的任务:把"现在在干嘛"直接写在卡片上。
53
+ 在此之前卡片只有右上角一个圆点 —— 一次跑二十分钟的任务,
54
+ 用户盯着看只知道"还在跑",是在改代码还是卡住了完全看不出来,
55
+ 只能点进编辑器翻输出。服务端随卡片一起把事实摘要发过来
56
+ (decorateTaskForBoard 的 live,与右栏进度报告同一份实现)。
57
+ 证据顺序沿用进度报告面板:工具调用(正在做什么)→ 思考(为什么)
58
+ → 最新回复;每一行没有内容就整行不渲染,不写"暂无"。
59
+ `),e.live?(j(),o(`div`,no,[Y(`p`,ro,[s(` 执行器只留图标 + 悬停提示:卡片这一行本来就窄(已运行 x 分 y 秒 · 工具 n 次),
60
+ 再钉一个 "Claude Code" 文本会把工具次数挤到第二行去。
61
+ v-if 挡住的是"认不出"(老记录没写 agent 字段)——那时宁可不画 `),r.cardAgent(e)?(j(),o(`span`,{key:0,class:`kb-card__live-agent`,title:r.taskExecutorName(r.cardAgent(e))},[x(r.TaskExecutorIcon,{executor:r.cardAgent(e),class:`kb-card__live-agent-icon`},null,8,[`executor`])],8,io)):s(`v-if`,!0),Y(`span`,null,E(r.$t(`@WORKBENCH:已运行 {elapsed}`,{elapsed:r.formatDurationMs(e.live.elapsedMs)})),1),s(` 次数看总数,鼠标停上去看分布:119 次里 118 次都是 Bash,
62
+ 和"改了三处代码"是完全不同的两件事 `),e.live.toolCallCount?(j(),o(`span`,{key:1,title:e.live.toolMix||``},E(r.$t(`@WORKBENCH:工具 {n} 次`,{n:e.live.toolCallCount})),9,ao)):s(`v-if`,!0),s(`
63
+ PID:左栏那个「执行监控」面板去掉了,它的字段里只有这一个卡片上没有,
64
+ 所以并到这一行来(面板其余字段卡片本来就都有,且比它更全)。
65
+ 不走 $t:PID 是中英文都这么写的通用缩写,没有可翻译的余地。
66
+ 放静默之前:静默是"它可能卡住了"的信号,该留在行尾最显眼。
67
+ `),e.live.pid?(j(),o(`span`,oo,`PID `+E(e.live.pid),1)):s(`v-if`,!0),s(` 静默只在**显然静默**时才有值(服务端有阈值),所以这里不用再过滤 `),typeof e.live.silentMs==`number`?(j(),o(`span`,so,E(r.$t(`@WORKBENCH:静默 {elapsed}`,{elapsed:r.formatDurationMs(e.live.silentMs)})),1)):s(`v-if`,!0)]),e.live.lastTool?(j(),o(`p`,{key:0,class:`kb-card__live-line is-tool`,title:e.live.lastTool},E(e.live.lastTool),9,co)):s(`v-if`,!0),e.live.lastThought?(j(),o(`p`,{key:1,class:`kb-card__live-line is-thought`,title:e.live.lastThought},[Y(`span`,uo,E(r.$t(`@WORKBENCH:最近思考`)),1),V(E(e.live.lastThought),1)],8,lo)):s(`v-if`,!0),e.live.lastLine?(j(),o(`p`,{key:2,class:`kb-card__live-line`,title:e.live.lastLine},[Y(`span`,po,E(r.$t(`@WORKBENCH:最新回复`)),1),V(E(e.live.lastLine),1)],8,fo)):s(`v-if`,!0)])):e.lastReply?(j(),o(X,{key:1},[s(`
68
+ 已经跑完的任务:留下"它最后说了什么"。
69
+ 卡片过去只有标题 + 时间,而模型收尾时常常反问一句「要 push 吗?」——
70
+ 这类任务看着是完成了,其实在等用户回话,用户却只能点进去翻日志才知道。
71
+ live 覆盖不到这一段:它只在 running 时有值、跑完就消失,恰好把最有信息量的
72
+ 收尾丢掉(服务端 decorateTaskForBoard 的 lastReply,与这里二选一)。
73
+ 样式沿用 live 里「思考」那行的竖线 —— 同一个含义(这是它说的原话);
74
+ 不加标签:卡片窄,一行放不下 4 个字的标签还挤掉正文。
75
+
76
+ 执行器图标(有才渲染)摆在引文开头:这句收尾的话是**它**说的,
77
+ 图标就贴着它,比跑到卡片别处去找更直接。
78
+ `),Y(`p`,{class:`kb-card__reply`,title:e.lastReply},[r.cardAgent(e)?(j(),o(`span`,{key:0,class:`kb-card__quote-agent`,title:r.taskExecutorName(r.cardAgent(e))},[x(r.TaskExecutorIcon,{executor:r.cardAgent(e),class:`kb-card__quote-agent-icon`},null,8,[`executor`])],8,ho)):s(`v-if`,!0),Y(`span`,go,E(e.lastReply),1)],8,mo)],2112)):s(`v-if`,!0),Y(`div`,_o,[e.runningJobs===0?(j(),o(`button`,{key:0,type:`button`,class:`kb-card__btn`,title:r.$t(`@WORKBENCH:执行`),onClick:q(t=>r.emit(`run-task`,e),[`stop`]),onKeydown:t[3]||=q(()=>{},[`stop`])},E(r.$t(`@WORKBENCH:执行`)),41,vo)):s(`v-if`,!0),Y(`button`,{type:`button`,class:`kb-card__btn kb-card__btn--danger`,title:r.$t(`@WORKBENCH:删除`),"aria-label":r.$t(`@WORKBENCH:删除`),onClick:q(t=>r.emit(`delete-task`,e),[`stop`]),onKeydown:t[4]||=q(()=>{},[`stop`])},`×`,40,yo)])],42,Za))),128)),s(`
79
+ 「新建任务」常驻待处理列末尾,不再只在列空时出现。
80
+ 之前入口和空状态是同一个 \`v-if="col.tasks.length === 0"\`:列里一有卡片,
81
+ 新建入口就整块消失,用户只能绕到左侧栏去建(看板里无处可点)。
82
+ 两件事本来就无关——空状态说的是"这列没有卡片",新建入口说的是"能往这儿加卡片"。
83
+ 列空时它顺带兼任空状态(--solo 撑高),所以待处理列不会再渲染下面的 kb-col__empty。
84
+ 位置沿用 Trello「Add a card」的做法:跟着列表滚(不吸底),长列表滚到底就是它。
85
+ `),e.key===`todo`?(j(),o(`li`,bo,[Y(`button`,{type:`button`,class:g([`kb-col__add-btn`,{"kb-col__add-btn--solo":e.tasks.length===0}]),onClick:t[5]||=e=>r.emit(`create-task`)},[t[7]||=Y(`span`,{class:`kb-col__add-plus`,"aria-hidden":`true`},`+`,-1),Y(`span`,null,E(r.$t(`@WORKBENCH:新建任务`)),1)],2)])):e.tasks.length===0?(j(),o(`li`,xo,[Y(`span`,null,E(r.$t(`@WORKBENCH:暂无任务`)),1)])):s(`v-if`,!0)])],2))),128))],4)):(j(),o(X,{key:1},[s(` 列表视图 `),Y(`div`,So,[Y(`table`,Co,[Y(`thead`,null,[Y(`tr`,null,[Y(`th`,wo,E(r.$t(`@WORKBENCH:任务`)),1),Y(`th`,To,E(r.$t(`@WORKBENCH:状态`)),1),Y(`th`,Eo,E(r.$t(`@WORKBENCH:更新时间`)),1)])]),Y(`tbody`,null,[(j(!0),o(X,null,M(r.filtered,e=>(j(),o(`tr`,{key:e.id,class:`kb-table__row`,tabindex:`0`,onClick:t=>r.emit(`open-task`,e),onKeydown:[P(q(t=>r.emit(`open-task`,e),[`prevent`]),[`enter`]),P(q(t=>r.emit(`open-task`,e),[`prevent`]),[`space`])]},[Y(`td`,Oo,[Y(`span`,ko,E(r.cardTitle(e)||r.$t(`@WORKBENCH:未命名任务`)),1),s(` 项目色标:与看板卡片同一枚(见 .kb-card__project-chip 的样式注释),
86
+ 列表视图是同一批任务的另一种画法,两处长得不一样会让人以为是两份数据 `),n.showProjectLabel&&r.projectLabel(e)?(j(),o(`span`,{key:0,class:`kb-table__project`,style:m(r.projectTagStyle(e.projectPath)),title:e.projectPath},E(r.projectLabel(e)),13,Ao)):s(`v-if`,!0),s(` 状态列的"进行中"太粗,跑起来之后一眼看不出进度:这里补一行
87
+ 最新回复 / 思考 / 工具(与卡片上的 live 同一份数据)。
88
+ 执行器图标摆最前(与看板卡片同一个位置:整块执行事实的开头) `),e.live?(j(),o(`span`,jo,[r.cardAgent(e)?(j(),o(`span`,{key:0,class:`kb-table__agent`,title:r.taskExecutorName(r.cardAgent(e))},[x(r.TaskExecutorIcon,{executor:r.cardAgent(e),class:`kb-table__agent-icon`},null,8,[`executor`])],8,Mo)):s(`v-if`,!0),V(` `+E(r.liveSummary(e.live))+` `,1),typeof e.live.silentMs==`number`?(j(),o(`span`,No,E(r.$t(`@WORKBENCH:静默 {elapsed}`,{elapsed:r.formatDurationMs(e.live.silentMs)})),1)):s(`v-if`,!0)])):e.lastReply?(j(),o(X,{key:2},[s(` 跑完的任务同理给一行"最后说了什么":列表视图与看板卡片是同一批任务的
89
+ 两种画法,一边有、一边没有会让人以为是两份数据 `),Y(`span`,Po,[r.cardAgent(e)?(j(),o(`span`,{key:0,class:`kb-table__agent`,title:r.taskExecutorName(r.cardAgent(e))},[x(r.TaskExecutorIcon,{executor:r.cardAgent(e),class:`kb-table__agent-icon`},null,8,[`executor`])],8,Fo)):s(`v-if`,!0),V(E(e.lastReply),1)])],2112)):s(`v-if`,!0)]),Y(`td`,Io,[Y(`span`,{class:g([`kb-table__status`,`is-`+e.column])},E(r.$t(r.COLUMNS.find(t=>t.key===e.column).labelKey)),3)]),Y(`td`,Lo,E(r.relativeTimeFromIso(e.updatedAt||e.createdAt)),1)],40,Do))),128)),r.filtered.length===0?(j(),o(`tr`,Ro,[Y(`td`,zo,E(r.$t(`@WORKBENCH:暂无任务`)),1)])):s(`v-if`,!0)])])])],2112))])}var Vo=Q(Ra,[[`render`,Bo],[`__scopeId`,`data-v-0b8fc27c`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchKanban.vue`]]);D();var Ho=T({__name:`TaskExecutorPicker`,props:{title:{type:String,required:!1}},setup(t,{expose:n}){n();let r=t,{active:i,availability:a,choose:o,executorModelText:s,executorModelTitle:c}=Yn(),l=Ie();he(()=>{l.fetchExecutorModels()});function u(){return[r.title,c(i.value)].filter(Boolean).join(` · `)}let d={props:r,active:i,availability:a,choose:o,executorModelText:s,executorModelTitle:c,toolsStore:l,btnTitle:u,get ArrowDown(){return me},get Check(){return e},get $t(){return Z},TaskExecutorIcon:qe,get TASK_EXECUTOR_OPTIONS(){return Ne},get taskExecutorName(){return Pe}};return Object.defineProperty(d,"__isScriptSetup",{enumerable:!1,value:!0}),d}});D(),S();var Uo=[`title`,`aria-label`],Wo={class:`tep__btn-name`},Go={class:`tep__item`},Ko={class:`tep__item-name`},qo=[`title`],Jo={key:2,class:`tep__item-missing`};function Yo(e,t,n,r,a,c){let l=h,u=i,d=be,f=O;return j(),k(f,{trigger:`click`,class:`tep`,onCommand:r.choose},{dropdown:G(()=>[x(d,null,{default:G(()=>[(j(!0),o(X,null,M(r.TASK_EXECUTOR_OPTIONS,e=>(j(),k(u,{key:e.id,command:e.id,disabled:!r.availability[e.id]},{default:G(()=>[Y(`span`,Go,[x(r.TaskExecutorIcon,{executor:e.id,class:`tep__item-icon`},null,8,[`executor`]),Y(`span`,Ko,E(e.name),1),r.executorModelText(e.id)?(j(),o(`span`,{key:0,class:`tep__item-model`,title:r.executorModelTitle(e.id)},E(r.executorModelText(e.id)),9,qo)):s(`v-if`,!0),r.active===e.id?(j(),k(l,{key:1,class:`tep__item-check`},{default:G(()=>[x(r.Check)]),_:1})):r.availability[e.id]?s(`v-if`,!0):(j(),o(`span`,Jo,E(r.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`,`disabled`]))),128))]),_:1})]),default:G(()=>[Y(`button`,{type:`button`,class:`tep__btn`,title:r.btnTitle(),"aria-label":r.$t(`@WORKBENCH:任务执行器`)},[x(r.TaskExecutorIcon,{executor:r.active,class:`tep__btn-icon`},null,8,[`executor`]),Y(`span`,Wo,E(r.taskExecutorName(r.active)),1),x(l,{class:`tep__btn-caret`},{default:G(()=>[x(r.ArrowDown)]),_:1})],8,Uo)]),_:1},8,[`onCommand`])}var Xo=Q(Ho,[[`render`,Yo],[`__scopeId`,`data-v-7674ee77`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/TaskExecutorPicker.vue`]]);D(),F();var Zo=T({__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}},setup(e,{expose:t}){t();let n=e,{active:r}=Yn(),{theme:i}=Le(),o=a(()=>i.value===`dark`?`dark`:`light`),{sessions:s,sessionsLoading:c,currentSessionId:l,messages:u,isStreaming:f,pendingQuestion:p,answeringQuestion:m,isSessionGenerating:h,currentEngine:g,pendingEngine:_,isEngineLocked:v,pickEngine:y,loadSessions:b,loadSession:x,deleteSession:S,renameSession:C,newSession:w,sendMessage:T,answerQuestion:E,stop:D}=tt(),O=a(()=>v.value?g.value:_.value);function k(e){v.value||y(e)}let ee=a(()=>n.allowDispatch!==!1&&O.value!==`gai`),te=a(()=>Xe(s.value,h)),ne=et(),A=Ze(),re=J(null),{width:j,narrow:M}=it(re),N=J(`chat`),P=J(null);function ie(e=!0){P.value?.scrollToBottom?.(e)}async function ae(e){await T(e.text,e.files,{allowDispatch:n.allowDispatch===!0,dispatchExecutor:r.value,dispatchUseDefaultPrompt:n.dispatchUseDefaultPrompt!==!1}),await d(),ie()}function oe(e){x(e),N.value=`chat`}function se(){w(),N.value=`chat`}B(()=>u.value.length,()=>{d(()=>ie(!1))}),B(()=>n.active,e=>{e&&(b().catch(()=>{}),d(()=>ie(!1)))}),B(M,e=>{e||(N.value=`chat`)}),he(()=>{b().catch(()=>{}),d(()=>ie(!1))});let F={props:n,executor:r,theme:i,chatTheme:o,sessions:s,sessionsLoading:c,currentSessionId:l,messages:u,isStreaming:f,pendingQuestion:p,answeringQuestion:m,isSessionGenerating:h,currentEngine:g,pendingEngine:_,isEngineLocked:v,pickEngine:y,loadSessions:b,loadSession:x,deleteSession:S,renameSession:C,newSession:w,sendMessage:T,answerQuestion:E,stop:D,displayEngine:O,onEngineSelect:k,engineCantDispatch:ee,conversationItems:te,conversationLabels:ne,questionLabels:A,rootRef:re,width:j,narrow:M,page:N,chatRef:P,scrollToBottom:ie,onSend:ae,onSelectSession:oe,onNewSession:se,get $t(){return Z},get ChatContainer(){return Ae},get ChatInput(){return Ee},get ConversationList(){return Oe},get AGENT_UPLOAD_ACCEPT(){return $e},get agentEngineName(){return rt},get AGENT_ASSISTANT_NAME(){return Qe},get AGENT_ASSISTANT_AVATAR(){return nt},AgentEngineSelector:at,TaskExecutorPicker:Xo};return Object.defineProperty(F,"__isScriptSetup",{enumerable:!1,value:!0}),F}});D(),S(),H();var Qo={ref:`rootRef`,class:`acs`},$o={class:`acs__head`},es=[`title`,`aria-label`],ts={class:`acs__title`},ns=[`title`,`aria-label`],rs={class:`acs__convs`},is={class:`acs__chat`},as=[`data-theme`],os={key:0,class:`acs__foot`},ss={key:0,class:`acs__notice`},cs={class:`acs__foot-label`},ls={class:`acs__foot-hint`};function us(e,n,r,i,a,c){return j(),o(`div`,Qo,[Y(`div`,$o,[s(` 窄屏的列表页:整条头让给「返回对话 + 标题」 `),i.narrow&&i.page===`list`?(j(),o(`button`,{key:0,type:`button`,class:`acs__icon-btn`,title:i.$t(`@EDITOR:返回对话`),"aria-label":i.$t(`@EDITOR:返回对话`),onClick:n[0]||=e=>i.page=`chat`},[...n[2]||=[Y(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[Y(`line`,{x1:`19`,y1:`12`,x2:`5`,y2:`12`}),Y(`polyline`,{points:`12 19 5 12 12 5`})],-1)]],8,es)):s(`v-if`,!0),Y(`span`,ts,E(r.title||i.$t(`@WORKBENCH:g ai 对话`)),1),n[4]||=Y(`span`,{class:`acs__spacer`},null,-1),s(` 引擎切换:与「智能体」视图 / 编辑器面板同一个选择器(唯一那份实现)。
90
+ 宽屏对话区一直在,所以常驻;窄屏只在对话页出现 —— 列表页摆它只会挤占标题。 `),!i.narrow||i.page===`chat`?(j(),k(i.AgentEngineSelector,{key:1,class:`acs__engine`,engine:i.displayEngine,locked:i.isEngineLocked,onSelect:i.onEngineSelect},null,8,[`engine`,`locked`])):s(`v-if`,!0),s(` 会话列表按钮:只有"列表是独立一页"时才需要它(宽屏列表就在旁边) `),i.narrow&&i.page===`chat`?(j(),o(`button`,{key:2,type:`button`,class:`acs__icon-btn`,title:i.$t(`@EDITOR:会话列表`),"aria-label":i.$t(`@EDITOR:会话列表`),onClick:n[1]||=e=>i.page=`list`},[...n[3]||=[t(`<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,ns)):s(`v-if`,!0)]),Y(`div`,{class:g([`acs__body`,{"is-wide":!i.narrow}])},[s(` 会话历史:宽屏是常驻左列,窄屏是独享整页 `),K(Y(`div`,rs,[x(i.ConversationList,{"show-search":!0,items:i.conversationItems,"active-id":i.currentSessionId,loading:i.sessionsLoading,labels:i.conversationLabels,onSelect:i.onSelectSession,onNew:i.onNewSession,onRename:i.renameSession,onDelete:i.deleteSession},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])],512),[[L,!i.narrow||i.page===`list`]]),s(` 气泡区:输入框已经不在这里了(show-input=false),见下面常驻的那一条 `),K(Y(`div`,is,[x(i.ChatContainer,{ref:`chatRef`,"show-input":!1,messages:i.messages,"assistant-name":i.AGENT_ASSISTANT_NAME,"assistant-avatar":i.AGENT_ASSISTANT_AVATAR,theme:i.chatTheme,question:i.pendingQuestion,"question-submitting":i.answeringQuestion,"question-labels":i.questionLabels,"plan-config":{labels:{title:i.$t(`@AGENT:计划`),raw:i.$t(`@AGENT:原始参数`)}},onAnswer:i.answerQuestion},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`question`,`question-submitting`,`question-labels`,`plan-config`,`onAnswer`])],512),[[L,!i.narrow||i.page===`chat`]]),s(`
91
+ 输入框常驻:两种形态、两个页面都在最下方。
92
+ 它被拆到 ChatContainer 外面,所以 acu-root 与 data-theme 得自己套上:
93
+ 库把盒模型重置限定在 .acu-root 子树里,而 ChatInput 根节点是 div(不是 button),
94
+ 少了它就会退回 content-box、横着溢出这条栏。
95
+
96
+ v-if="width > 0":**等量到本面板的宽度再挂载输入框**。库的 ChatInput 只在
97
+ onMounted 里量一次 scrollHeight,量到的宽度不对就再也纠不回来 —— 实测首帧挂载时
98
+ 容器还没宽度,占位文案被折成十几行,textarea 直接顶到 200px 上限并一直卡在那里
99
+ (切走再切回才对)。宽度是 useNarrowPane 在 onMounted 里同步量到的,所以这里
100
+ 晚的只是一次重渲染,同一帧内就补上了,看不到闪烁。
101
+ `),i.width>0?(j(),o(`div`,{key:0,class:`acs__composer acu-root`,"data-theme":i.chatTheme},[x(i.ChatInput,{disabled:i.isStreaming,generating:i.isStreaming,placeholder:r.placeholder||(i.isStreaming?i.$t(`@AGENT:正在生成中...`):i.$t(`@AGENT:输入消息,Enter 发送`)),"upload-config":{accept:i.AGENT_UPLOAD_ACCEPT},onSend:i.onSend,onStop:i.stop},null,8,[`disabled`,`generating`,`placeholder`,`upload-config`,`onStop`])],8,as)):s(`v-if`,!0)],2),s(` 底部:派发执行器。放在输入框下面而不是头部 —— 它修饰的是"派出去的活谁跑",
102
+ 不是"我在跟谁聊",和引擎选择器挤在一行会让人分不清哪个管哪件事 `),r.allowDispatch&&i.page===`chat`?(j(),o(`div`,os,[i.engineCantDispatch?(j(),o(`p`,ss,E(i.$t(`@WORKBENCH:当前引擎「{name}」只能对话,不能派发任务 —— 切到内置 g ai 才能派活`,{name:i.agentEngineName(i.displayEngine)})),1)):(j(),o(X,{key:1},[Y(`span`,cs,E(i.$t(`@WORKBENCH:派发执行器`)),1),x(i.TaskExecutorPicker,{title:i.$t(`@WORKBENCH:它派出去的任务由这个执行器跑(与执行按钮的临时切换共用)`)},null,8,[`title`]),Y(`span`,ls,E(i.$t(`@WORKBENCH:任务会落到看板,跑完有完成提示`)),1)],64))])):s(`v-if`,!0)],512)}var ds=Q(Zo,[[`render`,us],[`__scopeId`,`data-v-9e75d420`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/AgentChatSurface.vue`]]);D(),F();var fs=`wb.ocMode.v2`,ps=`/api/workbench/orchestrator/attachments`,ms=`wb.ocInputHeight.v1`,hs=76,gs=20,_s=T({__name:`OrchestratorConsole`,props:{active:{type:Boolean,required:!0},runningCount:{type:Number,required:!0},selectedProject:{type:[Object,null],required:!0},dispatching:{type:Boolean,required:!0},togglingSchedule:{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-schedule`,`toggle-collapse`,`open-prompt-settings`,`generate-report`,`set-report-interval`,`dispatch`],setup(e,{expose:t,emit:n}){let i=e,o=n,s=J(``),c=J(!0),l=J(!0),{active:d}=Yn(),p=J((()=>{try{return localStorage.getItem(fs)===`chat`?`chat`:`command`}catch{return`command`}})());function m(e){p.value=e;try{localStorage.setItem(fs,e)}catch{}}let h=J([]),g=a(()=>({kind:`draft`,list:h.value,replace:e=>{h.value=e}})),{isUploading:v,isImageAttachment:y,humanSize:b,onAttachmentPaste:x,onAttachmentDrop:S,removeAttachment:C,pickAttachmentFile:w}=Wn(),T=a(()=>v(`draft`)),E=J(!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 ee(e){C(g.value,e)}function te(){h.value=[]}function ne(){s.value=``}t({clearAttachments:te,clearDraft:ne});let A=a(()=>i.selectedProject?.key||``),re=a(()=>(i.defaultPrompt||``).trim()),j=a(()=>{let e=A.value;return e?(i.projectPrompts?.[e]?.prompt||``).trim():``}),M=a(()=>Object.values(i.projectPrompts||{}).some(e=>(e?.prompt||``).trim().length>0)),N=a(()=>!!re.value||M.value),P=a(()=>{let e=!!re.value,t=A.value?j.value?`project`:`none`:M.value?`target`:`none`;return Z(e&&t===`project`?`@WORKBENCH:全局 + 本项目`:e&&t===`target`?`@WORKBENCH:全局 + 落点项目`:e?`@WORKBENCH:全局`:t===`project`?`@WORKBENCH:本项目`:t===`target`?`@WORKBENCH:落点项目`:`@WORKBENCH:未设置`)}),ae=a(()=>s.value.trim().length),oe=a(()=>i.maxInstructionChars||1e5),se=a(()=>ae.value>oe.value),F=a(()=>!se.value&&ae.value>=oe.value*.9),ce=a(()=>s.value.trim().length>0&&!i.dispatching&&!T.value&&!se.value);function I(){ce.value&&o(`dispatch`,{text:s.value.trim(),autoRun:c.value,attachments:h.value,projectPath:i.selectedProject?i.selectedProject.path:``,useDefaultPrompt:l.value,executor:d.value})}function le(e){e.isComposing||e.keyCode===229||e.key!==`Enter`||e.shiftKey||(e.preventDefault(),I())}function L(){try{let e=localStorage.getItem(ms);if(!e)return null;let t=Number(e);return Number.isFinite(t)&&t>=hs?Math.round(t):null}catch{return null}}let ue=J(null),R=J(L()),z=a(()=>{let e={};return R.value&&(e.height=`${R.value}px`),e}),B=null,fe=!1,V=!0;function H(e){let t=ue.value;if(!t)return;let n=t.getBoundingClientRect();fe=n.right-e.clientX<=gs&&n.bottom-e.clientY<=gs}function U(){fe=!1}function W(e){let t=Math.round(e.offsetHeight);if(!(t<hs||t===R.value)){R.value=t;try{localStorage.setItem(ms,String(t))}catch{}}}he(()=>{let e=ue.value;e&&(window.addEventListener(`mouseup`,U),!(typeof ResizeObserver>`u`)&&(B=new ResizeObserver(()=>{if(V){V=!1;return}let t=parseFloat(getComputedStyle(e).maxHeight),n=Number.isFinite(t)&&e.offsetHeight>=t-1;(fe||!n)&&W(e)}),B.observe(e)))}),u(()=>{window.removeEventListener(`mouseup`,U),B?.disconnect(),B=null});let G=J(null),pe=a(()=>{let e=i.reports||[];return e.length?e.find(e=>e.id===G.value)||e[0]:null});function me(e){G.value=e.id}function ge(e){let t=String(e.text||``).replace(/\s+/g,` `).trim();return t?t.length>42?t.slice(0,42)+`…`:t:e.errorCode?Z(Wr(e.errorCode)):Z(`@WORKBENCH:当时没有任务在执行`)}function _e(e){return e.errorCode?Z(Wr(e.errorCode)):e.tasks.length?Z(`@WORKBENCH:模型没有返回内容`):Z(`@WORKBENCH:生成这份报告时没有任务在执行`)}function K(e){let t=e.target,n=Number(t.value);zr.includes(n)&&o(`set-report-interval`,n)}let ve={props:i,emit:o,draft:s,autoRun:c,useDefaultPrompt:l,selectedExecutor:d,MODE_KEY:fs,mode:p,setMode:m,draftAttachments:h,DRAFT_RAW_BASE:ps,attachTarget:g,isUploading:v,isImageAttachment:y,humanSize:b,onAttachmentPaste:x,onAttachmentDrop:S,removeAttachment:C,pickAttachmentFile:w,attachBusy:T,attachDragging:E,onPaste:D,onDrop:O,onPickAttachment:k,onRemoveAttachment:ee,clearAttachments:te,clearDraft:ne,projectKey:A,globalPromptText:re,projectPromptText:j,anyProjectPrompt:M,anyPromptConfigured:N,promptStateLabel:P,draftChars:ae,charLimit:oe,overLimit:se,nearLimit:F,canSend:ce,send:I,onInputKeydown:le,INPUT_H_KEY:ms,OC_INPUT_MIN_H:hs,readInputH:L,inputRef:ue,inputH:R,inputStyle:z,get inputRO(){return B},set inputRO(e){B=e},get inputDragging(){return fe},set inputDragging(e){fe=e},get inputROFirst(){return V},set inputROFirst(e){V=e},INPUT_GRIP_PX:gs,onInputMouseDown:H,onWindowMouseUp:U,commitInputH:W,selectedReportId:G,currentReport:pe,pickReport:me,reportBrief:ge,reportNotice:_e,onIntervalChange:K,gitSummary:a(()=>{let e=i.selectedProject;if(!e)return[];let t=[];if(e.exists===!1)return t.push({label:Z(`@WORKBENCH:工作区`),value:Z(`@WORKBENCH:目录不存在`),tone:`danger`}),t;let n=e.git;return!n||n.isGitRepo===null?(t.push({label:Z(`@WORKBENCH:Git 状态`),value:Z(`@WORKBENCH:未知`),tone:``}),t):n.isGitRepo?(t.push({label:Z(`@WORKBENCH:分支`),value:n.detached?Z(`@WORKBENCH:游离 HEAD`):n.branch||Z(`@WORKBENCH:未知`),tone:``}),t.push({label:Z(`@WORKBENCH:工作区`),value:n.changed>0?Z(`@WORKBENCH:未提交 {n} 项`,{n:n.changed}):Z(`@WORKBENCH:干净`),tone:n.changed>0?`warn`:``}),n.hasUpstream&&(n.ahead>0||n.behind>0)&&t.push({label:Z(`@WORKBENCH:与上游`),value:Z(`@WORKBENCH:领先 {ahead} / 落后 {behind}`,{ahead:n.ahead,behind:n.behind}),tone:n.behind>0?`warn`:``}),t):(t.push({label:Z(`@WORKBENCH:Git 状态`),value:Z(`@WORKBENCH:不是 Git 仓库`),tone:``}),t)}),get $t(){return Z},get Paperclip(){return f},get Promotion(){return Te},get Expand(){return de},get Fold(){return ie},get Setting(){return _},get Refresh(){return r},get clockFromIso(){return $r},get formatDurationMs(){return Zr},get relativeTimeFromIso(){return Xr},get REPORT_INTERVAL_OPTIONS_MS(){return zr},get reportIntervalLabelKey(){return Hr},get reportIntervalLabelParams(){return Ur},AttachmentZone:bt,AgentChatSurface:ds,TaskExecutorPicker:Xo};return Object.defineProperty(ve,"__isScriptSetup",{enumerable:!1,value:!0}),ve}});D(),S(),H();var vs=[`title`,`aria-label`],ys={class:`oc__rail-text`},bs={class:`oc__head`},xs={class:`oc__title`},Ss=[`disabled`,`title`],Cs=[`title`,`aria-label`],ws={class:`oc__state-label`},Ts={class:`oc__state-value`},Es={class:`oc__state-meta`},Ds=[`aria-label`],Os=[`aria-selected`],ks=[`aria-selected`],As={class:`oc__report`},js={class:`oc__report-head`},Ms={class:`oc__panel-title`},Ns=[`value`,`title`,`aria-label`],Ps=[`value`],Fs=[`disabled`,`title`],Is={class:`oc__report-list`},Ls={key:0,class:`rp`},Rs={class:`rp__head`},zs={class:`rp__count`},Bs={class:`rp__time`},Vs={key:0,class:`rp__text`},Hs=[`title`],Us={key:2,class:`rp__tasks`},Ws={class:`rpt__title`},Gs={class:`rpt__meta`},Ks={key:0,class:`rpt__project`},qs={key:1,class:`rpt__agent`},Js=[`title`],Ys={key:3,class:`rpt__silent`},Xs=[`title`],Zs=[`title`],Qs={class:`rpt__thought-tag`},$s=[`title`],ec={key:1,class:`oc-empty`},tc={key:0,class:`oc__history`},nc={class:`oc__history-title`},rc={class:`oc__history-list`},ic=[`onClick`],ac={class:`oc__history-time`},oc={class:`oc__history-sum`},sc={class:`oc__git`},cc={class:`oc__panel-title`},lc={class:`oc__git-name`},uc={class:`oc__git-list`},dc={class:`oc__git-label`},fc={class:`oc__git-label`},pc={class:`oc__git-value`},mc={class:`oc__git-label`},hc={class:`oc__git-value`},gc=[`placeholder`],_c={key:0},vc={key:1},yc={class:`oc__compose-foot`},bc=[`disabled`,`title`,`aria-label`],xc=[`title`,`aria-label`],Sc=[`title`],Cc=[`title`],wc=[`disabled`],Tc={class:`oc__hint`};function Ec(e,t,n,r,i,a){let c=h;return j(),o(`aside`,{class:g([`oc`,{"is-collapsed":n.collapsed}])},[s(` 折叠后的收纳条:只剩一枚展开按钮 + 竖排标题,宽度收到 32px。
103
+ 折叠不是"把宽度压成 0"—— 那样就再没有能点回来的地方了。 `),n.collapsed?(j(),o(`button`,{key:0,type:`button`,class:`oc__rail`,title:r.$t(`@WORKBENCH:展开主 Agent 控制台`),"aria-label":r.$t(`@WORKBENCH:展开主 Agent 控制台`),"aria-expanded":!1,onClick:t[0]||=e=>r.emit(`toggle-collapse`)},[x(c,{class:`oc__rail-icon`},{default:G(()=>[x(r.Fold)]),_:1}),Y(`span`,{class:g([`oc__rail-live`,{"is-off":!n.active}]),"aria-hidden":`true`},null,2),Y(`span`,ys,E(r.$t(`@WORKBENCH:主 Agent 控制台`)),1)],8,vs)):s(`v-if`,!0),s(` 折叠时这几块整体隐藏而不是销毁(v-show 而不是 v-if):
104
+ 草稿指令和已贴的附件都还留着,展开回来能接着发 `),K(Y(`header`,bs,[Y(`span`,{class:g([`oc__live`,{"is-off":!n.active}]),"aria-hidden":`true`},null,2),Y(`h3`,xs,E(r.$t(`@WORKBENCH:主 Agent 控制台`)),1),Y(`button`,{type:`button`,class:`oc__toggle`,disabled:n.togglingSchedule,title:n.active?r.$t(`@WORKBENCH:暂停后派发只建任务,不会自动执行`):r.$t(`@WORKBENCH:恢复后派发会自动执行`),onClick:t[1]||=e=>r.emit(`toggle-schedule`,!n.active)},E(n.active?r.$t(`@WORKBENCH:暂停调度`):r.$t(`@WORKBENCH:恢复调度`)),9,Ss),Y(`button`,{type:`button`,class:`oc__collapse`,title:r.$t(`@WORKBENCH:收起主 Agent 控制台`),"aria-label":r.$t(`@WORKBENCH:收起主 Agent 控制台`),"aria-expanded":!0,onClick:t[2]||=e=>r.emit(`toggle-collapse`)},[x(c,null,{default:G(()=>[x(r.Expand)]),_:1})],8,Cs)],512),[[L,!n.collapsed]]),K(Y(`div`,{class:g([`oc__state`,{"is-paused":!n.active}])},[Y(`span`,ws,E(r.$t(`@WORKBENCH:调度状态`)),1),Y(`span`,Ts,E(n.active?r.$t(`@WORKBENCH:调度中`):r.$t(`@WORKBENCH:已暂停`)),1),Y(`span`,Es,E(r.$t(`@WORKBENCH:{n} 个执行中`,{n:n.runningCount})),1)],2),[[L,!n.collapsed]]),s(` 工作方式:对话 = g ai 边聊边派(可以多轮、可以反问你);指令 = 你自己敲一句话派一条。
105
+ 两种方式落到的是**同一条派发链路、同一条指令流水**,变的只是"谁决定派什么"。 `),K(Y(`div`,{class:`oc__mode`,role:`tablist`,"aria-label":r.$t(`@WORKBENCH:切换主 Agent 控制台的工作方式`)},[Y(`button`,{type:`button`,role:`tab`,class:g([`oc__mode-btn`,{"is-active":r.mode===`chat`}]),"aria-selected":r.mode===`chat`,onClick:t[3]||=e=>r.setMode(`chat`)},E(r.$t(`@WORKBENCH:对话`)),11,Os),Y(`button`,{type:`button`,role:`tab`,class:g([`oc__mode-btn`,{"is-active":r.mode===`command`}]),"aria-selected":r.mode===`command`,onClick:t[4]||=e=>r.setMode(`command`)},E(r.$t(`@WORKBENCH:指令`)),11,ks)],8,Ds),[[L,!n.collapsed]]),K(x(r.AgentChatSurface,{class:`oc__chat`,active:!n.collapsed&&r.mode===`chat`,"allow-dispatch":``,"dispatch-use-default-prompt":r.useDefaultPrompt,title:r.$t(`@WORKBENCH:g ai 对话`)},null,8,[`active`,`dispatch-use-default-prompt`,`title`]),[[L,!n.collapsed&&r.mode===`chat`]]),s(` 进度报告:主 Agent 隔一会儿读一遍正在跑的 job,写一段"现在到哪一步了"。
106
+ 报告由服务端生成(自动那份由服务端定时器产生),这里只渲染 + 两个入口:
107
+ 改间隔、立即报告。 `),K(Y(`div`,As,[Y(`div`,js,[Y(`p`,Ms,E(r.$t(`@WORKBENCH:进度报告`)),1),s(` 间隔设置。做成下拉而不是输入框:这个值直接决定每多久烧一次模型额度,
108
+ 自由填一个 5(分钟写成了秒)会让额度很快见底,而用户不会立刻意识到 `),Y(`select`,{class:`oc__interval`,value:String(n.reportIntervalMs??0),title:r.$t(`@WORKBENCH:自动报告的间隔(关掉后仍可随时点「立即报告」)`),"aria-label":r.$t(`@WORKBENCH:自动报告间隔`),onChange:r.onIntervalChange},[(j(!0),o(X,null,M(r.REPORT_INTERVAL_OPTIONS_MS,e=>(j(),o(`option`,{key:e,value:String(e)},E(r.$t(r.reportIntervalLabelKey(e),r.reportIntervalLabelParams(e))),9,Ps))),128))],40,Ns),Y(`button`,{type:`button`,class:`oc__report-run`,disabled:n.generatingReport,title:r.$t(`@WORKBENCH:让主 Agent 现在汇报一次正在执行的任务进度`),onClick:t[5]||=e=>r.emit(`generate-report`)},[x(c,{class:g([`oc__report-run-icon`,{"is-spin":n.generatingReport}])},{default:G(()=>[x(r.Refresh)]),_:1},8,[`class`]),Y(`span`,null,E(n.generatingReport?r.$t(`@WORKBENCH:生成中…`):r.$t(`@WORKBENCH:立即报告`)),1)],8,Fs)]),Y(`ul`,Is,[r.currentReport?(j(),o(`li`,Ls,[Y(`div`,Rs,[Y(`span`,{class:g([`rp__trigger`,{"is-auto":r.currentReport.trigger===`auto`}])},E(r.currentReport.trigger===`auto`?r.$t(`@WORKBENCH:自动`):r.$t(`@WORKBENCH:手动`)),3),Y(`span`,zs,E(r.$t(`@WORKBENCH:{n} 个任务进行中`,{n:r.currentReport.tasks.length})),1),Y(`span`,Bs,E(r.clockFromIso(r.currentReport.at)),1)]),r.currentReport.text?(j(),o(`p`,Vs,E(r.currentReport.text),1)):(j(),o(X,{key:1},[s(` 没有正文时给的是**实话**:没任务 / 没配模型 / 模型没返回内容,
109
+ 三种情况的处理办法完全不同,一律写"暂无"会让人白等 `),Y(`p`,{class:`rp__notice`,title:r.currentReport.errorDetail},E(r.reportNotice(r.currentReport)),9,Hs)],2112)),r.currentReport.tasks.length?(j(),o(`ul`,Us,[(j(!0),o(X,null,M(r.currentReport.tasks,(e,t)=>(j(),o(`li`,{key:e.taskId||t,class:`rpt`},[Y(`p`,Ws,E(e.taskTitle||r.$t(`@WORKBENCH:未命名任务`)),1),Y(`p`,Gs,[e.projectName?(j(),o(`span`,Ks,E(e.projectName),1)):s(`v-if`,!0),Y(`span`,null,E(r.$t(`@WORKBENCH:已运行 {elapsed}`,{elapsed:r.formatDurationMs(e.elapsedMs)})),1),e.agent?(j(),o(`span`,qs,E(e.agent),1)):s(`v-if`,!0),s(` 次数看总数,鼠标停上去看**分布** —— 119 次里 118 次都是 Bash
110
+ 和"改了三处代码",是完全不同的两件事,而一行放不下分布 `),e.toolCallCount?(j(),o(`span`,{key:2,title:e.toolMix||``},E(r.$t(`@WORKBENCH:工具 {n} 次`,{n:e.toolCallCount})),9,Js)):s(`v-if`,!0),s(` 静默只在**显然静默**时才有值(服务端有阈值),所以这里不用再过滤 `),typeof e.silentMs==`number`?(j(),o(`span`,Ys,E(r.$t(`@WORKBENCH:静默 {elapsed}`,{elapsed:r.formatDurationMs(e.silentMs)})),1)):s(`v-if`,!0)]),s(` 证据按可靠程度排:工具调用(正在做什么)→ 思考(为什么这么做)→ 正文。
111
+ 思考这一行是 2026-09-29 补的:很多任务一句正文都不写,只靠工具调用
112
+ 根本看不出它在干嘛,而它的思考当时就在库里 `),e.lastTool?(j(),o(`p`,{key:0,class:`rpt__line`,title:e.lastTool},E(e.lastTool),9,Xs)):s(`v-if`,!0),e.lastThought?(j(),o(`p`,{key:1,class:`rpt__line is-thought`,title:e.lastThought},[Y(`span`,Qs,E(r.$t(`@WORKBENCH:最近思考`)),1),V(E(e.lastThought),1)],8,Zs)):s(`v-if`,!0),e.lastLine?(j(),o(`p`,{key:2,class:`rpt__line`,title:e.lastLine},E(e.lastLine),9,$s)):s(`v-if`,!0)]))),128))])):s(`v-if`,!0)])):(j(),o(`li`,ec,E(r.$t(`@WORKBENCH:暂无进度报告`)),1))]),s(` 历史:一行一份,点一条就把它换到上面看。只在有两份以上时出现 ——
113
+ 只有一份时这个列表纯粹是噪音 `),(n.reports||[]).length>1?(j(),o(`div`,tc,[Y(`p`,nc,E(r.$t(`@WORKBENCH:历史报告`)),1),Y(`ul`,rc,[(j(!0),o(X,null,M(n.reports,e=>(j(),o(`li`,{key:e.id},[Y(`button`,{type:`button`,class:g([`oc__history-item`,{"is-active":e.id===r.currentReport?.id}]),onClick:t=>r.pickReport(e)},[Y(`span`,ac,E(r.clockFromIso(e.at)),1),Y(`span`,oc,E(r.reportBrief(e)),1)],10,ic)]))),128))])])):s(`v-if`,!0)],512),[[L,!n.collapsed&&r.mode===`command`]]),K(Y(`div`,sc,[Y(`p`,cc,[V(E(r.$t(`@WORKBENCH:项目概览`))+` `,1),s(` 无选中项目即「全部项目」:显式标出来,否则底下只剩「今日完成」一行,看着像数据没加载出来 `),Y(`span`,lc,E(n.selectedProject?n.selectedProject.name:r.$t(`@WORKBENCH:全部项目`)),1)]),Y(`dl`,uc,[(j(!0),o(X,null,M(r.gitSummary,e=>(j(),o(X,{key:e.label},[Y(`dt`,dc,E(e.label),1),Y(`dd`,{class:g([`oc__git-value`,{"is-warn":e.tone===`warn`,"is-danger":e.tone===`danger`}])},E(e.value),3)],64))),128)),Y(`dt`,fc,E(r.$t(`@WORKBENCH:今日完成`)),1),Y(`dd`,pc,E(n.todayDone),1),Y(`dt`,mc,E(r.$t(`@WORKBENCH:最后活跃`)),1),Y(`dd`,hc,E(n.selectedProject&&r.relativeTimeFromIso(n.selectedProject.stats.lastActiveAt)||`—`),1)])],512),[[L,!n.collapsed&&r.mode===`command`]]),K(Y(`div`,{class:`oc__compose`,onPaste:r.onPaste,onDrop:q(r.onDrop,[`prevent`]),onDragover:t[13]||=q(e=>r.attachDragging=!0,[`prevent`]),onDragleave:t[14]||=e=>r.attachDragging=!1},[s(` 粘贴事件必须同时挂在 textarea 上:在输入框里按 Ctrl+V 时事件只到 textarea,
114
+ 不会冒泡经过下面的附件区 `),K(Y(`textarea`,{ref:`inputRef`,class:g([`oc__input`,{"is-over":r.overLimit}]),"onUpdate:modelValue":t[6]||=e=>r.draft=e,style:m(r.inputStyle),rows:`4`,placeholder:r.$t(`@WORKBENCH:给主 Agent 下一条指令,例如:把登录模块的错误处理重构一遍`),onKeydown:r.onInputKeydown,onPaste:r.onPaste,onMousedown:r.onInputMouseDown},null,46,gc),[[R,r.draft]]),r.draftAttachments.length>0||r.attachBusy?(j(),k(r.AttachmentZone,{key:0,attachments:r.draftAttachments,"is-image":r.isImageAttachment,"human-size":r.humanSize,"is-uploading":r.attachBusy,"is-paste-hover":r.attachDragging,"on-pick":r.onPickAttachment,"on-remove":r.onRemoveAttachment,"raw-base":r.DRAFT_RAW_BASE,onPaste:r.onPaste,onDrop:r.onDrop,onDragover:t[7]||=q(e=>r.attachDragging=!0,[`prevent`]),onDragenter:t[8]||=q(e=>r.attachDragging=!0,[`prevent`]),onDragleave:t[9]||=e=>r.attachDragging=!1},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`])):s(`v-if`,!0),s(`
115
+ 字数:单独占输入框下方一行,不挤底部那一排按钮。
116
+ 空草稿时不渲染("0 / 100000" 是噪音),接近上限转黄、超了转红 ——
117
+ 目的是让"粘太长发不出去"在**点之前**看得见,而不是点完等服务端 400 才知道
118
+ (而超长恰恰是最容易失败的那一类,必须能改一改再发)。
119
+ `),r.draftChars>0?(j(),o(`p`,{key:1,class:g([`oc__count`,{"is-warn":r.nearLimit,"is-over":r.overLimit}])},[r.overLimit?(j(),o(`span`,_c,E(r.$t(`@WORKBENCH:超出上限 {max} 字,请精简后再派发(超出的部分不会被发出)`,{max:r.charLimit})),1)):(j(),o(`span`,vc,E(r.draftChars)+` / `+E(r.charLimit),1))],2)):s(`v-if`,!0),Y(`div`,yc,[Y(`button`,{type:`button`,class:`oc__attach`,disabled:r.attachBusy,title:r.$t(`@WORKBENCH:添加附件(也可直接粘贴或拖入文件)`),"aria-label":r.$t(`@WORKBENCH:添加附件`),onClick:r.onPickAttachment},[x(c,null,{default:G(()=>[x(r.Paperclip)]),_:1})],8,bc),s(` 默认提示词设置入口:图标按钮按项目惯例不加底色,
120
+ 有没有设过看右侧"附加默认提示词"那个勾选(它是真实生效状态,这个只是入口) `),Y(`button`,{type:`button`,class:g([`oc__attach`,{"is-on":r.anyPromptConfigured}]),title:r.$t(`@WORKBENCH:设置派发时自动附加的默认提示词(全局 / 各项目)`),"aria-label":r.$t(`@WORKBENCH:默认提示词设置`),onClick:t[10]||=e=>r.emit(`open-prompt-settings`)},[x(c,null,{default:G(()=>[x(r.Setting)]),_:1})],10,xc),Y(`label`,{class:`oc__autorn`,title:r.$t(`@WORKBENCH:取消勾选则只建任务草稿,不自动执行`)},[K(Y(`input`,{type:`checkbox`,"onUpdate:modelValue":t[11]||=e=>r.autoRun=e},null,512),[[le,r.autoRun]]),Y(`span`,null,E(r.$t(`@WORKBENCH:立即执行`)),1)],8,Sc),s(` 一条都没设过时不出现:一个永远勾着、点了也没区别的开关只会占地方 `),r.anyPromptConfigured?(j(),o(`label`,{key:0,class:`oc__autorn`,title:r.$t(`@WORKBENCH:取消勾选则本次派发的任务不带默认提示词(设置本身不受影响)`)},[K(Y(`input`,{type:`checkbox`,"onUpdate:modelValue":t[12]||=e=>r.useDefaultPrompt=e},null,512),[[le,r.useDefaultPrompt]]),Y(`span`,null,E(r.$t(`@WORKBENCH:默认提示词({state})`,{state:r.promptStateLabel})),1)],8,Cc)):s(`v-if`,!0),s(` 执行器:与工作台执行按钮、看板「执行」共用同一份选择。
121
+ 下拉本体收口在 TaskExecutorPicker(对话模式底下那个也是它),
122
+ 它自己读 composable 的共享状态,这里不用再传 v-model `),x(r.TaskExecutorPicker,{title:r.$t(`@WORKBENCH:本次派发使用的执行器(与执行按钮的临时切换共用)`)},null,8,[`title`]),Y(`button`,{type:`button`,class:`oc__send`,disabled:!r.canSend,onClick:r.send},[x(c,{class:`oc__send-icon`},{default:G(()=>[x(r.Promotion)]),_:1}),Y(`span`,null,E(n.dispatching?r.$t(`@WORKBENCH:派发中…`):r.$t(`@WORKBENCH:派发`)),1)],8,wc)]),Y(`p`,Tc,[n.selectedProject?(j(),o(X,{key:0},[V(E(r.$t(`@WORKBENCH:指令会在「{name}」下新建一个任务;Enter 派发,Shift+Enter 换行`,{name:n.selectedProject.name})),1)],64)):(j(),o(X,{key:1},[V(E(r.$t(`@WORKBENCH:指令落到哪个项目由主 Agent 判断;Enter 派发,Shift+Enter 换行`)),1)],64))])],544),[[L,!n.collapsed&&r.mode===`command`]])],2)}var Dc=Q(_s,[[`render`,Ec],[`__scopeId`,`data-v-4c030231`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/OrchestratorConsole.vue`]]);D(),F();var Oc=4e3,kc=T({__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,o=J(``),s=J(``);B(()=>r.modelValue,e=>{e&&(o.value=r.defaultPrompt||``,s.value=r.projectPrompt||``)});let c=a(()=>!!r.projectPath),l=a(()=>o.value.trim()!==(r.defaultPrompt||``).trim()||c.value&&s.value.trim()!==(r.projectPrompt||``).trim());function u(){r.saving||i(`save`,{globalPrompt:o.value,projectPrompt:s.value})}function d(){i(`update:modelValue`,!1)}let f={props:r,emit:i,MAX_CHARS:Oc,globalDraft:o,projectDraft:s,hasProject:c,dirty:l,submit:u,close:d,get $t(){return Z},CommonDialog:Re};return Object.defineProperty(f,"__isScriptSetup",{enumerable:!1,value:!0}),f}});S(),D(),H();var Ac={class:`pd`},jc={class:`pd__intro`},Mc={class:`pd__field`},Nc={class:`pd__head`},Pc={class:`pd__label`,for:`pd-global`},Fc={class:`pd__count`},Ic=[`placeholder`],Lc={class:`pd__field`},Rc={class:`pd__head`},zc={class:`pd__label`,for:`pd-project`},Bc={key:0,class:`pd__count`},Vc=[`disabled`,`placeholder`],Hc={class:`pd__hint`},Uc={class:`pd__foot`},Wc=[`disabled`];function Gc(e,t,n,r,i,a){return j(),k(r.CommonDialog,{"model-value":n.modelValue,title:r.$t(`@WORKBENCH:默认提示词`),width:`min(640px, 94vw)`,"close-on-click-modal":!1,"onUpdate:modelValue":t[2]||=e=>r.emit(`update:modelValue`,e)},{footer:G(()=>[Y(`div`,Uc,[Y(`button`,{type:`button`,class:`pd__btn`,onClick:r.close},E(r.$t(`@WORKBENCH:取消`)),1),t[3]||=Y(`span`,{class:`pd__foot-spacer`},null,-1),Y(`button`,{type:`button`,class:`pd__btn pd__btn--primary`,disabled:n.saving||!r.dirty,onClick:r.submit},E(n.saving?r.$t(`@WORKBENCH:保存中…`):r.$t(`@WORKBENCH:保存`)),9,Wc)])]),default:G(()=>[Y(`div`,Ac,[Y(`p`,jc,E(r.$t(`@WORKBENCH:派发指令时自动附加在指令之前,让每个任务都带上这些约束。只影响之后派发的任务,不会改动已经建好的任务。`)),1),Y(`div`,Mc,[Y(`div`,Nc,[Y(`label`,Pc,E(r.$t(`@WORKBENCH:全局默认提示词`)),1),Y(`span`,Fc,E(r.globalDraft.length)+` / `+E(r.MAX_CHARS),1)]),K(Y(`textarea`,{id:`pd-global`,"onUpdate:modelValue":t[0]||=e=>r.globalDraft=e,class:`pd__area`,rows:`5`,maxlength:r.MAX_CHARS,placeholder:r.$t(`@WORKBENCH:对所有项目生效。例如:回答用中文;改完代码必须跑一遍测试;不要动 dist 目录`)},null,8,Ic),[[R,r.globalDraft]])]),Y(`div`,Lc,[Y(`div`,Rc,[Y(`label`,zc,E(r.hasProject?r.$t(`@WORKBENCH:「{name}」的项目提示词`,{name:n.projectName}):r.$t(`@WORKBENCH:项目提示词`)),1),r.hasProject?(j(),o(`span`,Bc,E(r.projectDraft.length)+` / `+E(r.MAX_CHARS),1)):s(`v-if`,!0)]),K(Y(`textarea`,{id:`pd-project`,"onUpdate:modelValue":t[1]||=e=>r.projectDraft=e,class:`pd__area`,rows:`5`,maxlength:r.MAX_CHARS,disabled:!r.hasProject,placeholder:r.hasProject?r.$t(`@WORKBENCH:只在这个项目派发时附加。例如:包管理器用 pnpm;改动集中在 src/ui 下`):r.$t(`@WORKBENCH:先在左侧选中一个具体项目,才能设置它的提示词`)},null,8,Vc),[[R,r.projectDraft]]),Y(`p`,Hc,E(r.hasProject?r.$t(`@WORKBENCH:项目提示词追加在全局提示词之后(不覆盖全局),派发到「{name}」时一起带上`,{name:n.projectName}):r.$t(`@WORKBENCH:选中的是「全部项目」,落点由主 Agent 判断 —— 想给某个项目单设提示词,先选中它`)),1)])])]),_:1},8,[`model-value`,`title`])}var Kc=Q(kc,[[`render`,Gc],[`__scopeId`,`data-v-766f470f`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchDefaultPromptDialog.vue`]]);D(),F();var qc=T({__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,o=J(``),s=J(``),c=J(``),l=J(!1),u=J(``);function d(e){let t=$(e);if(!t)return``;let n=r.projects.find(e=>$(e.path)===t);return n?n.path:``}B(()=>r.modelValue,e=>{e&&(o.value=``,s.value=``,c.value=d(r.defaultProjectPath),u.value=``,l.value=!1)});let f=a(()=>r.projects),p=a(()=>!l.value&&(o.value.trim().length>0||s.value.trim().length>0)),m=a(()=>{let e=$(c.value);if(!e)return``;let t=f.value.find(t=>$(t.path)===e);return t?t.name:``});async function h(e){if(p.value){l.value=!0,u.value=``;try{let t={title:o.value.trim(),desc:s.value,promptId:null,simpleOverride:``};c.value&&(t.projectPath=c.value);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){u.value=n?.error||Z(`@WORKBENCH:保存失败`);return}i(`update:modelValue`,!1),i(`created`,{task:n.task,openEditor:e})}finally{l.value=!1}}}let g={props:r,emit:i,title:o,desc:s,projectPath:c,submitting:l,error:u,matchOptionPath:d,projectOptions:f,canSubmit:p,projectName:m,submit:h,get $t(){return Z},CommonDialog:Re};return Object.defineProperty(g,"__isScriptSetup",{enumerable:!1,value:!0}),g}});S(),D(),H();var Jc={class:`nc`},Yc={class:`nc__field`},Xc={class:`nc__label`,for:`nc-project`},Zc={value:``},Qc=[`value`],$c=[`title`],el={class:`nc__field`},tl={class:`nc__label`,for:`nc-title`},nl=[`placeholder`],rl={class:`nc__field`},il={class:`nc__label`,for:`nc-desc`},al=[`placeholder`],ol={key:0,class:`nc__error`},sl={class:`nc__foot`},cl=[`disabled`],ll=[`disabled`];function ul(e,t,n,r,i,a){return j(),k(r.CommonDialog,{"model-value":n.modelValue,title:r.$t(`@WORKBENCH:新建开发任务`),width:`min(600px, 94vw)`,"close-on-click-modal":!1,"onUpdate:modelValue":t[9]||=e=>r.emit(`update:modelValue`,e)},{footer:G(()=>[Y(`div`,sl,[Y(`button`,{type:`button`,class:`nc__btn`,onClick:t[6]||=e=>r.emit(`update:modelValue`,!1)},E(r.$t(`@WORKBENCH:取消`)),1),t[10]||=Y(`span`,{class:`nc__foot-spacer`},null,-1),Y(`button`,{type:`button`,class:`nc__btn`,disabled:!r.canSubmit,onClick:t[7]||=e=>r.submit(!0)},E(r.$t(`@WORKBENCH:创建并打开编辑器`)),9,cl),Y(`button`,{type:`button`,class:`nc__btn nc__btn--primary`,disabled:!r.canSubmit,onClick:t[8]||=e=>r.submit(!1)},E(r.submitting?r.$t(`@WORKBENCH:创建中…`):r.$t(`@WORKBENCH:创建`)),9,ll)])]),default:G(()=>[Y(`div`,Jc,[Y(`div`,Yc,[Y(`label`,Xc,E(r.$t(`@WORKBENCH:项目`)),1),K(Y(`select`,{id:`nc-project`,"onUpdate:modelValue":t[0]||=e=>r.projectPath=e,class:`nc__select`},[Y(`option`,Zc,E(r.$t(`@WORKBENCH:跟随当前项目`)),1),(j(!0),o(X,null,M(r.projectOptions,e=>(j(),o(`option`,{key:e.key,value:e.path},E(e.name)+E(e.exists===!1?` · ${r.$t(`@WORKBENCH:目录不存在`)}`:``),9,Qc))),128))],512),[[W,r.projectPath]]),Y(`p`,{class:`nc__hint`,title:r.projectPath},E(r.projectName?r.$t(`@WORKBENCH:任务会在「{name}」目录下执行`,{name:r.projectName}):r.$t(`@WORKBENCH:任务会跟随应用当前的工作目录`)),9,$c)]),Y(`div`,el,[Y(`label`,tl,E(r.$t(`@WORKBENCH:标题`)),1),K(Y(`input`,{id:`nc-title`,"onUpdate:modelValue":t[1]||=e=>r.title=e,class:`nc__input`,type:`text`,maxlength:`200`,placeholder:r.$t(`@WORKBENCH:一句话说清要做什么`),onKeydown:t[2]||=P(q(e=>r.submit(!1),[`prevent`]),[`enter`])},null,40,nl),[[R,r.title]])]),Y(`div`,rl,[Y(`label`,il,E(r.$t(`@WORKBENCH:描述`)),1),K(Y(`textarea`,{id:`nc-desc`,"onUpdate:modelValue":t[3]||=e=>r.desc=e,class:`nc__input nc__input--area`,rows:`6`,placeholder:r.$t(`@WORKBENCH:把背景、验收标准、相关文件路径写进来,执行时用它当上下文`),onKeydown:[t[4]||=P(q(e=>r.submit(!1),[`ctrl`,`prevent`]),[`enter`]),t[5]||=P(q(e=>r.submit(!1),[`meta`,`prevent`]),[`enter`])]},null,40,al),[[R,r.desc]])]),r.error?(j(),o(`p`,ol,E(r.error),1)):s(`v-if`,!0)])]),_:1},8,[`model-value`,`title`])}var dl=Q(qc,[[`render`,ul],[`__scopeId`,`data-v-c60e660a`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchTaskCreateDialog.vue`]]);D(),F();var fl=`wb.boardProject.v1`,pl=5e3,ml=3e4,hl=`wb.boardLayout.v1`,gl=180,_l=420,vl=260,yl=900,bl=.26,xl=.46,Sl=T({__name:`WorkbenchBoard`,props:{openedTaskId:{type:[String,null],required:!0}},emits:[`open-task`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,{projects:o,boardTasks:s,currentProjectPath:c,loading:l,loadProjects:d}=Rr(),{active:f,activity:p,running:m,dispatching:h,togglingSchedule:g,maxInstructionChars:_,defaultPrompt:v,projectPrompts:y,reports:b,generatingReport:x,reportIntervalMs:S,loadOrchestrator:C,setSchedulingActive:w,dispatch:T,saveDefaultPrompt:E,saveProjectPrompt:D,loadReports:O,generateReport:k,setReportInterval:ee}=Kr(),{active:te}=Yn(),ne=(()=>{try{return localStorage.getItem(fl)}catch{return null}})(),A=J(ne||``);B(A,e=>{try{localStorage.setItem(fl,e)}catch{}});let re=a(()=>A.value&&o.value.find(e=>e.key===A.value)||null);B(o,e=>{A.value&&(e.some(e=>e.key===A.value)||(A.value=``))});let j=!1;function M(){if(j||(j=!0,ne!==null))return;let e=c.value?$(c.value):``;e&&o.value.some(t=>t.key===e)&&(A.value=e)}let N=a(()=>{let e=new Map(o.value.map(e=>[e.key,e.name])),t={};for(let n of s.value)n.projectPath&&(t[n.projectPath]=e.get($(n.projectPath))||``);return t}),P=a(()=>{if(!A.value)return s.value;let e=A.value;return s.value.filter(t=>$(t.projectPath)===e)}),ae=a(()=>{let e=new Date;e.setHours(0,0,0,0);let t=e.getTime();return{projects:o.value.length,tasks:s.value.length,running:m.value.length,todayDone:p.value.filter(e=>e.kind===`done`&&e.at&&new Date(e.at).getTime()>=t).length}});function oe(e){i(`open-task`,{taskId:e.id,projectPath:e.projectPath})}let se=null,F=!1,ce=null;async function I(e=!0){if(!F){F=!0;try{await Promise.all([d(e),C(e)])}finally{F=!1}}}function le(){document.hidden||(I(!0),O(!0))}he(async()=>{window.addEventListener(`resize`,H),await I(!1),O(!0),M(),se=setInterval(()=>{document.hidden||I(!0)},pl),ce=setInterval(()=>{document.hidden||O(!0)},ml),document.addEventListener(`visibilitychange`,le)}),u(()=>{window.removeEventListener(`resize`,H),se&&=(clearInterval(se),null),ce&&=(clearInterval(ce),null),document.removeEventListener(`visibilitychange`,le)});let L=ue({left:null,right:null,leftCollapsed:!1,rightCollapsed:!1});function R(){try{let e=localStorage.getItem(hl);if(!e)return;let t=JSON.parse(e);typeof t.left==`number`&&Number.isFinite(t.left)&&(L.left=t.left),typeof t.right==`number`&&Number.isFinite(t.right)&&(L.right=t.right),L.leftCollapsed=t.leftCollapsed===!0,L.rightCollapsed=t.rightCollapsed===!0}catch{}}R();function fe(){try{localStorage.setItem(hl,JSON.stringify(L))}catch{}}let V=J(typeof window>`u`?1920:window.innerWidth);function H(){V.value=window.innerWidth}let U=a(()=>V.value<=1024),W=a(()=>V.value<=860);function G(e,t){let n=e===`left`?gl:vl,r=Math.min(e===`left`?_l:yl,V.value*(e===`left`?bl:xl));return Math.round(Math.min(Math.max(t,n),Math.max(n,r)))}let pe=a(()=>{let e={};return L.left!=null&&(e[`--wb-left-w`]=G(`left`,L.left)+`px`),L.right!=null&&!W.value&&(e[`--wb-right-w`]=G(`right`,L.right)+`px`),e}),me=J(null),_e=J(null);function K(e){return me.value?.querySelector(e===`left`?`.board__left`:`.oc`)}function ve(e){window.removeEventListener(`mousemove`,e),document.body.style.userSelect=``,document.body.style.cursor=``,_e.value=null,fe()}function ye(e,t){if(e===`left`?U.value:W.value)return;let n=K(e);if(!n)return;t.preventDefault();let r=t.clientX,i=n.getBoundingClientRect().width;_e.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);L[e]=G(e,i+n)};window.addEventListener(`mousemove`,a),window.addEventListener(`mouseup`,()=>ve(a),{once:!0})}function q(e){L[e]=null,fe()}let be=J(!1),Y=a(()=>U.value?!be.value:L.leftCollapsed);function xe(){if(U.value){be.value=!be.value;return}L.leftCollapsed=!L.leftCollapsed,fe()}function Se(){U.value&&(be.value=!1)}let Ce=a(()=>L.rightCollapsed&&!W.value);function we(){L.rightCollapsed=!L.rightCollapsed,fe()}function X(e){A.value=e?e.key:``,be.value=!1}let Te=J(!1);function Ee(){Te.value=!0}async function De(e){if(await I(!0),e.openEditor){i(`open-task`,{taskId:e.task.id,projectPath:e.task.projectPath||``});return}z.success(Z(`@WORKBENCH:已创建任务`))}async function Oe(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){z.error(n?.error||Z(`@WORKBENCH:执行失败`));return}z.success(Z(`@WORKBENCH:已开始执行`)),await I(!0)}async function ke(e){let t=(e.title||``).trim()||Z(`@WORKBENCH:未命名任务`);try{await ge.confirm(Z(`@WORKBENCH:删除任务「{title}」?`,{title:t}),Z(`@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){z.error(n.error||Z(`@WORKBENCH:删除失败`));return}await I(!0)}let Ae=J(null),Q=a(()=>re.value?.path||c.value);async function je(e){let t=await T({text:e.text,projectPath:e.projectPath,autoRun:e.autoRun,attachments:e.attachments,useDefaultPrompt:e.useDefaultPrompt,executor:e.executor});t&&(Ae.value?.clearAttachments(),Ae.value?.clearDraft(),z.success(t.ran?Z(`@WORKBENCH:已派发并开始执行`):Z(`@WORKBENCH:已派发(只建任务未执行)`)),await I(!0))}async function Me(e){await w(e)}let Ne=J(!1),Pe=J(!1),Fe=a(()=>{let e=re.value?.key;return e&&y.value?.[e]?.prompt||``});async function Ie(e){if(Pe.value)return;let t=e.globalPrompt.trim(),n=e.projectPrompt.trim(),r=re.value;Pe.value=!0;try{let e=!0;t!==(v.value||``).trim()&&(e=await E(t)),e&&r&&n!==Fe.value.trim()&&(e=await D(r.path,n)),e&&(Ne.value=!1)}finally{Pe.value=!1}}let Le={props:r,emit:i,projects:o,boardTasks:s,currentProjectPath:c,loading:l,loadProjects:d,active:f,activity:p,running:m,dispatching:h,togglingSchedule:g,maxInstructionChars:_,defaultPrompt:v,projectPrompts:y,reports:b,generatingReport:x,reportIntervalMs:S,loadOrchestrator:C,setSchedulingActive:w,dispatch:T,saveDefaultPrompt:E,saveProjectPrompt:D,loadReports:O,generateReport:k,setReportInterval:ee,boardExecutor:te,SELECTED_KEY:fl,savedSelection:ne,selectedKey:A,selectedProject:re,get defaultSelectionApplied(){return j},set defaultSelectionApplied(e){j=e},applyDefaultSelection:M,projectLabels:N,visibleTasks:P,headerStats:ae,onOpenTask:oe,POLL_MS:pl,get pollTimer(){return se},set pollTimer(e){se=e},get inFlight(){return F},set inFlight(e){F=e},REPORT_POLL_MS:ml,get reportPollTimer(){return ce},set reportPollTimer(e){ce=e},refresh:I,onVisibilityChange:le,LAYOUT_KEY:hl,LEFT_W_MIN:gl,LEFT_W_MAX:_l,RIGHT_W_MIN:vl,RIGHT_W_MAX:yl,LEFT_W_SHARE:bl,RIGHT_W_SHARE:xl,layout:L,readLayout:R,saveLayout:fe,viewportW:V,onWindowResize:H,isNarrow:U,isStacked:W,clampWidth:G,boardStyle:pe,colsRef:me,dragging:_e,panelEl:K,endDrag:ve,onSplitterMouseDown:ye,onSplitterDblClick:q,leftDrawerOpen:be,leftHidden:Y,toggleLeft:xe,onLeftEsc:Se,rightHidden:Ce,toggleRight:we,onSelectProject:X,createOpen:Te,onCreateClick:Ee,onTaskCreated:De,runTask:Oe,deleteTask:ke,consoleRef:Ae,defaultProjectPath:Q,onDispatch:je,onToggleSchedule:Me,promptDialogOpen:Ne,savingPrompt:Pe,selectedProjectPrompt:Fe,onSavePromptDraft:Ie,get $t(){return Z},get Fold(){return ie},get Expand(){return de},WorkbenchProjectPanel:Ma,WorkbenchKanban:Vo,OrchestratorConsole:Dc,WorkbenchDefaultPromptDialog:Kc,WorkbenchTaskCreateDialog:dl};return Object.defineProperty(Le,"__isScriptSetup",{enumerable:!1,value:!0}),Le}});D(),S(),H();var Cl={class:`board__top`},wl=[`title`,`aria-label`,`aria-expanded`],Tl={class:`board__brand`},El={class:`board__brand-text`},Dl={class:`board__title`},Ol={class:`board__subtitle`},kl={class:`board__stats`},Al={class:`board__stat`},jl={class:`board__stat-label`},Ml={class:`board__stat-value`},Nl={class:`board__stat`},Pl={class:`board__stat-label`},Fl={class:`board__stat-value`},Il={class:`board__stat`},Ll={class:`board__stat-label`},Rl={class:`board__stat`},zl={class:`board__stat-label`},Bl={class:`board__stat-value`},Vl=[`title`],Hl={class:`board__main`},Ul={class:`board__main-head`},Wl={class:`board__main-title`},Gl={class:`board__project-name`},Kl=[`title`],ql={key:1,class:`board__project-path`},Jl={key:0,class:`board__project-meta`},Yl=[`title`];function Xl(e,t,n,r,i,a){let c=h;return j(),o(`div`,{class:`board`,style:m(r.boardStyle)},[Y(`header`,Cl,[s(` 左栏的开合。宽屏=收起/展开常驻那一栏;窄屏=抽屉 `),Y(`button`,{type:`button`,class:g([`board__icon-btn board__fold-btn`,{"is-on":!r.leftHidden}]),title:r.leftHidden?r.$t(`@WORKBENCH:展开项目列表`):r.$t(`@WORKBENCH:收起项目列表`),"aria-label":r.leftHidden?r.$t(`@WORKBENCH:展开项目列表`):r.$t(`@WORKBENCH:收起项目列表`),"aria-expanded":!r.leftHidden,onClick:r.toggleLeft},[r.leftHidden?(j(),k(c,{key:1},{default:G(()=>[x(r.Expand)]),_:1})):(j(),k(c,{key:0},{default:G(()=>[x(r.Fold)]),_:1}))],10,wl),Y(`div`,Tl,[Y(`span`,{class:g([`board__live`,{"is-off":!r.active}]),"aria-hidden":`true`},null,2),Y(`div`,El,[Y(`h1`,Dl,E(r.$t(`@WORKBENCH:多项目编排台`)),1),Y(`p`,Ol,E(r.active?r.$t(`@WORKBENCH:主 Agent 调度中`):r.$t(`@WORKBENCH:主 Agent 已暂停`)),1)])]),Y(`div`,kl,[Y(`span`,Al,[Y(`span`,jl,E(r.$t(`@WORKBENCH:项目`)),1),Y(`strong`,Ml,E(r.headerStats.projects),1)]),Y(`span`,Nl,[Y(`span`,Pl,E(r.$t(`@WORKBENCH:任务`)),1),Y(`strong`,Fl,E(r.headerStats.tasks),1)]),Y(`span`,Il,[Y(`span`,Ll,E(r.$t(`@WORKBENCH:活跃执行`)),1),Y(`strong`,{class:g([`board__stat-value`,{"is-live":r.headerStats.running>0}])},E(r.headerStats.running),3)]),Y(`span`,Rl,[Y(`span`,zl,E(r.$t(`@WORKBENCH:今日完成`)),1),Y(`strong`,Bl,E(r.headerStats.todayDone),1)])])]),Y(`div`,{ref:`colsRef`,class:g([`board__cols`,{"is-resizing":r.dragging!==null}])},[s(` 抽屉打开时的点击捕获层:点空白处收起。
123
+ 只在窄屏 + 打开时才 display:block(见媒体查询),宽屏下是个不占位的空 div。
124
+ 不加遮罩底色而是全透明 —— 只是为了接住点击,不是为了压暗看板;
125
+ 真要压暗就得处理深色主题下半透明背景叠不实的老问题(见 NOTES §2)。 `),Y(`div`,{class:g([`board__scrim`,{"is-on":r.leftDrawerOpen}]),"aria-hidden":`true`,onClick:t[0]||=e=>r.leftDrawerOpen=!1},null,2),Y(`aside`,{class:g([`board__left`,{"is-collapsed":r.leftHidden}]),onKeydown:P(r.onLeftEsc,[`esc`])},[x(r.WorkbenchProjectPanel,{projects:r.projects,"selected-key":r.selectedKey,loading:r.loading,onSelect:r.onSelectProject},null,8,[`projects`,`selected-key`,`loading`])],34),s(` 左栏分隔条:左栏收起 / 窄屏抽屉模式下不占位(不渲染 / 媒体查询里 display:none) `),r.leftHidden?s(`v-if`,!0):(j(),o(`div`,{key:0,class:`board__splitter board__splitter--left`,role:`separator`,"aria-orientation":`vertical`,title:r.$t(`@WORKBENCH:拖动调整项目列表宽度,双击恢复默认`),onMousedown:t[1]||=e=>r.onSplitterMouseDown(`left`,e),onDblclick:t[2]||=e=>r.onSplitterDblClick(`left`)},null,40,Vl)),Y(`main`,Hl,[Y(`div`,Ul,[Y(`div`,Wl,[Y(`h2`,Gl,E(r.selectedProject?r.selectedProject.name:r.$t(`@WORKBENCH:全部项目`)),1),r.selectedProject?(j(),o(`span`,{key:0,class:`board__project-path`,title:r.selectedProject.path},E(r.selectedProject.path),9,Kl)):(j(),o(`span`,ql,E(r.$t(`@WORKBENCH:共 {n} 个项目的任务`,{n:r.projects.length})),1))]),r.selectedProject?(j(),o(`span`,Jl,E(r.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:r.selectedProject.stats.done,total:r.selectedProject.stats.total})),1)):s(`v-if`,!0)]),x(r.WorkbenchKanban,{tasks:r.visibleTasks,"project-labels":r.projectLabels,"show-project-label":!r.selectedProject,"opened-task-id":r.props.openedTaskId,onOpenTask:r.onOpenTask,onRunTask:r.runTask,onDeleteTask:r.deleteTask,onCreateTask:r.onCreateClick},null,8,[`tasks`,`project-labels`,`show-project-label`,`opened-task-id`])]),s(` 右栏分隔条:右栏收起 / 竖排(≤860)时不占位 `),!r.rightHidden&&!r.isStacked?(j(),o(`div`,{key:1,class:`board__splitter board__splitter--right`,role:`separator`,"aria-orientation":`vertical`,title:r.$t(`@WORKBENCH:拖动调整主 Agent 控制台宽度,双击恢复默认`),onMousedown:t[3]||=e=>r.onSplitterMouseDown(`right`,e),onDblclick:t[4]||=e=>r.onSplitterDblClick(`right`)},null,40,Yl)):s(`v-if`,!0),x(r.OrchestratorConsole,{ref:`consoleRef`,active:r.active,"running-count":r.running.length,"selected-project":r.selectedProject,dispatching:r.dispatching,"toggling-schedule":r.togglingSchedule,"today-done":r.headerStats.todayDone,collapsed:r.rightHidden,"default-prompt":r.defaultPrompt,"project-prompts":r.projectPrompts,reports:r.reports,"report-interval-ms":r.reportIntervalMs,"generating-report":r.generatingReport,"max-instruction-chars":r.maxInstructionChars,onToggleCollapse:r.toggleRight,onToggleSchedule:r.onToggleSchedule,onDispatch:r.onDispatch,onGenerateReport:r.generateReport,onSetReportInterval:r.setReportInterval,onOpenPromptSettings:t[5]||=e=>r.promptDialogOpen=!0},null,8,[`active`,`running-count`,`selected-project`,`dispatching`,`toggling-schedule`,`today-done`,`collapsed`,`default-prompt`,`project-prompts`,`reports`,`report-interval-ms`,`generating-report`,`max-instruction-chars`,`onGenerateReport`,`onSetReportInterval`])],2),s(` 派发默认提示词:全局一条 + 选中项目一条,写完即生效于之后的派发 `),x(r.WorkbenchDefaultPromptDialog,{modelValue:r.promptDialogOpen,"onUpdate:modelValue":t[6]||=e=>r.promptDialogOpen=e,"default-prompt":r.defaultPrompt,"project-path":r.selectedProject?.path||``,"project-name":r.selectedProject?.name||``,"project-prompt":r.selectedProjectPrompt,saving:r.savingPrompt,onSave:r.onSavePromptDraft},null,8,[`modelValue`,`default-prompt`,`project-path`,`project-name`,`project-prompt`,`saving`]),s(` 新建任务:弹窗里问清字段,建完就关 `),x(r.WorkbenchTaskCreateDialog,{modelValue:r.createOpen,"onUpdate:modelValue":t[7]||=e=>r.createOpen=e,projects:r.projects,"default-project-path":r.defaultProjectPath,onCreated:r.onTaskCreated},null,8,[`modelValue`,`projects`,`default-project-path`])],4)}var Zl=Q(Sl,[[`render`,Xl],[`__scopeId`,`data-v-dd2dc7b4`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/components/WorkbenchBoard.vue`]]);D(),F();var Ql=`wb.lastTaskByProject.v1`,$l=`__no_project__`,eu=`wb.sidebarWidth.v1`,tu=200,nu=480,ru=268,iu=3e3,au=52,ou=320,su=500,cu=T({__name:`WorkbenchView`,setup(t,{expose:n}){n();let r=Fe(),i=Ie(),o=J((()=>{try{let e=parseInt(localStorage.getItem(eu)||``,10);return Number.isFinite(e)?Math.min(nu,Math.max(tu,e)):ru}catch{return ru}})());function s(e){e.preventDefault();let t=e.clientX,n=o.value;document.body.style.userSelect=`none`,document.body.style.cursor=`col-resize`;let r=e=>{o.value=Math.min(nu,Math.max(tu,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(eu,String(o.value))}catch{}},{once:!0})}function c(e){o.value=Math.min(nu,Math.max(tu,o.value+e));try{localStorage.setItem(eu,String(o.value))}catch{}}function l(){try{let e=localStorage.getItem(Ql),t=e?JSON.parse(e):{};return t&&typeof t==`object`&&!Array.isArray(t)?t:{}}catch{return{}}}function f(e){try{localStorage.setItem(Ql,JSON.stringify(e))}catch{}}function m(e,t){let n=l();n[e||$l]=t,f(n)}let h=J(!1);function g(){h.value=!1}let _=J(null);async function v(e){await ee(),M.value=e.taskId,_.value=e.taskId,ae(),N.value&&m($(S.value.path),e.taskId),h.value=!0}let{prompts:y,tasks:b,jobs:x,currentProject:S,syncRunningCount:C,connectSSE:w,disconnectSSE:T,loadPrompts:E,loadCurrentProject:D,loadJobs:O,clearJobsByTask:k,loadTasks:ee}=Xn();function te(){let e=$(S.value.path),t=b.value.filter(t=>!t.projectPath||$(t.projectPath)===e),n=l(),r=e&&n[e]||!e&&n[$l]||``,i=r?b.value.find(e=>e.id===r):null,a=t[0]||b.value[0]||null,o=i&&i.projectPath&&$(i.projectPath)!==e?null:i?i.id:a?a.id:null;M.value=o,ae()}async function ne(){let e=M.value;if(await ee(),e&&b.value.some(t=>t.id===e)){ae();return}te()}async function A(){await ee(),te()}let j=J(!1),M=J(null),N=a(()=>b.value.find(e=>e.id===M.value)||null),P=a(()=>{let e=N.value?.projectPath||``;return!e||$(e)===$(S.value.path)?null:{name:e.replace(/[\\/]+$/,``).split(/[\\/]/).pop()||e,path:e}}),ie=J({title:``,desc:``,promptId:null,simpleOverride:``});function ae(){N.value?ie.value={title:N.value.title,desc:N.value.desc,promptId:N.value.promptId,simpleOverride:N.value.simpleOverride||``}:ie.value={title:``,desc:``,promptId:null,simpleOverride:``}}let oe=J(`idle`),se=J(0),F=null,I=a(()=>{if(!N.value)return!1;let e=N.value;return ie.value.title!==e.title||ie.value.desc!==e.desc||ie.value.promptId!==e.promptId||ie.value.simpleOverride!==(e.simpleOverride||``)});function le(){F!==null&&(clearTimeout(F),F=null)}function L(e){return!(!e||(e.title||``).trim()||(e.desc||``).trim()||e.promptId||(e.simpleOverride||``).trim()||Array.isArray(e.attachments)&&e.attachments.length>0)}async function R(e){try{await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`})}catch{}let t=b.value.findIndex(t=>t.id===e.id);t!==-1&&b.value.splice(t,1)}async function de(){let e=b.value.filter(e=>e.id!==M.value&&L(e));for(let t of e)await R(t)}async function fe(){if(!N.value)return!1;if(!I.value)return!0;if(oe.value=`saving`,await at(!1))return se.value=Date.now(),oe.value=`saved`,setTimeout(()=>{oe.value===`saved`&&Date.now()-se.value>=4e3&&(oe.value=`idle`)},4e3),!0;oe.value=`error`;let e=Date.now();return setTimeout(()=>{oe.value===`error`&&Date.now()-e>=4e3&&(oe.value=`idle`)},4e3),!1}B(()=>N.value?{id:N.value.id,title:N.value.title,desc:N.value.desc,promptId:N.value.promptId,simpleOverride:N.value.simpleOverride||``}:null,(e,t)=>{e&&t&&e.id===t.id&&(F!==null&&clearTimeout(F),F=window.setTimeout(()=>{fe()},1500))},{deep:!0}),B(M,async(e,t)=>{le(),N.value&&I.value&&await fe()}),B(S,async e=>{if(!e.path)return;let t=$(e.path),n=N.value;n&&n.projectPath&&$(n.projectPath)!==t&&await A()});function V(e){try{let t=new Blob([JSON.stringify(e)],{type:`application/json`});navigator.sendBeacon?.(`/api/workbench/tasks`,t)}catch{}}function H(){N.value&&I.value&&!L(N.value)&&V(N.value)}let U=ue({visible:!1,editing:null,name:``,content:``,aiLoading:!1,projectPath:``}),W=ue({visible:!1,text:``,loading:!1,saving:!1}),G=J(!0),K=a(()=>{let e=$(S.value.path);return y.value.filter(t=>!t.projectPath||$(t.projectPath)===e)});async function ye(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 q=J(null),be=J(null);async function Y(e){if(e){if(!await ye((e.title||``).trim()||Z(`@WORKBENCH:未命名任务`))){z.error(Z(`@WORKBENCH:复制失败`));return}q.value=e.id,z.success(Z(`@WORKBENCH:已复制任务标题`)),window.setTimeout(()=>{q.value===e.id&&(q.value=null)},1500)}}async function xe(e){if(!e)return;let t=(e.desc||``).trim();if(!t){z.warning(Z(`@WORKBENCH:任务描述为空,无需复制`));return}if(!await ye(t)){z.error(Z(`@WORKBENCH:复制失败`));return}be.value=e.id,z.success(Z(`@WORKBENCH:已复制任务描述`)),window.setTimeout(()=>{be.value===e.id&&(be.value=null)},1500)}let{simpleConversationMessages:Se,simpleAllJobsFor:Ce,simpleJobFor:we,simpleJobState:X}=qn(x,N),Te=[`wheel`,`touchstart`,`pointerdown`,`keydown`],De=J(null),Oe=J(null),ke=null,Q=null,je=null;function Me(){if(ke&&=(ke.disconnect(),null),Q!==null&&(clearTimeout(Q),Q=null),je){for(let e of Te)je.removeEventListener(e,Me);je=null}}function Le(){Me();let e=De.value;if(!e)return;e.scrollToBottom?.(!1);let t=Oe.value?.querySelector(`.acu-message-list`);if(!(!t||typeof ResizeObserver>`u`)){je=t;for(let e of Te)t.addEventListener(e,Me,{passive:!0});ke=new ResizeObserver(()=>De.value?.scrollToBottom?.(!1)),ke.observe(t),t.firstElementChild&&ke.observe(t.firstElementChild),Q=setTimeout(Me,iu)}}let ze=a(()=>h.value&&N.value&&Ce(N.value).length>0?N.value.id:``);B(ze,async e=>{Me(),e&&(await d(),Le())}),u(Me);function Be(e){if(!e)return!1;let t=we(e);return!!t&&(t.status===`running`||t.status===`pending`)}function Ve(){U.editing=null,U.name=``,U.content=``,U.aiLoading=!1,U.projectPath=(S.value.path||``).trim(),U.visible=!0}function He(e){U.editing=e,U.name=e.name,U.content=e.content,U.aiLoading=!1,U.projectPath=(e.projectPath||``).trim(),U.visible=!0}async function Ue(){if(!U.aiLoading){U.aiLoading=!0;try{let e=await fetch(`/api/workbench/prompts/ai-generate`,{method:`POST`}).then(e=>e.json());e.success?(U.name=e.name||U.name,U.content=e.result||``,z.success(Z(`@WORKBENCH:已生成,可继续编辑`))):z.error(e.error||Z(`@WORKBENCH:生成失败`))}catch(e){z.error(Z(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}finally{U.aiLoading=!1}}}async function We(){W.visible=!0,W.loading=!0;try{let e=await fetch(`/api/workbench/prompts/ai-instruction`).then(e=>e.json());e.success?W.text=e.instruction||``:z.error(e.error||Z(`@WORKBENCH:读取指令失败`))}catch(e){z.error(Z(`@WORKBENCH:读取指令失败`)+`: `+(e&&e.message||e))}finally{W.loading=!1}}async function Ge(){if(!W.text.trim()){z.warning(Z(`@WORKBENCH:指令内容不能为空`));return}W.saving=!0;try{let e=await fetch(`/api/workbench/prompts/ai-instruction`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({instruction:W.text})}).then(e=>e.json());e.success?(z.success(Z(`@WORKBENCH:已保存指令`)),W.visible=!1):z.error(e.error||Z(`@WORKBENCH:保存失败`))}catch(e){z.error(Z(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}finally{W.saving=!1}}async function Ke(){if(!U.name.trim()||!U.content.trim()){z.warning(Z(`@WORKBENCH:名称和内容不能为空`));return}let e={id:U.editing?.id,name:U.name.trim(),content:U.content,projectPath:(U.projectPath||``).trim()},t=await fetch(`/api/workbench/prompts`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}).then(e=>e.json());t.success?(z.success(Z(`@WORKBENCH:已保存`)),U.visible=!1,E()):z.error(t.error||Z(`@WORKBENCH:保存失败`))}async function Je(e){await ge.confirm(Z(`@WORKBENCH:删除提示词「{name}」?`,{name:e.name}),Z(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/prompts/${e.id}`,{method:`DELETE`}),E();for(let t of b.value)t.promptId===e.id&&(t.promptId=null,await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)}));await ne()}let Ye=J(!1),Xe=J(null),Ze=J(null);function Qe(e){let t=e?.currentTarget||Ze.value;if(!t)return;t.style.height=`auto`;let n=document.activeElement===t?su:ou,r=Math.min(Math.max(t.scrollHeight,au),n);t.style.height=`${r}px`,t.style.overflowY=t.scrollHeight>n?`auto`:`hidden`}B(G,async e=>{e&&(await d(),Qe())}),B(()=>N.value?.id,async()=>{G.value&&(await d(),Qe())});async function $e(){if(Ye.value)return;Ye.value=!0;let e={title:``,desc:``,promptId:null,simpleOverride:``};S.value.path&&(e.projectPath=S.value.path);try{let t=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}).then(e=>e.json());if(!t.success){z.error(t.error||Z(`@WORKBENCH:保存失败`));return}le(),N.value&&L(N.value)?await R(N.value):N.value&&I.value&&await fe(),await A(),t.task?.id&&(M.value=t.task.id,ae(),z.success(Z(`@WORKBENCH:已新建任务`)),await d(),Xe.value?.focus())}finally{Ye.value=!1}}async function et(e){await ge.confirm(Z(`@WORKBENCH:删除任务「{title}」?`,{title:e.title}),Z(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`}),M.value===e.id&&(M.value=null),A()}async function tt(e){let t=(e.title||Z(`@WORKBENCH:未命名任务`)).trim(),n={title:Z(`@WORKBENCH:{title} (副本)`,{title:t}),desc:e.desc||``,promptId:e.promptId||null,simpleOverride:e.simpleOverride||``};S.value.path&&(n.projectPath=S.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){z.error(e.error||Z(`@WORKBENCH:复制失败`));return}await A(),e.task?.id&&(M.value=e.task.id,ae()),z.success(Z(`@WORKBENCH:已复制任务`))}catch(e){z.error(Z(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}}async function nt(e){if(M.value===e.id)return;le();let t=N.value;t&&L(t)?await R(t):t&&I.value&&await fe(),M.value=e.id,ae(),m($(S.value.path),e.id)}async function rt(e){let{groupPath:t,orderedIds:n}=e;if(!Array.isArray(n)||n.length===0)return;let r=b.value.slice(),i=it(b.value,t,n);if(i!==b.value){b.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:Z(`@WORKBENCH:排序保存失败`)}));e?.success||(b.value=r,z.error(e?.error||Z(`@WORKBENCH:排序保存失败`)))}catch(e){b.value=r,z.error(Z(`@WORKBENCH:排序保存失败`)+`: `+(e?.message||e))}}}function it(e,t,n){let r=e=>$(e)||$l,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 at(e){if(!N.value)return!1;let t=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(N.value)}).then(e=>e.json());return t.success?(e&&z.success(Z(`@WORKBENCH:已保存`)),await ne(),!0):(z.error(t.error||Z(`@WORKBENCH:保存失败`)),!1)}he(async()=>{await Promise.all([E(),A(),D(),O()]),await de(),w(),window.addEventListener(`beforeunload`,H),i.fetchExecutorModels()}),u(()=>{T(),window.removeEventListener(`beforeunload`,H),N.value&&I.value&&!L(N.value)&&V(N.value)});let{pasteHoverId:ot,isUploading:st,isImageAttachment:ct,humanSize:lt,onAttachmentPaste:ut,onAttachmentDrop:dt,uploadAttachment:ft,removeAttachment:pt,pickAttachmentFile:mt}=Wn(),{runTask:ht,onContinueSendFromChat:gt,cancelJob:_t,clearExecutionForSelectedTask:vt}=Jn(x,b,N,{syncRunningCount:C,clearJobsByTask:k,persistTask:at,uploadAttachment:ft,getExecutor:()=>yt.value}),{active:yt,availability:xt,hasAnyExecutor:St,choose:Ct,executorModelText:Tt,executorModelTitle:Et}=Yn();function Dt(e){return Pe(e)}let Ot=a(()=>Ce(N.value).slice(-1)[0]),kt={configStore:r,toolsStore:i,LAST_TASK_BY_PROJECT_KEY:Ql,NO_PROJECT_KEY:$l,SIDEBAR_WIDTH_KEY:eu,SIDEBAR_MIN_W:tu,SIDEBAR_MAX_W:nu,SIDEBAR_DEFAULT_W:ru,sidebarWidth:o,onSidebarSplitterMouseDown:s,nudgeSidebarWidth:c,readLastTaskMap:l,writeLastTaskMap:f,rememberLastTask:m,editorOpen:h,closeEditor:g,boardOpenedTaskId:_,openTaskFromBoard:v,prompts:y,tasks:b,jobs:x,currentProject:S,syncRunningCount:C,connectSSE:w,disconnectSSE:T,loadPrompts:E,loadCurrentProject:D,loadJobs:O,clearJobsByTask:k,_loadDataTasks:ee,applyRestoredSelection:te,refreshTasks:ne,loadTasks:A,logsDialogVisible:j,selectedTaskId:M,selectedTask:N,foreignRepo:P,metaSnapshot:ie,captureSnapshot:ae,metaSaveState:oe,metaSavedAt:se,get metaSaveTimer(){return F},set metaSaveTimer(e){F=e},metaDirty:I,clearMetaSaveTimers:le,isTaskBlank:L,discardBlankTask:R,pruneBlankTasks:de,flushMetaSave:fe,beaconPersist:V,onBeforeUnloadPersist:H,promptDialog:U,instructionDialog:W,taskDescExpanded:G,availablePrompts:K,copyToClipboard:ye,copyTitleFlashId:q,copyDescFlashId:be,copyTaskTitle:Y,copyTaskDesc:xe,simpleConversationMessages:Se,simpleAllJobsFor:Ce,simpleJobFor:we,simpleJobState:X,CHAT_PIN_WINDOW_MS:iu,CHAT_PIN_USER_EVENTS:Te,chatRef:De,chatWrapRef:Oe,get chatPinRO(){return ke},set chatPinRO(e){ke=e},get chatPinTimer(){return Q},set chatPinTimer(e){Q=e},get chatPinEl(){return je},set chatPinEl(e){je=e},stopChatPin:Me,pinChatToBottom:Le,chatRenderKey:ze,isTaskRunning:Be,openCreatePrompt:Ve,openEditPrompt:He,aiGeneratePrompt:Ue,openEditInstruction:We,saveInstruction:Ge,savePrompt:Ke,deletePrompt:Je,creatingTask:Ye,titleInputRef:Xe,taskDescTextareaRef:Ze,DESC_TEXTAREA_MIN_PX:au,DESC_TEXTAREA_MAX_PX:ou,DESC_TEXTAREA_MAX_PX_FOCUS:su,autoGrowTextarea:Qe,createTaskDirect:$e,deleteTask:et,copyTask:tt,selectTask:nt,reorderTasks:rt,applyLocalReorder:it,persistTask:at,pasteHoverId:ot,isUploading:st,isImageAttachment:ct,humanSize:lt,onAttachmentPaste:ut,onAttachmentDrop:dt,uploadAttachment:ft,removeAttachment:pt,pickAttachmentFile:mt,runTask:ht,onContinueSendFromChat:gt,cancelJob:_t,clearExecutionForSelectedTask:vt,selectedTaskExecutor:yt,executorAvailability:xt,hasAnyExecutor:St,pickExecutor:Ct,executorModelText:Tt,executorModelTitle:Et,executorLabel:Dt,lastSimpleJob:Ot,simpleAssistantLabel:a(()=>Pe(Ot.value?.agent)),simpleAssistantAvatar:a(()=>wt(Ot.value?.agent)),get $t(){return Z},get ArrowDown(){return me},get ArrowLeft(){return p},get ArrowRight(){return re},get Check(){return e},get Document(){return ce},get Delete(){return ve},get CopyDocument(){return pe},get Warning(){return _e},AttachmentZone:bt,get ChatInput(){return Ee},get ChatContainer(){return Ae},ExecutionLogManager:Nn,get ALLOWED_EXT_HINT(){return Fn},get MAX_ATTACHMENT_BYTES(){return In},get TASK_EXECUTOR_OPTIONS(){return Ne},TaskExecutorIcon:qe,WorkbenchSidebar:Lr,WorkbenchBoard:Zl,CommonDialog:Re};return Object.defineProperty(kt,"__isScriptSetup",{enumerable:!1,value:!0}),kt}});D(),S(),H();var lu={class:`workbench`},uu={class:`wb-editor`},du={class:`wb-editor-bar`},fu=[`title`],pu=[`title`],mu=[`title`],hu={class:`wb-editor-bar__hint`},gu={class:`workbench__editor-row`},_u=[`aria-label`,`aria-valuenow`,`title`],vu={class:`wb-split`},yu={key:0,class:`wb-placeholder`},bu={class:`wb-split__header`},xu={class:`wb-split__title-wrap`},Su=[`placeholder`,`aria-label`],Cu=[`title`,`aria-label`],wu=[`title`],Tu={key:0,class:`wb-meta-save__dot`},Eu={key:1,class:`wb-meta-save__check`},Du={key:2,class:`wb-meta-save__bang`},Ou={key:3,class:`wb-meta-save__dot`},ku=[`aria-label`],Au={value:null},ju=[`value`],Mu=[`title`],Nu={class:`wb-executor-item`},Pu={class:`wb-executor-item__name`},Fu=[`title`],Iu={key:2,class:`wb-executor-item__missing`},Lu={key:2,class:`wb-no-claude-hint`,role:`status`},Ru={class:`wb-no-claude-hint__text`},zu={class:`wb-no-claude-hint__link`,href:`https://docs.claude.com/en/docs/claude-code/setup`,target:`_blank`,rel:`noopener noreferrer`},Bu=[`title`,`aria-label`],Vu=[`title`,`aria-label`],Hu=[`open`],Uu={class:`wb-task-desc__summary`},Wu={class:`wb-task-desc__label`},Gu=[`title`,`aria-label`],Ku={key:0,class:`wb-task-desc__tag`},qu={key:0},Ju={key:1,class:`wb-task-desc__tag-attachment`},Yu=[`placeholder`,`aria-label`],Xu={class:`wb-execution-body`},Zu={class:`wb-exec-detail`},Qu={class:`wb-form-item__label wb-simple__override-summary`},$u=[`title`],ed=[`placeholder`,`aria-label`],td={key:0,class:`wb-simple-chat-wrap`,ref:`chatWrapRef`},nd={class:`wb-simple-chat`},rd={key:0,class:`wb-simple-chat__footer`},id={style:{display:`flex`,gap:`8px`,"align-items":`center`}};function ad(e,t,n,r,a,l){let u=h,d=i,f=be,p=O,_=ne,y=A,b=w,S=c,C=v,T=ee;return j(),o(`div`,lu,[s(` L1:多项目编排台 —— **常驻底图**,不再与编辑器互斥 `),x(r.WorkbenchBoard,{"opened-task-id":r.boardOpenedTaskId,onOpenTask:r.openTaskFromBoard},null,8,[`opened-task-id`]),s(` L2:单任务编辑器 —— 大弹窗浮在看板之上,关掉即回到原位,全程无跳转 `),x(r.CommonDialog,{modelValue:r.editorOpen,"onUpdate:modelValue":t[23]||=e=>r.editorOpen=e,title:r.$t(`@WORKBENCH:任务执行`),type:`flex`,"height-mode":`fixed`,"height-offset":`88px`,top:`2vh`,width:`min(1520px, 96vw)`},{default:G(()=>[Y(`div`,uu,[s(` 顶部细栏:关闭入口做成独立一条,而不是塞进任务头 ——
126
+ 没选中任务时(右侧是空态占位)也需要它,塞进任务头就会出现"进了编辑器却关不掉"的死角。 `),Y(`div`,du,[Y(`button`,{type:`button`,class:`wb-back-btn`,title:r.$t(`@WORKBENCH:返回看板`),onClick:r.closeEditor},[x(u,{class:`wb-back-btn__icon`},{default:G(()=>[x(r.ArrowLeft)]),_:1}),Y(`span`,null,E(r.$t(`@WORKBENCH:返回看板`)),1)],8,fu),Y(`span`,{class:`wb-editor-bar__project`,title:r.currentProject.path},E(r.currentProject.name),9,pu),r.foreignRepo?(j(),o(`span`,{key:0,class:`wb-editor-bar__repo`,title:r.foreignRepo.path},E(r.$t(`@WORKBENCH:执行于 {name}`,{name:r.foreignRepo.name})),9,mu)):s(`v-if`,!0),Y(`span`,hu,E(r.$t(`@WORKBENCH:任务执行`)),1)]),Y(`div`,gu,[x(r.WorkbenchSidebar,{style:m({width:r.sidebarWidth+`px`}),tasks:r.tasks,prompts:r.prompts,"selected-task-id":r.selectedTaskId,"current-project":r.currentProject,"creating-task":r.creatingTask,"is-task-running":r.isTaskRunning,onSelectTask:r.selectTask,onDeleteTask:r.deleteTask,onCopyTask:r.copyTask,onCreateTask:r.createTaskDirect,onOpenCreatePrompt:r.openCreatePrompt,onOpenEditPrompt:r.openEditPrompt,onDeletePrompt:r.deletePrompt,onReorderTasks:r.reorderTasks},null,8,[`style`,`tasks`,`prompts`,`selected-task-id`,`current-project`,`creating-task`]),Y(`div`,{class:`wb-splitter`,role:`separator`,tabindex:`0`,"aria-orientation":`vertical`,"aria-label":r.$t(`@WORKBENCH:拖动调整侧边栏宽度`),"aria-valuenow":r.sidebarWidth,"aria-valuemin":r.SIDEBAR_MIN_W,"aria-valuemax":r.SIDEBAR_MAX_W,title:r.$t(`@WORKBENCH:拖动调整侧边栏宽度`),onMousedown:r.onSidebarSplitterMouseDown,onKeydown:[t[0]||=P(q(e=>r.nudgeSidebarWidth(-16),[`prevent`]),[`left`]),t[1]||=P(q(e=>r.nudgeSidebarWidth(16),[`prevent`]),[`right`])]},null,40,_u),s(` 中:单任务编辑区 `),Y(`section`,vu,[r.selectedTask?(j(),o(X,{key:1},[Y(`div`,bu,[Y(`div`,xu,[K(Y(`input`,{ref:`titleInputRef`,class:`wb-input wb-input--title`,"onUpdate:modelValue":t[2]||=e=>r.selectedTask.title=e,placeholder:r.$t(`@WORKBENCH:任务标题`),"aria-label":r.$t(`@WORKBENCH:任务标题`)},null,8,Su),[[R,r.selectedTask.title]]),Y(`button`,{type:`button`,class:g([`wb-copy-btn`,{"is-flash":r.copyTitleFlashId===r.selectedTask.id}]),title:r.$t(`@WORKBENCH:复制任务标题`),"aria-label":r.$t(`@WORKBENCH:复制任务标题`),onClick:t[3]||=e=>r.copyTaskTitle(r.selectedTask)},[r.copyTitleFlashId===r.selectedTask.id?(j(),k(u,{key:1,class:`wb-copy-btn__icon wb-copy-btn__icon--check`},{default:G(()=>[...t[33]||=[V(`✓`,-1)]]),_:1})):(j(),k(u,{key:0,class:`wb-copy-btn__icon`},{default:G(()=>[x(r.CopyDocument)]),_:1}))],10,Cu)]),r.metaSaveState!==`idle`||r.metaDirty?(j(),o(`span`,{key:0,class:g([`wb-meta-save`,{"is-saving":r.metaSaveState===`saving`,"is-saved":r.metaSaveState===`saved`,"is-error":r.metaSaveState===`error`,"is-dirty":r.metaDirty&&r.metaSaveState===`idle`}]),title:r.metaSaveState===`saving`?r.$t(`@WORKBENCH:保存中…`):r.metaSaveState===`error`?r.$t(`@WORKBENCH:保存失败`):r.metaSaveState===`saved`?r.$t(`@WORKBENCH:已保存`):``},[r.metaSaveState===`saving`?(j(),o(`span`,Tu)):r.metaSaveState===`saved`?(j(),o(`span`,Eu,`✓`)):r.metaSaveState===`error`?(j(),o(`span`,Du,`!`)):(j(),o(`span`,Ou)),V(` `+E(r.metaSaveState===`saving`?r.$t(`@WORKBENCH:保存中…`):r.metaSaveState===`saved`?r.$t(`@WORKBENCH:已保存`):r.metaSaveState===`error`?r.$t(`@WORKBENCH:保存失败`):r.$t(`@WORKBENCH:有未保存的更改`)),1)],10,wu)):s(`v-if`,!0),K(Y(`select`,{class:`wb-select`,"onUpdate:modelValue":t[4]||=e=>r.selectedTask.promptId=e,"aria-label":r.$t(`@WORKBENCH:预置提示词`)},[Y(`option`,Au,E(r.$t(`@WORKBENCH:不绑定预置提示词`)),1),(j(!0),o(X,null,M(r.availablePrompts,e=>(j(),o(`option`,{key:e.id,value:e.id},E(e.name),9,ju))),128))],8,ku),[[W,r.selectedTask.promptId]]),s(` 执行:split button —— 主体按当前选中执行器直接跑,下拉临时切换执行器 `),r.hasAnyExecutor?(j(),k(p,{key:1,"split-button":``,type:`primary`,class:`wb-executor-split`,trigger:`click`,onClick:t[5]||=e=>r.runTask(r.selectedTask),onCommand:r.pickExecutor},{dropdown:G(()=>[x(f,null,{default:G(()=>[(j(!0),o(X,null,M(r.TASK_EXECUTOR_OPTIONS,e=>(j(),k(d,{key:e.id,command:e.id,disabled:!r.executorAvailability[e.id]},{default:G(()=>[Y(`span`,Nu,[x(r.TaskExecutorIcon,{executor:e.id,class:`wb-executor-item__icon`},null,8,[`executor`]),Y(`span`,Pu,E(e.name),1),r.executorModelText(e.id)?(j(),o(`span`,{key:0,class:`wb-executor-item__model`,title:r.executorModelTitle(e.id)},E(r.executorModelText(e.id)),9,Fu)):s(`v-if`,!0),r.selectedTaskExecutor===e.id?(j(),k(u,{key:1,class:`wb-executor-item__check`},{default:G(()=>[x(r.Check)]),_:1})):r.executorAvailability[e.id]?s(`v-if`,!0):(j(),o(`span`,Iu,E(r.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`,`disabled`]))),128))]),_:1})]),default:G(()=>[V(E(r.$t(`@WORKBENCH:执行任务`))+` `,1),Y(`span`,{class:`wb-executor-split__hint`,title:r.executorModelTitle(r.selectedTaskExecutor)},[x(r.TaskExecutorIcon,{executor:r.selectedTaskExecutor,class:`wb-executor-split__hint-icon`},null,8,[`executor`]),V(` `+E(r.executorLabel(r.selectedTaskExecutor)),1)],8,Mu)]),_:1},8,[`onCommand`])):(j(),o(`div`,Lu,[x(u,{class:`wb-no-claude-hint__icon`},{default:G(()=>[x(r.Warning)]),_:1}),Y(`span`,Ru,E(r.$t(`@WORKBENCH:未检测到本地 claude / opencode,无法执行任务`)),1),Y(`a`,zu,E(r.$t(`@WORKBENCH:查看安装指引`)),1)])),Y(`button`,{type:`button`,class:`wb-logs-inline-btn wb-logs-inline-btn--danger`,title:r.$t(`@WORKBENCH:清空当前任务的所有执行内容`),"aria-label":r.$t(`@WORKBENCH:清空当前任务的所有执行内容`),onClick:t[6]||=(...e)=>r.clearExecutionForSelectedTask&&r.clearExecutionForSelectedTask(...e)},[x(u,{class:`wb-logs-inline-btn__icon`},{default:G(()=>[x(r.Delete)]),_:1}),Y(`span`,null,E(r.$t(`@WORKBENCH:清空执行`)),1)],8,Bu),Y(`button`,{type:`button`,class:`wb-logs-inline-btn`,title:r.$t(`@WORKBENCH:执行日志`),"aria-label":r.$t(`@WORKBENCH:执行日志`),onClick:t[7]||=e=>r.logsDialogVisible=!0},[x(u,{class:`wb-logs-inline-btn__icon`},{default:G(()=>[x(r.Document)]),_:1}),Y(`span`,null,E(r.$t(`@WORKBENCH:执行日志`)),1)],8,Vu)]),s(` 任务描述区域:默认折叠,节省首屏空间;展开后可编辑/上传附件 `),Y(`details`,{class:`wb-task-desc`,open:r.taskDescExpanded,onToggle:t[19]||=e=>r.taskDescExpanded=e.target.open},[Y(`summary`,Uu,[x(u,{class:`wb-task-desc__caret`},{default:G(()=>[(j(),k(I(r.taskDescExpanded?r.ArrowDown:r.ArrowRight)))]),_:1}),Y(`span`,Wu,E(r.$t(`@WORKBENCH:任务描述(可选)`)),1),Y(`button`,{type:`button`,class:g([`wb-copy-btn wb-copy-btn--inline`,{"is-flash":r.copyDescFlashId===r.selectedTask.id}]),title:r.selectedTask.desc&&r.selectedTask.desc.trim()?r.$t(`@WORKBENCH:复制任务描述`):r.$t(`@WORKBENCH:任务描述为空,无需复制`),"aria-label":r.$t(`@WORKBENCH:复制任务描述`),onClick:t[8]||=q(e=>r.copyTaskDesc(r.selectedTask),[`stop`,`prevent`])},[r.copyDescFlashId===r.selectedTask.id?(j(),k(u,{key:1,class:`wb-copy-btn__icon wb-copy-btn__icon--check`},{default:G(()=>[...t[34]||=[V(`✓`,-1)]]),_:1})):(j(),k(u,{key:0,class:`wb-copy-btn__icon`},{default:G(()=>[x(r.CopyDocument)]),_:1}))],10,Gu),r.selectedTask.desc&&r.selectedTask.desc.length>0||r.selectedTask.attachments&&r.selectedTask.attachments.length>0?(j(),o(`span`,Ku,[r.selectedTask.desc&&r.selectedTask.desc.length>0?(j(),o(`span`,qu,E(r.$t(`@WORKBENCH:已填写`)),1)):s(`v-if`,!0),r.selectedTask.attachments&&r.selectedTask.attachments.length>0?(j(),o(`span`,Ju,E(r.selectedTask.attachments.length),1)):s(`v-if`,!0)])):s(`v-if`,!0)]),K(Y(`textarea`,{ref:`taskDescTextareaRef`,class:`wb-textarea wb-textarea--autogrow`,"onUpdate:modelValue":t[9]||=e=>r.selectedTask.desc=e,placeholder:r.$t(`@WORKBENCH:任务描述(可选)`),"aria-label":r.$t(`@WORKBENCH:任务描述(可选)`),onInput:t[10]||=e=>r.autoGrowTextarea(e),onFocus:t[11]||=e=>r.autoGrowTextarea(e),onBlur:t[12]||=e=>r.autoGrowTextarea(e),onPaste:t[13]||=e=>r.onAttachmentPaste(e,{kind:`task`,task:r.selectedTask})},null,40,Yu),[[R,r.selectedTask.desc]]),x(r.AttachmentZone,{attachments:r.selectedTask.attachments||[],"is-image":r.isImageAttachment,"human-size":r.humanSize,"is-uploading":r.isUploading(`task-`+r.selectedTask.id),"is-paste-hover":r.pasteHoverId===`task-`+r.selectedTask.id,"on-pick":()=>r.pickAttachmentFile({kind:`task`,task:r.selectedTask}),"on-remove":e=>r.removeAttachment({kind:`task`,task:r.selectedTask},e),onPaste:t[14]||=e=>r.onAttachmentPaste(e,{kind:`task`,task:r.selectedTask}),onDrop:t[15]||=q(e=>r.onAttachmentDrop(e,{kind:`task`,task:r.selectedTask}),[`prevent`]),onDragover:t[16]||=q(e=>r.pasteHoverId=`task-`+r.selectedTask.id,[`prevent`]),onDragenter:t[17]||=q(e=>r.pasteHoverId=`task-`+r.selectedTask.id,[`prevent`]),onDragleave:t[18]||=e=>r.pasteHoverId=r.pasteHoverId===`task-`+r.selectedTask.id?null:r.pasteHoverId},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`,`on-pick`,`on-remove`])],40,Hu),s(` ── 执行主体:一条任务 = 一次会话,详情面板占满整行 ── `),Y(`div`,Xu,[s(` 详情面板(执行内容区) `),Y(`div`,Zu,[s(` ⚠️ 这一层**不要**用裸 <template> 包起来(踩过,2026-09-22):
127
+ Vue 3 只把带 v-if / v-else / v-for / v-slot 的 <template> 编译成片段,
128
+ 裸 <template> 会被当成真的 <template> 元素渲染 —— 浏览器把子节点全塞进
129
+ template.content(inert DocumentFragment),不产生任何布局盒。
130
+ 症状:任务在跑、看板「执行中」,但对话区一片空白,
131
+ 而 innerText 里明明有内容(元素 0×0)。重构移除子任务概念时留下的空壳。 `),Y(`details`,{class:g([`wb-simple__override`,{"has-content":!!(r.selectedTask.simpleOverride&&r.selectedTask.simpleOverride.trim())}])},[Y(`summary`,Qu,[x(u,{class:`wb-simple__override-caret`},{default:G(()=>[x(r.ArrowRight)]),_:1}),Y(`span`,null,E(r.$t(`@WORKBENCH:覆盖预置提示词(可选)`)),1),r.selectedTask.simpleOverride&&r.selectedTask.simpleOverride.trim()?(j(),o(`span`,{key:0,class:`wb-simple__override-tag`,title:r.$t(`@WORKBENCH:已填写覆盖内容`)},E(r.$t(`@WORKBENCH:已填写`)),9,$u)):s(`v-if`,!0),r.simpleJobState(r.simpleJobFor(r.selectedTask))===`running`&&r.simpleJobFor(r.selectedTask)?(j(),o(`button`,{key:1,class:`wb-simple__stop`,onClick:t[20]||=q(e=>r.cancelJob(r.simpleJobFor(r.selectedTask)),[`stop`])},E(r.$t(`@WORKBENCH:停止`)),1)):s(`v-if`,!0)]),K(Y(`textarea`,{class:`wb-textarea`,"onUpdate:modelValue":t[21]||=e=>r.selectedTask.simpleOverride=e,placeholder:r.$t(`@WORKBENCH:留空则使用上方选定的「预置提示词」模板;可用变量:{{task.title}} {{task.desc}} {{repo.path}} {{branch}}`),"aria-label":r.$t(`@WORKBENCH:覆盖预置提示词(可选)`),rows:`6`},null,8,ed),[[R,r.selectedTask.simpleOverride]])],2),s(` 任务对话流:所有轮次合并到单个 ChatContainer `),r.simpleAllJobsFor(r.selectedTask).length>0?(j(),o(`div`,td,[s(` ⚠️ 这层 div 不是多余的,class 也**不要**挪回 ChatContainer 上(2026-09-29 踩过):
132
+ 传给 zen-ai-chat-ui 组件的 class 在**生产构建**里不会落到组件根节点上
133
+ (同一份源码 dev 会落、prod 静默丢掉,实测 class 与父级 data-v-* 双双消失),
134
+ 于是 \`.wb-simple-chat :deep(.acu-*)\` 这一组样式钩子在生产 bundle 里全是死的。
135
+ 症状之一就是「已完成的任务点开后有 2 个输入框」:原来靠
136
+ \`.acu-chat-footer{display:none}\` 藏 ChatContainer 自带输入框,prod 里那条规则
137
+ 根本没匹配上,lib 自带输入框与下面常驻的 ChatInput 同时显示。
138
+ 把 class 挂在自己的 div 上,样式钩子才在 dev / prod 都成立。 `),Y(`div`,nd,[(j(),k(r.ChatContainer,{ref:`chatRef`,key:r.selectedTask.id,messages:r.simpleConversationMessages,"assistant-name":r.simpleAssistantLabel,"assistant-avatar":r.simpleAssistantAvatar,"show-avatar":!0,theme:r.configStore.theme,"tool-calls-config":{group:!0,collapseThreshold:2},"plan-config":{labels:{title:r.$t(`@AGENT:计划`),raw:r.$t(`@AGENT:原始参数`)}},"show-input":!1},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`plan-config`]))]),s(` 终态控件 `),r.simpleJobFor(r.selectedTask)&&[`done`,`error`,`cancelled`].includes(r.simpleJobState(r.simpleJobFor(r.selectedTask)))?(j(),o(`div`,rd,[(j(),k(r.ChatInput,{key:`input-`+r.selectedTask.id,placeholder:r.$t(`@WORKBENCH:输入后续问题继续对话…(Ctrl+Enter 发送)`),"upload-config":{enabled:!0,accept:r.ALLOWED_EXT_HINT,multiple:!0,maxCount:0,maxSize:r.MAX_ATTACHMENT_BYTES},class:`wb-simple-chat__input`,onSend:t[22]||=e=>r.onContinueSendFromChat(r.selectedTask,e)},null,8,[`placeholder`,`upload-config`]))])):s(`v-if`,!0)],512)):s(`v-if`,!0)])])],64)):(j(),o(`div`,yu,[Y(`p`,null,E(r.$t(`@WORKBENCH:左侧选择任务,或新建一个任务开始`)),1)]))])])])]),_:1},8,[`modelValue`,`title`]),s(` 执行日志管理:弹窗形式承载,原本独立 tab 切换会占用首屏。
139
+
140
+ ⚠️ 必须 append-to-body。app shell 的 main.main-container 是 position:fixed + z-index:1001,
141
+ 它自成一个层叠上下文:留在这里面的弹窗 z-index 再高,也只是跟"同一个上下文里的兄弟"比,
142
+ 永远压不过挂在 body 下的 L2 编辑器弹窗(它 escape 了 1001 那层)。
143
+ 现象就是点了「执行日志」没反应 —— 其实弹窗开了,只是被编辑器整个盖住。 `),x(r.CommonDialog,{modelValue:r.logsDialogVisible,"onUpdate:modelValue":t[24]||=e=>r.logsDialogVisible=e,title:r.$t(`@WORKBENCH:执行日志`),width:`1080px`,"close-on-click-modal":!1,top:`6vh`,type:`flex`,"custom-class":`wb-logs-dialog`,"append-to-body":``},{default:G(()=>[x(r.ExecutionLogManager)]),_:1},8,[`modelValue`,`title`]),s(` 提示词编辑对话框:同「执行日志」,从编辑器里打开,必须 append-to-body 才压得住编辑器弹窗 `),x(r.CommonDialog,{modelValue:r.promptDialog.visible,"onUpdate:modelValue":t[29]||=e=>r.promptDialog.visible=e,title:r.promptDialog.editing?r.$t(`@WORKBENCH:编辑提示词`):r.$t(`@WORKBENCH:新建提示词`),width:`640px`,type:`flex`,"append-to-body":``},{footer:G(()=>[x(C,{onClick:t[28]||=e=>r.promptDialog.visible=!1},{default:G(()=>[V(E(r.$t(`@WORKBENCH:取消`)),1)]),_:1}),x(C,{type:`primary`,onClick:r.savePrompt},{default:G(()=>[V(E(r.$t(`@WORKBENCH:保存`)),1)]),_:1})]),default:G(()=>[x(T,{"label-position":`top`},{default:G(()=>[x(y,{label:r.$t(`@WORKBENCH:名称`)},{default:G(()=>[x(_,{modelValue:r.promptDialog.name,"onUpdate:modelValue":t[25]||=e=>r.promptDialog.name=e,placeholder:r.$t(`@WORKBENCH:如:代码审查 / 写测试`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`]),x(y,{label:r.$t(`@WORKBENCH:所属项目`)},{default:G(()=>[x(S,{modelValue:r.promptDialog.projectPath,"onUpdate:modelValue":t[26]||=e=>r.promptDialog.projectPath=e,placeholder:r.$t(`@WORKBENCH:所属项目`),style:{width:`100%`},disabled:!r.currentProject.path},{default:G(()=>[s(` 「全局」选项 = projectPath 为空串,所有项目都能看到 `),x(b,{label:r.$t(`@WORKBENCH:全局(所有项目可用)`),value:``},null,8,[`label`]),s(` 仅当有当前项目时才允许绑定到当前项目,避免“绑到空项目”的兑犷数据 `),r.currentProject.path?(j(),k(b,{key:r.currentProject.path,label:r.currentProject.name||r.currentProject.path,value:r.currentProject.path},null,8,[`label`,`value`])):s(`v-if`,!0)]),_:1},8,[`modelValue`,`placeholder`,`disabled`])]),_:1},8,[`label`]),x(y,null,{default:G(()=>[Y(`div`,id,[x(C,{type:`primary`,plain:``,loading:r.promptDialog.aiLoading,onClick:r.aiGeneratePrompt},{default:G(()=>[V(E(r.$t(`@WORKBENCH:AI 生成项目架构说明`)),1)]),_:1},8,[`loading`]),x(C,{onClick:r.openEditInstruction},{default:G(()=>[V(E(r.$t(`@WORKBENCH:编辑指令`)),1)]),_:1})])]),_:1}),x(y,{label:r.$t(`@WORKBENCH:内容`)},{default:G(()=>[x(_,{modelValue:r.promptDialog.content,"onUpdate:modelValue":t[27]||=e=>r.promptDialog.content=e,type:`textarea`,rows:10,placeholder:r.$t(`@WORKBENCH:可用变量:`)+`{{task.title}} {{task.desc}} {{sub.title}} {{sub.desc}} {{repo.path}} {{branch}}`},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])]),_:1})]),_:1},8,[`modelValue`,`title`]),s(` 生成指令编辑对话框 `),x(r.CommonDialog,{modelValue:r.instructionDialog.visible,"onUpdate:modelValue":t[32]||=e=>r.instructionDialog.visible=e,title:r.$t(`@WORKBENCH:编辑生成指令`),width:`720px`,type:`flex`,"append-to-body":``},{footer:G(()=>[x(C,{onClick:t[31]||=e=>r.instructionDialog.visible=!1},{default:G(()=>[V(E(r.$t(`@WORKBENCH:取消`)),1)]),_:1}),x(C,{type:`primary`,loading:r.instructionDialog.saving,onClick:r.saveInstruction},{default:G(()=>[V(E(r.$t(`@WORKBENCH:保存`)),1)]),_:1},8,[`loading`])]),default:G(()=>[x(T,{"label-position":`top`},{default:G(()=>[x(y,{label:r.$t(`@WORKBENCH:指令内容`)},{default:G(()=>[x(_,{modelValue:r.instructionDialog.text,"onUpdate:modelValue":t[30]||=e=>r.instructionDialog.text=e,type:`textarea`,rows:18,placeholder:r.$t(`@WORKBENCH:指令内容`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])]),_:1})]),_:1},8,[`modelValue`,`title`])])}var od=Q(cu,[[`render`,ad],[`__scopeId`,`data-v-28f2e82b`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/WorkbenchView.vue`]]);export{od as default};