@runfusion/fusion 0.55.0 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +5785 -1351
- package/dist/client/.vite/manifest.json +321 -321
- package/dist/client/assets/{AgentDetailView-B_VfFSlt.js → AgentDetailView-BPzzEIn1.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-QZhz41AU.js → AgentPermissionPolicyEditor-CqlLF0pf.js} +1 -1
- package/dist/client/assets/{AgentsView-hkhJ8SUq.js → AgentsView-C4uCWzdt.js} +6 -6
- package/dist/client/assets/ChatView-BGV9F2K0.js +6 -0
- package/dist/client/assets/{CommandCenter-B3fAajUO.js → CommandCenter-BhIfVVjz.js} +1 -1
- package/dist/client/assets/{DevServerView-BR0ngFBw.js → DevServerView-Bd86MWUa.js} +1 -1
- package/dist/client/assets/DirectoryPicker-BDe9G84f.js +1 -0
- package/dist/client/assets/{DocumentsView-BnRvIUpa.js → DocumentsView-BkAHMt19.js} +1 -1
- package/dist/client/assets/{EvalsView-Bvx18QyC.js → EvalsView-BxxCVaJ8.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-CKGJcfXI.js → ExperimentalAgentOnboardingModal-7-BD6W1v.js} +1 -1
- package/dist/client/assets/{GoalsView-Bj1yVIiv.js → GoalsView-B3KICwNu.js} +1 -1
- package/dist/client/assets/{InsightsView-DBX8DI60.js → InsightsView-DO8qefU1.js} +2 -2
- package/dist/client/assets/{MemoryView-CqkRH2fa.js → MemoryView-urkPdqTn.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-BMMmGWe2.js → PiExtensionsManager-BwVKjJIo.js} +2 -2
- package/dist/client/assets/{PluginManager-C1bdfN2W.js → PluginManager-C-OuqDLa.js} +1 -1
- package/dist/client/assets/{PullRequestView-D0CsXWLl.js → PullRequestView-B4q4X5WV.js} +1 -1
- package/dist/client/assets/{ResearchView-CVgmXAlj.js → ResearchView-DlW6z3sm.js} +1 -1
- package/dist/client/assets/{SecretsView-Bv_gw5Ix.js → SecretsView-C-3eC0KB.js} +1 -1
- package/dist/client/assets/SessionTerminal-DVfyVeS2.js +2 -0
- package/dist/client/assets/SettingsModal-BC_2Y56_.css +1 -0
- package/dist/client/assets/{SettingsModal-D7YgojbV.js → SettingsModal-BzXctrhu.js} +1 -1
- package/dist/client/assets/SettingsModal-qs8w3rov.js +21 -0
- package/dist/client/assets/SetupWizardModal-DDJ8PCkH.js +2 -0
- package/dist/client/assets/{ShadcnColorPicker-DM2fqGwl.js → ShadcnColorPicker-BcD5fZ_P.js} +1 -1
- package/dist/client/assets/{SkillsView-Bb-JTo99.js → SkillsView-DojlvxFh.js} +1 -1
- package/dist/client/assets/TodoView-BKZ07WxZ.js +6 -0
- package/dist/client/assets/WorkflowNodeEditor-BJNbi4_V.js +8 -0
- package/dist/client/assets/{agentSkills-DGFyuKuP.js → agentSkills-NbIIJy87.js} +1 -1
- package/dist/client/assets/app-0jcSCRQr.js +13 -0
- package/dist/client/assets/app-BPzPEE6G.js +13 -0
- package/dist/client/assets/app-BSZU5Uns.js +13 -0
- package/dist/client/assets/app-CEtD1B9K.js +13 -0
- package/dist/client/assets/app-CVyRSEUX.js +13 -0
- package/dist/client/assets/app-DoLz_4Dg.js +13 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DP7vOyXY.js → architectureDiagram-3BPJPVTR-CJu9RVXs.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-Di9v1pV8.js → blockDiagram-GPEHLZMM-crZsLLTq.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-Dvb8RSfr.js → c4Diagram-AAUBKEIU-D5mmJKvW.js} +1 -1
- package/dist/client/assets/channel-Zfk0yRN2.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-gLcAuGjI.js → chunk-2J33WTMH-BZIDltTX.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-B-B0wjkx.js → chunk-4BX2VUAB-ND_SzhUa.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-XUDeC0Co.js → chunk-55IACEB6-C3n-Nisk.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-1eebiGA2.js → chunk-727SXJPM-DfiPA7wv.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-D9VOB5QS.js → chunk-AQP2D5EJ-CDE0u57Z.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-EFNFEaAz.js → chunk-FMBD7UC4-COR53PTE.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-CbeQailD.js → chunk-ND2GUHAM-CbcTdl7C.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-D55N6EBz.js → chunk-QZHKN3VN-DiB3PReK.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BehQ-wnv.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BehQ-wnv.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-B0zbhkX3.js → cose-bilkent-S5V4N54A-Dg3YVyLX.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-BL6peXwl.js → dagre-BM42HDAG-D2bK3gNb.js} +1 -1
- package/dist/client/assets/{dashboard-view-CS1H5SQN.js → dashboard-view-BcbTWSCe.js} +1 -1
- package/dist/client/assets/{dashboard-view-Db3n_W85.js → dashboard-view-t2UfQxck.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-cYKwSHk7.js → diagram-2AECGRRQ-BWT8KaEl.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-DHIwTGuM.js → diagram-5GNKFQAL-DWfJlASD.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-DfHBJ4aX.js → diagram-KO2AKTUF-DE3hFbLT.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-pWhYmB6Z.js → diagram-LMA3HP47-CYCFeD4B.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-GzWqbi_m.js → diagram-OG6HWLK6-C0C8lEGv.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-CCVm5eiR.js → erDiagram-TEJ5UH35-kSo7RjKA.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-CUTdnU6S.js → flowDiagram-I6XJVG4X-DxRf1SVH.js} +1 -1
- package/dist/client/assets/{folder-open-DOCy9GVC.js → folder-open-DO1rnCxq.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CW4ENJaC.js → ganttDiagram-6RSMTGT7-CGtxSeWq.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-QXXMfSzp.js → gitGraphDiagram-PVQCEYII-BNZv_DFY.js} +1 -1
- package/dist/client/assets/index-BCf32Sgx.css +1 -0
- package/dist/client/assets/index-D7eX7QJk.js +2511 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-CZyHbj0n.js → infoDiagram-5YYISTIA-DailohMo.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-Dea84lqZ.js → ishikawaDiagram-YF4QCWOH-Cy3shDZP.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-Db2iKGU5.js → journeyDiagram-JHISSGLW-B1rU18Qx.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-CB9loIqR.js → kanban-definition-UN3LZRKU-CRNUDgkO.js} +1 -1
- package/dist/client/assets/{mermaid.core-CoQ8aCb0.js → mermaid.core-Cg0po76i.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-JPb2wF-K.js → mindmap-definition-RKZ34NQL-CEjwlhOe.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-pdZzOreP.js → pieDiagram-4H26LBE5-70T-php2.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Dh9Ids90.js → quadrantDiagram-W4KKPZXB-ChcpRG7l.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-BVPOSvHU.js → requirementDiagram-4Y6WPE33-9Pzb_Cot.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BqSMUpsx.js → sankeyDiagram-5OEKKPKP-Bx6DkeKq.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-B8nepQ6X.js → sequenceDiagram-3UESZ5HK-emWPkPv7.js} +1 -1
- package/dist/client/assets/{shield-alert-CtSaIQNY.js → shield-alert-BdAjnDkU.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CQv9RdRp.js → stateDiagram-AJRCARHV-B_X2-VQy.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DvQssSEq.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CAjwM-Z5.js → timeline-definition-PNZ67QCA-CkyhunuI.js} +1 -1
- package/dist/client/assets/{upload-0_pT1euA.js → upload-D9-yuO2D.js} +1 -1
- package/dist/client/assets/{users--1B6mnm8.js → users-B4aebngl.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-BO3Um3rH.js → vennDiagram-CIIHVFJN-8OGD6Vb7.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-BzqJcqDA.js → wardley-L42UT6IY-MnRFGNPm.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Bctxc6_5.js → wardleyDiagram-YWT4CUSO-BAEzb08c.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-CgDuiMFR.js → xychartDiagram-2RQKCTM6-DUxideKC.js} +1 -1
- package/dist/client/index.html +3 -3
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +4668 -913
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.d.ts +47 -3
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/ChatView-B4WnXLYA.js +0 -6
- package/dist/client/assets/DirectoryPicker-BiS41Hca.js +0 -1
- package/dist/client/assets/SessionTerminal-VLdVV3Ji.js +0 -2
- package/dist/client/assets/SettingsModal-4t8rV7rh.css +0 -1
- package/dist/client/assets/SettingsModal-gcrh5EOG.js +0 -21
- package/dist/client/assets/SetupWizardModal-DvmTlFP_.js +0 -2
- package/dist/client/assets/TodoView-bV-7deOh.js +0 -6
- package/dist/client/assets/WorkflowNodeEditor-Ui1q_fFI.js +0 -8
- package/dist/client/assets/app--OM-ul6R.js +0 -13
- package/dist/client/assets/app-BCvqf8qq.js +0 -13
- package/dist/client/assets/app-BZqqEiWR.js +0 -13
- package/dist/client/assets/app-DQeH1UDD.js +0 -13
- package/dist/client/assets/app-FiYwRatp.js +0 -13
- package/dist/client/assets/app-rGdYcsAA.js +0 -13
- package/dist/client/assets/channel-C5g9M3Sk.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-B-wdlvD6.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B-wdlvD6.js +0 -1
- package/dist/client/assets/index-B6ttSchA.js +0 -1336
- package/dist/client/assets/index-CPE2Kwra.css +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-BZ_mlvie.js +0 -1
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ExperimentalAgentOnboardingModal-CKGJcfXI.js","assets/vendor-react-SZ_qB27O.js","assets/index-B6ttSchA.js","assets/vendor-i18n-GF3RlKbq.js","assets/vendor-reactflow-CnI7NMXG.js","assets/vendor-reactflow-C5ap-Sga.css","assets/vendor-xterm-BNq00GSj.js","assets/vendor-xterm-LZoznX6r.css","assets/vendor-codemirror-jBKmHyH0.js","assets/index-CPE2Kwra.css","assets/ExperimentalAgentOnboardingModal-3ZEFv8sr.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{A as h,g as v,m as E,u as ie,d as ne,r as oe,a as le,b as de,e as ce,X as pe,L as C,C as ue,f as F,S as me,h as T,E as ge,_ as he}from"./index-B6ttSchA.js";import{r as o,j as e}from"./vendor-react-SZ_qB27O.js";import{D as xe}from"./DirectoryPicker-BiS41Hca.js";import{s as z}from"./projectDetection-G3XuxD2X.js";import{u as je}from"./vendor-i18n-GF3RlKbq.js";import"./vendor-reactflow-CnI7NMXG.js";import"./vendor-xterm-BNq00GSj.js";import"./vendor-codemirror-jBKmHyH0.js";import"./folder-open-DOCy9GVC.js";function P(p){const u=p.replace(/[^a-zA-Z]/g,"").toUpperCase();return u.length>=2&&u.length<=4?u:u.length>4?u.slice(0,4):"FN"}const fe=o.lazy(()=>he(()=>import("./ExperimentalAgentOnboardingModal-CKGJcfXI.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])).then(p=>({default:p.ExperimentalAgentOnboardingModal})));function Ie({onProjectRegistered:p,onClose:u,agentOnboardingEnabled:I=!1,includeAgentStep:A=!0}){const{t:s}=je("app"),U="https://discord.gg/ksrfuy7WYR",f=o.useMemo(()=>v("ceo")??h[0],[]),[W,H]=o.useState(!0),[t,n]=o.useState(()=>({step:"manual",manualMode:"existing",manualPath:"",manualCloneUrl:"",manualName:"",manualIsolationMode:"in-process",manualNodeId:"",manualTaskPrefix:"",detectedRepos:[],workspaceMode:!1,isDetectingWorkspace:!1,registeredProject:null,selectedPresetId:f.id,agentDraft:E(f),isCreatingAgent:!1,isRegistering:!1,error:null,agentError:null,agentOutcome:null})),[R,L]=o.useState(!1),[D,w]=o.useState(!1),M=o.useRef(null),{nodes:S,loading:O}=ie(),_=S.find(a=>a.type==="local")?.id,N=o.useCallback(()=>{H(!1),u?.()},[u]),B=o.useCallback(()=>{if(t.registeredProject){p(t.registeredProject);return}N()},[N,p,t.registeredProject]);o.useEffect(()=>{t.agentError&&M.current?.focus()},[t.agentError]);const x=o.useRef(0),G=o.useCallback(a=>{if(n(r=>{const i={manualPath:a,detectedRepos:[],workspaceMode:!1};a&&(!r.manualName||r.manualName===z(r.manualPath))&&(i.manualName=z(a));const l=i.manualName??r.manualName;return l&&(!r.manualTaskPrefix||r.manualTaskPrefix===P(z(r.manualPath)))&&(i.manualTaskPrefix=P(l)),{...r,...i}}),t.manualMode==="existing"&&a.trim()&&a.trim()!=="/"){const r=++x.current;n(i=>({...i,isDetectingWorkspace:!0})),ne(a.trim()).then(i=>{r===x.current&&n(l=>({...l,isDetectingWorkspace:!1,detectedRepos:i.repos,workspaceMode:i.isWorkspace}))}).catch(()=>{r===x.current&&n(i=>({...i,isDetectingWorkspace:!1}))})}},[t.manualMode]),y=o.useCallback(a=>{n(r=>({...r,manualMode:a,manualCloneUrl:a==="clone"?r.manualCloneUrl:"",detectedRepos:a==="existing"?r.detectedRepos:[],workspaceMode:a==="existing"?r.workspaceMode:!1,isDetectingWorkspace:!1,error:null})),x.current+=1},[]),$=o.useCallback(async()=>{const a=t.manualPath.trim(),r=t.manualName.trim(),i=t.manualCloneUrl.trim();if(!(!a||!r)&&!(t.manualMode==="clone"&&!i)){n(l=>({...l,isRegistering:!0,error:null}));try{const l={name:r,path:a,isolationMode:t.manualIsolationMode,nodeId:t.manualNodeId||void 0,gitSetupMode:t.manualMode,cloneUrl:t.manualMode==="clone"?i:void 0,workspaceMode:t.manualMode==="existing"?t.workspaceMode:!1,taskPrefix:t.manualTaskPrefix.trim()||void 0},d=await oe(l);if(!A){n(g=>({...g,isRegistering:!1})),p(d);return}n(g=>({...g,step:"agent",registeredProject:d,isRegistering:!1}))}catch(l){n(d=>({...d,isRegistering:!1,error:l instanceof Error?l.message:"Failed to register project"}))}}},[A,p,t.manualPath,t.manualName,t.manualCloneUrl,t.manualMode,t.manualIsolationMode,t.manualNodeId,t.workspaceMode,t.manualTaskPrefix]),b=o.useCallback(a=>{const r=v(a);r&&n(i=>({...i,selectedPresetId:r.id,agentDraft:E(r),agentError:null}))},[]),Y=o.useCallback((a,r)=>{const i=h.findIndex(re=>re.id===r);if(i<0)return;const l=h.length-1;let d=null;if(a.key==="ArrowDown"||a.key==="ArrowRight"?d=i===l?0:i+1:a.key==="ArrowUp"||a.key==="ArrowLeft"?d=i===0?l:i-1:a.key==="Home"?d=0:a.key==="End"&&(d=l),d===null)return;a.preventDefault();const g=h[d];b(g.id),requestAnimationFrame(()=>{document.querySelector(`[data-agent-preset-id="${g.id}"]`)?.focus()})},[b]),q=o.useCallback(a=>{n(r=>({...r,selectedPresetId:"",agentDraft:le(a),agentError:null}))},[]),K=o.useCallback(async()=>{if(!(!t.registeredProject||!t.agentDraft.name.trim())){n(a=>({...a,isCreatingAgent:!0,agentError:null}));try{await de(ce(t.agentDraft),t.registeredProject.id),n(a=>({...a,step:"complete",isCreatingAgent:!1,agentOutcome:"created"}))}catch(a){if(a instanceof Error&&/already exists/i.test(a.message)){n(r=>({...r,step:"complete",isCreatingAgent:!1,agentOutcome:"created"}));return}n(r=>({...r,isCreatingAgent:!1,agentError:a instanceof Error?a.message:s("setup.firstAgentCreateError","Failed to create agent")}))}}},[t.agentDraft,t.registeredProject,s]),Z=o.useCallback(()=>{n(a=>({...a,step:"complete",agentError:null,agentOutcome:"skipped"}))},[]);if(!W)return null;const k=t.manualMode==="existing",m=t.manualMode==="init",c=t.manualMode==="clone",V=c?s("setup.cloneAndRegisterProject","Clone and Register Project"):m?s("setup.initializeAndRegisterProject","Initialize and Register Project"):s("setup.registerProject","Register Project"),X=t.manualPath.trim().length>0,J=t.manualName.trim().length>0,Q=t.manualCloneUrl.trim().length>0,ee=t.isRegistering||!X||!J||c&&!Q,te=t.selectedPresetId?v(t.selectedPresetId):void 0,j=t.isCreatingAgent,se=t.selectedPresetId||f.id,ae=`modal setup-wizard-modal${t.step==="agent"?" setup-wizard-modal--agent":""}`;return e.jsxs("div",{className:"modal-overlay open setup-wizard-overlay",role:"dialog","aria-modal":"true","aria-labelledby":"wizard-title",children:[e.jsxs("div",{className:ae,children:[e.jsxs("div",{className:"setup-wizard-header",children:[e.jsxs("div",{className:"setup-wizard-heading",children:[e.jsxs("div",{className:"setup-wizard-brand","aria-label":s("setup.brandName","Fusion"),children:[e.jsxs("svg",{className:"setup-wizard-brand-logo",width:28,height:28,viewBox:"0 0 128 128",fill:"none","aria-label":s("setup.brandLogo","Fusion logo"),role:"img",children:[e.jsx("circle",{cx:"64",cy:"64",r:"52",stroke:"currentColor",strokeWidth:"8"}),e.jsx("path",{d:"M26 101C44 82 62 64 82 45C90 37 98 30 104 24C96 35 89 47 81 60C70 79 57 95 43 108C38 112 32 108 26 101Z",fill:"currentColor"})]}),e.jsx("span",{className:"setup-wizard-brand-name",children:s("setup.brandName","Fusion")})]}),e.jsxs("h2",{id:"wizard-title",className:"setup-wizard-title",children:[t.step==="manual"&&s("setup.welcomeToFusion","Welcome to Fusion"),t.step==="agent"&&s("setup.firstAgentTitle","Create your first agent"),t.step==="complete"&&s("setup.setupCompleteTitle","Setup Complete!")]})]}),t.step!=="complete"&&t.step!=="agent"&&e.jsx("button",{className:"modal-close",onClick:N,"aria-label":s("setup.closeWizard","Close wizard"),children:e.jsx(pe,{size:20})})]}),e.jsxs("div",{className:"setup-wizard-content",children:[t.step==="manual"&&e.jsxs("div",{className:"setup-wizard-manual",children:[e.jsxs("section",{className:"setup-wizard-repository-section","aria-labelledby":"setup-repository-mode-title",children:[e.jsxs("div",{className:"setup-wizard-section-heading",children:[e.jsx("h3",{id:"setup-repository-mode-title",children:s("setup.repositorySetupTitle","Repository setup")}),e.jsx("p",{children:s("setup.repositorySetupDescription","Choose how Fusion should prepare the project directory before registration.")})]}),e.jsxs("fieldset",{className:"setup-wizard-mode-switch","aria-label":s("setup.projectSetupModeAriaLabel","Project setup mode"),children:[e.jsx("legend",{children:s("setup.setupMode","Setup Mode")}),e.jsxs("label",{className:`setup-wizard-mode-option${k?" selected":""}`,children:[e.jsx("input",{type:"radio",name:"setup-mode",value:"existing","aria-label":s("setup.useExistingDirectory","Use Existing Directory"),checked:k,onChange:()=>y("existing")}),e.jsxs("span",{className:"setup-wizard-mode-option-copy",children:[e.jsx("strong",{children:s("setup.useExistingDirectory","Use Existing Directory")}),e.jsx("span",{children:s("setup.useExistingDirectoryHint","Register a folder that is already a git repository or workspace root.")})]})]}),e.jsxs("label",{className:`setup-wizard-mode-option${m?" selected":""}`,children:[e.jsx("input",{type:"radio",name:"setup-mode",value:"init","aria-label":s("setup.initializeNewRepository","Initialize New Repository"),checked:m,onChange:()=>y("init")}),e.jsxs("span",{className:"setup-wizard-mode-option-copy",children:[e.jsx("strong",{children:s("setup.initializeNewRepository","Initialize New Repository")}),e.jsx("span",{children:s("setup.initializeNewRepositoryHint","Register a selected non-git folder and let Fusion run git init on the server.")})]})]}),e.jsxs("label",{className:`setup-wizard-mode-option${c?" selected":""}`,children:[e.jsx("input",{type:"radio",name:"setup-mode",value:"clone","aria-label":s("setup.cloneGitRepository","Clone Git Repository"),checked:c,onChange:()=>y("clone")}),e.jsxs("span",{className:"setup-wizard-mode-option-copy",children:[e.jsx("strong",{children:s("setup.cloneGitRepository","Clone Git Repository")}),e.jsx("span",{children:s("setup.cloneGitRepositoryHint","Clone a remote repository into an empty or absent destination folder.")})]})]})]})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"project-path",children:c?s("setup.destinationDirectory","Destination Directory"):m?s("setup.newRepositoryDirectory","New Repository Directory"):s("setup.projectDirectory","Project Directory")}),e.jsx(xe,{value:t.manualPath,onChange:G,nodeId:t.manualNodeId||void 0,localNodeId:_,placeholder:c?s("setup.clonePathPlaceholder","/path/for/new-clone"):m?s("setup.initPathPlaceholder","/path/to/new-project"):s("setup.projectPathPlaceholder","/path/to/your/project")}),e.jsx("p",{className:"form-hint",children:c?s("setup.clonePathHint","Select or type an absolute destination path. Fusion will clone into this directory. The destination must be empty or absent."):m?s("setup.initPathHint","Select or type an absolute path to an empty or non-git folder. Fusion will run git init during registration."):s("setup.projectPathHint","Select or type the absolute path to an existing git repository or workspace root.")})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"project-name",children:s("setup.projectName","Project Name")}),e.jsx("input",{id:"project-name",type:"text",value:t.manualName,onChange:a=>n(r=>({...r,manualName:a.target.value})),placeholder:s("setup.projectNamePlaceholder","my-project")}),e.jsx("p",{className:"form-hint",children:c?s("setup.projectNameHintClone","By default this follows the destination folder name unless you edit it."):m?s("setup.projectNameHintInit","By default this follows the folder name Fusion will initialize unless you edit it."):s("setup.projectNameHintExisting","By default this follows the selected directory name unless you edit it.")})]}),c&&e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"project-clone-url",children:s("setup.repositoryUrl","Repository URL")}),e.jsx("input",{id:"project-clone-url",type:"text",value:t.manualCloneUrl,onChange:a=>n(r=>({...r,manualCloneUrl:a.target.value,error:null})),placeholder:s("setup.repositoryUrlPlaceholder","https://github.com/owner/repo.git")}),e.jsx("p",{className:"form-hint",children:s("setup.cloneGitHint","Fusion will run git clone into the destination directory, then register that cloned folder.")})]}),k&&t.manualPath.trim()&&e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{htmlFor:"workspace-mode",className:"checkbox-label",children:[e.jsx("input",{id:"workspace-mode",type:"checkbox",checked:t.workspaceMode,onChange:a=>n(r=>({...r,workspaceMode:a.target.checked}))}),s("setup.workspaceMode","Workspace mode (multi-repo)")]}),t.isDetectingWorkspace&&e.jsxs("p",{className:"form-hint",children:[e.jsx(C,{size:12,className:"animate-spin setup-wizard-inline-spinner"}),s("setup.detectingWorkspace","Detecting sub-repositories...")]}),!t.isDetectingWorkspace&&t.detectedRepos.length>0&&e.jsxs("p",{className:"form-hint",children:[s("setup.detectedRepos","Found {{count}} repositories:",{count:t.detectedRepos.length})," ",t.detectedRepos.join(", ")]}),!t.isDetectingWorkspace&&t.detectedRepos.length===0&&t.workspaceMode===!1&&t.manualPath.trim()&&e.jsx("p",{className:"form-hint",children:s("setup.noSubReposDetected","No sub-repositories detected. Enable if this is a multi-repo workspace.")})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"task-prefix",children:s("setup.taskPrefix","Task Prefix")}),e.jsx("input",{id:"task-prefix",type:"text",value:t.manualTaskPrefix,onChange:a=>n(r=>({...r,manualTaskPrefix:a.target.value.toUpperCase()})),placeholder:P(t.manualName||"FN"),maxLength:5}),e.jsx("p",{className:"form-hint",children:s("setup.taskPrefixHint",'Used for task IDs (e.g. "{{prefix}}-1"). Derived from project name.',{prefix:t.manualTaskPrefix||"FN"})})]}),e.jsxs("div",{className:"setup-wizard-advanced",children:[e.jsxs("button",{type:"button",className:"setup-wizard-advanced-toggle","aria-expanded":R,onClick:()=>L(a=>!a),children:[e.jsx(ue,{size:16,className:"setup-wizard-advanced-chevron"}),e.jsx("span",{children:s("setup.advancedSettings","Advanced settings")})]}),R&&e.jsxs("div",{className:"setup-wizard-advanced-panel",children:[e.jsx("div",{className:"form-group",children:e.jsxs("div",{className:"project-node-selector",children:[e.jsx("span",{className:"project-node-selector__label",children:s("setup.runtimeNode","Runtime Node")}),e.jsxs("select",{value:t.manualNodeId,onChange:a=>n(r=>({...r,manualNodeId:a.target.value})),disabled:O||t.isRegistering,children:[e.jsx("option",{value:"",children:s("setup.localNode","Local node")}),S.map(a=>e.jsxs("option",{value:a.id,children:[a.name," (",a.type,")"]},a.id))]})]})}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:s("setup.isolationMode","Isolation Mode")}),e.jsxs("div",{className:"setup-wizard-isolation-options",children:[e.jsxs("label",{className:`setup-wizard-isolation-option${t.manualIsolationMode==="in-process"?" selected":""}`,children:[e.jsx("input",{type:"radio",name:"isolation-mode",value:"in-process",checked:t.manualIsolationMode==="in-process",onChange:()=>n(a=>({...a,manualIsolationMode:"in-process"}))}),e.jsxs("div",{className:"setup-wizard-isolation-option-content",children:[e.jsx("strong",{children:s("setup.inProcess","In-Process")}),e.jsx("span",{children:s("setup.inProcessDesc","Lower overhead, shared memory. Best for most projects.")}),e.jsx("span",{className:"wizard-option-recommended",children:s("setup.recommended","Recommended")})]})]}),e.jsxs("label",{className:`setup-wizard-isolation-option${t.manualIsolationMode==="child-process"?" selected":""}`,children:[e.jsx("input",{type:"radio",name:"isolation-mode",value:"child-process",checked:t.manualIsolationMode==="child-process",onChange:()=>n(a=>({...a,manualIsolationMode:"child-process"}))}),e.jsxs("div",{className:"setup-wizard-isolation-option-content",children:[e.jsx("strong",{children:s("setup.childProcess","Child-Process")}),e.jsx("span",{children:s("setup.childProcessDesc","Isolated execution with crash containment.")})]})]})]})]})]})]}),t.error&&e.jsx("div",{className:"wizard-error",role:"alert",children:t.error})]}),t.step==="agent"&&e.jsxs("div",{className:"setup-wizard-agent-step",children:[e.jsx("p",{className:"setup-wizard-agent-intro",children:s("setup.firstAgentIntro","Agents are optional. Fusion can build tasks without one by starting temporary agents for planning, coding, review, and merge. Create an agent only if you want help coordinating tasks and direction.")}),e.jsxs("div",{className:"setup-wizard-agent-layout",children:[e.jsxs("section",{className:"setup-wizard-agent-presets","aria-labelledby":"setup-first-agent-presets-heading",children:[e.jsx("div",{className:"setup-wizard-agent-section-heading",id:"setup-first-agent-presets-heading",children:s("setup.firstAgentTemplates","Templates")}),e.jsx("div",{className:"setup-wizard-agent-preset-list",role:"radiogroup","aria-label":s("setup.firstAgentTemplates","Templates"),children:h.map(a=>{const r=t.selectedPresetId===a.id;return e.jsxs("button",{type:"button",className:`setup-wizard-agent-preset${r?" selected":""}`,role:"radio","aria-checked":r,"aria-label":r?s("setup.selectedAgentTemplate","{{name}} selected",{name:a.name}):a.name,tabIndex:a.id===se?0:-1,"data-agent-preset-id":a.id,disabled:j,onClick:()=>b(a.id),onKeyDown:i=>Y(i,a.id),children:[e.jsx(F,{agent:{id:a.id,icon:a.icon,name:a.name},size:28}),e.jsxs("span",{className:"setup-wizard-agent-preset-copy",children:[e.jsxs("span",{className:"setup-wizard-agent-preset-name",children:[a.name,a.id==="ceo"&&e.jsx("span",{className:"wizard-option-recommended",children:s("setup.recommended","Recommended")})]}),e.jsx("span",{className:"setup-wizard-agent-preset-description",children:a.description})]})]},a.id)})})]}),e.jsxs("section",{className:"setup-wizard-agent-preview","aria-labelledby":"setup-first-agent-preview-heading",children:[e.jsx("div",{className:"setup-wizard-agent-section-heading",id:"setup-first-agent-preview-heading",children:s("setup.firstAgentPreview","Preview")}),e.jsxs("div",{className:"setup-wizard-agent-preview-card",children:[e.jsxs("div",{className:"setup-wizard-agent-preview-title-row",children:[e.jsx(F,{agent:{id:t.selectedPresetId||"draft",icon:t.agentDraft.icon,name:t.agentDraft.name},size:36}),e.jsxs("div",{children:[e.jsx("h3",{children:t.agentDraft.name||s("setup.firstAgentDraftName","Draft agent")}),e.jsx("p",{children:t.agentDraft.title||te?.title||s("setup.firstAgentCustomDraft","Custom agent draft")})]})]}),e.jsxs("dl",{className:"setup-wizard-agent-preview-list",children:[e.jsxs("div",{children:[e.jsx("dt",{children:s("agents.fieldRole","Role")}),e.jsx("dd",{children:t.agentDraft.role})]}),e.jsxs("div",{children:[e.jsx("dt",{children:s("agents.fieldInstructionsText","Inline Instructions")}),e.jsx("dd",{children:t.agentDraft.instructionsText||s("setup.firstAgentNoInstructions","No inline instructions yet")})]})]}),I&&e.jsxs("button",{type:"button",className:"btn setup-wizard-agent-ai-btn",onClick:()=>w(!0),disabled:j,children:[e.jsx(me,{size:16}),e.jsx("span",{children:s("agents.aiInterview","AI Interview")})]})]})]})]}),t.agentError&&e.jsx("div",{className:"wizard-error",role:"alert",tabIndex:-1,ref:M,children:t.agentError})]}),t.step==="complete"&&e.jsxs("div",{className:"setup-wizard-complete",children:[e.jsxs("div",{className:"setup-wizard-success-streak","aria-hidden":"true",children:[e.jsx("div",{className:"setup-wizard-success-streak-core"}),e.jsx("div",{className:"setup-wizard-success-streak-glow"})]}),e.jsx(T,{size:64,className:"success-icon"}),e.jsx("h3",{children:s("setup.allSet","All Set!")}),e.jsx("p",{children:t.agentOutcome==="created"?s("setup.firstAgentCreatedSuccess","Your project is registered and your first agent is ready."):s("setup.projectRegisteredSuccess","Your project has been registered successfully.")}),e.jsx("p",{children:t.agentOutcome==="skipped"?s("setup.firstAgentSkippedHint","You can create agents later from the Agents view."):s("setup.addMoreProjectsHint","You can add more projects anytime from the project overview.")})]})]}),e.jsxs("div",{className:"setup-wizard-footer",children:[e.jsx("a",{className:"btn setup-wizard-help-link",href:U,target:"_blank",rel:"noopener noreferrer",children:s("setup.needHelp","Need help?")}),t.step==="manual"&&e.jsx("button",{className:"btn btn-primary",onClick:$,disabled:ee,children:t.isRegistering?e.jsxs(e.Fragment,{children:[e.jsx(C,{size:16,className:"animate-spin"}),e.jsx("span",{children:s("setup.registering","Registering...")})]}):e.jsx("span",{children:V})}),t.step==="agent"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"btn",onClick:Z,disabled:j,children:s("setup.skipFirstAgent","Skip for now")}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void K(),disabled:j||!t.agentDraft.name.trim(),"aria-busy":t.isCreatingAgent,children:t.isCreatingAgent?e.jsxs(e.Fragment,{children:[e.jsx(C,{size:16,className:"animate-spin"}),e.jsx("span",{children:s("setup.creatingFirstAgent","Creating agent...")})]}):e.jsx("span",{children:s("setup.createFirstAgent","Create Agent")})})]}),t.step==="complete"&&e.jsxs("button",{className:"btn btn-primary",onClick:B,children:[e.jsx(T,{size:16}),e.jsx("span",{children:s("setup.getStarted","Get Started")})]})]})]}),I&&D&&e.jsx(ge,{level:"modal",fallback:e.jsxs("div",{className:"wizard-error setup-wizard-agent-interview-error",role:"alert",children:[e.jsx("span",{children:s("setup.firstAgentInterviewLoadError","AI interview could not load. You can still create an agent from a template or skip this step.")}),e.jsx("button",{type:"button",className:"btn",onClick:()=>w(!1),children:s("setup.firstAgentContinueWithTemplates","Continue with templates")})]}),children:e.jsx(o.Suspense,{fallback:e.jsx("div",{className:"wizard-error setup-wizard-agent-interview-error",role:"status",children:s("setup.firstAgentInterviewLoading","Loading AI Interview...")}),children:e.jsx(fe,{isOpen:D,onClose:()=>w(!1),onUseDraft:q,projectId:t.registeredProject?.id,existingAgents:[],mode:"create"})})})]})}export{Ie as SetupWizardModal};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import{r as l,j as e}from"./vendor-react-SZ_qB27O.js";import{c as Rt,ay as ft,az as ht,aA as Ot,bh as _t,bi as Pt,bj as Ut,bk as Kt,bl as Bt,bm as Vt,bn as Xt,bo as zt,aD as Gt,ae as Wt,bp as qt,bq as Z,br as xt,L as Ht,P as gt,G as tt,X as et,bs as vt,I as Lt,J as yt,bt as Jt,ad as Yt,o as Qt,bu as Zt,bv as jt,al as te}from"./index-B6ttSchA.js";import{u as kt}from"./vendor-i18n-GF3RlKbq.js";import"./vendor-reactflow-CnI7NMXG.js";import"./vendor-xterm-BNq00GSj.js";import"./vendor-codemirror-jBKmHyH0.js";/**
|
|
2
|
-
* @license lucide-react v1.7.0 - ISC
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the ISC license.
|
|
5
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const ee=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M8 12h8",key:"1wcyev"}],["path",{d:"M12 8v8",key:"napkw2"}]],se=Rt("circle-plus",ee);function oe(C){const{items:r,...f}=C;return f}function It(C){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?`${C}-${crypto.randomUUID()}`:`${C}-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function ae(C={}){const{t:r}=kt("app"),{projectId:f,addToast:L}=C,o=`${Ot.TODO_LISTS_PREFIX}${f??"global"}`,[w,I]=l.useState(()=>{const s=ft(o,{maxAgeMs:ht});return Array.isArray(s)?s:[]}),[N,k]=l.useState([]),[T,O]=l.useState(()=>w.length===0),[q,y]=l.useState(null),[F,$]=l.useState(null),[j,g]=l.useState([]),S=l.useRef(F);S.current=F,l.useEffect(()=>{let s=!1;const c=ft(o,{maxAgeMs:ht}),u=Array.isArray(c)&&c.length>0;u?(I(c),O(!1)):(I([]),O(!0));async function b(){u||O(!0),y(null);try{const n=await zt(f);if(s)return;g(n);const a=n.map(oe);I(a),Gt(o,a,{maxBytes:5e5});const i=S.current&&n.some(d=>d.id===S.current)?S.current:n[0]?.id??null;$(i),k(i?n.find(d=>d.id===i)?.items??[]:[])}catch(n){if(s)return;g([]),I([]),k([]),$(null),y(n instanceof Error?n.message:r("todo.failedLoadLists","Failed to load todo lists"))}finally{s||O(!1)}}return b(),()=>{s=!0}},[o,f]),l.useEffect(()=>{if(!F){k([]);return}const s=j.find(c=>c.id===F);k(s?.items??[])},[j,F]);const H=l.useCallback(async s=>{const c=w,u=j,b=new Date().toISOString(),n={id:It("temp-list"),projectId:f??"",title:s,createdAt:b,updatedAt:b};y(null),I(a=>[...a,n]),g(a=>[...a,{...n,items:[]}]);try{const a=await _t(s,f);I(i=>i.map(d=>d.id===n.id?a:d)),g(i=>i.map(d=>d.id===n.id?{...a,items:[]}:d)),S.current||$(a.id)}catch(a){I(c),g(u),y(a instanceof Error?a.message:r("todo.failedCreateList","Failed to create list")),L?.(r("todo.failedCreateListToast","Failed to create todo list"),"error")}},[L,j,w,f,r]),P=l.useCallback(async(s,c)=>{const u=w,b=j;y(null),I(n=>n.map(a=>a.id===s?{...a,title:c}:a)),g(n=>n.map(a=>a.id===s?{...a,title:c}:a));try{const n=await Pt(s,c,f);I(a=>a.map(i=>i.id===s?n:i)),g(a=>a.map(i=>i.id===s?{...n,items:i.items}:i))}catch(n){I(u),g(b),y(n instanceof Error?n.message:r("todo.failedRenameList","Failed to rename list")),L?.(r("todo.failedRenameListToast","Failed to rename todo list"),"error")}},[L,j,w,f,r]),D=l.useCallback(async s=>{const c=w,u=j,b=S.current,n=b===s?w.find(a=>a.id!==s)?.id??null:b;y(null),I(a=>a.filter(i=>i.id!==s)),g(a=>a.filter(i=>i.id!==s)),b===s&&$(n);try{await Ut(s,f)}catch(a){I(c),g(u),$(b),y(a instanceof Error?a.message:r("todo.failedDeleteList","Failed to delete list")),L?.(r("todo.failedDeleteListToast","Failed to delete todo list"),"error")}},[L,j,w,f,r]),X=l.useCallback(async s=>{const c=S.current;if(!c)return;const u=N,b=j,n=new Date().toISOString(),a=N.reduce((d,p)=>Math.max(d,p.sortOrder),-1),i={id:It("temp-item"),listId:c,text:s,completed:!1,completedAt:null,createdAt:n,updatedAt:n,sortOrder:a+1};y(null),k(d=>[...d,i]),g(d=>d.map(p=>p.id===c?{...p,items:[...p.items,i]}:p));try{const d=await Kt(c,s,f);k(p=>p.map(v=>v.id===i.id?d:v)),g(p=>p.map(v=>v.id===c?{...v,items:v.items.map(R=>R.id===i.id?d:R)}:v))}catch(d){k(u),g(b),y(d instanceof Error?d.message:r("todo.failedCreateItem","Failed to create item")),L?.(r("todo.failedCreateItemToast","Failed to create todo item"),"error")}},[L,N,j,f,r]),A=l.useCallback(async(s,c)=>{const u=N.find(d=>d.id===s);if(!u)return;const b=N,n=j,a=c.completed??u.completed,i={...u,...c,completed:a,completedAt:a?u.completedAt??new Date().toISOString():null,updatedAt:new Date().toISOString()};y(null),k(d=>d.map(p=>p.id===s?i:p)),g(d=>d.map(p=>p.id===i.listId?{...p,items:p.items.map(v=>v.id===s?i:v)}:p));try{const d=await Bt(s,c,f);k(p=>p.map(v=>v.id===s?d:v)),g(p=>p.map(v=>v.id===d.listId?{...v,items:v.items.map(R=>R.id===s?d:R)}:v))}catch(d){k(b),g(n),y(d instanceof Error?d.message:r("todo.failedUpdateItem","Failed to update item")),L?.(r("todo.failedUpdateItemToast","Failed to update todo item"),"error")}},[L,N,j,f,r]),U=l.useCallback(async s=>{const c=N.find(u=>u.id===s);c&&await A(s,{completed:!c.completed})},[N,A]),M=l.useCallback(async s=>{const c=N,u=j;y(null),k(b=>b.filter(n=>n.id!==s)),g(b=>b.map(n=>({...n,items:n.items.filter(a=>a.id!==s)})));try{await Vt(s,f)}catch(b){k(c),g(u),y(b instanceof Error?b.message:r("todo.failedDeleteItem","Failed to delete item")),L?.(r("todo.failedDeleteItemToast","Failed to delete todo item"),"error")}},[L,N,j,f,r]),z=l.useCallback(async s=>{const c=S.current;if(!c)return;const u=N,b=j,n=new Map(N.map(i=>[i.id,i])),a=s.map((i,d)=>{const p=n.get(i);return p?{...p,sortOrder:d}:null}).filter(i=>i!==null);y(null),k(a),g(i=>i.map(d=>d.id===c?{...d,items:a}:d));try{await Xt(c,s,f)}catch(i){k(u),g(b),y(i instanceof Error?i.message:r("todo.failedReorderItems","Failed to reorder items")),L?.(r("todo.failedReorderItemsToast","Failed to reorder todo items"),"error")}},[L,N,j,f,r]);return{lists:w,items:N,loading:T,error:q,selectedListId:F,setSelectedListId:$,createList:H,renameList:P,deleteList:D,createItem:X,updateItem:A,toggleItem:U,deleteItem:M,reorderItems:z}}function ne(C){return[...C].sort((r,f)=>r.sortOrder-f.sortOrder)}function ue({projectId:C,addToast:r,onPlanningMode:f,onTaskCreated:L}){const{t:o}=kt("app"),{lists:w,items:I,loading:N,error:k,selectedListId:T,setSelectedListId:O,createList:q,renameList:y,deleteList:F,createItem:$,updateItem:j,toggleItem:g,deleteItem:S,reorderItems:H}=ae({projectId:C,addToast:(t,m)=>{if(m==="success"||m==="error"||m==="info"||m===void 0){r(t,m);return}r(t,"info")}}),[P,D]=l.useState(null),[X,A]=l.useState(""),[U,M]=l.useState(null),[z,s]=l.useState(""),[c,u]=l.useState(""),[b,n]=l.useState(!1),[a,i]=l.useState(""),[d,p]=l.useState([]),[v,R]=l.useState(!1),[J,K]=l.useState(!1),[st,B]=l.useState(null),Y=l.useRef(null),{confirm:Ct}=Wt(),[wt,ot]=l.useState("list"),G=l.useMemo(()=>w.find(t=>t.id===T)??null,[w,T]),_=l.useMemo(()=>ne(I.filter(t=>t.listId===T)),[I,T]),at=l.useMemo(()=>{const t=new Map;for(const m of w)t.set(m.id,{total:0,completed:0});for(const m of I){const h=t.get(m.listId)??{total:0,completed:0};h.total+=1,m.completed&&(h.completed+=1),t.set(m.listId,h)}return t},[I,w]),Q=G?at.get(G.id)??{total:_.length,completed:_.filter(t=>t.completed).length}:null;function nt(){D(null),A(""),u(""),n(!1)}function W(){M(null),s(""),i("")}function Nt(t){nt(),W(),O(t),ot("detail")}function At(){ot("list")}const St=l.useCallback(async()=>{R(!0);try{const t=await qt(void 0,C);p(t),K(!0)}catch(t){r(o("todo.failedToLoadAgents","Failed to load agents: {{error}}",{error:Z(t)}),"error"),K(!1),B(null)}finally{R(!1)}},[C,r,o]);l.useEffect(()=>{D(null),A(""),u(""),n(!1),M(null),s(""),i(""),K(!1),B(null)},[T]),l.useEffect(()=>{if(!J)return;const t=m=>{Y.current&&!Y.current.contains(m.target)&&(K(!1),B(null))};return document.addEventListener("mousedown",t),()=>{document.removeEventListener("mousedown",t)}},[J]);function Et(t){W(),D(t.id),A(t.title),n(!1)}async function it(){if(!P)return;const t=X.trim();if(!t){D(null),A("");return}await y(P,t),D(null),A("")}function dt(){D(null),A("")}function lt(t){nt(),M(t.id),s(t.text)}async function rt(){if(!U)return;const t=z.trim();if(!t){M(null),s("");return}await j(U,{text:t}),M(null),s("")}function ct(){M(null),s("")}async function mt(){const t=c.trim();t&&(await q(t),u(""),n(!1))}async function ut(){if(!T)return;const t=a.trim();t&&(await $(t),i(""))}async function Tt(t){await Ct({title:o("todo.deleteListTitle","Delete List"),message:o("todo.deleteListConfirm","Delete this list and all its items?"),danger:!0})&&await F(t)}async function Dt(t){await S(t)}async function bt(t,m){const h=_.map(V=>V.id),x=h.findIndex(V=>V===t);if(x<0)return;const E=m==="up"?x-1:x+1;E<0||E>=h.length||([h[x],h[E]]=[h[E],h[x]],await H(h))}const Ft=l.useCallback(async t=>{try{const m={description:t.text,column:"triage",source:{sourceType:"dashboard_ui"}},h=await xt(m,C);L?.(h),r(o("todo.taskCreatedFromTodo","Created {{id}} from todo",{id:h.id}),"success")}catch(m){r(o("todo.failedToCreateTask","Failed to create task: {{error}}",{error:Z(m)}),"error")}},[C,r,L,o]),$t=l.useCallback(async(t,m)=>{try{const h={description:t.text,column:"triage",assignedAgentId:m,source:{sourceType:"dashboard_ui"}},x=await xt(h,C);L?.(x);const V=d.find(Mt=>Mt.id===m)?.name??m;r(o("todo.taskCreatedAndAssigned","Created {{id}} and assigned to {{agent}}",{id:x.id,agent:V}),"success"),K(!1),B(null)}catch(h){r(o("todo.failedToCreateAndAssign","Failed to create and assign task: {{error}}",{error:Z(h)}),"error")}},[C,r,d,L,o]),pt=null;return N?e.jsxs("div",{className:"todo-view","data-testid":"todo-view-root",children:[pt,e.jsxs("div",{className:"todo-loading",children:[e.jsx(Ht,{className:"todo-loading-icon","aria-hidden":"true"}),e.jsx("p",{children:o("todo.loading","Loading todos...")})]})]}):e.jsxs("div",{className:"todo-view","data-testid":"todo-view-root",children:[pt,e.jsxs("div",{className:"todo-view-layout","data-mobile-stack-view":wt,children:[e.jsxs("aside",{className:"todo-view-sidebar","aria-label":o("todo.listsLabel","Todo lists sidebar"),children:[e.jsxs("div",{className:"todo-sidebar-header",children:[e.jsx("h3",{className:"todo-sidebar-title",children:o("todo.lists","Lists")}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-add-list-btn",onClick:()=>{W(),n(!0),D(null)},"aria-label":o("todo.addList","Add list"),"data-testid":"add-list-button",children:e.jsx(gt,{})})]}),b&&e.jsxs("div",{className:"todo-list-item",children:[e.jsx("input",{className:"input todo-inline-edit-input",placeholder:o("todo.newListTitle","New list title"),value:c,onChange:t=>u(t.target.value),onKeyDown:t=>{t.key==="Enter"&&mt(),t.key==="Escape"&&(u(""),n(!1))},autoFocus:!0,"data-testid":"new-list-input"}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:()=>{mt()},"aria-label":o("todo.saveList","Save list"),children:e.jsx(tt,{})}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:()=>{u(""),n(!1)},"aria-label":o("todo.cancelList","Cancel list"),children:e.jsx(et,{})})]}),w.length===0&&!b?e.jsxs("div",{className:"todo-empty-state",children:[e.jsx(vt,{"aria-hidden":"true"}),e.jsx("p",{children:o("todo.noListsEmpty","No todo lists yet. Create one to get started.")}),e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>{W(),n(!0)},children:o("todo.createList","Create List")})]}):e.jsx("div",{className:"todo-list-items",role:"list","aria-label":o("todo.todoListsLabel","Todo lists"),children:w.map(t=>{const m=t.id===T,h=t.id===P,x=at.get(t.id)??{total:0,completed:0};return e.jsx("div",{className:`todo-list-item${m?" todo-list-item--active":""}`,role:"listitem",children:h?e.jsxs(e.Fragment,{children:[e.jsx("input",{className:"input todo-inline-edit-input",value:X,onChange:E=>A(E.target.value),onKeyDown:E=>{E.key==="Enter"&&it(),E.key==="Escape"&&dt()},autoFocus:!0,"data-testid":`rename-list-input-${t.id}`}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:()=>{it()},"aria-label":o("todo.saveListRename","Save list rename"),children:e.jsx(tt,{})}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:dt,"aria-label":o("todo.cancelListRename","Cancel list rename"),children:e.jsx(et,{})})]}):e.jsxs(e.Fragment,{children:[e.jsxs("button",{type:"button",className:"todo-list-select-btn",onClick:()=>Nt(t.id),"aria-label":o("todo.selectList","Select list {{title}}",{title:t.title}),"aria-current":m?"true":void 0,"data-testid":`todo-list-${t.id}`,children:[e.jsx("span",{className:"todo-list-item-name",children:t.title}),e.jsxs("span",{className:"todo-list-item-count",children:[x.completed,"/",x.total]})]}),e.jsxs("div",{className:"todo-list-item-actions",children:[e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:()=>{Et(t)},"aria-label":o("todo.renameList","Rename {{title}}",{title:t.title}),"data-testid":`rename-list-button-${t.id}`,children:e.jsx(Lt,{})}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon btn-danger todo-icon-btn",onClick:()=>{Tt(t.id)},"aria-label":o("todo.deleteList","Delete {{title}}",{title:t.title}),"data-testid":`delete-list-button-${t.id}`,children:e.jsx(yt,{})})]})]})},t.id)})})]}),e.jsxs("section",{className:"todo-view-main","aria-label":o("todo.itemsLabel","Todo items"),children:[k&&e.jsxs("div",{className:"todo-error-banner",role:"alert",children:[e.jsx("span",{className:"todo-error-message",children:k}),e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>window.location.reload(),children:o("actions.retry","Retry")})]}),G?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"todo-items-header",children:[e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn todo-mobile-back-btn",onClick:At,"aria-label":o("todo.backToLists","Back to lists"),"data-testid":"todo-mobile-back-button",children:e.jsx(Jt,{})}),e.jsxs("div",{className:"todo-items-heading",children:[e.jsx("h3",{children:G.title}),Q&&e.jsx("span",{className:"todo-items-progress",children:o("todo.completedCount","{{completed}}/{{total}} complete",{completed:Q.completed,total:Q.total})})]})]}),e.jsxs("div",{className:"todo-add-item-row",children:[e.jsx("input",{className:"input",placeholder:o("todo.addItemPlaceholder","Add a todo item"),value:a,onChange:t=>i(t.target.value),onKeyDown:t=>{t.key==="Enter"&&ut(),t.key==="Escape"&&i("")},"data-testid":"new-item-input"}),e.jsxs("button",{type:"button",className:"btn btn-primary",onClick:()=>{ut()},children:[e.jsx(gt,{size:14}),o("actions.add","Add")]})]}),_.length===0?e.jsx("div",{className:"todo-empty-state",children:e.jsx("p",{children:o("todo.noItemsEmpty","No items in this list. Add one above.")})}):e.jsx("div",{className:"todo-items-list",children:_.map((t,m)=>{const h=t.id===U;return e.jsxs("div",{className:"todo-item","data-testid":`todo-item-${t.id}`,children:[e.jsxs("div",{className:"todo-item-main-row",children:[e.jsx("input",{type:"checkbox",checked:t.completed,onChange:()=>{g(t.id)},className:"todo-item-checkbox","aria-label":`Toggle ${t.text}`,"data-testid":`toggle-item-${t.id}`}),h?e.jsx("input",{className:"input todo-inline-edit-input",value:z,onChange:x=>s(x.target.value),onKeyDown:x=>{x.key==="Enter"&&rt(),x.key==="Escape"&&ct()},autoFocus:!0,"data-testid":`edit-item-input-${t.id}`}):e.jsx("button",{type:"button",className:`todo-item-text${t.completed?" todo-item-text--completed":""}`,onClick:()=>lt(t),children:t.text})]}),e.jsx("div",{className:"todo-item-actions","data-testid":`todo-item-actions-${t.id}`,children:h?e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:()=>{rt()},"aria-label":o("todo.saveItemEdit","Save item edit"),children:e.jsx(tt,{})}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:ct,"aria-label":o("todo.cancelItemEdit","Cancel item edit"),children:e.jsx(et,{})})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"todo-item-reorder-btns",children:[e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-item-reorder-btn",onClick:()=>{bt(t.id,"up")},disabled:m===0,"aria-label":o("todo.moveItemUp","Move {{text}} up",{text:t.text}),"data-testid":`move-up-${t.id}`,children:e.jsx(Yt,{})}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-item-reorder-btn",onClick:()=>{bt(t.id,"down")},disabled:m===_.length-1,"aria-label":o("todo.moveItemDown","Move {{text}} down",{text:t.text}),"data-testid":`move-down-${t.id}`,children:e.jsx(Qt,{})})]}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:()=>{f?.(t.text)},"aria-label":o("todo.startPlanning","Start planning from {{text}}",{text:t.text}),"data-testid":`planning-from-${t.id}`,children:e.jsx(Zt,{})}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:()=>{Ft(t)},"aria-label":o("todo.createTaskFrom","Create task from {{text}}",{text:t.text}),"data-testid":`create-task-from-${t.id}`,children:e.jsx(se,{})}),e.jsxs("div",{className:"todo-agent-picker-trigger",ref:st===t.id?Y:void 0,children:[e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:()=>{B(t.id),St()},"aria-label":o("todo.assignAgent","Assign {{text}} to agent",{text:t.text}),"data-testid":`assign-agent-for-${t.id}`,children:e.jsx(jt,{})}),J&&st===t.id&&e.jsx("div",{className:"todo-agent-picker-dropdown",onMouseDown:x=>{x.preventDefault()},children:v?e.jsx("div",{className:"todo-agent-picker-loading",children:e.jsx(te,{label:o("todo.loadingAgents","Loading agents...")})}):d.length>0?d.map(x=>e.jsxs("button",{type:"button",className:"todo-agent-picker-item",onClick:()=>{$t(t,x.id)},children:[e.jsx(jt,{}),e.jsx("span",{children:x.name}),e.jsx("span",{className:"todo-agent-picker-role",children:x.role})]},x.id)):e.jsx("div",{className:"todo-agent-picker-empty",children:o("todo.noAgentsAvailable","No agents available")})})]}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon todo-icon-btn",onClick:()=>lt(t),"aria-label":o("todo.editItem","Edit {{text}}",{text:t.text}),"data-testid":`edit-item-${t.id}`,children:e.jsx(Lt,{})}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon btn-danger todo-icon-btn",onClick:()=>{Dt(t.id)},"aria-label":o("todo.deleteItem","Delete {{text}}",{text:t.text}),"data-testid":`delete-item-${t.id}`,children:e.jsx(yt,{})})]})})]},t.id)})})]}):e.jsxs("div",{className:"todo-empty-state",children:[e.jsx(vt,{"aria-hidden":"true"}),e.jsx("p",{children:o("todo.selectListEmpty","Select a list from the sidebar")})]})]})]})]})}export{ue as TodoView};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import{r as n,j as e,b as Da}from"./vendor-react-SZ_qB27O.js";import{R as Ta,u as La,d as za,e as Wa,f as $a,g as _a,B as Ba,C as Ga,M as qa}from"./vendor-reactflow-CnI7NMXG.js";import{c as Va,ek as Et,el as lo,em as we,en as Hs,eo as Ha,ep as Ua,eq as Us,bq as ae,bp as At,P as Re,b9 as ze,bv as Ka,ad as Ya,o as Ae,J as ve,am as Ks,er as Ja,bM as Rt,es as os,bG as Ys,et as io,al as Xa,C as Me,bQ as ro,I as Qa,eu as Za,ev as en,cr as ss,ew as tn,ex as on,ey as sn,ez as an,dx as nn,a4 as as,ae as ln,eA as rn,eB as dn,eC as cn,eD as un,eE as fn,eF as pn,ai as mn,eG as wn,eH as hn,eI as ns,eJ as ls,eK as is,eL as rs,eM as ds,eN as gn,eO as bn,eP as kn,eQ as ut,eR as xn,eS as vn,eT as jn,eU as Nn,eV as yn,eW as Cn,eX as cs,eY as Sn,eZ as us,e_ as fs,e$ as En,f0 as ps,f1 as ms,f2 as An,f3 as eo,f4 as Rn,f5 as Js,f6 as ws,f7 as Fn,i as hs,dj as gs,f8 as bs,X as Xs,bt as ks,L as Ie,f9 as Le,fa as to,bs as Qs,ak as Zs,bc as Pn,fb as ea,a2 as Mn,bb as In,fc as On,fd as Dn,fe as Tn,ff as xs,fg as Ln,fh as zn,fi as Wn,fj as $n,fk as St,S as Je,fl as _n,fm as Bn,fn as Gn,dk as vs,fo as js,fp as qn,fq as Vn,dm as Hn,fr as Un,fs as Kn}from"./index-B6ttSchA.js";import{u as je}from"./vendor-i18n-GF3RlKbq.js";import{U as Yn}from"./upload-0_pT1euA.js";import"./vendor-xterm-BNq00GSj.js";import"./vendor-codemirror-jBKmHyH0.js";/**
|
|
2
|
-
* @license lucide-react v1.7.0 - ISC
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the ISC license.
|
|
5
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const Jn=[["path",{d:"m16 6 4 14",key:"ji33uf"}],["path",{d:"M12 6v14",key:"1n7gus"}],["path",{d:"M8 8v12",key:"1gg7y9"}],["path",{d:"M4 4v16",key:"6qkkli"}]],Xn=Va("library",Jn);function Qn(s){return typeof s.irKind=="string"?s.irKind:s.kind}const Zn={start:{title:"Start",summary:"Marks where a task enters the workflow. Every workflow has exactly one start node.",configure:"Set the Entry column to choose which board column a task lands in when it enters (v2 workflows). Leave on Auto to use the first column.",inputs:"None — this is the entry point.",outputs:"Hands the task to the first downstream node.",edges:"One outgoing edge (success). No incoming edges."},end:{title:"End",summary:"A terminal state. A task that reaches an end node is finished on that path.",inputs:"One or more incoming edges.",outputs:"None — the task stops here.",edges:"Incoming edges only; no outgoing edges."},prompt:{title:"Prompt (agent step)",summary:"Runs a unit of work against the task — an AI model, a named agent, a skill, or a CLI command. The workhorse node for executing, planning, and reviewing.",configure:"Write the Prompt, then pick an Executor (model, agent, skill, CLI, or CLI-agent) and its options (model, agent, skill, or command). Optionally set Gate mode (advisory vs blocking), Max retries, Auto-approve, or Wait for user input.",inputs:"The task plus any prior step output and context.",outputs:"The step's result, passed downstream; may record a gate verdict.",edges:"success / failure outgoing edges. As a blocking gate it can stop the task on failure."},script:{title:"Script",summary:"Runs a named project script (defined in project settings) as a workflow step.",configure:"Set Script name to a script from project settings. Set Gate mode to choose whether a non-zero exit blocks the task. The node prompt is passed to the script via FUSION_NODE_PROMPT.",inputs:"The task; the node prompt via FUSION_NODE_PROMPT.",outputs:"The script's exit status and output.",edges:"success / failure."},gate:{title:"Gate",summary:"A decision checkpoint that evaluates a prompt and routes the task by its verdict, optionally blocking progress.",configure:"Write the gate Prompt. Set Gate mode to Advisory (records a verdict but never blocks) or Gate (blocks the task on failure).",inputs:"The task plus prior context.",outputs:"A pass/fail (or outcome) verdict.",edges:"success / failure; a blocking gate holds the task on failure."},merge:{title:"Merge boundary",summary:"A marker separating pre-merge from post-merge steps. Steps before it run before the branch merges; steps after run after.",configure:"No fields to set — placement is what matters. Position it where the merge happens in your pipeline.",inputs:"The task after upstream steps complete.",outputs:"Passes the task to post-merge steps.",edges:"One outgoing edge (success)."},hold:{title:"Hold",summary:"Pauses the task until a release condition is met — a manual promote, a timer, downstream capacity, a dependency, or an external event.",configure:"Pick a Release condition: Manual promote, Timer, Downstream capacity, Dependency complete, or External event.",inputs:"The task arriving from upstream.",outputs:"Releases the task downstream once the condition is satisfied.",edges:"One outgoing edge (success), taken once released."},split:{title:"Split (parallel branch)",summary:"Fans the task out into multiple branches that run concurrently. Pair with a Join downstream to recombine them.",configure:"No fields to set — connect multiple outgoing edges; each becomes a parallel branch.",inputs:"A single task path.",outputs:"Multiple concurrent branches.",edges:"Multiple outgoing edges, one per branch. Recombine with a Join."},join:{title:"Join",summary:"Waits for parallel branches (from a Split) and recombines them according to a join policy.",configure:"Set Join mode: All branches, Any branch, or Quorum (n) with a count. Set On branch failure to Collect (wait for all) or Fail-fast (cancel siblings).",inputs:"Multiple parallel branches.",outputs:"A single resumed path once the join policy is satisfied.",edges:"One outgoing edge (success), taken when the join condition is met."},foreach:{title:"For-each",summary:"Runs a template of steps once per item (e.g. per parsed step), sequentially or in parallel. Renders as a group you drop step nodes into.",configure:"Set Mode (sequential/parallel), Isolation (shared or per-step worktree), Concurrency (parallel only), and Max rework cycles (the bound on rework loop-backs). Drop a step-execute node inside.",inputs:"A collection of items (e.g. parsed steps) plus the task.",outputs:"Aggregated per-item results.",edges:"success once all iterations finish. Internal rework edges loop back within a step instance, bounded by Max rework cycles."},loop:{title:"Loop",summary:"Repeats a template of steps until an exit condition is met or a cap is hit. Renders as a group you drop loop steps into.",configure:"Set the Exit condition (output contains / output matches regex) and its value or pattern, an optional Watch node id, Max iterations, and Timeout (ms).",inputs:"The task plus the loop body steps.",outputs:"The final iteration's result.",edges:"One outgoing edge (success) on exit. Exits on condition match, max iterations, or timeout."},"optional-group":{title:"Optional group",summary:"Holds a group of steps that run only when the task has this group enabled. Enabled tasks run the group's steps once at this position; disabled tasks pass straight through. Renders as a group you drop step nodes into.",configure:"Set the group Name and whether it is Enabled by default for new tasks (defaultOn). A task can override the default per-task. Drop the optional steps inside the region.",inputs:"The task arriving from upstream, plus prior context.",outputs:"The group's result when enabled; an unchanged pass-through when disabled.",edges:"success once the group finishes (or is skipped). A template failure inside an enabled group routes the group's failure edge."},"step-review":{title:"Step review",summary:"An AI review gate that emits a verdict (approve / revise / rethink / unavailable) used to route the task — typically back for rework or forward on approval.",configure:"Set Review type (plan or code) and an optional Review model. Route each outgoing edge by verdict; mark a loop-back edge as Rework.",inputs:"The artifact or step output to review.",outputs:"A verdict: approve, revise, rethink, or unavailable.",edges:"Verdict edges (outcome:approve / revise / rethink / unavailable). A rework edge loops back, bounded by Max rework cycles."},"parse-steps":{title:"Parse steps",summary:"Parses a task artifact (e.g. PROMPT.md) into discrete steps a downstream for-each can iterate over.",configure:"Pick the Artifact to parse (e.g. PROMPT.md) and the Parser (e.g. step-headings, plus any plugin parsers).",inputs:"A task artifact or document.",outputs:"A list of parsed steps for a downstream for-each.",edges:"success / failure."},code:{title:"Code",summary:"Runs a sandboxed TypeScript snippet as a workflow step — for lightweight transforms, routing, or computed values.",configure:"Write the TypeScript Source and an optional Timeout (ms). Syntax is validated at save.",inputs:"Task context available to the snippet.",outputs:"The snippet's return value.",edges:"success / failure."},notify:{title:"Notify",summary:"Emits a notification event (and optional title/message) without changing the task's path — for pings on state changes.",configure:"Pick an Event type (or a Custom event) and optional Title/Message. Templates may use {{taskTitle}}, {{taskId}}, {{workflowName}}, and {{context:key}}.",inputs:"The task at this point in the flow.",outputs:"A notification event; the task continues unchanged.",edges:"One outgoing edge (success); the node is pass-through."},"merge-gate":{title:"Auto-merge gate",summary:"Checks whether the task is ready to auto-merge: a live PR/merge entity exists, auto-merge is opted in, and the entity is merge-ready (approved, checks green, mergeable clean).",configure:"Engine-managed checkpoint — not hand-edited. Governed by the project and task auto-merge settings.",inputs:"An approved task with its PR/merge entity.",outputs:"An auto-on / auto-off decision.",edges:"outcome:auto-on → branch-group member integration; auto-off → parks at the manual merge hold for a human.",graphOnly:!0},"merge-attempt":{title:"Merge attempt",summary:"Performs the actual merge of the task's branch toward the integration/default branch (squash by project default), with conflict and post-merge audit handling.",configure:"Engine-managed — not hand-edited. Follows the project's merge strategy and audit settings.",inputs:"A promotion-ready branch.",outputs:"A merged branch, or a conflict requiring manual resolution.",edges:"success → end; conflict/failure → manual merge hold.",graphOnly:!0},"manual-merge-hold":{title:"Manual merge hold",summary:"Parks the task in review for a human to merge when auto-merge is off or a step needs manual resolution. While auto-merge is off, in-review is terminal until a person merges.",configure:"Engine-managed park state — not hand-edited.",inputs:"A task blocked from auto-merge, or one with a merge conflict.",outputs:"A human-resolved merge that resumes the flow.",edges:"On manual resolution, loops back into integration/merge (rework).",graphOnly:!0},"retry-backoff":{title:"Retry backoff",summary:"Waits a backoff interval before retrying a failed step, bounded by a retry budget.",configure:"Engine-managed — not hand-edited.",inputs:"A failed step eligible for retry.",outputs:"A delayed retry of the step.",edges:"Loops back to the step until the retry budget is exhausted.",graphOnly:!0},"recovery-router":{title:"Recovery router",summary:"A self-healing decision point that routes a stuck or interrupted task onto the right recovery path (retry, rebound, or escalate).",configure:"Engine-managed — not hand-edited.",inputs:"A task in an anomalous or interrupted state.",outputs:"A recovery-route decision.",edges:"Branches to retry, rebound, or manual paths by recovery outcome.",graphOnly:!0},"branch-group-member-integration":{title:"Branch group · member integration",summary:"For a task in a shared branch group, integrates this member's work onto the group's shared branch. A soft pre-integration step that runs even when global auto-merge is off (it only assembles the group branch).",configure:"Engine-managed — not hand-edited. Active only for shared-branch-group members.",inputs:"An approved group-member task and the group's shared branch.",outputs:"The member's work landed on the shared branch.",edges:"success → branch group promotion; manual-required → manual merge hold.",graphOnly:!0},"branch-group-promotion":{title:"Branch group · promotion",summary:"Once all members have landed on the shared branch, carries the complete group forward — merging the group branch toward the integration branch and creating-or-reusing the group's single managed PR. Idempotent: re-running never creates a second PR. Gated by group/global auto-merge.",configure:"Engine-managed — not hand-edited. Runs once the group is complete and auto-merge is eligible.",inputs:"A complete shared branch group (all members landed).",outputs:"The group promoted toward the integration branch, plus its single managed PR.",edges:"success → merge attempt; manual-required → manual merge hold.",graphOnly:!0},"pr-create":{title:"PR create",summary:"Creates (or reuses) the pull request for the task in pull-request merge mode.",configure:"Engine-managed — not hand-edited. Active in pull-request merge mode.",inputs:"A task branch ready for review.",outputs:"An open PR entity (created or reused).",edges:"success → the PR review/merge path.",graphOnly:!0},"pr-respond":{title:"PR respond",summary:"Responds to PR review feedback — addressing comments and pushing follow-up commits — during the PR review cycle.",configure:"Engine-managed — not hand-edited.",inputs:"PR review comments and threads.",outputs:"Replies and follow-up commits on the PR.",edges:"Loops within the PR review cycle until feedback is resolved.",graphOnly:!0},"pr-merge":{title:"PR merge",summary:"Merges the pull request once it is approved and all checks pass, in pull-request mode.",configure:"Engine-managed — not hand-edited. Governed by auto-merge readiness.",inputs:"An approved, green PR.",outputs:"A merged PR.",edges:"success → end; blocked → manual merge hold.",graphOnly:!0}};function el(s){return Zn[s]??null}function tl(s){return el(Qn(s))}const Ns=80,ol=24,ys=16,Cs=0,sl=0,oo=Hs+ol;function al(s){return!(we(s.id)||s.parentId)}function nl(s){const i=s.style?.width;return typeof i=="number"?i:Et}function ll(s,i){const r=new Set(s),g=new Map,d=new Map;for(const x of s)d.set(x,0);for(const x of i)x.data?.kind!=="rework"&&(!r.has(x.source)||!r.has(x.target)||x.source!==x.target&&((g.get(x.source)??g.set(x.source,[]).get(x.source)).push(x.target),d.set(x.target,(d.get(x.target)??0)+1)));const k=s.filter(x=>x==="start"),I=k.length?k:s.filter(x=>(d.get(x)??0)===0),p=new Map,R=s.length+1,P=[];for(const x of I)p.set(x,0),P.push(x);let O=s.length*s.length+s.length+1;for(;P.length&&O-- >0;){const x=P.shift(),w=p.get(x)??0;for(const c of g.get(x)??[]){const S=w+1,j=p.get(c);(j===void 0||S>j)&&S<=R&&(p.set(c,S),P.push(c))}}let D=0;for(const x of p.values())x>D&&(D=x);const y=p.size?D+1:0;for(const x of s)p.has(x)||p.set(x,y);return p}function Ss(s,i,r){const g=s.filter(al),d=g.map(w=>w.id),k=ll(d,i),I=new Map(g.map(w=>[w.id,w])),p=new Map,R=new Map;for(const w of d){const c=k.get(w)??0;(R.get(c)??R.set(c,[]).get(c)).push(w)}const P=r.length>0,O=new Map;for(const[w,c]of R)O.set(w,Math.max(...c.map(S=>nl(I.get(S))),Et));const D=[...R.keys()].sort((w,c)=>w-c),y=new Map;let x=Cs;for(const w of D)y.set(w,x),x+=(O.get(w)??Et)+Ns;for(const[w,c]of R){const S=[...c].sort((b,M)=>{const A=I.get(b),C=I.get(M);return A.position.y!==C.position.y?A.position.y-C.position.y:b<M?-1:b>M?1:0}),j=y.get(w)??Cs;if(!P){S.forEach((b,M)=>{p.set(b,{x:j,y:sl+M*oo})});continue}const $=new Map;for(const b of S){const M=I.get(b),A=M.data.column??(lo(M.position.y,r)?lo(M.position.y,r):void 0);if(!A){p.set(b,{x:j,y:M.position.y});continue}const C=r.findIndex(se=>se.id===A),z=C>=0?C:0,ue=Ua(z),U=ue+ys,Y=ue+Ha-Hs-ys,te=Math.max(1,Math.floor((Y-U)/oo)+1),V=$.get(A??`__idx${z}`)??0,v=V%te,T=Math.floor(V/te),B=U+v*oo,G=j+T*((O.get(w)??Et)+Ns)/2;p.set(b,{x:G,y:B}),$.set(A??`__idx${z}`,V+1)}}return p}function Es(s,i){return s.map(r=>{const g=i.get(r.id);return g?{...r,position:g}:r})}let As=0;function il(){return As+=1,`col-${Date.now().toString(36)}-${As}`}function Rs({columns:s,onChange:i,violations:r,readOnly:g,projectId:d,addToast:k,columnAgentsEnabled:I}){const{t:p}=je("app"),[R,P]=n.useState([]),[O,D]=n.useState([]),[y,x]=n.useState(!0),[w,c]=n.useState(null);n.useEffect(()=>{let v=!1;return Us(d).then(T=>{v||P(T)}).catch(T=>{v||k(ae(T)||p("workflowColumns.traitsLoadFailed","Failed to load traits"),"error")}),()=>{v=!0}},[d,k,p]),n.useEffect(()=>{let v=!1;return x(!0),c(null),Promise.resolve(At(void 0,d)).then(T=>{v||(D(T??[]),x(!1))}).catch(T=>{if(v)return;const B=ae(T)||p("workflowColumns.agentsLoadFailed","Failed to load agents");c(B),x(!1),k(B,"error")}),()=>{v=!0}},[d,k,p]);const S=n.useMemo(()=>O.map(v=>v.id).join(","),[O]),j=n.useMemo(()=>{const v=new Map;for(const T of O)v.set(T.id,T);return v},[S]),$=n.useCallback((v,T)=>{i(s.map(B=>{if(B.id!==v)return B;if(!T){const{agent:G,...se}=B;return se}return{...B,agent:T}}))},[s,i]),b=n.useCallback((v,T)=>{if(!T){$(v,void 0);return}const B=s.find(G=>G.id===v)?.agent;$(v,{agentId:T,mode:B?.mode??"defer"})},[s,$]),M=n.useCallback((v,T)=>{const B=s.find(G=>G.id===v)?.agent;B&&$(v,{...B,mode:T})},[s,$]),A=g||!I||y||!!w,C=r.filter(v=>v.columnId===null),z=n.useCallback(v=>r.filter(T=>T.columnId===v),[r]),ue=n.useCallback(()=>{const v=il();i([...s,{id:v,name:p("workflowColumns.newColumnName","New column"),traits:[]}])},[s,i,p]),U=n.useCallback((v,T)=>{i(s.map(B=>B.id===v?{...B,name:T}:B))},[s,i]),Y=n.useCallback(v=>{i(s.filter(T=>T.id!==v))},[s,i]),te=n.useCallback((v,T)=>{const B=v+T;if(B<0||B>=s.length)return;const G=[...s];[G[v],G[B]]=[G[B],G[v]],i(G)},[s,i]),V=n.useCallback((v,T)=>{i(s.map(B=>{if(B.id!==v)return B;const G=B.traits.some(se=>se.trait===T);return{...B,traits:G?B.traits.filter(se=>se.trait!==T):[...B.traits,{trait:T}]}}))},[s,i]);return e.jsxs("aside",{className:"wf-column-panel","data-testid":"wf-column-panel",children:[e.jsxs("header",{className:"wf-column-panel-header",children:[e.jsx("h3",{children:p("workflowColumns.title","Columns")}),e.jsxs("button",{className:"wf-column-add",onClick:ue,disabled:g,title:g?p("workflowColumns.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,children:[e.jsx(Re,{size:13})," ",p("workflowColumns.add","Add column")]})]}),C.length>0&&e.jsx("div",{className:"wf-column-panel-errors",role:"alert",children:C.map((v,T)=>e.jsxs("p",{className:"wf-column-violation",children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",v.message]},`${v.code}-${T}`))}),s.length===0?e.jsx("p",{className:"wf-column-panel-empty",children:p("workflowColumns.empty","No columns yet. Add a column to place nodes into board lanes.")}):e.jsx("ul",{className:"wf-column-list",children:s.map((v,T)=>{const B=z(v.id),G=v.agent?.agentId,se=G?j.get(G):void 0,fe=!!G&&!y&&!w&&!se,ie=se?.name??(fe?p("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:G??""}):G);return e.jsxs("li",{className:`wf-column-item${B.length?" wf-column-item--error":""}`,"data-testid":`wf-column-${v.id}`,"data-column-error":B.length?"true":void 0,children:[e.jsxs("div",{className:"wf-column-item-head",children:[e.jsx("input",{className:"wf-column-name","aria-label":p("workflowColumns.nameLabel","Column name"),value:v.name,disabled:g,onChange:X=>U(v.id,X.target.value)}),G&&e.jsxs("span",{className:`wf-column-agent-badge${fe?" wf-column-agent-badge--stale":""}`,"data-testid":`wf-column-agent-badge-${v.id}`,title:v.agent?.mode==="override"?p("workflowColumns.agentBadgeOverride","Column agent (override)"):p("workflowColumns.agentBadgeDefer","Column agent (defer)"),children:[e.jsx(Ka,{size:11,"aria-hidden":!0})," ",ie]}),e.jsxs("div",{className:"wf-column-item-actions",children:[e.jsx("button",{className:"wf-column-move","aria-label":p("workflowColumns.moveUp","Move column up"),disabled:g||T===0,onClick:()=>te(T,-1),children:e.jsx(Ya,{size:13})}),e.jsx("button",{className:"wf-column-move","aria-label":p("workflowColumns.moveDown","Move column down"),disabled:g||T===s.length-1,onClick:()=>te(T,1),children:e.jsx(Ae,{size:13})}),e.jsx("button",{className:"wf-column-remove","aria-label":p("workflowColumns.remove","Remove column"),disabled:g,onClick:()=>Y(v.id),children:e.jsx(ve,{size:13})})]})]}),B.map((X,ne)=>e.jsxs("p",{className:"wf-column-violation",role:"alert",children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",X.message]},`${X.code}-${ne}`)),e.jsxs("div",{className:"wf-column-traits",children:[e.jsx("span",{className:"wf-column-traits-label",children:p("workflowColumns.traits","Traits")}),e.jsx("div",{className:"wf-column-trait-options",children:R.map(X=>{const ne=v.traits.some(re=>re.trait===X.id);return e.jsxs("label",{className:"wf-column-trait",title:X.description,children:[e.jsx("input",{type:"checkbox",checked:ne,disabled:g,onChange:()=>V(v.id,X.id)}),e.jsx("span",{children:X.name})]},X.id)})})]}),e.jsxs("div",{className:"wf-column-agent",children:[e.jsx("span",{className:"wf-column-agent-label",children:p("workflowColumns.agent","Column agent")}),e.jsxs("select",{className:"wf-column-agent-select","data-testid":`wf-column-agent-select-${v.id}`,"aria-label":p("workflowColumns.agentLabel","Column agent"),value:G??"",disabled:A,title:g?p("workflowColumns.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,onChange:X=>b(v.id,X.target.value),children:[e.jsx("option",{value:"",children:p("workflowColumns.agentNone","(none)")}),fe&&G&&e.jsx("option",{value:G,children:p("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:G})}),O.map(X=>e.jsx("option",{value:X.id,children:X.name},X.id))]}),w&&e.jsxs("p",{className:"wf-column-agent-error",role:"alert",children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",w]}),fe&&e.jsxs("p",{className:"wf-column-agent-stale",role:"alert","data-testid":`wf-column-agent-stale-${v.id}`,children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",p("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:G??""})]}),G&&e.jsxs("div",{className:"wf-column-agent-mode",role:"radiogroup","aria-label":p("workflowColumns.agentMode","Agent mode"),children:[e.jsxs("label",{className:"wf-column-agent-mode-option",children:[e.jsx("input",{type:"radio",name:`wf-column-agent-mode-${v.id}`,checked:(v.agent?.mode??"defer")==="defer",disabled:A,onChange:()=>M(v.id,"defer")}),e.jsx("span",{title:p("workflowColumns.agentModeDeferHint","Column agent applies only when the work carries no agent/model settings of its own"),children:p("workflowColumns.agentModeDefer","Defer")})]}),e.jsxs("label",{className:"wf-column-agent-mode-option",children:[e.jsx("input",{type:"radio",name:`wf-column-agent-mode-${v.id}`,checked:v.agent?.mode==="override",disabled:A,onChange:()=>M(v.id,"override")}),e.jsx("span",{title:p("workflowColumns.agentModeOverrideHint","Column agent supersedes node- and task-level agent/model settings"),children:p("workflowColumns.agentModeOverride","Override")})]})]})]})]},v.id)})})]})}const rl=["string","text","number","boolean","enum","multi-enum","date","url"],Fs={string:["input"],text:["textarea","input"],number:["input"],boolean:["toggle"],enum:["select","radio","chips"],"multi-enum":["chips"],date:["input"],url:["input"]},dl=["#4f7cff","#22c55e","#f59e0b","#ef4444","#a855f7","#06b6d4","#ec4899","#64748b"];function Ft(s){return s==="enum"||s==="multi-enum"}function cl(s){return s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}let Ps=0;function ul(){return Ps+=1,`field-${Date.now().toString(36)}-${Ps}`}function fl({field:s}){const i=n.useMemo(()=>{if(Ft(s.type)){const g=s.options?.[0];return g?s.type==="multi-enum"?{node:e.jsx("span",{className:"card-field-badge card-field-badge--multi",title:s.name,children:(s.options??[]).slice(0,2).map(d=>e.jsx("span",{className:"card-field-badge-token",style:d.color?{backgroundColor:d.color,borderColor:d.color,color:"#fff"}:void 0,children:d.label},d.value))})}:{node:e.jsx("span",{className:"card-field-badge card-field-badge--enum",title:`${s.name}: ${g.label}`,style:g.color?{backgroundColor:g.color,borderColor:g.color,color:"#fff"}:void 0,children:g.label})}:null}if(s.type==="boolean")return{node:e.jsx("span",{className:"card-field-badge card-field-badge--boolean",title:s.name,children:s.name})};const r=s.type==="number"?"42":s.type==="date"?"2026-06-04":s.type==="url"?"example.com":s.name;return{node:e.jsx("span",{className:"card-field-badge",title:s.name,children:r})}},[s]);return i?e.jsx("div",{className:"wf-field-preview","data-testid":`wf-field-preview-${s.id}`,children:e.jsx("div",{className:"card-field-badges",children:i.node})}):null}function Ms({fields:s,onChange:i,readOnly:r,addToast:g}){const{t:d}=je("app"),[k,I]=n.useState(null),p=n.useCallback((c,S)=>{i(s.map(j=>j.id===c?{...j,...S}:j))},[s,i]),R=n.useCallback(()=>{const c=ul();i([...s,{id:c,name:d("workflowFields.newFieldName","New field"),type:"string"}])},[s,i,d]),P=n.useCallback(c=>{i(s.filter(S=>S.id!==c))},[s,i]),O=n.useCallback((c,S)=>{const j=cl(S);if(j){if(j!==c&&s.some($=>$.id===j)){g(d("workflowFields.duplicateId","A field with that id already exists"),"error");return}p(c,{id:j})}},[s,p,g,d]),D=n.useCallback((c,S)=>{const j=s.find(b=>b.id===c);if(!j)return;const $={type:S};Ft(S)?(!j.options||j.options.length===0)&&($.options=[{value:"option-1",label:d("workflowFields.newOptionLabel","Option 1")}]):$.options=void 0,j.render?.widget&&!Fs[S].includes(j.render.widget)&&($.render={...j.render,widget:void 0}),$.default=void 0,p(c,$)},[s,p,d]),y=n.useCallback((c,S)=>p(c,{options:S}),[p]),x=n.useCallback((c,S)=>{const j=!S||S.placement===void 0&&S.widget===void 0&&!S.badge;p(c,{render:j?void 0:S})},[p]),w=c=>{const S=b=>p(c.id,{default:b});if(c.type==="boolean")return e.jsxs("label",{className:"wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:c.default===!0,disabled:r,onChange:b=>S(b.target.checked)}),e.jsx("span",{children:d("workflowFields.defaultTrue","Default on")})]});if(Ft(c.type)){const b=c.type==="multi-enum"?Array.isArray(c.default)?c.default[0]??"":"":typeof c.default=="string"?c.default:"";return e.jsxs("select",{"aria-label":d("workflowFields.defaultLabel","Default value"),value:b,disabled:r,onChange:M=>{const A=M.target.value;if(A==="")return S(void 0);S(c.type==="multi-enum"?[A]:A)},children:[e.jsx("option",{value:"",children:d("workflowFields.noDefault","— none —")}),(c.options??[]).map(M=>e.jsx("option",{value:M.value,children:M.label},M.value))]})}const j=c.type==="number"?"number":c.type==="date"?"date":c.type==="url"?"url":"text",$=c.type==="number"?typeof c.default=="number"?String(c.default):"":typeof c.default=="string"?c.default:"";return e.jsx("input",{type:j,"aria-label":d("workflowFields.defaultLabel","Default value"),defaultValue:$,disabled:r,onBlur:b=>{const M=b.target.value;if(M==="")return S(void 0);S(c.type==="number"?Number(M):M)}})};return e.jsxs("aside",{className:"wf-fields-panel","data-testid":"wf-fields-panel",children:[e.jsxs("header",{className:"wf-fields-panel-header",children:[e.jsx("h3",{children:d("workflowFields.title","Fields")}),e.jsxs("button",{className:"wf-fields-add",onClick:R,disabled:r,title:r?d("workflowFields.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,children:[e.jsx(Re,{size:13})," ",d("workflowFields.add","Add field")]})]}),s.length===0?e.jsx("p",{className:"wf-fields-panel-empty",children:d("workflowFields.empty","No custom fields yet. Add a field to extend the task form and cards.")}):e.jsx("ul",{className:"wf-fields-list",children:s.map(c=>{const S=Fs[c.type],j=c.render?.placement??"detail",$=k===c.id;return e.jsxs("li",{className:"wf-field-item","data-testid":`wf-field-${c.id}`,children:[e.jsxs("div",{className:"wf-field-item-head",children:[e.jsx("input",{className:"wf-field-name","aria-label":d("workflowFields.nameLabel","Field name"),value:c.name,disabled:r,onChange:b=>p(c.id,{name:b.target.value})}),e.jsx("button",{className:"wf-field-remove","aria-label":d("workflowFields.remove","Remove field"),disabled:r,onClick:()=>P(c.id),children:e.jsx(ve,{size:13})})]}),e.jsx("div",{className:"wf-field-id-row",children:$?e.jsxs(e.Fragment,{children:[e.jsx("input",{className:"wf-field-id","aria-label":d("workflowFields.idLabel","Field id"),defaultValue:c.id,disabled:r,onBlur:b=>{O(c.id,b.target.value),I(null)}}),e.jsxs("p",{className:"wf-field-id-warn",role:"note",children:[e.jsx(ze,{size:11,"aria-hidden":!0})," ",d("workflowFields.idWarn","Changing the id discards values stored under the old id (remove + add).")]})]}):e.jsxs(e.Fragment,{children:[e.jsx("code",{className:"wf-field-id-static",children:c.id}),e.jsx("button",{className:"wf-field-id-edit",disabled:r,onClick:()=>I(c.id),children:d("workflowFields.editId","Edit id")})]})}),e.jsxs("div",{className:"wf-field-row",children:[e.jsxs("label",{className:"wf-field-sub",children:[e.jsx("span",{children:d("workflowFields.typeLabel","Type")}),e.jsx("select",{value:c.type,disabled:r,onChange:b=>D(c.id,b.target.value),children:rl.map(b=>e.jsx("option",{value:b,children:b},b))})]}),e.jsxs("label",{className:"wf-field--checkbox wf-field-required",children:[e.jsx("input",{type:"checkbox",checked:c.required===!0,disabled:r,onChange:b=>p(c.id,{required:b.target.checked||void 0})}),e.jsx("span",{children:d("workflowFields.required","Required")})]})]}),e.jsxs("label",{className:"wf-field-sub",children:[e.jsx("span",{children:d("workflowFields.default","Default")}),w(c)]}),Ft(c.type)&&e.jsxs("div",{className:"wf-field-options","data-testid":`wf-field-options-${c.id}`,children:[e.jsx("span",{className:"wf-field-options-label",children:d("workflowFields.options","Options")}),(c.options??[]).map((b,M)=>e.jsxs("div",{className:"wf-field-option-row",children:[e.jsx("input",{className:"wf-field-option-value","aria-label":d("workflowFields.optionValue","Option value"),value:b.value,disabled:r,onChange:A=>{const C=[...c.options??[]];C[M]={...b,value:A.target.value},y(c.id,C)}}),e.jsx("input",{className:"wf-field-option-label","aria-label":d("workflowFields.optionLabel","Option label"),value:b.label,disabled:r,onChange:A=>{const C=[...c.options??[]];C[M]={...b,label:A.target.value},y(c.id,C)}}),e.jsx("div",{className:"wf-field-option-colors",role:"group","aria-label":d("workflowFields.optionColor","Option color"),children:dl.map(A=>e.jsx("button",{type:"button",className:`wf-field-color-swatch${b.color===A?" is-active":""}`,style:{backgroundColor:A},"aria-label":A,"aria-pressed":b.color===A,disabled:r,onClick:()=>{const C=[...c.options??[]];C[M]={...b,color:b.color===A?void 0:A},y(c.id,C)}},A))}),e.jsx("button",{className:"wf-field-option-remove","aria-label":d("workflowFields.removeOption","Remove option"),disabled:r,onClick:()=>y(c.id,(c.options??[]).filter((A,C)=>C!==M)),children:e.jsx(ve,{size:12})})]},M)),e.jsxs("button",{className:"wf-field-option-add",disabled:r,onClick:()=>{const b=(c.options??[]).length+1;y(c.id,[...c.options??[],{value:`option-${b}`,label:d("workflowFields.optionN","Option {{n}}",{n:b})}])},children:[e.jsx(Re,{size:12})," ",d("workflowFields.addOption","Add option")]})]}),e.jsxs("div",{className:"wf-field-render",children:[e.jsxs("label",{className:"wf-field-sub",children:[e.jsx("span",{children:d("workflowFields.placement","Placement")}),e.jsxs("select",{value:j,disabled:r,onChange:b=>x(c.id,{...c.render,placement:b.target.value}),children:[e.jsx("option",{value:"detail",children:d("workflowFields.placementDetail","Detail (inline)")}),e.jsx("option",{value:"detail-section",children:d("workflowFields.placementSection","Detail section")}),e.jsx("option",{value:"card",children:d("workflowFields.placementCard","Card badge")})]})]}),e.jsxs("label",{className:"wf-field-sub",children:[e.jsx("span",{children:d("workflowFields.widget","Widget")}),e.jsxs("select",{value:c.render?.widget??"",disabled:r,onChange:b=>x(c.id,{...c.render,widget:b.target.value||void 0}),children:[e.jsx("option",{value:"",children:d("workflowFields.widgetDefault","Default")}),S.map(b=>e.jsx("option",{value:b,children:b},b))]})]}),e.jsxs("label",{className:"wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:c.render?.badge===!0,disabled:r,onChange:b=>x(c.id,{...c.render,badge:b.target.checked||void 0})}),e.jsx("span",{children:d("workflowFields.badge","Render as badge")})]})]}),j==="card"&&e.jsx(fl,{field:c})]},c.id)})})]})}const pl={planningProvider:{group:"models",label:"Plan/Triage provider",description:"Provider used when planning or triaging tasks."},planningModelId:{group:"models",label:"Plan/Triage model",description:"Model used when planning or triaging tasks."},planningFallbackProvider:{group:"models",label:"Plan/Triage fallback provider"},planningFallbackModelId:{group:"models",label:"Plan/Triage fallback model"},executionProvider:{group:"models",label:"Executor provider",description:"Provider used by task implementation agents."},executionModelId:{group:"models",label:"Executor model",description:"Model used by task implementation agents."},validatorProvider:{group:"models",label:"Reviewer provider",description:"Provider used by review and validation agents."},validatorModelId:{group:"models",label:"Reviewer model",description:"Model used by review and validation agents."},validatorFallbackProvider:{group:"models",label:"Reviewer fallback provider"},validatorFallbackModelId:{group:"models",label:"Reviewer fallback model"},requirePrApproval:{group:"review",label:"Require PR approval"},requirePlanApproval:{group:"review",label:"Require plan approval"},reviewHandoffPolicy:{group:"review",label:"Review handoff policy"},maxReviewerContextRetries:{group:"review",label:"Reviewer context retries"},maxReviewerFallbackRetries:{group:"review",label:"Reviewer fallback retries"},reflectionEnabled:{group:"review",label:"Reflection enabled"},planReviewMaxRevisions:{group:"review",label:"Plan Review revision cap",description:"Leave empty for unbounded automatic Plan Review/spec revision; set 0 to disable automatic revision."},codeReviewMaxRevisions:{group:"review",label:"Code Review revision cap",description:"Leave empty for unbounded automatic Code Review remediation; set 0 to disable automatic revision."},workflowStepTimeoutMs:{group:"steps",label:"Step timeout"},workflowStepScopeEnforcement:{group:"steps",label:"Step scope enforcement"},planOnlyScopeLeakEnforcement:{group:"steps",label:"Plan-only scope leak enforcement"},workflowRevisionForkOnScopeMismatch:{group:"steps",label:"Fork revision on scope mismatch"},strictScopeEnforcement:{group:"steps",label:"Strict scope enforcement"},runStepsInNewSessions:{group:"steps",label:"Run steps in new sessions"},maxParallelSteps:{group:"steps",label:"Max parallel steps"},buildRetryCount:{group:"steps",label:"Build retry count"},verificationFixRetries:{group:"steps",label:"Verification fix retries"},maxPostReviewFixes:{group:"steps",label:"Post-review fix passes"}},ml=["models","review","steps","advanced"],wl={models:"Models",review:"Review & Approval",steps:"Step Execution",advanced:"Advanced"};function ta(s){return pl[s.id]??{group:"advanced",label:s.name,description:s.description}}function hl(s){const i=new Map;for(const r of s){const g=ta(r).group,d=i.get(g)??[];d.push(r),i.set(g,d)}return ml.map(r=>({group:r,settings:i.get(r)??[]})).filter(r=>r.settings.length>0)}function Xe({htmlFor:s,label:i,help:r,error:g,scope:d,disabled:k,clearable:I,onClear:p,children:R}){const{t:P}=je("app");return e.jsxs("div",{className:`settings-field-row${k?" is-disabled":""}`,children:[e.jsxs("div",{className:"settings-field-row-head",children:[e.jsx("label",{className:"settings-field-row-label",htmlFor:s,children:i}),d&&e.jsx("span",{className:`settings-field-row-scope settings-field-row-scope--${d}`,"data-testid":"settings-field-row-scope",children:d})]}),e.jsxs("div",{className:"settings-field-row-control",children:[R,I&&e.jsx("button",{type:"button",className:"settings-field-row-clear","aria-label":P("settings.clearToDefault","Reset to default"),title:P("settings.clearToDefault","Reset to default"),disabled:k,onClick:p,children:e.jsx(Ks,{size:13,"aria-hidden":!0})})]}),r&&e.jsx("p",{className:"settings-field-row-help",children:r}),g&&e.jsx("p",{className:"settings-field-row-error",role:"alert",children:g})]})}function gl({descriptor:s,value:i,onChange:r,error:g,clearable:d}){const{key:k,label:I,help:p,scope:R,disabled:P}=s;return e.jsx(Xe,{htmlFor:k,label:I,help:p,error:g,scope:R,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("label",{className:"settings-toggle",children:e.jsx("input",{id:k,type:"checkbox",checked:i===!0,disabled:P,onChange:O=>r(O.target.checked)})})})}function bl({descriptor:s,value:i,onChange:r,error:g,clearable:d}){const{key:k,label:I,help:p,scope:R,disabled:P,min:O,max:D,step:y,placeholder:x}=s;return e.jsx(Xe,{htmlFor:k,label:I,help:p,error:g,scope:R,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("input",{id:k,className:"settings-number",type:"number",value:i??"",min:O,max:D,step:y,placeholder:x,disabled:P,onChange:w=>{const c=w.target.value;if(c==="")return r(null);const S=Number(c);Number.isNaN(S)||r(S)}})})}function Is({descriptor:s,value:i,onChange:r,error:g,clearable:d}){const{key:k,label:I,help:p,scope:R,disabled:P,options:O}=s;return e.jsx(Xe,{htmlFor:k,label:I,help:p,error:g,scope:R,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("select",{id:k,className:"settings-select",value:i??"",disabled:P,onChange:D=>r(D.target.value),children:O.map(D=>e.jsx("option",{value:D.value,children:D.label},D.value))})})}function kl({descriptor:s,value:i,onChange:r,error:g,clearable:d}){const{key:k,label:I,help:p,scope:R,disabled:P,placeholder:O}=s;return e.jsx(Xe,{htmlFor:k,label:I,help:p,error:g,scope:R,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("input",{id:k,className:"settings-text",type:"text",value:i??"",placeholder:O,disabled:P,onChange:D=>r(D.target.value)})})}function xl({descriptor:s,value:i,onChange:r,error:g,clearable:d}){const{key:k,label:I,help:p,scope:R,disabled:P,placeholder:O}=s;return e.jsx(Xe,{htmlFor:k,label:I,help:p,error:g,scope:R,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("textarea",{id:k,className:"settings-textarea",value:i??"",placeholder:O,disabled:P,rows:3,onChange:D=>r(D.target.value)})})}const vl=["string","text","number","boolean","enum","multi-enum"],Os={string:["input"],text:["textarea","input"],number:["input"],boolean:["toggle"],enum:["select","radio","chips"],"multi-enum":["chips"]},jl=["#4f7cff","#22c55e","#f59e0b","#ef4444","#a855f7","#06b6d4","#ec4899","#64748b"];function so(s){return s==="enum"||s==="multi-enum"}function Nl(s){return s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}let Ds=0;function yl(){return Ds+=1,`setting-${Date.now().toString(36)}-${Ds}`}function Cl({settings:s,onChange:i,readOnly:r,addToast:g}){const{t:d}=je("app"),[k,I]=n.useState(null),p=n.useCallback((w,c)=>{i(s.map(S=>S.id===w?{...S,...c}:S))},[s,i]),R=n.useCallback(()=>{i([...s,{id:yl(),name:d("workflowSettings.newSettingName","New setting"),type:"string"}])},[s,i,d]),P=n.useCallback(w=>i(s.filter(c=>c.id!==w)),[s,i]),O=n.useCallback((w,c)=>{const S=Nl(c);if(S){if(S!==w&&s.some(j=>j.id===S)){g(d("workflowSettings.duplicateId","A setting with that id already exists"),"error");return}p(w,{id:S})}},[s,p,g,d]),D=n.useCallback((w,c)=>{const S=s.find($=>$.id===w);if(!S)return;const j={type:c};so(c)?(!S.options||S.options.length===0)&&(j.options=[{value:"option-1",label:d("workflowSettings.newOptionLabel","Option 1")}]):j.options=void 0,S.render?.widget&&!Os[c].includes(S.render.widget)&&(j.render=void 0),j.default=void 0,p(w,j)},[s,p,d]),y=n.useCallback((w,c)=>p(w,{options:c}),[p]),x=w=>{const c=$=>p(w.id,{default:$});if(w.type==="boolean")return e.jsxs("label",{className:"wf-setting--checkbox",children:[e.jsx("input",{type:"checkbox",checked:w.default===!0,disabled:r,onChange:$=>c($.target.checked)}),e.jsx("span",{children:d("workflowSettings.defaultTrue","Default on")})]});if(so(w.type)){const $=w.type==="multi-enum"?Array.isArray(w.default)?w.default[0]??"":"":typeof w.default=="string"?w.default:"";return e.jsxs("select",{"aria-label":d("workflowSettings.defaultLabel","Default value"),value:$,disabled:r,onChange:b=>{const M=b.target.value;if(M==="")return c(void 0);c(w.type==="multi-enum"?[M]:M)},children:[e.jsx("option",{value:"",children:d("workflowSettings.noDefault","— none —")}),(w.options??[]).map(b=>e.jsx("option",{value:b.value,children:b.label},b.value))]})}const S=w.type==="number"?"number":"text",j=w.type==="number"?typeof w.default=="number"?String(w.default):"":typeof w.default=="string"?w.default:"";return e.jsx("input",{type:S,"aria-label":d("workflowSettings.defaultLabel","Default value"),defaultValue:j,disabled:r,onBlur:$=>{const b=$.target.value;if(b==="")return c(void 0);c(w.type==="number"?Number(b):b)}})};return e.jsxs("div",{className:"wf-settings-tabpanel","data-testid":"wf-settings-definitions",children:[e.jsx("div",{className:"wf-settings-tabpanel-head",children:e.jsxs("button",{className:"wf-settings-add",onClick:R,disabled:r,title:r?d("workflowSettings.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,children:[e.jsx(Re,{size:13})," ",d("workflowSettings.add","Add setting")]})}),r&&e.jsx("p",{className:"wf-settings-note wf-settings-note--info",role:"note",children:d("workflowSettings.builtinDefinitionsReadOnly","Built-in workflow — declarations are read-only. Values are editable below.")}),s.length===0?e.jsx("p",{className:"wf-settings-empty",children:d("workflowSettings.empty","No settings declared yet. Add a setting to expose a typed, per-project knob.")}):e.jsx("ul",{className:"wf-settings-list",children:s.map(w=>{const c=Os[w.type],S=k===w.id;return e.jsxs("li",{className:"wf-setting-item","data-testid":`wf-setting-${w.id}`,children:[e.jsxs("div",{className:"wf-setting-item-head",children:[e.jsx("input",{className:"wf-setting-name","aria-label":d("workflowSettings.nameLabel","Setting name"),value:w.name,disabled:r,onChange:j=>p(w.id,{name:j.target.value})}),e.jsx("button",{className:"wf-setting-remove","aria-label":d("workflowSettings.remove","Remove setting"),disabled:r,onClick:()=>P(w.id),children:e.jsx(ve,{size:13})})]}),e.jsx("div",{className:"wf-setting-id-row",children:S?e.jsxs(e.Fragment,{children:[e.jsx("input",{className:"wf-setting-id","aria-label":d("workflowSettings.idLabel","Setting id"),defaultValue:w.id,disabled:r,onBlur:j=>{O(w.id,j.target.value),I(null)}}),e.jsxs("p",{className:"wf-setting-id-warn",role:"note",children:[e.jsx(ze,{size:11,"aria-hidden":!0})," ",d("workflowSettings.idWarn","Changing the id discards values stored under the old id (remove + add).")]})]}):e.jsxs(e.Fragment,{children:[e.jsx("code",{className:"wf-setting-id-static",children:w.id}),e.jsx("button",{className:"wf-setting-id-edit",disabled:r,onClick:()=>I(w.id),children:d("workflowSettings.editId","Edit id")})]})}),e.jsxs("div",{className:"wf-setting-row",children:[e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.typeLabel","Type")}),e.jsx("select",{value:w.type,disabled:r,onChange:j=>D(w.id,j.target.value),children:vl.map(j=>e.jsx("option",{value:j,children:j},j))})]}),e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.widget","Widget")}),e.jsxs("select",{value:w.render?.widget??"",disabled:r,onChange:j=>p(w.id,{render:j.target.value?{widget:j.target.value}:void 0}),children:[e.jsx("option",{value:"",children:d("workflowSettings.widgetDefault","Default")}),c.map(j=>e.jsx("option",{value:j,children:j},j))]})]})]}),e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.default","Default")}),x(w)]}),e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.description","Description")}),e.jsx("input",{"aria-label":d("workflowSettings.descriptionLabel","Setting description"),value:w.description??"",disabled:r,onChange:j=>p(w.id,{description:j.target.value||void 0})})]}),so(w.type)&&e.jsxs("div",{className:"wf-setting-options","data-testid":`wf-setting-options-${w.id}`,children:[e.jsx("span",{className:"wf-setting-options-label",children:d("workflowSettings.options","Options")}),(w.options??[]).map((j,$)=>e.jsxs("div",{className:"wf-setting-option-row",children:[e.jsx("input",{className:"wf-setting-option-value","aria-label":d("workflowSettings.optionValue","Option value"),value:j.value,disabled:r,onChange:b=>{const M=[...w.options??[]];M[$]={...j,value:b.target.value},y(w.id,M)}}),e.jsx("input",{className:"wf-setting-option-label","aria-label":d("workflowSettings.optionLabel","Option label"),value:j.label,disabled:r,onChange:b=>{const M=[...w.options??[]];M[$]={...j,label:b.target.value},y(w.id,M)}}),e.jsx("div",{className:"wf-setting-option-colors",role:"group","aria-label":d("workflowSettings.optionColor","Option color"),children:jl.map(b=>e.jsx("button",{type:"button",className:`wf-setting-color-swatch${j.color===b?" is-active":""}`,style:{backgroundColor:b},"aria-label":b,"aria-pressed":j.color===b,disabled:r,onClick:()=>{const M=[...w.options??[]];M[$]={...j,color:j.color===b?void 0:b},y(w.id,M)}},b))}),e.jsx("button",{className:"wf-setting-option-remove","aria-label":d("workflowSettings.removeOption","Remove option"),disabled:r,onClick:()=>y(w.id,(w.options??[]).filter((b,M)=>M!==$)),children:e.jsx(ve,{size:12})})]},$)),e.jsxs("button",{className:"wf-setting-option-add",disabled:r,onClick:()=>{const j=(w.options??[]).length+1;y(w.id,[...w.options??[],{value:`option-${j}`,label:d("workflowSettings.optionN","Option {{n}}",{n:j})}])},children:[e.jsx(Re,{size:12})," ",d("workflowSettings.addOption","Add option")]})]})]},w.id)})})]})}function Sl(s){if(typeof s=="string")return s;try{return JSON.stringify(s)}catch{return String(s)}}function El(s,i){return Object.is(s,i)?!0:Array.isArray(s)&&Array.isArray(i)?s.length===i.length&&s.every((r,g)=>Object.is(r,i[g])):!1}const Al=[{id:"planning",providerId:"planningProvider",modelId:"planningModelId",label:"Plan/Triage Model",help:"Provider and model used when planning or triaging tasks. Leave unset to inherit from the default lane."},{id:"execution",providerId:"executionProvider",modelId:"executionModelId",label:"Executor Model",help:"Provider and model used by task implementation agents. Leave unset to inherit from the default lane."},{id:"validator",providerId:"validatorProvider",modelId:"validatorModelId",label:"Reviewer Model",help:"Provider and model used by review and validation agents. Leave unset to inherit from the default lane."},{id:"planning-fallback",providerId:"planningFallbackProvider",modelId:"planningFallbackModelId",label:"Planning Fallback Model",help:"Fallback provider and model used when the primary Plan/Triage model cannot be used."},{id:"validator-fallback",providerId:"validatorFallbackProvider",modelId:"validatorFallbackModelId",label:"Reviewer Fallback Model",help:"Fallback provider and model used when the primary Reviewer model cannot be used."}];function Rl(s){if(!s)return null;const i=s.indexOf("/");return i<=0||i===s.length-1?null:{provider:s.slice(0,i),modelId:s.slice(i+1)}}function Fl({workflowId:s,settings:i,boundProjectId:r,currentProjectId:g,addToast:d}){const{t:k}=je("app"),[I,p]=n.useState(null),[R,P]=n.useState(!1),[O,D]=n.useState({}),[y,x]=n.useState({}),[w,c]=n.useState(!1),[S,j]=n.useState(!1),[$,b]=n.useState([]),[M,A]=n.useState(!1),[C,z]=n.useState([]),[ue,U]=n.useState([]),Y=n.useRef(0),te=n.useRef(0),V=n.useMemo(()=>new Map(i.map(m=>[m.id,m])),[i]),v=n.useMemo(()=>Al.filter(m=>{const _=V.get(m.providerId),H=V.get(m.modelId);return _?.type==="string"&&H?.type==="string"}),[V]),T=n.useMemo(()=>new Set(v.flatMap(m=>[m.providerId,m.modelId])),[v]),B=r!==void 0&&g!==void 0&&g!==r,G=n.useCallback(async()=>{if(r===void 0)return;const m=++Y.current;P(!0);try{const _=await Ja(s,r);Y.current===m&&(p(_),D({}),x({}))}catch{Y.current===m&&d(k("workflowSettings.loadFailed","Failed to load setting values"),"error")}finally{Y.current===m&&P(!1)}},[s,r,d,k]);if(n.useEffect(()=>{G()},[G]),n.useEffect(()=>{if(r===void 0||v.length===0){b([]),z([]),U([]),A(!1);return}const m=++te.current;A(!0),Rt().then(_=>{te.current===m&&(b(_.models??[]),z(_.favoriteProviders??[]),U(_.favoriteModels??[]))}).catch(()=>{te.current===m&&(b([]),z([]),U([]),d(k("workflowSettings.modelsLoadFailed","Failed to load available models"),"error"))}).finally(()=>{te.current===m&&A(!1)})},[r,v.length,d,k]),r===void 0)return e.jsx("div",{className:"wf-settings-tabpanel","data-testid":"wf-settings-values",children:e.jsx("p",{className:"wf-settings-note wf-settings-note--info",role:"note",children:k("workflowSettings.requiresProject","Open a project to view and edit per-project setting values.")})});const se=m=>{if(Object.prototype.hasOwnProperty.call(O,m.id)){const _=O[m.id];return _===null?m.default:_}return I?.effective?.[m.id]??m.default},fe=m=>Object.prototype.hasOwnProperty.call(O,m.id)?O[m.id]!==null:I?Object.prototype.hasOwnProperty.call(I.stored,m.id):!1,ie=(m,_)=>{D(H=>({...H,[m]:_})),x(H=>{if(!H[m])return H;const Q={...H};return delete Q[m],Q})},X=m=>ie(m,null),ne=(m,_)=>{const H=Rl(_);D(Q=>({...Q,[m.providerId]:H?.provider??null,[m.modelId]:H?.modelId??null})),x(Q=>{if(!Q[m.providerId]&&!Q[m.modelId])return Q;const oe={...Q};return delete oe[m.providerId],delete oe[m.modelId],oe})},re=Object.keys(O).length>0,Ne=n.useCallback(async()=>{if(!re)return;const m={...O},_=Object.keys(m);c(!0);try{const H=await os(s,m,r);p(H),D(Q=>{const oe={...Q};for(const K of _)El(Q[K],m[K])&&delete oe[K];return oe}),x({}),d(k("workflowSettings.valuesSaved","Setting values saved"),"success")}catch(H){if(H instanceof Ys&&H.status===400&&H.details){const Q=H.details.rejections??[];if(Q.length>0){const oe={};for(const K of Q)oe[K.settingId]=K;x(oe),d(k("workflowSettings.valuesRejected","Some values were rejected — see the highlighted fields"),"error");return}}d(k("workflowSettings.saveFailed","Failed to save setting values"),"error")}finally{c(!1)}},[re,s,O,r,d,k]),o=m=>{const _=V.get(m);return _?se(_):void 0},q=m=>{const _=V.get(m);return _?fe(_):!1},de=m=>{const _=o(m.providerId),H=o(m.modelId),Q=typeof _=="string"&&typeof H=="string"?`${_}/${H}`:"",oe=y[m.providerId]?.message??y[m.modelId]?.message,K=q(m.providerId)||q(m.modelId),ge=M||$.length===0,J=!M&&$.length===0?` ${k("workflowSettings.noModelsAvailable","No models are available. Configure authentication before selecting a workflow model.")}`:"";return e.jsxs("div",{className:"wf-settings-value-item","data-testid":`wf-settings-value-${m.id}`,children:[e.jsx(Xe,{htmlFor:`wf-model-lane-${m.id}`,label:m.label,help:`${m.help}${J}`,error:oe,scope:"project",disabled:M,clearable:K,onClear:()=>ne(m,""),children:e.jsx(ro,{id:`wf-model-lane-${m.id}`,label:m.label,models:$,value:Q,onChange:Ce=>ne(m,Ce),placeholder:k("workflowSettings.selectModel","Select a model…"),defaultOptionLabel:k("workflowSettings.useInheritedModel","Use inherited/default model"),disabled:ge,favoriteProviders:C,favoriteModels:ue})}),K&&e.jsx("span",{className:"wf-settings-customized","data-testid":`wf-settings-customized-${m.id}`,children:k("workflowSettings.customized","Customized")})]},m.id)},ye=m=>{const _=se(m),H=y[m.id]?.message,Q=fe(m),oe=ta(m),K={key:m.id,label:oe.label,help:oe.description??m.description,scope:"project"},ge=Q;switch(m.type){case"boolean":return e.jsx(gl,{descriptor:K,value:_===!0,error:H,clearable:ge,onChange:J=>J===null?X(m.id):ie(m.id,J)});case"number":return e.jsx(bl,{descriptor:K,value:typeof _=="number"?_:null,error:H,clearable:ge,onChange:J=>J===null?X(m.id):ie(m.id,J)});case"enum":return e.jsx(Is,{descriptor:{...K,options:(m.options??[]).map(J=>({value:J.value,label:J.label}))},value:typeof _=="string"?_:null,error:H,clearable:ge,onChange:J=>J===null?X(m.id):ie(m.id,J)});case"multi-enum":{const J=Array.isArray(_)?_[0]??null:null;return e.jsx(Is,{descriptor:{...K,options:(m.options??[]).map(Ce=>({value:Ce.value,label:Ce.label}))},value:J,error:H,clearable:ge,onChange:Ce=>Ce===null?X(m.id):ie(m.id,[Ce])})}case"text":return e.jsx(xl,{descriptor:K,value:typeof _=="string"?_:null,error:H,clearable:ge,onChange:J=>J===null||J===""?X(m.id):ie(m.id,J)});case"string":default:return e.jsx(kl,{descriptor:K,value:typeof _=="string"?_:null,error:H,clearable:ge,onChange:J=>J===null||J===""?X(m.id):ie(m.id,J)})}},he=I?.orphaned??[],le=n.useCallback(async m=>{try{const _=await os(s,{[m]:null},r);p(_),d(k("workflowSettings.orphanDeleted","Orphaned value removed"),"success")}catch{d(k("workflowSettings.saveFailed","Failed to save setting values"),"error")}},[s,r,d,k]);return e.jsxs("div",{className:"wf-settings-tabpanel","data-testid":"wf-settings-values",children:[B&&e.jsxs("p",{className:"wf-settings-note wf-settings-note--warn",role:"note","data-testid":"wf-settings-stale-notice",children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",k("workflowSettings.staleContext","Values shown are for project {{project}} — reopen the editor to edit values for the current project.",{project:r})]}),e.jsx("div",{className:"wf-settings-values-head",children:e.jsxs("button",{className:"wf-settings-save-values",onClick:Ne,disabled:!re||w||B,"data-testid":"wf-settings-save-values",children:[e.jsx(io,{size:13})," ",k("workflowSettings.saveValues","Save values")]})}),i.length===0?e.jsx("p",{className:"wf-settings-empty",children:R?e.jsx(Xa,{label:k("workflowSettings.loading","Loading…")}):k("workflowSettings.noDeclarations","This workflow declares no settings, so there are no values to edit.")}):e.jsx("div",{className:"wf-settings-values-list",children:hl(i).map(({group:m,settings:_})=>{const H=new Set(_.map(K=>K.id)),Q=m==="models"?v.filter(K=>H.has(K.providerId)&&H.has(K.modelId)):[],oe=_.filter(K=>!T.has(K.id));return e.jsxs("section",{className:"wf-settings-value-group","data-testid":`wf-settings-group-${m}`,children:[e.jsx("h4",{className:"wf-settings-value-group-title",children:k(`workflowSettings.group.${m}`,wl[m])}),Q.map(K=>de(K)),oe.map(K=>e.jsxs("div",{className:"wf-settings-value-item","data-testid":`wf-settings-value-${K.id}`,children:[ye(K),fe(K)&&e.jsx("span",{className:"wf-settings-customized","data-testid":`wf-settings-customized-${K.id}`,children:k("workflowSettings.customized","Customized")})]},K.id))]},m)})}),he.length>0&&e.jsxs("div",{className:"wf-settings-orphaned","data-testid":"wf-settings-orphaned",children:[e.jsxs("button",{className:"wf-settings-orphaned-toggle",onClick:()=>j(m=>!m),"aria-expanded":S,children:[S?e.jsx(Ae,{size:13}):e.jsx(Me,{size:13})," ",k("workflowSettings.orphanedTitle","Orphaned values ({{count}})",{count:he.length})]}),S&&e.jsxs("div",{className:"wf-settings-orphaned-body",children:[e.jsx("p",{className:"wf-settings-note wf-settings-note--muted",role:"note",children:k("workflowSettings.orphanedNote","These stored values no longer match a current declaration (the setting was retyped or removed). They are ignored by the engine; delete them to clean up.")}),e.jsx("ul",{className:"wf-settings-orphaned-list",children:he.map(m=>e.jsxs("li",{className:"wf-settings-orphaned-row","data-testid":`wf-settings-orphan-${m.id}`,children:[e.jsx("code",{className:"wf-settings-orphan-id",children:m.id}),e.jsx("span",{className:"wf-settings-orphan-value",children:Sl(m.value)}),e.jsx("button",{className:"wf-settings-orphan-delete","aria-label":k("workflowSettings.deleteOrphan","Delete orphaned value"),disabled:B||w,onClick:()=>le(m.id),children:e.jsx(ve,{size:12})})]},m.id))})]})]}),i.length>0&&e.jsxs("p",{className:"wf-settings-reset-hint",role:"note",children:[e.jsx(Ks,{size:11,"aria-hidden":!0})," ",k("workflowSettings.clearHint","Use the reset control on a row to clear a value back to its declaration default.")]})]})}function Ts({workflowId:s,settings:i,onChange:r,readOnly:g,projectId:d,addToast:k,initialTab:I}){const{t:p}=je("app"),[R,P]=n.useState(()=>I??(i.length>0?"values":"definitions")),O=n.useRef({workflowId:s,projectId:d});O.current.workflowId!==s&&(O.current={workflowId:s,projectId:d});const D=O.current.projectId;return e.jsxs("aside",{className:"wf-settings-panel","data-testid":"wf-settings-panel",children:[e.jsx("header",{className:"wf-settings-panel-header",children:e.jsx("h3",{children:p("workflowSettings.title","Settings")})}),e.jsxs("div",{className:"wf-settings-tabs",role:"tablist",children:[e.jsx("button",{role:"tab","aria-selected":R==="definitions",className:`wf-settings-tab${R==="definitions"?" is-active":""}`,onClick:()=>P("definitions"),"data-testid":"wf-settings-tab-definitions",children:p("workflowSettings.definitionsTab","Definitions")}),e.jsx("button",{role:"tab","aria-selected":R==="values",className:`wf-settings-tab${R==="values"?" is-active":""}`,onClick:()=>P("values"),"data-testid":"wf-settings-tab-values",children:p("workflowSettings.valuesTab","Values")})]}),R==="definitions"?e.jsx(Cl,{settings:i,onChange:r,readOnly:g,addToast:k}):e.jsx(Fl,{workflowId:s,settings:i,boundProjectId:D,currentProjectId:d,addToast:k},s)]})}function oa(s,i){return s[i]?.editable?{up:s[i-1]?.editable===!0,down:s[i+1]?.editable===!0}:{up:!1,down:!1}}function sa({row:s,depth:i,selectedNodeId:r,selectedEdgeId:g,onSelectNode:d,onSelectEdge:k,onCreateConnection:I,canReorder:p,onMoveNode:R,canMoveUp:P,canMoveDown:O}){const{t:D}=je("app"),y=s.children.length>0,[x,w]=n.useState(i===0),[c,S]=n.useState(!1),j=r===s.id,$=s.connectionTargets??[],b=!!I&&s.editable&&$.length>0,M=!!p&&!!R&&s.editable;return e.jsxs("div",{className:"mobile-wf-node-group",children:[e.jsxs("div",{className:`mobile-wf-node-row${j?" mobile-wf-node-row--selected":""}`,style:{"--mobile-wf-depth":String(i)},"data-testid":`mobile-wf-node-${s.id}`,children:[e.jsxs("button",{type:"button",className:"mobile-wf-node-main",onClick:()=>d(s.id),"aria-current":j?"true":void 0,children:[e.jsx("span",{className:"mobile-wf-node-kind",children:s.kind}),e.jsxs("span",{className:"mobile-wf-node-text",children:[e.jsx("span",{className:"mobile-wf-node-title",children:s.label}),s.summary?e.jsx("span",{className:"mobile-wf-node-summary",children:s.summary}):null]}),s.editable?e.jsx(Qa,{size:14,"aria-hidden":!0}):null]}),y||M?e.jsxs("div",{className:"mobile-wf-node-actions",children:[M?e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"btn-icon mobile-wf-node-move","data-testid":`mobile-wf-node-move-up-${s.id}`,"aria-label":D("workflowNodes.mobileMoveUp","Move up"),disabled:!P,onClick:()=>R?.(s.id,"up"),children:e.jsx(Za,{size:16,"aria-hidden":!0})}),e.jsx("button",{type:"button",className:"btn-icon mobile-wf-node-move","data-testid":`mobile-wf-node-move-down-${s.id}`,"aria-label":D("workflowNodes.mobileMoveDown","Move down"),disabled:!O,onClick:()=>R?.(s.id,"down"),children:e.jsx(en,{size:16,"aria-hidden":!0})})]}):null,y?e.jsx("button",{type:"button",className:"mobile-wf-node-expand","aria-expanded":x,"aria-label":x?D("common.collapse","Collapse"):D("common.expand","Expand"),onClick:()=>w(A=>!A),children:x?e.jsx(Ae,{size:16}):e.jsx(Me,{size:16})}):null]}):null]}),b?e.jsx("div",{className:"mobile-wf-node-actions mobile-wf-node-actions--connect",style:{"--mobile-wf-depth":String(i)},children:e.jsxs("button",{type:"button",className:"mobile-wf-connect-button","data-testid":`mobile-wf-connect-${s.id}`,"aria-expanded":c,onClick:()=>S(A=>!A),children:[e.jsx(ss,{size:14,"aria-hidden":!0}),e.jsx("span",{children:D("workflowNodes.mobileConnect","Connect")})]})}):null,b&&c?e.jsxs("div",{className:"mobile-wf-connect-picker",style:{"--mobile-wf-depth":String(i)},children:[e.jsx("label",{className:"mobile-wf-connect-label",htmlFor:`mobile-wf-connect-target-${s.id}`,children:D("workflowNodes.mobileConnectTarget","Target node")}),e.jsxs("select",{id:`mobile-wf-connect-target-${s.id}`,className:"input mobile-wf-connect-select","data-testid":`mobile-wf-connect-target-${s.id}`,defaultValue:"",onChange:A=>{const C=A.currentTarget.value;C&&(I?.(s.id,C),A.currentTarget.value="",S(!1))},children:[e.jsx("option",{value:"",children:D("workflowNodes.mobileConnectChooseTarget","Choose a target…")}),$.map(A=>e.jsxs("option",{value:A.id,children:[A.label," (",A.kind,")"]},A.id))]})]}):null,(s.columnName||s.outgoing.length>0)&&e.jsxs("div",{className:"mobile-wf-node-meta",style:{"--mobile-wf-depth":String(i)},children:[s.columnName?e.jsx("span",{className:"mobile-wf-column-chip",children:s.columnName}):null,s.outgoing.map(A=>e.jsxs("button",{type:"button",className:`mobile-wf-edge-chip${g===A.id?" mobile-wf-edge-chip--selected":""}`,"data-testid":`mobile-wf-edge-${A.id}`,onClick:()=>k(A.id),children:[e.jsx(ss,{size:12,"aria-hidden":!0}),e.jsx("span",{children:A.label}),e.jsx("span",{className:"mobile-wf-edge-target",children:A.targetLabel})]},A.id))]}),y&&x?e.jsx("div",{className:"mobile-wf-node-children",children:s.children.map((A,C)=>{const z=oa(s.children,C);return e.jsx(sa,{row:A,depth:i+1,selectedNodeId:r,selectedEdgeId:g,onSelectNode:d,onSelectEdge:k,onCreateConnection:I,canReorder:p,onMoveNode:R,canMoveUp:z.up,canMoveDown:z.down},A.id)})}):null]})}function Pl({rows:s,selectedNodeId:i,selectedEdgeId:r,onSelectNode:g,onSelectEdge:d,onCreateConnection:k,canReorder:I,onMoveNode:p}){const{t:R}=je("app");return s.length===0?e.jsx("div",{className:"mobile-wf-graph-empty","data-testid":"mobile-wf-graph-empty",children:R("workflowNodes.mobileGraphEmpty","No graph nodes yet.")}):e.jsx("div",{className:"mobile-wf-graph","data-testid":"mobile-wf-graph",children:s.map((P,O)=>{const D=oa(s,O);return e.jsx(sa,{row:P,depth:0,selectedNodeId:i,selectedEdgeId:r,onSelectNode:g,onSelectEdge:d,onCreateConnection:k,canReorder:I,onMoveNode:p,canMoveUp:D.up,canMoveDown:D.down},P.id)})})}function Ml(s){return typeof s.label=="string"&&s.label.trim()?s.label:String(s.data?.condition??"success")}function Ls(s){return s.data.label||s.id}function co(s,i){const r=Math.round(s.position.y),g=Math.round(i.position.y);return r!==g?r-g:Math.round(s.position.x)-Math.round(i.position.x)}function zs(s){return s.data.kind!=="start"&&s.data.kind!=="end"&&!we(s.id)}function Il(s,i){return we(i.id)?!1:s.parentId||i.parentId?s.parentId===i.parentId:s.data.column===i.data.column}function Ol(s,i,r){const g=s.find(p=>p.id===i);if(!g||!zs(g))return s;const d=s.filter(p=>Il(g,p)).sort(co),k=d.findIndex(p=>p.id===i),I=d[k+(r==="up"?-1:1)];return!I||!zs(I)?s:s.map(p=>p.id===g.id?{...p,position:{...I.position}}:p.id===I.id?{...p,position:{...g.position}}:p)}function Dl(s,i){const r=new Map(s.map(g=>[g.id,g.name||g.id]));for(const g of i){if(!we(g.id))continue;const d=on(g.id);r.has(d)||r.set(d,g.data.label||d)}return r}function Tl(s,i,r=[],g={},d){const k=Dl(r,s),I=new Map(s.map(y=>[y.id,y])),p=new Map,R=new Map;for(const y of s){if(!y.parentId)continue;const x=p.get(y.parentId)??[];x.push(y),p.set(y.parentId,x)}for(const y of p.values())y.sort(co);for(const y of i){if(tn(y))continue;const x=R.get(y.source)??[];x.push(y),R.set(y.source,x)}const P=y=>{const x=I.get(y.target);return{id:y.id,source:y.source,target:y.target,targetLabel:x?Ls(x):y.target,label:Ml(y),kind:typeof y.data?.kind=="string"?y.data.kind:void 0}},O=y=>{const x=(p.get(y.id)??[]).map(O),w=y.data.column;return{id:y.id,label:Ls(y),kind:y.data.kind,summary:an(y.data,g,d),columnName:w?k.get(w)??w:void 0,editable:y.data.kind!=="start"&&y.data.kind!=="end"&&!we(y.id),parentId:y.parentId,templateLocalId:y.parentId?sn(y.parentId,y.id):void 0,outgoing:(R.get(y.id)??[]).map(P),children:x}};return s.filter(y=>!y.parentId&&!we(y.id)).sort(co).map(O)}function Ll(s){switch(typeof s?.seam=="string"?s.seam:""){case"planning":return"Generate the task plan and write the planning artifact that downstream workflow nodes consume.";case"execute":return"Run Fusion's standard implementation prompt for this task, generated from the task spec, current project context, workflow fields, and available tools.";case"step-execute":return"Run Fusion's step implementation prompt for the active planned step in the task worktree.";case"review":return"Run Fusion's review boundary for completed implementation work and route the task based on the review result.";case"merge":return"Run Fusion's merge boundary: verify merge readiness, apply the configured merge strategy, and update the final task state.";default:return""}}const zl=[{id:"claude-code",name:"Claude Code",tier:"native"},{id:"codex",name:"Codex",tier:"hybrid"},{id:"droid",name:"Droid",tier:"hybrid"},{id:"pi",name:"Pi",tier:"hybrid"},{id:"generic",name:"Generic CLI",tier:"generic"}],We=s=>s.startsWith("builtin:");function Ws(s,i){return s&&i?`${s}/${i}`:""}function $s(s){if(!s)return{provider:"",modelId:""};const i=s.indexOf("/");return i===-1?{provider:"",modelId:""}:{provider:s.slice(0,i),modelId:s.slice(i+1)}}function Wl(s){return we(s.id)?"transparent":s.data.kind==="start"?"var(--ws-success)":s.data.kind==="end"?"var(--ws-info)":s.data.kind==="gate"||s.data.kind==="step-review"?"var(--ws-warning)":s.data.kind==="merge"||s.data.kind==="join"?"var(--accent)":"var(--todo)"}function $l(s){return we(s.id)?"transparent":"var(--border-strong, var(--border))"}function ao(s,i,r,g,d,k,I,p){const{ir:R,layout:P}=Js(s,g,d,k.length?k:void 0,I.length?I:void 0,p.length?p:void 0);return JSON.stringify({name:s,description:i,icon:r?.trim()||void 0,ir:R,layout:P})}let _s=0;function Bs(){return _s+=1,`n-${Date.now().toString(36)}-${_s}`}const _l=["step-headings","json-steps"],Bl=["approve","revise","rethink","unavailable"],Gs=["in-review","merged","failed","awaiting-approval","task-created","workflow-notify"],no="__custom",Gl="npm test -- --runInBand",ql='export default async (ctx) => ({ outcome: "success" });',Vl="Task {{taskId}} reached {{workflowName}}",qs=[{kind:"prompt",label:"Prompt",icon:Pn},{kind:"prompt",label:"User input",icon:ea,presetConfig:{awaitInput:!0}},{kind:"script",label:"Script",icon:Mn},{kind:"gate",label:"Gate",icon:Zs},{kind:"merge",label:"Merge boundary",icon:In},{kind:"hold",label:"Hold",icon:On,presetConfig:{release:"manual"}},{kind:"split",label:"Split",icon:Dn},{kind:"join",label:"Join",icon:Tn,presetConfig:{mode:"all",onBranchFailure:"collect"}},{kind:"foreach",label:"For-each step",icon:xs,presetConfig:{source:"task-steps"}},{kind:"loop",label:"Loop",icon:xs,presetConfig:{maxIterations:3,exitWhen:{type:"output-contains",value:"DONE"}}},{kind:"optional-group",label:"Optional group",icon:Ln,presetConfig:{defaultOn:!1}},{kind:"step-review",label:"Step review",icon:zn,presetConfig:{type:"code"}},{kind:"parse-steps",label:"Parse steps",icon:Qs,presetConfig:{artifact:"PROMPT.md",parser:"step-headings"}},{kind:"code",label:"Code",icon:Wn,presetConfig:{source:""}},{kind:"notify",label:"Notify",icon:$n,presetConfig:{event:"in-review",title:"{{taskTitle}}",message:""}}];function Vs(s){const i={name:s.name,gateMode:s.gateMode??"advisory"};return s.description&&(i.description=s.description),s.mode==="script"?(s.scriptName&&(i.scriptName=s.scriptName),{kind:"script",label:s.name,config:i}):(i.prompt=s.prompt??"",i.toolMode=s.toolMode==="coding"?"coding":"readonly",s.modelProvider&&s.modelId&&(i.modelProvider=s.modelProvider,i.modelId=s.modelId),{kind:"prompt",label:s.name,config:i})}const Hl=new Set(["prompt","script","gate","code","hold","split","join","foreach","loop","optional-group","step-review","parse-steps","notify","merge"]);function Ul({workflows:s,onCreate:i,onDesign:r,onClose:g}){const{t:d}=je("app"),[k,I]=n.useState(""),[p,R]=n.useState(""),[P,O]=n.useState(""),[D,y]=n.useState(null),[x,w]=n.useState(!1),[c,S]=n.useState(!1),[j,$]=n.useState(""),[b,M]=n.useState(!1),[A,C]=n.useState(null),z=n.useRef(null),[ue,U]=n.useState(!1),Y=n.useRef(null),te=n.useRef([]),V=n.useMemo(()=>{const o={id:null,name:d("workflows.templateBlank","Blank"),description:d("workflows.templateBlankDescription","Start from an empty start → end graph."),nodeCount:0,builtin:!1},q=s.filter(le=>le.kind!=="fragment"),de=le=>({id:le.id,name:le.name,description:le.description??"",icon:le.icon,nodeCount:le.ir.nodes.length,source:le,builtin:We(le.id)}),ye=q.filter(le=>We(le.id)).map(de),he=q.filter(le=>!We(le.id)).map(de);return[o,...ye,...he]},[s,d]),[v,T]=n.useState(0),B=V[v]??V[0];n.useEffect(()=>{Y.current?.focus()},[]);const G=n.useCallback(o=>{const q=V[o];q&&(T(o),q.id===null?(ue||I(""),R(""),O("")):(ue||I(d("workflows.templateCopyName","{{name}} copy",{name:q.name})),R(q.description),O(q.builtin||!q.icon?"✨":q.icon)),D&&y(null))},[V,ue,D,d]),se=n.useCallback(o=>{if(o.key==="ArrowDown"||o.key==="ArrowRight"){o.preventDefault();const q=Math.min(v+1,V.length-1);G(q),te.current[q]?.focus()}else if(o.key==="ArrowUp"||o.key==="ArrowLeft"){o.preventDefault();const q=Math.max(v-1,0);G(q),te.current[q]?.focus()}else(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),G(v),Y.current?.focus())},[v,V.length,G]),fe=Hn(g),ie=n.useCallback(async o=>{o.preventDefault();const q=k.trim();if(!q){y(d("workflows.createNameRequired","Enter a workflow name"));return}w(!0),y(null);try{await i(q,p.trim(),P.trim(),B)}catch(de){y(ae(de)||d("workflows.createFailed","Failed to create workflow")),w(!1)}},[k,p,P,B,i,d]),X=n.useCallback(async()=>{const o=j.trim();if(!o){C(d("workflows.aiPromptRequired","Describe the workflow you want"));return}const q=new AbortController;z.current=q,M(!0),C(null);try{await r(o,k.trim(),q.signal)}catch(de){if(q.signal.aborted)return;C(ae(de)||d("workflows.aiFailed","Failed to design workflow"))}finally{z.current===q&&(z.current=null),M(!1)}},[j,k,r,d]),ne=n.useCallback(()=>{z.current?.abort(),M(!1)},[]),re=V.findIndex(o=>o.id!==null&&o.builtin),Ne=V.findIndex(o=>o.id!==null&&!o.builtin);return e.jsx("div",{className:"modal-overlay open wf-create-overlay",...fe,children:e.jsxs("div",{className:"modal wf-create-modal","data-testid":"wf-create-dialog",role:"dialog","aria-modal":"true","aria-label":d("workflows.createTitle","New workflow"),onClick:o=>o.stopPropagation(),onKeyDown:o=>{o.key==="Escape"&&(o.stopPropagation(),g())},children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:d("workflows.createTitle","New workflow")}),e.jsx("button",{type:"button",className:"modal-close",onClick:g,"aria-label":d("actions.close","Close"),children:e.jsx(Xs,{size:16})})]}),e.jsxs("form",{onSubmit:ie,children:[e.jsxs("div",{className:"modal-body",children:[e.jsxs("div",{className:"wf-ai-create","aria-busy":b,"data-testid":"wf-ai-create",children:[e.jsxs("button",{type:"button",className:"wf-ai-toggle","data-testid":"wf-ai-toggle","aria-expanded":c,onClick:()=>{S(o=>!o),C(null)},children:[e.jsx(Je,{size:13})," ",d("workflows.aiToggle","Describe it instead")]}),c&&e.jsxs("div",{className:"wf-ai-create-body",children:[e.jsx("textarea",{className:"wf-ai-prompt","data-testid":"wf-ai-prompt",rows:3,value:j,disabled:b,placeholder:d("workflows.aiPromptPlaceholder","e.g. Run lint and tests before merge, then post a changelog comment after merge"),onChange:o=>{$(o.target.value),A&&C(null)}}),A&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-ai-error",children:A}),e.jsxs("div",{className:"wf-ai-actions",children:[e.jsxs("button",{type:"button",className:"btn btn-primary wf-ai-submit","data-testid":"wf-ai-submit",disabled:b,onClick:()=>void X(),children:[b?e.jsx(Ie,{size:13,className:"wf-spin"}):e.jsx(Je,{size:13})," ",d("workflows.aiSubmit","Design with AI")]}),b&&e.jsx("button",{type:"button",className:"btn wf-ai-cancel","data-testid":"wf-ai-cancel",onClick:ne,children:d("common.cancel","Cancel")})]})]})]}),e.jsxs("div",{className:"wf-field",children:[e.jsx("span",{id:"wf-template-label",children:d("workflows.templatePickerLabel","Start from")}),e.jsx("div",{className:"wf-template-list",role:"radiogroup","aria-labelledby":"wf-template-label","data-testid":"wf-template-list",children:V.map((o,q)=>{const de=q===v,ye=o.id??"blank";return e.jsxs("div",{children:[q===re&&re>=0&&e.jsxs("p",{className:"wf-template-section wf-template-section--icon",children:[e.jsx(Le,{workflowId:"builtin:template-section",decorative:!0}),e.jsx("span",{children:d("workflows.templateSectionBuiltin","Fusion workflows")})]}),q===Ne&&Ne>=0&&e.jsx("p",{className:"wf-template-section",children:d("workflows.templateSectionYours","Your workflows")}),e.jsxs("div",{ref:he=>{te.current[q]=he},role:"radio","aria-checked":de,tabIndex:de?0:-1,className:`wf-template-option${de?" selected":""}`,"data-testid":o.id===null?"wf-template-option-blank":`wf-template-option-${o.id}`,onClick:()=>{G(q),te.current[q]?.focus()},onKeyDown:se,children:[e.jsxs("span",{className:"wf-template-option-heading",children:[e.jsx(Le,{workflowId:o.id??"",icon:o.icon,decorative:!0}),e.jsx("span",{className:"wf-template-option-name",children:o.name})]}),o.description&&e.jsx("span",{className:"wf-template-option-desc",children:o.description}),o.id!==null&&e.jsx("span",{className:"wf-template-option-count",children:d("workflows.templateNodeCount","{{count}} nodes",{count:o.nodeCount})})]})]},ye)})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:d("workflows.createName","Name")}),e.jsx("input",{ref:Y,"data-testid":"wf-create-name",value:k,onChange:o=>{I(o.target.value),U(!0),D&&y(null)}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:d("workflows.iconLabel","Icon (optional)")}),e.jsx("input",{"data-testid":"wf-create-icon",value:P,maxLength:16,placeholder:d("workflows.iconPlaceholder","e.g. 🚀"),onChange:o=>O(o.target.value)})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:d("workflows.createDescription","Description (optional)")}),e.jsx("textarea",{rows:2,"data-testid":"wf-create-description",value:p,onChange:o=>R(o.target.value)})]}),D&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-create-error",children:D})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{type:"button",className:"btn",onClick:g,children:d("common.cancel","Cancel")}),e.jsxs("button",{type:"submit",className:"btn btn-primary","data-testid":"wf-create-submit",disabled:x,children:[x?e.jsx(Ie,{size:13,className:"wf-spin"}):null," ",d("workflows.createSubmit","Create")]})]})]})]})})}function Kl({onClose:s,addToast:i,projectId:r,initialPanel:g,initialAction:d,initialWorkflowId:k,modalRef:I,isEmbedded:p=!1}){const[R,P]=n.useState([]),[O,D]=n.useState(null),x=nn()==="mobile",[w,c]=n.useState(()=>as()),[S,j]=n.useState(!1),[$,b]=n.useState(!1),[M,A]=n.useState(null),[C,z,ue]=La([]),[U,Y]=za([]),[te,V]=n.useState(null),[v,T]=n.useState(null),[B,G]=n.useState(!1),[se,fe]=n.useState(!1),[ie,X]=n.useState(!1),[ne,re]=n.useState(()=>g==="settings"?"settings":"graph"),Ne=x||ie,{t:o}=je("app"),{confirm:q}=ln(),[de,ye]=n.useState(d==="create"),he=n.useRef(null),le=n.useRef(null),[m,_]=n.useState(""),[H,Q]=n.useState(""),[oe,K]=n.useState(void 0),[ge,J]=n.useState(!1),[Ce,Qe]=n.useState(!1),Ze=n.useRef(null),[Z,et]=n.useState([]),[Fe,tt]=n.useState([]),[Pe,ot]=n.useState([]),[$e,ft]=n.useState(null),[aa,_e]=n.useState(null),Pt=n.useRef(null),[uo,na]=n.useState([]),[la,ia]=n.useState([..._l]),[Mt,ra]=n.useState([]),[It,da]=n.useState([]),fo="fusion:wf-templates-collapsed",[Be,ca]=n.useState(()=>{try{const t=localStorage.getItem(fo);return t!=null?t==="1":as()}catch{return!1}}),[pt,po]=n.useState(""),[mt,mo]=n.useState(null),Ot=n.useRef(!1),wo="fusion:wf-left-sidebar-collapsed",ho="fusion:wf-sidebar-columns-collapsed",go="fusion:wf-sidebar-fields-collapsed",bo="fusion:wf-sidebar-settings-collapsed",[st,ko]=n.useState(()=>{try{return localStorage.getItem(wo)==="1"}catch{return!1}}),[at,ua]=n.useState(()=>{try{return localStorage.getItem(ho)==="1"}catch{return!1}}),[nt,fa]=n.useState(()=>{try{return localStorage.getItem(go)==="1"}catch{return!1}}),[lt,pa]=n.useState(()=>{try{return localStorage.getItem(bo)==="1"}catch{return!1}});n.useEffect(()=>{try{localStorage.setItem(wo,st?"1":"0")}catch{}},[st]),n.useEffect(()=>{try{localStorage.setItem(ho,at?"1":"0")}catch{}},[at]),n.useEffect(()=>{try{localStorage.setItem(go,nt?"1":"0")}catch{}},[nt]),n.useEffect(()=>{try{localStorage.setItem(bo,lt?"1":"0")}catch{}},[lt]);const{setViewport:xo}=Wa(),Dt=n.useRef(null),[vo,Tt]=n.useState(null),[jo,No]=n.useState([]),[yo,Co]=n.useState(!1),wt=n.useRef(null),[Lt,zt]=n.useState(!1),[ht,Wt]=n.useState(""),[be,$t]=n.useState(!1),[Ge,qe]=n.useState(null),gt=n.useRef(null),N=n.useMemo(()=>R.find(t=>t.id===O),[R,O]),L=!!N&&We(N.id),So=N?.lifecycleWarnings??[],Eo=n.useRef(O);Eo.current=O;const ma=n.useMemo(()=>!N||L?!1:!C.some(t=>Hl.has(t.data.kind)),[N,L,C]),Ao=!0;n.useEffect(()=>{let t=!1;return Us(r).then(a=>{t||na(a)}).catch(()=>{}),()=>{t=!0}},[r]),n.useEffect(()=>{let t=!1;return rn(r).then(a=>{!t&&a.length>0&&ia(a)}).catch(()=>{}),()=>{t=!0}},[r]),n.useEffect(()=>{let t=!1;return dn().then(a=>{t||ra(a.templates??[])}).catch(()=>{}),cn().then(a=>{t||da(a.templates??[])}).catch(()=>{}),()=>{t=!0}},[]),n.useEffect(()=>{try{localStorage.setItem(fo,Be?"1":"0")}catch{}},[Be]),n.useEffect(()=>{te&&G(!1)},[te]),n.useEffect(()=>{g==="settings"&&re("settings")},[g]);const _t=n.useMemo(()=>R.filter(t=>t.kind==="fragment"),[R]),pe=n.useMemo(()=>{const t=pt.trim().toLowerCase(),a=E=>!t||E.toLowerCase().includes(t),l=(E,ee)=>E.name.localeCompare(ee.name),u=[..._t].sort(l).filter(E=>a(E.name)),h=[...Mt].sort(l).filter(E=>a(E.name)),F=[...It].sort((E,ee)=>E.template.name.localeCompare(ee.template.name)).filter(E=>a(E.template.name));return{fragmentEntries:u,stepEntries:h,pluginEntries:F}},[_t,Mt,It,pt]),Bt=_t.length+Mt.length+It.length,Ro=Bt>0,Gt=n.useMemo(()=>Z.length?un(Z,uo):[],[Z,uo]),Oe=n.useMemo(()=>fn(C,Z),[C,Z]),Fo=Gt.filter(t=>t.severity==="error").length,it=n.useMemo(()=>L||!N||Ze.current===null?!1:ao(m,H,oe,C,U,Z,Fe,Pe)!==Ze.current,[L,N,m,H,oe,C,U,Z,Fe,Pe]),Ve=n.useCallback(async t=>{j(!0);try{const a=await pn(r,t);P(a),D(l=>l&&a.some(u=>u.id===l)?l:d!=="create"&&k&&a.some(u=>u.id===k)?k:x?null:a[0]?.id??null)}catch(a){i(ae(a)||o("workflows.loadFailed","Failed to load workflows"),"error")}finally{j(!1)}},[r,i,x,d,k,o]);n.useEffect(()=>{Ve()},[Ve]),n.useEffect(()=>{const t=r?`?projectId=${encodeURIComponent(r)}`:"",a=()=>{Ve({forceFresh:!0})};return mn(`/api/events${t}`,{events:{"workflow:created":a,"workflow:updated":a,"workflow:deleted":a}})},[Ve,r]),n.useEffect(()=>{!k||!x||!w||O===k&&le.current!==k&&(le.current=k,c(!1))},[O,k,x,w]);const bt=n.useCallback(async()=>{if(N)try{await wn(N.id,r)}catch(t){i(ae(t)||o("workflows.exportFailed","Failed to export workflow"),"error")}},[N,r,i,o]),wa=n.useCallback(async t=>{const a=t.target.files?.[0];if(wt.current&&(wt.current.value=""),!!a){Tt(null),No([]),Co(!0);try{const l=await a.text();let u;try{u=JSON.parse(l)}catch{Tt(o("workflows.importInvalidJson","That file isn't valid JSON."));return}const h=await hn(u,r);await Ve(),D(h.workflow.id),c(!1),i(o("workflows.imported",'Imported workflow "{{name}}"',{name:h.workflow.name}),"success"),h.strippedApprovalFlags&&i(o("workflows.importStripped","Auto-approval flags were removed from imported nodes"),"warning"),h.warnings.length>0&&No(h.warnings)}catch(l){l instanceof Ys&&l.status>=400&&l.status<500?Tt(ae(l)||o("workflows.importFailed","Import failed")):i(ae(l)||o("workflows.importFailed","Import failed"),"error")}finally{Co(!1)}}},[r,Ve,i,o]);n.useEffect(()=>{if(Ot.current=!1,!N){z([]),Y([]),et([]),tt([]),ot([]),ft(null),_e(null),_(""),Q(""),K(void 0),Ze.current=null;return}const t=ns(N),a=ls(N),l=is(N),u=rs(N),h=Ss(t.nodes,t.edges,a),F=Es(t.nodes,h);z(F),Y(t.edges),et(a),tt(l),ot(u),_(N.name),Q(N.description??""),K(N.icon),J(!1),Qe(!1),Ze.current=ao(N.name,N.description??"",N.icon,F,t.edges,a,l,u),V(null),T(null),A(null),xo({x:0,y:0,zoom:1},{duration:0})},[N,z,Y,xo]),n.useEffect(()=>{C.length>0&&(Ot.current=!0)},[C]),n.useEffect(()=>{if(!N||!L){ft(null),_e(null);return}let t=!1;return ds(N.id,r).then(a=>{t||(ft(a),z(l=>l.map(u=>{if(u.data.kind!=="prompt"&&u.data.kind!=="gate")return u;const h=a.effective[u.id];return h===void 0?u:{...u,data:{...u.data,config:{...u.data.config??{},prompt:h}}}})))}).catch(a=>{t||i(ae(a)||o("workflowEditor.promptOverridesLoadFailed","Failed to load prompt overrides"),"error")}),()=>{t=!0}},[N,L,r,i,o,z]);const qt=n.useRef(!1);n.useEffect(()=>{if(g!=="settings"||qt.current||!N)return;const t=Pt.current;t&&(qt.current=!0,t.scrollIntoView({behavior:"smooth",inline:"end",block:"nearest"}))},[g,N]),n.useEffect(()=>()=>{qt.current=!1},[g]);const[Vt,Po]=n.useState(null);n.useEffect(()=>{z(t=>{const a=t.filter(l=>!we(l.id)&&l.type!=="group");return[...gn(Z),...bn(a,Z)]})},[Z,z]);const kt=n.useCallback((t,a={})=>{const l=kn(t,U,C);if("error"in l){l.error==="cycle"?i(o("workflowNodes.cycleBlocked","That connection would create a cycle — only rework edges inside a for-each template may loop back"),"warning"):l.error==="duplicate"?i(o("workflowNodes.duplicateBlocked","That connection already exists"),"warning"):l.error==="reserved-handle"&&i(o("workflowNodes.reservedHandleBlocked","Optional-block boundary guides cannot be connected manually"),"warning");return}Y(u=>{const h=ut(C,[...u,l.edge]);return z(h.nodes),h.edges}),a.selectCreatedEdge&&(T(l.edge.id),V(null),G(!1))},[U,C,Y,z,i,o]),ha=n.useCallback(t=>{Y(a=>{const l=$a(t,a),u=ut(C,l);return z(u.nodes),u.edges})},[C,Y,z]),ga=n.useCallback(t=>{kt(t)},[kt]),ba=n.useCallback((t,a)=>{kt({source:t,target:a,sourceHandle:null,targetHandle:null},{selectCreatedEdge:!0})},[kt]),ka=n.useCallback((t,a)=>{z(l=>Ol(l,t,a))},[z]),xa=n.useCallback((t,a)=>{if(we(a.id)||Z.length===0)return;const l=lo(a.position.y,Z);l&&z(u=>u.map(h=>h.id===a.id?{...h,data:{...h.data,column:l}}:h))},[Z,z]),xt=n.useCallback((t,a,l)=>{const u=Bs(),h=a??(t==="merge"?"Merge boundary":t.charAt(0).toUpperCase()+t.slice(1)),F=t==="gate"?{gateMode:"gate"}:{},E=l?{...F,...l}:F;if(t==="foreach"||t==="loop"||t==="optional-group"){const ee=xn(u,Bs()),Ee=t==="foreach"?o("workflowNodes.stepExecuteLabel","Step execute"):t==="optional-group"?o("workflowNodes.optionalGroupStepLabel","Optional step"):o("workflowNodes.loopStepLabel","Loop step"),ce=t==="foreach"?{seam:"step-execute"}:{prompt:""};z(Ye=>{const ct=[...Ye,{id:u,type:t,position:{x:200+Ye.length*40,y:240+Ye.length%3*70},data:{kind:t,label:h,config:E,templateEmpty:!1},style:{width:jn,height:vn},deletable:!0},{id:ee,type:"prompt",position:{x:yn,y:Nn},parentId:u,extent:"parent",data:{kind:"prompt",label:Ee,config:ce},deletable:!0}],ts=ut(ct,U);return Y(ts.edges),ts.nodes}),V(u);return}z(ee=>[...ee,{id:u,type:t,position:{x:200+ee.length*40,y:240+ee.length%3*70},data:{kind:t,label:h,config:E},deletable:!0}]),V(u)},[U,Y,z,o]),vt=n.useCallback(t=>{if(L)return;const{kind:a,label:l,config:u}=Vs(t);xt(a,l,u)},[L,xt]),Mo=n.useCallback(t=>{if(L)return;const{kind:a,config:l}=Vs(t),u=Cn({kind:a,config:l},{name:t.name,defaultOn:t.defaultOn??!1}),h=cs(C,U,u,{x:240,y:200+C.length%4*40});z(h.nodes),Y(h.edges),V(h.insertedNodeIds[0]??null)},[L,C,U,z,Y]),Io=n.useCallback(t=>{if(L)return!1;const a=Ot.current?void 0:N?.ir,l=Sn(t.ir,C,a);if(l.length>0)return mo(l.join(", ")),!1;mo(null);const u=cs(C,U,t.ir,{x:240,y:200+C.length%4*40},t.layout);return z(u.nodes),Y(u.edges),V(u.insertedNodeIds[0]??null),!0},[L,C,U,N,z,Y]),Oo=n.useCallback(()=>{z(t=>Es(t,Ss(t,U,Z)))},[z,U,Z]),Do=n.useCallback(async()=>{if(!N||L)return;const t=ht.trim();if(!t){qe(o("workflows.aiPromptRequired","Describe the workflow you want"));return}const a=new AbortController;gt.current=a;const l=N;$t(!0),qe(null);try{const u=await us({prompt:t,workflowId:l.id},r,a.signal);if(Eo.current!==l.id){i(o("workflows.aiStaleDiscarded","Discarded AI design — you switched workflows"),"warning");return}if(!await q({title:o("workflows.aiReplaceTitle","Replace graph?"),message:o("workflows.aiReplaceConfirm","Replace the current graph with the AI design? Unsaved changes will be lost."),confirmLabel:o("workflows.aiReplaceConfirmLabel","Replace"),danger:!0}))return;const F=ns({...l,ir:u.ir,layout:u.layout});z(F.nodes),Y(F.edges),et(ls({...l,ir:u.ir})),tt(is({...l,ir:u.ir})),ot(rs({...l,ir:u.ir})),V(null),T(null),A(null),u.strippedApprovalFlags&&i(o("workflows.importStripped","Auto-approval flags were removed from imported nodes"),"warning"),zt(!1),Wt("")}catch(u){if(a.signal.aborted)return;qe(ae(u)||o("workflows.aiFailed","Failed to design workflow"))}finally{gt.current===a&&(gt.current=null),$t(!1)}},[N,L,ht,r,q,o,z,Y,i]),To=n.useCallback(()=>{gt.current?.abort(),$t(!1)},[]),W=n.useCallback(t=>{te&&z(a=>a.map(l=>l.id===te?{...l,data:{...l.data,..."config"in t?{config:typeof t.config=="function"?t.config(l.data.config??{}):{...l.data.config??{},...t.config}}:t}}:l))},[te,z]),rt=n.useCallback((t,a)=>{ft(a);const l=a.effective[t]??a.defaults[t]??"";z(u=>u.map(h=>h.id===t?{...h,data:{...h.data,config:{...h.data.config??{},prompt:l}}}:h))},[z]),Lo=n.useCallback(async(t,a)=>{if(!(!N||!L)){_e(t);try{const l=await fs(N.id,{[t]:a},r);rt(t,l),i(o("workflowEditor.promptOverrideSaved","Prompt override saved"),"success")}catch(l){i(ae(l)||o("workflowEditor.promptOverrideSaveFailed","Failed to save prompt override"),"error");try{const u=await ds(N.id,r);rt(t,u)}catch{}}finally{_e(l=>l===t?null:l)}}},[N,L,r,i,o,rt]),zo=n.useCallback(async t=>{if(!(!N||!L)){_e(t);try{const a=await fs(N.id,{[t]:null},r);rt(t,a),i(o("workflowEditor.promptOverrideReset","Prompt reset to default"),"success")}catch(a){i(ae(a)||o("workflowEditor.promptOverrideResetFailed","Failed to reset prompt"),"error")}finally{_e(a=>a===t?null:a)}}},[N,L,r,i,o,rt]),Ht=n.useCallback(t=>{v&&Y(a=>{const l=a.map(h=>{if(h.id!==v)return h;const F=t.condition??h.data?.condition??"success",E=t.rework??h.data?.kind==="rework";return{...h,label:E?`${ps(F)} (rework)`:ps(F),data:{...h.data??{},condition:F,kind:E?"rework":void 0},type:E?"step":void 0,animated:E,className:En(F,E)}}),u=ut(C,l);return z(u.nodes),u.edges})},[C,v,Y,z]),Wo=n.useCallback(t=>{const a=new Set(t);let l=null;z(u=>{const h=ms(u,U,a);return l=ut(h.nodes,h.edges),l.nodes}),l&&Y(l.edges),te!==null&&a.has(te)&&V(null),v!==null&&a.has(v)&&T(null)},[U,z,Y,te,v]),va=n.useCallback(async({nodes:t,edges:a})=>{if(L)return!1;const l=new Set([...t.map(E=>E.id),...a.map(E=>E.id)]),u=ms(C,U,l),h=new Set(C.map(E=>E.id));for(const E of u.nodes)h.delete(E.id);const F=new Set(U.map(E=>E.id));for(const E of u.edges)F.delete(E.id);return h.size===0&&F.size===0?!1:{nodes:C.filter(E=>h.has(E.id)),edges:U.filter(E=>F.has(E.id))}},[L,C,U]),ja=n.useCallback(()=>{V(null),Dt.current?.focus()},[]),Na=n.useCallback(()=>{T(null),Dt.current?.focus()},[]),dt=n.useCallback(()=>{ye(!1),he.current?.focus()},[]),ya=n.useCallback(async(t,a,l,u)=>{const h=u.source!==void 0?An(u.source.ir,u.source.layout):{ir:Kn(t),layout:Un()},F=await eo({name:t,description:a||void 0,icon:l||void 0,kind:"workflow",ir:h.ir,layout:h.layout},r);P(E=>[...E,F]),D(F.id),c(!1),i(o("workflows.created",'Created workflow "{{name}}"',{name:F.name}),"success"),dt()},[r,i,o,dt]),Ca=n.useCallback(async(t,a,l)=>{const u=await us({prompt:t},r,l),h=`AI: ${t.slice(0,30)}`,E=await eo({name:a||h,kind:"workflow",ir:u.ir,layout:u.layout},r);P(ee=>[...ee,E]),D(E.id),c(!1),i(o("workflows.created",'Created workflow "{{name}}"',{name:E.name}),"success"),u.strippedApprovalFlags&&i(o("workflows.importStripped","Auto-approval flags were removed from imported nodes"),"warning"),dt()},[r,i,o,dt]),$o=n.useCallback(async()=>{if(!(!N||We(N.id)||!await q({title:o("workflows.deleteTitle","Delete workflow?"),message:o("workflows.deleteMessage",'Delete workflow "{{name}}"? This cannot be undone.',{name:N.name}),confirmLabel:o("common.delete","Delete"),danger:!0})))try{await Rn(N.id,r),P(a=>a.filter(l=>l.id!==N.id)),D(null),x&&c(!0),i(o("workflows.deleted","Workflow deleted"),"success")}catch(a){i(ae(a)||o("workflows.deleteFailed","Failed to delete workflow"),"error")}},[N,r,i,q,o,x]),_o=n.useCallback(async()=>{if(N)try{const t=await eo({name:`${N.name} (copy)`,description:N.description,icon:We(N.id)||!N.icon?"✨":N.icon,ir:N.ir,layout:N.layout},r);P(a=>[...a,t]),D(t.id),c(!1),i(o("workflows.duplicatedEditable",'Duplicated to "{{name}}" — editable',{name:t.name}),"success")}catch(t){i(ae(t)||o("workflows.duplicateFailed","Failed to duplicate workflow"),"error")}},[N,r,i,o]),Bo=n.useCallback(async()=>{if(N&&!We(N.id)){if(Oe.length>0){const t=o("workflowColumns.unplacedCount","{{count}} nodes not placed in a column",{count:Oe.length});A(t),i(t,"error");return}if(Fo>0){const t=o("workflowColumns.compositionBlocked","Resolve trait conflicts on highlighted columns before saving");A(t),i(t,"error");return}b(!0),A(null),Po(null);try{const t=m.trim()||N.name,{ir:a,layout:l}=Js(t,C,U,Z.length?Z:void 0,Fe.length?Fe:void 0,Pe.length?Pe:void 0),u=t!==N.name,h=H!==(N.description??""),F=oe?.trim()||void 0,E=F!==N.icon,ee=async ce=>{P(Ye=>Ye.map(ct=>ct.id===ce.id?ce:ct)),Ze.current=ao(ce.name,ce.description??"",ce.icon,C,U,Z,Fe,Pe),_(ce.name),Q(ce.description??""),K(ce.icon),i(o("workflows.saved","Workflow saved"),"success")},Ee={ir:a,layout:l,...u?{name:t}:{},...h?{description:H}:{},...E?{icon:F??null}:{}};try{await ee(await ws(N.id,Ee,r))}catch(ce){if(!(ce?.details?.policyEscalation===!0))throw ce;if(!window.confirm(`${ae(ce)}
|
|
7
|
-
|
|
8
|
-
${o("workflowColumns.confirmPolicyEscalation","Bind it anyway? The column agent will run with broader permissions than this project's default.")}`)){i(o("workflowColumns.escalationDeclined","Save cancelled — column agent binding not confirmed"),"error");return}await ee(await ws(N.id,{...Ee,confirmPolicyEscalation:!0},r))}}catch(t){const a=ae(t)||o("workflows.saveFailed","Failed to save workflow"),l=/node '([^']+)'/.exec(a);l&&C.some(u=>u.id===l[1])&&Po({nodeId:l[1],message:a}),A(a),i(a,"error")}finally{b(!1)}}},[N,m,H,C,U,Z,Fe,Pe,Oe,Fo,r,i,o]),He=n.useMemo(()=>{const t=new Set(Oe),a=new Map;for(const l of C)l.parentId&&a.set(l.parentId,(a.get(l.parentId)??0)+1);return C.map(l=>{let u;t.has(l.id)&&(u=o("workflowColumns.nodeUnplaced","Not placed in a column")),Vt?.nodeId===l.id&&(u=Vt.message);const h=l.data.kind==="foreach"||l.data.kind==="loop"||l.data.kind==="optional-group",F=l.data.kind==="loop"?o("workflowNodes.loopEmptyHint","Drag loop steps here"):l.data.kind==="optional-group"?o("workflowNodes.optionalGroupEmptyHint","Drag optional steps here"):o("workflowNodes.foreachEmptyHint","Drag a step-execute node here"),E=h?(a.get(l.id)??0)===0:void 0;return u===l.data.errorBadge&&(!h||E===l.data.templateEmpty&&l.data.emptyHint===F)?l:{...l,data:{...l.data,errorBadge:u,...h?{templateEmpty:E,emptyHint:F}:{}}}})},[C,Oe,Vt,o]),f=C.find(t=>t.id===te)??null,Go=f!==null&&f.data.kind!=="end",Se=f!==null?tl(f.data):null,ke=U.find(t=>t.id===v)??null,Sa=x&&Go&&!B,Ea=x&&ke!==null,[Ut,qo]=n.useState(!1),Vo=n.useCallback(()=>{qo(t=>!t)},[]),Aa=n.useCallback(t=>{!Ut||t.key!=="Escape"||(t.preventDefault(),t.stopPropagation(),qo(!1))},[Ut]),Ue=f&&(f.data.kind==="prompt"||f.data.kind==="gate")?String(f.data.config?.prompt??$e?.effective[f.id]??(L?Ll(f.data.config):"")):"",Kt=f?$e?.defaults[f.id]:void 0,Ho=f?$e?.stored[f.id]:void 0,Yt=Ho!==void 0,Uo=Yt&&Kt!==void 0&&Ho!==Kt,jt=!!f&&aa===f.id,Nt=!!f&&(f.data.kind==="prompt"||f.data.kind==="gate")&&(!L||Kt!==void 0),Ko=n.useCallback(t=>{Nt&&W({config:{prompt:t}})},[Nt,W]),Yo=n.useCallback(()=>{if(!L||!f||f.data.kind!=="prompt"&&f.data.kind!=="gate")return;const t=$e?.stored[f.id],a=$e?.defaults[f.id],l=Ue.trim()?Ue:"";t===void 0&&(a===void 0||l===a)||t===l||Lo(f.id,Ue)},[L,f,Ue,$e,Lo]),Jo=n.useCallback(()=>{f&&zo(f.id)},[f,zo]),Xo=n.useMemo(()=>{if(!ke)return"readonly";const t=C.find(a=>a.id===ke.source);return Fn(t?.data.kind)},[ke,C]),Jt=n.useMemo(()=>{const t=N?.ir;return t&&t.version==="v2"&&Array.isArray(t.artifacts)?t.artifacts.map(a=>a.key):[]},[N]),[De,Xt]=n.useState([]),[xe,yt]=n.useState([]);n.useEffect(()=>{yt([])},[r]);const[Ke,Qo]=n.useState([]),[Ra,Fa]=n.useState(zl);n.useEffect(()=>{let t=!1;return Promise.resolve(Rt()).then(a=>{!t&&a?.models&&Xt(a.models)}).catch(()=>{}),Promise.resolve(At()).then(a=>{!t&&Array.isArray(a)&&yt(a)}).catch(()=>{}),Promise.resolve(hs(r)).then(a=>{!t&&Array.isArray(a)&&Qo(a)}).catch(()=>{}),()=>{t=!0}},[r]);const Qt=n.useMemo(()=>({models:De.map(t=>({provider:t.provider,id:t.id,name:t.name})),agents:xe.map(t=>({id:t.id,name:t.name})),skills:Ke.map(t=>({id:t.id,name:t.name}))}),[De,xe,Ke]),Zo=n.useMemo(()=>{const t=He.filter(l=>!we(l.id)&&l.data.kind!=="start").map(l=>({id:l.id,label:l.data.label||l.id,kind:l.data.kind})),a=new Map;for(const l of He){if(we(l.id)||l.data.kind==="start"||l.data.kind==="end")continue;const u=t.filter(h=>h.id!==l.id);u.length>0&&a.set(l.id,u)}return a},[He]),Pa=n.useMemo(()=>{const t=a=>a.map(l=>({...l,connectionTargets:L?[]:Zo.get(l.id)??[],children:t(l.children)}));return t(Tl(He,U,Z,Qt,o))},[He,U,Z,Qt,o,L,Zo]),me=f?.data.config?.executor??"model",Te=n.useMemo(()=>{const t=f?.data.column??(f?.parentId?C.find(l=>l.id===f.parentId)?.data.column:void 0);if(!t)return;const a=Z.find(l=>l.id===t);if(!(!a?.agent||a.agent.mode!=="override"))return a.agent},[f?.data.column,f?.parentId,C,Z]),Ma=n.useMemo(()=>Te?xe.find(t=>t.id===Te.agentId):void 0,[Te,xe]);n.useEffect(()=>{if(me!=="cli-agent")return;let t=!1;return fetch("/api/cli-agents").then(a=>a.ok?a.json():null).then(a=>{t||!a?.adapters||Fa(a.adapters)}).catch(()=>{}),()=>{t=!0}},[me]),n.useEffect(()=>{if(f?.data.kind==="step-review"&&De.length===0){Rt().then(t=>Xt(t.models)).catch(t=>{i(ae(t)||o("workflowEditor.modelsLoadFailed","Failed to load models"),"error")});return}!f||f.data.kind!=="prompt"&&f.data.kind!=="gate"||(me==="model"&&De.length===0?Rt().then(t=>Xt(t.models)).catch(t=>{i(ae(t)||o("workflowEditor.modelsLoadFailed","Failed to load models"),"error")}):me==="agent"&&xe.length===0?At(void 0,r).then(yt).catch(t=>{i(ae(t)||o("workflowEditor.agentsLoadFailed","Failed to load agents"),"error")}):me==="skill"&&Ke.length===0&&hs(r).then(Qo).catch(t=>{i(ae(t)||o("workflowEditor.skillsLoadFailed","Failed to load skills"),"error")}))},[me,f?.id,f?.data.kind,r,i,De.length,xe.length,Ke.length,o]);const Ct=n.useCallback(t=>{if(!it){t();return}q({title:o("workflows.discardTitle","Discard unsaved changes?"),message:o("workflows.discardMessage","You have unsaved changes to this workflow. Discard them?"),confirmLabel:o("workflows.discardConfirm","Discard"),danger:!0}).then(a=>{a&&t()})},[it,q,o]),Zt=n.useCallback(()=>{Ct(s)},[Ct,s]),Ia=n.useCallback(t=>{if(t===O){c(!1);return}Ct(()=>{D(t),c(!1)})},[Ct,O]);n.useEffect(()=>{if(!Te||xe.length>0)return;let t=!1;return Promise.resolve(At(void 0,r)).then(a=>{t||yt(a??[])}).catch(a=>{t||i(ae(a)||o("workflowEditor.agentsLoadFailed","Failed to load agents"),"error")}),()=>{t=!0}},[Te,xe.length,r,i,o]);const Oa=Ut&&(f?.data.kind==="prompt"||f?.data.kind==="gate")?Da.createPortal(e.jsxs("div",{className:"wf-prompt-editor wf-prompt-editor--fullscreen",onKeyDown:Aa,children:[e.jsxs("div",{className:"wf-prompt-fullscreen-header",children:[e.jsx("span",{children:o("workflowEditor.editingPrompt","Editing Prompt")}),e.jsx("button",{type:"button",className:"btn btn-sm wf-prompt-expand-btn",onClick:Vo,"aria-label":o("workflowEditor.collapsePrompt","Collapse prompt editor"),title:o("workflowEditor.collapsePrompt","Collapse prompt editor"),children:e.jsx(gs,{size:14})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.prompt","Prompt")}),e.jsx("textarea",{rows:void 0,value:Ue,readOnly:!Nt,onChange:t=>Ko(t.target.value),onBlur:Yo,autoFocus:!0})]}),L?e.jsxs("div",{className:"wf-prompt-override-actions wf-prompt-override-actions--fullscreen",children:[Uo?e.jsx("span",{className:"wf-prompt-override-badge","data-testid":"wf-prompt-overridden",children:o("workflowEditor.promptOverridden","Overridden")}):null,e.jsx("button",{type:"button",className:"btn btn-sm",onClick:Jo,disabled:!Yt||jt,children:jt?o("workflowEditor.promptSaving","Saving…"):o("workflowEditor.resetPromptDefault","Reset to default")})]}):null]}),document.body):null,es=e.jsxs("div",{className:`modal wf-editor-modal${p?" wf-editor-modal--embedded":""}`,ref:I,onClick:t=>t.stopPropagation(),onKeyDown:t=>{if(t.key!=="Escape"||p||de)return;const l=t.target.tagName;l==="INPUT"||l==="TEXTAREA"||l==="SELECT"||(t.stopPropagation(),Zt())},children:[e.jsxs("header",{className:"wf-editor-header",children:[e.jsxs("h2",{children:[e.jsx(bs,{size:20,"aria-hidden":"true"}),e.jsx("span",{children:o("workflows.title","Workflows")})]}),p?null:e.jsx("button",{className:"wf-editor-close",onClick:Zt,"aria-label":o("workflows.closeEditor","Close workflow editor"),children:e.jsx(Xs,{size:18})})]}),e.jsxs("div",{className:`wf-editor-body${w?" wf-editor-body--list-stage":" wf-editor-body--editor-stage"}${Ne?" wf-editor-body--simple-layout":""}${Sa?" wf-editor-body--mobile-node-detail":""}${Ea?" wf-editor-body--mobile-edge-detail":""}${st?" wf-editor-body--sidebar-collapsed":""}`,children:[e.jsxs("aside",{className:"wf-editor-sidebar",children:[e.jsxs("div",{className:"wf-editor-sidebar-head",children:[e.jsxs("button",{className:"wf-editor-new",ref:he,"data-testid":"wf-new-workflow",onClick:()=>ye(!0),children:[e.jsx(Re,{size:14})," ",o("workflows.newWorkflow","New workflow")]}),!x&&e.jsx("button",{type:"button",className:"wf-sidebar-shell-toggle","data-testid":"wf-sidebar-collapse","aria-expanded":!st,"aria-label":o("workflows.collapseSidebar","Collapse workflow sidebar"),title:o("workflows.collapseSidebar","Collapse workflow sidebar"),onClick:()=>ko(!0),children:e.jsx(ks,{size:14,"aria-hidden":!0})})]}),e.jsxs("button",{type:"button",className:"wf-editor-import","data-testid":"wf-import",disabled:yo,onClick:()=>wt.current?.click(),title:o("workflows.importTooltip","Import a workflow from a JSON file"),children:[yo?e.jsx(Ie,{size:14,className:"wf-spin"}):e.jsx(Yn,{size:14})," ",o("workflows.import","Import")]}),e.jsx("input",{ref:wt,type:"file",accept:".json",className:"wf-editor-import-input","data-testid":"wf-import-input",style:{display:"none"},onChange:wa}),vo&&e.jsx("div",{className:"wf-editor-import-error",role:"alert","data-testid":"wf-import-error",children:vo}),jo.length>0&&e.jsx("div",{className:"wf-editor-import-warnings","data-testid":"wf-import-warnings",children:jo.map((t,a)=>e.jsx("p",{className:"wf-editor-import-warning",children:t},a))}),x&&R.length>0&&!N?e.jsx("div",{className:"wf-editor-select-note","data-testid":"wf-mobile-select-note",children:o("workflows.mobileSelectNote","Select a workflow to edit.")}):null,S?e.jsxs("div",{className:"wf-editor-empty",children:[e.jsx(Ie,{size:16,className:"wf-spin"})," ",o("workflows.loading","Loading…")]}):R.length===0?e.jsx("div",{className:"wf-editor-empty",children:o("workflows.noneYet","No workflows yet.")}):e.jsx("ul",{className:"wf-editor-list",children:R.map(t=>e.jsx("li",{children:e.jsx("button",{className:`wf-editor-list-item${t.id===O?" active":""}`,onClick:()=>Ia(t.id),children:t.name})},t.id))}),N&&!Ne&&e.jsxs("div",{className:"wf-sidebar-panels",children:[e.jsxs("section",{className:"wf-sidebar-section","data-testid":"wf-sidebar-columns-section",children:[e.jsxs("button",{type:"button",className:"wf-sidebar-section-toggle","aria-expanded":!at,"data-testid":"wf-sidebar-columns-toggle",onClick:()=>ua(t=>!t),children:[at?e.jsx(Me,{size:13}):e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowColumns.title","Columns")})]}),!at&&e.jsx(Rs,{columns:Z,onChange:et,violations:Gt,readOnly:L,projectId:r,addToast:i,columnAgentsEnabled:Ao})]}),e.jsxs("section",{className:"wf-sidebar-section","data-testid":"wf-sidebar-fields-section",children:[e.jsxs("button",{type:"button",className:"wf-sidebar-section-toggle","aria-expanded":!nt,"data-testid":"wf-sidebar-fields-toggle",onClick:()=>fa(t=>!t),children:[nt?e.jsx(Me,{size:13}):e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowFields.title","Fields")})]}),!nt&&e.jsx(Ms,{fields:Fe,onChange:tt,readOnly:L,addToast:i})]}),e.jsxs("section",{className:"wf-sidebar-section","data-testid":"wf-sidebar-settings-section",children:[e.jsxs("button",{type:"button",className:"wf-sidebar-section-toggle","aria-expanded":!lt,"data-testid":"wf-sidebar-settings-toggle",onClick:()=>pa(t=>!t),children:[lt?e.jsx(Me,{size:13}):e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowSettings.title","Settings")})]}),!lt&&e.jsx("div",{ref:Pt,className:"wf-settings-panel-wrap",children:e.jsx(Ts,{workflowId:N.id,settings:Pe,onChange:ot,readOnly:L,projectId:r,addToast:i,initialTab:"values"})})]})]})]}),e.jsxs("section",{className:"wf-editor-canvas-wrap",children:[e.jsxs("button",{type:"button",className:"wf-editor-mobile-back",onClick:()=>c(!0),"aria-label":o("workflows.backToWorkflowList","Back to workflows"),children:[e.jsx(ks,{size:16}),e.jsx("span",{children:o("common.back","Back")})]}),N?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"wf-name-strip",children:[st&&!x&&e.jsx("button",{type:"button",className:"wf-sidebar-shell-restore","data-testid":"wf-sidebar-restore","aria-expanded":"false","aria-label":o("workflows.showSidebar","Show workflow sidebar"),title:o("workflows.showSidebar","Show workflow sidebar"),onClick:()=>ko(!1),children:e.jsx(Me,{size:14,"aria-hidden":!0})}),e.jsx(Le,{workflowId:N.id,icon:oe,decorative:!0}),L?e.jsx("span",{className:"wf-workflow-name wf-workflow-name--readonly","data-testid":"wf-workflow-name",children:N.name}):ge?e.jsx("input",{className:"wf-workflow-name-input","data-testid":"wf-workflow-name-input",autoFocus:!0,value:m,"aria-label":o("workflows.nameLabel","Workflow name"),onChange:t=>_(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),m.trim()||_(N.name),J(!1)):t.key==="Escape"&&(t.preventDefault(),_(N.name),J(!1))},onBlur:()=>{m.trim()||_(N.name),J(!1)}}):e.jsx("button",{type:"button",className:"wf-workflow-name","data-testid":"wf-workflow-name",onClick:()=>J(!0),title:o("workflows.clickToRename","Click to rename"),children:m||N.name}),L?null:e.jsx("input",{className:"wf-workflow-icon-input","data-testid":"wf-workflow-icon-input",value:oe??"",maxLength:16,"aria-label":o("workflows.iconLabel","Icon (optional)"),placeholder:o("workflows.iconPlaceholder","e.g. 🚀"),onChange:t=>K(t.target.value)}),L?N.description?e.jsx("span",{className:"wf-workflow-description wf-workflow-description--readonly","data-testid":"wf-workflow-description",children:N.description}):null:Ce?e.jsx("input",{className:"wf-workflow-description-input","data-testid":"wf-workflow-description-input",autoFocus:!0,value:H,"aria-label":o("workflows.descriptionLabel","Workflow description"),placeholder:o("workflows.descriptionPlaceholder","Add a description"),onChange:t=>Q(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),Qe(!1)):t.key==="Escape"&&(t.preventDefault(),Q(N.description??""),Qe(!1))},onBlur:()=>Qe(!1)}):e.jsx("button",{type:"button",className:"wf-workflow-description","data-testid":"wf-workflow-description",onClick:()=>Qe(!0),title:o("workflows.clickToEditDescription","Click to edit description"),children:H||o("workflows.descriptionPlaceholder","Add a description")}),!x&&e.jsxs("button",{type:"button",className:"wf-layout-toggle","data-testid":"wf-layout-toggle","aria-pressed":ie,onClick:()=>X(t=>!t),children:[ie?e.jsx(to,{size:14}):e.jsx(Qs,{size:14}),e.jsx("span",{children:ie?o("workflows.showCanvasEditor","Show canvas editor"):o("workflows.showSimpleEditor","Show simple editor")})]})]}),So.length>0&&e.jsxs("div",{className:"wf-lifecycle-warnings",role:"status","data-testid":"wf-lifecycle-warnings",children:[e.jsxs("div",{className:"wf-lifecycle-warnings-title",children:[e.jsx(Zs,{size:14,"aria-hidden":!0}),e.jsx("span",{children:o("workflows.lifecycleWarningsTitle","Lifecycle warnings")})]}),e.jsx("ul",{children:So.map((t,a)=>e.jsxs("li",{children:[e.jsx("span",{className:"wf-lifecycle-warning-code",children:t.code}),t.nodeId&&e.jsx("span",{className:"wf-lifecycle-warning-node",children:t.nodeId}),e.jsx("span",{children:t.message})]},`${t.code}:${t.nodeId??""}:${a}`))})]}),Ne&&e.jsxs("div",{className:"wf-mobile-shell","data-testid":"wf-mobile-shell",children:[e.jsx("nav",{className:"wf-mobile-tabs","aria-label":o("workflows.mobileEditorNav","Workflow editor sections"),children:[["graph",o("workflowNodes.mobileGraph","Graph")],["add",o("workflowNodes.mobileAdd","Add")],["settings",o("workflowSettings.title","Settings")],["fields",o("workflowFields.title","Fields")],["columns",o("workflowColumns.title","Columns")],["actions",o("workflowNodes.mobileActions","Actions")]].map(([t,a])=>e.jsx("button",{type:"button",className:`wf-mobile-tab${ne===t?" wf-mobile-tab--active":""}`,"aria-current":ne===t?"page":void 0,"data-testid":`wf-mobile-tab-${t}`,onClick:()=>re(t),children:a},t))}),e.jsxs("div",{className:"wf-mobile-panel","data-testid":`wf-mobile-panel-${ne}`,children:[ne==="graph"&&e.jsx(Pl,{rows:Pa,selectedNodeId:te,selectedEdgeId:v,onSelectNode:t=>{V(t),T(null),G(!1)},onSelectEdge:t=>{T(t),V(null)},onCreateConnection:L?void 0:ba,canReorder:!L,onMoveNode:ka}),ne==="add"&&e.jsx("div",{className:"wf-mobile-add",children:L?e.jsxs("p",{className:"wf-inspector-note wf-inspector-note--info wf-inspector-note--with-icon",children:[e.jsx(Le,{workflowId:N.id,decorative:!0}),e.jsx("span",{children:o("workflows.readOnlyBuiltin","Workflow structure is read-only; prompts are editable.")})]}):e.jsxs(e.Fragment,{children:[e.jsxs("section",{className:"wf-mobile-add-section",children:[e.jsx("h3",{children:o("workflowNodes.mobileNodeKinds","Node types")}),e.jsx("div",{className:"wf-mobile-add-grid",children:qs.map(({kind:t,label:a,icon:l,presetConfig:u})=>e.jsxs("button",{type:"button",className:"wf-mobile-add-option","data-testid":`wf-mobile-add-${t}-${a.toLowerCase().replace(/[^a-z0-9]+/g,"-")}`,onClick:()=>{xt(t,a,u),re("graph")},children:[e.jsx(l,{size:16,"aria-hidden":!0}),e.jsx("span",{children:a})]},a))})]}),Ro&&e.jsxs("section",{className:"wf-mobile-add-section",children:[e.jsx("h3",{children:o("workflowNodes.templatesSection","Templates")}),Bt>8&&e.jsx("input",{type:"text",className:"wf-templates-filter wf-mobile-template-filter","data-testid":"wf-mobile-template-filter",value:pt,onChange:t=>po(t.target.value),placeholder:o("workflowNodes.templateFilterPlaceholder","Filter templates"),"aria-label":o("workflowNodes.templateFilterLabel","Filter templates")}),mt&&e.jsx("div",{className:"wf-templates-conflict",role:"alert","data-testid":"wf-mobile-tpl-conflict",children:o("workflowNodes.templateSeamConflict",`This fragment duplicates the "{{seam}}" seam already on the canvas, so it can't be inserted.`,{seam:mt})}),pe.fragmentEntries.length>0&&e.jsxs("div",{className:"wf-mobile-template-group",children:[e.jsx("h4",{children:o("workflowNodes.templatesFragments","Fragments")}),pe.fragmentEntries.map(t=>e.jsx("button",{type:"button",className:"wf-mobile-template-option","data-testid":`wf-mobile-tpl-fragment-${t.id}`,onClick:()=>{Io(t)&&re("graph")},children:t.name},t.id))]}),pe.stepEntries.length>0&&e.jsxs("div",{className:"wf-mobile-template-group",children:[e.jsx("h4",{children:o("workflowNodes.templatesBuiltinSteps","Fusion steps")}),pe.stepEntries.map(t=>e.jsxs("div",{className:"wf-mobile-template-option-row",children:[e.jsx("button",{type:"button",className:"wf-mobile-template-option","data-testid":`wf-mobile-tpl-step-${t.id}`,onClick:()=>{vt(t),re("graph")},children:t.name}),e.jsx("button",{type:"button",className:"wf-mobile-template-option-optional","data-testid":`wf-mobile-tpl-step-${t.id}-optional-group`,"aria-label":o("workflowNodes.insertTemplateAsOptionalGroup","Insert {{name}} as optional group",{name:t.name}),onClick:()=>{Mo(t),re("graph")},children:o("workflowNodes.asOptionalGroup","as optional group")})]},t.id))]}),pe.pluginEntries.length>0&&e.jsxs("div",{className:"wf-mobile-template-group",children:[e.jsx("h4",{children:o("workflowNodes.templatesPluginSteps","Plugin steps")}),pe.pluginEntries.map(({pluginId:t,template:a})=>e.jsxs("button",{type:"button",className:"wf-mobile-template-option","data-testid":`wf-mobile-tpl-plugin-${a.id}`,onClick:()=>{vt(a),re("graph")},children:[e.jsx("span",{children:a.name}),e.jsx("span",{className:"wf-templates-badge",children:t})]},`${t}:${a.id}`))]})]})]})}),ne==="settings"&&N&&e.jsx("div",{ref:Pt,className:"wf-mobile-destination",children:e.jsx(Ts,{workflowId:N.id,settings:Pe,onChange:ot,readOnly:L,projectId:r,addToast:i,initialTab:"values"})}),ne==="fields"&&e.jsx("div",{className:"wf-mobile-destination",children:e.jsx(Ms,{fields:Fe,onChange:tt,readOnly:L,addToast:i})}),ne==="columns"&&e.jsx("div",{className:"wf-mobile-destination",children:e.jsx(Rs,{columns:Z,onChange:et,violations:Gt,readOnly:L,projectId:r,addToast:i,columnAgentsEnabled:Ao})}),ne==="actions"&&e.jsx("div",{className:"wf-mobile-actions",children:L?e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"wf-inspector-note wf-inspector-note--info wf-inspector-note--with-icon",children:[e.jsx(Le,{workflowId:N.id,decorative:!0}),e.jsx("span",{children:o("workflows.readOnlyBuiltin","Workflow structure is read-only; prompts are editable.")})]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-export",onClick:bt,children:[e.jsx(St,{size:15})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-save wf-editor-duplicate-primary","data-testid":"wf-mobile-duplicate",onClick:_o,children:[e.jsx(Re,{size:15})," ",o("workflows.duplicateToCustomize","Duplicate to customize")]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"wf-editor-save","data-testid":"wf-mobile-save",onClick:Bo,disabled:$,children:[$?e.jsx(Ie,{size:15,className:"wf-spin"}):e.jsx(io,{size:15}),o("common.save","Save")]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-ai-edit",onClick:()=>zt(t=>!t),children:[e.jsx(Je,{size:15})," ",o("workflows.aiEdit","Design with AI")]}),Lt&&e.jsxs("div",{className:"wf-ai-panel wf-mobile-ai-panel","data-testid":"wf-mobile-ai-panel",role:"dialog","aria-busy":be,children:[e.jsx("textarea",{className:"wf-ai-prompt","data-testid":"wf-mobile-ai-edit-prompt",rows:4,value:ht,disabled:be,placeholder:o("workflows.aiPromptPlaceholder","e.g. Run lint and tests before merge, then post a changelog comment after merge"),onChange:t=>{Wt(t.target.value),Ge&&qe(null)}}),Ge&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-mobile-ai-edit-error",children:Ge}),e.jsxs("div",{className:"wf-ai-actions",children:[e.jsxs("button",{type:"button",className:"btn btn-primary wf-ai-submit","data-testid":"wf-mobile-ai-edit-submit",disabled:be,onClick:()=>void Do(),children:[be?e.jsx(Ie,{size:13,className:"wf-spin"}):e.jsx(Je,{size:13}),o("workflows.aiSubmit","Design with AI")]}),be&&e.jsx("button",{type:"button",className:"btn wf-ai-cancel",onClick:To,children:o("common.cancel","Cancel")})]})]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-auto-layout",onClick:Oo,children:[e.jsx(to,{size:15})," ",o("workflowNodes.autoLayout","Auto-layout")]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-export",onClick:bt,disabled:it,children:[e.jsx(St,{size:15})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-delete","data-testid":"wf-mobile-delete",onClick:$o,children:[e.jsx(ve,{size:15})," ",o("common.delete","Delete")]})]})})]})]}),L?e.jsxs("div",{className:"wf-editor-readonly-banner",role:"status","data-testid":"wf-readonly-banner",children:[e.jsxs("span",{className:"wf-editor-readonly-note",children:[e.jsx(Le,{workflowId:N.id,decorative:!0}),e.jsx("span",{children:o("workflows.readOnlyBuiltin","Workflow structure is read-only; prompts are editable.")})]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-export",onClick:bt,title:o("workflows.exportTooltip","Download as JSON — contains your full prompt and command text"),children:[e.jsx(St,{size:13})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-save wf-editor-duplicate-primary",onClick:_o,children:[e.jsx(Re,{size:13})," ",o("workflows.duplicateToCustomize","Duplicate to customize")]})]}):e.jsxs("div",{className:"wf-editor-toolbar",children:[e.jsx("div",{className:"wf-editor-palette",children:qs.map(({kind:t,label:a,icon:l,presetConfig:u})=>e.jsxs("button",{className:"wf-palette-btn",onClick:()=>xt(t,a,u),children:[e.jsx(l,{size:13})," ",a]},a))}),e.jsxs("div",{className:"wf-editor-actions",children:[e.jsxs("div",{className:"wf-ai-edit-wrap",children:[e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-ai-edit","aria-expanded":Lt,onClick:()=>{zt(t=>!t),qe(null)},children:[e.jsx(Je,{size:13})," ",o("workflows.aiEdit","Design with AI")]}),Lt&&e.jsxs("div",{className:"wf-ai-panel","data-testid":"wf-ai-panel",role:"dialog","aria-busy":be,"aria-label":o("workflows.aiEdit","Design with AI"),children:[e.jsx("textarea",{className:"wf-ai-prompt","data-testid":"wf-ai-edit-prompt",rows:3,value:ht,disabled:be,placeholder:o("workflows.aiPromptPlaceholder","e.g. Run lint and tests before merge, then post a changelog comment after merge"),onChange:t=>{Wt(t.target.value),Ge&&qe(null)}}),Ge&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-ai-edit-error",children:Ge}),e.jsxs("div",{className:"wf-ai-actions",children:[e.jsxs("button",{type:"button",className:"btn btn-primary wf-ai-submit","data-testid":"wf-ai-edit-submit",disabled:be,onClick:()=>void Do(),children:[be?e.jsx(Ie,{size:13,className:"wf-spin"}):e.jsx(Je,{size:13})," ",o("workflows.aiSubmit","Design with AI")]}),be&&e.jsx("button",{type:"button",className:"btn wf-ai-cancel","data-testid":"wf-ai-edit-cancel",onClick:To,children:o("common.cancel","Cancel")})]})]})]}),e.jsxs("button",{className:"wf-editor-action",onClick:Oo,"data-testid":"wf-auto-layout",children:[e.jsx(to,{size:13})," ",o("workflowNodes.autoLayout","Auto-layout")]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-export",onClick:bt,disabled:it,title:it?o("workflows.exportDirtyTooltip","Save before exporting"):o("workflows.exportTooltip","Download as JSON — contains your full prompt and command text"),children:[e.jsx(St,{size:13})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-delete",onClick:$o,children:[e.jsx(ve,{size:13})," ",o("common.delete","Delete")]}),e.jsxs("button",{className:"wf-editor-save",onClick:Bo,disabled:$,children:[$?e.jsx(Ie,{size:13,className:"wf-spin"}):e.jsx(io,{size:13})," ",o("common.save","Save")]})]})]}),Ro&&e.jsxs("section",{className:"wf-templates","data-testid":"wf-palette-templates","aria-label":o("workflowNodes.templatesSection","Templates"),children:[e.jsxs("div",{className:"wf-templates-header",children:[e.jsxs("button",{type:"button",className:"wf-templates-toggle","aria-expanded":!Be,"data-testid":"wf-templates-toggle",onClick:()=>ca(t=>!t),children:[Be?e.jsx(Me,{size:13}):e.jsx(Ae,{size:13}),e.jsx(Xn,{size:13})," ",o("workflowNodes.templatesSection","Templates")]}),!Be&&Bt>8&&e.jsx("input",{type:"text",className:"wf-templates-filter","data-testid":"wf-template-filter",value:pt,onChange:t=>po(t.target.value),placeholder:o("workflowNodes.templateFilterPlaceholder","Filter templates"),"aria-label":o("workflowNodes.templateFilterLabel","Filter templates")})]}),!Be&&e.jsxs("div",{className:"wf-templates-body",children:[mt&&e.jsx("div",{className:"wf-templates-conflict",role:"alert","data-testid":"wf-tpl-conflict",children:o("workflowNodes.templateSeamConflict",`This fragment duplicates the "{{seam}}" seam already on the canvas, so it can't be inserted.`,{seam:mt})}),pe.fragmentEntries.length>0&&e.jsxs("div",{className:"wf-templates-group",children:[e.jsx("h4",{className:"wf-templates-group-title",children:o("workflowNodes.templatesFragments","Fragments")}),e.jsx("div",{className:"wf-templates-entries",children:pe.fragmentEntries.map(t=>e.jsx("button",{type:"button",className:"wf-templates-entry","data-testid":`wf-tpl-fragment-${t.id}`,disabled:L,"aria-label":o("workflowNodes.insertTemplate","Insert template {{name}}",{name:t.name}),onClick:()=>Io(t),children:t.name},t.id))})]}),pe.stepEntries.length>0&&e.jsxs("div",{className:"wf-templates-group",children:[e.jsx("h4",{className:"wf-templates-group-title",children:o("workflowNodes.templatesBuiltinSteps","Fusion steps")}),e.jsx("div",{className:"wf-templates-entries",children:pe.stepEntries.map(t=>e.jsxs("div",{className:"wf-templates-entry-row",children:[e.jsx("button",{type:"button",className:"wf-templates-entry","data-testid":`wf-tpl-step-${t.id}`,disabled:L,"aria-label":o("workflowNodes.insertTemplate","Insert template {{name}}",{name:t.name}),onClick:()=>vt(t),children:t.name}),e.jsx("button",{type:"button",className:"wf-templates-entry-optional","data-testid":`wf-tpl-step-${t.id}-optional-group`,disabled:L,title:o("workflowNodes.insertAsOptionalGroup","Insert as optional group"),"aria-label":o("workflowNodes.insertTemplateAsOptionalGroup","Insert {{name}} as optional group",{name:t.name}),onClick:()=>Mo(t),children:o("workflowNodes.asOptionalGroup","as optional group")})]},t.id))})]}),pe.pluginEntries.length>0&&e.jsxs("div",{className:"wf-templates-group",children:[e.jsx("h4",{className:"wf-templates-group-title",children:o("workflowNodes.templatesPluginSteps","Plugin steps")}),e.jsx("div",{className:"wf-templates-entries",children:pe.pluginEntries.map(({pluginId:t,template:a})=>e.jsxs("button",{type:"button",className:"wf-templates-entry","data-testid":`wf-tpl-plugin-${a.id}`,disabled:L,"aria-label":o("workflowNodes.insertTemplate","Insert template {{name}}",{name:a.name}),onClick:()=>vt(a),children:[a.name,e.jsx("span",{className:"wf-templates-badge",children:t})]},`${t}:${a.id}`))})]})]})]}),M&&e.jsx("div",{className:"wf-editor-banner",role:"alert",children:M}),Oe.length>0&&e.jsx("div",{className:"wf-editor-banner wf-editor-banner--warn",role:"alert","data-testid":"wf-unplaced-summary",children:o("workflowColumns.unplacedCount","{{count}} nodes not placed in a column",{count:Oe.length})}),e.jsxs("div",{className:"wf-editor-canvas",ref:Dt,tabIndex:-1,children:[x&&B&&f&&f.data.kind!=="end"&&e.jsxs("button",{type:"button",className:"wf-inspector-toggle wf-inspector-toggle--collapsed","data-testid":"wf-inspector-toggle","aria-expanded":"false",onClick:()=>G(!1),children:[e.jsx(Me,{size:13}),e.jsx("span",{children:o("workflowNodes.showInspector","Show node details")})]}),ma&&e.jsx("div",{className:"wf-trivial-hint",role:"status","data-testid":"wf-trivial-hint",children:o("workflowNodes.trivialGraphHint","This workflow only runs start → end. Add steps from the palette above to build it out.")}),e.jsx(_n.Provider,{value:Qt,children:e.jsxs(_a,{nodes:He,edges:U,nodeTypes:Gn,onNodesChange:ue,onEdgesChange:ha,onConnect:ga,onNodeDragStop:xa,deleteKeyCode:L?null:["Backspace","Delete"],onBeforeDelete:va,onNodesDelete:ja,onEdgesDelete:Na,onNodeClick:(t,a)=>{V(a.id),T(null),G(!1)},onEdgeClick:(t,a)=>{T(a.id),V(null)},onPaneClick:()=>{V(null),T(null)},defaultEdgeOptions:{interactionWidth:Bn},defaultViewport:{x:0,y:0,zoom:1},children:[e.jsx(Ba,{}),e.jsx(Ga,{}),e.jsxs("button",{type:"button",className:`wf-minimap-toggle nodrag nopan${se?" wf-minimap-toggle--collapsed":""}`,"aria-expanded":!se,"aria-controls":"wf-workflow-minimap","data-testid":"wf-minimap-toggle",onClick:()=>fe(t=>!t),children:[se?e.jsx(vs,{size:13,"aria-hidden":!0}):e.jsx(gs,{size:13,"aria-hidden":!0}),e.jsx("span",{children:se?o("workflowNodes.showMiniMap","Show mini map"):o("workflowNodes.hideMiniMap","Hide mini map")})]}),!se&&e.jsx(qa,{id:"wf-workflow-minimap",pannable:!0,zoomable:!0,nodeColor:Wl,nodeStrokeColor:$l,maskColor:"color-mix(in srgb, var(--surface) 70%, transparent)",bgColor:"var(--surface)"})]})})]})]}):e.jsxs("div",{className:"wf-editor-empty wf-editor-canvas-empty wf-editor-onboard",children:[e.jsx(bs,{className:"wf-editor-onboard-icon",size:40,"aria-hidden":!0}),e.jsx("h3",{className:"wf-editor-onboard-title",children:o("workflows.emptyTitle","No workflow selected")}),e.jsx("p",{className:"wf-editor-onboard-text",children:o("workflows.emptyDescription","Workflows orchestrate the steps and gates that run around task execution. Create one to start arranging that flow.")}),e.jsxs("button",{className:"wf-editor-save wf-editor-onboard-cta","data-testid":"wf-empty-create",onClick:()=>ye(!0),children:[e.jsx(Re,{size:14})," ",o("workflows.newWorkflow","New workflow")]})]})]}),Go&&!(x&&B)&&e.jsxs("aside",{className:"wf-editor-inspector","data-testid":"wf-node-inspector",children:[e.jsxs("div",{className:"wf-inspector-heading",children:[e.jsx("h3",{children:Se?.title??o("workflowNodes.nodeInspector","Node")}),x&&e.jsxs("button",{type:"button",className:"wf-inspector-toggle wf-inspector-toggle--expanded","data-testid":"wf-inspector-toggle","aria-expanded":"true",onClick:()=>{Ne?V(null):G(!0)},children:[e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowNodes.collapseInspector","Collapse")})]})]}),Se&&e.jsxs("details",{className:"wf-inspector-help","data-testid":"wf-node-help",children:[e.jsxs("summary",{className:"wf-inspector-help-summary",children:[e.jsx(ea,{size:13,"aria-hidden":!0}),e.jsx("span",{children:o("workflowNodes.helpTitle","What does this node do?")}),Se.graphOnly&&e.jsx("span",{className:"wf-inspector-help-badge","data-testid":"wf-node-help-engine-managed",children:o("workflowNodes.helpEngineManaged","Engine-managed")})]}),e.jsxs("div",{className:"wf-inspector-help-body",children:[e.jsx("p",{className:"wf-inspector-help-summary-text",children:Se.summary}),e.jsxs("dl",{className:"wf-inspector-help-dl",children:[Se.configure&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:o("workflowNodes.helpConfigure","Configure")}),e.jsx("dd",{children:Se.configure})]}),e.jsx("dt",{children:o("workflowNodes.helpInputs","Inputs")}),e.jsx("dd",{children:Se.inputs}),e.jsx("dt",{children:o("workflowNodes.helpOutputs","Outputs")}),e.jsx("dd",{children:Se.outputs}),e.jsx("dt",{children:o("workflowNodes.helpEdges","Edges")}),e.jsx("dd",{children:Se.edges})]})]})]}),L&&e.jsxs("p",{className:"wf-inspector-note wf-inspector-note--info wf-inspector-note--with-icon",children:[e.jsx(Le,{workflowId:N.id,decorative:!0}),e.jsx("span",{children:o("workflowNodes.readOnlyDuplicateToEdit","Workflow structure is read-only — prompts on prompt and gate nodes can be edited here.")})]}),e.jsxs("fieldset",{className:"wf-inspector-fields",disabled:L,children:[f.data.kind!=="start"&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("common:labels.name","Name")}),e.jsx("input",{value:f.data.label,onChange:t=>W({label:t.target.value})})]}),f.data.kind==="start"&&e.jsxs("div",{"data-testid":"wf-start-inspector",children:[e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.startNote","The start node marks where a task enters the workflow.")}),Z.length>0&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.startEntryColumn","Entry column")}),e.jsxs("select",{"data-testid":"wf-start-entry-column",value:String(f.data.column??""),onChange:t=>W({column:t.target.value||void 0}),children:[e.jsx("option",{value:"",children:o("workflowNodes.startEntryColumnAuto","— Auto (first column)")}),Z.map(t=>e.jsx("option",{value:t.id,children:t.name},t.id))]})]})]})]}),f.data.kind==="prompt"||f.data.kind==="gate"?e.jsxs("div",{className:"wf-prompt-editor",children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.prompt","Prompt")}),e.jsx("textarea",{rows:5,value:Ue,readOnly:!Nt,onChange:t=>Ko(t.target.value),onBlur:Yo})]}),e.jsxs("div",{className:"wf-prompt-override-actions",children:[L&&Uo?e.jsx("span",{className:"wf-prompt-override-badge","data-testid":"wf-prompt-overridden",children:o("workflowEditor.promptOverridden","Overridden")}):null,L?e.jsx("button",{type:"button",className:"btn btn-sm",onClick:Jo,disabled:!Yt||jt,children:jt?o("workflowEditor.promptSaving","Saving…"):o("workflowEditor.resetPromptDefault","Reset to default")}):null]}),e.jsx("button",{type:"button",className:"btn btn-sm wf-prompt-expand-btn wf-prompt-expand-btn--inline",onClick:Vo,"aria-label":o("workflowEditor.expandPrompt","Expand prompt editor"),title:o("workflowEditor.expandPrompt","Expand prompt editor"),children:e.jsx(vs,{size:14})})]}):null,e.jsxs("fieldset",{className:"wf-inspector-fields",disabled:L,children:[f.data.kind==="prompt"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.executor","Executor")}),e.jsxs("select",{value:me,onChange:t=>W({config:{executor:t.target.value}}),children:[e.jsx("option",{value:"model",children:o("workflowEditor.model","Model")}),e.jsx("option",{value:"agent",children:o("workflowEditor.agent","Agent")}),e.jsx("option",{value:"skill",children:o("workflowEditor.skill","Skill")}),e.jsx("option",{value:"cli",children:o("workflowEditor.cliScript","CLI / script")}),e.jsx("option",{value:"cli-agent",children:o("workflowEditor.cliAgent.executorOption")})]})]}),Te&&e.jsx("p",{className:"wf-inspector-note wf-inspector-note--warn","data-testid":"wf-node-overridden-by-column-agent",children:o("workflowColumns.overriddenByColumnAgent","Overridden by column agent {{name}} — this node's executor settings are superseded.",{name:Ma?.name??o("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:Te.agentId})})}),me==="model"&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.model","Model")}),e.jsx(ro,{label:o("workflowEditor.model","Model"),models:De,value:Ws(String(f.data.config?.modelProvider??""),String(f.data.config?.modelId??"")),onChange:t=>{const{provider:a,modelId:l}=$s(t);W({config:{modelProvider:a||void 0,modelId:l||void 0}})}})]}),me==="agent"&&(()=>{const t=String(f.data.config?.agentId??""),a=t!==""&&!xe.some(l=>l.id===t);return e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.agent","Agent")}),e.jsxs("select",{value:t,onChange:l=>W({config:{agentId:l.target.value||void 0}}),children:[e.jsx("option",{value:"",children:o("workflowEditor.selectAgent","— select agent —")}),a&&e.jsx("option",{value:t,children:o("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:t})}),xe.map(l=>e.jsx("option",{value:l.id,children:l.name},l.id))]}),a&&e.jsx("p",{className:"wf-inspector-note wf-inspector-note--warn","data-testid":"wf-node-agent-stale",children:o("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:t})})]})})(),me==="skill"&&(()=>{const t=String(f.data.config?.skillName??""),a=t?Ke.find(u=>js(u.name)===js(t)):void 0,l=a?a.name:t;return e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.skill","Skill")}),e.jsxs("select",{value:l,onChange:u=>W({config:{skillName:u.target.value||void 0}}),children:[e.jsx("option",{value:"",children:o("workflowEditor.selectSkill","— select skill —")}),Ke.map(u=>e.jsx("option",{value:u.name,children:u.name},u.id))]})]})})(),me==="cli"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.cliMode","CLI mode")}),e.jsxs("select",{value:String(f.data.config?.cliMode??"command"),onChange:t=>W({config:{cliMode:t.target.value}}),children:[e.jsx("option",{value:"command",children:o("workflowEditor.command","Command")}),e.jsx("option",{value:"script",children:o("workflowEditor.namedScript","Named script")})]})]}),(f.data.config?.cliMode??"command")==="command"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.command","Command")}),e.jsx("textarea",{rows:3,placeholder:Gl,value:String(f.data.config?.cliCommand??""),onChange:t=>W({config:{cliCommand:t.target.value}})}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowEditor.cliCommandNote","Runs an arbitrary command in the task worktree. The first time this exact command runs, the task pauses for your approval. The node prompt is passed via FUSION_NODE_PROMPT.")}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:f.data.config?.cliSkipApproval===!0,onChange:t=>W({config:{cliSkipApproval:t.target.checked}})}),e.jsx("span",{children:o("workflowEditor.skipFirstRunApproval","Skip first-run approval (runs without pausing)")})]})]}):e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.scriptName","Script name")}),e.jsx("input",{value:String(f.data.config?.scriptName??""),onChange:t=>W({config:{scriptName:t.target.value}})}),e.jsx("span",{className:"wf-inspector-note",children:o("workflowEditor.namedScriptNote","Named script from project settings. The node prompt is passed via FUSION_NODE_PROMPT.")})]})]}),me==="cli-agent"&&e.jsxs("div",{"data-testid":"cli-agent-config",children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.cliAgent.adapterLabel")}),e.jsxs("select",{"data-testid":"cli-agent-adapter",value:String(f.data.config?.cliAdapterId??""),onChange:t=>W({config:{cliAdapterId:t.target.value||void 0}}),children:[e.jsx("option",{value:"",children:o("workflowEditor.cliAgent.adapterPlaceholder")}),Ra.map(t=>e.jsxs("option",{value:t.id,children:[t.name," (",o(`workflowEditor.cliAgent.tier.${t.tier}`),")"]},t.id))]}),e.jsx("span",{className:"wf-inspector-note",children:o("workflowEditor.cliAgent.adapterNote")})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox","data-testid":"cli-agent-autonomy",checked:!!f.data.config?.cliAutonomy?.autoApprove,onChange:t=>W({config:{cliAutonomy:{...f.data.config?.cliAutonomy??{},autoApprove:t.target.checked}}})}),e.jsx("span",{children:o("workflowEditor.cliAgent.autonomyLabel")})]}),!!f.data.config?.cliAutonomy?.autoApprove&&e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowEditor.cliAgent.autonomyNote")}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.cliAgent.notifyLabel")}),e.jsxs("select",{"data-testid":"cli-agent-notify",value:String(f.data.config?.cliNotify?.mode??"banner"),onChange:t=>W({config:{cliNotify:{mode:t.target.value}}}),children:[e.jsx("option",{value:"banner",children:o("workflowEditor.cliAgent.notify.banner")}),e.jsx("option",{value:"banner+notify",children:o("workflowEditor.cliAgent.notify.bannerNotify")})]}),e.jsx("span",{className:"wf-inspector-note",children:o("workflowEditor.cliAgent.notifyNote")})]})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:!!f.data.config?.autoApprove,onChange:t=>W({config:{autoApprove:t.target.checked}})}),e.jsx("span",{children:o("workflowEditor.autoApproveRequests","Auto-approve requests")})]}),!!f.data.config?.autoApprove&&e.jsx("p",{className:"wf-inspector-note",children:o("workflowEditor.autoApproveRequestsNote","Runs without pausing for approval — e.g. a CLI command executes on its first run without waiting for your sign-off.")}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.maxRetries","Max retries")}),e.jsx("input",{type:"number",min:1,max:10,placeholder:"default",value:f.data.config?.maxRetries!=null?String(f.data.config.maxRetries):"",onChange:t=>{const a=t.target.value.trim();if(a==="")W({config:l=>{const u={...l};return delete u.maxRetries,u}});else{const l=parseInt(a,10);isNaN(l)||W({config:{maxRetries:l}})}}})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:!!f.data.config?.awaitInput,onChange:t=>W({config:{awaitInput:t.target.checked}})}),e.jsx("span",{children:o("workflowEditor.waitForUserInput","Wait for user input")})]}),!!f.data.config?.awaitInput&&e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowEditor.waitForUserInputNote","This node pauses the task until you reply in the task's comments and unpause. The Prompt field above is shown to the user as the question.")})]}):null,f.data.kind==="script"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.scriptName","Script name")}),e.jsx("input",{value:String(f.data.config?.scriptName??""),onChange:t=>W({config:{scriptName:t.target.value}})})]}):null,f.data.kind==="hold"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.releaseCondition","Release condition")}),e.jsxs("select",{value:String(f.data.config?.release??"manual"),onChange:t=>W({config:{release:t.target.value}}),children:[e.jsx("option",{value:"manual",children:o("workflowNodes.releaseManual","Manual promote")}),e.jsx("option",{value:"timer",children:o("workflowNodes.releaseTimer","Timer")}),e.jsx("option",{value:"capacity",children:o("workflowNodes.releaseCapacity","Downstream capacity")}),e.jsx("option",{value:"dependency",children:o("workflowNodes.releaseDependency","Dependency complete")}),e.jsx("option",{value:"external-event",children:o("workflowNodes.releaseExternal","External event")})]})]}):null,f.data.kind==="join"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.joinMode","Join mode")}),e.jsxs("select",{value:(()=>{const t=f.data.config?.mode;return t&&typeof t=="object"&&"quorum"in t?"quorum":typeof t=="string"?t:"all"})(),onChange:t=>{const a=t.target.value;W(a==="quorum"?{config:{mode:{quorum:2}}}:{config:{mode:a}})},children:[e.jsx("option",{value:"all",children:o("workflowNodes.joinAll","All branches")}),e.jsx("option",{value:"any",children:o("workflowNodes.joinAny","Any branch")}),e.jsx("option",{value:"quorum",children:o("workflowNodes.joinQuorum","Quorum (n)")})]})]}),(()=>{const t=f.data.config?.mode;return t&&typeof t=="object"&&"quorum"in t})()&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.quorumN","Quorum count (n)")}),e.jsx("input",{type:"number",min:1,value:String(f.data.config?.mode?.quorum??2),onChange:t=>{const a=parseInt(t.target.value,10);isNaN(a)||W({config:{mode:{quorum:a}}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.failurePolicy","On branch failure")}),e.jsxs("select",{value:String(f.data.config?.onBranchFailure??"collect"),onChange:t=>W({config:{onBranchFailure:t.target.value}}),children:[e.jsx("option",{value:"collect",children:o("workflowNodes.failureCollect","Collect (wait for all)")}),e.jsx("option",{value:"fail-fast",children:o("workflowNodes.failureFailFast","Fail-fast (cancel siblings)")})]})]})]}):null,f.data.kind==="split"?e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.splitNote","Branches run concurrently from this node. Execute and merge seams are not allowed inside a branch.")}):null,f.data.kind==="foreach"?(()=>{const t=String(f.data.config?.mode??"sequential"),a=t==="parallel";return e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.foreachMode","Mode")}),e.jsxs("select",{value:t,onChange:l=>{const u=l.target.value;W({config:h=>({...h,mode:u,...u==="parallel"&&h.isolation==="shared"?{isolation:"worktree"}:{}})})},children:[e.jsx("option",{value:"sequential",children:o("workflowNodes.foreachSequential","Sequential")}),e.jsx("option",{value:"parallel",children:o("workflowNodes.foreachParallel","Parallel")})]})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.foreachIsolation","Isolation")}),e.jsxs("select",{value:String(f.data.config?.isolation??(a?"worktree":"shared")),onChange:l=>W({config:{isolation:l.target.value}}),children:[e.jsx("option",{value:"shared",disabled:a,children:o("workflowNodes.foreachShared","Shared worktree")}),e.jsx("option",{value:"worktree",children:o("workflowNodes.foreachWorktree","Per-step worktree")})]})]}),a&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.foreachConcurrency","Concurrency")}),e.jsx("input",{type:"number",min:1,max:8,placeholder:"2",value:f.data.config?.concurrency!=null?String(f.data.config.concurrency):"",onChange:l=>{const u=l.target.value.trim();if(u==="")W({config:h=>{const F={...h};return delete F.concurrency,F}});else{const h=parseInt(u,10);isNaN(h)||W({config:{concurrency:h}})}}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.foreachMaxRework","Max rework cycles")}),e.jsx("input",{type:"number",min:1,max:10,placeholder:"3",value:f.data.config?.maxReworkCycles!=null?String(f.data.config.maxReworkCycles):"",onChange:l=>{const u=l.target.value.trim();if(u==="")W({config:h=>{const F={...h};return delete F.maxReworkCycles,F}});else{const h=parseInt(u,10);isNaN(h)||W({config:{maxReworkCycles:h}})}}})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.foreachNote","Expands once per planned step. Drop a step-execute node (and optional step-review) into the region.")})]})})():null,f.data.kind==="loop"?(()=>{const t=f.data.config?.exitWhen&&typeof f.data.config.exitWhen=="object"?f.data.config.exitWhen:{type:"output-contains",value:"DONE"},a=String(t.type??"output-contains"),l=String(a==="output-matches"?t.pattern??"":t.value??"");return e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.loopExitType","Exit condition")}),e.jsxs("select",{value:a,onChange:u=>{const h=u.target.value;W({config:F=>{const E=F.exitWhen&&typeof F.exitWhen=="object"?F.exitWhen:{},ee=String(h==="output-matches"?E.pattern??E.value??"":E.value??E.pattern??""),Ee={...E,type:h};return delete Ee.pattern,delete Ee.value,{...F,exitWhen:h==="output-matches"?{...Ee,pattern:ee}:{...Ee,value:ee}}}})},children:[e.jsx("option",{value:"output-contains",children:o("workflowNodes.loopOutputContains","Output contains")}),e.jsx("option",{value:"output-matches",children:o("workflowNodes.loopOutputMatches","Output matches regex")})]})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:a==="output-matches"?o("workflowNodes.loopPattern","Pattern"):o("workflowNodes.loopValue","Value")}),e.jsx("input",{value:l,placeholder:a==="output-matches"?"DONE|COMPLETE":"DONE",onChange:u=>{const h=u.target.value;W({config:F=>{const E=F.exitWhen&&typeof F.exitWhen=="object"?F.exitWhen:{};return{...F,exitWhen:a==="output-matches"?{...E,type:a,pattern:h}:{...E,type:a,value:h}}}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.loopNodeId","Watch node id (optional)")}),e.jsx("input",{value:String(t.nodeId??""),placeholder:o("workflowNodes.loopNodeIdPlaceholder","Template exit node"),onChange:u=>{const h=u.target.value.trim();W({config:F=>{const ee={...F.exitWhen&&typeof F.exitWhen=="object"?F.exitWhen:{type:"output-contains",value:"DONE"}};return h?ee.nodeId=h:delete ee.nodeId,{...F,exitWhen:ee}}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.loopMaxIterations","Max iterations")}),e.jsx("input",{type:"number",min:1,max:50,placeholder:"3",value:f.data.config?.maxIterations!=null?String(f.data.config.maxIterations):"",onChange:u=>{const h=u.target.value.trim();W({config:F=>{const E={...F};if(h==="")delete E.maxIterations;else{const ee=parseInt(h,10);isNaN(ee)||(E.maxIterations=ee)}return E}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.loopTimeoutMs","Timeout (ms)")}),e.jsx("input",{type:"number",min:1,max:36e5,placeholder:"300000",value:f.data.config?.timeoutMs!=null?String(f.data.config.timeoutMs):"",onChange:u=>{const h=u.target.value.trim();W({config:F=>{const E={...F};if(h==="")delete E.timeoutMs;else{const ee=parseInt(h,10);isNaN(ee)||(E.timeoutMs=ee)}return E}})}})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.loopNote","Repeats the template until the selected output matches, an iteration limit is reached, or the timeout expires.")})]})})():null,f.data.kind==="optional-group"?(()=>{const t=f.data.config?.maxRevisions,a=t==="unbounded";return e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox","data-testid":"wf-optional-group-default-on",checked:!!f.data.config?.defaultOn,onChange:l=>W({config:{defaultOn:l.target.checked}})}),e.jsx("span",{children:o("workflowNodes.optionalGroupDefaultOn","Enabled by default for new tasks")})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.optionalGroupMaxRevisions","Max revisions")}),e.jsx("input",{type:"number",min:0,placeholder:o("workflowNodes.optionalGroupMaxRevisionsPlaceholder","Use global setting"),"data-testid":"wf-optional-group-max-revisions",disabled:a,value:typeof t=="number"?String(t):"",onChange:l=>{const u=l.target.value.trim();W({config:h=>{const F={...h};if(u==="")delete F.maxRevisions;else{const E=parseInt(u,10);!isNaN(E)&&E>=0&&(F.maxRevisions=E)}return F}})}})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox","data-testid":"wf-optional-group-max-revisions-unbounded",checked:a,onChange:l=>{W({config:u=>{const h={...u};return l.target.checked?h.maxRevisions="unbounded":h.maxRevisions==="unbounded"&&delete h.maxRevisions,h}})}}),e.jsx("span",{children:o("workflowNodes.optionalGroupMaxRevisionsUnbounded","Unbounded")})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.optionalGroupNote","Runs the steps inside this group once when the task enables it (seeded from this default), and skips them when disabled. Drop the optional steps into the region.")})]})})():null,f.data.kind==="step-review"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.reviewType","Review type")}),e.jsxs("select",{value:String(f.data.config?.type??"code"),onChange:t=>W({config:{type:t.target.value}}),children:[e.jsx("option",{value:"plan",children:o("workflowNodes.reviewPlan","Plan review")}),e.jsx("option",{value:"code",children:o("workflowNodes.reviewCode","Code review")})]})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.reviewModel","Review model (optional)")}),e.jsx(ro,{label:o("workflowNodes.reviewModel","Review model (optional)"),models:De,value:Ws(String(f.data.config?.modelProvider??""),String(f.data.config?.modelId??"")),onChange:t=>{const{provider:a,modelId:l}=$s(t);W({config:{modelProvider:a||void 0,modelId:l||void 0,model:t||void 0}})}})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.reviewNote","Verdicts route as outcome edges. Click an outgoing edge to set its verdict and rework behavior.")})]}):null,f.data.kind==="parse-steps"?e.jsxs(e.Fragment,{children:[Jt.length>0?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.parseArtifact","Artifact")}),e.jsx("select",{value:String(f.data.config?.artifact??Jt[0]),onChange:t=>W({config:{artifact:t.target.value}}),children:Jt.map(t=>e.jsx("option",{value:t,children:t},t))})]}):e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.parseArtifact","Artifact")}),e.jsx("input",{placeholder:"PROMPT.md",value:String(f.data.config?.artifact??"PROMPT.md"),onChange:t=>W({config:{artifact:t.target.value}})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.parseParser","Parser")}),e.jsx("select",{value:String(f.data.config?.parser??"step-headings"),onChange:t=>W({config:{parser:t.target.value}}),children:Array.from(new Set([String(f.data.config?.parser??"step-headings"),...la])).map(t=>e.jsx("option",{value:t,children:t},t))})]})]}):null,f.data.kind==="code"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.codeSource","Source (TypeScript)")}),e.jsx("textarea",{className:"wf-code-source",rows:8,spellCheck:!1,placeholder:ql,value:String(f.data.config?.source??""),onChange:t=>W({config:{source:t.target.value}})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.codeTimeout","Timeout (ms)")}),e.jsx("input",{type:"number",min:1,placeholder:"30000",value:f.data.config?.timeoutMs!=null?String(f.data.config.timeoutMs):"",onChange:t=>{const a=t.target.value.trim();if(a==="")W({config:l=>{const u={...l};return delete u.timeoutMs,u}});else{const l=parseInt(a,10);isNaN(l)||W({config:{timeoutMs:l}})}}})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.codeNote","Runs sandboxed TypeScript. Syntax is validated at save.")})]}):null,f.data.kind==="notify"?(()=>{const t=String(f.data.config?.event??"workflow-notify"),a=!Gs.includes(t);return e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.notifyEvent","Event type")}),e.jsxs("select",{value:a?no:t,onChange:l=>{const u=l.target.value;W({config:{event:u===no?"custom-event":u}})},children:[Gs.map(l=>e.jsx("option",{value:l,children:l},l)),e.jsx("option",{value:no,children:o("workflowNodes.notifyCustom","Custom")})]})]}),a?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.notifyCustomEvent","Custom event")}),e.jsx("input",{value:t,placeholder:"custom-event",onChange:l=>W({config:{event:l.target.value}})})]}):null,e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.notifyTitle","Title (optional)")}),e.jsx("input",{value:String(f.data.config?.title??"{{taskTitle}}"),placeholder:"{{taskTitle}}",onChange:l=>W({config:{title:l.target.value}})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.notifyMessage","Message (optional)")}),e.jsx("textarea",{rows:4,value:String(f.data.config?.message??""),placeholder:Vl,onChange:l=>W({config:{message:l.target.value}})})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.notifyNote","Templates may use {{taskTitle}}, {{taskId}}, {{workflowName}}, and {{context:key}}.")})]})})():null,f.data.kind==="prompt"||f.data.kind==="gate"||f.data.kind==="script"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.gateMode","Gate mode")}),e.jsxs("select",{value:String(f.data.config?.gateMode??(f.data.kind==="prompt"?"advisory":"gate")),onChange:t=>W({config:{gateMode:t.target.value}}),children:[e.jsx("option",{value:"advisory",children:o("workflowNodes.advisory","Advisory")}),e.jsx("option",{value:"gate",children:o("workflowNodes.gateBlocks","Gate (blocks)")})]})]}):f.data.kind==="merge"?e.jsx("p",{className:"wf-inspector-note",children:o("workflowNodes.mergeBoundaryNote","Steps before this marker run pre-merge; steps after run post-merge.")}):null]}),!L&&e.jsxs("button",{type:"button",className:"wf-editor-delete wf-inspector-delete","data-testid":"wf-delete-node",onClick:()=>{Wo([f.id]),V(null)},children:[e.jsx(ve,{size:13})," ",o("workflowNodes.deleteNode","Delete node")]})]}),ke&&e.jsxs("aside",{className:"wf-editor-inspector","data-testid":"wf-edge-inspector",children:[e.jsxs("div",{className:"wf-inspector-heading",children:[e.jsx("h3",{children:o("workflowNodes.edgeInspector","Edge")}),x&&e.jsxs("button",{type:"button",className:"wf-inspector-toggle wf-inspector-toggle--expanded","data-testid":"wf-edge-inspector-close","aria-expanded":"true",onClick:()=>T(null),children:[e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowNodes.collapseInspector","Collapse")})]})]}),e.jsx("fieldset",{className:"wf-inspector-fields",disabled:L,children:Xo==="verdicts"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.edgeVerdict","Review verdict")}),e.jsxs("select",{"data-testid":"wf-edge-verdict",value:(()=>{const t=String(ke.data?.condition??"success");return t.startsWith("outcome:")?t.slice(8):""})(),onChange:t=>{const a=t.target.value;Ht({condition:a?`outcome:${a}`:"success"})},children:[e.jsx("option",{value:"",children:o("workflowNodes.edgeNoVerdict","— success (no verdict) —")}),Bl.map(t=>e.jsx("option",{value:t,children:t},t))]})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox","data-testid":"wf-edge-rework",checked:ke.data?.kind==="rework",onChange:t=>Ht({rework:t.target.checked})}),e.jsx("span",{children:o("workflowNodes.edgeRework","Rework edge (loop back, bounded)")})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.edgeReworkNote","Rework edges are the only legal cycles — they loop back within the for-each step instance, bounded by Max rework cycles.")})]}):Xo==="conditions"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.edgeCondition","Condition")}),e.jsxs("select",{"data-testid":"wf-edge-condition",value:String(ke.data?.condition??"success"),onChange:t=>Ht({condition:t.target.value}),children:[e.jsx("option",{value:"success",children:o("workflowNodes.conditionSuccess","success")}),e.jsx("option",{value:"failure",children:o("workflowNodes.conditionFailure","failure")})]})]}):e.jsx("p",{className:"wf-inspector-note",children:o("workflowNodes.edgeConditionLabel","Condition: {{condition}}",{condition:String(ke.data?.condition??"success")})})}),!L&&e.jsxs("button",{type:"button",className:"wf-editor-delete wf-inspector-delete","data-testid":"wf-delete-edge",onClick:()=>{Wo([ke.id]),T(null)},children:[e.jsx(ve,{size:13})," ",o("workflowNodes.deleteEdge","Delete edge")]})]})]}),de&&e.jsx(Ul,{workflows:R,onCreate:ya,onDesign:Ca,onClose:dt})]});return e.jsxs(e.Fragment,{children:[p?e.jsx("div",{className:"workflow-editor-embedded right-dock-embedded-view",children:es}):e.jsx(qn,{title:o("workflows.title","Workflows"),onClose:Zt,windowKey:"workflow-node-editor",className:"floating-window--workflow-editor",hideHeader:!0,dragHandleSelector:".wf-editor-header",defaultSize:{width:1200,height:820},minSize:{width:640,height:480},persistGeometryKey:"fusion:workflow-node-editor-floating-geometry",children:es}),Oa]})}function oi({isOpen:s,onClose:i,addToast:r,projectId:g,initialPanel:d,initialAction:k,initialWorkflowId:I,presentation:p="modal"}){const R=n.useRef(null),{isEmbedded:P}=Vn(p);return s?e.jsx(Ta,{children:e.jsx(Kl,{onClose:i,addToast:r,projectId:g,initialPanel:d,initialAction:k,initialWorkflowId:I,modalRef:R,isEmbedded:P})}):null}export{oi as WorkflowNodeEditor};
|