zen-gitsync 2.17.14 → 2.17.16

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 (89) hide show
  1. package/README.md +211 -185
  2. package/package.json +2 -2
  3. package/scripts/release.js +33 -16
  4. package/src/cli/ai/agent.js +24 -2
  5. package/src/cli/ai/runtime.test.js +1 -1
  6. package/src/cli/ai/tools.js +69 -14
  7. package/src/cli/ai/tools.test.js +46 -1
  8. package/src/config.js +8 -4
  9. package/src/gitCommit.js +18 -1
  10. package/src/ui/public/assets/AgentView-DOyN97Ve.js +5 -0
  11. package/src/ui/public/assets/{AgentView-vvVhbIQ5.css → AgentView-DkM2KXuc.css} +1 -1
  12. package/src/ui/public/assets/AppVersionBadge-oON3sAj4.js +2 -0
  13. package/src/ui/public/assets/{BranchSelector-XIN87Mkw.js → BranchSelector-Cpj7eGqY.js} +1 -1
  14. package/src/ui/public/assets/CommitForm-D_ovYhVw.js +6 -0
  15. package/src/ui/public/assets/{CommonDialog-BiNTGpA-.js → CommonDialog-ChZbqfRF.js} +1 -1
  16. package/src/ui/public/assets/EditorView-BPzpI0GV.js +1 -0
  17. package/src/ui/public/assets/FileDiffViewer-B_qEKA9L.js +15 -0
  18. package/src/ui/public/assets/{FlowExecutionViewer-D9Vzgh91.js → FlowExecutionViewer-Drw4hlJG.js} +1 -1
  19. package/src/ui/public/assets/FlowOrchestrationWorkspace-C7yTD1gj.js +21 -0
  20. package/src/ui/public/assets/{IconButton-DysyaC1j.js → IconButton-DEARmMkZ.js} +1 -1
  21. package/src/ui/public/assets/{LogList-QDgok-UJ.js → LogList-BA_gowxE.js} +5 -5
  22. package/src/ui/public/assets/MindmapView-8X6z245q.css +1 -0
  23. package/src/ui/public/assets/MindmapView-K-XcLLXr.js +2 -0
  24. package/src/ui/public/assets/MonitorView-C0RL5K9W.js +1 -0
  25. package/src/ui/public/assets/ProjectStartupButton-DC36_vvU.js +1 -0
  26. package/src/ui/public/assets/RemoteManagerDialog-Bkqja660.js +4 -0
  27. package/src/ui/public/assets/{RemoteRepoCard-Bn9cKt1D.js → RemoteRepoCard-Bsm7cj_H.js} +2 -2
  28. package/src/ui/public/assets/SourceMapView-Y5NKdIk6.js +3 -0
  29. package/src/ui/public/assets/{SvgIcon-CvtoU5yo.js → SvgIcon-D_mFHXP4.js} +1 -1
  30. package/src/ui/public/assets/{TemplateManager-saqC9kdQ.js → TemplateManager-BzKVXZhy.js} +1 -1
  31. package/src/ui/public/assets/UserInputNode-BPLK4aYx.js +1 -0
  32. package/src/ui/public/assets/WorkbenchView-xbGdiVMQ.js +56 -0
  33. package/src/ui/public/assets/_plugin-vue_export-helper-dg2VUnSQ.js +19 -0
  34. package/src/ui/public/assets/configStore-DtjAc3w9.js +1 -0
  35. package/src/ui/public/assets/{css.worker-DFdt6_zu.js → css.worker-BDCmgL4U.js} +9 -9
  36. package/src/ui/public/assets/editor.worker-GCPm6rMv.js +26 -0
  37. package/src/ui/public/assets/{element-plus-Dc1iTOWq.css → element-plus-Cwwq-Gje.css} +1 -1
  38. package/src/ui/public/assets/element-plus-DxBPQwL7.js +48 -0
  39. package/src/ui/public/assets/{flow-mindmap-CHxAWdLw.js → flow-mindmap-BqFb1WO5.js} +1 -1
  40. package/src/ui/public/assets/{gitStore-BgC8OY0k.js → gitStore-BZo9_zyy.js} +5 -5
  41. package/src/ui/public/assets/{html.worker-JUzsMP-j.js → html.worker-DG8hnSJR.js} +8 -8
  42. package/src/ui/public/assets/index-CHuCYLWm.js +111 -0
  43. package/src/ui/public/assets/index-CmbatbSR.css +1 -0
  44. package/src/ui/public/assets/json.worker-CxwlJRnL.js +58 -0
  45. package/src/ui/public/assets/{monaco-DkJuNcCr.js → monaco-BScz9v63.js} +6 -6
  46. package/src/ui/public/assets/{office-docx-CmBY5bpF.js → office-docx-CZXLkCf5.js} +1 -1
  47. package/src/ui/public/assets/{office-excel-BEhsBUNX.js → office-excel-CBKszjVA.js} +1 -1
  48. package/src/ui/public/assets/{office-pptx-DWfi413x.js → office-pptx-NeUSnN3k.js} +3 -3
  49. package/src/ui/public/assets/previewSandbox-BTTTXooN.js +0 -0
  50. package/src/ui/public/assets/{ts.worker-CmEKzkmF.js → ts.worker-DgFMIcEs.js} +49 -49
  51. package/src/ui/public/assets/{useThemeObserver-DhCU3SIo.js → useThemeObserver-E7Hk50l3.js} +1 -1
  52. package/src/ui/public/assets/vendor-DnB9EJa3.css +1 -0
  53. package/src/ui/public/assets/{vendor-CZnXb2r9.js → vendor-bdHhLiED.js} +28 -28
  54. package/src/ui/public/assets/{vue-flow-7_n4vJqi.js → vue-flow-fLUQ0_kE.js} +1 -1
  55. package/src/ui/public/index.html +19 -19
  56. package/src/ui/server/index.js +4 -0
  57. package/src/ui/server/routes/explorerContextMenu.js +208 -0
  58. package/src/ui/server/routes/explorerContextMenu.test.js +180 -0
  59. package/src/ui/server/routes/workbench/agentChat.js +14 -3
  60. package/src/ui/server/routes/workbench/agentMarketplace.js +23 -9
  61. package/src/ui/server/routes/workbench/agentMarketplace.test.js +32 -0
  62. package/src/ui/server/routes/workbench/agentRoutes.js +14 -7
  63. package/src/ui/server/routes/workbench/agentRoutes.test.js +47 -1
  64. package/src/ui/server/routes/workbench/taskRunner.codex.test.js +173 -0
  65. package/src/ui/server/routes/workbench/taskRunner.js +259 -10
  66. package/src/ui/server/routes/workbench/taskRunner.opencode.test.js +4 -2
  67. package/src/ui/public/assets/AgentView-DLHlVWRg.js +0 -5
  68. package/src/ui/public/assets/AppVersionBadge-JxpMuGwP.js +0 -2
  69. package/src/ui/public/assets/CommitForm-CW53Er5m.js +0 -6
  70. package/src/ui/public/assets/EditorView-D0JoJhgt.js +0 -1
  71. package/src/ui/public/assets/FileDiffViewer-Yas2nO2U.js +0 -15
  72. package/src/ui/public/assets/FlowOrchestrationWorkspace-DQ3fg5b9.js +0 -21
  73. package/src/ui/public/assets/MindmapView-BQTqx842.css +0 -1
  74. package/src/ui/public/assets/MindmapView-CeZsQNBK.js +0 -2
  75. package/src/ui/public/assets/MonitorView-D1tgmjjS.js +0 -1
  76. package/src/ui/public/assets/ProjectStartupButton-COntA4q1.js +0 -1
  77. package/src/ui/public/assets/RemoteManagerDialog-3dihAOab.js +0 -4
  78. package/src/ui/public/assets/SourceMapView-C8UdzQXF.js +0 -3
  79. package/src/ui/public/assets/UserInputNode-CvEfvX3i.js +0 -1
  80. package/src/ui/public/assets/WorkbenchView-B7WAu1Ay.js +0 -56
  81. package/src/ui/public/assets/_plugin-vue_export-helper-BdTxl34g.js +0 -19
  82. package/src/ui/public/assets/configStore-AQMSazCM.js +0 -1
  83. package/src/ui/public/assets/editor.worker-O-CH8JUO.js +0 -26
  84. package/src/ui/public/assets/element-plus-CMSkP_w2.js +0 -48
  85. package/src/ui/public/assets/index-Dpx9Bcqn.css +0 -1
  86. package/src/ui/public/assets/index-qAmzFO10.js +0 -104
  87. package/src/ui/public/assets/json.worker-B4dEhy0e.js +0 -58
  88. package/src/ui/public/assets/previewSandbox-CyuMMYaq.js +0 -0
  89. package/src/ui/public/assets/vendor-4ojsjDYc.css +0 -1
