@runfusion/fusion 0.48.0 → 0.50.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.
Files changed (140) hide show
  1. package/dist/bin.js +43336 -15114
  2. package/dist/client/.vite/manifest.json +250 -249
  3. package/dist/client/assets/AgentDetailView-BzSyldiW.css +1 -0
  4. package/dist/client/assets/{AgentDetailView-CF6isJ51.js → AgentDetailView-D2oYUApl.js} +5 -5
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-DFldf6aS.js → AgentPermissionPolicyEditor-DGgx46f3.js} +1 -1
  6. package/dist/client/assets/AgentsView-Dhf5Vq_T.js +29 -0
  7. package/dist/client/assets/ChatView-DpgpxHva.js +19 -0
  8. package/dist/client/assets/ChatView-DwIIrJxb.css +1 -0
  9. package/dist/client/assets/CommandCenter-B9q-zM9p.css +1 -0
  10. package/dist/client/assets/CommandCenter-DzQhGq_J.js +71 -0
  11. package/dist/client/assets/{DevServerView-D6RFaGPU.js → DevServerView-DjJYp6Jj.js} +1 -1
  12. package/dist/client/assets/{DirectoryPicker-DNBB-viz.js → DirectoryPicker-CYPYp9T4.js} +1 -1
  13. package/dist/client/assets/{DocumentsView-DXG-sctG.js → DocumentsView-CeQVRVdp.js} +1 -1
  14. package/dist/client/assets/{EvalsView-Ol6ECKz5.js → EvalsView-D250mVR5.js} +1 -1
  15. package/dist/client/assets/{ExperimentalAgentOnboardingModal-BQc3GaE_.js → ExperimentalAgentOnboardingModal-B1EEY_bl.js} +1 -1
  16. package/dist/client/assets/{GoalsView-C_m90anC.js → GoalsView-MftVwE9g.js} +1 -1
  17. package/dist/client/assets/{InsightsView-BbFgPsDH.js → InsightsView-CbWItYe8.js} +1 -1
  18. package/dist/client/assets/{MemoryView-CRS7AjWK.js → MemoryView-Ct0nOTES.js} +1 -1
  19. package/dist/client/assets/{PiExtensionsManager-BEj5xu45.js → PiExtensionsManager-DSQwngX-.js} +1 -1
  20. package/dist/client/assets/{PluginManager-CzCM3XUY.js → PluginManager-DqLxCiNg.js} +1 -1
  21. package/dist/client/assets/{PullRequestView-9yNYCunb.js → PullRequestView-D0WgwdAi.js} +1 -1
  22. package/dist/client/assets/{ResearchView-BKdirpiw.js → ResearchView-CJQL9XKC.js} +1 -1
  23. package/dist/client/assets/{SecretsView-qGjo-0Cp.js → SecretsView-ChN9aTbi.js} +1 -1
  24. package/dist/client/assets/{SessionTerminal-C7YlkdGJ.js → SessionTerminal-BVon9kbr.js} +1 -1
  25. package/dist/client/assets/SettingsModal-B4WANQnu.js +21 -0
  26. package/dist/client/assets/{SettingsModal-CvbiSIHS.css → SettingsModal-BzZNPNIh.css} +1 -1
  27. package/dist/client/assets/{SettingsModal-DihNd7g8.js → SettingsModal-CIC5jhgo.js} +1 -1
  28. package/dist/client/assets/SettingsModal-tUDR6nJ9.css +1 -0
  29. package/dist/client/assets/{SetupWizardModal-MovTj5pY.js → SetupWizardModal-C6EGjmbd.js} +2 -2
  30. package/dist/client/assets/{ShadcnColorPicker-Bnf5n5R4.js → ShadcnColorPicker-4e_aXoGX.js} +1 -1
  31. package/dist/client/assets/{ShadcnColorPicker-pqVWCC5-.css → ShadcnColorPicker-CzZo9UOD.css} +1 -1
  32. package/dist/client/assets/SkillsView-Dz8dDwfP.js +1 -0
  33. package/dist/client/assets/SkillsView-tAW7TTCz.css +1 -0
  34. package/dist/client/assets/{TodoView-CIsL_uvQ.css → TodoView--YoVYWvw.css} +1 -1
  35. package/dist/client/assets/{TodoView-BEdk6FTU.js → TodoView-DvJFzoOv.js} +1 -1
  36. package/dist/client/assets/WorkflowNodeEditor-DrdTCstS.js +8 -0
  37. package/dist/client/assets/WorkflowNodeEditor-WYIxHTxY.css +1 -0
  38. package/dist/client/assets/{agentSkills-D5nDZPRY.js → agentSkills-B2dD5Nm5.js} +1 -1
  39. package/dist/client/assets/app-BYq4S7Cb.js +13 -0
  40. package/dist/client/assets/app-D27ewSC0.js +13 -0
  41. package/dist/client/assets/app-DFLDkeOE.js +13 -0
  42. package/dist/client/assets/app-OPrfgjjn.js +13 -0
  43. package/dist/client/assets/app-dATBczl3.js +13 -0
  44. package/dist/client/assets/{app-D_IT9Buz.js → app-k1K9zAjp.js} +3 -3
  45. package/dist/client/assets/{architectureDiagram-3BPJPVTR-BbkXWBni.js → architectureDiagram-3BPJPVTR-ClO0MnzR.js} +1 -1
  46. package/dist/client/assets/{blockDiagram-GPEHLZMM-DhaqpHqZ.js → blockDiagram-GPEHLZMM-C4cyy4WE.js} +1 -1
  47. package/dist/client/assets/{c4Diagram-AAUBKEIU-qC0WSHMZ.js → c4Diagram-AAUBKEIU-NHPC9TJo.js} +1 -1
  48. package/dist/client/assets/channel-Q2WKocEP.js +1 -0
  49. package/dist/client/assets/{chunk-2J33WTMH-Dah9zMeT.js → chunk-2J33WTMH-CGYIKTVR.js} +1 -1
  50. package/dist/client/assets/{chunk-4BX2VUAB-epHwnUb_.js → chunk-4BX2VUAB-BkCCD0tE.js} +1 -1
  51. package/dist/client/assets/{chunk-55IACEB6-DpYBy44g.js → chunk-55IACEB6-Be3yOIDe.js} +1 -1
  52. package/dist/client/assets/{chunk-727SXJPM-B9b8698e.js → chunk-727SXJPM-DxjyMaQQ.js} +1 -1
  53. package/dist/client/assets/{chunk-AQP2D5EJ-DrM8nnhR.js → chunk-AQP2D5EJ-BC0PjN0W.js} +1 -1
  54. package/dist/client/assets/{chunk-FMBD7UC4-jyT6Scwe.js → chunk-FMBD7UC4-DoWxmM8k.js} +1 -1
  55. package/dist/client/assets/{chunk-ND2GUHAM-EoPfF-PK.js → chunk-ND2GUHAM-EOpuc9pP.js} +1 -1
  56. package/dist/client/assets/{chunk-QZHKN3VN-qMwLVfgJ.js → chunk-QZHKN3VN-DiRyx9QZ.js} +1 -1
  57. package/dist/client/assets/classDiagram-4FO5ZUOK-CPFl2Aqd.js +1 -0
  58. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CPFl2Aqd.js +1 -0
  59. package/dist/client/assets/{cose-bilkent-S5V4N54A-DmPFKoVD.js → cose-bilkent-S5V4N54A-CfVoUUxT.js} +1 -1
  60. package/dist/client/assets/{dagre-BM42HDAG-DeHxd-ej.js → dagre-BM42HDAG-BfILvxLb.js} +1 -1
  61. package/dist/client/assets/{dashboard-view-DXjNQ5IF.js → dashboard-view-C9YIcx-O.js} +2 -2
  62. package/dist/client/assets/{dashboard-view-Cw5mMJay.js → dashboard-view-wFC1pe4d.js} +1 -1
  63. package/dist/client/assets/{diagram-2AECGRRQ-C04A2mhr.js → diagram-2AECGRRQ-6mdmbH-5.js} +1 -1
  64. package/dist/client/assets/{diagram-5GNKFQAL-DqtOwADI.js → diagram-5GNKFQAL-CY7MMwO1.js} +1 -1
  65. package/dist/client/assets/{diagram-KO2AKTUF-CH0har-Z.js → diagram-KO2AKTUF-D05XnQqd.js} +1 -1
  66. package/dist/client/assets/{diagram-LMA3HP47-CxN-U-0W.js → diagram-LMA3HP47-B18FTOJG.js} +1 -1
  67. package/dist/client/assets/{diagram-OG6HWLK6-42A7wpwF.js → diagram-OG6HWLK6-xmXlYf5m.js} +1 -1
  68. package/dist/client/assets/{erDiagram-TEJ5UH35-CnZI5YlN.js → erDiagram-TEJ5UH35-4XlgVLCs.js} +1 -1
  69. package/dist/client/assets/{flowDiagram-I6XJVG4X-BKfQhMVF.js → flowDiagram-I6XJVG4X-BYl3ps7f.js} +1 -1
  70. package/dist/client/assets/{folder-open-STXgbemw.js → folder-open-BH6FwmO7.js} +1 -1
  71. package/dist/client/assets/{ganttDiagram-6RSMTGT7-BfA0pME8.js → ganttDiagram-6RSMTGT7-4vxuH9Dx.js} +1 -1
  72. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-BgDFB7PS.js → gitGraphDiagram-PVQCEYII-BESmFgXT.js} +1 -1
  73. package/dist/client/assets/index-B9jtBwFy.css +1 -0
  74. package/dist/client/assets/index-DFeBJ3GM.js +1302 -0
  75. package/dist/client/assets/{infoDiagram-5YYISTIA-Bb5F155s.js → infoDiagram-5YYISTIA-DvjdjtwB.js} +1 -1
  76. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-8Oati7l_.js → ishikawaDiagram-YF4QCWOH-Cis5IoEm.js} +1 -1
  77. package/dist/client/assets/{journeyDiagram-JHISSGLW-DhHTHXTM.js → journeyDiagram-JHISSGLW-C20pB1W8.js} +1 -1
  78. package/dist/client/assets/{kanban-definition-UN3LZRKU-BWB9EtUX.js → kanban-definition-UN3LZRKU-CiVfCeU3.js} +1 -1
  79. package/dist/client/assets/{mermaid.core-BD-L2gUQ.js → mermaid.core-CW0vCXA6.js} +4 -4
  80. package/dist/client/assets/{mindmap-definition-RKZ34NQL-BSKGd7LE.js → mindmap-definition-RKZ34NQL-E5rPHUdw.js} +1 -1
  81. package/dist/client/assets/{pieDiagram-4H26LBE5-BtBFPvSW.js → pieDiagram-4H26LBE5-DVIFbPjH.js} +1 -1
  82. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-aWQWYPto.js → quadrantDiagram-W4KKPZXB-C8qPRe_x.js} +1 -1
  83. package/dist/client/assets/{requirementDiagram-4Y6WPE33-CprlEpIa.js → requirementDiagram-4Y6WPE33-DQ-pwXh3.js} +1 -1
  84. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Cw-AcRAV.js → sankeyDiagram-5OEKKPKP-BnghLuUc.js} +1 -1
  85. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BMW5slyv.js → sequenceDiagram-3UESZ5HK-ChlGxGVk.js} +1 -1
  86. package/dist/client/assets/{shield-alert-Bzf8yNOc.js → shield-alert-BfOnDO6O.js} +1 -1
  87. package/dist/client/assets/{stateDiagram-AJRCARHV-CcxvIVwM.js → stateDiagram-AJRCARHV-ByUvNEch.js} +1 -1
  88. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-awOfoFOB.js → stateDiagram-v2-BHNVJYJU-Df38ITSP.js} +1 -1
  89. package/dist/client/assets/{timeline-definition-PNZ67QCA-DIEAc2YP.js → timeline-definition-PNZ67QCA-bsAGc83D.js} +1 -1
  90. package/dist/client/assets/{upload-DuwyPTKe.js → upload-BK1crTqn.js} +1 -1
  91. package/dist/client/assets/{users-D1Qhfyro.js → users-DW8jC2Z9.js} +1 -1
  92. package/dist/client/assets/{vennDiagram-CIIHVFJN-DOkqg5Wi.js → vennDiagram-CIIHVFJN-BBIj6LFN.js} +1 -1
  93. package/dist/client/assets/{wardley-L42UT6IY-DoPK1Q6d.js → wardley-L42UT6IY-De6JFroy.js} +1 -1
  94. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-l1vun-m2.js → wardleyDiagram-YWT4CUSO-P1LOLx0_.js} +1 -1
  95. package/dist/client/assets/{xychartDiagram-2RQKCTM6-DcUOUKvl.js → xychartDiagram-2RQKCTM6-v1G4ki6U.js} +1 -1
  96. package/dist/client/index.html +2 -2
  97. package/dist/client/version.json +1 -1
  98. package/dist/droid-cli/package.json +6 -25
  99. package/dist/extension.js +37091 -9900
  100. package/dist/pi-claude-cli/index.ts +26 -22
  101. package/dist/pi-claude-cli/package.json +6 -20
  102. package/dist/pi-claude-cli/src/mcp-config.ts +58 -7
  103. package/dist/plugin-sdk/index.d.ts +246 -186
  104. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  105. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +2 -9
  106. package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +250 -19
  107. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  108. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  109. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  110. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  111. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  112. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  113. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  114. package/dist/plugins/fusion-plugin-reports/package.json +2 -10
  115. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  116. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +3 -15
  117. package/package.json +1 -1
  118. package/skill/fusion/references/engine-tools.md +5 -1
  119. package/dist/client/assets/AgentDetailView-CgbB51Iw.css +0 -1
  120. package/dist/client/assets/AgentsView-DiGseTuo.js +0 -29
  121. package/dist/client/assets/ChatView-BjQBbDyo.js +0 -19
  122. package/dist/client/assets/ChatView-BtjkE0V7.css +0 -1
  123. package/dist/client/assets/CommandCenter-DDjpYkPe.css +0 -1
  124. package/dist/client/assets/CommandCenter-DwpiADSX.js +0 -71
  125. package/dist/client/assets/SettingsModal-DpaptT6t.js +0 -21
  126. package/dist/client/assets/SettingsModal-ino68pI2.css +0 -1
  127. package/dist/client/assets/SkillsView-Br2LkA3x.js +0 -1
  128. package/dist/client/assets/SkillsView-CJ8snrma.css +0 -1
  129. package/dist/client/assets/WorkflowNodeEditor-BOouksjw.css +0 -1
  130. package/dist/client/assets/WorkflowNodeEditor-e-eR6yzw.js +0 -8
  131. package/dist/client/assets/app-BM6bAO0b.js +0 -13
  132. package/dist/client/assets/app-BglOELbc.js +0 -13
  133. package/dist/client/assets/app-ChkCVQpq.js +0 -13
  134. package/dist/client/assets/app-DMn7Jt9g.js +0 -13
  135. package/dist/client/assets/app-S8fehQv8.js +0 -13
  136. package/dist/client/assets/channel-CCKvUami.js +0 -1
  137. package/dist/client/assets/classDiagram-4FO5ZUOK-C_HqY7AI.js +0 -1
  138. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C_HqY7AI.js +0 -1
  139. package/dist/client/assets/index-BnfnLXyO.css +0 -1
  140. package/dist/client/assets/index-CHy0WNjH.js +0 -1301