@@ -1,56 +0,0 @@
1
- import"./rolldown-runtime-C0FnF6B9.js";import{$r as e,Bt as t,C as n,Dn as r,E as i,En as a,F as o,Fn as s,It as c,J as l,Jn as u,K as d,Kn as f,L as p,Lt as m,M as h,Mn as g,Nn as _,On as v,P as y,Pr as b,Pt as x,Qn as S,Rt as C,S as w,Sn as T,St as E,Tn as D,Tt as O,U as ee,Un as k,V as te,Vt as A,W as j,Wt as ne,Xn as M,Y as re,Yr as N,_n as P,_r as ie,a as F,ar as I,at as ae,b as L,bn as R,cr as z,ct as oe,et as se,fr as B,ft as ce,gn as V,gt as le,hn as ue,i as de,in as fe,jt as pe,o as me,pn as H,q as he,qr as U,qt as ge,r as _e,sr as W,st as ve,tr as ye,un as G,ut as be,v as xe,vn as K,vt as Se,w as Ce,wn as q,xt as we,y as Te,yn as J,yr as Y,zn as X}from"./element-plus-CMSkP_w2.js";import{a as Ee,i as De,o as Oe,r as ke}from"./vendor-CZnXb2r9.js";import{n as Z,t as Q}from"./_plugin-vue_export-helper-BdTxl34g.js";import{t as Ae}from"./SvgIcon-CvtoU5yo.js";import{t as je}from"./configStore-AQMSazCM.js";import{t as Me}from"./CommonDialog-BiNTGpA-.js";import{E as $,T as Ne,_ as Pe,a as Fe,c as Ie,d as Le,f as Re,g as ze,h as Be,i as Ve,l as He,m as Ue,o as We,p as Ge,s as Ke,u as qe}from"./index-qAmzFO10.js";X(),B();var Je=s({__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},maxCount:{type:Number,required:!0},onPick:{type:Function,required:!0},onRemove:{type:Function,required:!0},rawBase:{type:String,required:!1}},emits:[`paste`,`drop`,`dragover`,`dragenter`,`dragleave`],setup(e,{expose:t,emit:n}){t();let r=e;function i(e){return`${r.rawBase||`/api/workbench/attachments`}/${e.id}/raw`}let a=n,o=q(()=>r.attachments.filter(e=>r.isImage(e))),s=q(()=>o.value.map(e=>i(e))),c=Y(0),l=Y(!1);function u(e){if(r.isImage(e)){let t=o.value.findIndex(t=>t.id===e.id);c.value=t>=0?t:0,l.value=!0}else window.open(i(e),`_blank`,`noopener`)}function d(){l.value=!1}let p=Y({visible:!1,x:0,y:0,att:null}),m=Y(!1);function h(e,t){if(!r.isImage(e))return;t.preventDefault();let n=window.innerWidth-180,i=window.innerHeight-120;p.value={visible:!0,x:Math.min(t.clientX,n),y:Math.min(t.clientY,i),att:e}}function g(){p.value.visible&&(p.value.visible=!1)}async function _(){let e=p.value.att;if(e&&!m.value){if(g(),!navigator.clipboard||typeof ClipboardItem>`u`){F({type:`warning`,message:Z(`@WORKBENCH:当前浏览器不支持复制图片`)});return}m.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]),F({type:`success`,message:Z(`@WORKBENCH:图片已复制到剪贴板`),duration:1800})}catch(e){F({type:`error`,message:Z(`@WORKBENCH:复制失败 {error}`,{error:e?.message||``})})}finally{m.value=!1}}}typeof window<`u`&&(window.addEventListener(`click`,g),window.addEventListener(`scroll`,g,!0),window.addEventListener(`blur`,g)),f(()=>{typeof window<`u`&&(window.removeEventListener(`click`,g),window.removeEventListener(`scroll`,g,!0),window.removeEventListener(`blur`,g))});let v={props:r,rawOf:i,emit:a,imageList:o,previewUrls:s,previewIndex:c,previewVisible:l,previewAttachment:u,closePreview:d,contextMenu:p,copyBusy:m,openContextMenu:h,closeContextMenu:g,copyImageToClipboard:_,get ElImageViewer(){return L},get $t(){return Z}};return Object.defineProperty(v,"__isScriptSetup",{enumerable:!1,value:!0}),v}});b(),X(),G();var Ye={class:`wb-attachments__head`},Xe={class:`wb-attachments__label`},Ze={class:`wb-attachments__count`},Qe=[`disabled`],$e={key:0,class:`wb-attachments__paste-hint`},et={key:1,class:`wb-attachments__list`},tt=[`title`,`onClick`,`onContextmenu`],nt=[`src`,`alt`],rt={key:1},it={class:`wb-attachment__meta`},at=[`title`],ot=[`onClick`,`title`];function st(t,n,i,o,s,c){return M(),v(R,null,[D(`div`,{class:U([`wb-attachments`,{"is-paste-hover":i.isPasteHover}]),onPaste:n[1]||=e=>o.emit(`paste`,e),onDrop:n[2]||=J(e=>o.emit(`drop`,e),[`prevent`]),onDragover:n[3]||=J(e=>o.emit(`dragover`,e),[`prevent`]),onDragenter:n[4]||=J(e=>o.emit(`dragenter`,e),[`prevent`]),onDragleave:n[5]||=e=>o.emit(`dragleave`,e)},[D(`div`,Ye,[D(`span`,Xe,[g(e(o.$t(`@WORKBENCH:附件`))+` `,1),D(`span`,Ze,e(i.attachments.length)+` / `+e(i.maxCount),1)]),D(`button`,{class:`wb-attachments__add wb-soft-btn`,disabled:i.isUploading||i.attachments.length>=i.maxCount,onClick:n[0]||=(...e)=>i.onPick&&i.onPick(...e)},e(i.isUploading?o.$t(`@WORKBENCH:上传中…`):o.$t(`@WORKBENCH:添加附件`)),9,Qe)]),i.isPasteHover?(M(),v(`div`,$e,e(o.$t(`@WORKBENCH:粘贴图片以快速添加`)),1)):r(`v-if`,!0),i.attachments.length>0?(M(),v(`ul`,et,[(M(!0),v(R,null,S(i.attachments,t=>(M(),v(`li`,{key:t.id,class:`wb-attachment`},[D(`button`,{type:`button`,class:`wb-attachment__preview`,title:o.$t(`@WORKBENCH:点击预览`),onClick:e=>o.previewAttachment(t),onContextmenu:e=>o.openContextMenu(t,e)},[D(`div`,{class:U([`wb-attachment__icon`,{"wb-attachment__icon--img":i.isImage(t)}])},[i.isImage(t)?(M(),v(`img`,{key:0,src:o.rawOf(t),alt:t.originalName,loading:`lazy`},null,8,nt)):(M(),v(`span`,rt,e(t.ext.toUpperCase()),1))],2),D(`div`,it,[D(`div`,{class:`wb-attachment__name`,title:`${t.originalName} (${i.humanSize(t.size)})`},e(t.originalName),9,at)])],40,tt),D(`button`,{class:`wb-attachment__del`,onClick:J(e=>i.onRemove(t),[`stop`]),title:o.$t(`@WORKBENCH:删除`)},`×`,8,ot)]))),128))])):r(`v-if`,!0)],34),r(`
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
- `),o.previewVisible&&o.previewUrls.length>0?(M(),a(o.ElImageViewer,{key:0,"url-list":o.previewUrls,"initial-index":o.previewIndex,"hide-on-click-modal":!0,teleported:!0,onClose:o.closePreview},null,8,[`url-list`,`initial-index`])):r(`v-if`,!0),r(` 右键菜单:仅图片附件可用 `),(M(),a(T,{to:`body`},[o.contextMenu.visible&&o.contextMenu.att&&i.isImage(o.contextMenu.att)?(M(),v(`ul`,{key:0,class:`wb-ctx-menu`,style:N({top:o.contextMenu.y+`px`,left:o.contextMenu.x+`px`}),onContextmenu:n[6]||=J(()=>{},[`prevent`])},[D(`li`,{class:U([`wb-ctx-menu__item`,{"is-disabled":o.copyBusy}]),onClick:o.copyImageToClipboard},[n[7]||=D(`span`,{class:`wb-ctx-menu__icon`,"aria-hidden":`true`},[D(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[D(`rect`,{x:`9`,y:`9`,width:`11`,height:`11`,rx:`2`}),D(`path`,{d:`M5 15V5a2 2 0 0 1 2-2h10`})])],-1),D(`span`,null,e(o.$t(`@WORKBENCH:复制图片`)),1)],2)],36)):r(`v-if`,!0)]))],64)}var ct=Q(Je,[[`render`,st],[`__scopeId`,`data-v-d2df2361`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/AttachmentZone.vue`]]),lt=Oe(`claude`),ut=Oe(`opencode`);function dt(e){return e===`opencode`?ut:lt}function ft(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 pt(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 mt=8192;function ht(e,t){return e.length>t?`…(前文已截断)\n${e.slice(-t)}`:e}function gt(e,t){let n=e||`done`;return n!==`pending`&&n!==`running`||t===`running`||t===`pending`?n:t===`cancelled`||t===`error`?`error`:`done`}function _t(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=gt(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?ht(o,mt):``,status:a,error:typeof i.error==`string`&&i.error?i.error:void 0})}return r}X(),B();var vt=65536,yt=s({__name:`JobLogDetails`,props:{job:{type:Object,required:!0}},emits:[`re-execute`],setup(e,{expose:t,emit:n}){t();let r=je(),i=e,a=n,o=Y(!1);function s(){o.value=!o.value}let c=q(()=>i.job.status===`running`||i.job.status===`pending`);I(()=>i.job.status,(e,t)=>{t!==`running`&&t!==`pending`&&(e===`running`||e===`pending`)&&(o.value=!1)});function l(){let e=i.job.output||``;return e?e.length<=vt?e:`${Z(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`:``}function u(){let e=i.job.thinking||``;return e?e.length<=vt?e:`${Z(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`:``}async function d(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 f(){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){F.warning(Z(`@WORKBENCH:暂无内容可复制`));return}await d(e.join(`
7
-
8
- ---
9
-
10
- `))?F.success(Z(`@WORKBENCH:已复制到剪贴板`)):F.error(Z(`@WORKBENCH:复制失败`))}let p=q(()=>{let e=i.job.status;return e===`done`||e===`error`||e===`cancelled`}),m=q(()=>i.job.status===`cancelled`?`wb-log-summary__status--cancelled`:i.job.status===`error`?`wb-log-summary__status--error`:`wb-log-summary__status--done`),h=q(()=>i.job.status===`cancelled`?`⏹`:i.job.status===`error`?`✗`:`✓`),g=q(()=>i.job.status===`cancelled`?Z(`@WORKBENCH:已停止`):i.job.status===`error`?Z(`@WORKBENCH:执行出错`):Z(`@WORKBENCH:执行完成`)),_=q(()=>i.job?.agent===`opencode`?`OpenCode`:`Claude`),v=q(()=>dt(i.job?.agent));function y(e,t){return e===`running`||e===`pending`?t?`streaming`:`pending`:e===`error`?`error`:`done`}let b=q(()=>{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=l(),a=u(),o=!!r,s=!!a,c=_t(e),d=c.length>0,f=o||s||d,p=y(e.status,f);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:d?c:void 0,status:p,error:p===`error`&&e.error||void 0,createdAt:n}),t}),x=Y(null);I(()=>i.job.status,(e,t)=>{e===`running`&&t!==`running`&&(x.value=x.value??Date.now())});let S=q(()=>{if(!x.value)return``;let e=x.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`)}秒`}),C=Y(!1),w=q(()=>!!(i.job.output&&i.job.output.length)),T=q(()=>i.job.output||``),E=Y(null);I(C,async e=>{e&&(await k(),E.value&&(E.value.scrollTop=E.value.scrollHeight))}),I(()=>(i.job.output||``).length,async()=>{C.value&&(await k(),E.value&&(E.value.scrollTop=E.value.scrollHeight))});function D(){}let O=q(()=>p.value&&!!i.job.prompt);function ee(){a(`re-execute`,i.job)}let te={configStore:r,props:i,emit:a,isCollapsed:o,toggleOpen:s,isActive:c,MAX_LOG_DISPLAY:vt,displayOutput:l,displayThinking:u,copyToClipboard:d,copyAll:f,isFinished:p,finishedStatusClass:m,finishedStatusIcon:h,finishedStatusLabel:g,assistantLabel:_,assistantAvatar:v,mapStatus:y,chatMessages:b,startedAt:x,elapsedLabel:S,fullscreenOpen:C,hasOutput:w,fullscreenSource:T,fullscreenContainerRef:E,onFullscreenClosed:D,canReExecute:O,onReExecute:ee,get ChatContainer(){return De},get MarkdownRenderer(){return ke},get $t(){return Z}};return Object.defineProperty(te,"__isScriptSetup",{enumerable:!1,value:!0}),te}});b(),X(),G();var bt=[`aria-expanded`],xt={class:`wb-log-summary__left`},St={key:0,class:`wb-log-summary__status wb-log-summary__status--running`},Ct={class:`wb-log-summary__label`},wt={key:0,class:`wb-log-summary__elapsed`},Tt={key:1,class:`wb-log-summary__status wb-log-summary__status--pending`},Et={class:`wb-log-summary__label`},Dt={class:`wb-log-summary__icon`},Ot={class:`wb-log-summary__label`},kt={key:0,class:`wb-log-summary__elapsed`},At={key:3},jt={class:`wb-log-summary__right`},Mt={class:`wb-log-summary__meta`},Nt=[`title`,`aria-label`],Pt={class:`wb-log-details__body`},Ft={key:0,class:`wb-chat__foot`},It=[`title`,`aria-label`],Lt={ref:`fullscreenContainerRef`,class:`wb-log-fullscreen`},Rt={key:1,class:`wb-log-fullscreen__empty`};function zt(t,n,o,s,c,l){let u=i;return M(),v(`div`,{class:U([`wb-log-details`,{"is-running":s.isActive,"is-pending":o.job.status===`pending`,"is-finished":s.isFinished}])},[D(`div`,{class:`wb-log-summary`,onClick:s.toggleOpen,role:`button`,"aria-expanded":!s.isCollapsed},[D(`span`,xt,[o.job.status===`running`?(M(),v(`span`,St,[D(`span`,Ct,e(s.$t(`@WORKBENCH:正在执行…`)),1),n[1]||=D(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[D(`span`,{class:`wb-log-dots__dot`}),D(`span`,{class:`wb-log-dots__dot`}),D(`span`,{class:`wb-log-dots__dot`})],-1),s.elapsedLabel?(M(),v(`span`,wt,e(s.elapsedLabel),1)):r(`v-if`,!0)])):o.job.status===`pending`?(M(),v(`span`,Tt,[D(`span`,Et,e(s.$t(`@WORKBENCH:排队中…`)),1),n[2]||=D(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[D(`span`,{class:`wb-log-dots__dot`}),D(`span`,{class:`wb-log-dots__dot`}),D(`span`,{class:`wb-log-dots__dot`})],-1)])):s.isFinished?(M(),v(`span`,{key:2,class:U([`wb-log-summary__status`,s.finishedStatusClass])},[D(`span`,Dt,e(s.finishedStatusIcon),1),D(`span`,Ot,e(s.finishedStatusLabel),1),s.elapsedLabel?(M(),v(`span`,kt,e(s.elapsedLabel),1)):r(`v-if`,!0)],2)):(M(),v(`span`,At,e(s.$t(`@WORKBENCH:查看执行日志`)),1))]),D(`span`,jt,[D(`span`,Mt,e((o.job.output||``).length)+` `+e(s.$t(`@WORKBENCH:字符`)),1),D(`button`,{type:`button`,class:`wb-log-copy`,title:s.$t(`@WORKBENCH:复制全部(含提示词与输出)`),"aria-label":s.$t(`@WORKBENCH:复制全部`),onClick:J(s.copyAll,[`stop`])},` ⧉ `,8,Nt)])],8,bt),r(`
11
- body 容器:用 zen-ai-chat-ui 的 ChatContainer 渲染单轮对话。
12
- 隐藏 ChatContainer 自带的输入框(acu-chat-footer),续聊输入由父组件统一承载。
13
- 下方保留"重新执行"footer。
14
- `),z(D(`div`,Pt,[_(s.ChatContainer,{messages:s.chatMessages,"assistant-name":s.assistantLabel,"assistant-avatar":s.assistantAvatar,"show-avatar":!0,theme:s.configStore.theme,"tool-calls-config":{group:!0,collapseThreshold:2},class:`wb-job-chat`},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`]),r(` footer:任务结束后显示"重新执行",运行中不显示 `),s.canReExecute?(M(),v(`footer`,Ft,[D(`button`,{type:`button`,class:`wb-chat__action`,title:s.$t(`@WORKBENCH:用相同的提示词重新执行此任务`),"aria-label":s.$t(`@WORKBENCH:重新执行`),onClick:s.onReExecute},` ↻ `,8,It)])):r(`v-if`,!0),r(` 全屏查看 dialog `),_(u,{modelValue:s.fullscreenOpen,"onUpdate:modelValue":n[0]||=e=>s.fullscreenOpen=e,title:s.$t(`@WORKBENCH:模型返回 - 全屏查看`),fullscreen:``,"close-on-click-modal":!1,class:`wb-log-fullscreen-dialog`,onClosed:s.onFullscreenClosed},{default:W(()=>[D(`div`,Lt,[s.hasOutput?(M(),a(s.MarkdownRenderer,{key:0,source:s.fullscreenSource,class:`wb-log-fullscreen__render`},null,8,[`source`])):(M(),v(`div`,Rt,e(s.$t(`@WORKBENCH:(暂无输出)`)),1))],512)]),_:1},8,[`modelValue`,`title`])],512),[[P,!s.isCollapsed]]),r(` /.wb-log-details__body `)],2)}var Bt=Q(yt,[[`render`,zt],[`__scopeId`,`data-v-a4bb55c4`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/JobLogDetails.vue`]]);X(),B();var Vt=50,Ht=s({__name:`ExecutionLogManager`,setup(e,{expose:t}){t();function n(e){return e instanceof Error?e.message:String(e)}let r=Y([]),i=Y(0),a=ie({count:0,sizeMB:0,byStatus:{}}),o=Y(!1),s=Y(new Set),c=ie({q:``,status:``,page:1}),l=Y({maxCount:500,maxSizeMB:256}),d=ie({maxCount:500,maxSizeMB:256}),f=Y(!1),p=[{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:已取消`)}],m=q(()=>r.value.length>0&&r.value.every(e=>s.value.has(e.id))),h=q(()=>r.value.some(e=>s.value.has(e.id))&&!m.value);async function g(){o.value=!0;try{let e=new URLSearchParams;c.q&&e.set(`q`,c.q),c.status&&e.set(`status`,c.status),e.set(`limit`,String(Vt)),e.set(`offset`,String((c.page-1)*Vt));let t=await fetch(`/api/workbench/jobs/list?${e.toString()}`).then(e=>e.json());if(!t.success)throw Error(t.error||`list failed`);r.value=t.jobs,i.value=t.total,a.count=t.stats.count,a.sizeMB=t.stats.sizeMB,a.byStatus=t.stats.byStatus;let n=new Set(r.value.map(e=>e.id));for(let e of Array.from(s.value))n.has(e)||s.value.delete(e)}catch(e){F.error(Z(`@WORKBENCH:加载失败`)+`: `+n(e))}finally{o.value=!1}}async function _(){try{let e=await fetch(`/api/workbench/jobs/config`).then(e=>e.json());e.success&&(l.value=e.config,d.maxCount=e.config.maxCount,d.maxSizeMB=e.config.maxSizeMB)}catch{}}async function v(){f.value=!0;try{let e=await fetch(`/api/workbench/jobs/config`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({maxCount:d.maxCount,maxSizeMB:d.maxSizeMB})}).then(e=>e.json());if(!e.success)throw Error(e.error||`save failed`);l.value=e.config,F.success(Z(`@WORKBENCH:已保存策略`)),await g()}catch(e){F.error(Z(`@WORKBENCH:保存失败`)+`: `+n(e))}finally{f.value=!1}}function y(){c.page=1,g()}function b(){c.q=``,c.status=``,c.page=1,g()}function x(e,t){t?s.value.add(e):s.value.delete(e),s.value=new Set(s.value)}function S(e){if(e)for(let e of r.value)s.value.add(e.id);else for(let e of r.value)s.value.delete(e.id);s.value=new Set(s.value)}function C(e){F.info(Z(`@WORKBENCH:请到工作台主面板的对应任务上点击「重新执行」`))}async function w(e){try{await de.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`);s.value.delete(e),s.value=new Set(s.value),await g()}catch(e){F.error(Z(`@WORKBENCH:保存失败`)+`: `+n(e))}}async function T(){let e=Array.from(s.value);if(e.length!==0){try{await de.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`);F.success(Z(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e.length})),s.value=new Set,await g()}catch(e){F.error(Z(`@WORKBENCH:保存失败`)+`: `+n(e))}}}async function E(){let e=a.count;if(e!==0){try{await de.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`);F.success(Z(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e})),s.value=new Set,await g()}catch(e){F.error(Z(`@WORKBENCH:保存失败`)+`: `+n(e))}}}function D(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`}u(()=>{g(),_()});let O={errMsg:n,list:r,total:i,stats:a,loading:o,selectedIds:s,pageSize:Vt,filter:c,config:l,configDraft:d,configSaving:f,STATUS_OPTIONS:p,isAllOnPageSelected:m,isSomeOnPageSelected:h,load:g,loadConfig:_,saveConfig:v,onFilterChange:y,resetFilter:b,toggleSelect:x,toggleSelectAllOnPage:S,onReExecuteInLog:C,deleteOne:w,batchDelete:T,clearAll:E,formatDuration:D,get Document(){return ce},get Refresh(){return A},get $t(){return Z},get statusLabel(){return ft},get statusColor(){return pt},JobLogDetails:Bt};return Object.defineProperty(O,"__isScriptSetup",{enumerable:!1,value:!0}),O}});X(),b(),G();var Ut={class:`exec-logs`},Wt={class:`exec-logs__head`},Gt={class:`exec-logs__title-block`},Kt={class:`exec-logs__stats`},qt={class:`exec-logs__head-actions`},Jt={class:`exec-logs__config`},Yt={class:`exec-logs__config-label`},Xt={class:`exec-logs__config-field`},Zt={class:`exec-logs__config-name`},Qt={class:`exec-logs__config-field`},$t={class:`exec-logs__config-name`},en={class:`exec-logs__filter`},tn={key:0,class:`exec-logs__batch-meta`},nn={key:0,class:`exec-logs__batch`},rn={class:`exec-logs__list`},an={key:0,class:`exec-logs__empty`},on={class:`exec-logs__empty-art`,"aria-hidden":`true`},sn={class:`exec-logs__empty-title`},cn={class:`exec-logs__empty-hint`},ln={class:`exec-card__head`},un=[`title`],dn={class:`exec-card__meta`},fn={key:0,class:`exec-card__task`},pn={key:1,class:`exec-card__time`},mn={key:2,class:`exec-card__exit`},hn=[`title`,`onClick`],gn={key:0,class:`exec-card__error`},_n={key:1,class:`exec-logs__pager`};function vn(t,n,i,a,s,c){let l=p,u=Te,f=te,m=y,b=o,x=h,C=d,w=xe,T=me;return M(),v(`div`,Ut,[r(` 头部:统计 + 刷新 + 清空。
15
- 标题已由外层 el-dialog 提供,这里不再重复 h2。 `),D(`header`,Wt,[D(`div`,Gt,[D(`span`,Kt,e(a.$t(`@WORKBENCH:共 {count} 条,占 {size} MB`,{count:a.stats.count,size:a.stats.sizeMB})),1)]),D(`div`,qt,[_(l,{icon:a.Refresh,size:`small`,loading:a.loading,onClick:a.load},{default:W(()=>[g(e(a.$t(`@WORKBENCH:刷新`)),1)]),_:1},8,[`icon`,`loading`]),_(l,{type:`danger`,plain:``,size:`small`,disabled:a.stats.count===0,onClick:a.clearAll},{default:W(()=>[g(e(a.$t(`@WORKBENCH:清空全部`)),1)]),_:1},8,[`disabled`])])]),r(` 保留策略 `),D(`div`,Jt,[D(`span`,Yt,e(a.$t(`@WORKBENCH:保存策略`)),1),D(`span`,Xt,[D(`span`,Zt,e(a.$t(`@WORKBENCH:最大条数`)),1),_(u,{modelValue:a.configDraft.maxCount,"onUpdate:modelValue":n[0]||=e=>a.configDraft.maxCount=e,min:0,max:1e4,step:50,size:`small`,"controls-position":`right`,style:{width:`130px`}},null,8,[`modelValue`])]),D(`span`,Qt,[D(`span`,$t,e(a.$t(`@WORKBENCH:最大体积 (MB)`)),1),_(u,{modelValue:a.configDraft.maxSizeMB,"onUpdate:modelValue":n[1]||=e=>a.configDraft.maxSizeMB=e,min:0,max:10240,step:32,size:`small`,"controls-position":`right`,style:{width:`140px`}},null,8,[`modelValue`])]),_(l,{type:`primary`,size:`small`,loading:a.configSaving,onClick:a.saveConfig},{default:W(()=>[g(e(a.$t(`@WORKBENCH:保存策略`)),1)]),_:1},8,[`loading`])]),r(` 过滤栏 `),D(`div`,en,[_(f,{modelValue:a.filter.q,"onUpdate:modelValue":n[2]||=e=>a.filter.q=e,placeholder:a.$t(`@WORKBENCH:搜索标题 / 任务`),clearable:``,size:`small`,style:{width:`240px`},onKeyup:K(a.onFilterChange,[`enter`]),onClear:a.onFilterChange},null,8,[`modelValue`,`placeholder`]),_(b,{modelValue:a.filter.status,"onUpdate:modelValue":n[3]||=e=>a.filter.status=e,placeholder:a.$t(`@WORKBENCH:全部状态`),clearable:``,size:`small`,style:{width:`130px`},onChange:a.onFilterChange},{default:W(()=>[(M(),v(R,null,S(a.STATUS_OPTIONS,e=>_(m,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`])),64))]),_:1},8,[`modelValue`,`placeholder`]),_(l,{size:`small`,onClick:a.resetFilter},{default:W(()=>[g(e(a.$t(`@WORKBENCH:重置`)),1)]),_:1}),n[5]||=D(`span`,{class:`exec-logs__filter-spacer`},null,-1),a.selectedIds.size>0?(M(),v(`span`,tn,e(a.$t(`@WORKBENCH:已选择 {count} 项`,{count:a.selectedIds.size})),1)):r(`v-if`,!0)]),r(` 批量操作条 `),a.selectedIds.size>0?(M(),v(`div`,nn,[_(x,{"model-value":a.isAllOnPageSelected,indeterminate:a.isSomeOnPageSelected,onChange:a.toggleSelectAllOnPage},{default:W(()=>[g(e(a.isAllOnPageSelected?a.$t(`@WORKBENCH:取消全选`):a.$t(`@WORKBENCH:全选`)),1)]),_:1},8,[`model-value`,`indeterminate`]),_(l,{type:`danger`,size:`small`,onClick:a.batchDelete},{default:W(()=>[g(e(a.$t(`@WORKBENCH:批量删除`)),1)]),_:1})])):r(`v-if`,!0),r(` 列表 `),z((M(),v(`div`,rn,[!a.loading&&a.list.length===0?(M(),v(`div`,an,[D(`div`,on,[_(C,null,{default:W(()=>[_(a.Document)]),_:1})]),D(`div`,sn,e(a.$t(`@WORKBENCH:暂无执行日志`)),1),D(`div`,cn,e(a.$t(`@WORKBENCH:点击「执行任务」开始一次执行,日志会出现在这里。`)),1)])):r(`v-if`,!0),(M(!0),v(R,null,S(a.list,t=>(M(),v(`article`,{key:t.id,class:U([`exec-card`,{"is-selected":a.selectedIds.has(t.id)}])},[D(`header`,ln,[_(x,{"model-value":a.selectedIds.has(t.id),onChange:e=>a.toggleSelect(t.id,e)},null,8,[`model-value`,`onChange`]),D(`span`,{class:`exec-card__status`,style:N({color:a.statusColor(t.status),borderColor:a.statusColor(t.status)})},e(a.statusLabel(t.status)),5),D(`span`,{class:`exec-card__title`,title:t.title||a.$t(`@WORKBENCH:无标题`)},e(t.title||a.$t(`@WORKBENCH:无标题`)),9,un),n[6]||=D(`span`,{class:`exec-card__spacer`},null,-1),D(`span`,dn,[t.taskTitle?(M(),v(`span`,fn,`📁 `+e(t.taskTitle),1)):r(`v-if`,!0),t.startedAt?(M(),v(`span`,pn,`⏱ `+e(a.formatDuration(t.startedAt,t.endedAt)),1)):r(`v-if`,!0),t.exitCode===null?r(`v-if`,!0):(M(),v(`span`,mn,`exit `+e(t.exitCode),1))]),D(`button`,{type:`button`,class:`exec-card__del`,title:a.$t(`@WORKBENCH:删除`),onClick:e=>a.deleteOne(t.id)},`×`,8,hn)]),t.error?(M(),v(`p`,gn,`⚠ `+e(t.error),1)):r(`v-if`,!0),_(a.JobLogDetails,{job:t,onReExecute:a.onReExecuteInLog},null,8,[`job`])],2))),128))])),[[T,a.loading]]),r(` 分页 `),a.total>a.pageSize?(M(),v(`footer`,_n,[_(w,{"current-page":a.filter.page,"onUpdate:currentPage":n[4]||=e=>a.filter.page=e,"page-size":a.pageSize,total:a.total,layout:`prev, pager, next, total`,background:``,small:``,onCurrentChange:a.load},null,8,[`current-page`,`total`])])):r(`v-if`,!0)])}var yn=Q(Ht,[[`render`,vn],[`__scopeId`,`data-v-d3ebe953`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/ExecutionLogManager.vue`]]);B();var bn=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`]),xn=`.png,.jpg,.jpeg,.gif,.webp,.bmp,.svg,.pdf,.txt,.md,.csv,.json,.log`,Sn=20971520,Cn=3840,wn=new Set([`image/png`,`image/jpeg`,`image/jpg`,`image/webp`,`image/bmp`]);function Tn(e){if(e.size<=3670016)return!1;let t=String(e.type||``).toLowerCase();return t?wn.has(t):/\.(png|jpe?g|webp|bmp)$/i.test(e.name)}function En(e,t){return`${String(e||`attachment`).replace(/\.[^./\\]+$/,``)}.${t}`}async function Dn(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 On(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 kn(e){let t=await Dn(e);if(!t)return null;try{let n=[{edge:Cn,quality:.95},{edge:Cn,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 On(o,`image/webp`,e.quality)||await On(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 An(){let e=Y({}),t=Y(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(!bn.has(n.type)&&!n.name.match(/\.(png|jpg|jpeg|gif|webp|bmp|svg|pdf|txt|md|markdown|csv|json|log)$/i)){F.error(`${Z(`@WORKBENCH:不支持的文件类型`)}(${n.name})`);return}let c=a(t);if(c.length>=9){F.error(Z(`@WORKBENCH:单个任务最多 9 个附件`));return}if(c.find(e=>e.originalName===n.name&&e.size===n.size)){F.info(`${n.name} ${Z(`@WORKBENCH:已存在,已复用`)}`);return}let l=i(t);e.value[l]=!0;try{let e=n;if(Tn(n)){let t=await kn(n);t&&(e=r(t.blob,En(n.name,t.ext)),F.info(Z(`@WORKBENCH:图片过大,已压缩后上传:{from} → {to}`,{from:g(n.size),to:g(e.size)})))}if(e.size>20971520){F.error(`「${n.name}」${Z(`@WORKBENCH:超过 {size} 限制`,{size:g(Sn)})}`);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),F.success(`${Z(`@WORKBENCH:已添加:`)}${e.name}`)}else F.error(i.error||Z(`@WORKBENCH:上传失败`))}catch(e){F.error(Z(`@WORKBENCH:上传失败`)+`:`+(e&&e.message||e))}finally{e.value[l]=!1}}async function f(e,t){try{await de.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)),F.success(Z(`@WORKBENCH:已删除`))):F.error(n.error||Z(`@WORKBENCH:删除失败`))}function p(e){let t=document.createElement(`input`);t.type=`file`,t.accept=xn,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}}X();var jn=`__simple`,Mn=65536;function Nn(e,t){function n(t){if(!t)return[];let n=`${t.id}${jn}`;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:q(()=>{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>Mn?`\u2026(前文已截断)\n${o.slice(-65536)}`:o,l=s.length>Mn?`\u2026(前文已截断)\n${s.slice(-65536)}`:s,u=!!c,d=!!l,f=_t(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:jn,MAX_LOG_DISPLAY_SIMPLE:Mn}}function Pn(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?F.success(t.message||Z(`@WORKBENCH:已加入执行队列`)):F.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){F.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?F.success(a.message||Z(`@WORKBENCH:已加入续接队列`)):F.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){F.error(Z(`@WORKBENCH:找不到对应任务,无法重新执行`));return}await o(n)}async function u(e){try{await de.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?F.success(Z(`@WORKBENCH:已发送停止信号`)):F.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 de.confirm(o,Z(`@WORKBENCH:清空执行内容`),{confirmButtonText:Z(`@WORKBENCH:清空`),cancelButtonText:Z(`@WORKBENCH:取消`),type:`warning`})}catch{return}if(a>0){F.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(),F.success(s.message||Z(`@WORKBENCH:已清空执行内容`))):F.error(s?.error||Z(`@WORKBENCH:清空失败`))}return{runTask:o,continueChat:s,onContinueSendFromChat:c,onReExecuteJob:l,cancelJob:u,clearExecutionForSelectedTask:d}}B();function Fn(){let e=Y([]),t=Y([]),n=Y([]),r=Y({path:``,name:``}),i=Ve();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`&&F.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:(F.error(e.error||Z(`@WORKBENCH:保存失败`)),null)}catch{return F.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}}B(),X();var In=`__no_project__`,Ln=`wb.collapsedGroupPaths.v1`,Rn=`wb.seenGroupPaths.v1`;function zn(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 Bn(e,t){try{localStorage.setItem(e,JSON.stringify(Array.from(t)))}catch{}}function Vn(e,t){let n=Y(zn(Ln)),r=Y(zn(Rn));I(n,e=>Bn(Ln,e),{deep:!1}),I(r,e=>Bn(Rn,e),{deep:!1});function i(e){return n.value.has(e)}function a(e){n.value.has(e)?n.value.delete(e):n.value.add(e),n.value=new Set(n.value);let t=new Set(r.value);t.add(e),r.value=t}let o=q(()=>{let r=e.value,i=new Map;for(let e of r){let t=$(e.projectPath)||In;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===In?1:t===In?-1:e.localeCompare(t));return{groups:o.map(e=>({path:e,label:e===In?Z(`@WORKBENCH:未关联项目`):e,tasks:i.get(e)})),hasMultiple:o.length>1||o.length===1&&n.value.has(o[0])}});function s(e){if(!e||e===In)return e;let t=e.split(/[\\/]/).filter(Boolean);return t.length<=1?e:t.slice(-2).join(`/`)}let c=q(()=>`${$(t.value.path)}|${o.value.groups.map(e=>e.path).join(`
16
- `)}`);return I(c,()=>{let e=$(t.value.path);if(!e)return;let i=new Set(n.value),a=new Set(r.value),s=!1;for(let t of o.value.groups)a.has(t.path)||(a.add(t.path),t.path!==e&&(i.add(t.path),s=!0));s&&(n.value=i),r.value=a},{immediate:!0}),{groupedTasksList:o,isGroupCollapsed:i,toggleGroupCollapsed:a,shortProjectLabel:s}}X(),B();var Hn=5,Un=s({__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:n}){t();let r=e,i=n,a=q(()=>r.currentProject),o=q(()=>r.tasks),{groupedTasksList:s,isGroupCollapsed:c,toggleGroupCollapsed:l,shortProjectLabel:u}=Vn(o,a),d=q(()=>$(r.currentProject.path));function f(e){return!!e.projectPath&&$(e.projectPath)!==d.value}let p=q(()=>{let e=d.value;return r.prompts.filter(t=>!t.projectPath||$(t.projectPath)===e)});function m(e){return(e.title||``).trim()||(e.desc||``).replace(/\s+/g,` `).trim()}function h(e){let t=m(e),n=Z(`@WORKBENCH:拖动排序提示`);return t?`${t} · ${n}`:n}function g(e){return r.isTaskRunning(e)}let _=Y(null),v=Y(null),y=Y(null),b=Y(null),x=Y(null),S=null;function w(){_.value=null,v.value=null,y.value=null,b.value=null,x.value=null,S=null}function T(e,t,n,r){e.button===0&&(S={pointerY:e.clientY,li:r,taskId:t.id,groupPath:n},window.addEventListener(`mousemove`,E),window.addEventListener(`mouseup`,D,{once:!0}))}function E(e){if(!S)return;if(_.value===null){if(Math.abs(e.clientY-S.pointerY)<Hn)return;_.value=S.taskId,v.value=S.groupPath,window.getSelection()?.removeAllRanges(),document.body.style.userSelect=`none`}let t=document.elementFromPoint(e.clientX,e.clientY);if(!t)return;let n=t.closest(`.wb-task-item`);if(!n){y.value=null,b.value=null,x.value=null;return}let r=n.getAttribute(`data-task-id`),i=n.getAttribute(`data-group-path`);if(!r||!i)return;if(i!==v.value){y.value=null,b.value=null,x.value=null;return}let a=n.getBoundingClientRect(),o=a.top+a.height/2;y.value=r,b.value=i,x.value=e.clientY<o?`before`:`after`}function D(e){if(window.removeEventListener(`mousemove`,E),document.body.style.userSelect=``,!S){w();return}let t=S.groupPath,n=S.taskId,r=y.value,a=x.value,o=b.value;if(w(),!r||!a||o!==t)return;let c=s.value.groups.find(e=>e.path===t);if(!c)return;let l=c.tasks.map(e=>e.id),u=l.indexOf(n);if(u<0)return;l.splice(u,1);let d=l.indexOf(r)+ +(a===`after`);l.splice(d,0,n),i(`reorder-tasks`,{groupPath:t,orderedIds:l})}let O={props:r,emit:i,currentProjectRef:a,tasksRef:o,groupedTasksList:s,isGroupCollapsed:c,toggleGroupCollapsed:l,shortProjectLabel:u,currentProjectKey:d,isOtherProject:f,availablePrompts:p,taskDisplayName:m,taskTooltip:h,taskIsRunning:g,draggingTaskId:_,dragStartGroupPath:v,dragOverTaskId:y,dragOverGroupPath:b,dragPosition:x,get dragStart(){return S},set dragStart(e){S=e},DRAG_THRESHOLD_PX:Hn,resetDragState:w,onTaskMouseDown:T,onWindowMouseMove:E,onWindowMouseUp:D,get $t(){return Z},get Plus(){return C},get Close(){return ae},get DocumentAdd(){return be},get Memo(){return pe},get Folder(){return we},get ArrowDown(){return he},get ArrowRight(){return re},get CopyDocument(){return ve}};return Object.defineProperty(O,"__isScriptSetup",{enumerable:!1,value:!0}),O}});X(),b(),G();var Wn={class:`wb-sidebar`},Gn={class:`wb-section`},Kn=[`disabled`],qn=[`aria-expanded`,`title`,`onClick`,`onKeydown`],Jn=[`title`],Yn={class:`wb-pill wb-task-group__count`},Xn=[`data-task-id`,`data-group-path`,`title`,`onClick`,`onMousedown`],Zn={class:`wb-task-item__body`},Qn=[`title`],$n=[`title`],er={class:`wb-task-item__action-group`},tr=[`title`,`aria-label`,`onClick`],nr=[`onClick`,`title`,`aria-label`],rr={key:0,class:`wb-empty wb-empty--rich`},ir={class:`wb-empty__art`,"aria-hidden":`true`},ar={class:`wb-empty__title`},or={class:`wb-empty__hint`},sr={class:`wb-empty__cta`},cr={class:`wb-section`},lr={class:`wb-section__head`},ur={class:`wb-section__tag wb-section__tag--accent`},dr={class:`wb-section__title`},fr={class:`wb-pill wb-section__count`},pr=[`title`,`aria-label`],mr={class:`wb-prompt-list`},hr={class:`wb-prompt-item__icon`},gr=[`onClick`,`title`],_r=[`title`],vr=[`title`],yr=[`onClick`,`title`,`aria-label`],br={key:0,class:`wb-empty wb-empty--compact`};function xr(t,n,i,o,s,c){let l=d,u=p;return M(),v(`aside`,Wn,[D(`section`,Gn,[r(` 任务分组 header 已去掉:"任务"/"任务列表"/计数 三件套冗余,下方任务项本身已能自我说明。
17
- 提示词分组保留 header(含 + 新建按钮 + 计数),信息密度不一对齐,后续按需统一。 `),D(`button`,{class:`wb-new-btn`,disabled:i.creatingTask,onClick:n[0]||=e=>o.emit(`create-task`)},[_(l,{class:`wb-new-btn__icon`},{default:W(()=>[_(o.Plus)]),_:1}),D(`span`,null,e(o.$t(`@WORKBENCH:新建任务`)),1),n[3]||=D(`span`,{class:`wb-new-btn__shortcut`},`N`,-1)],8,Kn),D(`ul`,{class:U([`wb-task-list`,{"is-grouped":o.groupedTasksList.hasMultiple}])},[(M(!0),v(R,null,S(o.groupedTasksList.groups,t=>(M(),v(R,{key:t.path},[o.groupedTasksList.hasMultiple?(M(),v(`li`,{key:0,class:U([`wb-task-group__head`,{"is-current":t.path===o.currentProjectKey,"is-collapsed":o.isGroupCollapsed(t.path)}]),role:`button`,tabindex:`0`,"aria-expanded":!o.isGroupCollapsed(t.path),title:o.isGroupCollapsed(t.path)?o.$t(`@WORKBENCH:展开`):o.$t(`@WORKBENCH:收起`),onClick:e=>o.toggleGroupCollapsed(t.path),onKeydown:[K(J(e=>o.toggleGroupCollapsed(t.path),[`prevent`]),[`enter`]),K(J(e=>o.toggleGroupCollapsed(t.path),[`prevent`]),[`space`])]},[_(l,{class:`wb-task-group__caret`},{default:W(()=>[(M(),a(ye(o.isGroupCollapsed(t.path)?o.ArrowRight:o.ArrowDown)))]),_:2},1024),_(l,{class:`wb-task-group__icon`},{default:W(()=>[_(o.Folder)]),_:1}),D(`span`,{class:`wb-task-group__name`,title:t.path===o.currentProjectKey?i.currentProject.path:t.label},e(t.path===o.currentProjectKey?i.currentProject.name:o.shortProjectLabel(t.label)),9,Jn),D(`span`,Yn,e(t.tasks.length),1)],42,qn)):r(`v-if`,!0),o.isGroupCollapsed(t.path)?r(`v-if`,!0):(M(!0),v(R,{key:1},S(t.tasks,n=>(M(),v(`li`,{key:n.id,class:U([`wb-task-item`,{active:n.id===i.selectedTaskId,"is-other-project":o.isOtherProject(n),"is-running":o.taskIsRunning(n),"is-dragging":o.draggingTaskId===n.id,"is-drop-before":o.dragOverTaskId===n.id&&o.dragPosition===`before`,"is-drop-after":o.dragOverTaskId===n.id&&o.dragPosition===`after`}]),"data-task-id":n.id,"data-group-path":t.path,title:o.taskTooltip(n),onClick:e=>o.emit(`select-task`,n),onMousedown:e=>o.onTaskMouseDown(e,n,t.path,e.currentTarget)},[r(` 单行展示:只显示标题;没写标题用任务描述压平后顶上(CSS ellipsis 截断)。
18
- 子任务数 / 附件数 等 meta 行已移除,降噪 `),D(`div`,Zn,[D(`div`,{class:`wb-task-item__title`,title:o.taskDisplayName(n)},e(o.taskDisplayName(n)),9,Qn)]),o.taskIsRunning(n)?(M(),v(`span`,{key:0,class:`wb-task-item__running-dot`,title:o.$t(`@WORKBENCH:执行中`),"aria-hidden":`true`},null,8,$n)):r(`v-if`,!0),D(`div`,er,[D(`button`,{class:`wb-task-item__copy`,title:o.$t(`@WORKBENCH:复制任务`),"aria-label":o.$t(`@WORKBENCH:复制任务`),onClick:J(e=>o.emit(`copy-task`,n),[`stop`])},[_(l,null,{default:W(()=>[_(o.CopyDocument)]),_:1})],8,tr),r(` 执行中不允许删除:避免误杀正在跑的实例(jobs 还在内存里,
19
- 任务从 tasks.json 消失后,runSingleSubtask 读不到 task
20
- 会留一堆孤儿 job)。后端 DELETE 路由也加了同样的 live-job 守卫兜底 `),o.taskIsRunning(n)?r(`v-if`,!0):(M(),v(`button`,{key:0,class:`wb-task-item__del`,onClick:J(e=>o.emit(`delete-task`,n),[`stop`]),title:o.$t(`@WORKBENCH:删除`),"aria-label":o.$t(`@WORKBENCH:删除`)},[_(l,null,{default:W(()=>[_(o.Close)]),_:1})],8,nr))])],42,Xn))),128))],64))),128)),i.tasks.length===0?(M(),v(`li`,rr,[D(`div`,ir,[_(l,null,{default:W(()=>[_(o.DocumentAdd)]),_:1})]),D(`div`,ar,e(o.$t(`@WORKBENCH:暂无任务`)),1),D(`div`,or,e(o.$t(`@WORKBENCH:点击上方按钮新建`)),1),D(`div`,sr,[_(u,{type:`primary`,size:`small`,icon:o.Plus,loading:i.creatingTask,onClick:n[1]||=e=>o.emit(`create-task`)},{default:W(()=>[g(e(o.$t(`@WORKBENCH:新建任务`)),1)]),_:1},8,[`icon`,`loading`])])])):r(`v-if`,!0)],2)]),D(`section`,cr,[D(`header`,lr,[D(`span`,ur,e(o.$t(`@WORKBENCH:提示`)),1),D(`h3`,dr,e(o.$t(`@WORKBENCH:预置提示词`)),1),D(`span`,fr,e(o.availablePrompts.length),1),D(`button`,{class:`wb-section__action`,onClick:n[2]||=e=>o.emit(`open-create-prompt`),title:o.$t(`@WORKBENCH:新建提示词`),"aria-label":o.$t(`@WORKBENCH:新建提示词`)},[_(l,null,{default:W(()=>[_(o.Plus)]),_:1})],8,pr)]),D(`ul`,mr,[(M(!0),v(R,null,S(o.availablePrompts,t=>(M(),v(`li`,{key:t.id,class:`wb-prompt-item`},[D(`div`,hr,[_(l,null,{default:W(()=>[_(o.Memo)]),_:1})]),D(`span`,{class:`wb-prompt-item__name`,onClick:e=>o.emit(`open-edit-prompt`,t),title:t.content},e(t.name),9,gr),t.projectPath?(M(),v(`span`,{key:1,class:`wb-prompt-item__tag wb-prompt-item__tag--project`,title:t.projectPath},e(o.shortProjectLabel(t.projectPath)),9,vr)):(M(),v(`span`,{key:0,class:`wb-prompt-item__tag`,title:o.$t(`@WORKBENCH:全局(所有项目可用)`)},e(o.$t(`@WORKBENCH:全局(所有项目可用)`)),9,_r)),D(`button`,{class:`wb-prompt-item__del`,onClick:e=>o.emit(`delete-prompt`,t),title:o.$t(`@WORKBENCH:删除`),"aria-label":o.$t(`@WORKBENCH:删除`)},[_(l,null,{default:W(()=>[_(o.Close)]),_:1})],8,yr)]))),128)),o.availablePrompts.length===0?(M(),v(`li`,br,e(o.$t(`@WORKBENCH:暂无提示词`)),1)):r(`v-if`,!0)])])])}var Sr=Q(Un,[[`render`,xr],[`__scopeId`,`data-v-458e9455`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/components/WorkbenchSidebar.vue`]]);B();function Cr(){let e=Y([]),t=Y([]),n=Y(``),r=Y(!1),i=Y(!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||F.error(r?.error||Z(`@WORKBENCH:读取项目列表失败`)),!1)}catch(e){return a||F.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),!1}finally{r.value=!1}}return{projects:e,boardTasks:t,currentProjectPath:n,loading:r,loaded:i,loadProjects:a}}B();function wr(){let e=Y(!0),t=Y([]),n=Y([]),r=Y([]),i=Y(null),a=Y(!1),o=Y(!1),s=Y(!1),c=Y(``),l=Y({});async function u(o=!1){try{let s=await fetch(`/api/workbench/orchestrator`,{cache:`no-store`}).then(e=>e.json());return s?.success?(e.value=s.active!==!1,t.value=Array.isArray(s.instructions)?s.instructions:[],n.value=Array.isArray(s.activity)?s.activity:[],r.value=Array.isArray(s.running)?s.running:[],i.value=s.updatedAt||null,c.value=typeof s.defaultPrompt==`string`?s.defaultPrompt:``,l.value=s.projectPrompts&&typeof s.projectPrompts==`object`?s.projectPrompts:{},a.value=!0,!0):(o||F.error(s?.error||Z(`@WORKBENCH:读取编排状态失败`)),!1)}catch(e){return o||F.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),!1}}async function d(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?(c.value=typeof t.defaultPrompt==`string`?t.defaultPrompt:``,F.success(Z(`@WORKBENCH:已保存全局默认提示词`)),!0):(F.error(t?.error||Z(`@WORKBENCH:保存失败`)),!1)}catch(e){return F.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),!1}}async function f(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?(l.value=n.projectPrompts&&typeof n.projectPrompts==`object`?n.projectPrompts:{},F.success(Z(`@WORKBENCH:已保存项目默认提示词`)),!0):(F.error(n?.error||Z(`@WORKBENCH:保存失败`)),!1)}catch(e){return F.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),!1}}async function p(t){if(o.value)return!1;let n=e.value;e.value=t,o.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,F.success(e.value?Z(`@WORKBENCH:已恢复调度`):Z(`@WORKBENCH:已暂停调度,派发将只建任务不执行`)),!0):(e.value=n,F.error(r?.error||Z(`@WORKBENCH:切换调度状态失败`)),!1)}catch(t){return e.value=n,F.error(Z(`@WORKBENCH:网络错误: `)+(t?.message||t)),!1}finally{o.value=!1}}async function m(e){if(s.value)return null;s.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 u(!0),{task:t.task||null,ran:!!t.ran}):(F.error(t?.error||Z(`@WORKBENCH:派发失败`)),null)}catch(e){return F.error(Z(`@WORKBENCH:网络错误: `)+(e?.message||e)),null}finally{s.value=!1}}return{active:e,instructions:t,activity:n,running:r,updatedAt:i,loaded:a,togglingSchedule:o,dispatching:s,defaultPrompt:c,projectPrompts:l,loadOrchestrator:u,setSchedulingActive:p,dispatch:m,saveDefaultPrompt:d,saveProjectPrompt:f}}var Tr=6e4,Er=60*Tr,Dr=24*Er;function Or(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<Tr?Z(`@WORKBENCH:刚刚`):r<Er?Z(`@WORKBENCH:N 分钟前`,{n:Math.floor(r/Tr)}):r<Dr?Z(`@WORKBENCH:N 小时前`,{n:Math.floor(r/Er)}):r<30*Dr?Z(`@WORKBENCH:N 天前`,{n:Math.floor(r/Dr)}):new Date(n).toLocaleDateString()}function kr(e,t,n=Date.now()){if(!e)return``;let r=new Date(e).getTime();if(Number.isNaN(r))return``;let i=t?new Date(t).getTime():n;if(Number.isNaN(i))return``;let a=Math.max(0,i-r),o=Math.floor(a/1e3),s=Math.floor(o/3600),c=Math.floor(o%3600/60),l=o%60;return s>0?Z(`@WORKBENCH:N 小时 M 分`,{n:s,m:c}):c>0?Z(`@WORKBENCH:N 分 M 秒`,{n:c,m:l}):Z(`@WORKBENCH:N 秒`,{n:l})}function Ar(e,t){return e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate()}function jr(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(Ar(n,a))return i;if(Ar(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}`}X(),B();var Mr=s({__name:`WorkbenchProjectPanel`,props:{projects:{type:Array,required:!0},selectedKey:{type:String,required:!0},loading:{type:Boolean,required:!0}},emits:[`select`],setup(e,{expose:n,emit:r}){n();let i=e,a=r,o=q(()=>[...i.projects].sort((e,t)=>{if(e.stats.runningJobs>0!=t.stats.runningJobs>0)return e.stats.runningJobs>0?-1:1;let n=e.stats.lastActiveAt||``,r=t.stats.lastActiveAt||``;return n===r?e.name.localeCompare(t.name):r.localeCompare(n)})),s=Y(``),l=Y(!1),d=Y(!1),p=q(()=>!!s.value.trim()||l.value||d.value),m=q(()=>{let e=s.value.trim().toLowerCase();return o.value.filter(t=>l.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 h(){s.value=``,l.value=!1,d.value=!1}let g=q(()=>i.projects.reduce((e,t)=>({running:e.running+t.stats.runningJobs,done:e.done+t.stats.done,total:e.total+t.stats.total}),{running:0,done:0,total:0})),_=q(()=>g.value.total>0?Math.round(g.value.done/g.value.total*100):0);function v(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 y(e){return!!(e.git&&e.git.isGitRepo&&(e.git.detached||e.git.branch))}let b=Y(null),S=Y(null);function C(e,t){if(b.value===e.key){b.value=null;return}S.value=t.currentTarget,b.value=e.key}function w(){b.value=null}function T(e){if(!b.value)return;let t=e.target;if(t&&!S.value?.contains(t)){for(let e of Array.from(document.querySelectorAll(`.proj-open-menu`)))if(e.contains(t))return;b.value=null}}u(()=>document.addEventListener(`mousedown`,T,!0)),f(()=>document.removeEventListener(`mousedown`,T,!0));let D=Ne(),ee=Y(!1),k=Y(null);function te(e){return D.lastCheckedAt!==null&&!D.isToolAvailable(e)}async function A(e){w();let t=await Ge(e.path);t.success?F.success(t.message||Z(`@WORKBENCH:已在文件管理器中打开文件夹`)):F.error(t.error||Z(`@WORKBENCH:打开文件夹失败`))}async function j(e){w();let t=await Ue(e.path);t.success?F.success(t.message||Z(`@67CE7:已在终端中打开目录`)):F.error(t.error||Z(`@WORKBENCH:打开终端失败`))}async function M(e){w();let t=await Re(e.path);t.success?F.success(Z(`@WORKBENCH:已在新标签页启动 g ui`)):F.error(t.error||Z(`@WORKBENCH:启动 g ui 失败`))}async function re(e){if(w(),e.name)try{await navigator.clipboard.writeText(e.name),F.success(Z(`@67CE7:已复制文件夹名称`))}catch{F.error(Z(`@67CE7:复制失败`))}}async function N(e,t,n){if(w(),!await Le()){F.warning(Z(`@67CE7:工具检测失败,请稍后重试`));return}if(!D.isToolAvailable(t)){k.value=t,ee.value=!0;return}let r=await Be(t,e.path,n);r.success?F.success(r.message||Z(`@67CE7:已用 {tool} 打开目录`,{tool:qe[t]})):F.error(`${Z(`@67CE7:打开失败: `)}${r.error??``}`)}let P={props:i,emit:a,ordered:o,query:s,onlyWithTasks:l,hideNonGit:d,filtering:p,visible:m,clearFilters:h,totals:g,overallProgress:_,gitLine:v,hasBranchIcon:y,openMenuKey:b,menuTriggerEl:S,toggleOpenMenu:C,closeOpenMenu:w,onDocumentMouseDown:T,toolsStore:D,installVisible:ee,installTool:k,toolMissing:te,openInFileManager:A,openInTerminal:j,launchGui:M,copyFolderName:re,openWithTool:N,get $t(){return Z},get CopyDocument(){return ve},get Folder(){return we},get FolderOpened(){return E},get Grid(){return O},get Monitor(){return x},get MoreFilled(){return c},get Promotion(){return t},get Search(){return ne},SvgIcon:Ae,ToolInstallDialog:Pe,get claudeCodeIcon(){return ze},get OPEN_WITH_TOOLS(){return He},get relativeTimeFromIso(){return Or}};return Object.defineProperty(P,"__isScriptSetup",{enumerable:!1,value:!0}),P}});b(),X(),G();var Nr={class:`proj`},Pr={class:`proj__head`},Fr={class:`proj__title`},Ir={class:`proj__count`},Lr={key:0,class:`proj__tools`},Rr={class:`proj__search`},zr=[`placeholder`,`aria-label`],Br={class:`proj__toggles`},Vr=[`aria-pressed`,`title`],Hr=[`aria-pressed`,`title`],Ur={class:`proj__list`},Wr=[`title`],Gr={class:`proj-item__row1`},Kr={class:`proj-item__name`},qr={key:0,class:`proj-item__running`,"aria-hidden":`true`},Jr={class:`proj-item__num`},Yr={class:`proj-item__row2`},Xr={key:0,class:`proj-item__running-text`},Zr={key:0,class:`proj-item__row3`},Qr={class:`proj-item__bar`,"aria-hidden":`true`},$r={class:`proj-item__progress-text`},ei=[`title`,`onClick`,`onKeydown`],ti={class:`proj-item__row1`},ni={class:`proj-item__name`},ri={class:`proj-item__signals`},ii={key:0,class:`proj-item__running`,"aria-hidden":`true`},ai={key:1,class:`proj-item__badge`},oi={class:`proj-item__row2`},si={key:0,class:`proj-chip proj-chip--missing`},ci={key:0,class:`proj-item__branch`},li={class:`proj-item__branch-name`},ui={key:1,class:`proj-chip proj-chip--ahead`},di={key:2,class:`proj-chip proj-chip--behind`},fi={key:3,class:`proj-chip proj-chip--dirty`},pi={class:`proj-item__time`},mi={key:0,class:`proj-item__row3`},hi={class:`proj-item__bar`,"aria-hidden":`true`},gi={class:`proj-item__progress-text`},_i={key:1,class:`proj-item__actions`},vi=[`title`,`aria-label`,`onClick`],yi=[`title`,`aria-label`,`aria-expanded`,`onClick`],bi=[`aria-label`],xi=[`onClick`,`onKeydown`],Si={class:`proj-menu__icon`},Ci={class:`proj-menu__label`},wi=[`onClick`,`onKeydown`],Ti={class:`proj-menu__icon`},Ei={class:`proj-menu__label`},Di=[`onClick`,`onKeydown`],Oi={class:`proj-menu__icon`},ki={class:`proj-menu__label`},Ai=[`onClick`,`onKeydown`],ji={class:`proj-menu__icon`},Mi={class:`proj-menu__label`},Ni={class:`proj-menu__title`,role:`presentation`},Pi=[`onClick`,`onKeydown`],Fi={class:`proj-menu__icon`},Ii={class:`proj-menu__label`},Li={key:0,class:`proj-menu__hint`},Ri=[`onClick`,`onKeydown`],zi={class:`proj-menu__icon`},Bi=[`src`],Vi={class:`proj-menu__label`},Hi={class:`proj-menu__hint`},Ui=[`onClick`,`onKeydown`],Wi={class:`proj-menu__icon`},Gi=[`src`],Ki={class:`proj-menu__label`},qi={key:0,class:`proj-empty`},Ji={class:`proj-empty__title`},Yi={class:`proj-empty__hint`},Xi={key:1,class:`proj-empty`},Zi={class:`proj-empty__title`};function Qi(t,n,i,o,s,c){let l=d,u=_e;return M(),v(`section`,Nr,[D(`header`,Pr,[D(`h3`,Fr,e(o.$t(`@WORKBENCH:项目列表`)),1),D(`span`,Ir,[o.filtering?(M(),v(R,{key:0},[g(e(o.$t(`@WORKBENCH:匹配 {n}/{total} 个项目`,{n:o.visible.length,total:i.projects.length})),1)],64)):(M(),v(R,{key:1},[g(e(i.projects.length),1)],64))])]),r(` 一个项目都没有时不渲染筛选条:没有可筛的东西,这一行只是占位 `),i.projects.length>0?(M(),v(`div`,Lr,[D(`div`,Rr,[_(l,{class:`proj__search-icon`,"aria-hidden":`true`},{default:W(()=>[_(o.Search)]),_:1}),z(D(`input`,{"onUpdate:modelValue":n[0]||=e=>o.query=e,class:`proj__search-input`,type:`search`,placeholder:o.$t(`@WORKBENCH:搜索项目名称或路径`),"aria-label":o.$t(`@WORKBENCH:搜索项目名称或路径`),onKeydown:n[1]||=K(e=>o.query=``,[`esc`])},null,40,zr),[[V,o.query]])]),D(`div`,Br,[D(`button`,{type:`button`,class:U([`proj__toggle`,{"is-on":o.onlyWithTasks}]),"aria-pressed":o.onlyWithTasks,title:o.$t(`@WORKBENCH:只显示有任务的项目`),onClick:n[2]||=e=>o.onlyWithTasks=!o.onlyWithTasks},[D(`span`,null,e(o.$t(`@WORKBENCH:只看有任务`)),1)],10,Vr),D(`button`,{type:`button`,class:U([`proj__toggle`,{"is-on":o.hideNonGit}]),"aria-pressed":o.hideNonGit,title:o.$t(`@WORKBENCH:只显示 Git 仓库`),onClick:n[3]||=e=>o.hideNonGit=!o.hideNonGit},[D(`span`,null,e(o.$t(`@WORKBENCH:隐藏非 Git`)),1)],10,Hr)])])):r(`v-if`,!0),D(`ul`,Ur,[D(`li`,{class:U([`proj-item proj-item--all`,{"is-active":i.selectedKey===``}]),role:`button`,tabindex:`0`,title:o.$t(`@WORKBENCH:全部项目`),onClick:n[4]||=e=>o.emit(`select`,null),onKeydown:[n[5]||=K(J(e=>o.emit(`select`,null),[`prevent`]),[`enter`]),n[6]||=K(J(e=>o.emit(`select`,null),[`prevent`]),[`space`])]},[D(`div`,Gr,[_(l,{class:`proj-item__icon`},{default:W(()=>[_(o.Grid)]),_:1}),D(`span`,Kr,e(o.$t(`@WORKBENCH:全部项目`)),1),o.totals.running>0?(M(),v(`span`,qr)):r(`v-if`,!0),D(`span`,Jr,e(i.projects.length),1)]),D(`div`,Yr,[D(`span`,null,e(o.$t(`@WORKBENCH:{n} 个项目`,{n:i.projects.length})),1),o.totals.running>0?(M(),v(`span`,Xr,e(o.$t(`@WORKBENCH:{n} 个执行中`,{n:o.totals.running})),1)):r(`v-if`,!0)]),r(` 一个任务都没有时整行不渲染(「0/0 任务完成」+ 空进度条是纯噪声) `),o.totals.total>0?(M(),v(`div`,Zr,[D(`span`,Qr,[D(`i`,{class:`proj-item__bar-fill`,style:N({width:o.overallProgress+`%`})},null,4)]),D(`span`,$r,e(o.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:o.totals.done,total:o.totals.total})),1)])):r(`v-if`,!0)],42,Wr),(M(!0),v(R,null,S(o.visible,t=>(M(),v(`li`,{key:t.key,class:U([`proj-item`,{"is-active":t.key===i.selectedKey,"is-running":t.stats.runningJobs>0,"is-missing":t.exists===!1}]),role:`button`,tabindex:`0`,title:t.path,onClick:e=>o.emit(`select`,t),onKeydown:[K(J(e=>o.emit(`select`,t),[`self`,`prevent`]),[`enter`]),K(J(e=>o.emit(`select`,t),[`self`,`prevent`]),[`space`])]},[D(`div`,ti,[_(l,{class:`proj-item__icon`},{default:W(()=>[_(o.Folder)]),_:1}),D(`span`,ni,e(t.name),1),r(` 运行中 / 当前 这两个信号与 hover 才出现的操作按钮锚在同一个右端点:
21
- hover 时整组淡出让位给按钮,而不是让图标压在徽标上 `),D(`span`,ri,[t.stats.runningJobs>0?(M(),v(`span`,ii)):r(`v-if`,!0),t.isCurrent?(M(),v(`span`,ai,e(o.$t(`@WORKBENCH:当前`)),1)):r(`v-if`,!0)])]),D(`div`,oi,[t.exists===!1?(M(),v(`span`,si,e(o.$t(`@WORKBENCH:目录不存在`)),1)):(M(),v(R,{key:1},[r(` gitLine 为空即"不是 Git 仓库":不给文字,也不给图标 `),o.gitLine(t)?(M(),v(`span`,ci,[o.hasBranchIcon(t)?(M(),a(o.SvgIcon,{key:0,"icon-class":`git-branch`,"class-name":`proj-item__branch-icon`})):r(`v-if`,!0),D(`span`,li,e(o.gitLine(t)),1)])):r(`v-if`,!0),t.git&&t.git.ahead>0?(M(),v(`span`,ui,`↑`+e(t.git.ahead),1)):r(`v-if`,!0),t.git&&t.git.behind>0?(M(),v(`span`,di,`↓`+e(t.git.behind),1)):r(`v-if`,!0),t.git&&t.git.changed>0?(M(),v(`span`,fi,`●`+e(t.git.changed),1)):r(`v-if`,!0)],64)),D(`span`,pi,e(o.relativeTimeFromIso(t.stats.lastActiveAt)),1)]),r(` 同上:这个项目一个任务都没有就不给进度行 `),t.stats.total>0?(M(),v(`div`,mi,[D(`span`,hi,[D(`i`,{class:`proj-item__bar-fill`,style:N({width:t.stats.progress+`%`})},null,4)]),D(`span`,gi,e(o.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:t.stats.done,total:t.stats.total})),1)])):r(`v-if`,!0),r(` 打开动作:与行主体平级,绝对定位锚在 row1 右端(不占位,否则「当前」徽标
22
- 永远离右边缘一条);.stop 阻止冒泡到行的选中逻辑。目录都不存在了就不渲染——
23
- 点了只会弹一个「无法打开目录」的报错。
24
- 两个按钮:最常用的「打开文件夹」留一键直达,其余打开方式(终端 / 编辑器 /
25
- AI 工具 / 新标签页跑 g ui)收进「打开方式」菜单 —— 一行放不下七个图标,
26
- 而项目名被挤成省略号比多点一次更难受。
27
- ⚠️ 行上的 keydown 必须带 .self:事件从按钮冒泡上来,不带 .self 时
28
- 焦点在按钮上按回车会「选中该行 + preventDefault 掉按钮自己的激活」,
29
- 键盘用户反而打不开文件夹。 `),t.exists===!1?r(`v-if`,!0):(M(),v(`div`,_i,[D(`button`,{type:`button`,class:`proj-item__action`,title:o.$t(`@WORKBENCH:打开文件夹`),"aria-label":`${o.$t(`@WORKBENCH:打开文件夹`)} ${t.name}`,onClick:J(e=>o.openInFileManager(t),[`stop`])},[_(l,{"aria-hidden":`true`},{default:W(()=>[_(o.FolderOpened)]),_:1})],8,vi),_(u,{visible:o.openMenuKey===t.key,trigger:`manual`,placement:`right-start`,width:272,"show-arrow":!1,offset:6,"popper-class":`proj-open-menu`},{reference:W(()=>[D(`button`,{type:`button`,class:U([`proj-item__action`,{"is-open":o.openMenuKey===t.key}]),title:o.$t(`@WORKBENCH:打开方式`),"aria-label":`${o.$t(`@WORKBENCH:打开方式`)} ${t.name}`,"aria-expanded":o.openMenuKey===t.key,"aria-haspopup":`menu`,onClick:J(e=>o.toggleOpenMenu(t,e),[`stop`])},[_(l,{"aria-hidden":`true`},{default:W(()=>[_(o.MoreFilled)]),_:1})],10,yi)]),default:W(()=>[o.openMenuKey===t.key?(M(),v(`ul`,{key:0,class:`proj-menu`,role:`menu`,"aria-label":o.$t(`@WORKBENCH:打开方式`)},[D(`li`,{class:`proj-menu__item`,role:`menuitem`,tabindex:`-1`,onClick:e=>o.openInFileManager(t),onKeydown:[K(J(e=>o.openInFileManager(t),[`prevent`]),[`enter`]),K(J(e=>o.openInFileManager(t),[`prevent`]),[`space`])]},[D(`span`,Si,[_(l,{"aria-hidden":`true`},{default:W(()=>[_(o.FolderOpened)]),_:1})]),D(`span`,Ci,e(o.$t(`@WORKBENCH:在文件管理器中打开`)),1)],40,xi),D(`li`,{class:`proj-menu__item`,role:`menuitem`,tabindex:`-1`,onClick:e=>o.openInTerminal(t),onKeydown:[K(J(e=>o.openInTerminal(t),[`prevent`]),[`enter`]),K(J(e=>o.openInTerminal(t),[`prevent`]),[`space`])]},[D(`span`,Ti,[_(l,{"aria-hidden":`true`},{default:W(()=>[_(o.Monitor)]),_:1})]),D(`span`,Ei,e(o.$t(`@WORKBENCH:在终端中打开`)),1)],40,wi),D(`li`,{class:`proj-menu__item`,role:`menuitem`,tabindex:`-1`,onClick:e=>o.launchGui(t),onKeydown:[K(J(e=>o.launchGui(t),[`prevent`]),[`enter`]),K(J(e=>o.launchGui(t),[`prevent`]),[`space`])]},[D(`span`,Oi,[_(l,{"aria-hidden":`true`},{default:W(()=>[_(o.Promotion)]),_:1})]),D(`span`,ki,e(o.$t(`@WORKBENCH:在新标签页启动 g ui`)),1)],40,Di),r(` 复制文件夹名称:放在"打开"这一组里,因为它操作的是项目目录本身,
30
- 而不是"用哪个工具打开"(下面那组有独立标题)。 `),D(`li`,{class:`proj-menu__item`,role:`menuitem`,tabindex:`-1`,onClick:e=>o.copyFolderName(t),onKeydown:[K(J(e=>o.copyFolderName(t),[`prevent`]),[`enter`]),K(J(e=>o.copyFolderName(t),[`prevent`]),[`space`])]},[D(`span`,ji,[_(l,{"aria-hidden":`true`},{default:W(()=>[_(o.CopyDocument)]),_:1})]),D(`span`,Mi,e(o.$t(`@67CE7:复制文件夹名称`)),1)],40,Ai),n[8]||=D(`li`,{class:`proj-menu__sep`,role:`separator`},null,-1),D(`li`,Ni,e(o.$t(`@WORKBENCH:用工具打开`)),1),(M(!0),v(R,null,S(o.OPEN_WITH_TOOLS,n=>(M(),v(`li`,{key:n.id,class:U([`proj-menu__item`,{"is-missing":o.toolMissing(n.id)}]),role:`menuitem`,tabindex:`-1`,onClick:e=>o.openWithTool(t,n.id),onKeydown:[K(J(e=>o.openWithTool(t,n.id),[`prevent`]),[`enter`]),K(J(e=>o.openWithTool(t,n.id),[`prevent`]),[`space`])]},[D(`span`,Fi,[_(o.SvgIcon,{"icon-class":n.icon},null,8,[`icon-class`])]),D(`span`,Ii,e(o.$t(n.labelKey)),1),o.toolMissing(n.id)?(M(),v(`span`,Li,e(o.$t(`@67CE7:未安装`)),1)):r(`v-if`,!0)],42,Pi))),128)),r(` claude 有两种权限模式,不混进上面的工具列表(顶栏也是单独排布的) `),D(`li`,{class:U([`proj-menu__item`,{"is-missing":o.toolMissing(`claude`)}]),role:`menuitem`,tabindex:`-1`,onClick:e=>o.openWithTool(t,`claude`),onKeydown:[K(J(e=>o.openWithTool(t,`claude`),[`prevent`]),[`enter`]),K(J(e=>o.openWithTool(t,`claude`),[`prevent`]),[`space`])]},[D(`span`,zi,[D(`img`,{src:o.claudeCodeIcon,alt:``,class:`proj-menu__img`},null,8,Bi)]),D(`span`,Vi,e(o.$t(`@67CE7:用 Claude Code 打开`)),1),D(`span`,Hi,e(o.toolMissing(`claude`)?o.$t(`@67CE7:未安装`):o.$t(`@67CE7:默认权限`)),1)],42,Ri),D(`li`,{class:U([`proj-menu__item proj-menu__item--danger`,{"is-missing":o.toolMissing(`claude`)}]),role:`menuitem`,tabindex:`-1`,onClick:e=>o.openWithTool(t,`claude`,`bypassPermissions`),onKeydown:[K(J(e=>o.openWithTool(t,`claude`,`bypassPermissions`),[`prevent`]),[`enter`]),K(J(e=>o.openWithTool(t,`claude`,`bypassPermissions`),[`prevent`]),[`space`])]},[D(`span`,Wi,[D(`img`,{src:o.claudeCodeIcon,alt:``,class:`proj-menu__img`},null,8,Gi)]),D(`span`,Ki,e(o.$t(`@67CE7:用 Claude Code 打开(完全批准)`)),1)],42,Ui)],8,bi)):r(`v-if`,!0)]),_:2},1032,[`visible`])]))],42,ei))),128)),!i.loading&&i.projects.length===0?(M(),v(`li`,qi,[D(`p`,Ji,e(o.$t(`@WORKBENCH:尚无项目`)),1),D(`p`,Yi,e(o.$t(`@WORKBENCH:常用目录与建过任务的目录都会出现在这里`)),1)])):r(`v-if`,!0),r(` 有项目、只是被筛没了:这必须说出来。
31
- 空着会让人以为项目列表坏了,而"没有匹配"和"一个项目都没有"是两件事。
32
- 刻意写成两个互斥的 v-if(而不是 v-else-if):条件里带上了 projects.length,
33
- 读代码时不用回头找上一段才敢确定它们不重叠。 `),!i.loading&&i.projects.length>0&&o.visible.length===0?(M(),v(`li`,Xi,[D(`p`,Zi,e(o.$t(`@WORKBENCH:没有匹配的项目`)),1),D(`button`,{type:`button`,class:`proj-empty__clear`,onClick:o.clearFilters},e(o.$t(`@WORKBENCH:清除筛选`)),1)])):r(`v-if`,!0)]),r(` 未安装的工具:复用顶栏那套安装引导(同一个组件),不在这里另写一份说明。
34
- 挂在面板根上只渲染一份,而不是每行一个 —— 同时最多只可能开一个。 `),_(o.ToolInstallDialog,{modelValue:o.installVisible,"onUpdate:modelValue":n[7]||=e=>o.installVisible=e,tool:o.installTool},null,8,[`modelValue`,`tool`])])}var $i=Q(Mr,[[`render`,Qi],[`__scopeId`,`data-v-de1af726`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/components/WorkbenchProjectPanel.vue`]]);X(),B();var ea=s({__name:`WorkbenchAgentPanel`,props:{running:{type:Array,required:!0}},setup(e,{expose:t}){t();let n=e,r=Y(Date.now()),i=null;function a(){i&&=(clearInterval(i),null)}function o(){if(n.running.length>0){if(i)return;r.value=Date.now(),i=setInterval(()=>{r.value=Date.now()},1e3)}else a()}I(()=>n.running.length,o,{immediate:!0}),f(a);let s={props:n,now:r,get timer(){return i},set timer(e){i=e},stopTimer:a,syncTimer:o,rows:q(()=>n.running.map(e=>({...e,elapsed:kr(e.startedAt,null,r.value)}))),get $t(){return Z}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}});b(),X();var ta={class:`agents`},na={class:`agents__head`},ra={class:`agents__title`},ia={class:`agents__list`},aa={class:`agent-item__row1`},oa=[`title`],sa={class:`agent-item__status`},ca=[`title`],la={class:`agent-item__row3`},ua={key:0,class:`agent-item__pid`},da={class:`agent-item__elapsed`},fa={key:0,class:`agents-empty`};function pa(t,n,i,a,o,s){return M(),v(`section`,ta,[D(`header`,na,[D(`h3`,ra,e(a.$t(`@WORKBENCH:执行监控`)),1),D(`span`,{class:U([`agents__count`,{"is-live":i.running.length>0}])},e(a.$t(`@WORKBENCH:{n} 个执行中`,{n:i.running.length})),3)]),D(`ul`,ia,[(M(!0),v(R,null,S(a.rows,t=>(M(),v(`li`,{key:t.jobId,class:`agent-item`},[D(`div`,aa,[D(`span`,{class:U([`agent-item__dot`,{"is-pending":t.status===`pending`}]),"aria-hidden":`true`},null,2),D(`span`,{class:`agent-item__project`,title:t.projectName},e(t.projectName||`—`),9,oa),D(`span`,sa,e(t.status===`pending`?a.$t(`@WORKBENCH:排队中`):a.$t(`@WORKBENCH:执行中`)),1)]),D(`p`,{class:`agent-item__task`,title:t.taskTitle},e(t.taskTitle||a.$t(`@WORKBENCH:未命名任务`)),9,ca),D(`div`,la,[t.pid?(M(),v(`span`,ua,`PID `+e(t.pid),1)):r(`v-if`,!0),D(`span`,da,e(t.elapsed),1)])]))),128)),i.running.length===0?(M(),v(`li`,fa,e(a.$t(`@WORKBENCH:暂无执行中的任务`)),1)):r(`v-if`,!0)])])}var ma=Q(ea,[[`render`,pa],[`__scopeId`,`data-v-09820e5d`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/components/WorkbenchAgentPanel.vue`]]);X(),B();var ha=`wb.boardView.v1`,ga=s({__name:`WorkbenchKanban`,props:{tasks:{type:Array,required:!0},projectLabels:{type:Object,required:!0},showProjectLabel:{type:Boolean,required:!0}},emits:[`open-task`,`run-task`,`delete-task`,`create-task`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,a=Y((()=>{try{return localStorage.getItem(ha)===`list`?`list`:`kanban`}catch{return`kanban`}})());I(a,e=>{try{localStorage.setItem(ha,e)}catch{}});let o=Y(``),s=Y(!1),c=[{key:`todo`,labelKey:`@WORKBENCH:待处理`},{key:`doing`,labelKey:`@WORKBENCH:进行中`},{key:`done`,labelKey:`@WORKBENCH:已完成`}],l=q(()=>{let e=o.value.trim().toLowerCase();return r.tasks.filter(t=>s.value&&t.lastJobStatus!==`error`?!1:!e||(t.title||``).toLowerCase().includes(e)||(t.desc||``).toLowerCase().includes(e))}),u=q(()=>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=q(()=>({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`}let v={props:r,emit:i,VIEW_KEY:ha,view:a,search:o,onlyErrors:s,COLUMNS:c,filtered:l,columns:u,doneAt:d,byDoneAtDesc:f,cardTime:p,columnsStyle:m,cardTitle:h,projectLabel:g,hasError:_,get $t(){return Z},get Search(){return ne},get relativeTimeFromIso(){return Or}};return Object.defineProperty(v,"__isScriptSetup",{enumerable:!1,value:!0}),v}});b(),X(),G();var _a={class:`kb`},va={class:`kb__toolbar`},ya={class:`kb__views`,role:`tablist`},ba=[`aria-selected`],xa=[`aria-selected`],Sa={class:`kb__filters`},Ca=[`title`],wa={class:`kb__search`},Ta=[`placeholder`],Ea={class:`kb-col__head`},Da={class:`kb-col__title`},Oa={class:`kb-col__count`},ka={class:`kb-col__list`},Aa=[`onClick`],ja={class:`kb-card__row1`},Ma={key:0,class:`kb-card__running`,"aria-hidden":`true`},Na={class:`kb-card__time`},Pa=[`title`],Fa={key:0,class:`kb-card__project`},Ia={class:`kb-card__actions`},La=[`title`,`onClick`],Ra=[`title`,`aria-label`,`onClick`],za={key:0,class:`kb-col__empty`},Ba={key:1},Va={class:`kb__table-wrap`},Ha={class:`kb-table`},Ua={class:`kb-table__th`},Wa={class:`kb-table__th kb-table__th--narrow`},Ga={class:`kb-table__th kb-table__th--narrow`},Ka=[`onClick`],qa={class:`kb-table__td`},Ja={class:`kb-table__name`},Ya={key:0,class:`kb-table__project`},Xa={class:`kb-table__td`},Za={class:`kb-table__td kb-table__td--num`},Qa={key:0},$a={class:`kb-table__td kb-table__empty`,colspan:`3`};function eo(t,n,i,a,o,s){let c=d;return M(),v(`div`,_a,[D(`div`,va,[D(`div`,ya,[D(`button`,{type:`button`,role:`tab`,class:U([`kb__view-btn`,{"is-active":a.view===`kanban`}]),"aria-selected":a.view===`kanban`,onClick:n[0]||=e=>a.view=`kanban`},e(a.$t(`@WORKBENCH:看板视图`)),11,ba),D(`button`,{type:`button`,role:`tab`,class:U([`kb__view-btn`,{"is-active":a.view===`list`}]),"aria-selected":a.view===`list`,onClick:n[1]||=e=>a.view=`list`},e(a.$t(`@WORKBENCH:列表视图`)),11,xa)]),D(`div`,Sa,[D(`label`,{class:`kb__check`,title:a.$t(`@WORKBENCH:只显示最近一次执行报错的任务`)},[z(D(`input`,{type:`checkbox`,"onUpdate:modelValue":n[2]||=e=>a.onlyErrors=e},null,512),[[H,a.onlyErrors]]),D(`span`,null,e(a.$t(`@WORKBENCH:仅看报错`)),1)],8,Ca),D(`div`,wa,[_(c,{class:`kb__search-icon`},{default:W(()=>[_(a.Search)]),_:1}),z(D(`input`,{class:`kb__search-input`,type:`search`,"onUpdate:modelValue":n[3]||=e=>a.search=e,placeholder:a.$t(`@WORKBENCH:搜索任务标题或描述`)},null,8,Ta),[[V,a.search]])])])]),r(` 看板视图 `),a.view===`kanban`?(M(),v(`div`,{key:0,class:`kb__columns`,style:N(a.columnsStyle)},[(M(!0),v(R,null,S(a.columns,t=>(M(),v(`section`,{key:t.key,class:U([`kb-col`,`kb-col--`+t.key])},[D(`header`,Ea,[n[5]||=D(`span`,{class:`kb-col__dot`,"aria-hidden":`true`},null,-1),D(`h3`,Da,e(a.$t(t.labelKey)),1),D(`span`,Oa,e(t.tasks.length),1)]),D(`ul`,ka,[(M(!0),v(R,null,S(t.tasks,t=>(M(),v(`li`,{key:t.id,class:U([`kb-card`,{"is-running":t.runningJobs>0,"has-error":a.hasError(t)}]),onClick:e=>a.emit(`open-task`,t)},[D(`div`,ja,[t.runningJobs>0?(M(),v(`span`,Ma)):r(`v-if`,!0),D(`span`,Na,e(a.relativeTimeFromIso(a.cardTime(t))),1)]),D(`p`,{class:`kb-card__title`,title:a.cardTitle(t)},e(a.cardTitle(t)||a.$t(`@WORKBENCH:未命名任务`)),9,Pa),i.showProjectLabel&&a.projectLabel(t)?(M(),v(`p`,Fa,e(a.projectLabel(t)),1)):r(`v-if`,!0),D(`div`,Ia,[t.runningJobs===0?(M(),v(`button`,{key:0,type:`button`,class:`kb-card__btn`,title:a.$t(`@WORKBENCH:执行`),onClick:J(e=>a.emit(`run-task`,t),[`stop`])},e(a.$t(`@WORKBENCH:执行`)),9,La)):r(`v-if`,!0),D(`button`,{type:`button`,class:`kb-card__btn kb-card__btn--danger`,title:a.$t(`@WORKBENCH:删除`),"aria-label":a.$t(`@WORKBENCH:删除`),onClick:J(e=>a.emit(`delete-task`,t),[`stop`])},`×`,8,Ra)])],10,Aa))),128)),t.tasks.length===0?(M(),v(`li`,za,[t.key===`todo`?(M(),v(`button`,{key:0,type:`button`,class:`kb-col__empty-btn`,onClick:n[4]||=e=>a.emit(`create-task`)},e(a.$t(`@WORKBENCH:新建任务`)),1)):(M(),v(`span`,Ba,e(a.$t(`@WORKBENCH:暂无任务`)),1))])):r(`v-if`,!0)])],2))),128))],4)):(M(),v(R,{key:1},[r(` 列表视图 `),D(`div`,Va,[D(`table`,Ha,[D(`thead`,null,[D(`tr`,null,[D(`th`,Ua,e(a.$t(`@WORKBENCH:任务`)),1),D(`th`,Wa,e(a.$t(`@WORKBENCH:状态`)),1),D(`th`,Ga,e(a.$t(`@WORKBENCH:更新时间`)),1)])]),D(`tbody`,null,[(M(!0),v(R,null,S(a.filtered,t=>(M(),v(`tr`,{key:t.id,class:`kb-table__row`,onClick:e=>a.emit(`open-task`,t)},[D(`td`,qa,[D(`span`,Ja,e(a.cardTitle(t)||a.$t(`@WORKBENCH:未命名任务`)),1),i.showProjectLabel&&a.projectLabel(t)?(M(),v(`span`,Ya,e(a.projectLabel(t)),1)):r(`v-if`,!0)]),D(`td`,Xa,[D(`span`,{class:U([`kb-table__status`,`is-`+t.column])},e(a.$t(a.COLUMNS.find(e=>e.key===t.column).labelKey)),3)]),D(`td`,Za,e(a.relativeTimeFromIso(t.updatedAt||t.createdAt)),1)],8,Ka))),128)),a.filtered.length===0?(M(),v(`tr`,Qa,[D(`td`,$a,e(a.$t(`@WORKBENCH:暂无任务`)),1)])):r(`v-if`,!0)])])])],2112))])}var to=Q(ga,[[`render`,eo],[`__scopeId`,`data-v-0b8fc27c`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/components/WorkbenchKanban.vue`]]);X(),B();var no=`/api/workbench/orchestrator/attachments`,ro=`wb.ocInputHeight.v1`,io=76,ao=20,oo=s({__name:`OrchestratorConsole`,props:{active:{type:Boolean,required:!0},activity:{type:Array,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}},emits:[`toggle-schedule`,`toggle-collapse`,`open-prompt-settings`,`dispatch`],setup(e,{expose:n,emit:r}){let i=e,a=r,o=Y(``),s=Y(!0),c=Y(!0),l=Ne(),d=q(()=>({claude:l.claudeAvailable,opencode:l.opencodeAvailable})),p=Y(Ke());function h(){if(d.value[p.value]){Ie(p.value);return}let e=Object.keys(d.value).find(e=>d.value[e]);e&&(p.value=e)}function g(e){return We.find(t=>t.id===e)?.name||e}function _(e){p.value=e,h()}let v=Y([]),y=q(()=>({kind:`draft`,list:v.value,replace:e=>{v.value=e}})),{isUploading:b,isImageAttachment:x,humanSize:S,onAttachmentPaste:C,onAttachmentDrop:w,removeAttachment:T,pickAttachmentFile:E}=An(),D=q(()=>b(`draft`)),O=Y(!1);function ee(e){e.stopPropagation(),C(e,y.value)}function k(e){O.value=!1,w(e,y.value)}function te(){E(y.value)}function A(e){T(y.value,e)}function j(){v.value=[]}n({clearAttachments:j});let ne=q(()=>i.selectedProject?.key||``),M=q(()=>(i.defaultPrompt||``).trim()),re=q(()=>{let e=ne.value;return e?(i.projectPrompts?.[e]?.prompt||``).trim():``}),N=q(()=>Object.values(i.projectPrompts||{}).some(e=>(e?.prompt||``).trim().length>0)),P=q(()=>!!M.value||N.value),ie=q(()=>{let e=!!M.value,t=ne.value?re.value?`project`:`none`:N.value?`target`:`none`;return Z(e&&t===`project`?`@WORKBENCH:全局 + 本项目`:e&&t===`target`?`@WORKBENCH:全局 + 落点项目`:e?`@WORKBENCH:全局`:t===`project`?`@WORKBENCH:本项目`:t===`target`?`@WORKBENCH:落点项目`:`@WORKBENCH:未设置`)}),F=q(()=>o.value.trim().length>0&&!i.dispatching&&!D.value);function I(){F.value&&(a(`dispatch`,{text:o.value.trim(),autoRun:s.value,attachments:v.value,projectPath:i.selectedProject?i.selectedProject.path:``,useDefaultPrompt:c.value,executor:p.value}),o.value=``)}function ae(e){e.isComposing||e.keyCode===229||e.key!==`Enter`||e.shiftKey||(e.preventDefault(),I())}function L(){try{let e=localStorage.getItem(ro);if(!e)return null;let t=Number(e);return Number.isFinite(t)&&t>=io?Math.round(t):null}catch{return null}}let R=Y(null),z=Y(L()),oe=q(()=>{let e={};return z.value&&(e.height=`${z.value}px`),e}),B=null,ce=!1,V=!0;function ue(e){let t=R.value;if(!t)return;let n=t.getBoundingClientRect();ce=n.right-e.clientX<=ao&&n.bottom-e.clientY<=ao}function de(){ce=!1}function fe(e){let t=Math.round(e.offsetHeight);if(!(t<io||t===z.value)){z.value=t;try{localStorage.setItem(ro,String(t))}catch{}}}u(()=>{let e=R.value;e&&(window.addEventListener(`mouseup`,de),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;(ce||!n)&&fe(e)}),B.observe(e)))}),f(()=>{window.removeEventListener(`mouseup`,de),B?.disconnect(),B=null});function pe(e){let t=e.taskTitle||Z(`@WORKBENCH:未命名任务`),n=e.projectName||`—`;switch(e.kind){case`user`:return e.text||``;case`dispatch`:return Z(`@WORKBENCH:派发「{task}」至 {project}`,{task:t,project:n});case`done`:return Z(`@WORKBENCH:「{task}」执行完成`,{task:t});case`error`:return Z(`@WORKBENCH:「{task}」执行出错`,{task:t});case`cancelled`:return Z(`@WORKBENCH:「{task}」已取消`,{task:t});default:return t}}let me={user:`@WORKBENCH:用户派发`,dispatch:`@WORKBENCH:派发`,done:`@WORKBENCH:完成`,error:`@WORKBENCH:出错`,cancelled:`@WORKBENCH:取消`};function H(e){return e.kind===`user`?e.instructionStatus===`accepted`?Z(`@WORKBENCH:已建任务并开始执行`):e.instructionStatus===`rejected`?Z(`@WORKBENCH:被拒绝:{reason}`,{reason:e.reason||``}):e.reason||Z(`@WORKBENCH:已建任务(未执行)`):``}function U(e){switch(e.targetSource){case`mention`:return Z(`@WORKBENCH:指令里提到了它`);case`agent`:return Z(`@WORKBENCH:主 Agent 判断`);case`default`:return Z(`@WORKBENCH:没识别出项目,用了默认项目`);default:return``}}function _e(e){switch(e.promptSource){case`global`:return Z(`@WORKBENCH:附带全局默认提示词`);case`project`:return Z(`@WORKBENCH:附带项目默认提示词`);case`both`:return Z(`@WORKBENCH:附带全局 + 项目默认提示词`);default:return``}}let W={props:i,emit:a,draft:o,autoRun:s,useDefaultPrompt:c,toolsStore:l,executorAvailability:d,selectedExecutor:p,onExecutorChange:h,executorName:g,onExecutorPick:_,draftAttachments:v,DRAFT_RAW_BASE:no,attachTarget:y,isUploading:b,isImageAttachment:x,humanSize:S,onAttachmentPaste:C,onAttachmentDrop:w,removeAttachment:T,pickAttachmentFile:E,attachBusy:D,attachDragging:O,onPaste:ee,onDrop:k,onPickAttachment:te,onRemoveAttachment:A,clearAttachments:j,projectKey:ne,globalPromptText:M,projectPromptText:re,anyProjectPrompt:N,anyPromptConfigured:P,promptStateLabel:ie,canSend:F,send:I,onInputKeydown:ae,INPUT_H_KEY:ro,OC_INPUT_MIN_H:io,readInputH:L,inputRef:R,inputH:z,inputStyle:oe,get inputRO(){return B},set inputRO(e){B=e},get inputDragging(){return ce},set inputDragging(e){ce=e},get inputROFirst(){return V},set inputROFirst(e){V=e},INPUT_GRIP_PX:ao,onInputMouseDown:ue,onWindowMouseUp:de,commitInputH:fe,describe:pe,KIND_LABEL:me,instructionNote:H,targetReason:U,promptNote:_e,gitSummary:q(()=>{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 m},get Promotion(){return t},get Expand(){return le},get Fold(){return Se},get Setting(){return ge},get ArrowDown(){return he},get Check(){return se},TaskExecutorIcon:Fe,get clockFromIso(){return jr},get relativeTimeFromIso(){return Or},AttachmentZone:ct,get TASK_EXECUTOR_OPTIONS(){return We}};return Object.defineProperty(W,"__isScriptSetup",{enumerable:!1,value:!0}),W}});X(),b(),G();var so=[`title`,`aria-label`],co={class:`oc__rail-text`},lo={class:`oc__head`},uo={class:`oc__title`},fo=[`disabled`,`title`],po=[`title`,`aria-label`],mo={class:`oc__state-label`},ho={class:`oc__state-value`},go={class:`oc__state-meta`},_o={class:`oc__feed`},vo={class:`oc__feed-title`},yo={class:`oc__feed-list`},bo={class:`oc-row__head`},xo={class:`oc-row__kind`},So={class:`oc-row__time`},Co={class:`oc-row__text`},wo={key:0,class:`oc-row__note`},To={key:1,class:`oc-row__note`},Eo={key:0},Do={key:2,class:`oc-row__note`},Oo=[`title`],ko={key:4,class:`oc-row__note`},Ao={key:0,class:`oc-empty`},jo={class:`oc__git`},Mo={class:`oc__feed-title`},No={class:`oc__git-name`},Po={class:`oc__git-list`},Fo={class:`oc__git-label`},Io={class:`oc__git-label`},Lo={class:`oc__git-value`},Ro={class:`oc__git-label`},zo={class:`oc__git-value`},Bo=[`placeholder`],Vo={class:`oc__compose-foot`},Ho=[`disabled`,`title`,`aria-label`],Uo=[`title`,`aria-label`],Wo=[`title`],Go=[`title`],Ko=[`title`,`aria-label`],qo={class:`oc__executor-item`},Jo={class:`oc__executor-item__name`},Yo={key:1,class:`oc__executor-item__missing`},Xo=[`disabled`],Zo={class:`oc__hint`};function Qo(t,i,o,s,c,l){let u=d,f=n,p=Ce,m=w;return M(),v(`aside`,{class:U([`oc`,{"is-collapsed":o.collapsed}])},[r(` 折叠后的收纳条:只剩一枚展开按钮 + 竖排标题,宽度收到 32px。
35
- 折叠不是"把宽度压成 0"—— 那样就再没有能点回来的地方了。 `),o.collapsed?(M(),v(`button`,{key:0,type:`button`,class:`oc__rail`,title:s.$t(`@WORKBENCH:展开主 Agent 控制台`),"aria-label":s.$t(`@WORKBENCH:展开主 Agent 控制台`),"aria-expanded":!1,onClick:i[0]||=e=>s.emit(`toggle-collapse`)},[_(u,{class:`oc__rail-icon`},{default:W(()=>[_(s.Fold)]),_:1}),D(`span`,{class:U([`oc__rail-live`,{"is-off":!o.active}]),"aria-hidden":`true`},null,2),D(`span`,co,e(s.$t(`@WORKBENCH:主 Agent 控制台`)),1)],8,so)):r(`v-if`,!0),r(` 折叠时这几块整体隐藏而不是销毁(v-show 而不是 v-if):
36
- 草稿指令和已贴的附件都还留着,展开回来能接着发 `),z(D(`header`,lo,[D(`span`,{class:U([`oc__live`,{"is-off":!o.active}]),"aria-hidden":`true`},null,2),D(`h3`,uo,e(s.$t(`@WORKBENCH:主 Agent 控制台`)),1),D(`button`,{type:`button`,class:`oc__toggle`,disabled:o.togglingSchedule,title:o.active?s.$t(`@WORKBENCH:暂停后派发只建任务,不会自动执行`):s.$t(`@WORKBENCH:恢复后派发会自动执行`),onClick:i[1]||=e=>s.emit(`toggle-schedule`,!o.active)},e(o.active?s.$t(`@WORKBENCH:暂停调度`):s.$t(`@WORKBENCH:恢复调度`)),9,fo),D(`button`,{type:`button`,class:`oc__collapse`,title:s.$t(`@WORKBENCH:收起主 Agent 控制台`),"aria-label":s.$t(`@WORKBENCH:收起主 Agent 控制台`),"aria-expanded":!0,onClick:i[2]||=e=>s.emit(`toggle-collapse`)},[_(u,null,{default:W(()=>[_(s.Expand)]),_:1})],8,po)],512),[[P,!o.collapsed]]),z(D(`div`,{class:U([`oc__state`,{"is-paused":!o.active}])},[D(`span`,mo,e(s.$t(`@WORKBENCH:调度状态`)),1),D(`span`,ho,e(o.active?s.$t(`@WORKBENCH:调度中`):s.$t(`@WORKBENCH:已暂停`)),1),D(`span`,go,e(s.$t(`@WORKBENCH:{n} 个执行中`,{n:o.runningCount})),1)],2),[[P,!o.collapsed]]),z(D(`div`,_o,[D(`p`,vo,e(s.$t(`@WORKBENCH:活动日志`)),1),D(`ul`,yo,[(M(!0),v(R,null,S(o.activity,t=>(M(),v(`li`,{key:t.id,class:U([`oc-row`,`oc-row--`+t.kind])},[D(`div`,bo,[D(`span`,xo,e(s.$t(s.KIND_LABEL[t.kind]||`@WORKBENCH:派发`)),1),r(` 时间走 clockFromIso:非当天会带上日期前缀,避免跨天记录看起来像今天刚发生 `),D(`span`,So,e(s.clockFromIso(t.at)),1)]),D(`p`,Co,e(s.describe(t)),1),s.instructionNote(t)?(M(),v(`p`,wo,e(s.instructionNote(t)),1)):r(`v-if`,!0),r(` 落点 + 依据。判断错了,用户至少要能看出是"没识别出来、退了默认"
37
- 还是"模型猜的",否则只能对着一个错误项目名干瞪眼 `),t.kind===`user`&&t.projectName?(M(),v(`p`,To,[g(e(s.$t(`@WORKBENCH:落点「{name}」`,{name:t.projectName}))+` `,1),s.targetReason(t)?(M(),v(`span`,Eo,`· `+e(s.targetReason(t)),1)):r(`v-if`,!0)])):r(`v-if`,!0),r(` 提示词单独占一行:它解释的是"任务正文里多出来的那段话是哪来的",
38
- 和落点是两件事,挤在一行会看不清 `),t.kind===`user`&&s.promptNote(t)?(M(),v(`p`,Do,e(s.promptNote(t)),1)):r(`v-if`,!0),t.kind===`error`&&t.error?(M(),v(`p`,{key:3,class:`oc-row__error`,title:t.error},e(t.error),9,Oo)):r(`v-if`,!0),t.kind===`done`&&t.projectName?(M(),v(`p`,ko,e(t.projectName),1)):r(`v-if`,!0)],2))),128)),o.activity.length===0?(M(),v(`li`,Ao,e(s.$t(`@WORKBENCH:暂无活动记录`)),1)):r(`v-if`,!0)])],512),[[P,!o.collapsed]]),z(D(`div`,jo,[D(`p`,Mo,[g(e(s.$t(`@WORKBENCH:项目概览`))+` `,1),r(` 无选中项目即「全部项目」:显式标出来,否则底下只剩「今日完成」一行,看着像数据没加载出来 `),D(`span`,No,e(o.selectedProject?o.selectedProject.name:s.$t(`@WORKBENCH:全部项目`)),1)]),D(`dl`,Po,[(M(!0),v(R,null,S(s.gitSummary,t=>(M(),v(R,{key:t.label},[D(`dt`,Fo,e(t.label),1),D(`dd`,{class:U([`oc__git-value`,{"is-warn":t.tone===`warn`,"is-danger":t.tone===`danger`}])},e(t.value),3)],64))),128)),D(`dt`,Io,e(s.$t(`@WORKBENCH:今日完成`)),1),D(`dd`,Lo,e(o.todayDone),1),D(`dt`,Ro,e(s.$t(`@WORKBENCH:最后活跃`)),1),D(`dd`,zo,e(o.selectedProject&&s.relativeTimeFromIso(o.selectedProject.stats.lastActiveAt)||`—`),1)])],512),[[P,!o.collapsed]]),z(D(`div`,{class:`oc__compose`,onPaste:s.onPaste,onDrop:J(s.onDrop,[`prevent`]),onDragover:i[10]||=J(e=>s.attachDragging=!0,[`prevent`]),onDragleave:i[11]||=e=>s.attachDragging=!1},[r(` 粘贴事件必须同时挂在 textarea 上:在输入框里按 Ctrl+V 时事件只到 textarea,
39
- 不会冒泡经过下面的附件区 `),z(D(`textarea`,{ref:`inputRef`,class:`oc__input`,"onUpdate:modelValue":i[3]||=e=>s.draft=e,style:N(s.inputStyle),rows:`4`,placeholder:s.$t(`@WORKBENCH:给主 Agent 下一条指令,例如:把登录模块的错误处理重构一遍`),onKeydown:s.onInputKeydown,onPaste:s.onPaste,onMousedown:s.onInputMouseDown},null,44,Bo),[[V,s.draft]]),s.draftAttachments.length>0||s.attachBusy?(M(),a(s.AttachmentZone,{key:0,attachments:s.draftAttachments,"is-image":s.isImageAttachment,"human-size":s.humanSize,"is-uploading":s.attachBusy,"is-paste-hover":s.attachDragging,"max-count":9,"on-pick":s.onPickAttachment,"on-remove":s.onRemoveAttachment,"raw-base":s.DRAFT_RAW_BASE,onPaste:s.onPaste,onDrop:s.onDrop,onDragover:i[4]||=J(e=>s.attachDragging=!0,[`prevent`]),onDragenter:i[5]||=J(e=>s.attachDragging=!0,[`prevent`]),onDragleave:i[6]||=e=>s.attachDragging=!1},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`])):r(`v-if`,!0),D(`div`,Vo,[D(`button`,{type:`button`,class:`oc__attach`,disabled:s.attachBusy||s.draftAttachments.length>=9,title:s.$t(`@WORKBENCH:添加附件(也可直接粘贴或拖入文件)`),"aria-label":s.$t(`@WORKBENCH:添加附件`),onClick:s.onPickAttachment},[_(u,null,{default:W(()=>[_(s.Paperclip)]),_:1})],8,Ho),r(` 默认提示词设置入口:图标按钮按项目惯例不加底色,
40
- 有没有设过看右侧"附加默认提示词"那个勾选(它是真实生效状态,这个只是入口) `),D(`button`,{type:`button`,class:U([`oc__attach`,{"is-on":s.anyPromptConfigured}]),title:s.$t(`@WORKBENCH:设置派发时自动附加的默认提示词(全局 / 各项目)`),"aria-label":s.$t(`@WORKBENCH:默认提示词设置`),onClick:i[7]||=e=>s.emit(`open-prompt-settings`)},[_(u,null,{default:W(()=>[_(s.Setting)]),_:1})],10,Uo),D(`label`,{class:`oc__autorn`,title:s.$t(`@WORKBENCH:取消勾选则只建任务草稿,不自动执行`)},[z(D(`input`,{type:`checkbox`,"onUpdate:modelValue":i[8]||=e=>s.autoRun=e},null,512),[[H,s.autoRun]]),D(`span`,null,e(s.$t(`@WORKBENCH:立即执行`)),1)],8,Wo),r(` 一条都没设过时不出现:一个永远勾着、点了也没区别的开关只会占地方 `),s.anyPromptConfigured?(M(),v(`label`,{key:0,class:`oc__autorn`,title:s.$t(`@WORKBENCH:取消勾选则本次派发的任务不带默认提示词(设置本身不受影响)`)},[z(D(`input`,{type:`checkbox`,"onUpdate:modelValue":i[9]||=e=>s.useDefaultPrompt=e},null,512),[[H,s.useDefaultPrompt]]),D(`span`,null,e(s.$t(`@WORKBENCH:默认提示词({state})`,{state:s.promptStateLabel})),1)],8,Go)):r(`v-if`,!0),r(` 执行器:与执行按钮共用同一份临时选择,派发时覆盖设置里的默认值。
41
- 不用原生 select —— option 里塞不了品牌图标,el-dropdown 才有精致度 `),_(m,{trigger:`click`,class:`oc__executor`,onCommand:s.onExecutorPick},{dropdown:W(()=>[_(p,null,{default:W(()=>[(M(!0),v(R,null,S(s.TASK_EXECUTOR_OPTIONS,t=>(M(),a(f,{key:t.id,command:t.id,disabled:!s.executorAvailability[t.id]},{default:W(()=>[D(`span`,qo,[_(s.TaskExecutorIcon,{executor:t.id,class:`oc__executor-item__icon`},null,8,[`executor`]),D(`span`,Jo,e(t.name),1),s.selectedExecutor===t.id?(M(),a(u,{key:0,class:`oc__executor-item__check`},{default:W(()=>[_(s.Check)]),_:1})):s.executorAvailability[t.id]?r(`v-if`,!0):(M(),v(`span`,Yo,e(s.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`,`disabled`]))),128))]),_:1})]),default:W(()=>[D(`button`,{type:`button`,class:`oc__executor-btn`,title:s.$t(`@WORKBENCH:本次派发使用的执行器(与执行按钮的临时切换共用)`),"aria-label":s.$t(`@WORKBENCH:任务执行器`)},[_(s.TaskExecutorIcon,{executor:s.selectedExecutor,class:`oc__executor-btn__icon`},null,8,[`executor`]),D(`span`,null,e(s.executorName(s.selectedExecutor)),1),_(u,{class:`oc__executor-btn__caret`},{default:W(()=>[_(s.ArrowDown)]),_:1})],8,Ko)]),_:1}),D(`button`,{type:`button`,class:`oc__send`,disabled:!s.canSend,onClick:s.send},[_(u,{class:`oc__send-icon`},{default:W(()=>[_(s.Promotion)]),_:1}),D(`span`,null,e(o.dispatching?s.$t(`@WORKBENCH:派发中…`):s.$t(`@WORKBENCH:派发`)),1)],8,Xo)]),D(`p`,Zo,[o.selectedProject?(M(),v(R,{key:0},[g(e(s.$t(`@WORKBENCH:指令会在「{name}」下新建一个任务;Enter 派发,Shift+Enter 换行`,{name:o.selectedProject.name})),1)],64)):(M(),v(R,{key:1},[g(e(s.$t(`@WORKBENCH:指令落到哪个项目由主 Agent 判断;Enter 派发,Shift+Enter 换行`)),1)],64))])],544),[[P,!o.collapsed]])],2)}var $o=Q(oo,[[`render`,Qo],[`__scopeId`,`data-v-4c030231`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/components/OrchestratorConsole.vue`]]);X(),B();var es=4e3,ts=s({__name:`WorkbenchDefaultPromptDialog`,props:{modelValue:{type:Boolean,required:!0},defaultPrompt:{type:String,required:!0},projectPath:{type:String,required:!0},projectName:{type:String,required:!0},projectPrompt:{type:String,required:!0},saving:{type:Boolean,required:!0}},emits:[`update:modelValue`,`save`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,a=Y(``),o=Y(``);I(()=>r.modelValue,e=>{e&&(a.value=r.defaultPrompt||``,o.value=r.projectPrompt||``)});let s=q(()=>!!r.projectPath),c=q(()=>a.value.trim()!==(r.defaultPrompt||``).trim()||s.value&&o.value.trim()!==(r.projectPrompt||``).trim());function l(){r.saving||i(`save`,{globalPrompt:a.value,projectPrompt:o.value})}function u(){i(`update:modelValue`,!1)}let d={props:r,emit:i,MAX_CHARS:es,globalDraft:a,projectDraft:o,hasProject:s,dirty:c,submit:l,close:u,get $t(){return Z},CommonDialog:Me};return Object.defineProperty(d,"__isScriptSetup",{enumerable:!1,value:!0}),d}});b(),X(),G();var ns={class:`pd`},rs={class:`pd__intro`},is={class:`pd__field`},as={class:`pd__head`},os={class:`pd__label`,for:`pd-global`},ss={class:`pd__count`},cs=[`placeholder`],ls={class:`pd__field`},us={class:`pd__head`},ds={class:`pd__label`,for:`pd-project`},fs={key:0,class:`pd__count`},ps=[`disabled`,`placeholder`],ms={class:`pd__hint`},hs={class:`pd__foot`},gs=[`disabled`];function _s(t,n,i,o,s,c){return M(),a(o.CommonDialog,{"model-value":i.modelValue,title:o.$t(`@WORKBENCH:默认提示词`),width:`min(640px, 94vw)`,"close-on-click-modal":!1,"onUpdate:modelValue":n[2]||=e=>o.emit(`update:modelValue`,e)},{footer:W(()=>[D(`div`,hs,[D(`button`,{type:`button`,class:`pd__btn`,onClick:o.close},e(o.$t(`@WORKBENCH:取消`)),1),n[3]||=D(`span`,{class:`pd__foot-spacer`},null,-1),D(`button`,{type:`button`,class:`pd__btn pd__btn--primary`,disabled:i.saving||!o.dirty,onClick:o.submit},e(i.saving?o.$t(`@WORKBENCH:保存中…`):o.$t(`@WORKBENCH:保存`)),9,gs)])]),default:W(()=>[D(`div`,ns,[D(`p`,rs,e(o.$t(`@WORKBENCH:派发指令时自动附加在指令之前,让每个任务都带上这些约束。只影响之后派发的任务,不会改动已经建好的任务。`)),1),D(`div`,is,[D(`div`,as,[D(`label`,os,e(o.$t(`@WORKBENCH:全局默认提示词`)),1),D(`span`,ss,e(o.globalDraft.length)+` / `+e(o.MAX_CHARS),1)]),z(D(`textarea`,{id:`pd-global`,"onUpdate:modelValue":n[0]||=e=>o.globalDraft=e,class:`pd__area`,rows:`5`,maxlength:o.MAX_CHARS,placeholder:o.$t(`@WORKBENCH:对所有项目生效。例如:回答用中文;改完代码必须跑一遍测试;不要动 dist 目录`)},null,8,cs),[[V,o.globalDraft]])]),D(`div`,ls,[D(`div`,us,[D(`label`,ds,e(o.hasProject?o.$t(`@WORKBENCH:「{name}」的项目提示词`,{name:i.projectName}):o.$t(`@WORKBENCH:项目提示词`)),1),o.hasProject?(M(),v(`span`,fs,e(o.projectDraft.length)+` / `+e(o.MAX_CHARS),1)):r(`v-if`,!0)]),z(D(`textarea`,{id:`pd-project`,"onUpdate:modelValue":n[1]||=e=>o.projectDraft=e,class:`pd__area`,rows:`5`,maxlength:o.MAX_CHARS,disabled:!o.hasProject,placeholder:o.hasProject?o.$t(`@WORKBENCH:只在这个项目派发时附加。例如:包管理器用 pnpm;改动集中在 src/ui 下`):o.$t(`@WORKBENCH:先在左侧选中一个具体项目,才能设置它的提示词`)},null,8,ps),[[V,o.projectDraft]]),D(`p`,ms,e(o.hasProject?o.$t(`@WORKBENCH:项目提示词追加在全局提示词之后(不覆盖全局),派发到「{name}」时一起带上`,{name:i.projectName}):o.$t(`@WORKBENCH:选中的是「全部项目」,落点由主 Agent 判断 —— 想给某个项目单设提示词,先选中它`)),1)])])]),_:1},8,[`model-value`,`title`])}var vs=Q(ts,[[`render`,_s],[`__scopeId`,`data-v-766f470f`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/components/WorkbenchDefaultPromptDialog.vue`]]);X(),B();var ys=s({__name:`WorkbenchTaskCreateDialog`,props:{modelValue:{type:Boolean,required:!0},projects:{type:Array,required:!0},defaultProjectPath:{type:String,required:!0}},emits:[`update:modelValue`,`created`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,a=Y(``),o=Y(``),s=Y(``),c=Y(!1),l=Y(``);function u(e){let t=$(e);if(!t)return``;let n=r.projects.find(e=>$(e.path)===t);return n?n.path:``}I(()=>r.modelValue,e=>{e&&(a.value=``,o.value=``,s.value=u(r.defaultProjectPath),l.value=``,c.value=!1)});let d=q(()=>r.projects),f=q(()=>!c.value&&(a.value.trim().length>0||o.value.trim().length>0)),p=q(()=>{let e=$(s.value);if(!e)return``;let t=d.value.find(t=>$(t.path)===e);return t?t.name:``});async function m(e){if(f.value){c.value=!0,l.value=``;try{let t={title:a.value.trim(),desc:o.value,promptId:null,simpleOverride:``};s.value&&(t.projectPath=s.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){l.value=n?.error||Z(`@WORKBENCH:保存失败`);return}i(`update:modelValue`,!1),i(`created`,{task:n.task,openEditor:e})}finally{c.value=!1}}}let h={props:r,emit:i,title:a,desc:o,projectPath:s,submitting:c,error:l,matchOptionPath:u,projectOptions:d,canSubmit:f,projectName:p,submit:m,get $t(){return Z},CommonDialog:Me};return Object.defineProperty(h,"__isScriptSetup",{enumerable:!1,value:!0}),h}});b(),X(),G();var bs={class:`nc`},xs={class:`nc__field`},Ss={class:`nc__label`,for:`nc-project`},Cs={value:``},ws=[`value`],Ts=[`title`],Es={class:`nc__field`},Ds={class:`nc__label`,for:`nc-title`},Os=[`placeholder`],ks={class:`nc__field`},As={class:`nc__label`,for:`nc-desc`},js=[`placeholder`],Ms={key:0,class:`nc__error`},Ns={class:`nc__foot`},Ps=[`disabled`],Fs=[`disabled`];function Is(t,n,i,o,s,c){return M(),a(o.CommonDialog,{"model-value":i.modelValue,title:o.$t(`@WORKBENCH:新建开发任务`),width:`min(600px, 94vw)`,"close-on-click-modal":!1,"onUpdate:modelValue":n[9]||=e=>o.emit(`update:modelValue`,e)},{footer:W(()=>[D(`div`,Ns,[D(`button`,{type:`button`,class:`nc__btn`,onClick:n[6]||=e=>o.emit(`update:modelValue`,!1)},e(o.$t(`@WORKBENCH:取消`)),1),n[10]||=D(`span`,{class:`nc__foot-spacer`},null,-1),D(`button`,{type:`button`,class:`nc__btn`,disabled:!o.canSubmit,onClick:n[7]||=e=>o.submit(!0)},e(o.$t(`@WORKBENCH:创建并打开编辑器`)),9,Ps),D(`button`,{type:`button`,class:`nc__btn nc__btn--primary`,disabled:!o.canSubmit,onClick:n[8]||=e=>o.submit(!1)},e(o.submitting?o.$t(`@WORKBENCH:创建中…`):o.$t(`@WORKBENCH:创建`)),9,Fs)])]),default:W(()=>[D(`div`,bs,[D(`div`,xs,[D(`label`,Ss,e(o.$t(`@WORKBENCH:项目`)),1),z(D(`select`,{id:`nc-project`,"onUpdate:modelValue":n[0]||=e=>o.projectPath=e,class:`nc__select`},[D(`option`,Cs,e(o.$t(`@WORKBENCH:跟随当前项目`)),1),(M(!0),v(R,null,S(o.projectOptions,t=>(M(),v(`option`,{key:t.key,value:t.path},e(t.name)+e(t.exists===!1?` · ${o.$t(`@WORKBENCH:目录不存在`)}`:``),9,ws))),128))],512),[[ue,o.projectPath]]),D(`p`,{class:`nc__hint`,title:o.projectPath},e(o.projectName?o.$t(`@WORKBENCH:任务会在「{name}」目录下执行`,{name:o.projectName}):o.$t(`@WORKBENCH:任务会跟随应用当前的工作目录`)),9,Ts)]),D(`div`,Es,[D(`label`,Ds,e(o.$t(`@WORKBENCH:标题`)),1),z(D(`input`,{id:`nc-title`,"onUpdate:modelValue":n[1]||=e=>o.title=e,class:`nc__input`,type:`text`,maxlength:`200`,placeholder:o.$t(`@WORKBENCH:一句话说清要做什么`),onKeydown:n[2]||=K(J(e=>o.submit(!1),[`prevent`]),[`enter`])},null,40,Os),[[V,o.title]])]),D(`div`,ks,[D(`label`,As,e(o.$t(`@WORKBENCH:描述`)),1),z(D(`textarea`,{id:`nc-desc`,"onUpdate:modelValue":n[3]||=e=>o.desc=e,class:`nc__input nc__input--area`,rows:`6`,placeholder:o.$t(`@WORKBENCH:把背景、验收标准、相关文件路径写进来,执行时用它当上下文`),onKeydown:[n[4]||=K(J(e=>o.submit(!1),[`ctrl`,`prevent`]),[`enter`]),n[5]||=K(J(e=>o.submit(!1),[`meta`,`prevent`]),[`enter`])]},null,40,js),[[V,o.desc]])]),o.error?(M(),v(`p`,Ms,e(o.error),1)):r(`v-if`,!0)])]),_:1},8,[`model-value`,`title`])}var Ls=Q(ys,[[`render`,Is],[`__scopeId`,`data-v-c60e660a`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/components/WorkbenchTaskCreateDialog.vue`]]);X(),B();var Rs=`wb.boardProject.v1`,zs=5e3,Bs=`wb.boardLayout.v1`,Vs=180,Hs=420,Us=260,Ws=900,Gs=.26,Ks=.46,qs=120,Js=560,Ys=.5,Xs=s({__name:`WorkbenchBoard`,emits:[`open-task`],setup(e,{expose:t,emit:n}){t();let r=n,{projects:i,boardTasks:a,currentProjectPath:o,loading:s,loadProjects:c}=Cr(),{active:l,activity:d,running:p,dispatching:m,togglingSchedule:h,defaultPrompt:g,projectPrompts:_,loadOrchestrator:v,setSchedulingActive:y,dispatch:b,saveDefaultPrompt:x,saveProjectPrompt:S}=wr(),w=Y((()=>{try{return localStorage.getItem(Rs)||``}catch{return``}})());I(w,e=>{try{localStorage.setItem(Rs,e)}catch{}});let T=q(()=>w.value&&i.value.find(e=>e.key===w.value)||null);I(i,e=>{w.value&&(e.some(e=>e.key===w.value)||(w.value=``))});let E=q(()=>{let e=new Map(i.value.map(e=>[e.key,e.name])),t={};for(let n of a.value)n.projectPath&&(t[n.projectPath]=e.get($(n.projectPath))||``);return t}),D=q(()=>{if(!w.value)return a.value;let e=w.value;return a.value.filter(t=>$(t.projectPath)===e)}),O=q(()=>{let e=new Date;e.setHours(0,0,0,0);let t=e.getTime();return{projects:i.value.length,tasks:a.value.length,running:p.value.length,todayDone:d.value.filter(e=>e.kind===`done`&&e.at&&new Date(e.at).getTime()>=t).length}});function ee(e){r(`open-task`,{taskId:e.id,projectPath:e.projectPath})}let k=null,te=!1;async function j(e=!0){if(!te){te=!0;try{await Promise.all([c(e),v(e)])}finally{te=!1}}}function ne(){document.hidden||j(!0)}u(async()=>{window.addEventListener(`resize`,L),await j(!1),k=setInterval(()=>{document.hidden||j(!0)},zs),document.addEventListener(`visibilitychange`,ne)}),f(()=>{window.removeEventListener(`resize`,L),k&&=(clearInterval(k),null),document.removeEventListener(`visibilitychange`,ne)});let M=ie({left:null,right:null,agentH:null,leftCollapsed:!1,rightCollapsed:!1});function re(){try{let e=localStorage.getItem(Bs);if(!e)return;let t=JSON.parse(e);typeof t.left==`number`&&Number.isFinite(t.left)&&(M.left=t.left),typeof t.right==`number`&&Number.isFinite(t.right)&&(M.right=t.right),typeof t.agentH==`number`&&Number.isFinite(t.agentH)&&(M.agentH=t.agentH),M.leftCollapsed=t.leftCollapsed===!0,M.rightCollapsed=t.rightCollapsed===!0}catch{}}re();function N(){try{localStorage.setItem(Bs,JSON.stringify(M))}catch{}}let P=Y(typeof window>`u`?1920:window.innerWidth),ae=Y(typeof window>`u`?1080:window.innerHeight);function L(){P.value=window.innerWidth,ae.value=window.innerHeight}let R=q(()=>P.value<=1024),z=q(()=>P.value<=860);function oe(e,t){let n=e===`left`?Vs:Us,r=Math.min(e===`left`?Hs:Ws,P.value*(e===`left`?Gs:Ks));return Math.round(Math.min(Math.max(t,n),Math.max(n,r)))}function se(e){let t=Math.min(Js,ae.value*Ys);return Math.round(Math.min(Math.max(e,qs),Math.max(qs,t)))}let B=q(()=>{let e={};return M.left!=null&&(e[`--wb-left-w`]=oe(`left`,M.left)+`px`),M.right!=null&&!z.value&&(e[`--wb-right-w`]=oe(`right`,M.right)+`px`),e}),ce=q(()=>{let e={};return M.agentH!=null&&(e[`--wb-agents-h`]=se(M.agentH)+`px`),e}),V=Y(null),ue=Y(null),fe=Y(null);function pe(e){return V.value?.querySelector(e===`left`?`.board__left`:`.oc`)}function me(e){window.removeEventListener(`mousemove`,e),document.body.style.userSelect=``,document.body.style.cursor=``,fe.value=null,N()}function H(e,t){if(e===`left`?R.value:z.value)return;let n=pe(e);if(!n)return;t.preventDefault();let r=t.clientX,i=n.getBoundingClientRect().width;fe.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);M[e]=oe(e,i+n)};window.addEventListener(`mousemove`,a),window.addEventListener(`mouseup`,()=>me(a),{once:!0})}function he(e){M[e]=null,N()}function U(){return ue.value?.querySelector(`.agents`)}function ge(e){let t=U();if(!t)return;e.preventDefault();let n=e.clientY,r=t.getBoundingClientRect().height;fe.value=`agents`,document.body.style.userSelect=`none`,document.body.style.cursor=`row-resize`;let i=e=>{M.agentH=se(r+(n-e.clientY))};window.addEventListener(`mousemove`,i),window.addEventListener(`mouseup`,()=>me(i),{once:!0})}function _e(){M.agentH=null,N()}let W=Y(!1),ve=q(()=>R.value?!W.value:M.leftCollapsed);function ye(){if(R.value){W.value=!W.value;return}M.leftCollapsed=!M.leftCollapsed,N()}function G(){R.value&&(W.value=!1)}let be=q(()=>M.rightCollapsed&&!z.value);function xe(){M.rightCollapsed=!M.rightCollapsed,N()}function K(e){w.value=e?e.key:``,W.value=!1}let Ce=Y(!1);function we(){Ce.value=!0}async function Te(e){if(await j(!0),e.openEditor){r(`open-task`,{taskId:e.task.id,projectPath:e.task.projectPath||``});return}F.success(Z(`@WORKBENCH:已创建任务`))}async function J(e){if(e.runningJobs>0)return;let t=Ne(),n={claude:t.claudeAvailable,opencode:t.opencodeAvailable},r=Ke();n[r]||(r=r===`claude`?`opencode`:`claude`);let i=`/api/workbench/tasks/${encodeURIComponent(e.id)}/run`,a=await fetch(i,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({executor:r})}).then(e=>e.json()).catch(()=>null);if(!a?.success){F.error(a?.error||Z(`@WORKBENCH:执行失败`));return}F.success(Z(`@WORKBENCH:已开始执行`)),await j(!0)}async function X(e){let t=(e.title||``).trim()||Z(`@WORKBENCH:未命名任务`);try{await de.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){F.error(n.error||Z(`@WORKBENCH:删除失败`));return}await j(!0)}let Ee=Y(null),De=q(()=>T.value?.path||o.value);async function Oe(e){let t=await b({text:e.text,projectPath:e.projectPath,autoRun:e.autoRun,attachments:e.attachments,useDefaultPrompt:e.useDefaultPrompt,executor:e.executor});t&&(Ee.value?.clearAttachments(),F.success(t.ran?Z(`@WORKBENCH:已派发并开始执行`):Z(`@WORKBENCH:已派发(只建任务未执行)`)),await j(!0))}async function ke(e){await y(e)}let Q=Y(!1),Ae=Y(!1),je=q(()=>{let e=T.value?.key;return e&&_.value?.[e]?.prompt||``});async function Me(e){if(Ae.value)return;let t=e.globalPrompt.trim(),n=e.projectPrompt.trim(),r=T.value;Ae.value=!0;try{let e=!0;t!==(g.value||``).trim()&&(e=await x(t)),e&&r&&n!==je.value.trim()&&(e=await S(r.path,n)),e&&(Q.value=!1)}finally{Ae.value=!1}}let Pe={emit:r,projects:i,boardTasks:a,currentProjectPath:o,loading:s,loadProjects:c,active:l,activity:d,running:p,dispatching:m,togglingSchedule:h,defaultPrompt:g,projectPrompts:_,loadOrchestrator:v,setSchedulingActive:y,dispatch:b,saveDefaultPrompt:x,saveProjectPrompt:S,SELECTED_KEY:Rs,selectedKey:w,selectedProject:T,projectLabels:E,visibleTasks:D,headerStats:O,onOpenTask:ee,POLL_MS:zs,get pollTimer(){return k},set pollTimer(e){k=e},get inFlight(){return te},set inFlight(e){te=e},refresh:j,onVisibilityChange:ne,LAYOUT_KEY:Bs,LEFT_W_MIN:Vs,LEFT_W_MAX:Hs,RIGHT_W_MIN:Us,RIGHT_W_MAX:Ws,LEFT_W_SHARE:Gs,RIGHT_W_SHARE:Ks,AGENT_H_MIN:qs,AGENT_H_MAX:Js,AGENT_H_SHARE:Ys,layout:M,readLayout:re,saveLayout:N,viewportW:P,viewportH:ae,onWindowResize:L,isNarrow:R,isStacked:z,clampWidth:oe,clampAgentH:se,boardStyle:B,leftStyle:ce,colsRef:V,leftRef:ue,dragging:fe,panelEl:pe,endDrag:me,onSplitterMouseDown:H,onSplitterDblClick:he,agentEl:U,onAgentSplitterMouseDown:ge,onAgentSplitterDblClick:_e,leftDrawerOpen:W,leftHidden:ve,toggleLeft:ye,onLeftEsc:G,rightHidden:be,toggleRight:xe,onSelectProject:K,createOpen:Ce,onCreateClick:we,onTaskCreated:Te,runTask:J,deleteTask:X,consoleRef:Ee,defaultProjectPath:De,onDispatch:Oe,onToggleSchedule:ke,promptDialogOpen:Q,savingPrompt:Ae,selectedProjectPrompt:je,onSavePromptDraft:Me,get $t(){return Z},get Plus(){return C},get Refresh(){return A},get Fold(){return Se},get Expand(){return le},WorkbenchProjectPanel:$i,WorkbenchAgentPanel:ma,WorkbenchKanban:to,OrchestratorConsole:$o,WorkbenchDefaultPromptDialog:vs,WorkbenchTaskCreateDialog:Ls};return Object.defineProperty(Pe,"__isScriptSetup",{enumerable:!1,value:!0}),Pe}});X(),b(),G();var Zs={class:`board__top`},Qs=[`title`,`aria-label`,`aria-expanded`],$s={class:`board__brand`},ec={class:`board__brand-text`},tc={class:`board__title`},nc={class:`board__subtitle`},rc={class:`board__stats`},ic={class:`board__stat`},ac={class:`board__stat-label`},oc={class:`board__stat-value`},sc={class:`board__stat`},cc={class:`board__stat-label`},lc={class:`board__stat-value`},uc={class:`board__stat`},dc={class:`board__stat-label`},fc={class:`board__stat`},pc={class:`board__stat-label`},mc={class:`board__stat-value`},hc={class:`board__actions`},gc=[`title`,`aria-label`],_c=[`title`],vc=[`title`],yc={class:`board__main`},bc={class:`board__main-head`},xc={class:`board__main-title`},Sc={class:`board__project-name`},Cc=[`title`],wc={key:1,class:`board__project-path`},Tc={key:0,class:`board__project-meta`},Ec=[`title`];function Dc(t,n,i,o,s,c){let l=d,u=p;return M(),v(`div`,{class:`board`,style:N(o.boardStyle)},[D(`header`,Zs,[r(` 左栏的开合。宽屏=收起/展开常驻那一栏;窄屏=抽屉 `),D(`button`,{type:`button`,class:U([`board__icon-btn board__fold-btn`,{"is-on":!o.leftHidden}]),title:o.leftHidden?o.$t(`@WORKBENCH:展开项目列表`):o.$t(`@WORKBENCH:收起项目列表`),"aria-label":o.leftHidden?o.$t(`@WORKBENCH:展开项目列表`):o.$t(`@WORKBENCH:收起项目列表`),"aria-expanded":!o.leftHidden,onClick:o.toggleLeft},[o.leftHidden?(M(),a(l,{key:1},{default:W(()=>[_(o.Expand)]),_:1})):(M(),a(l,{key:0},{default:W(()=>[_(o.Fold)]),_:1}))],10,Qs),D(`div`,$s,[D(`span`,{class:U([`board__live`,{"is-off":!o.active}]),"aria-hidden":`true`},null,2),D(`div`,ec,[D(`h1`,tc,e(o.$t(`@WORKBENCH:多项目编排台`)),1),D(`p`,nc,e(o.active?o.$t(`@WORKBENCH:主 Agent 调度中`):o.$t(`@WORKBENCH:主 Agent 已暂停`)),1)])]),D(`div`,rc,[D(`span`,ic,[D(`span`,ac,e(o.$t(`@WORKBENCH:项目`)),1),D(`strong`,oc,e(o.headerStats.projects),1)]),D(`span`,sc,[D(`span`,cc,e(o.$t(`@WORKBENCH:任务`)),1),D(`strong`,lc,e(o.headerStats.tasks),1)]),D(`span`,uc,[D(`span`,dc,e(o.$t(`@WORKBENCH:活跃执行`)),1),D(`strong`,{class:U([`board__stat-value`,{"is-live":o.headerStats.running>0}])},e(o.headerStats.running),3)]),D(`span`,fc,[D(`span`,pc,e(o.$t(`@WORKBENCH:今日完成`)),1),D(`strong`,mc,e(o.headerStats.todayDone),1)])]),D(`div`,hc,[D(`button`,{type:`button`,class:`board__icon-btn`,title:o.$t(`@WORKBENCH:刷新`),"aria-label":o.$t(`@WORKBENCH:刷新`),onClick:n[0]||=e=>o.refresh(!1)},[_(l,null,{default:W(()=>[_(o.Refresh)]),_:1})],8,gc),_(u,{type:`primary`,size:`small`,icon:o.Plus,onClick:o.onCreateClick},{default:W(()=>[g(e(o.$t(`@WORKBENCH:新建开发任务`)),1)]),_:1},8,[`icon`])])]),D(`div`,{ref:`colsRef`,class:U([`board__cols`,{"is-resizing":o.dragging!==null}])},[r(` 抽屉打开时的点击捕获层:点空白处收起。
42
- 只在窄屏 + 打开时才 display:block(见媒体查询),宽屏下是个不占位的空 div。
43
- 不加遮罩底色而是全透明 —— 只是为了接住点击,不是为了压暗看板;
44
- 真要压暗就得处理深色主题下半透明背景叠不实的老问题(见 NOTES §2)。 `),D(`div`,{class:U([`board__scrim`,{"is-on":o.leftDrawerOpen}]),"aria-hidden":`true`,onClick:n[1]||=e=>o.leftDrawerOpen=!1},null,2),D(`aside`,{ref:`leftRef`,class:U([`board__left`,{"is-collapsed":o.leftHidden}]),style:N(o.leftStyle),onKeydown:K(o.onLeftEsc,[`esc`])},[_(o.WorkbenchProjectPanel,{projects:o.projects,"selected-key":o.selectedKey,loading:o.loading,onSelect:o.onSelectProject},null,8,[`projects`,`selected-key`,`loading`]),r(` 项目列表 / 执行监控之间的横向分隔条:上下拖动改监控高度,双击恢复默认。
45
- 这条同时也画出两段之间的那条 1px 分隔线(原来挂在 .agents 的 border-top 上)。 `),D(`div`,{class:`board__splitter board__splitter--h`,role:`separator`,"aria-orientation":`horizontal`,title:o.$t(`@WORKBENCH:上下拖动调整执行监控高度,双击恢复默认`),onMousedown:o.onAgentSplitterMouseDown,onDblclick:o.onAgentSplitterDblClick},null,40,_c),_(o.WorkbenchAgentPanel,{running:o.running},null,8,[`running`])],38),r(` 左栏分隔条:左栏收起 / 窄屏抽屉模式下不占位(不渲染 / 媒体查询里 display:none) `),o.leftHidden?r(`v-if`,!0):(M(),v(`div`,{key:0,class:`board__splitter board__splitter--left`,role:`separator`,"aria-orientation":`vertical`,title:o.$t(`@WORKBENCH:拖动调整项目列表宽度,双击恢复默认`),onMousedown:n[2]||=e=>o.onSplitterMouseDown(`left`,e),onDblclick:n[3]||=e=>o.onSplitterDblClick(`left`)},null,40,vc)),D(`main`,yc,[D(`div`,bc,[D(`div`,xc,[D(`h2`,Sc,e(o.selectedProject?o.selectedProject.name:o.$t(`@WORKBENCH:全部项目`)),1),o.selectedProject?(M(),v(`span`,{key:0,class:`board__project-path`,title:o.selectedProject.path},e(o.selectedProject.path),9,Cc)):(M(),v(`span`,wc,e(o.$t(`@WORKBENCH:共 {n} 个项目的任务`,{n:o.projects.length})),1))]),o.selectedProject?(M(),v(`span`,Tc,e(o.$t(`@WORKBENCH:{done}/{total} 任务完成`,{done:o.selectedProject.stats.done,total:o.selectedProject.stats.total})),1)):r(`v-if`,!0)]),_(o.WorkbenchKanban,{tasks:o.visibleTasks,"project-labels":o.projectLabels,"show-project-label":!o.selectedProject,onOpenTask:o.onOpenTask,onRunTask:o.runTask,onDeleteTask:o.deleteTask,onCreateTask:o.onCreateClick},null,8,[`tasks`,`project-labels`,`show-project-label`])]),r(` 右栏分隔条:右栏收起 / 竖排(≤860)时不占位 `),!o.rightHidden&&!o.isStacked?(M(),v(`div`,{key:1,class:`board__splitter board__splitter--right`,role:`separator`,"aria-orientation":`vertical`,title:o.$t(`@WORKBENCH:拖动调整主 Agent 控制台宽度,双击恢复默认`),onMousedown:n[4]||=e=>o.onSplitterMouseDown(`right`,e),onDblclick:n[5]||=e=>o.onSplitterDblClick(`right`)},null,40,Ec)):r(`v-if`,!0),_(o.OrchestratorConsole,{ref:`consoleRef`,active:o.active,activity:o.activity,"running-count":o.running.length,"selected-project":o.selectedProject,dispatching:o.dispatching,"toggling-schedule":o.togglingSchedule,"today-done":o.headerStats.todayDone,collapsed:o.rightHidden,"default-prompt":o.defaultPrompt,"project-prompts":o.projectPrompts,onToggleCollapse:o.toggleRight,onToggleSchedule:o.onToggleSchedule,onDispatch:o.onDispatch,onOpenPromptSettings:n[6]||=e=>o.promptDialogOpen=!0},null,8,[`active`,`activity`,`running-count`,`selected-project`,`dispatching`,`toggling-schedule`,`today-done`,`collapsed`,`default-prompt`,`project-prompts`])],2),r(` 派发默认提示词:全局一条 + 选中项目一条,写完即生效于之后的派发 `),_(o.WorkbenchDefaultPromptDialog,{modelValue:o.promptDialogOpen,"onUpdate:modelValue":n[7]||=e=>o.promptDialogOpen=e,"default-prompt":o.defaultPrompt,"project-path":o.selectedProject?.path||``,"project-name":o.selectedProject?.name||``,"project-prompt":o.selectedProjectPrompt,saving:o.savingPrompt,onSave:o.onSavePromptDraft},null,8,[`modelValue`,`default-prompt`,`project-path`,`project-name`,`project-prompt`,`saving`]),r(` 新建任务:弹窗里问清字段,建完就关 `),_(o.WorkbenchTaskCreateDialog,{modelValue:o.createOpen,"onUpdate:modelValue":n[8]||=e=>o.createOpen=e,projects:o.projects,"default-project-path":o.defaultProjectPath,onCreated:o.onTaskCreated},null,8,[`modelValue`,`projects`,`default-project-path`])],4)}var Oc=Q(Xs,[[`render`,Dc],[`__scopeId`,`data-v-dd2dc7b4`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/components/WorkbenchBoard.vue`]]);X(),B();var kc=`wb.lastTaskByProject.v1`,Ac=`__no_project__`,jc=`wb.sidebarWidth.v1`,Mc=200,Nc=480,Pc=268,Fc=52,Ic=320,Lc=500,Rc=s({__name:`WorkbenchView`,setup(e,{expose:t}){t();let n=je(),r=Ne(),i=Y((()=>{try{let e=parseInt(localStorage.getItem(jc)||``,10);return Number.isFinite(e)?Math.min(Nc,Math.max(Mc,e)):Pc}catch{return Pc}})());function a(e){e.preventDefault();let t=e.clientX,n=i.value;document.body.style.userSelect=`none`,document.body.style.cursor=`col-resize`;let r=e=>{i.value=Math.min(Nc,Math.max(Mc,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(jc,String(i.value))}catch{}},{once:!0})}function o(){try{let e=localStorage.getItem(kc),t=e?JSON.parse(e):{};return t&&typeof t==`object`&&!Array.isArray(t)?t:{}}catch{return{}}}function s(e){try{localStorage.setItem(kc,JSON.stringify(e))}catch{}}function c(e,t){let n=o();n[e||Ac]=t,s(n)}let d=Y(!1);function p(){d.value=!1}async function m(e){await E(),A.value=e.taskId,N(),j.value&&c($(v.value.path),e.taskId),d.value=!0}let{prompts:h,tasks:g,jobs:_,currentProject:v,syncRunningCount:y,connectSSE:b,disconnectSSE:x,loadPrompts:S,loadCurrentProject:C,loadJobs:w,clearJobsByTask:T,loadTasks:E}=Fn();function D(){let e=$(v.value.path),t=g.value.filter(t=>!t.projectPath||$(t.projectPath)===e),n=o(),r=e&&n[e]||!e&&n[Ac]||``,i=r?g.value.find(e=>e.id===r):null,a=t[0]||g.value[0]||null,s=i&&i.projectPath&&$(i.projectPath)!==e?null:i?i.id:a?a.id:null;A.value=s,N()}async function O(){let e=A.value;if(await E(),e&&g.value.some(t=>t.id===e)){N();return}D()}async function ee(){await E(),D()}let te=Y(!1),A=Y(null),j=q(()=>g.value.find(e=>e.id===A.value)||null),ne=q(()=>{let e=j.value?.projectPath||``;return!e||$(e)===$(v.value.path)?null:{name:e.replace(/[\\/]+$/,``).split(/[\\/]/).pop()||e,path:e}}),M=Y({title:``,desc:``,promptId:null,simpleOverride:``});function N(){j.value?M.value={title:j.value.title,desc:j.value.desc,promptId:j.value.promptId,simpleOverride:j.value.simpleOverride||``}:M.value={title:``,desc:``,promptId:null,simpleOverride:``}}let P=Y(`idle`),ae=Y(0),L=null,R=q(()=>{if(!j.value)return!1;let e=j.value;return M.value.title!==e.title||M.value.desc!==e.desc||M.value.promptId!==e.promptId||M.value.simpleOverride!==(e.simpleOverride||``)});function z(){L!==null&&(clearTimeout(L),L=null)}function B(e){return!(!e||(e.title||``).trim()||(e.desc||``).trim()||e.promptId||(e.simpleOverride||``).trim()||Array.isArray(e.attachments)&&e.attachments.length>0)}async function V(e){try{await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`})}catch{}let t=g.value.findIndex(t=>t.id===e.id);t!==-1&&g.value.splice(t,1)}async function le(){let e=g.value.filter(e=>e.id!==A.value&&B(e));for(let t of e)await V(t)}async function ue(){if(!j.value)return!1;if(!R.value)return!0;if(P.value=`saving`,await Ye(!1))return ae.value=Date.now(),P.value=`saved`,setTimeout(()=>{P.value===`saved`&&Date.now()-ae.value>=4e3&&(P.value=`idle`)},4e3),!0;P.value=`error`;let e=Date.now();return setTimeout(()=>{P.value===`error`&&Date.now()-e>=4e3&&(P.value=`idle`)},4e3),!1}I(()=>j.value?{id:j.value.id,title:j.value.title,desc:j.value.desc,promptId:j.value.promptId,simpleOverride:j.value.simpleOverride||``}:null,(e,t)=>{e&&t&&e.id===t.id&&(L!==null&&clearTimeout(L),L=window.setTimeout(()=>{ue()},1500))},{deep:!0}),I(A,async(e,t)=>{z(),j.value&&R.value&&await ue()}),I(v,async e=>{if(!e.path)return;let t=$(e.path),n=j.value;n&&n.projectPath&&$(n.projectPath)!==t&&await ee()});function pe(e){try{let t=new Blob([JSON.stringify(e)],{type:`application/json`});navigator.sendBeacon?.(`/api/workbench/tasks`,t)}catch{}}function me(){j.value&&R.value&&!B(j.value)&&pe(j.value)}let H=ie({visible:!1,editing:null,name:``,content:``,aiLoading:!1,projectPath:``}),U=ie({visible:!1,text:``,loading:!1,saving:!1}),ge=Y(!0),_e=q(()=>{let e=$(v.value.path);return h.value.filter(t=>!t.projectPath||$(t.projectPath)===e)});async function W(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 ye=Y(null),G=Y(null);async function be(e){if(e){if(!await W((e.title||``).trim()||Z(`@WORKBENCH:未命名任务`))){F.error(Z(`@WORKBENCH:复制失败`));return}ye.value=e.id,F.success(Z(`@WORKBENCH:已复制任务标题`)),window.setTimeout(()=>{ye.value===e.id&&(ye.value=null)},1500)}}async function xe(e){if(!e)return;let t=(e.desc||``).trim();if(!t){F.warning(Z(`@WORKBENCH:任务描述为空,无需复制`));return}if(!await W(t)){F.error(Z(`@WORKBENCH:复制失败`));return}G.value=e.id,F.success(Z(`@WORKBENCH:已复制任务描述`)),window.setTimeout(()=>{G.value===e.id&&(G.value=null)},1500)}let{simpleConversationMessages:K,simpleAllJobsFor:Se,simpleJobFor:Ce,simpleJobState:we}=Nn(_,j);function Te(e){if(!e)return!1;let t=Ce(e);return!!t&&(t.status===`running`||t.status===`pending`)}function J(){H.editing=null,H.name=``,H.content=``,H.aiLoading=!1,H.projectPath=(v.value.path||``).trim(),H.visible=!0}function X(e){H.editing=e,H.name=e.name,H.content=e.content,H.aiLoading=!1,H.projectPath=(e.projectPath||``).trim(),H.visible=!0}async function Oe(){if(!H.aiLoading){H.aiLoading=!0;try{let e=await fetch(`/api/workbench/prompts/ai-generate`,{method:`POST`}).then(e=>e.json());e.success?(H.name=e.name||H.name,H.content=e.result||``,F.success(Z(`@WORKBENCH:已生成,可继续编辑`))):F.error(e.error||Z(`@WORKBENCH:生成失败`))}catch(e){F.error(Z(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}finally{H.aiLoading=!1}}}async function ke(){U.visible=!0,U.loading=!0;try{let e=await fetch(`/api/workbench/prompts/ai-instruction`).then(e=>e.json());e.success?U.text=e.instruction||``:F.error(e.error||Z(`@WORKBENCH:读取指令失败`))}catch(e){F.error(Z(`@WORKBENCH:读取指令失败`)+`: `+(e&&e.message||e))}finally{U.loading=!1}}async function Q(){if(!U.text.trim()){F.warning(Z(`@WORKBENCH:指令内容不能为空`));return}U.saving=!0;try{let e=await fetch(`/api/workbench/prompts/ai-instruction`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({instruction:U.text})}).then(e=>e.json());e.success?(F.success(Z(`@WORKBENCH:已保存指令`)),U.visible=!1):F.error(e.error||Z(`@WORKBENCH:保存失败`))}catch(e){F.error(Z(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}finally{U.saving=!1}}async function Ae(){if(!H.name.trim()||!H.content.trim()){F.warning(Z(`@WORKBENCH:名称和内容不能为空`));return}let e={id:H.editing?.id,name:H.name.trim(),content:H.content,projectPath:(H.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?(F.success(Z(`@WORKBENCH:已保存`)),H.visible=!1,S()):F.error(t.error||Z(`@WORKBENCH:保存失败`))}async function Pe(e){await de.confirm(Z(`@WORKBENCH:删除提示词「{name}」?`,{name:e.name}),Z(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/prompts/${e.id}`,{method:`DELETE`}),S();for(let t of g.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 O()}let Le=Y(!1),Re=Y(null),ze=Y(null);function Be(e){let t=e?.currentTarget||ze.value;if(!t)return;t.style.height=`auto`;let n=document.activeElement===t?Lc:Ic,r=Math.min(Math.max(t.scrollHeight,Fc),n);t.style.height=`${r}px`,t.style.overflowY=t.scrollHeight>n?`auto`:`hidden`}I(ge,async e=>{e&&(await k(),Be())}),I(()=>j.value?.id,async()=>{ge.value&&(await k(),Be())});async function Ve(){if(Le.value)return;Le.value=!0;let e={title:``,desc:``,promptId:null,simpleOverride:``};v.value.path&&(e.projectPath=v.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){F.error(t.error||Z(`@WORKBENCH:保存失败`));return}z(),j.value&&B(j.value)?await V(j.value):j.value&&R.value&&await ue(),await ee(),t.task?.id&&(A.value=t.task.id,N(),F.success(Z(`@WORKBENCH:已新建任务`)),await k(),Re.value?.focus())}finally{Le.value=!1}}async function He(e){await de.confirm(Z(`@WORKBENCH:删除任务「{title}」?`,{title:e.title}),Z(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`}),A.value===e.id&&(A.value=null),ee()}async function Ue(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||``};v.value.path&&(n.projectPath=v.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){F.error(e.error||Z(`@WORKBENCH:复制失败`));return}await ee(),e.task?.id&&(A.value=e.task.id,N()),F.success(Z(`@WORKBENCH:已复制任务`))}catch(e){F.error(Z(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}}async function Ge(e){if(A.value===e.id)return;z();let t=j.value;t&&B(t)?await V(t):t&&R.value&&await ue(),A.value=e.id,N(),c($(v.value.path),e.id)}async function qe(e){let{groupPath:t,orderedIds:n}=e;if(!Array.isArray(n)||n.length===0)return;let r=g.value.slice(),i=Je(g.value,t,n);if(i!==g.value){g.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||(g.value=r,F.error(e?.error||Z(`@WORKBENCH:排序保存失败`)))}catch(e){g.value=r,F.error(Z(`@WORKBENCH:排序保存失败`)+`: `+(e?.message||e))}}}function Je(e,t,n){let r=e=>$(e)||Ac,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 Ye(e){if(!j.value)return!1;let t=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(j.value)}).then(e=>e.json());return t.success?(e&&F.success(Z(`@WORKBENCH:已保存`)),await O(),!0):(F.error(t.error||Z(`@WORKBENCH:保存失败`)),!1)}u(async()=>{await Promise.all([S(),ee(),C(),w()]),await le(),b(),window.addEventListener(`beforeunload`,me)}),f(()=>{x(),window.removeEventListener(`beforeunload`,me),j.value&&R.value&&!B(j.value)&&pe(j.value)});let{pasteHoverId:Xe,isUploading:Ze,isImageAttachment:Qe,humanSize:$e,onAttachmentPaste:et,onAttachmentDrop:tt,uploadAttachment:nt,removeAttachment:rt,pickAttachmentFile:it}=An(),{runTask:at,onContinueSendFromChat:ot,cancelJob:st,clearExecutionForSelectedTask:lt}=Pn(_,g,j,{syncRunningCount:y,clearJobsByTask:T,persistTask:Ye,uploadAttachment:nt,getExecutor:()=>ut.value}),ut=Y(Ke()),ft=q(()=>({claude:r.claudeAvailable,opencode:r.opencodeAvailable})),pt=q(()=>ft.value.claude||ft.value.opencode);I(ft,e=>{if(e[ut.value])return;let t=Object.keys(e).find(t=>e[t]);t&&(ut.value=t)},{immediate:!0});function mt(e){ft.value[e]&&(ut.value=e,Ie(e))}function ht(e){return We.find(t=>t.id===e)?.name||e}let gt=q(()=>Se(j.value).slice(-1)[0]),_t={configStore:n,toolsStore:r,LAST_TASK_BY_PROJECT_KEY:kc,NO_PROJECT_KEY:Ac,SIDEBAR_WIDTH_KEY:jc,SIDEBAR_MIN_W:Mc,SIDEBAR_MAX_W:Nc,SIDEBAR_DEFAULT_W:Pc,sidebarWidth:i,onSidebarSplitterMouseDown:a,readLastTaskMap:o,writeLastTaskMap:s,rememberLastTask:c,editorOpen:d,closeEditor:p,openTaskFromBoard:m,prompts:h,tasks:g,jobs:_,currentProject:v,syncRunningCount:y,connectSSE:b,disconnectSSE:x,loadPrompts:S,loadCurrentProject:C,loadJobs:w,clearJobsByTask:T,_loadDataTasks:E,applyRestoredSelection:D,refreshTasks:O,loadTasks:ee,logsDialogVisible:te,selectedTaskId:A,selectedTask:j,foreignRepo:ne,metaSnapshot:M,captureSnapshot:N,metaSaveState:P,metaSavedAt:ae,get metaSaveTimer(){return L},set metaSaveTimer(e){L=e},metaDirty:R,clearMetaSaveTimers:z,isTaskBlank:B,discardBlankTask:V,pruneBlankTasks:le,flushMetaSave:ue,beaconPersist:pe,onBeforeUnloadPersist:me,promptDialog:H,instructionDialog:U,taskDescExpanded:ge,availablePrompts:_e,copyToClipboard:W,copyTitleFlashId:ye,copyDescFlashId:G,copyTaskTitle:be,copyTaskDesc:xe,simpleConversationMessages:K,simpleAllJobsFor:Se,simpleJobFor:Ce,simpleJobState:we,isTaskRunning:Te,openCreatePrompt:J,openEditPrompt:X,aiGeneratePrompt:Oe,openEditInstruction:ke,saveInstruction:Q,savePrompt:Ae,deletePrompt:Pe,creatingTask:Le,titleInputRef:Re,taskDescTextareaRef:ze,DESC_TEXTAREA_MIN_PX:Fc,DESC_TEXTAREA_MAX_PX:Ic,DESC_TEXTAREA_MAX_PX_FOCUS:Lc,autoGrowTextarea:Be,createTaskDirect:Ve,deleteTask:He,copyTask:Ue,selectTask:Ge,reorderTasks:qe,applyLocalReorder:Je,persistTask:Ye,pasteHoverId:Xe,isUploading:Ze,isImageAttachment:Qe,humanSize:$e,onAttachmentPaste:et,onAttachmentDrop:tt,uploadAttachment:nt,removeAttachment:rt,pickAttachmentFile:it,runTask:at,onContinueSendFromChat:ot,cancelJob:st,clearExecutionForSelectedTask:lt,selectedTaskExecutor:ut,executorAvailability:ft,hasAnyExecutor:pt,pickExecutor:mt,executorLabel:ht,lastSimpleJob:gt,simpleAssistantLabel:q(()=>gt.value?.agent===`opencode`?`OpenCode`:`Claude`),simpleAssistantAvatar:q(()=>dt(gt.value?.agent)),get $t(){return Z},get ArrowDown(){return he},get ArrowLeft(){return l},get ArrowRight(){return re},get Check(){return se},get Document(){return ce},get Delete(){return oe},get CopyDocument(){return ve},get Warning(){return fe},AttachmentZone:ct,get ChatInput(){return Ee},get ChatContainer(){return De},ExecutionLogManager:yn,get ALLOWED_EXT_HINT(){return xn},get MAX_ATTACHMENT_BYTES(){return Sn},get TASK_EXECUTOR_OPTIONS(){return We},TaskExecutorIcon:Fe,WorkbenchSidebar:Sr,WorkbenchBoard:Oc,CommonDialog:Me};return Object.defineProperty(_t,"__isScriptSetup",{enumerable:!1,value:!0}),_t}});X(),b(),G();var zc={class:`workbench`},Bc={class:`wb-editor`},Vc={class:`wb-editor-bar`},Hc=[`title`],Uc=[`title`],Wc=[`title`],Gc={class:`wb-editor-bar__hint`},Kc={class:`workbench__editor-row`},qc=[`title`],Jc={class:`wb-split`},Yc={key:0,class:`wb-placeholder`},Xc={class:`wb-split__header`},Zc={class:`wb-split__title-wrap`},Qc=[`placeholder`],$c=[`title`,`aria-label`],el=[`title`],tl={key:0,class:`wb-meta-save__dot`},nl={key:1,class:`wb-meta-save__check`},rl={key:2,class:`wb-meta-save__bang`},il={key:3,class:`wb-meta-save__dot`},al={value:null},ol=[`value`],sl={class:`wb-executor-split__hint`},cl={class:`wb-executor-item`},ll={class:`wb-executor-item__name`},ul={key:1,class:`wb-executor-item__missing`},dl={key:2,class:`wb-no-claude-hint`,role:`status`},fl={class:`wb-no-claude-hint__text`},pl={class:`wb-no-claude-hint__link`,href:`https://docs.claude.com/en/docs/claude-code/setup`,target:`_blank`,rel:`noopener noreferrer`},ml=[`title`,`aria-label`],hl=[`title`,`aria-label`],gl=[`open`],_l={class:`wb-task-desc__summary`},vl={class:`wb-task-desc__label`},yl=[`title`,`aria-label`],bl={key:0,class:`wb-task-desc__tag`},xl={key:0},Sl={key:1,class:`wb-task-desc__tag-attachment`},Cl=[`placeholder`],wl={class:`wb-execution-body`},Tl={class:`wb-exec-detail`},El={class:`wb-form-item__label wb-simple__override-summary`},Dl=[`title`],Ol=[`placeholder`],kl={key:0,class:`wb-simple-chat-wrap`},Al={key:0,class:`wb-simple-chat__footer`},jl={style:{display:`flex`,gap:`8px`,"align-items":`center`}};function Ml(t,s,c,l,u,f){let m=d,h=n,b=Ce,x=w,C=i,T=te,E=j,O=y,k=o,A=p,ne=ee;return M(),v(`div`,zc,[r(` L1:多项目编排台 —— **常驻底图**,不再与编辑器互斥 `),_(l.WorkbenchBoard,{onOpenTask:l.openTaskFromBoard}),r(` L2:单任务编辑器 —— 大弹窗浮在看板之上,关掉即回到原位,全程无跳转 `),_(l.CommonDialog,{modelValue:l.editorOpen,"onUpdate:modelValue":s[21]||=e=>l.editorOpen=e,title:l.$t(`@WORKBENCH:任务执行`),type:`flex`,"height-mode":`fixed`,"height-offset":`88px`,top:`2vh`,width:`min(1520px, 96vw)`},{default:W(()=>[D(`div`,Bc,[r(` 顶部细栏:关闭入口做成独立一条,而不是塞进任务头 ——
46
- 没选中任务时(右侧是空态占位)也需要它,塞进任务头就会出现"进了编辑器却关不掉"的死角。 `),D(`div`,Vc,[D(`button`,{type:`button`,class:`wb-back-btn`,title:l.$t(`@WORKBENCH:返回看板`),onClick:l.closeEditor},[_(m,{class:`wb-back-btn__icon`},{default:W(()=>[_(l.ArrowLeft)]),_:1}),D(`span`,null,e(l.$t(`@WORKBENCH:返回看板`)),1)],8,Hc),D(`span`,{class:`wb-editor-bar__project`,title:l.currentProject.path},e(l.currentProject.name),9,Uc),l.foreignRepo?(M(),v(`span`,{key:0,class:`wb-editor-bar__repo`,title:l.foreignRepo.path},e(l.$t(`@WORKBENCH:执行于 {name}`,{name:l.foreignRepo.name})),9,Wc)):r(`v-if`,!0),D(`span`,Gc,e(l.$t(`@WORKBENCH:任务执行`)),1)]),D(`div`,Kc,[_(l.WorkbenchSidebar,{style:N({width:l.sidebarWidth+`px`}),tasks:l.tasks,prompts:l.prompts,"selected-task-id":l.selectedTaskId,"current-project":l.currentProject,"creating-task":l.creatingTask,"is-task-running":l.isTaskRunning,onSelectTask:l.selectTask,onDeleteTask:l.deleteTask,onCopyTask:l.copyTask,onCreateTask:l.createTaskDirect,onOpenCreatePrompt:l.openCreatePrompt,onOpenEditPrompt:l.openEditPrompt,onDeletePrompt:l.deletePrompt,onReorderTasks:l.reorderTasks},null,8,[`style`,`tasks`,`prompts`,`selected-task-id`,`current-project`,`creating-task`]),D(`div`,{class:`wb-splitter`,role:`separator`,"aria-orientation":`vertical`,title:l.$t(`@WORKBENCH:拖动调整侧边栏宽度`),onMousedown:l.onSidebarSplitterMouseDown},null,40,qc),r(` 中:单任务编辑区 `),D(`section`,Jc,[l.selectedTask?(M(),v(R,{key:1},[D(`div`,Xc,[D(`div`,Zc,[z(D(`input`,{ref:`titleInputRef`,class:`wb-input wb-input--title`,"onUpdate:modelValue":s[0]||=e=>l.selectedTask.title=e,placeholder:l.$t(`@WORKBENCH:任务标题`)},null,8,Qc),[[V,l.selectedTask.title]]),D(`button`,{type:`button`,class:U([`wb-copy-btn`,{"is-flash":l.copyTitleFlashId===l.selectedTask.id}]),title:l.$t(`@WORKBENCH:复制任务标题`),"aria-label":l.$t(`@WORKBENCH:复制任务标题`),onClick:s[1]||=e=>l.copyTaskTitle(l.selectedTask)},[l.copyTitleFlashId===l.selectedTask.id?(M(),a(m,{key:1,class:`wb-copy-btn__icon wb-copy-btn__icon--check`},{default:W(()=>[...s[31]||=[g(`✓`,-1)]]),_:1})):(M(),a(m,{key:0,class:`wb-copy-btn__icon`},{default:W(()=>[_(l.CopyDocument)]),_:1}))],10,$c)]),l.metaSaveState!==`idle`||l.metaDirty?(M(),v(`span`,{key:0,class:U([`wb-meta-save`,{"is-saving":l.metaSaveState===`saving`,"is-saved":l.metaSaveState===`saved`,"is-error":l.metaSaveState===`error`,"is-dirty":l.metaDirty&&l.metaSaveState===`idle`}]),title:l.metaSaveState===`saving`?l.$t(`@WORKBENCH:保存中…`):l.metaSaveState===`error`?l.$t(`@WORKBENCH:保存失败`):l.metaSaveState===`saved`?l.$t(`@WORKBENCH:已保存`):``},[l.metaSaveState===`saving`?(M(),v(`span`,tl)):l.metaSaveState===`saved`?(M(),v(`span`,nl,`✓`)):l.metaSaveState===`error`?(M(),v(`span`,rl,`!`)):(M(),v(`span`,il)),g(` `+e(l.metaSaveState===`saving`?l.$t(`@WORKBENCH:保存中…`):l.metaSaveState===`saved`?l.$t(`@WORKBENCH:已保存`):l.metaSaveState===`error`?l.$t(`@WORKBENCH:保存失败`):l.$t(`@WORKBENCH:有未保存的更改`)),1)],10,el)):r(`v-if`,!0),z(D(`select`,{class:`wb-select`,"onUpdate:modelValue":s[2]||=e=>l.selectedTask.promptId=e},[D(`option`,al,e(l.$t(`@WORKBENCH:不绑定预置提示词`)),1),(M(!0),v(R,null,S(l.availablePrompts,t=>(M(),v(`option`,{key:t.id,value:t.id},e(t.name),9,ol))),128))],512),[[ue,l.selectedTask.promptId]]),r(` 执行:split button —— 主体按当前选中执行器直接跑,下拉临时切换执行器 `),l.hasAnyExecutor?(M(),a(x,{key:1,"split-button":``,type:`primary`,class:`wb-executor-split`,trigger:`click`,onClick:s[3]||=e=>l.runTask(l.selectedTask),onCommand:l.pickExecutor},{dropdown:W(()=>[_(b,null,{default:W(()=>[(M(!0),v(R,null,S(l.TASK_EXECUTOR_OPTIONS,t=>(M(),a(h,{key:t.id,command:t.id,disabled:!l.executorAvailability[t.id]},{default:W(()=>[D(`span`,cl,[_(l.TaskExecutorIcon,{executor:t.id,class:`wb-executor-item__icon`},null,8,[`executor`]),D(`span`,ll,e(t.name),1),l.selectedTaskExecutor===t.id?(M(),a(m,{key:0,class:`wb-executor-item__check`},{default:W(()=>[_(l.Check)]),_:1})):l.executorAvailability[t.id]?r(`v-if`,!0):(M(),v(`span`,ul,e(l.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`,`disabled`]))),128))]),_:1})]),default:W(()=>[g(e(l.$t(`@WORKBENCH:执行任务`))+` `,1),D(`span`,sl,[_(l.TaskExecutorIcon,{executor:l.selectedTaskExecutor,class:`wb-executor-split__hint-icon`},null,8,[`executor`]),g(` `+e(l.executorLabel(l.selectedTaskExecutor)),1)])]),_:1})):(M(),v(`div`,dl,[_(m,{class:`wb-no-claude-hint__icon`},{default:W(()=>[_(l.Warning)]),_:1}),D(`span`,fl,e(l.$t(`@WORKBENCH:未检测到本地 claude / opencode,无法执行任务`)),1),D(`a`,pl,e(l.$t(`@WORKBENCH:查看安装指引`)),1)])),D(`button`,{type:`button`,class:`wb-logs-inline-btn wb-logs-inline-btn--danger`,title:l.$t(`@WORKBENCH:清空当前任务的所有执行内容`),"aria-label":l.$t(`@WORKBENCH:清空当前任务的所有执行内容`),onClick:s[4]||=(...e)=>l.clearExecutionForSelectedTask&&l.clearExecutionForSelectedTask(...e)},[_(m,{class:`wb-logs-inline-btn__icon`},{default:W(()=>[_(l.Delete)]),_:1}),D(`span`,null,e(l.$t(`@WORKBENCH:清空执行`)),1)],8,ml),D(`button`,{type:`button`,class:`wb-logs-inline-btn`,title:l.$t(`@WORKBENCH:执行日志`),"aria-label":l.$t(`@WORKBENCH:执行日志`),onClick:s[5]||=e=>l.logsDialogVisible=!0},[_(m,{class:`wb-logs-inline-btn__icon`},{default:W(()=>[_(l.Document)]),_:1}),D(`span`,null,e(l.$t(`@WORKBENCH:执行日志`)),1)],8,hl)]),r(` 任务描述区域:默认折叠,节省首屏空间;展开后可编辑/上传附件 `),D(`details`,{class:`wb-task-desc`,open:l.taskDescExpanded,onToggle:s[17]||=e=>l.taskDescExpanded=e.target.open},[D(`summary`,_l,[_(m,{class:`wb-task-desc__caret`},{default:W(()=>[(M(),a(ye(l.taskDescExpanded?l.ArrowDown:l.ArrowRight)))]),_:1}),D(`span`,vl,e(l.$t(`@WORKBENCH:任务描述(可选)`)),1),D(`button`,{type:`button`,class:U([`wb-copy-btn wb-copy-btn--inline`,{"is-flash":l.copyDescFlashId===l.selectedTask.id}]),title:l.selectedTask.desc&&l.selectedTask.desc.trim()?l.$t(`@WORKBENCH:复制任务描述`):l.$t(`@WORKBENCH:任务描述为空,无需复制`),"aria-label":l.$t(`@WORKBENCH:复制任务描述`),onClick:s[6]||=J(e=>l.copyTaskDesc(l.selectedTask),[`stop`,`prevent`])},[l.copyDescFlashId===l.selectedTask.id?(M(),a(m,{key:1,class:`wb-copy-btn__icon wb-copy-btn__icon--check`},{default:W(()=>[...s[32]||=[g(`✓`,-1)]]),_:1})):(M(),a(m,{key:0,class:`wb-copy-btn__icon`},{default:W(()=>[_(l.CopyDocument)]),_:1}))],10,yl),l.selectedTask.desc&&l.selectedTask.desc.length>0||l.selectedTask.attachments&&l.selectedTask.attachments.length>0?(M(),v(`span`,bl,[l.selectedTask.desc&&l.selectedTask.desc.length>0?(M(),v(`span`,xl,e(l.$t(`@WORKBENCH:已填写`)),1)):r(`v-if`,!0),l.selectedTask.attachments&&l.selectedTask.attachments.length>0?(M(),v(`span`,Sl,e(l.selectedTask.attachments.length),1)):r(`v-if`,!0)])):r(`v-if`,!0)]),z(D(`textarea`,{ref:`taskDescTextareaRef`,class:`wb-textarea wb-textarea--autogrow`,"onUpdate:modelValue":s[7]||=e=>l.selectedTask.desc=e,placeholder:l.$t(`@WORKBENCH:任务描述(可选)`),onInput:s[8]||=e=>l.autoGrowTextarea(e),onFocus:s[9]||=e=>l.autoGrowTextarea(e),onBlur:s[10]||=e=>l.autoGrowTextarea(e),onPaste:s[11]||=e=>l.onAttachmentPaste(e,{kind:`task`,task:l.selectedTask})},null,40,Cl),[[V,l.selectedTask.desc]]),_(l.AttachmentZone,{attachments:l.selectedTask.attachments||[],"is-image":l.isImageAttachment,"human-size":l.humanSize,"is-uploading":l.isUploading(`task-`+l.selectedTask.id),"is-paste-hover":l.pasteHoverId===`task-`+l.selectedTask.id,"max-count":9,"on-pick":()=>l.pickAttachmentFile({kind:`task`,task:l.selectedTask}),"on-remove":e=>l.removeAttachment({kind:`task`,task:l.selectedTask},e),onPaste:s[12]||=e=>l.onAttachmentPaste(e,{kind:`task`,task:l.selectedTask}),onDrop:s[13]||=J(e=>l.onAttachmentDrop(e,{kind:`task`,task:l.selectedTask}),[`prevent`]),onDragover:s[14]||=J(e=>l.pasteHoverId=`task-`+l.selectedTask.id,[`prevent`]),onDragenter:s[15]||=J(e=>l.pasteHoverId=`task-`+l.selectedTask.id,[`prevent`]),onDragleave:s[16]||=e=>l.pasteHoverId=l.pasteHoverId===`task-`+l.selectedTask.id?null:l.pasteHoverId},null,8,[`attachments`,`is-image`,`human-size`,`is-uploading`,`is-paste-hover`,`on-pick`,`on-remove`])],40,gl),r(` ── 执行主体:一条任务 = 一次会话,详情面板占满整行 ── `),D(`div`,wl,[r(` 详情面板(执行内容区) `),D(`div`,Tl,[r(` ⚠️ 这一层**不要**用裸 <template> 包起来(踩过,2026-09-22):
47
- Vue 3 只把带 v-if / v-else / v-for / v-slot 的 <template> 编译成片段,
48
- 裸 <template> 会被当成真的 <template> 元素渲染 —— 浏览器把子节点全塞进
49
- template.content(inert DocumentFragment),不产生任何布局盒。
50
- 症状:任务在跑、看板「执行中」、执行监控有 PID,但对话区一片空白,
51
- 而 innerText 里明明有内容(元素 0×0)。重构移除子任务概念时留下的空壳。 `),D(`details`,{class:U([`wb-simple__override`,{"has-content":!!(l.selectedTask.simpleOverride&&l.selectedTask.simpleOverride.trim())}])},[D(`summary`,El,[_(m,{class:`wb-simple__override-caret`},{default:W(()=>[_(l.ArrowRight)]),_:1}),D(`span`,null,e(l.$t(`@WORKBENCH:覆盖预置提示词(可选)`)),1),l.selectedTask.simpleOverride&&l.selectedTask.simpleOverride.trim()?(M(),v(`span`,{key:0,class:`wb-simple__override-tag`,title:l.$t(`@WORKBENCH:已填写覆盖内容`)},e(l.$t(`@WORKBENCH:已填写`)),9,Dl)):r(`v-if`,!0),l.simpleJobState(l.simpleJobFor(l.selectedTask))===`running`&&l.simpleJobFor(l.selectedTask)?(M(),v(`button`,{key:1,class:`wb-simple__stop`,onClick:s[18]||=J(e=>l.cancelJob(l.simpleJobFor(l.selectedTask)),[`stop`])},e(l.$t(`@WORKBENCH:停止`)),1)):r(`v-if`,!0)]),z(D(`textarea`,{class:`wb-textarea`,"onUpdate:modelValue":s[19]||=e=>l.selectedTask.simpleOverride=e,placeholder:l.$t(`@WORKBENCH:留空则使用上方选定的「预置提示词」模板;可用变量:{{task.title}} {{task.desc}} {{repo.path}} {{branch}}`),rows:`6`},null,8,Ol),[[V,l.selectedTask.simpleOverride]])],2),r(` 任务对话流:所有轮次合并到单个 ChatContainer `),l.simpleAllJobsFor(l.selectedTask).length>0?(M(),v(`div`,kl,[(M(),a(l.ChatContainer,{key:l.selectedTask.id,messages:l.simpleConversationMessages,"assistant-name":l.simpleAssistantLabel,"assistant-avatar":l.simpleAssistantAvatar,"show-avatar":!0,theme:l.configStore.theme,"tool-calls-config":{group:!0,collapseThreshold:2},class:`wb-simple-chat`},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`])),r(` 终态控件 `),l.simpleJobFor(l.selectedTask)&&[`done`,`error`,`cancelled`].includes(l.simpleJobState(l.simpleJobFor(l.selectedTask)))?(M(),v(`div`,Al,[(M(),a(l.ChatInput,{key:`input-`+l.selectedTask.id,placeholder:l.$t(`@WORKBENCH:输入后续问题继续对话…(Ctrl+Enter 发送)`),"upload-config":{enabled:!0,accept:l.ALLOWED_EXT_HINT,multiple:!0,maxCount:Math.max(0,9-(l.selectedTask.attachments?.length??0)),maxSize:l.MAX_ATTACHMENT_BYTES},class:`wb-simple-chat__input`,onSend:s[20]||=e=>l.onContinueSendFromChat(l.selectedTask,e)},null,8,[`placeholder`,`upload-config`]))])):r(`v-if`,!0)])):r(`v-if`,!0)])])],64)):(M(),v(`div`,Yc,[D(`p`,null,e(l.$t(`@WORKBENCH:左侧选择任务,或新建一个任务开始`)),1)]))])])])]),_:1},8,[`modelValue`,`title`]),r(` 执行日志管理:弹窗形式承载,原本独立 tab 切换会占用首屏。
52
-
53
- ⚠️ 必须 append-to-body。app shell 的 main.main-container 是 position:fixed + z-index:1001,
54
- 它自成一个层叠上下文:留在这里面的弹窗 z-index 再高,也只是跟"同一个上下文里的兄弟"比,
55
- 永远压不过挂在 body 下的 L2 编辑器弹窗(它 escape 了 1001 那层)。
56
- 现象就是点了「执行日志」没反应 —— 其实弹窗开了,只是被编辑器整个盖住。 `),_(C,{modelValue:l.logsDialogVisible,"onUpdate:modelValue":s[22]||=e=>l.logsDialogVisible=e,title:l.$t(`@WORKBENCH:执行日志`),width:`1080px`,"close-on-click-modal":!1,top:`6vh`,class:`wb-logs-dialog`,"append-to-body":``},{default:W(()=>[_(l.ExecutionLogManager)]),_:1},8,[`modelValue`,`title`]),r(` 提示词编辑对话框:同「执行日志」,从编辑器里打开,必须 append-to-body 才压得住编辑器弹窗 `),_(C,{modelValue:l.promptDialog.visible,"onUpdate:modelValue":s[27]||=e=>l.promptDialog.visible=e,title:l.promptDialog.editing?l.$t(`@WORKBENCH:编辑提示词`):l.$t(`@WORKBENCH:新建提示词`),width:`640px`,"append-to-body":``},{footer:W(()=>[_(A,{onClick:s[26]||=e=>l.promptDialog.visible=!1},{default:W(()=>[g(e(l.$t(`@WORKBENCH:取消`)),1)]),_:1}),_(A,{type:`primary`,onClick:l.savePrompt},{default:W(()=>[g(e(l.$t(`@WORKBENCH:保存`)),1)]),_:1})]),default:W(()=>[_(ne,{"label-position":`top`},{default:W(()=>[_(E,{label:l.$t(`@WORKBENCH:名称`)},{default:W(()=>[_(T,{modelValue:l.promptDialog.name,"onUpdate:modelValue":s[23]||=e=>l.promptDialog.name=e,placeholder:l.$t(`@WORKBENCH:如:代码审查 / 写测试`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`]),_(E,{label:l.$t(`@WORKBENCH:所属项目`)},{default:W(()=>[_(k,{modelValue:l.promptDialog.projectPath,"onUpdate:modelValue":s[24]||=e=>l.promptDialog.projectPath=e,placeholder:l.$t(`@WORKBENCH:所属项目`),style:{width:`100%`},disabled:!l.currentProject.path},{default:W(()=>[r(` 「全局」选项 = projectPath 为空串,所有项目都能看到 `),_(O,{label:l.$t(`@WORKBENCH:全局(所有项目可用)`),value:``},null,8,[`label`]),r(` 仅当有当前项目时才允许绑定到当前项目,避免“绑到空项目”的兑犷数据 `),l.currentProject.path?(M(),a(O,{key:l.currentProject.path,label:l.currentProject.name||l.currentProject.path,value:l.currentProject.path},null,8,[`label`,`value`])):r(`v-if`,!0)]),_:1},8,[`modelValue`,`placeholder`,`disabled`])]),_:1},8,[`label`]),_(E,null,{default:W(()=>[D(`div`,jl,[_(A,{type:`primary`,plain:``,loading:l.promptDialog.aiLoading,onClick:l.aiGeneratePrompt},{default:W(()=>[g(e(l.$t(`@WORKBENCH:AI 生成项目架构说明`)),1)]),_:1},8,[`loading`]),_(A,{onClick:l.openEditInstruction},{default:W(()=>[g(e(l.$t(`@WORKBENCH:编辑指令`)),1)]),_:1})])]),_:1}),_(E,{label:l.$t(`@WORKBENCH:内容`)},{default:W(()=>[_(T,{modelValue:l.promptDialog.content,"onUpdate:modelValue":s[25]||=e=>l.promptDialog.content=e,type:`textarea`,rows:10,placeholder:l.$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`]),r(` 生成指令编辑对话框 `),_(C,{modelValue:l.instructionDialog.visible,"onUpdate:modelValue":s[30]||=e=>l.instructionDialog.visible=e,title:l.$t(`@WORKBENCH:编辑生成指令`),width:`720px`,"append-to-body":``},{footer:W(()=>[_(A,{onClick:s[29]||=e=>l.instructionDialog.visible=!1},{default:W(()=>[g(e(l.$t(`@WORKBENCH:取消`)),1)]),_:1}),_(A,{type:`primary`,loading:l.instructionDialog.saving,onClick:l.saveInstruction},{default:W(()=>[g(e(l.$t(`@WORKBENCH:保存`)),1)]),_:1},8,[`loading`])]),default:W(()=>[_(ne,{"label-position":`top`},{default:W(()=>[_(E,{label:l.$t(`@WORKBENCH:指令内容`)},{default:W(()=>[_(T,{modelValue:l.instructionDialog.text,"onUpdate:modelValue":s[28]||=e=>l.instructionDialog.text=e,type:`textarea`,rows:18,placeholder:l.$t(`@WORKBENCH:指令内容`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])]),_:1})]),_:1},8,[`modelValue`,`title`])])}var Nl=Q(Rc,[[`render`,Ml],[`__scopeId`,`data-v-28f2e82b`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/WorkbenchView.vue`]]);export{Nl as default};