@@ -1,8 +0,0 @@
1
- import{r as a,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,B as _a,C as Ba,M as Ga}from"./vendor-reactflow-Bg-Qjzh8.js";import{c as qa,ed as ao,ee as we,ef as qs,eg as Va,eh as Ha,ei as Ua,ej as Vs,bp as ne,bo as yt,P as Ee,b7 as Te,bu as Ka,ad as Ya,o as Se,J as Ne,am as Hs,ek as Ja,bL as Ct,el as ts,bF as Us,em as no,al as Xa,C as Re,bP as lo,I as Qa,en as Za,eo as en,cq as os,ep as tn,eq as on,er as sn,ce as an,es as nn,dy as ln,a3 as ss,ae as rn,et as dn,eu as cn,ev as un,ew as fn,ex as pn,ey as mn,ez as wn,eA as hn,eB as gn,eC as as,eD as ns,eE as ls,eF as is,eG as rs,eH as bn,eI as kn,eJ as xn,eK as vn,eL as jn,eM as Nn,eN as yn,eO as Cn,eP as Sn,eQ as ds,eR as En,eS as cs,eT as us,eU as An,eV as fs,eW as ps,eX as Fn,eY as Qt,eZ as Pn,e_ as Ks,e$ as Rn,f0 as ms,f1 as Mn,i as ws,dj as Ys,dg as hs,f2 as gs,X as io,bs,L as Me,f3 as Zt,br as Js,bb as In,f4 as Xs,a1 as On,ak as Dn,ba as Tn,f5 as Ln,f6 as zn,f7 as Wn,f8 as ks,f9 as $n,fa as _n,fb as Bn,fc as Gn,fd as Nt,S as He,fe as qn,ff as Vn,fg as Hn,dh as xs,fh as vs,fi as Un,fj as Kn}from"./index-CHy0WNjH.js";import{u as ye}from"./vendor-i18n-GF3RlKbq.js";import{U as Yn}from"./upload-DuwyPTKe.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=qa("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 ol=80,sl=24,js=16,Ns=Va+ol,al=0,nl=0,eo=qs+sl;function ll(s){return!(we(s.id)||s.parentId)}function il(s,i){const r=new Set(s),w=new Map,d=new Map;for(const k of s)d.set(k,0);for(const k of i)k.data?.kind!=="rework"&&(!r.has(k.source)||!r.has(k.target)||k.source!==k.target&&((w.get(k.source)??w.set(k.source,[]).get(k.source)).push(k.target),d.set(k.target,(d.get(k.target)??0)+1)));const g=s.filter(k=>k==="start"),I=g.length?g:s.filter(k=>(d.get(k)??0)===0),f=new Map,A=s.length+1,P=[];for(const k of I)f.set(k,0),P.push(k);let S=s.length*s.length+s.length+1;for(;P.length&&S-- >0;){const k=P.shift(),h=f.get(k)??0;for(const c of w.get(k)??[]){const j=h+1,b=f.get(c);(b===void 0||j>b)&&j<=A&&(f.set(c,j),P.push(c))}}let M=0;for(const k of f.values())k>M&&(M=k);const N=f.size?M+1:0;for(const k of s)f.has(k)||f.set(k,N);return f}function ys(s,i,r){const w=s.filter(ll),d=w.map(S=>S.id),g=il(d,i),I=new Map(w.map(S=>[S.id,S])),f=new Map,A=new Map;for(const S of d){const M=g.get(S)??0;(A.get(M)??A.set(M,[]).get(M)).push(S)}const P=r.length>0;for(const[S,M]of A){const N=[...M].sort((c,j)=>{const b=I.get(c),D=I.get(j);return b.position.y!==D.position.y?b.position.y-D.position.y:c<j?-1:c>j?1:0}),k=al+S*Ns;if(!P){N.forEach((c,j)=>{f.set(c,{x:k,y:nl+j*eo})});continue}const h=new Map;for(const c of N){const j=I.get(c),b=j.data.column??(ao(j.position.y,r)?ao(j.position.y,r):void 0);if(!b){f.set(c,{x:k,y:j.position.y});continue}const D=r.findIndex(y=>y.id===b),x=D>=0?D:0,z=Ha(x),E=z+js,Q=z+Ua-qs-js,ie=Math.max(1,Math.floor((Q-E)/eo)+1),B=h.get(b??`__idx${x}`)??0,G=B%ie,le=Math.floor(B/ie),q=E+G*eo,Z=k+le*(Ns/2);f.set(c,{x:Z,y:q}),h.set(b??`__idx${x}`,B+1)}}return f}function Cs(s,i){return s.map(r=>{const w=i.get(r.id);return w?{...r,position:w}:r})}let Ss=0;function rl(){return Ss+=1,`col-${Date.now().toString(36)}-${Ss}`}function Es({columns:s,onChange:i,violations:r,readOnly:w,projectId:d,addToast:g,columnAgentsEnabled:I}){const{t:f}=ye("app"),[A,P]=a.useState([]),[S,M]=a.useState([]),[N,k]=a.useState(!0),[h,c]=a.useState(null);a.useEffect(()=>{let y=!1;return Vs(d).then(O=>{y||P(O)}).catch(O=>{y||g(ne(O)||f("workflowColumns.traitsLoadFailed","Failed to load traits"),"error")}),()=>{y=!0}},[d,g,f]),a.useEffect(()=>{let y=!1;return k(!0),c(null),Promise.resolve(yt(void 0,d)).then(O=>{y||(M(O??[]),k(!1))}).catch(O=>{if(y)return;const T=ne(O)||f("workflowColumns.agentsLoadFailed","Failed to load agents");c(T),k(!1),g(T,"error")}),()=>{y=!0}},[d,g,f]);const j=a.useMemo(()=>S.map(y=>y.id).join(","),[S]),b=a.useMemo(()=>{const y=new Map;for(const O of S)y.set(O.id,O);return y},[j]),D=a.useCallback((y,O)=>{i(s.map(T=>{if(T.id!==y)return T;if(!O){const{agent:V,...te}=T;return te}return{...T,agent:O}}))},[s,i]),x=a.useCallback((y,O)=>{if(!O){D(y,void 0);return}const T=s.find(V=>V.id===y)?.agent;D(y,{agentId:O,mode:T?.mode??"defer"})},[s,D]),z=a.useCallback((y,O)=>{const T=s.find(V=>V.id===y)?.agent;T&&D(y,{...T,mode:O})},[s,D]),E=w||!I||N||!!h,Q=r.filter(y=>y.columnId===null),ie=a.useCallback(y=>r.filter(O=>O.columnId===y),[r]),B=a.useCallback(()=>{const y=rl();i([...s,{id:y,name:f("workflowColumns.newColumnName","New column"),traits:[]}])},[s,i,f]),G=a.useCallback((y,O)=>{i(s.map(T=>T.id===y?{...T,name:O}:T))},[s,i]),le=a.useCallback(y=>{i(s.filter(O=>O.id!==y))},[s,i]),q=a.useCallback((y,O)=>{const T=y+O;if(T<0||T>=s.length)return;const V=[...s];[V[y],V[T]]=[V[T],V[y]],i(V)},[s,i]),Z=a.useCallback((y,O)=>{i(s.map(T=>{if(T.id!==y)return T;const V=T.traits.some(te=>te.trait===O);return{...T,traits:V?T.traits.filter(te=>te.trait!==O):[...T.traits,{trait:O}]}}))},[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:f("workflowColumns.title","Columns")}),e.jsxs("button",{className:"wf-column-add",onClick:B,disabled:w,title:w?f("workflowColumns.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,children:[e.jsx(Ee,{size:13})," ",f("workflowColumns.add","Add column")]})]}),Q.length>0&&e.jsx("div",{className:"wf-column-panel-errors",role:"alert",children:Q.map((y,O)=>e.jsxs("p",{className:"wf-column-violation",children:[e.jsx(Te,{size:12,"aria-hidden":!0})," ",y.message]},`${y.code}-${O}`))}),s.length===0?e.jsx("p",{className:"wf-column-panel-empty",children:f("workflowColumns.empty","No columns yet. Add a column to place nodes into board lanes.")}):e.jsx("ul",{className:"wf-column-list",children:s.map((y,O)=>{const T=ie(y.id),V=y.agent?.agentId,te=V?b.get(V):void 0,de=!!V&&!N&&!h&&!te,re=te?.name??(de?f("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:V??""}):V);return e.jsxs("li",{className:`wf-column-item${T.length?" wf-column-item--error":""}`,"data-testid":`wf-column-${y.id}`,"data-column-error":T.length?"true":void 0,children:[e.jsxs("div",{className:"wf-column-item-head",children:[e.jsx("input",{className:"wf-column-name","aria-label":f("workflowColumns.nameLabel","Column name"),value:y.name,disabled:w,onChange:U=>G(y.id,U.target.value)}),V&&e.jsxs("span",{className:`wf-column-agent-badge${de?" wf-column-agent-badge--stale":""}`,"data-testid":`wf-column-agent-badge-${y.id}`,title:y.agent?.mode==="override"?f("workflowColumns.agentBadgeOverride","Column agent (override)"):f("workflowColumns.agentBadgeDefer","Column agent (defer)"),children:[e.jsx(Ka,{size:11,"aria-hidden":!0})," ",re]}),e.jsxs("div",{className:"wf-column-item-actions",children:[e.jsx("button",{className:"wf-column-move","aria-label":f("workflowColumns.moveUp","Move column up"),disabled:w||O===0,onClick:()=>q(O,-1),children:e.jsx(Ya,{size:13})}),e.jsx("button",{className:"wf-column-move","aria-label":f("workflowColumns.moveDown","Move column down"),disabled:w||O===s.length-1,onClick:()=>q(O,1),children:e.jsx(Se,{size:13})}),e.jsx("button",{className:"wf-column-remove","aria-label":f("workflowColumns.remove","Remove column"),disabled:w,onClick:()=>le(y.id),children:e.jsx(Ne,{size:13})})]})]}),T.map((U,he)=>e.jsxs("p",{className:"wf-column-violation",role:"alert",children:[e.jsx(Te,{size:12,"aria-hidden":!0})," ",U.message]},`${U.code}-${he}`)),e.jsxs("div",{className:"wf-column-traits",children:[e.jsx("span",{className:"wf-column-traits-label",children:f("workflowColumns.traits","Traits")}),e.jsx("div",{className:"wf-column-trait-options",children:A.map(U=>{const he=y.traits.some(F=>F.trait===U.id);return e.jsxs("label",{className:"wf-column-trait",title:U.description,children:[e.jsx("input",{type:"checkbox",checked:he,disabled:w,onChange:()=>Z(y.id,U.id)}),e.jsx("span",{children:U.name})]},U.id)})})]}),e.jsxs("div",{className:"wf-column-agent",children:[e.jsx("span",{className:"wf-column-agent-label",children:f("workflowColumns.agent","Column agent")}),e.jsxs("select",{className:"wf-column-agent-select","data-testid":`wf-column-agent-select-${y.id}`,"aria-label":f("workflowColumns.agentLabel","Column agent"),value:V??"",disabled:E,title:w?f("workflowColumns.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,onChange:U=>x(y.id,U.target.value),children:[e.jsx("option",{value:"",children:f("workflowColumns.agentNone","(none)")}),de&&V&&e.jsx("option",{value:V,children:f("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:V})}),S.map(U=>e.jsx("option",{value:U.id,children:U.name},U.id))]}),h&&e.jsxs("p",{className:"wf-column-agent-error",role:"alert",children:[e.jsx(Te,{size:12,"aria-hidden":!0})," ",h]}),de&&e.jsxs("p",{className:"wf-column-agent-stale",role:"alert","data-testid":`wf-column-agent-stale-${y.id}`,children:[e.jsx(Te,{size:12,"aria-hidden":!0})," ",f("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:V??""})]}),V&&e.jsxs("div",{className:"wf-column-agent-mode",role:"radiogroup","aria-label":f("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-${y.id}`,checked:(y.agent?.mode??"defer")==="defer",disabled:E,onChange:()=>z(y.id,"defer")}),e.jsx("span",{title:f("workflowColumns.agentModeDeferHint","Column agent applies only when the work carries no agent/model settings of its own"),children:f("workflowColumns.agentModeDefer","Defer")})]}),e.jsxs("label",{className:"wf-column-agent-mode-option",children:[e.jsx("input",{type:"radio",name:`wf-column-agent-mode-${y.id}`,checked:y.agent?.mode==="override",disabled:E,onChange:()=>z(y.id,"override")}),e.jsx("span",{title:f("workflowColumns.agentModeOverrideHint","Column agent supersedes node- and task-level agent/model settings"),children:f("workflowColumns.agentModeOverride","Override")})]})]})]})]},y.id)})})]})}const dl=["string","text","number","boolean","enum","multi-enum","date","url"],As={string:["input"],text:["textarea","input"],number:["input"],boolean:["toggle"],enum:["select","radio","chips"],"multi-enum":["chips"],date:["input"],url:["input"]},cl=["#4f7cff","#22c55e","#f59e0b","#ef4444","#a855f7","#06b6d4","#ec4899","#64748b"];function St(s){return s==="enum"||s==="multi-enum"}function ul(s){return s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}let Fs=0;function fl(){return Fs+=1,`field-${Date.now().toString(36)}-${Fs}`}function pl({field:s}){const i=a.useMemo(()=>{if(St(s.type)){const w=s.options?.[0];return w?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}: ${w.label}`,style:w.color?{backgroundColor:w.color,borderColor:w.color,color:"#fff"}:void 0,children:w.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 Ps({fields:s,onChange:i,readOnly:r,addToast:w}){const{t:d}=ye("app"),[g,I]=a.useState(null),f=a.useCallback((c,j)=>{i(s.map(b=>b.id===c?{...b,...j}:b))},[s,i]),A=a.useCallback(()=>{const c=fl();i([...s,{id:c,name:d("workflowFields.newFieldName","New field"),type:"string"}])},[s,i,d]),P=a.useCallback(c=>{i(s.filter(j=>j.id!==c))},[s,i]),S=a.useCallback((c,j)=>{const b=ul(j);if(b){if(b!==c&&s.some(D=>D.id===b)){w(d("workflowFields.duplicateId","A field with that id already exists"),"error");return}f(c,{id:b})}},[s,f,w,d]),M=a.useCallback((c,j)=>{const b=s.find(x=>x.id===c);if(!b)return;const D={type:j};St(j)?(!b.options||b.options.length===0)&&(D.options=[{value:"option-1",label:d("workflowFields.newOptionLabel","Option 1")}]):D.options=void 0,b.render?.widget&&!As[j].includes(b.render.widget)&&(D.render={...b.render,widget:void 0}),D.default=void 0,f(c,D)},[s,f,d]),N=a.useCallback((c,j)=>f(c,{options:j}),[f]),k=a.useCallback((c,j)=>{const b=!j||j.placement===void 0&&j.widget===void 0&&!j.badge;f(c,{render:b?void 0:j})},[f]),h=c=>{const j=x=>f(c.id,{default:x});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:x=>j(x.target.checked)}),e.jsx("span",{children:d("workflowFields.defaultTrue","Default on")})]});if(St(c.type)){const x=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:x,disabled:r,onChange:z=>{const E=z.target.value;if(E==="")return j(void 0);j(c.type==="multi-enum"?[E]:E)},children:[e.jsx("option",{value:"",children:d("workflowFields.noDefault","— none —")}),(c.options??[]).map(z=>e.jsx("option",{value:z.value,children:z.label},z.value))]})}const b=c.type==="number"?"number":c.type==="date"?"date":c.type==="url"?"url":"text",D=c.type==="number"?typeof c.default=="number"?String(c.default):"":typeof c.default=="string"?c.default:"";return e.jsx("input",{type:b,"aria-label":d("workflowFields.defaultLabel","Default value"),defaultValue:D,disabled:r,onBlur:x=>{const z=x.target.value;if(z==="")return j(void 0);j(c.type==="number"?Number(z):z)}})};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:A,disabled:r,title:r?d("workflowFields.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,children:[e.jsx(Ee,{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 j=As[c.type],b=c.render?.placement??"detail",D=g===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:x=>f(c.id,{name:x.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(Ne,{size:13})})]}),e.jsx("div",{className:"wf-field-id-row",children:D?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:x=>{S(c.id,x.target.value),I(null)}}),e.jsxs("p",{className:"wf-field-id-warn",role:"note",children:[e.jsx(Te,{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:x=>M(c.id,x.target.value),children:dl.map(x=>e.jsx("option",{value:x,children:x},x))})]}),e.jsxs("label",{className:"wf-field--checkbox wf-field-required",children:[e.jsx("input",{type:"checkbox",checked:c.required===!0,disabled:r,onChange:x=>f(c.id,{required:x.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")}),h(c)]}),St(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((x,z)=>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:x.value,disabled:r,onChange:E=>{const Q=[...c.options??[]];Q[z]={...x,value:E.target.value},N(c.id,Q)}}),e.jsx("input",{className:"wf-field-option-label","aria-label":d("workflowFields.optionLabel","Option label"),value:x.label,disabled:r,onChange:E=>{const Q=[...c.options??[]];Q[z]={...x,label:E.target.value},N(c.id,Q)}}),e.jsx("div",{className:"wf-field-option-colors",role:"group","aria-label":d("workflowFields.optionColor","Option color"),children:cl.map(E=>e.jsx("button",{type:"button",className:`wf-field-color-swatch${x.color===E?" is-active":""}`,style:{backgroundColor:E},"aria-label":E,"aria-pressed":x.color===E,disabled:r,onClick:()=>{const Q=[...c.options??[]];Q[z]={...x,color:x.color===E?void 0:E},N(c.id,Q)}},E))}),e.jsx("button",{className:"wf-field-option-remove","aria-label":d("workflowFields.removeOption","Remove option"),disabled:r,onClick:()=>N(c.id,(c.options??[]).filter((E,Q)=>Q!==z)),children:e.jsx(Ne,{size:12})})]},z)),e.jsxs("button",{className:"wf-field-option-add",disabled:r,onClick:()=>{const x=(c.options??[]).length+1;N(c.id,[...c.options??[],{value:`option-${x}`,label:d("workflowFields.optionN","Option {{n}}",{n:x})}])},children:[e.jsx(Ee,{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:b,disabled:r,onChange:x=>k(c.id,{...c.render,placement:x.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:x=>k(c.id,{...c.render,widget:x.target.value||void 0}),children:[e.jsx("option",{value:"",children:d("workflowFields.widgetDefault","Default")}),j.map(x=>e.jsx("option",{value:x,children:x},x))]})]}),e.jsxs("label",{className:"wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:c.render?.badge===!0,disabled:r,onChange:x=>k(c.id,{...c.render,badge:x.target.checked||void 0})}),e.jsx("span",{children:d("workflowFields.badge","Render as badge")})]})]}),b==="card"&&e.jsx(pl,{field:c})]},c.id)})})]})}const ml={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"},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"}},wl=["models","review","steps","advanced"],hl={models:"Models",review:"Review & Approval",steps:"Step Execution",advanced:"Advanced"};function Qs(s){return ml[s.id]??{group:"advanced",label:s.name,description:s.description}}function gl(s){const i=new Map;for(const r of s){const w=Qs(r).group,d=i.get(w)??[];d.push(r),i.set(w,d)}return wl.map(r=>({group:r,settings:i.get(r)??[]})).filter(r=>r.settings.length>0)}function Ke({htmlFor:s,label:i,help:r,error:w,scope:d,disabled:g,clearable:I,onClear:f,children:A}){const{t:P}=ye("app");return e.jsxs("div",{className:`settings-field-row${g?" 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:[A,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:g,onClick:f,children:e.jsx(Hs,{size:13,"aria-hidden":!0})})]}),r&&e.jsx("p",{className:"settings-field-row-help",children:r}),w&&e.jsx("p",{className:"settings-field-row-error",role:"alert",children:w})]})}function bl({descriptor:s,value:i,onChange:r,error:w,clearable:d}){const{key:g,label:I,help:f,scope:A,disabled:P}=s;return e.jsx(Ke,{htmlFor:g,label:I,help:f,error:w,scope:A,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("label",{className:"settings-toggle",children:e.jsx("input",{id:g,type:"checkbox",checked:i===!0,disabled:P,onChange:S=>r(S.target.checked)})})})}function kl({descriptor:s,value:i,onChange:r,error:w,clearable:d}){const{key:g,label:I,help:f,scope:A,disabled:P,min:S,max:M,step:N,placeholder:k}=s;return e.jsx(Ke,{htmlFor:g,label:I,help:f,error:w,scope:A,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("input",{id:g,className:"settings-number",type:"number",value:i??"",min:S,max:M,step:N,placeholder:k,disabled:P,onChange:h=>{const c=h.target.value;if(c==="")return r(null);const j=Number(c);Number.isNaN(j)||r(j)}})})}function Rs({descriptor:s,value:i,onChange:r,error:w,clearable:d}){const{key:g,label:I,help:f,scope:A,disabled:P,options:S}=s;return e.jsx(Ke,{htmlFor:g,label:I,help:f,error:w,scope:A,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("select",{id:g,className:"settings-select",value:i??"",disabled:P,onChange:M=>r(M.target.value),children:S.map(M=>e.jsx("option",{value:M.value,children:M.label},M.value))})})}function xl({descriptor:s,value:i,onChange:r,error:w,clearable:d}){const{key:g,label:I,help:f,scope:A,disabled:P,placeholder:S}=s;return e.jsx(Ke,{htmlFor:g,label:I,help:f,error:w,scope:A,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("input",{id:g,className:"settings-text",type:"text",value:i??"",placeholder:S,disabled:P,onChange:M=>r(M.target.value)})})}function vl({descriptor:s,value:i,onChange:r,error:w,clearable:d}){const{key:g,label:I,help:f,scope:A,disabled:P,placeholder:S}=s;return e.jsx(Ke,{htmlFor:g,label:I,help:f,error:w,scope:A,disabled:P,clearable:d,onClear:()=>r(null),children:e.jsx("textarea",{id:g,className:"settings-textarea",value:i??"",placeholder:S,disabled:P,rows:3,onChange:M=>r(M.target.value)})})}const jl=["string","text","number","boolean","enum","multi-enum"],Ms={string:["input"],text:["textarea","input"],number:["input"],boolean:["toggle"],enum:["select","radio","chips"],"multi-enum":["chips"]},Nl=["#4f7cff","#22c55e","#f59e0b","#ef4444","#a855f7","#06b6d4","#ec4899","#64748b"];function to(s){return s==="enum"||s==="multi-enum"}function yl(s){return s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}let Is=0;function Cl(){return Is+=1,`setting-${Date.now().toString(36)}-${Is}`}function Sl({settings:s,onChange:i,readOnly:r,addToast:w}){const{t:d}=ye("app"),[g,I]=a.useState(null),f=a.useCallback((h,c)=>{i(s.map(j=>j.id===h?{...j,...c}:j))},[s,i]),A=a.useCallback(()=>{i([...s,{id:Cl(),name:d("workflowSettings.newSettingName","New setting"),type:"string"}])},[s,i,d]),P=a.useCallback(h=>i(s.filter(c=>c.id!==h)),[s,i]),S=a.useCallback((h,c)=>{const j=yl(c);if(j){if(j!==h&&s.some(b=>b.id===j)){w(d("workflowSettings.duplicateId","A setting with that id already exists"),"error");return}f(h,{id:j})}},[s,f,w,d]),M=a.useCallback((h,c)=>{const j=s.find(D=>D.id===h);if(!j)return;const b={type:c};to(c)?(!j.options||j.options.length===0)&&(b.options=[{value:"option-1",label:d("workflowSettings.newOptionLabel","Option 1")}]):b.options=void 0,j.render?.widget&&!Ms[c].includes(j.render.widget)&&(b.render=void 0),b.default=void 0,f(h,b)},[s,f,d]),N=a.useCallback((h,c)=>f(h,{options:c}),[f]),k=h=>{const c=D=>f(h.id,{default:D});if(h.type==="boolean")return e.jsxs("label",{className:"wf-setting--checkbox",children:[e.jsx("input",{type:"checkbox",checked:h.default===!0,disabled:r,onChange:D=>c(D.target.checked)}),e.jsx("span",{children:d("workflowSettings.defaultTrue","Default on")})]});if(to(h.type)){const D=h.type==="multi-enum"?Array.isArray(h.default)?h.default[0]??"":"":typeof h.default=="string"?h.default:"";return e.jsxs("select",{"aria-label":d("workflowSettings.defaultLabel","Default value"),value:D,disabled:r,onChange:x=>{const z=x.target.value;if(z==="")return c(void 0);c(h.type==="multi-enum"?[z]:z)},children:[e.jsx("option",{value:"",children:d("workflowSettings.noDefault","— none —")}),(h.options??[]).map(x=>e.jsx("option",{value:x.value,children:x.label},x.value))]})}const j=h.type==="number"?"number":"text",b=h.type==="number"?typeof h.default=="number"?String(h.default):"":typeof h.default=="string"?h.default:"";return e.jsx("input",{type:j,"aria-label":d("workflowSettings.defaultLabel","Default value"),defaultValue:b,disabled:r,onBlur:D=>{const x=D.target.value;if(x==="")return c(void 0);c(h.type==="number"?Number(x):x)}})};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:A,disabled:r,title:r?d("workflowSettings.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,children:[e.jsx(Ee,{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(h=>{const c=Ms[h.type],j=g===h.id;return e.jsxs("li",{className:"wf-setting-item","data-testid":`wf-setting-${h.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:h.name,disabled:r,onChange:b=>f(h.id,{name:b.target.value})}),e.jsx("button",{className:"wf-setting-remove","aria-label":d("workflowSettings.remove","Remove setting"),disabled:r,onClick:()=>P(h.id),children:e.jsx(Ne,{size:13})})]}),e.jsx("div",{className:"wf-setting-id-row",children:j?e.jsxs(e.Fragment,{children:[e.jsx("input",{className:"wf-setting-id","aria-label":d("workflowSettings.idLabel","Setting id"),defaultValue:h.id,disabled:r,onBlur:b=>{S(h.id,b.target.value),I(null)}}),e.jsxs("p",{className:"wf-setting-id-warn",role:"note",children:[e.jsx(Te,{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:h.id}),e.jsx("button",{className:"wf-setting-id-edit",disabled:r,onClick:()=>I(h.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:h.type,disabled:r,onChange:b=>M(h.id,b.target.value),children:jl.map(b=>e.jsx("option",{value:b,children:b},b))})]}),e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.widget","Widget")}),e.jsxs("select",{value:h.render?.widget??"",disabled:r,onChange:b=>f(h.id,{render:b.target.value?{widget:b.target.value}:void 0}),children:[e.jsx("option",{value:"",children:d("workflowSettings.widgetDefault","Default")}),c.map(b=>e.jsx("option",{value:b,children:b},b))]})]})]}),e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.default","Default")}),k(h)]}),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:h.description??"",disabled:r,onChange:b=>f(h.id,{description:b.target.value||void 0})})]}),to(h.type)&&e.jsxs("div",{className:"wf-setting-options","data-testid":`wf-setting-options-${h.id}`,children:[e.jsx("span",{className:"wf-setting-options-label",children:d("workflowSettings.options","Options")}),(h.options??[]).map((b,D)=>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:b.value,disabled:r,onChange:x=>{const z=[...h.options??[]];z[D]={...b,value:x.target.value},N(h.id,z)}}),e.jsx("input",{className:"wf-setting-option-label","aria-label":d("workflowSettings.optionLabel","Option label"),value:b.label,disabled:r,onChange:x=>{const z=[...h.options??[]];z[D]={...b,label:x.target.value},N(h.id,z)}}),e.jsx("div",{className:"wf-setting-option-colors",role:"group","aria-label":d("workflowSettings.optionColor","Option color"),children:Nl.map(x=>e.jsx("button",{type:"button",className:`wf-setting-color-swatch${b.color===x?" is-active":""}`,style:{backgroundColor:x},"aria-label":x,"aria-pressed":b.color===x,disabled:r,onClick:()=>{const z=[...h.options??[]];z[D]={...b,color:b.color===x?void 0:x},N(h.id,z)}},x))}),e.jsx("button",{className:"wf-setting-option-remove","aria-label":d("workflowSettings.removeOption","Remove option"),disabled:r,onClick:()=>N(h.id,(h.options??[]).filter((x,z)=>z!==D)),children:e.jsx(Ne,{size:12})})]},D)),e.jsxs("button",{className:"wf-setting-option-add",disabled:r,onClick:()=>{const b=(h.options??[]).length+1;N(h.id,[...h.options??[],{value:`option-${b}`,label:d("workflowSettings.optionN","Option {{n}}",{n:b})}])},children:[e.jsx(Ee,{size:12})," ",d("workflowSettings.addOption","Add option")]})]})]},h.id)})})]})}function El(s){if(typeof s=="string")return s;try{return JSON.stringify(s)}catch{return String(s)}}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 Fl(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 Pl({workflowId:s,settings:i,boundProjectId:r,currentProjectId:w,addToast:d}){const{t:g}=ye("app"),[I,f]=a.useState(null),[A,P]=a.useState(!1),[S,M]=a.useState({}),[N,k]=a.useState({}),[h,c]=a.useState(!1),[j,b]=a.useState(!1),[D,x]=a.useState([]),[z,E]=a.useState(!1),[Q,ie]=a.useState([]),[B,G]=a.useState([]),le=a.useRef(0),q=a.useRef(0),Z=a.useMemo(()=>new Map(i.map(m=>[m.id,m])),[i]),y=a.useMemo(()=>Al.filter(m=>{const W=Z.get(m.providerId),J=Z.get(m.modelId);return W?.type==="string"&&J?.type==="string"}),[Z]),O=a.useMemo(()=>new Set(y.flatMap(m=>[m.providerId,m.modelId])),[y]),T=r!==void 0&&w!==void 0&&w!==r,V=a.useCallback(async()=>{if(r===void 0)return;const m=++le.current;P(!0);try{const W=await Ja(s,r);le.current===m&&(f(W),M({}),k({}))}catch{le.current===m&&d(g("workflowSettings.loadFailed","Failed to load setting values"),"error")}finally{le.current===m&&P(!1)}},[s,r,d,g]);if(a.useEffect(()=>{V()},[V]),a.useEffect(()=>{if(r===void 0||y.length===0){x([]),ie([]),G([]),E(!1);return}const m=++q.current;E(!0),Ct().then(W=>{q.current===m&&(x(W.models??[]),ie(W.favoriteProviders??[]),G(W.favoriteModels??[]))}).catch(()=>{q.current===m&&(x([]),ie([]),G([]),d(g("workflowSettings.modelsLoadFailed","Failed to load available models"),"error"))}).finally(()=>{q.current===m&&E(!1)})},[r,y.length,d,g]),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:g("workflowSettings.requiresProject","Open a project to view and edit per-project setting values.")})});const te=m=>{if(Object.prototype.hasOwnProperty.call(S,m.id)){const W=S[m.id];return W===null?m.default:W}return I?.effective?.[m.id]??m.default},de=m=>Object.prototype.hasOwnProperty.call(S,m.id)?S[m.id]!==null:I?Object.prototype.hasOwnProperty.call(I.stored,m.id):!1,re=(m,W)=>{M(J=>({...J,[m]:W})),k(J=>{if(!J[m])return J;const X={...J};return delete X[m],X})},U=m=>re(m,null),he=(m,W)=>{const J=Fl(W);M(X=>({...X,[m.providerId]:J?.provider??null,[m.modelId]:J?.modelId??null})),k(X=>{if(!X[m.providerId]&&!X[m.modelId])return X;const ae={...X};return delete ae[m.providerId],delete ae[m.modelId],ae})},F=Object.keys(S).length>0,K=a.useCallback(async()=>{if(!F)return;const m=new Set(Object.keys(S));c(!0);try{const W=await ts(s,S,r);f(W),M(J=>{const X={...J};for(const ae of m)delete X[ae];return X}),k({}),d(g("workflowSettings.valuesSaved","Setting values saved"),"success")}catch(W){if(W instanceof Us&&W.status===400&&W.details){const J=W.details.rejections??[];if(J.length>0){const X={};for(const ae of J)X[ae.settingId]=ae;k(X),d(g("workflowSettings.valuesRejected","Some values were rejected — see the highlighted fields"),"error");return}}d(g("workflowSettings.saveFailed","Failed to save setting values"),"error")}finally{c(!1)}},[F,s,S,r,d,g]),se=m=>{const W=Z.get(m);return W?te(W):void 0},ce=m=>{const W=Z.get(m);return W?de(W):!1},be=m=>{const W=se(m.providerId),J=se(m.modelId),X=typeof W=="string"&&typeof J=="string"?`${W}/${J}`:"",ae=N[m.providerId]?.message??N[m.modelId]?.message,Y=ce(m.providerId)||ce(m.modelId),ue=z||D.length===0,oe=!z&&D.length===0?` ${g("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(Ke,{htmlFor:`wf-model-lane-${m.id}`,label:m.label,help:`${m.help}${oe}`,error:ae,scope:"project",disabled:z,clearable:Y,onClear:()=>he(m,""),children:e.jsx(lo,{id:`wf-model-lane-${m.id}`,label:m.label,models:D,value:X,onChange:fe=>he(m,fe),placeholder:g("workflowSettings.selectModel","Select a model…"),defaultOptionLabel:g("workflowSettings.useInheritedModel","Use inherited/default model"),disabled:ue,favoriteProviders:Q,favoriteModels:B})}),Y&&e.jsx("span",{className:"wf-settings-customized","data-testid":`wf-settings-customized-${m.id}`,children:g("workflowSettings.customized","Customized")})]},m.id)},o=m=>{const W=te(m),J=N[m.id]?.message,X=de(m),ae=Qs(m),Y={key:m.id,label:ae.label,help:ae.description??m.description,scope:"project"},ue=X;switch(m.type){case"boolean":return e.jsx(bl,{descriptor:Y,value:W===!0,error:J,clearable:ue,onChange:oe=>oe===null?U(m.id):re(m.id,oe)});case"number":return e.jsx(kl,{descriptor:Y,value:typeof W=="number"?W:null,error:J,clearable:ue,onChange:oe=>oe===null?U(m.id):re(m.id,oe)});case"enum":return e.jsx(Rs,{descriptor:{...Y,options:(m.options??[]).map(oe=>({value:oe.value,label:oe.label}))},value:typeof W=="string"?W:null,error:J,clearable:ue,onChange:oe=>oe===null?U(m.id):re(m.id,oe)});case"multi-enum":{const oe=Array.isArray(W)?W[0]??null:null;return e.jsx(Rs,{descriptor:{...Y,options:(m.options??[]).map(fe=>({value:fe.value,label:fe.label}))},value:oe,error:J,clearable:ue,onChange:fe=>fe===null?U(m.id):re(m.id,[fe])})}case"text":return e.jsx(vl,{descriptor:Y,value:typeof W=="string"?W:null,error:J,clearable:ue,onChange:oe=>oe===null||oe===""?U(m.id):re(m.id,oe)});case"string":default:return e.jsx(xl,{descriptor:Y,value:typeof W=="string"?W:null,error:J,clearable:ue,onChange:oe=>oe===null||oe===""?U(m.id):re(m.id,oe)})}},ke=I?.orphaned??[],it=a.useCallback(async m=>{try{const W=await ts(s,{[m]:null},r);f(W),d(g("workflowSettings.orphanDeleted","Orphaned value removed"),"success")}catch{d(g("workflowSettings.saveFailed","Failed to save setting values"),"error")}},[s,r,d,g]);return e.jsxs("div",{className:"wf-settings-tabpanel","data-testid":"wf-settings-values",children:[T&&e.jsxs("p",{className:"wf-settings-note wf-settings-note--warn",role:"note","data-testid":"wf-settings-stale-notice",children:[e.jsx(Te,{size:12,"aria-hidden":!0})," ",g("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:K,disabled:!F||h||T,"data-testid":"wf-settings-save-values",children:[e.jsx(no,{size:13})," ",g("workflowSettings.saveValues","Save values")]})}),i.length===0?e.jsx("p",{className:"wf-settings-empty",children:A?e.jsx(Xa,{label:g("workflowSettings.loading","Loading…")}):g("workflowSettings.noDeclarations","This workflow declares no settings, so there are no values to edit.")}):e.jsx("div",{className:"wf-settings-values-list",children:gl(i).map(({group:m,settings:W})=>{const J=new Set(W.map(Y=>Y.id)),X=m==="models"?y.filter(Y=>J.has(Y.providerId)&&J.has(Y.modelId)):[],ae=W.filter(Y=>!O.has(Y.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:g(`workflowSettings.group.${m}`,hl[m])}),X.map(Y=>be(Y)),ae.map(Y=>e.jsxs("div",{className:"wf-settings-value-item","data-testid":`wf-settings-value-${Y.id}`,children:[o(Y),de(Y)&&e.jsx("span",{className:"wf-settings-customized","data-testid":`wf-settings-customized-${Y.id}`,children:g("workflowSettings.customized","Customized")})]},Y.id))]},m)})}),ke.length>0&&e.jsxs("div",{className:"wf-settings-orphaned","data-testid":"wf-settings-orphaned",children:[e.jsxs("button",{className:"wf-settings-orphaned-toggle",onClick:()=>b(m=>!m),"aria-expanded":j,children:[j?e.jsx(Se,{size:13}):e.jsx(Re,{size:13})," ",g("workflowSettings.orphanedTitle","Orphaned values ({{count}})",{count:ke.length})]}),j&&e.jsxs("div",{className:"wf-settings-orphaned-body",children:[e.jsx("p",{className:"wf-settings-note wf-settings-note--muted",role:"note",children:g("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:ke.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:El(m.value)}),e.jsx("button",{className:"wf-settings-orphan-delete","aria-label":g("workflowSettings.deleteOrphan","Delete orphaned value"),disabled:T||h,onClick:()=>it(m.id),children:e.jsx(Ne,{size:12})})]},m.id))})]})]}),i.length>0&&e.jsxs("p",{className:"wf-settings-reset-hint",role:"note",children:[e.jsx(Hs,{size:11,"aria-hidden":!0})," ",g("workflowSettings.clearHint","Use the reset control on a row to clear a value back to its declaration default.")]})]})}function Os({workflowId:s,settings:i,onChange:r,readOnly:w,projectId:d,addToast:g,initialTab:I}){const{t:f}=ye("app"),[A,P]=a.useState(()=>I??(i.length>0?"values":"definitions")),S=a.useRef({workflowId:s,projectId:d});S.current.workflowId!==s&&(S.current={workflowId:s,projectId:d});const M=S.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:f("workflowSettings.title","Settings")})}),e.jsxs("div",{className:"wf-settings-tabs",role:"tablist",children:[e.jsx("button",{role:"tab","aria-selected":A==="definitions",className:`wf-settings-tab${A==="definitions"?" is-active":""}`,onClick:()=>P("definitions"),"data-testid":"wf-settings-tab-definitions",children:f("workflowSettings.definitionsTab","Definitions")}),e.jsx("button",{role:"tab","aria-selected":A==="values",className:`wf-settings-tab${A==="values"?" is-active":""}`,onClick:()=>P("values"),"data-testid":"wf-settings-tab-values",children:f("workflowSettings.valuesTab","Values")})]}),A==="definitions"?e.jsx(Sl,{settings:i,onChange:r,readOnly:w,addToast:g}):e.jsx(Pl,{workflowId:s,settings:i,boundProjectId:M,currentProjectId:d,addToast:g},s)]})}function Zs(s,i){return s[i]?.editable?{up:s[i-1]?.editable===!0,down:s[i+1]?.editable===!0}:{up:!1,down:!1}}function ea({row:s,depth:i,selectedNodeId:r,selectedEdgeId:w,onSelectNode:d,onSelectEdge:g,onCreateConnection:I,canReorder:f,onMoveNode:A,canMoveUp:P,canMoveDown:S}){const{t:M}=ye("app"),N=s.children.length>0,[k,h]=a.useState(i===0),[c,j]=a.useState(!1),b=r===s.id,D=s.connectionTargets??[],x=!!I&&s.editable&&D.length>0,z=!!f&&!!A&&s.editable;return e.jsxs("div",{className:"mobile-wf-node-group",children:[e.jsxs("div",{className:`mobile-wf-node-row${b?" 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":b?"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]}),N||z?e.jsxs("div",{className:"mobile-wf-node-actions",children:[z?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":M("workflowNodes.mobileMoveUp","Move up"),disabled:!P,onClick:()=>A?.(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":M("workflowNodes.mobileMoveDown","Move down"),disabled:!S,onClick:()=>A?.(s.id,"down"),children:e.jsx(en,{size:16,"aria-hidden":!0})})]}):null,N?e.jsx("button",{type:"button",className:"mobile-wf-node-expand","aria-expanded":k,"aria-label":k?M("common.collapse","Collapse"):M("common.expand","Expand"),onClick:()=>h(E=>!E),children:k?e.jsx(Se,{size:16}):e.jsx(Re,{size:16})}):null]}):null]}),x?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:()=>j(E=>!E),children:[e.jsx(os,{size:14,"aria-hidden":!0}),e.jsx("span",{children:M("workflowNodes.mobileConnect","Connect")})]})}):null,x&&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:M("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:E=>{const Q=E.currentTarget.value;Q&&(I?.(s.id,Q),E.currentTarget.value="",j(!1))},children:[e.jsx("option",{value:"",children:M("workflowNodes.mobileConnectChooseTarget","Choose a target…")}),D.map(E=>e.jsxs("option",{value:E.id,children:[E.label," (",E.kind,")"]},E.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(E=>e.jsxs("button",{type:"button",className:`mobile-wf-edge-chip${w===E.id?" mobile-wf-edge-chip--selected":""}`,"data-testid":`mobile-wf-edge-${E.id}`,onClick:()=>g(E.id),children:[e.jsx(os,{size:12,"aria-hidden":!0}),e.jsx("span",{children:E.label}),e.jsx("span",{className:"mobile-wf-edge-target",children:E.targetLabel})]},E.id))]}),N&&k?e.jsx("div",{className:"mobile-wf-node-children",children:s.children.map((E,Q)=>{const ie=Zs(s.children,Q);return e.jsx(ea,{row:E,depth:i+1,selectedNodeId:r,selectedEdgeId:w,onSelectNode:d,onSelectEdge:g,onCreateConnection:I,canReorder:f,onMoveNode:A,canMoveUp:ie.up,canMoveDown:ie.down},E.id)})}):null]})}function Rl({rows:s,selectedNodeId:i,selectedEdgeId:r,onSelectNode:w,onSelectEdge:d,onCreateConnection:g,canReorder:I,onMoveNode:f}){const{t:A}=ye("app");return s.length===0?e.jsx("div",{className:"mobile-wf-graph-empty","data-testid":"mobile-wf-graph-empty",children:A("workflowNodes.mobileGraphEmpty","No graph nodes yet.")}):e.jsx("div",{className:"mobile-wf-graph","data-testid":"mobile-wf-graph",children:s.map((P,S)=>{const M=Zs(s,S);return e.jsx(ea,{row:P,depth:0,selectedNodeId:i,selectedEdgeId:r,onSelectNode:w,onSelectEdge:d,onCreateConnection:g,canReorder:I,onMoveNode:f,canMoveUp:M.up,canMoveDown:M.down},P.id)})})}function Ml(s){return typeof s.label=="string"&&s.label.trim()?s.label:String(s.data?.condition??"success")}function Ds(s){return s.data.label||s.id}function ro(s,i){const r=Math.round(s.position.y),w=Math.round(i.position.y);return r!==w?r-w:Math.round(s.position.x)-Math.round(i.position.x)}function Ts(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 w=s.find(f=>f.id===i);if(!w||!Ts(w))return s;const d=s.filter(f=>Il(w,f)).sort(ro),g=d.findIndex(f=>f.id===i),I=d[g+(r==="up"?-1:1)];return!I||!Ts(I)?s:s.map(f=>f.id===w.id?{...f,position:{...I.position}}:f.id===I.id?{...f,position:{...w.position}}:f)}function Dl(s,i){const r=new Map(s.map(w=>[w.id,w.name||w.id]));for(const w of i){if(!we(w.id))continue;const d=tn(w.id);r.has(d)||r.set(d,w.data.label||d)}return r}function Tl(s,i,r=[],w={},d){const g=Dl(r,s),I=new Map(s.map(N=>[N.id,N])),f=new Map,A=new Map;for(const N of s){if(!N.parentId)continue;const k=f.get(N.parentId)??[];k.push(N),f.set(N.parentId,k)}for(const N of f.values())N.sort(ro);for(const N of i){const k=A.get(N.source)??[];k.push(N),A.set(N.source,k)}const P=N=>{const k=I.get(N.target);return{id:N.id,source:N.source,target:N.target,targetLabel:k?Ds(k):N.target,label:Ml(N),kind:typeof N.data?.kind=="string"?N.data.kind:void 0}},S=N=>{const k=(f.get(N.id)??[]).map(S),h=N.data.column;return{id:N.id,label:Ds(N),kind:N.data.kind,summary:sn(N.data,w,d),columnName:h?g.get(h)??h:void 0,editable:N.data.kind!=="start"&&N.data.kind!=="end"&&!we(N.id),parentId:N.parentId,templateLocalId:N.parentId?on(N.parentId,N.id):void 0,outgoing:(A.get(N.id)??[]).map(P),children:k}};return s.filter(N=>!N.parentId&&!we(N.id)).sort(ro).map(S)}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"}],Ue=s=>s.startsWith("builtin:");function Ls(s,i){return s&&i?`${s}/${i}`:""}function zs(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 oo(s,i,r,w,d,g,I){const{ir:f,layout:A}=Ks(s,r,w,d.length?d:void 0,g.length?g:void 0,I.length?I:void 0);return JSON.stringify({name:s,description:i,ir:f,layout:A})}let Ws=0;function $s(){return Ws+=1,`n-${Date.now().toString(36)}-${Ws}`}const _l=["step-headings","json-steps"],Bl=["approve","revise","rethink","unavailable"],_s=["in-review","merged","failed","awaiting-approval","task-created","workflow-notify"],so="__custom",Gl="npm test -- --runInBand",ql='export default async (ctx) => ({ outcome: "success" });',Vl="Task {{taskId}} reached {{workflowName}}",Bs=[{kind:"prompt",label:"Prompt",icon:In},{kind:"prompt",label:"User input",icon:Xs,presetConfig:{awaitInput:!0}},{kind:"script",label:"Script",icon:On},{kind:"gate",label:"Gate",icon:Dn},{kind:"merge",label:"Merge boundary",icon:Tn},{kind:"hold",label:"Hold",icon:Ln,presetConfig:{release:"manual"}},{kind:"split",label:"Split",icon:zn},{kind:"join",label:"Join",icon:Wn,presetConfig:{mode:"all",onBranchFailure:"collect"}},{kind:"foreach",label:"For-each step",icon:ks,presetConfig:{source:"task-steps"}},{kind:"loop",label:"Loop",icon:ks,presetConfig:{maxIterations:3,exitWhen:{type:"output-contains",value:"DONE"}}},{kind:"optional-group",label:"Optional group",icon:$n,presetConfig:{defaultOn:!1}},{kind:"step-review",label:"Step review",icon:_n,presetConfig:{type:"code"}},{kind:"parse-steps",label:"Parse steps",icon:Js,presetConfig:{artifact:"PROMPT.md",parser:"step-headings"}},{kind:"code",label:"Code",icon:Bn,presetConfig:{source:""}},{kind:"notify",label:"Notify",icon:Gn,presetConfig:{event:"in-review",title:"{{taskTitle}}",message:""}}];function Gs(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:w}){const{t:d}=ye("app"),[g,I]=a.useState(""),[f,A]=a.useState(""),[P,S]=a.useState(null),[M,N]=a.useState(!1),[k,h]=a.useState(!1),[c,j]=a.useState(""),[b,D]=a.useState(!1),[x,z]=a.useState(null),E=a.useRef(null),[Q,ie]=a.useState(!1),B=a.useRef(null),G=a.useRef([]),le=a.useMemo(()=>{const F={id:null,name:d("workflows.templateBlank","Blank"),description:d("workflows.templateBlankDescription","Start from an empty start → end graph."),nodeCount:0,builtin:!1},K=s.filter(o=>o.kind!=="fragment"),se=o=>({id:o.id,name:o.name,description:o.description??"",nodeCount:o.ir.nodes.length,source:o,builtin:Ue(o.id)}),ce=K.filter(o=>Ue(o.id)).map(se),be=K.filter(o=>!Ue(o.id)).map(se);return[F,...ce,...be]},[s,d]),[q,Z]=a.useState(0),y=le[q]??le[0];a.useEffect(()=>{B.current?.focus()},[]);const O=a.useCallback(F=>{const K=le[F];K&&(Z(F),Q||(K.id===null?(I(""),A("")):(I(d("workflows.templateCopyName","{{name}} copy",{name:K.name})),A(K.description))),P&&S(null))},[le,Q,P,d]),T=a.useCallback(F=>{if(F.key==="ArrowDown"||F.key==="ArrowRight"){F.preventDefault();const K=Math.min(q+1,le.length-1);O(K),G.current[K]?.focus()}else if(F.key==="ArrowUp"||F.key==="ArrowLeft"){F.preventDefault();const K=Math.max(q-1,0);O(K),G.current[K]?.focus()}else(F.key==="Enter"||F.key===" ")&&(F.preventDefault(),O(q),B.current?.focus())},[q,le.length,O]),V=Ys(w),te=a.useCallback(async F=>{F.preventDefault();const K=g.trim();if(!K){S(d("workflows.createNameRequired","Enter a workflow name"));return}N(!0),S(null);try{await i(K,f.trim(),y)}catch(se){S(ne(se)||d("workflows.createFailed","Failed to create workflow")),N(!1)}},[g,f,y,i,d]),de=a.useCallback(async()=>{const F=c.trim();if(!F){z(d("workflows.aiPromptRequired","Describe the workflow you want"));return}const K=new AbortController;E.current=K,D(!0),z(null);try{await r(F,g.trim(),K.signal)}catch(se){if(K.signal.aborted)return;z(ne(se)||d("workflows.aiFailed","Failed to design workflow"))}finally{E.current===K&&(E.current=null),D(!1)}},[c,g,r,d]),re=a.useCallback(()=>{E.current?.abort(),D(!1)},[]),U=le.findIndex(F=>F.id!==null&&F.builtin),he=le.findIndex(F=>F.id!==null&&!F.builtin);return e.jsx("div",{className:"modal-overlay open wf-create-overlay",...V,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:F=>F.stopPropagation(),onKeyDown:F=>{F.key==="Escape"&&(F.stopPropagation(),w())},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:w,"aria-label":d("actions.close","Close"),children:e.jsx(io,{size:16})})]}),e.jsxs("form",{onSubmit:te,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":k,onClick:()=>{h(F=>!F),z(null)},children:[e.jsx(He,{size:13})," ",d("workflows.aiToggle","Describe it instead")]}),k&&e.jsxs("div",{className:"wf-ai-create-body",children:[e.jsx("textarea",{className:"wf-ai-prompt","data-testid":"wf-ai-prompt",rows:3,value:c,disabled:b,placeholder:d("workflows.aiPromptPlaceholder","e.g. Run lint and tests before merge, then post a changelog comment after merge"),onChange:F=>{j(F.target.value),x&&z(null)}}),x&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-ai-error",children:x}),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 de(),children:[b?e.jsx(Me,{size:13,className:"wf-spin"}):e.jsx(He,{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:re,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:le.map((F,K)=>{const se=K===q,ce=F.id??"blank";return e.jsxs("div",{children:[K===U&&U>=0&&e.jsx("p",{className:"wf-template-section",children:d("workflows.templateSectionBuiltin","Built-in workflows")}),K===he&&he>=0&&e.jsx("p",{className:"wf-template-section",children:d("workflows.templateSectionYours","Your workflows")}),e.jsxs("div",{ref:be=>{G.current[K]=be},role:"radio","aria-checked":se,tabIndex:se?0:-1,className:`wf-template-option${se?" selected":""}`,"data-testid":F.id===null?"wf-template-option-blank":`wf-template-option-${F.id}`,onClick:()=>{O(K),G.current[K]?.focus()},onKeyDown:T,children:[e.jsx("span",{className:"wf-template-option-name",children:F.name}),F.description&&e.jsx("span",{className:"wf-template-option-desc",children:F.description}),F.id!==null&&e.jsx("span",{className:"wf-template-option-count",children:d("workflows.templateNodeCount","{{count}} nodes",{count:F.nodeCount})})]})]},ce)})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:d("workflows.createName","Name")}),e.jsx("input",{ref:B,"data-testid":"wf-create-name",value:g,onChange:F=>{I(F.target.value),ie(!0),P&&S(null)}})]}),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:f,onChange:F=>A(F.target.value)})]}),P&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-create-error",children:P})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{type:"button",className:"btn",onClick:w,children:d("common.cancel","Cancel")}),e.jsxs("button",{type:"submit",className:"btn btn-primary","data-testid":"wf-create-submit",disabled:M,children:[M?e.jsx(Me,{size:13,className:"wf-spin"}):null," ",d("workflows.createSubmit","Create")]})]})]})]})})}function Kl({onClose:s,addToast:i,projectId:r,initialPanel:w,initialAction:d,initialWorkflowId:g,modalRef:I,isEmbedded:f=!1}){const[A,P]=a.useState([]),[S,M]=a.useState(null),k=ln()==="mobile",[h,c]=a.useState(()=>ss()),[j,b]=a.useState(!1),[D,x]=a.useState(!1),[z,E]=a.useState(null),[Q,ie]=a.useState(!1),[B,G,le]=La([]),[q,Z,y]=za([]),[O,T]=a.useState(null),[V,te]=a.useState(null),[de,re]=a.useState(!1),[U,he]=a.useState(!1),[F,K]=a.useState(!1),[se,ce]=a.useState(()=>w==="settings"?"settings":"graph"),be=k||F,{t:o}=ye("app"),{confirm:ke}=rn(),[it,m]=a.useState(d==="create"),W=a.useRef(null),J=a.useRef(null),[X,ae]=a.useState(""),[Y,ue]=a.useState(""),[oe,fe]=a.useState(!1),[ta,Ye]=a.useState(!1),Je=a.useRef(null),[ee,Xe]=a.useState([]),[Ae,Qe]=a.useState([]),[Fe,Ze]=a.useState([]),[Le,rt]=a.useState(null),[oa,ze]=a.useState(null),Et=a.useRef(null),[co,sa]=a.useState([]),[aa,na]=a.useState([..._l]),[At,la]=a.useState([]),[Ft,ia]=a.useState([]),uo="fusion:wf-templates-collapsed",[We,ra]=a.useState(()=>{try{const t=localStorage.getItem(uo);return t!=null?t==="1":ss()}catch{return!1}}),[dt,fo]=a.useState(""),[ct,po]=a.useState(null),Pt=a.useRef(!1),mo="fusion:wf-left-sidebar-collapsed",wo="fusion:wf-sidebar-columns-collapsed",ho="fusion:wf-sidebar-fields-collapsed",go="fusion:wf-sidebar-settings-collapsed",[et,bo]=a.useState(()=>{try{return localStorage.getItem(mo)==="1"}catch{return!1}}),[tt,da]=a.useState(()=>{try{return localStorage.getItem(wo)==="1"}catch{return!1}}),[ot,ca]=a.useState(()=>{try{return localStorage.getItem(ho)==="1"}catch{return!1}}),[st,ua]=a.useState(()=>{try{return localStorage.getItem(go)==="1"}catch{return!1}});a.useEffect(()=>{try{localStorage.setItem(mo,et?"1":"0")}catch{}},[et]),a.useEffect(()=>{try{localStorage.setItem(wo,tt?"1":"0")}catch{}},[tt]),a.useEffect(()=>{try{localStorage.setItem(ho,ot?"1":"0")}catch{}},[ot]),a.useEffect(()=>{try{localStorage.setItem(go,st?"1":"0")}catch{}},[st]);const{setViewport:ko}=Wa(),Rt=a.useRef(null),ut=a.useMemo(()=>`fusion:wf-migration-notice-dismissed${r?`:${r}`:""}`,[r]),[fa,xo]=a.useState(!1),[vo,Mt]=a.useState(null),[jo,No]=a.useState([]),[yo,Co]=a.useState(!1),ft=a.useRef(null),[It,Ot]=a.useState(!1),[pt,Dt]=a.useState(""),[xe,Tt]=a.useState(!1),[$e,_e]=a.useState(null),mt=a.useRef(null),Lt=a.useRef(!1),C=a.useMemo(()=>A.find(t=>t.id===S),[A,S]),L=!!C&&Ue(C.id),So=a.useRef(S);So.current=S;const pa=a.useMemo(()=>!C||L?!1:!B.some(t=>Hl.has(t.data.kind)),[C,L,B]),Eo=!0;a.useEffect(()=>{let t=!1;return Vs(r).then(n=>{t||sa(n)}).catch(()=>{}),()=>{t=!0}},[r]),a.useEffect(()=>{let t=!1;return dn(r).then(n=>{!t&&n.length>0&&na(n)}).catch(()=>{}),()=>{t=!0}},[r]),a.useEffect(()=>{let t=!1;return cn().then(n=>{t||la(n.templates??[])}).catch(()=>{}),un().then(n=>{t||ia(n.templates??[])}).catch(()=>{}),()=>{t=!0}},[]),a.useEffect(()=>{try{localStorage.setItem(uo,We?"1":"0")}catch{}},[We]),a.useEffect(()=>{O&&re(!1)},[O]),a.useEffect(()=>{w==="settings"&&ce("settings")},[w]);const zt=a.useMemo(()=>A.filter(t=>t.kind==="fragment"),[A]),pe=a.useMemo(()=>{const t=dt.trim().toLowerCase(),n=R=>!t||R.toLowerCase().includes(t),l=(R,H)=>R.name.localeCompare(H.name),p=[...zt].sort(l).filter(R=>n(R.name)),v=[...At].sort(l).filter(R=>n(R.name)),_=[...Ft].sort((R,H)=>R.template.name.localeCompare(H.template.name)).filter(R=>n(R.template.name));return{fragmentEntries:p,stepEntries:v,pluginEntries:_}},[zt,At,Ft,dt]),Wt=zt.length+At.length+Ft.length,Ao=Wt>0,$t=a.useMemo(()=>ee.length?fn(ee,co):[],[ee,co]),Ie=a.useMemo(()=>pn(B,ee),[B,ee]),Fo=$t.filter(t=>t.severity==="error").length,at=a.useMemo(()=>L||!C||Je.current===null?!1:oo(X,Y,B,q,ee,Ae,Fe)!==Je.current,[L,C,X,Y,B,q,ee,Ae,Fe]),Be=a.useCallback(async()=>{b(!0);try{const t=await mn(r);P(t),M(n=>n&&t.some(l=>l.id===n)?n:d!=="create"&&g&&t.some(l=>l.id===g)?g:k?null:t[0]?.id??null)}catch(t){i(ne(t)||o("workflows.loadFailed","Failed to load workflows"),"error")}finally{b(!1)}},[r,i,k,d,g,o]);a.useEffect(()=>{Be()},[Be]),a.useEffect(()=>{!g||!k||!h||S===g&&J.current!==g&&(J.current=g,c(!1))},[S,g,k,h]);const Po=a.useRef(!1);a.useEffect(()=>{if(Po.current)return;Po.current=!0;let t=!1;return(async()=>{try{const n=await wn(r);if(t)return;if(n.migrated>0){if(await Be(),t)return;let l=!1;try{l=localStorage.getItem(ut)==="1"}catch{}l||xo(!0)}}catch{}})(),()=>{t=!0}},[r,Be,ut]);const ma=a.useCallback(()=>{xo(!1);try{localStorage.setItem(ut,"1")}catch{}},[ut]),wt=a.useCallback(async()=>{if(C)try{await hn(C.id,r)}catch(t){i(ne(t)||o("workflows.exportFailed","Failed to export workflow"),"error")}},[C,r,i,o]),wa=a.useCallback(async t=>{const n=t.target.files?.[0];if(ft.current&&(ft.current.value=""),!!n){Mt(null),No([]),Co(!0);try{const l=await n.text();let p;try{p=JSON.parse(l)}catch{Mt(o("workflows.importInvalidJson","That file isn't valid JSON."));return}const v=await gn(p,r);await Be(),M(v.workflow.id),c(!1),i(o("workflows.imported",'Imported workflow "{{name}}"',{name:v.workflow.name}),"success"),v.strippedApprovalFlags&&i(o("workflows.importStripped","Auto-approval flags were removed from imported nodes"),"warning"),v.warnings.length>0&&No(v.warnings)}catch(l){l instanceof Us&&l.status>=400&&l.status<500?Mt(ne(l)||o("workflows.importFailed","Import failed")):i(ne(l)||o("workflows.importFailed","Import failed"),"error")}finally{Co(!1)}}},[r,Be,i,o]);a.useEffect(()=>{if(Pt.current=!1,!C){G([]),Z([]),Xe([]),Qe([]),Ze([]),rt(null),ze(null),ae(""),ue(""),Je.current=null;return}const t=as(C),n=ns(C),l=ls(C),p=is(C),v=ys(t.nodes,t.edges,n),_=Cs(t.nodes,v);G(_),Z(t.edges),Xe(n),Qe(l),Ze(p),ae(C.name),ue(C.description??""),fe(!1),Ye(!1),Je.current=oo(C.name,C.description??"",_,t.edges,n,l,p),T(null),te(null),E(null),ko({x:0,y:0,zoom:1},{duration:0}),Lt.current?(Lt.current=!1,ie(!0)):ie(!1)},[C,G,Z,ko]),a.useEffect(()=>{B.length>0&&(Pt.current=!0)},[B]),a.useEffect(()=>{if(!C||!L){rt(null),ze(null);return}let t=!1;return rs(C.id,r).then(n=>{t||(rt(n),G(l=>l.map(p=>{if(p.data.kind!=="prompt"&&p.data.kind!=="gate")return p;const v=n.effective[p.id];return v===void 0?p:{...p,data:{...p.data,config:{...p.data.config??{},prompt:v}}}})))}).catch(n=>{t||i(ne(n)||o("workflowEditor.promptOverridesLoadFailed","Failed to load prompt overrides"),"error")}),()=>{t=!0}},[C,L,r,i,o,G]);const _t=a.useRef(!1);a.useEffect(()=>{if(w!=="settings"||_t.current||!C)return;const t=Et.current;t&&(_t.current=!0,t.scrollIntoView({behavior:"smooth",inline:"end",block:"nearest"}))},[w,C]),a.useEffect(()=>()=>{_t.current=!1},[w]);const[Bt,Ro]=a.useState(null);a.useEffect(()=>{G(t=>{const n=t.filter(l=>!we(l.id)&&l.type!=="group");return[...bn(ee),...kn(n,ee)]})},[ee,G]);const ht=a.useCallback((t,n={})=>{const l=xn(t,q,B);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");return}Z(p=>[...p,l.edge]),n.selectCreatedEdge&&(te(l.edge.id),T(null),re(!1))},[q,B,Z,i,o]),ha=a.useCallback(t=>{ht(t)},[ht]),ga=a.useCallback((t,n)=>{ht({source:t,target:n,sourceHandle:null,targetHandle:null},{selectCreatedEdge:!0})},[ht]),ba=a.useCallback((t,n)=>{G(l=>Ol(l,t,n))},[G]),ka=a.useCallback((t,n)=>{if(we(n.id)||ee.length===0)return;const l=ao(n.position.y,ee);l&&G(p=>p.map(v=>v.id===n.id?{...v,data:{...v.data,column:l}}:v))},[ee,G]),gt=a.useCallback((t,n,l)=>{const p=$s(),v=n??(t==="merge"?"Merge boundary":t.charAt(0).toUpperCase()+t.slice(1)),_=t==="gate"?{gateMode:"gate"}:{},R=l?{..._,...l}:_;if(t==="foreach"||t==="loop"||t==="optional-group"){const H=vn(p,$s()),ge=t==="foreach"?o("workflowNodes.stepExecuteLabel","Step execute"):t==="optional-group"?o("workflowNodes.optionalGroupStepLabel","Optional step"):o("workflowNodes.loopStepLabel","Loop step"),Pe=t==="foreach"?{seam:"step-execute"}:{prompt:""};G(Xt=>[...Xt,{id:p,type:t,position:{x:200+Xt.length*40,y:240+Xt.length%3*70},data:{kind:t,label:v,config:R,templateEmpty:!1},style:{width:Nn,height:jn},deletable:!0},{id:H,type:"prompt",position:{x:Cn,y:yn},parentId:p,extent:"parent",data:{kind:"prompt",label:ge,config:Pe},deletable:!0}]),T(p);return}G(H=>[...H,{id:p,type:t,position:{x:200+H.length*40,y:240+H.length%3*70},data:{kind:t,label:v,config:R},deletable:!0}]),T(p)},[G,o]),bt=a.useCallback(t=>{if(L)return;const{kind:n,label:l,config:p}=Gs(t);gt(n,l,p)},[L,gt]),Mo=a.useCallback(t=>{if(L)return;const{kind:n,config:l}=Gs(t),p=Sn({kind:n,config:l},{name:t.name,defaultOn:t.defaultOn??!1}),v=ds(B,q,p,{x:240,y:200+B.length%4*40});G(v.nodes),Z(v.edges),T(v.insertedNodeIds[0]??null)},[L,B,q,G,Z]),Io=a.useCallback(t=>{if(L)return!1;const n=Pt.current?void 0:C?.ir,l=En(t.ir,B,n);if(l.length>0)return po(l.join(", ")),!1;po(null);const p=ds(B,q,t.ir,{x:240,y:200+B.length%4*40},t.layout);return G(p.nodes),Z(p.edges),T(p.insertedNodeIds[0]??null),!0},[L,B,q,C,G,Z]),Oo=a.useCallback(()=>{G(t=>Cs(t,ys(t,q,ee)))},[G,q,ee]),Do=a.useCallback(async()=>{if(!C||L)return;const t=pt.trim();if(!t){_e(o("workflows.aiPromptRequired","Describe the workflow you want"));return}const n=new AbortController;mt.current=n;const l=C;Tt(!0),_e(null);try{const p=await cs({prompt:t,workflowId:l.id},r,n.signal);if(So.current!==l.id){i(o("workflows.aiStaleDiscarded","Discarded AI design — you switched workflows"),"warning");return}if(!await ke({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 _=as({...l,ir:p.ir,layout:p.layout});G(_.nodes),Z(_.edges),Xe(ns({...l,ir:p.ir})),Qe(ls({...l,ir:p.ir})),Ze(is({...l,ir:p.ir})),T(null),te(null),E(null),ie(p.interpreterOnly),p.strippedApprovalFlags&&i(o("workflows.importStripped","Auto-approval flags were removed from imported nodes"),"warning"),Ot(!1),Dt("")}catch(p){if(n.signal.aborted)return;_e(ne(p)||o("workflows.aiFailed","Failed to design workflow"))}finally{mt.current===n&&(mt.current=null),Tt(!1)}},[C,L,pt,r,ke,o,G,Z,i]),To=a.useCallback(()=>{mt.current?.abort(),Tt(!1)},[]),$=a.useCallback(t=>{O&&G(n=>n.map(l=>l.id===O?{...l,data:{...l.data,..."config"in t?{config:typeof t.config=="function"?t.config(l.data.config??{}):{...l.data.config??{},...t.config}}:t}}:l))},[O,G]),nt=a.useCallback((t,n)=>{rt(n);const l=n.effective[t]??n.defaults[t]??"";G(p=>p.map(v=>v.id===t?{...v,data:{...v.data,config:{...v.data.config??{},prompt:l}}}:v))},[G]),Lo=a.useCallback(async(t,n)=>{if(!(!C||!L)){ze(t);try{const l=await us(C.id,{[t]:n},r);nt(t,l),i(o("workflowEditor.promptOverrideSaved","Prompt override saved"),"success")}catch(l){i(ne(l)||o("workflowEditor.promptOverrideSaveFailed","Failed to save prompt override"),"error");try{const p=await rs(C.id,r);nt(t,p)}catch{}}finally{ze(l=>l===t?null:l)}}},[C,L,r,i,o,nt]),zo=a.useCallback(async t=>{if(!(!C||!L)){ze(t);try{const n=await us(C.id,{[t]:null},r);nt(t,n),i(o("workflowEditor.promptOverrideReset","Prompt reset to default"),"success")}catch(n){i(ne(n)||o("workflowEditor.promptOverrideResetFailed","Failed to reset prompt"),"error")}finally{ze(n=>n===t?null:n)}}},[C,L,r,i,o,nt]),Gt=a.useCallback(t=>{V&&Z(n=>n.map(l=>{if(l.id!==V)return l;const p=t.condition??l.data?.condition??"success",v=t.rework??l.data?.kind==="rework";return{...l,label:v?`${fs(p)} (rework)`:fs(p),data:{...l.data??{},condition:p,kind:v?"rework":void 0},type:v?"step":void 0,animated:v,className:An(p,v)}}))},[V,Z]),Wo=a.useCallback(t=>{const n=new Set(t);let l=null;G(p=>(l=ps(p,q,n),l.nodes)),l&&Z(l.edges),O!==null&&n.has(O)&&T(null),V!==null&&n.has(V)&&te(null)},[q,G,Z,O,V]),xa=a.useCallback(async({nodes:t,edges:n})=>{if(L)return!1;const l=new Set([...t.map(R=>R.id),...n.map(R=>R.id)]),p=ps(B,q,l),v=new Set(B.map(R=>R.id));for(const R of p.nodes)v.delete(R.id);const _=new Set(q.map(R=>R.id));for(const R of p.edges)_.delete(R.id);return v.size===0&&_.size===0?!1:{nodes:B.filter(R=>v.has(R.id)),edges:q.filter(R=>_.has(R.id))}},[L,B,q]),va=a.useCallback(()=>{T(null),Rt.current?.focus()},[]),ja=a.useCallback(()=>{te(null),Rt.current?.focus()},[]),lt=a.useCallback(()=>{m(!1),W.current?.focus()},[]),Na=a.useCallback(async(t,n,l)=>{const p=l.source!==void 0?Fn(l.source.ir,l.source.layout):{ir:Kn(t),layout:Un()},v=await Qt({name:t,description:n||void 0,kind:"workflow",ir:p.ir,layout:p.layout},r);P(_=>[..._,v]),M(v.id),c(!1),i(o("workflows.created",'Created workflow "{{name}}"',{name:v.name}),"success"),lt()},[r,i,o,lt]),ya=a.useCallback(async(t,n,l)=>{const p=await cs({prompt:t},r,l),v=`AI: ${t.slice(0,30)}`,R=await Qt({name:n||v,kind:"workflow",ir:p.ir,layout:p.layout},r);Lt.current=p.interpreterOnly,P(H=>[...H,R]),M(R.id),c(!1),i(o("workflows.created",'Created workflow "{{name}}"',{name:R.name}),"success"),p.strippedApprovalFlags&&i(o("workflows.importStripped","Auto-approval flags were removed from imported nodes"),"warning"),lt()},[r,i,o,lt]),$o=a.useCallback(async()=>{if(!(!C||Ue(C.id)||!await ke({title:o("workflows.deleteTitle","Delete workflow?"),message:o("workflows.deleteMessage",'Delete workflow "{{name}}"? This cannot be undone.',{name:C.name}),confirmLabel:o("common.delete","Delete"),danger:!0})))try{await Pn(C.id,r),P(n=>n.filter(l=>l.id!==C.id)),M(null),k&&c(!0),i(o("workflows.deleted","Workflow deleted"),"success")}catch(n){i(ne(n)||o("workflows.deleteFailed","Failed to delete workflow"),"error")}},[C,r,i,ke,o,k]),_o=a.useCallback(async()=>{if(C)try{const t=await Qt({name:`${C.name} (copy)`,description:C.description,ir:C.ir,layout:C.layout},r);P(n=>[...n,t]),M(t.id),c(!1),i(o("workflows.duplicatedEditable",'Duplicated to "{{name}}" — editable',{name:t.name}),"success")}catch(t){i(ne(t)||o("workflows.duplicateFailed","Failed to duplicate workflow"),"error")}},[C,r,i,o]),Bo=a.useCallback(async()=>{if(C&&!Ue(C.id)){if(Ie.length>0){const t=o("workflowColumns.unplacedCount","{{count}} nodes not placed in a column",{count:Ie.length});E(t),i(t,"error");return}if(Fo>0){const t=o("workflowColumns.compositionBlocked","Resolve trait conflicts on highlighted columns before saving");E(t),i(t,"error");return}x(!0),E(null),ie(!1),Ro(null);try{const t=X.trim()||C.name,{ir:n,layout:l}=Ks(t,B,q,ee.length?ee:void 0,Ae.length?Ae:void 0,Fe.length?Fe:void 0),p=t!==C.name,v=Y!==(C.description??""),_=async H=>{P(ge=>ge.map(Pe=>Pe.id===H.id?H:Pe)),Je.current=oo(H.name,H.description??"",B,q,ee,Ae,Fe),ae(H.name),ue(H.description??"");try{await Rn(H.id,r),i(o("workflows.saved","Workflow saved"),"success")}catch(ge){const Pe=ne(ge)||"";Pe.includes("require the workflow interpreter (deferred)")?ie(!0):E(Pe||o("workflows.savedNotCompilable","Workflow saved but cannot be compiled"))}},R={ir:n,layout:l,...p?{name:t}:{},...v?{description:Y}:{}};try{await _(await ms(C.id,R,r))}catch(H){if(!(H?.details?.policyEscalation===!0))throw H;if(!window.confirm(`${ne(H)}
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 _(await ms(C.id,{...R,confirmPolicyEscalation:!0},r))}}catch(t){const n=ne(t)||o("workflows.saveFailed","Failed to save workflow"),l=/node '([^']+)'/.exec(n);l&&B.some(p=>p.id===l[1])&&Ro({nodeId:l[1],message:n}),E(n),i(n,"error")}finally{x(!1)}}},[C,X,Y,B,q,ee,Ae,Fe,Ie,Fo,r,i,o]),Ge=a.useMemo(()=>{const t=new Set(Ie),n=new Map;for(const l of B)l.parentId&&n.set(l.parentId,(n.get(l.parentId)??0)+1);return B.map(l=>{let p;t.has(l.id)&&(p=o("workflowColumns.nodeUnplaced","Not placed in a column")),Bt?.nodeId===l.id&&(p=Bt.message);const v=l.data.kind==="foreach"||l.data.kind==="loop"||l.data.kind==="optional-group",_=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"),R=v?(n.get(l.id)??0)===0:void 0;return p===l.data.errorBadge&&(!v||R===l.data.templateEmpty&&l.data.emptyHint===_)?l:{...l,data:{...l.data,errorBadge:p,...v?{templateEmpty:R,emptyHint:_}:{}}}})},[B,Ie,Bt,o]),u=B.find(t=>t.id===O)??null,Go=u!==null&&u.data.kind!=="end",Ce=u!==null?tl(u.data):null,ve=q.find(t=>t.id===V)??null,Ca=k&&Go&&!de,Sa=k&&ve!==null,[qt,qo]=a.useState(!1),Vo=a.useCallback(()=>{qo(t=>!t)},[]),Ea=a.useCallback(t=>{!qt||t.key!=="Escape"||(t.preventDefault(),t.stopPropagation(),qo(!1))},[qt]),qe=u&&(u.data.kind==="prompt"||u.data.kind==="gate")?String(u.data.config?.prompt??Le?.effective[u.id]??(L?Ll(u.data.config):"")):"",Vt=u?Le?.defaults[u.id]:void 0,Ho=u?Le?.stored[u.id]:void 0,Ht=Ho!==void 0,Uo=Ht&&Vt!==void 0&&Ho!==Vt,kt=!!u&&oa===u.id,xt=!!u&&(u.data.kind==="prompt"||u.data.kind==="gate")&&(!L||Vt!==void 0),Ko=a.useCallback(t=>{xt&&$({config:{prompt:t}})},[xt,$]),Yo=a.useCallback(()=>{if(!L||!u||u.data.kind!=="prompt"&&u.data.kind!=="gate")return;const t=Le?.stored[u.id],n=Le?.defaults[u.id],l=qe.trim()?qe:"";t===void 0&&(n===void 0||l===n)||t===l||Lo(u.id,qe)},[L,u,qe,Le,Lo]),Jo=a.useCallback(()=>{u&&zo(u.id)},[u,zo]),Xo=a.useMemo(()=>{if(!ve)return"readonly";const t=B.find(n=>n.id===ve.source);return Mn(t?.data.kind)},[ve,B]),Ut=a.useMemo(()=>{const t=C?.ir;return t&&t.version==="v2"&&Array.isArray(t.artifacts)?t.artifacts.map(n=>n.key):[]},[C]),[Oe,Kt]=a.useState([]),[je,vt]=a.useState([]);a.useEffect(()=>{vt([])},[r]);const[Ve,Qo]=a.useState([]),[Aa,Fa]=a.useState(zl);a.useEffect(()=>{let t=!1;return Promise.resolve(Ct()).then(n=>{!t&&n?.models&&Kt(n.models)}).catch(()=>{}),Promise.resolve(yt()).then(n=>{!t&&Array.isArray(n)&&vt(n)}).catch(()=>{}),Promise.resolve(ws(r)).then(n=>{!t&&Array.isArray(n)&&Qo(n)}).catch(()=>{}),()=>{t=!0}},[r]);const Yt=a.useMemo(()=>({models:Oe.map(t=>({provider:t.provider,id:t.id,name:t.name})),agents:je.map(t=>({id:t.id,name:t.name})),skills:Ve.map(t=>({id:t.id,name:t.name}))}),[Oe,je,Ve]),Zo=a.useMemo(()=>{const t=Ge.filter(l=>!we(l.id)&&l.data.kind!=="start").map(l=>({id:l.id,label:l.data.label||l.id,kind:l.data.kind})),n=new Map;for(const l of Ge){if(we(l.id)||l.data.kind==="start"||l.data.kind==="end")continue;const p=t.filter(v=>v.id!==l.id);p.length>0&&n.set(l.id,p)}return n},[Ge]),Pa=a.useMemo(()=>{const t=n=>n.map(l=>({...l,connectionTargets:L?[]:Zo.get(l.id)??[],children:t(l.children)}));return t(Tl(Ge,q,ee,Yt,o))},[Ge,q,ee,Yt,o,L,Zo]),me=u?.data.config?.executor??"model",De=a.useMemo(()=>{const t=u?.data.column??(u?.parentId?B.find(l=>l.id===u.parentId)?.data.column:void 0);if(!t)return;const n=ee.find(l=>l.id===t);if(!(!n?.agent||n.agent.mode!=="override"))return n.agent},[u?.data.column,u?.parentId,B,ee]),Ra=a.useMemo(()=>De?je.find(t=>t.id===De.agentId):void 0,[De,je]);a.useEffect(()=>{if(me!=="cli-agent")return;let t=!1;return fetch("/api/cli-agents").then(n=>n.ok?n.json():null).then(n=>{t||!n?.adapters||Fa(n.adapters)}).catch(()=>{}),()=>{t=!0}},[me]),a.useEffect(()=>{if(u?.data.kind==="step-review"&&Oe.length===0){Ct().then(t=>Kt(t.models)).catch(t=>{i(ne(t)||o("workflowEditor.modelsLoadFailed","Failed to load models"),"error")});return}!u||u.data.kind!=="prompt"&&u.data.kind!=="gate"||(me==="model"&&Oe.length===0?Ct().then(t=>Kt(t.models)).catch(t=>{i(ne(t)||o("workflowEditor.modelsLoadFailed","Failed to load models"),"error")}):me==="agent"&&je.length===0?yt(void 0,r).then(vt).catch(t=>{i(ne(t)||o("workflowEditor.agentsLoadFailed","Failed to load agents"),"error")}):me==="skill"&&Ve.length===0&&ws(r).then(Qo).catch(t=>{i(ne(t)||o("workflowEditor.skillsLoadFailed","Failed to load skills"),"error")}))},[me,u?.id,u?.data.kind,r,i,Oe.length,je.length,Ve.length,o]);const jt=a.useCallback(t=>{if(!at){t();return}ke({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(n=>{n&&t()})},[at,ke,o]),Jt=a.useCallback(()=>{jt(s)},[jt,s]),Ma=a.useCallback(t=>{if(t===S){c(!1);return}jt(()=>{M(t),c(!1)})},[jt,S]);a.useEffect(()=>{if(!De||je.length>0)return;let t=!1;return Promise.resolve(yt(void 0,r)).then(n=>{t||vt(n??[])}).catch(n=>{t||i(ne(n)||o("workflowEditor.agentsLoadFailed","Failed to load agents"),"error")}),()=>{t=!0}},[De,je.length,r,i,o]);const Ia=Ys(Jt),Oa=qt&&(u?.data.kind==="prompt"||u?.data.kind==="gate")?Da.createPortal(e.jsxs("div",{className:"wf-prompt-editor wf-prompt-editor--fullscreen",onKeyDown:Ea,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(hs,{size:14})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.prompt","Prompt")}),e.jsx("textarea",{rows:void 0,value:qe,readOnly:!xt,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:!Ht||kt,children:kt?o("workflowEditor.promptSaving","Saving…"):o("workflowEditor.resetPromptDefault","Reset to default")})]}):null]}),document.body):null,es=e.jsxs("div",{className:`modal wf-editor-modal${f?" wf-editor-modal--embedded":""}`,ref:I,onClick:t=>t.stopPropagation(),onKeyDown:t=>{if(t.key!=="Escape"||f||it)return;const l=t.target.tagName;l==="INPUT"||l==="TEXTAREA"||l==="SELECT"||(t.stopPropagation(),Jt())},children:[e.jsxs("header",{className:"wf-editor-header",children:[e.jsxs("h2",{children:[e.jsx(gs,{size:20,"aria-hidden":"true"}),e.jsx("span",{children:o("workflows.title","Workflows")})]}),f?null:e.jsx("button",{className:"wf-editor-close",onClick:Jt,"aria-label":o("workflows.closeEditor","Close workflow editor"),children:e.jsx(io,{size:18})})]}),fa?e.jsxs("div",{className:"wf-migration-notice",role:"status","data-testid":"wf-migration-notice",children:[e.jsx("span",{className:"wf-migration-notice-text",children:o("workflows.migrationNotice",'Your legacy workflow steps were converted — find them as templates in the palette and as the "Migrated steps" workflow.')}),e.jsx("button",{type:"button",className:"wf-migration-notice-dismiss","data-testid":"wf-migration-notice-dismiss",onClick:ma,"aria-label":o("common.dismiss","Dismiss"),children:e.jsx(io,{size:14})})]}):null,e.jsxs("div",{className:`wf-editor-body${h?" wf-editor-body--list-stage":" wf-editor-body--editor-stage"}${be?" wf-editor-body--simple-layout":""}${Ca?" wf-editor-body--mobile-node-detail":""}${Sa?" wf-editor-body--mobile-edge-detail":""}${et?" 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:W,"data-testid":"wf-new-workflow",onClick:()=>m(!0),children:[e.jsx(Ee,{size:14})," ",o("workflows.newWorkflow","New workflow")]}),!k&&e.jsx("button",{type:"button",className:"wf-sidebar-shell-toggle","data-testid":"wf-sidebar-collapse","aria-expanded":!et,"aria-label":o("workflows.collapseSidebar","Collapse workflow sidebar"),title:o("workflows.collapseSidebar","Collapse workflow sidebar"),onClick:()=>bo(!0),children:e.jsx(bs,{size:14,"aria-hidden":!0})})]}),e.jsxs("button",{type:"button",className:"wf-editor-import","data-testid":"wf-import",disabled:yo,onClick:()=>ft.current?.click(),title:o("workflows.importTooltip","Import a workflow from a JSON file"),children:[yo?e.jsx(Me,{size:14,className:"wf-spin"}):e.jsx(Yn,{size:14})," ",o("workflows.import","Import")]}),e.jsx("input",{ref:ft,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,n)=>e.jsx("p",{className:"wf-editor-import-warning",children:t},n))}),k&&A.length>0&&!C?e.jsx("div",{className:"wf-editor-select-note","data-testid":"wf-mobile-select-note",children:o("workflows.mobileSelectNote","Select a workflow to edit.")}):null,j?e.jsxs("div",{className:"wf-editor-empty",children:[e.jsx(Me,{size:16,className:"wf-spin"})," ",o("workflows.loading","Loading…")]}):A.length===0?e.jsx("div",{className:"wf-editor-empty",children:o("workflows.noneYet","No workflows yet.")}):e.jsx("ul",{className:"wf-editor-list",children:A.map(t=>e.jsx("li",{children:e.jsx("button",{className:`wf-editor-list-item${t.id===S?" active":""}`,onClick:()=>Ma(t.id),children:t.name})},t.id))}),C&&!be&&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":!tt,"data-testid":"wf-sidebar-columns-toggle",onClick:()=>da(t=>!t),children:[tt?e.jsx(Re,{size:13}):e.jsx(Se,{size:13}),e.jsx("span",{children:o("workflowColumns.title","Columns")})]}),!tt&&e.jsx(Es,{columns:ee,onChange:Xe,violations:$t,readOnly:L,projectId:r,addToast:i,columnAgentsEnabled:Eo})]}),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":!ot,"data-testid":"wf-sidebar-fields-toggle",onClick:()=>ca(t=>!t),children:[ot?e.jsx(Re,{size:13}):e.jsx(Se,{size:13}),e.jsx("span",{children:o("workflowFields.title","Fields")})]}),!ot&&e.jsx(Ps,{fields:Ae,onChange:Qe,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":!st,"data-testid":"wf-sidebar-settings-toggle",onClick:()=>ua(t=>!t),children:[st?e.jsx(Re,{size:13}):e.jsx(Se,{size:13}),e.jsx("span",{children:o("workflowSettings.title","Settings")})]}),!st&&e.jsx("div",{ref:Et,className:"wf-settings-panel-wrap",children:e.jsx(Os,{workflowId:C.id,settings:Fe,onChange:Ze,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(bs,{size:16}),e.jsx("span",{children:o("common.back","Back")})]}),C?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"wf-name-strip",children:[et&&!k&&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:()=>bo(!1),children:e.jsx(Re,{size:14,"aria-hidden":!0})}),L?e.jsx("span",{className:"wf-workflow-name wf-workflow-name--readonly","data-testid":"wf-workflow-name",children:C.name}):oe?e.jsx("input",{className:"wf-workflow-name-input","data-testid":"wf-workflow-name-input",autoFocus:!0,value:X,"aria-label":o("workflows.nameLabel","Workflow name"),onChange:t=>ae(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),X.trim()||ae(C.name),fe(!1)):t.key==="Escape"&&(t.preventDefault(),ae(C.name),fe(!1))},onBlur:()=>{X.trim()||ae(C.name),fe(!1)}}):e.jsx("button",{type:"button",className:"wf-workflow-name","data-testid":"wf-workflow-name",onClick:()=>fe(!0),title:o("workflows.clickToRename","Click to rename"),children:X||C.name}),L?C.description?e.jsx("span",{className:"wf-workflow-description wf-workflow-description--readonly","data-testid":"wf-workflow-description",children:C.description}):null:ta?e.jsx("input",{className:"wf-workflow-description-input","data-testid":"wf-workflow-description-input",autoFocus:!0,value:Y,"aria-label":o("workflows.descriptionLabel","Workflow description"),placeholder:o("workflows.descriptionPlaceholder","Add a description"),onChange:t=>ue(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),Ye(!1)):t.key==="Escape"&&(t.preventDefault(),ue(C.description??""),Ye(!1))},onBlur:()=>Ye(!1)}):e.jsx("button",{type:"button",className:"wf-workflow-description","data-testid":"wf-workflow-description",onClick:()=>Ye(!0),title:o("workflows.clickToEditDescription","Click to edit description"),children:Y||o("workflows.descriptionPlaceholder","Add a description")}),!k&&e.jsxs("button",{type:"button",className:"wf-layout-toggle","data-testid":"wf-layout-toggle","aria-pressed":F,onClick:()=>K(t=>!t),children:[F?e.jsx(Zt,{size:14}):e.jsx(Js,{size:14}),e.jsx("span",{children:F?o("workflows.showCanvasEditor","Show canvas editor"):o("workflows.showSimpleEditor","Show simple editor")})]})]}),be&&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,n])=>e.jsx("button",{type:"button",className:`wf-mobile-tab${se===t?" wf-mobile-tab--active":""}`,"aria-current":se===t?"page":void 0,"data-testid":`wf-mobile-tab-${t}`,onClick:()=>ce(t),children:n},t))}),e.jsxs("div",{className:"wf-mobile-panel","data-testid":`wf-mobile-panel-${se}`,children:[se==="graph"&&e.jsx(Rl,{rows:Pa,selectedNodeId:O,selectedEdgeId:V,onSelectNode:t=>{T(t),te(null),re(!1)},onSelectEdge:t=>{te(t),T(null)},onCreateConnection:L?void 0:ga,canReorder:!L,onMoveNode:ba}),se==="add"&&e.jsx("div",{className:"wf-mobile-add",children:L?e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflows.readOnlyBuiltin","Built-in 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:Bs.map(({kind:t,label:n,icon:l,presetConfig:p})=>e.jsxs("button",{type:"button",className:"wf-mobile-add-option","data-testid":`wf-mobile-add-${t}-${n.toLowerCase().replace(/[^a-z0-9]+/g,"-")}`,onClick:()=>{gt(t,n,p),ce("graph")},children:[e.jsx(l,{size:16,"aria-hidden":!0}),e.jsx("span",{children:n})]},n))})]}),Ao&&e.jsxs("section",{className:"wf-mobile-add-section",children:[e.jsx("h3",{children:o("workflowNodes.templatesSection","Templates")}),Wt>8&&e.jsx("input",{type:"text",className:"wf-templates-filter wf-mobile-template-filter","data-testid":"wf-mobile-template-filter",value:dt,onChange:t=>fo(t.target.value),placeholder:o("workflowNodes.templateFilterPlaceholder","Filter templates"),"aria-label":o("workflowNodes.templateFilterLabel","Filter templates")}),ct&&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:ct})}),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)&&ce("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","Built-in 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:()=>{bt(t),ce("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),ce("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:n})=>e.jsxs("button",{type:"button",className:"wf-mobile-template-option","data-testid":`wf-mobile-tpl-plugin-${n.id}`,onClick:()=>{bt(n),ce("graph")},children:[e.jsx("span",{children:n.name}),e.jsx("span",{className:"wf-templates-badge",children:t})]},`${t}:${n.id}`))]})]})]})}),se==="settings"&&C&&e.jsx("div",{ref:Et,className:"wf-mobile-destination",children:e.jsx(Os,{workflowId:C.id,settings:Fe,onChange:Ze,readOnly:L,projectId:r,addToast:i,initialTab:"values"})}),se==="fields"&&e.jsx("div",{className:"wf-mobile-destination",children:e.jsx(Ps,{fields:Ae,onChange:Qe,readOnly:L,addToast:i})}),se==="columns"&&e.jsx("div",{className:"wf-mobile-destination",children:e.jsx(Es,{columns:ee,onChange:Xe,violations:$t,readOnly:L,projectId:r,addToast:i,columnAgentsEnabled:Eo})}),se==="actions"&&e.jsx("div",{className:"wf-mobile-actions",children:L?e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflows.readOnlyBuiltin","Built-in workflow: structure is read-only, prompts are editable.")}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-export",onClick:wt,children:[e.jsx(Nt,{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(Ee,{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:D,children:[D?e.jsx(Me,{size:15,className:"wf-spin"}):e.jsx(no,{size:15}),o("common.save","Save")]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-ai-edit",onClick:()=>Ot(t=>!t),children:[e.jsx(He,{size:15})," ",o("workflows.aiEdit","Design with AI")]}),It&&e.jsxs("div",{className:"wf-ai-panel wf-mobile-ai-panel","data-testid":"wf-mobile-ai-panel",role:"dialog","aria-busy":xe,children:[e.jsx("textarea",{className:"wf-ai-prompt","data-testid":"wf-mobile-ai-edit-prompt",rows:4,value:pt,disabled:xe,placeholder:o("workflows.aiPromptPlaceholder","e.g. Run lint and tests before merge, then post a changelog comment after merge"),onChange:t=>{Dt(t.target.value),$e&&_e(null)}}),$e&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-mobile-ai-edit-error",children:$e}),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:xe,onClick:()=>void Do(),children:[xe?e.jsx(Me,{size:13,className:"wf-spin"}):e.jsx(He,{size:13}),o("workflows.aiSubmit","Design with AI")]}),xe&&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(Zt,{size:15})," ",o("workflowNodes.autoLayout","Auto-layout")]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-export",onClick:wt,disabled:at,children:[e.jsx(Nt,{size:15})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-delete","data-testid":"wf-mobile-delete",onClick:$o,children:[e.jsx(Ne,{size:15})," ",o("common.delete","Delete")]})]})})]})]}),L?e.jsxs("div",{className:"wf-editor-readonly-banner",role:"status","data-testid":"wf-readonly-banner",children:[e.jsx("span",{className:"wf-editor-readonly-note",children:o("workflows.readOnlyBuiltin","Built-in workflow: structure is read-only, prompts are editable.")}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-export",onClick:wt,title:o("workflows.exportTooltip","Download as JSON — contains your full prompt and command text"),children:[e.jsx(Nt,{size:13})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-save wf-editor-duplicate-primary",onClick:_o,children:[e.jsx(Ee,{size:13})," ",o("workflows.duplicateToCustomize","Duplicate to customize")]})]}):e.jsxs("div",{className:"wf-editor-toolbar",children:[e.jsx("div",{className:"wf-editor-palette",children:Bs.map(({kind:t,label:n,icon:l,presetConfig:p})=>e.jsxs("button",{className:"wf-palette-btn",onClick:()=>gt(t,n,p),children:[e.jsx(l,{size:13})," ",n]},n))}),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":It,onClick:()=>{Ot(t=>!t),_e(null)},children:[e.jsx(He,{size:13})," ",o("workflows.aiEdit","Design with AI")]}),It&&e.jsxs("div",{className:"wf-ai-panel","data-testid":"wf-ai-panel",role:"dialog","aria-busy":xe,"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:pt,disabled:xe,placeholder:o("workflows.aiPromptPlaceholder","e.g. Run lint and tests before merge, then post a changelog comment after merge"),onChange:t=>{Dt(t.target.value),$e&&_e(null)}}),$e&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-ai-edit-error",children:$e}),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:xe,onClick:()=>void Do(),children:[xe?e.jsx(Me,{size:13,className:"wf-spin"}):e.jsx(He,{size:13})," ",o("workflows.aiSubmit","Design with AI")]}),xe&&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(Zt,{size:13})," ",o("workflowNodes.autoLayout","Auto-layout")]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-export",onClick:wt,disabled:at,title:at?o("workflows.exportDirtyTooltip","Save before exporting"):o("workflows.exportTooltip","Download as JSON — contains your full prompt and command text"),children:[e.jsx(Nt,{size:13})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-delete",onClick:$o,children:[e.jsx(Ne,{size:13})," ",o("common.delete","Delete")]}),e.jsxs("button",{className:"wf-editor-save",onClick:Bo,disabled:D,children:[D?e.jsx(Me,{size:13,className:"wf-spin"}):e.jsx(no,{size:13})," ",o("common.save","Save")]})]})]}),Ao&&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":!We,"data-testid":"wf-templates-toggle",onClick:()=>ra(t=>!t),children:[We?e.jsx(Re,{size:13}):e.jsx(Se,{size:13}),e.jsx(Xn,{size:13})," ",o("workflowNodes.templatesSection","Templates")]}),!We&&Wt>8&&e.jsx("input",{type:"text",className:"wf-templates-filter","data-testid":"wf-template-filter",value:dt,onChange:t=>fo(t.target.value),placeholder:o("workflowNodes.templateFilterPlaceholder","Filter templates"),"aria-label":o("workflowNodes.templateFilterLabel","Filter templates")})]}),!We&&e.jsxs("div",{className:"wf-templates-body",children:[ct&&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:ct})}),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","Built-in 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:()=>bt(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:n})=>e.jsxs("button",{type:"button",className:"wf-templates-entry","data-testid":`wf-tpl-plugin-${n.id}`,disabled:L,"aria-label":o("workflowNodes.insertTemplate","Insert template {{name}}",{name:n.name}),onClick:()=>bt(n),children:[n.name,e.jsx("span",{className:"wf-templates-badge",children:t})]},`${t}:${n.id}`))})]})]})]}),z&&e.jsx("div",{className:"wf-editor-banner",role:"alert",children:z}),Q&&e.jsx("div",{className:"wf-editor-banner wf-editor-banner--info",role:"status","data-testid":"wf-interpreter-only-banner",children:o("workflowNodes.interpreterOnly","This workflow branches, so it runs on the graph interpreter — it can't compile to the linear step engine, but it will still run.")}),Ie.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:Ie.length})}),e.jsxs("div",{className:"wf-editor-canvas",ref:Rt,tabIndex:-1,children:[k&&de&&u&&u.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:()=>re(!1),children:[e.jsx(Re,{size:13}),e.jsx("span",{children:o("workflowNodes.showInspector","Show node details")})]}),pa&&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(qn.Provider,{value:Yt,children:e.jsxs($a,{nodes:Ge,edges:q,nodeTypes:Hn,onNodesChange:le,onEdgesChange:y,onConnect:ha,onNodeDragStop:ka,deleteKeyCode:L?null:["Backspace","Delete"],onBeforeDelete:xa,onNodesDelete:va,onEdgesDelete:ja,onNodeClick:(t,n)=>{T(n.id),te(null),re(!1)},onEdgeClick:(t,n)=>{te(n.id),T(null)},onPaneClick:()=>{T(null),te(null)},defaultEdgeOptions:{interactionWidth:Vn},defaultViewport:{x:0,y:0,zoom:1},children:[e.jsx(_a,{}),e.jsx(Ba,{}),e.jsxs("button",{type:"button",className:`wf-minimap-toggle nodrag nopan${U?" wf-minimap-toggle--collapsed":""}`,"aria-expanded":!U,"aria-controls":"wf-workflow-minimap","data-testid":"wf-minimap-toggle",onClick:()=>he(t=>!t),children:[U?e.jsx(xs,{size:13,"aria-hidden":!0}):e.jsx(hs,{size:13,"aria-hidden":!0}),e.jsx("span",{children:U?o("workflowNodes.showMiniMap","Show mini map"):o("workflowNodes.hideMiniMap","Hide mini map")})]}),!U&&e.jsx(Ga,{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(gs,{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:()=>m(!0),children:[e.jsx(Ee,{size:14})," ",o("workflows.newWorkflow","New workflow")]})]})]}),Go&&!(k&&de)&&!(F&&!k)&&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:Ce?.title??o("workflowNodes.nodeInspector","Node")}),k&&e.jsxs("button",{type:"button",className:"wf-inspector-toggle wf-inspector-toggle--expanded","data-testid":"wf-inspector-toggle","aria-expanded":"true",onClick:()=>{be?T(null):re(!0)},children:[e.jsx(Se,{size:13}),e.jsx("span",{children:o("workflowNodes.collapseInspector","Collapse")})]})]}),Ce&&e.jsxs("details",{className:"wf-inspector-help","data-testid":"wf-node-help",children:[e.jsxs("summary",{className:"wf-inspector-help-summary",children:[e.jsx(Xs,{size:13,"aria-hidden":!0}),e.jsx("span",{children:o("workflowNodes.helpTitle","What does this node do?")}),Ce.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:Ce.summary}),e.jsxs("dl",{className:"wf-inspector-help-dl",children:[Ce.configure&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:o("workflowNodes.helpConfigure","Configure")}),e.jsx("dd",{children:Ce.configure})]}),e.jsx("dt",{children:o("workflowNodes.helpInputs","Inputs")}),e.jsx("dd",{children:Ce.inputs}),e.jsx("dt",{children:o("workflowNodes.helpOutputs","Outputs")}),e.jsx("dd",{children:Ce.outputs}),e.jsx("dt",{children:o("workflowNodes.helpEdges","Edges")}),e.jsx("dd",{children:Ce.edges})]})]})]}),L&&e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.readOnlyDuplicateToEdit","Built-in structure is read-only — prompts on prompt and gate nodes can be edited here.")}),e.jsxs("fieldset",{className:"wf-inspector-fields",disabled:L,children:[u.data.kind!=="start"&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("common:labels.name","Name")}),e.jsx("input",{value:u.data.label,onChange:t=>$({label:t.target.value})})]}),u.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.")}),ee.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(u.data.column??""),onChange:t=>$({column:t.target.value||void 0}),children:[e.jsx("option",{value:"",children:o("workflowNodes.startEntryColumnAuto","— Auto (first column)")}),ee.map(t=>e.jsx("option",{value:t.id,children:t.name},t.id))]})]})]})]}),u.data.kind==="prompt"||u.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:qe,readOnly:!xt,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:!Ht||kt,children:kt?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(xs,{size:14})})]}):null,e.jsxs("fieldset",{className:"wf-inspector-fields",disabled:L,children:[u.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=>$({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")})]})]}),De&&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:Ra?.name??o("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:De.agentId})})}),me==="model"&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.model","Model")}),e.jsx(lo,{label:o("workflowEditor.model","Model"),models:Oe,value:Ls(String(u.data.config?.modelProvider??""),String(u.data.config?.modelId??"")),onChange:t=>{const{provider:n,modelId:l}=zs(t);$({config:{modelProvider:n||void 0,modelId:l||void 0}})}})]}),me==="agent"&&(()=>{const t=String(u.data.config?.agentId??""),n=t!==""&&!je.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=>$({config:{agentId:l.target.value||void 0}}),children:[e.jsx("option",{value:"",children:o("workflowEditor.selectAgent","— select agent —")}),n&&e.jsx("option",{value:t,children:o("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:t})}),je.map(l=>e.jsx("option",{value:l.id,children:l.name},l.id))]}),n&&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(u.data.config?.skillName??""),n=t?Ve.find(p=>vs(p.name)===vs(t)):void 0,l=n?n.name:t;return e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.skill","Skill")}),e.jsxs("select",{value:l,onChange:p=>$({config:{skillName:p.target.value||void 0}}),children:[e.jsx("option",{value:"",children:o("workflowEditor.selectSkill","— select skill —")}),Ve.map(p=>e.jsx("option",{value:p.name,children:p.name},p.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(u.data.config?.cliMode??"command"),onChange:t=>$({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")})]})]}),(u.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(u.data.config?.cliCommand??""),onChange:t=>$({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:u.data.config?.cliSkipApproval===!0,onChange:t=>$({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(u.data.config?.scriptName??""),onChange:t=>$({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(u.data.config?.cliAdapterId??""),onChange:t=>$({config:{cliAdapterId:t.target.value||void 0}}),children:[e.jsx("option",{value:"",children:o("workflowEditor.cliAgent.adapterPlaceholder")}),Aa.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:!!u.data.config?.cliAutonomy?.autoApprove,onChange:t=>$({config:{cliAutonomy:{...u.data.config?.cliAutonomy??{},autoApprove:t.target.checked}}})}),e.jsx("span",{children:o("workflowEditor.cliAgent.autonomyLabel")})]}),!!u.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(u.data.config?.cliNotify?.mode??"banner"),onChange:t=>$({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:!!u.data.config?.autoApprove,onChange:t=>$({config:{autoApprove:t.target.checked}})}),e.jsx("span",{children:o("workflowEditor.autoApproveRequests","Auto-approve requests")})]}),!!u.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:u.data.config?.maxRetries!=null?String(u.data.config.maxRetries):"",onChange:t=>{const n=t.target.value.trim();if(n==="")$({config:l=>{const p={...l};return delete p.maxRetries,p}});else{const l=parseInt(n,10);isNaN(l)||$({config:{maxRetries:l}})}}})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:!!u.data.config?.awaitInput,onChange:t=>$({config:{awaitInput:t.target.checked}})}),e.jsx("span",{children:o("workflowEditor.waitForUserInput","Wait for user input")})]}),!!u.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,u.data.kind==="script"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.scriptName","Script name")}),e.jsx("input",{value:String(u.data.config?.scriptName??""),onChange:t=>$({config:{scriptName:t.target.value}})})]}):null,u.data.kind==="hold"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.releaseCondition","Release condition")}),e.jsxs("select",{value:String(u.data.config?.release??"manual"),onChange:t=>$({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,u.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=u.data.config?.mode;return t&&typeof t=="object"&&"quorum"in t?"quorum":typeof t=="string"?t:"all"})(),onChange:t=>{const n=t.target.value;$(n==="quorum"?{config:{mode:{quorum:2}}}:{config:{mode:n}})},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=u.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(u.data.config?.mode?.quorum??2),onChange:t=>{const n=parseInt(t.target.value,10);isNaN(n)||$({config:{mode:{quorum:n}}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.failurePolicy","On branch failure")}),e.jsxs("select",{value:String(u.data.config?.onBranchFailure??"collect"),onChange:t=>$({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,u.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,u.data.kind==="foreach"?(()=>{const t=String(u.data.config?.mode??"sequential"),n=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 p=l.target.value;$({config:v=>({...v,mode:p,...p==="parallel"&&v.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(u.data.config?.isolation??(n?"worktree":"shared")),onChange:l=>$({config:{isolation:l.target.value}}),children:[e.jsx("option",{value:"shared",disabled:n,children:o("workflowNodes.foreachShared","Shared worktree")}),e.jsx("option",{value:"worktree",children:o("workflowNodes.foreachWorktree","Per-step worktree")})]})]}),n&&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:u.data.config?.concurrency!=null?String(u.data.config.concurrency):"",onChange:l=>{const p=l.target.value.trim();if(p==="")$({config:v=>{const _={...v};return delete _.concurrency,_}});else{const v=parseInt(p,10);isNaN(v)||$({config:{concurrency:v}})}}})]}),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:u.data.config?.maxReworkCycles!=null?String(u.data.config.maxReworkCycles):"",onChange:l=>{const p=l.target.value.trim();if(p==="")$({config:v=>{const _={...v};return delete _.maxReworkCycles,_}});else{const v=parseInt(p,10);isNaN(v)||$({config:{maxReworkCycles:v}})}}})]}),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,u.data.kind==="loop"?(()=>{const t=u.data.config?.exitWhen&&typeof u.data.config.exitWhen=="object"?u.data.config.exitWhen:{type:"output-contains",value:"DONE"},n=String(t.type??"output-contains"),l=String(n==="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:n,onChange:p=>{const v=p.target.value;$({config:_=>{const R=_.exitWhen&&typeof _.exitWhen=="object"?_.exitWhen:{},H=String(v==="output-matches"?R.pattern??R.value??"":R.value??R.pattern??""),ge={...R,type:v};return delete ge.pattern,delete ge.value,{..._,exitWhen:v==="output-matches"?{...ge,pattern:H}:{...ge,value:H}}}})},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:n==="output-matches"?o("workflowNodes.loopPattern","Pattern"):o("workflowNodes.loopValue","Value")}),e.jsx("input",{value:l,placeholder:n==="output-matches"?"DONE|COMPLETE":"DONE",onChange:p=>{const v=p.target.value;$({config:_=>{const R=_.exitWhen&&typeof _.exitWhen=="object"?_.exitWhen:{};return{..._,exitWhen:n==="output-matches"?{...R,type:n,pattern:v}:{...R,type:n,value:v}}}})}})]}),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:p=>{const v=p.target.value.trim();$({config:_=>{const H={..._.exitWhen&&typeof _.exitWhen=="object"?_.exitWhen:{type:"output-contains",value:"DONE"}};return v?H.nodeId=v:delete H.nodeId,{..._,exitWhen:H}}})}})]}),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:u.data.config?.maxIterations!=null?String(u.data.config.maxIterations):"",onChange:p=>{const v=p.target.value.trim();$({config:_=>{const R={..._};if(v==="")delete R.maxIterations;else{const H=parseInt(v,10);isNaN(H)||(R.maxIterations=H)}return R}})}})]}),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:u.data.config?.timeoutMs!=null?String(u.data.config.timeoutMs):"",onChange:p=>{const v=p.target.value.trim();$({config:_=>{const R={..._};if(v==="")delete R.timeoutMs;else{const H=parseInt(v,10);isNaN(H)||(R.timeoutMs=H)}return R}})}})]}),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,u.data.kind==="optional-group"?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:!!u.data.config?.defaultOn,onChange:t=>$({config:{defaultOn:t.target.checked}})}),e.jsx("span",{children:o("workflowNodes.optionalGroupDefaultOn","Enabled by default for new tasks")})]}),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,u.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(u.data.config?.type??"code"),onChange:t=>$({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(lo,{label:o("workflowNodes.reviewModel","Review model (optional)"),models:Oe,value:Ls(String(u.data.config?.modelProvider??""),String(u.data.config?.modelId??"")),onChange:t=>{const{provider:n,modelId:l}=zs(t);$({config:{modelProvider:n||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,u.data.kind==="parse-steps"?e.jsxs(e.Fragment,{children:[Ut.length>0?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.parseArtifact","Artifact")}),e.jsx("select",{value:String(u.data.config?.artifact??Ut[0]),onChange:t=>$({config:{artifact:t.target.value}}),children:Ut.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(u.data.config?.artifact??"PROMPT.md"),onChange:t=>$({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(u.data.config?.parser??"step-headings"),onChange:t=>$({config:{parser:t.target.value}}),children:Array.from(new Set([String(u.data.config?.parser??"step-headings"),...aa])).map(t=>e.jsx("option",{value:t,children:t},t))})]})]}):null,u.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(u.data.config?.source??""),onChange:t=>$({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:u.data.config?.timeoutMs!=null?String(u.data.config.timeoutMs):"",onChange:t=>{const n=t.target.value.trim();if(n==="")$({config:l=>{const p={...l};return delete p.timeoutMs,p}});else{const l=parseInt(n,10);isNaN(l)||$({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,u.data.kind==="notify"?(()=>{const t=String(u.data.config?.event??"workflow-notify"),n=!_s.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:n?so:t,onChange:l=>{const p=l.target.value;$({config:{event:p===so?"custom-event":p}})},children:[_s.map(l=>e.jsx("option",{value:l,children:l},l)),e.jsx("option",{value:so,children:o("workflowNodes.notifyCustom","Custom")})]})]}),n?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=>$({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(u.data.config?.title??"{{taskTitle}}"),placeholder:"{{taskTitle}}",onChange:l=>$({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(u.data.config?.message??""),placeholder:Vl,onChange:l=>$({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,u.data.kind==="prompt"||u.data.kind==="gate"||u.data.kind==="script"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.gateMode","Gate mode")}),e.jsxs("select",{value:String(u.data.config?.gateMode??(u.data.kind==="prompt"?"advisory":"gate")),onChange:t=>$({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)")})]})]}):u.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([u.id]),T(null)},children:[e.jsx(Ne,{size:13})," ",o("workflowNodes.deleteNode","Delete node")]})]}),ve&&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")}),k&&e.jsxs("button",{type:"button",className:"wf-inspector-toggle wf-inspector-toggle--expanded","data-testid":"wf-edge-inspector-close","aria-expanded":"true",onClick:()=>te(null),children:[e.jsx(Se,{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(ve.data?.condition??"success");return t.startsWith("outcome:")?t.slice(8):""})(),onChange:t=>{const n=t.target.value;Gt({condition:n?`outcome:${n}`:"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:ve.data?.kind==="rework",onChange:t=>Gt({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(ve.data?.condition??"success"),onChange:t=>Gt({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(ve.data?.condition??"success")})})}),!L&&e.jsxs("button",{type:"button",className:"wf-editor-delete wf-inspector-delete","data-testid":"wf-delete-edge",onClick:()=>{Wo([ve.id]),te(null)},children:[e.jsx(Ne,{size:13})," ",o("workflowNodes.deleteEdge","Delete edge")]})]})]}),it&&e.jsx(Ul,{workflows:A,onCreate:Na,onDesign:ya,onClose:lt})]});return e.jsxs(e.Fragment,{children:[f?e.jsx("div",{className:"workflow-editor-embedded right-dock-embedded-view",children:es}):e.jsx("div",{className:"modal-overlay open wf-editor-overlay",...Ia,children:es}),Oa]})}function oi({isOpen:s,onClose:i,addToast:r,projectId:w,initialPanel:d,initialAction:g,initialWorkflowId:I,presentation:f="modal"}){const A=a.useRef(null),{isEmbedded:P,resizePersistEnabled:S}=nn(f);return an(A,s&&S,"fusion:workflow-node-editor-size"),s?e.jsx(Ta,{children:e.jsx(Kl,{onClose:i,addToast:r,projectId:w,initialPanel:d,initialAction:g,initialWorkflowId:I,modalRef:A,isEmbedded:P})}):null}export{oi as WorkflowNodeEditor};