@runfusion/fusion 0.55.0 → 0.56.1

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 (127) hide show
  1. package/dist/bin.js +5829 -1357
  2. package/dist/client/.vite/manifest.json +322 -322
  3. package/dist/client/assets/{AgentDetailView-B_VfFSlt.js → AgentDetailView-BICsleMh.js} +1 -1
  4. package/dist/client/assets/{AgentPermissionPolicyEditor-QZhz41AU.js → AgentPermissionPolicyEditor-DQDzCWq_.js} +2 -2
  5. package/dist/client/assets/{AgentsView-hkhJ8SUq.js → AgentsView-DRpFG7gE.js} +6 -6
  6. package/dist/client/assets/ChatView-5vVkIiNh.js +6 -0
  7. package/dist/client/assets/{CommandCenter-B3fAajUO.js → CommandCenter-CZ856YOj.js} +1 -1
  8. package/dist/client/assets/{DevServerView-BR0ngFBw.js → DevServerView-BqsnMChS.js} +1 -1
  9. package/dist/client/assets/DirectoryPicker-cW1rnVoG.js +1 -0
  10. package/dist/client/assets/{DocumentsView-BnRvIUpa.js → DocumentsView-C6a5tuBQ.js} +1 -1
  11. package/dist/client/assets/{EvalsView-Bvx18QyC.js → EvalsView-DZd_TM3I.js} +1 -1
  12. package/dist/client/assets/{ExperimentalAgentOnboardingModal-CKGJcfXI.js → ExperimentalAgentOnboardingModal-cA-aWWsB.js} +1 -1
  13. package/dist/client/assets/{GoalsView-Bj1yVIiv.js → GoalsView-Bzvw1aDV.js} +1 -1
  14. package/dist/client/assets/{InsightsView-DBX8DI60.js → InsightsView-B3WQIXKs.js} +2 -2
  15. package/dist/client/assets/{MemoryView-CqkRH2fa.js → MemoryView-BZ2KwFO5.js} +1 -1
  16. package/dist/client/assets/{PiExtensionsManager-BMMmGWe2.js → PiExtensionsManager-D5x6GZOP.js} +2 -2
  17. package/dist/client/assets/{PluginManager-C1bdfN2W.js → PluginManager-YfHRH24B.js} +1 -1
  18. package/dist/client/assets/{PullRequestView-D0CsXWLl.js → PullRequestView-DX3J4hgm.js} +1 -1
  19. package/dist/client/assets/{ResearchView-CVgmXAlj.js → ResearchView-MZV2S2kT.js} +1 -1
  20. package/dist/client/assets/{SecretsView-Bv_gw5Ix.js → SecretsView--R3u3G4b.js} +1 -1
  21. package/dist/client/assets/SessionTerminal-BQWc1_Ty.js +2 -0
  22. package/dist/client/assets/SettingsModal-CNYosRF3.js +21 -0
  23. package/dist/client/assets/{SettingsModal-D7YgojbV.js → SettingsModal-Coqvlmud.js} +1 -1
  24. package/dist/client/assets/SettingsModal-D8AyVDar.css +1 -0
  25. package/dist/client/assets/SetupWizardModal-CoReXugb.js +2 -0
  26. package/dist/client/assets/{ShadcnColorPicker-DM2fqGwl.js → ShadcnColorPicker-D-u_ECbM.js} +1 -1
  27. package/dist/client/assets/{SkillsView-Bb-JTo99.js → SkillsView-D21ils_G.js} +1 -1
  28. package/dist/client/assets/TodoView-BFZQSkv4.js +6 -0
  29. package/dist/client/assets/WorkflowNodeEditor-E-7d5R9z.js +8 -0
  30. package/dist/client/assets/{agentSkills-DGFyuKuP.js → agentSkills-CM_yYVTx.js} +1 -1
  31. package/dist/client/assets/app-0jcSCRQr.js +13 -0
  32. package/dist/client/assets/app-BPzPEE6G.js +13 -0
  33. package/dist/client/assets/app-BSZU5Uns.js +13 -0
  34. package/dist/client/assets/app-CEtD1B9K.js +13 -0
  35. package/dist/client/assets/app-CVyRSEUX.js +13 -0
  36. package/dist/client/assets/app-DoLz_4Dg.js +13 -0
  37. package/dist/client/assets/{architectureDiagram-3BPJPVTR-DP7vOyXY.js → architectureDiagram-3BPJPVTR-DhgVYwmg.js} +1 -1
  38. package/dist/client/assets/{blockDiagram-GPEHLZMM-Di9v1pV8.js → blockDiagram-GPEHLZMM-AlG0kVWu.js} +1 -1
  39. package/dist/client/assets/{c4Diagram-AAUBKEIU-Dvb8RSfr.js → c4Diagram-AAUBKEIU-BOzpW3F7.js} +1 -1
  40. package/dist/client/assets/channel-DHSVrpL1.js +1 -0
  41. package/dist/client/assets/{chunk-2J33WTMH-gLcAuGjI.js → chunk-2J33WTMH-BAmZfsv0.js} +1 -1
  42. package/dist/client/assets/{chunk-4BX2VUAB-B-B0wjkx.js → chunk-4BX2VUAB-Cs587QhG.js} +1 -1
  43. package/dist/client/assets/{chunk-55IACEB6-XUDeC0Co.js → chunk-55IACEB6-qpIQSO06.js} +1 -1
  44. package/dist/client/assets/{chunk-727SXJPM-1eebiGA2.js → chunk-727SXJPM-DF3vZtMc.js} +1 -1
  45. package/dist/client/assets/{chunk-AQP2D5EJ-D9VOB5QS.js → chunk-AQP2D5EJ-BuETIys5.js} +1 -1
  46. package/dist/client/assets/{chunk-FMBD7UC4-EFNFEaAz.js → chunk-FMBD7UC4-B8D1TSR9.js} +1 -1
  47. package/dist/client/assets/{chunk-ND2GUHAM-CbeQailD.js → chunk-ND2GUHAM-BJv9aIQn.js} +1 -1
  48. package/dist/client/assets/{chunk-QZHKN3VN-D55N6EBz.js → chunk-QZHKN3VN-BJbK2pNR.js} +1 -1
  49. package/dist/client/assets/classDiagram-4FO5ZUOK-CTu3cN1i.js +1 -0
  50. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CTu3cN1i.js +1 -0
  51. package/dist/client/assets/{cose-bilkent-S5V4N54A-B0zbhkX3.js → cose-bilkent-S5V4N54A-BWRikddb.js} +1 -1
  52. package/dist/client/assets/{dagre-BM42HDAG-BL6peXwl.js → dagre-BM42HDAG-DpAxJj7T.js} +1 -1
  53. package/dist/client/assets/{dashboard-view-Db3n_W85.js → dashboard-view-Dw8L8k-2.js} +1 -1
  54. package/dist/client/assets/{dashboard-view-CS1H5SQN.js → dashboard-view-qq3ayA0B.js} +1 -1
  55. package/dist/client/assets/{diagram-2AECGRRQ-cYKwSHk7.js → diagram-2AECGRRQ-DRRIILsg.js} +1 -1
  56. package/dist/client/assets/{diagram-5GNKFQAL-DHIwTGuM.js → diagram-5GNKFQAL-DSOu28ss.js} +1 -1
  57. package/dist/client/assets/{diagram-KO2AKTUF-DfHBJ4aX.js → diagram-KO2AKTUF-CWzbnTBM.js} +1 -1
  58. package/dist/client/assets/{diagram-LMA3HP47-pWhYmB6Z.js → diagram-LMA3HP47-CGqf3bt6.js} +1 -1
  59. package/dist/client/assets/{diagram-OG6HWLK6-GzWqbi_m.js → diagram-OG6HWLK6-C1axXteT.js} +1 -1
  60. package/dist/client/assets/{erDiagram-TEJ5UH35-CCVm5eiR.js → erDiagram-TEJ5UH35-bBdlc4OY.js} +1 -1
  61. package/dist/client/assets/{flowDiagram-I6XJVG4X-CUTdnU6S.js → flowDiagram-I6XJVG4X-BTCJ2J3b.js} +1 -1
  62. package/dist/client/assets/{folder-open-DOCy9GVC.js → folder-open-BN3_NdbL.js} +1 -1
  63. package/dist/client/assets/{ganttDiagram-6RSMTGT7-CW4ENJaC.js → ganttDiagram-6RSMTGT7-CiFY9oBj.js} +1 -1
  64. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-QXXMfSzp.js → gitGraphDiagram-PVQCEYII-CxubcP4l.js} +1 -1
  65. package/dist/client/assets/index-CbmH1ED8.css +1 -0
  66. package/dist/client/assets/index-rfsTNfpA.js +2511 -0
  67. package/dist/client/assets/{infoDiagram-5YYISTIA-CZyHbj0n.js → infoDiagram-5YYISTIA-ToDlIyOV.js} +1 -1
  68. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-Dea84lqZ.js → ishikawaDiagram-YF4QCWOH-BgO681xo.js} +1 -1
  69. package/dist/client/assets/{journeyDiagram-JHISSGLW-Db2iKGU5.js → journeyDiagram-JHISSGLW-OJZ3op9w.js} +1 -1
  70. package/dist/client/assets/{kanban-definition-UN3LZRKU-CB9loIqR.js → kanban-definition-UN3LZRKU-q2OOqX8K.js} +1 -1
  71. package/dist/client/assets/{mermaid.core-CoQ8aCb0.js → mermaid.core-BmDOYmFS.js} +4 -4
  72. package/dist/client/assets/{mindmap-definition-RKZ34NQL-JPb2wF-K.js → mindmap-definition-RKZ34NQL-Dw8JehwG.js} +1 -1
  73. package/dist/client/assets/{pieDiagram-4H26LBE5-pdZzOreP.js → pieDiagram-4H26LBE5-D5Li6GnX.js} +1 -1
  74. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Dh9Ids90.js → quadrantDiagram-W4KKPZXB-B4s-2jdZ.js} +1 -1
  75. package/dist/client/assets/{requirementDiagram-4Y6WPE33-BVPOSvHU.js → requirementDiagram-4Y6WPE33-Drc3rc_E.js} +1 -1
  76. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BqSMUpsx.js → sankeyDiagram-5OEKKPKP-C_R01GQC.js} +1 -1
  77. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-B8nepQ6X.js → sequenceDiagram-3UESZ5HK-gyl7Yhgc.js} +1 -1
  78. package/dist/client/assets/{shield-alert-CtSaIQNY.js → shield-alert-DjhYmFaV.js} +1 -1
  79. package/dist/client/assets/{stateDiagram-AJRCARHV-CQv9RdRp.js → stateDiagram-AJRCARHV-BY53czZh.js} +1 -1
  80. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-C53cIaWg.js +1 -0
  81. package/dist/client/assets/{timeline-definition-PNZ67QCA-CAjwM-Z5.js → timeline-definition-PNZ67QCA-BYwv2FZJ.js} +1 -1
  82. package/dist/client/assets/{upload-0_pT1euA.js → upload-BKpOp-Bn.js} +1 -1
  83. package/dist/client/assets/{users--1B6mnm8.js → users-BUMHTZuX.js} +1 -1
  84. package/dist/client/assets/{vennDiagram-CIIHVFJN-BO3Um3rH.js → vennDiagram-CIIHVFJN-Dt94bP0k.js} +1 -1
  85. package/dist/client/assets/{wardley-L42UT6IY-BzqJcqDA.js → wardley-L42UT6IY-536kdB5p.js} +1 -1
  86. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Bctxc6_5.js → wardleyDiagram-YWT4CUSO-D8iNQ_MW.js} +1 -1
  87. package/dist/client/assets/{xychartDiagram-2RQKCTM6-CgDuiMFR.js → xychartDiagram-2RQKCTM6-CXqp8mzh.js} +1 -1
  88. package/dist/client/index.html +3 -3
  89. package/dist/client/version.json +1 -1
  90. package/dist/droid-cli/package.json +1 -1
  91. package/dist/extension.js +4678 -917
  92. package/dist/pi-claude-cli/package.json +1 -1
  93. package/dist/plugin-sdk/index.d.ts +47 -3
  94. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  95. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  96. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  97. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  98. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  99. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  100. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  101. package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
  102. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  103. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  104. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  105. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  106. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  107. package/package.json +1 -1
  108. package/dist/client/assets/ChatView-B4WnXLYA.js +0 -6
  109. package/dist/client/assets/DirectoryPicker-BiS41Hca.js +0 -1
  110. package/dist/client/assets/SessionTerminal-VLdVV3Ji.js +0 -2
  111. package/dist/client/assets/SettingsModal-4t8rV7rh.css +0 -1
  112. package/dist/client/assets/SettingsModal-gcrh5EOG.js +0 -21
  113. package/dist/client/assets/SetupWizardModal-DvmTlFP_.js +0 -2
  114. package/dist/client/assets/TodoView-bV-7deOh.js +0 -6
  115. package/dist/client/assets/WorkflowNodeEditor-Ui1q_fFI.js +0 -8
  116. package/dist/client/assets/app--OM-ul6R.js +0 -13
  117. package/dist/client/assets/app-BCvqf8qq.js +0 -13
  118. package/dist/client/assets/app-BZqqEiWR.js +0 -13
  119. package/dist/client/assets/app-DQeH1UDD.js +0 -13
  120. package/dist/client/assets/app-FiYwRatp.js +0 -13
  121. package/dist/client/assets/app-rGdYcsAA.js +0 -13
  122. package/dist/client/assets/channel-C5g9M3Sk.js +0 -1
  123. package/dist/client/assets/classDiagram-4FO5ZUOK-B-wdlvD6.js +0 -1
  124. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B-wdlvD6.js +0 -1
  125. package/dist/client/assets/index-B6ttSchA.js +0 -1336
  126. package/dist/client/assets/index-CPE2Kwra.css +0 -1
  127. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-BZ_mlvie.js +0 -1
@@ -0,0 +1,8 @@
1
+ import{r as n,j as e,b as Da}from"./vendor-react-SZ_qB27O.js";import{R as Ta,u as La,d as za,e as Wa,f as $a,g as _a,B as Ba,C as Ga,M as qa}from"./vendor-reactflow-CnI7NMXG.js";import{c as Va,em as Et,en as io,eo as he,ep as Hs,eq as Ha,er as Ua,es as Us,bs as ae,br as At,P as Pe,bb as ze,bx as Ka,af as Ya,o as Ae,J as je,ao as Ks,et as Ja,bO as Pt,eu as os,bI as Ys,ev as lo,an as Qa,C as Ie,bS as ro,I as Xa,ew as Za,ex as en,ct as ss,ey as tn,ez as on,eA as sn,eB as an,dz as nn,a5 as as,ag as ln,eC as rn,eD as dn,eE as cn,eF as un,eG as fn,eH as pn,ak as mn,eI as wn,eJ as hn,eK as ns,eL as is,eM as ls,eN as rs,eO as ds,eP as gn,eQ as bn,eR as kn,eS as ut,eT as xn,eU as vn,eV as jn,eW as Nn,eX as yn,eY as Cn,eZ as cs,e_ as Sn,e$ as us,f0 as fs,f1 as En,f2 as ps,f3 as ms,f4 as An,f5 as eo,f6 as Pn,f7 as Js,f8 as ws,f9 as Fn,i as hs,dl as gs,fa as bs,X as Qs,bv as ks,L as Me,fb as Le,fc as to,bu as Xs,am as Zs,be as Rn,fd as ea,fe as In,a3 as Mn,bd as On,ff as Dn,fg as Tn,fh as Ln,fi as xs,fj as zn,fk as Wn,fl as $n,fm as _n,fn as St,S as Je,fo as Bn,fp as Gn,fq as qn,dm as vs,fr as js,fs as Vn,ft as Hn,dp as Un,fu as Kn,fv as Yn}from"./index-rfsTNfpA.js";import{u as Ne}from"./vendor-i18n-GF3RlKbq.js";import{U as Jn}from"./upload-BKpOp-Bn.js";import"./vendor-codemirror-jBKmHyH0.js";import"./vendor-xterm-BNq00GSj.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 Qn=[["path",{d:"m16 6 4 14",key:"ji33uf"}],["path",{d:"M12 6v14",key:"1n7gus"}],["path",{d:"M8 8v12",key:"1gg7y9"}],["path",{d:"M4 4v16",key:"6qkkli"}]],Xn=Va("library",Qn);function Zn(s){return typeof s.irKind=="string"?s.irKind:s.kind}const ei={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."},"ask-user":{title:"Ask user question",summary:"Reaches out to the user from inside the running task: parks the task awaiting a reply, surfaces the Question in the task chat/detail, and resumes the flow once the user replies and unpauses. First-class surface over the same park/resume plumbing a Prompt node's Wait for user input option uses.",configure:'Write the Question the user is asked. Leave it blank to use the default "This workflow is waiting for your input" prompt.',inputs:"The task at this point in the flow.",outputs:"The user's reply, available downstream as this node's input context.",edges:"One outgoing edge (success), taken once the user replies. Compose with an Exit gate for a brainstorm ask → refine → exit-when-approved loop."},"exit-gate":{title:"Exit gate",summary:"Lets a workflow terminate early — routing straight to the terminal End node — instead of always walking the full graph. Useful for breaking out of a brainstorming ask-user/refine loop once the user approves.",configure:"Optionally set an Exit condition (output contains / output matches regex) checked against a referenced node's input (e.g. an Ask user question's reply). Leave unset for an unconditional exit.",inputs:"The task plus prior context (e.g. an Ask user question's reply).",outputs:"An exit / continue decision.",edges:"outcome:exit → routes to End; outcome:continue → falls through to the next node (e.g. back into the brainstorm loop)."},"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 ti(s){return ei[s]??null}function oi(s){return ti(Zn(s))}const Ns=80,si=24,ys=16,Cs=0,ai=0,oo=Hs+si;function ni(s){return!(he(s.id)||s.parentId)}function ii(s){const l=s.style?.width;return typeof l=="number"?l:Et}function li(s,l){const r=new Set(s),g=new Map,d=new Map;for(const x of s)d.set(x,0);for(const x of l)x.data?.kind!=="rework"&&(!r.has(x.source)||!r.has(x.target)||x.source!==x.target&&((g.get(x.source)??g.set(x.source,[]).get(x.source)).push(x.target),d.set(x.target,(d.get(x.target)??0)+1)));const k=s.filter(x=>x==="start"),O=k.length?k:s.filter(x=>(d.get(x)??0)===0),p=new Map,F=s.length+1,R=[];for(const x of O)p.set(x,0),R.push(x);let D=s.length*s.length+s.length+1;for(;R.length&&D-- >0;){const x=R.shift(),w=p.get(x)??0;for(const c of g.get(x)??[]){const A=w+1,N=p.get(c);(N===void 0||A>N)&&A<=F&&(p.set(c,A),R.push(c))}}let T=0;for(const x of p.values())x>T&&(T=x);const C=p.size?T+1:0;for(const x of s)p.has(x)||p.set(x,C);return p}function Ss(s,l,r){const g=s.filter(ni),d=g.map(w=>w.id),k=li(d,l),O=new Map(g.map(w=>[w.id,w])),p=new Map,F=new Map;for(const w of d){const c=k.get(w)??0;(F.get(c)??F.set(c,[]).get(c)).push(w)}const R=r.length>0,D=new Map;for(const[w,c]of F)D.set(w,Math.max(...c.map(A=>ii(O.get(A))),Et));const T=[...F.keys()].sort((w,c)=>w-c),C=new Map;let x=Cs;for(const w of T)C.set(w,x),x+=(D.get(w)??Et)+Ns;for(const[w,c]of F){const A=[...c].sort((b,I)=>{const P=O.get(b),S=O.get(I);return P.position.y!==S.position.y?P.position.y-S.position.y:b<I?-1:b>I?1:0}),N=C.get(w)??Cs;if(!R){A.forEach((b,I)=>{p.set(b,{x:N,y:ai+I*oo})});continue}const $=new Map;for(const b of A){const I=O.get(b),P=I.data.column??(io(I.position.y,r)?io(I.position.y,r):void 0);if(!P){p.set(b,{x:N,y:I.position.y});continue}const S=r.findIndex(se=>se.id===P),W=S>=0?S:0,fe=Ua(W),K=fe+ys,J=fe+Ha-Hs-ys,te=Math.max(1,Math.floor((J-K)/oo)+1),V=$.get(P??`__idx${W}`)??0,j=V%te,L=Math.floor(V/te),B=K+j*oo,G=N+L*((D.get(w)??Et)+Ns)/2;p.set(b,{x:G,y:B}),$.set(P??`__idx${W}`,V+1)}}return p}function Es(s,l){return s.map(r=>{const g=l.get(r.id);return g?{...r,position:g}:r})}let As=0;function ri(){return As+=1,`col-${Date.now().toString(36)}-${As}`}function Ps({columns:s,onChange:l,violations:r,readOnly:g,projectId:d,addToast:k,columnAgentsEnabled:O}){const{t:p}=Ne("app"),[F,R]=n.useState([]),[D,T]=n.useState([]),[C,x]=n.useState(!0),[w,c]=n.useState(null);n.useEffect(()=>{let j=!1;return Us(d).then(L=>{j||R(L)}).catch(L=>{j||k(ae(L)||p("workflowColumns.traitsLoadFailed","Failed to load traits"),"error")}),()=>{j=!0}},[d,k,p]),n.useEffect(()=>{let j=!1;return x(!0),c(null),Promise.resolve(At(void 0,d)).then(L=>{j||(T(L??[]),x(!1))}).catch(L=>{if(j)return;const B=ae(L)||p("workflowColumns.agentsLoadFailed","Failed to load agents");c(B),x(!1),k(B,"error")}),()=>{j=!0}},[d,k,p]);const A=n.useMemo(()=>D.map(j=>j.id).join(","),[D]),N=n.useMemo(()=>{const j=new Map;for(const L of D)j.set(L.id,L);return j},[A]),$=n.useCallback((j,L)=>{l(s.map(B=>{if(B.id!==j)return B;if(!L){const{agent:G,...se}=B;return se}return{...B,agent:L}}))},[s,l]),b=n.useCallback((j,L)=>{if(!L){$(j,void 0);return}const B=s.find(G=>G.id===j)?.agent;$(j,{agentId:L,mode:B?.mode??"defer"})},[s,$]),I=n.useCallback((j,L)=>{const B=s.find(G=>G.id===j)?.agent;B&&$(j,{...B,mode:L})},[s,$]),P=g||!O||C||!!w,S=r.filter(j=>j.columnId===null),W=n.useCallback(j=>r.filter(L=>L.columnId===j),[r]),fe=n.useCallback(()=>{const j=ri();l([...s,{id:j,name:p("workflowColumns.newColumnName","New column"),traits:[]}])},[s,l,p]),K=n.useCallback((j,L)=>{l(s.map(B=>B.id===j?{...B,name:L}:B))},[s,l]),J=n.useCallback(j=>{l(s.filter(L=>L.id!==j))},[s,l]),te=n.useCallback((j,L)=>{const B=j+L;if(B<0||B>=s.length)return;const G=[...s];[G[j],G[B]]=[G[B],G[j]],l(G)},[s,l]),V=n.useCallback((j,L)=>{l(s.map(B=>{if(B.id!==j)return B;const G=B.traits.some(se=>se.trait===L);return{...B,traits:G?B.traits.filter(se=>se.trait!==L):[...B.traits,{trait:L}]}}))},[s,l]);return e.jsxs("aside",{className:"wf-column-panel","data-testid":"wf-column-panel",children:[e.jsxs("header",{className:"wf-column-panel-header",children:[e.jsx("h3",{children:p("workflowColumns.title","Columns")}),e.jsxs("button",{className:"wf-column-add",onClick:fe,disabled:g,title:g?p("workflowColumns.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,children:[e.jsx(Pe,{size:13})," ",p("workflowColumns.add","Add column")]})]}),S.length>0&&e.jsx("div",{className:"wf-column-panel-errors",role:"alert",children:S.map((j,L)=>e.jsxs("p",{className:"wf-column-violation",children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",j.message]},`${j.code}-${L}`))}),s.length===0?e.jsx("p",{className:"wf-column-panel-empty",children:p("workflowColumns.empty","No columns yet. Add a column to place nodes into board lanes.")}):e.jsx("ul",{className:"wf-column-list",children:s.map((j,L)=>{const B=W(j.id),G=j.agent?.agentId,se=G?N.get(G):void 0,pe=!!G&&!C&&!w&&!se,re=se?.name??(pe?p("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:G??""}):G);return e.jsxs("li",{className:`wf-column-item${B.length?" wf-column-item--error":""}`,"data-testid":`wf-column-${j.id}`,"data-column-error":B.length?"true":void 0,children:[e.jsxs("div",{className:"wf-column-item-head",children:[e.jsx("input",{className:"wf-column-name","aria-label":p("workflowColumns.nameLabel","Column name"),value:j.name,disabled:g,onChange:X=>K(j.id,X.target.value)}),G&&e.jsxs("span",{className:`wf-column-agent-badge${pe?" wf-column-agent-badge--stale":""}`,"data-testid":`wf-column-agent-badge-${j.id}`,title:j.agent?.mode==="override"?p("workflowColumns.agentBadgeOverride","Column agent (override)"):p("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":p("workflowColumns.moveUp","Move column up"),disabled:g||L===0,onClick:()=>te(L,-1),children:e.jsx(Ya,{size:13})}),e.jsx("button",{className:"wf-column-move","aria-label":p("workflowColumns.moveDown","Move column down"),disabled:g||L===s.length-1,onClick:()=>te(L,1),children:e.jsx(Ae,{size:13})}),e.jsx("button",{className:"wf-column-remove","aria-label":p("workflowColumns.remove","Remove column"),disabled:g,onClick:()=>J(j.id),children:e.jsx(je,{size:13})})]})]}),B.map((X,ie)=>e.jsxs("p",{className:"wf-column-violation",role:"alert",children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",X.message]},`${X.code}-${ie}`)),e.jsxs("div",{className:"wf-column-traits",children:[e.jsx("span",{className:"wf-column-traits-label",children:p("workflowColumns.traits","Traits")}),e.jsx("div",{className:"wf-column-trait-options",children:F.map(X=>{const ie=j.traits.some(de=>de.trait===X.id);return e.jsxs("label",{className:"wf-column-trait",title:X.description,children:[e.jsx("input",{type:"checkbox",checked:ie,disabled:g,onChange:()=>V(j.id,X.id)}),e.jsx("span",{children:X.name})]},X.id)})})]}),e.jsxs("div",{className:"wf-column-agent",children:[e.jsx("span",{className:"wf-column-agent-label",children:p("workflowColumns.agent","Column agent")}),e.jsxs("select",{className:"wf-column-agent-select","data-testid":`wf-column-agent-select-${j.id}`,"aria-label":p("workflowColumns.agentLabel","Column agent"),value:G??"",disabled:P,title:g?p("workflowColumns.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,onChange:X=>b(j.id,X.target.value),children:[e.jsx("option",{value:"",children:p("workflowColumns.agentNone","(none)")}),pe&&G&&e.jsx("option",{value:G,children:p("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:G})}),D.map(X=>e.jsx("option",{value:X.id,children:X.name},X.id))]}),w&&e.jsxs("p",{className:"wf-column-agent-error",role:"alert",children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",w]}),pe&&e.jsxs("p",{className:"wf-column-agent-stale",role:"alert","data-testid":`wf-column-agent-stale-${j.id}`,children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",p("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:G??""})]}),G&&e.jsxs("div",{className:"wf-column-agent-mode",role:"radiogroup","aria-label":p("workflowColumns.agentMode","Agent mode"),children:[e.jsxs("label",{className:"wf-column-agent-mode-option",children:[e.jsx("input",{type:"radio",name:`wf-column-agent-mode-${j.id}`,checked:(j.agent?.mode??"defer")==="defer",disabled:P,onChange:()=>I(j.id,"defer")}),e.jsx("span",{title:p("workflowColumns.agentModeDeferHint","Column agent applies only when the work carries no agent/model settings of its own"),children:p("workflowColumns.agentModeDefer","Defer")})]}),e.jsxs("label",{className:"wf-column-agent-mode-option",children:[e.jsx("input",{type:"radio",name:`wf-column-agent-mode-${j.id}`,checked:j.agent?.mode==="override",disabled:P,onChange:()=>I(j.id,"override")}),e.jsx("span",{title:p("workflowColumns.agentModeOverrideHint","Column agent supersedes node- and task-level agent/model settings"),children:p("workflowColumns.agentModeOverride","Override")})]})]})]})]},j.id)})})]})}const di=["string","text","number","boolean","enum","multi-enum","date","url"],Fs={string:["input"],text:["textarea","input"],number:["input"],boolean:["toggle"],enum:["select","radio","chips"],"multi-enum":["chips"],date:["input"],url:["input"]},ci=["#4f7cff","#22c55e","#f59e0b","#ef4444","#a855f7","#06b6d4","#ec4899","#64748b"];function Ft(s){return s==="enum"||s==="multi-enum"}function ui(s){return s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}let Rs=0;function fi(){return Rs+=1,`field-${Date.now().toString(36)}-${Rs}`}function pi({field:s}){const l=n.useMemo(()=>{if(Ft(s.type)){const g=s.options?.[0];return g?s.type==="multi-enum"?{node:e.jsx("span",{className:"card-field-badge card-field-badge--multi",title:s.name,children:(s.options??[]).slice(0,2).map(d=>e.jsx("span",{className:"card-field-badge-token",style:d.color?{backgroundColor:d.color,borderColor:d.color,color:"#fff"}:void 0,children:d.label},d.value))})}:{node:e.jsx("span",{className:"card-field-badge card-field-badge--enum",title:`${s.name}: ${g.label}`,style:g.color?{backgroundColor:g.color,borderColor:g.color,color:"#fff"}:void 0,children:g.label})}:null}if(s.type==="boolean")return{node:e.jsx("span",{className:"card-field-badge card-field-badge--boolean",title:s.name,children:s.name})};const r=s.type==="number"?"42":s.type==="date"?"2026-06-04":s.type==="url"?"example.com":s.name;return{node:e.jsx("span",{className:"card-field-badge",title:s.name,children:r})}},[s]);return l?e.jsx("div",{className:"wf-field-preview","data-testid":`wf-field-preview-${s.id}`,children:e.jsx("div",{className:"card-field-badges",children:l.node})}):null}function Is({fields:s,onChange:l,readOnly:r,addToast:g}){const{t:d}=Ne("app"),[k,O]=n.useState(null),p=n.useCallback((c,A)=>{l(s.map(N=>N.id===c?{...N,...A}:N))},[s,l]),F=n.useCallback(()=>{const c=fi();l([...s,{id:c,name:d("workflowFields.newFieldName","New field"),type:"string"}])},[s,l,d]),R=n.useCallback(c=>{l(s.filter(A=>A.id!==c))},[s,l]),D=n.useCallback((c,A)=>{const N=ui(A);if(N){if(N!==c&&s.some($=>$.id===N)){g(d("workflowFields.duplicateId","A field with that id already exists"),"error");return}p(c,{id:N})}},[s,p,g,d]),T=n.useCallback((c,A)=>{const N=s.find(b=>b.id===c);if(!N)return;const $={type:A};Ft(A)?(!N.options||N.options.length===0)&&($.options=[{value:"option-1",label:d("workflowFields.newOptionLabel","Option 1")}]):$.options=void 0,N.render?.widget&&!Fs[A].includes(N.render.widget)&&($.render={...N.render,widget:void 0}),$.default=void 0,p(c,$)},[s,p,d]),C=n.useCallback((c,A)=>p(c,{options:A}),[p]),x=n.useCallback((c,A)=>{const N=!A||A.placement===void 0&&A.widget===void 0&&!A.badge;p(c,{render:N?void 0:A})},[p]),w=c=>{const A=b=>p(c.id,{default:b});if(c.type==="boolean")return e.jsxs("label",{className:"wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:c.default===!0,disabled:r,onChange:b=>A(b.target.checked)}),e.jsx("span",{children:d("workflowFields.defaultTrue","Default on")})]});if(Ft(c.type)){const b=c.type==="multi-enum"?Array.isArray(c.default)?c.default[0]??"":"":typeof c.default=="string"?c.default:"";return e.jsxs("select",{"aria-label":d("workflowFields.defaultLabel","Default value"),value:b,disabled:r,onChange:I=>{const P=I.target.value;if(P==="")return A(void 0);A(c.type==="multi-enum"?[P]:P)},children:[e.jsx("option",{value:"",children:d("workflowFields.noDefault","— none —")}),(c.options??[]).map(I=>e.jsx("option",{value:I.value,children:I.label},I.value))]})}const N=c.type==="number"?"number":c.type==="date"?"date":c.type==="url"?"url":"text",$=c.type==="number"?typeof c.default=="number"?String(c.default):"":typeof c.default=="string"?c.default:"";return e.jsx("input",{type:N,"aria-label":d("workflowFields.defaultLabel","Default value"),defaultValue:$,disabled:r,onBlur:b=>{const I=b.target.value;if(I==="")return A(void 0);A(c.type==="number"?Number(I):I)}})};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:F,disabled:r,title:r?d("workflowFields.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,children:[e.jsx(Pe,{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 A=Fs[c.type],N=c.render?.placement??"detail",$=k===c.id;return e.jsxs("li",{className:"wf-field-item","data-testid":`wf-field-${c.id}`,children:[e.jsxs("div",{className:"wf-field-item-head",children:[e.jsx("input",{className:"wf-field-name","aria-label":d("workflowFields.nameLabel","Field name"),value:c.name,disabled:r,onChange:b=>p(c.id,{name:b.target.value})}),e.jsx("button",{className:"wf-field-remove","aria-label":d("workflowFields.remove","Remove field"),disabled:r,onClick:()=>R(c.id),children:e.jsx(je,{size:13})})]}),e.jsx("div",{className:"wf-field-id-row",children:$?e.jsxs(e.Fragment,{children:[e.jsx("input",{className:"wf-field-id","aria-label":d("workflowFields.idLabel","Field id"),defaultValue:c.id,disabled:r,onBlur:b=>{D(c.id,b.target.value),O(null)}}),e.jsxs("p",{className:"wf-field-id-warn",role:"note",children:[e.jsx(ze,{size:11,"aria-hidden":!0})," ",d("workflowFields.idWarn","Changing the id discards values stored under the old id (remove + add).")]})]}):e.jsxs(e.Fragment,{children:[e.jsx("code",{className:"wf-field-id-static",children:c.id}),e.jsx("button",{className:"wf-field-id-edit",disabled:r,onClick:()=>O(c.id),children:d("workflowFields.editId","Edit id")})]})}),e.jsxs("div",{className:"wf-field-row",children:[e.jsxs("label",{className:"wf-field-sub",children:[e.jsx("span",{children:d("workflowFields.typeLabel","Type")}),e.jsx("select",{value:c.type,disabled:r,onChange:b=>T(c.id,b.target.value),children:di.map(b=>e.jsx("option",{value:b,children:b},b))})]}),e.jsxs("label",{className:"wf-field--checkbox wf-field-required",children:[e.jsx("input",{type:"checkbox",checked:c.required===!0,disabled:r,onChange:b=>p(c.id,{required:b.target.checked||void 0})}),e.jsx("span",{children:d("workflowFields.required","Required")})]})]}),e.jsxs("label",{className:"wf-field-sub",children:[e.jsx("span",{children:d("workflowFields.default","Default")}),w(c)]}),Ft(c.type)&&e.jsxs("div",{className:"wf-field-options","data-testid":`wf-field-options-${c.id}`,children:[e.jsx("span",{className:"wf-field-options-label",children:d("workflowFields.options","Options")}),(c.options??[]).map((b,I)=>e.jsxs("div",{className:"wf-field-option-row",children:[e.jsx("input",{className:"wf-field-option-value","aria-label":d("workflowFields.optionValue","Option value"),value:b.value,disabled:r,onChange:P=>{const S=[...c.options??[]];S[I]={...b,value:P.target.value},C(c.id,S)}}),e.jsx("input",{className:"wf-field-option-label","aria-label":d("workflowFields.optionLabel","Option label"),value:b.label,disabled:r,onChange:P=>{const S=[...c.options??[]];S[I]={...b,label:P.target.value},C(c.id,S)}}),e.jsx("div",{className:"wf-field-option-colors",role:"group","aria-label":d("workflowFields.optionColor","Option color"),children:ci.map(P=>e.jsx("button",{type:"button",className:`wf-field-color-swatch${b.color===P?" is-active":""}`,style:{backgroundColor:P},"aria-label":P,"aria-pressed":b.color===P,disabled:r,onClick:()=>{const S=[...c.options??[]];S[I]={...b,color:b.color===P?void 0:P},C(c.id,S)}},P))}),e.jsx("button",{className:"wf-field-option-remove","aria-label":d("workflowFields.removeOption","Remove option"),disabled:r,onClick:()=>C(c.id,(c.options??[]).filter((P,S)=>S!==I)),children:e.jsx(je,{size:12})})]},I)),e.jsxs("button",{className:"wf-field-option-add",disabled:r,onClick:()=>{const b=(c.options??[]).length+1;C(c.id,[...c.options??[],{value:`option-${b}`,label:d("workflowFields.optionN","Option {{n}}",{n:b})}])},children:[e.jsx(Pe,{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:N,disabled:r,onChange:b=>x(c.id,{...c.render,placement:b.target.value}),children:[e.jsx("option",{value:"detail",children:d("workflowFields.placementDetail","Detail (inline)")}),e.jsx("option",{value:"detail-section",children:d("workflowFields.placementSection","Detail section")}),e.jsx("option",{value:"card",children:d("workflowFields.placementCard","Card badge")})]})]}),e.jsxs("label",{className:"wf-field-sub",children:[e.jsx("span",{children:d("workflowFields.widget","Widget")}),e.jsxs("select",{value:c.render?.widget??"",disabled:r,onChange:b=>x(c.id,{...c.render,widget:b.target.value||void 0}),children:[e.jsx("option",{value:"",children:d("workflowFields.widgetDefault","Default")}),A.map(b=>e.jsx("option",{value:b,children:b},b))]})]}),e.jsxs("label",{className:"wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:c.render?.badge===!0,disabled:r,onChange:b=>x(c.id,{...c.render,badge:b.target.checked||void 0})}),e.jsx("span",{children:d("workflowFields.badge","Render as badge")})]})]}),N==="card"&&e.jsx(pi,{field:c})]},c.id)})})]})}const mi={planningProvider:{group:"models",label:"Plan/Triage provider",description:"Provider used when planning or triaging tasks."},planningModelId:{group:"models",label:"Plan/Triage model",description:"Model used when planning or triaging tasks."},planningFallbackProvider:{group:"models",label:"Plan/Triage fallback provider"},planningFallbackModelId:{group:"models",label:"Plan/Triage fallback model"},executionProvider:{group:"models",label:"Executor provider",description:"Provider used by task implementation agents."},executionModelId:{group:"models",label:"Executor model",description:"Model used by task implementation agents."},validatorProvider:{group:"models",label:"Reviewer provider",description:"Provider used by review and validation agents."},validatorModelId:{group:"models",label:"Reviewer model",description:"Model used by review and validation agents."},validatorFallbackProvider:{group:"models",label:"Reviewer fallback provider"},validatorFallbackModelId:{group:"models",label:"Reviewer fallback model"},requirePrApproval:{group:"review",label:"Require PR approval"},requirePlanApproval:{group:"review",label:"Require plan approval"},reviewHandoffPolicy:{group:"review",label:"Review handoff policy"},maxReviewerContextRetries:{group:"review",label:"Reviewer context retries"},maxReviewerFallbackRetries:{group:"review",label:"Reviewer fallback retries"},reflectionEnabled:{group:"review",label:"Reflection enabled"},planReviewMaxRevisions:{group:"review",label:"Plan Review revision cap",description:"Leave empty for unbounded automatic Plan Review/spec revision; set 0 to disable automatic revision."},codeReviewMaxRevisions:{group:"review",label:"Code Review revision cap",description:"Leave empty for unbounded automatic Code Review remediation; set 0 to disable automatic revision."},triageProactiveSubtaskSplittingEnabled:{group:"steps",label:"Automatic large-task splitting",description:"Default enabled. When off, triage keeps oversized tasks whole unless breakIntoSubtasks: true is explicitly requested."},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"},plannerOversightLevel:{group:"oversight",label:"Planner oversight level",description:"Off disables oversight; Observe watches only; Steer injects guidance or suggests revisions; Autonomous recovery enables bounded retry and targeted-fix recovery. Per-task overrides are set on individual tasks and win over this project/global default."}},wi=["models","review","oversight","steps","advanced"],hi={models:"Models",review:"Review & Approval",oversight:"Planner Oversight",steps:"Step Execution",advanced:"Advanced"};function ta(s){return mi[s.id]??{group:"advanced",label:s.name,description:s.description}}function gi(s){const l=new Map;for(const r of s){const g=ta(r).group,d=l.get(g)??[];d.push(r),l.set(g,d)}return wi.map(r=>({group:r,settings:l.get(r)??[]})).filter(r=>r.settings.length>0)}function Qe({htmlFor:s,label:l,help:r,error:g,scope:d,disabled:k,clearable:O,onClear:p,children:F}){const{t:R}=Ne("app");return e.jsxs("div",{className:`settings-field-row${k?" is-disabled":""}`,children:[e.jsxs("div",{className:"settings-field-row-head",children:[e.jsx("label",{className:"settings-field-row-label",htmlFor:s,children:l}),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:[F,O&&e.jsx("button",{type:"button",className:"settings-field-row-clear","aria-label":R("settings.clearToDefault","Reset to default"),title:R("settings.clearToDefault","Reset to default"),disabled:k,onClick:p,children:e.jsx(Ks,{size:13,"aria-hidden":!0})})]}),r&&e.jsx("p",{className:"settings-field-row-help",children:r}),g&&e.jsx("p",{className:"settings-field-row-error",role:"alert",children:g})]})}function bi({descriptor:s,value:l,onChange:r,error:g,clearable:d}){const{key:k,label:O,help:p,scope:F,disabled:R}=s;return e.jsx(Qe,{htmlFor:k,label:O,help:p,error:g,scope:F,disabled:R,clearable:d,onClear:()=>r(null),children:e.jsx("label",{className:"settings-toggle",children:e.jsx("input",{id:k,type:"checkbox",checked:l===!0,disabled:R,onChange:D=>r(D.target.checked)})})})}function ki({descriptor:s,value:l,onChange:r,error:g,clearable:d}){const{key:k,label:O,help:p,scope:F,disabled:R,min:D,max:T,step:C,placeholder:x}=s;return e.jsx(Qe,{htmlFor:k,label:O,help:p,error:g,scope:F,disabled:R,clearable:d,onClear:()=>r(null),children:e.jsx("input",{id:k,className:"settings-number",type:"number",value:l??"",min:D,max:T,step:C,placeholder:x,disabled:R,onChange:w=>{const c=w.target.value;if(c==="")return r(null);const A=Number(c);Number.isNaN(A)||r(A)}})})}function Ms({descriptor:s,value:l,onChange:r,error:g,clearable:d}){const{key:k,label:O,help:p,scope:F,disabled:R,options:D}=s;return e.jsx(Qe,{htmlFor:k,label:O,help:p,error:g,scope:F,disabled:R,clearable:d,onClear:()=>r(null),children:e.jsx("select",{id:k,className:"settings-select",value:l??"",disabled:R,onChange:T=>r(T.target.value),children:D.map(T=>e.jsx("option",{value:T.value,children:T.label},T.value))})})}function xi({descriptor:s,value:l,onChange:r,error:g,clearable:d}){const{key:k,label:O,help:p,scope:F,disabled:R,placeholder:D}=s;return e.jsx(Qe,{htmlFor:k,label:O,help:p,error:g,scope:F,disabled:R,clearable:d,onClear:()=>r(null),children:e.jsx("input",{id:k,className:"settings-text",type:"text",value:l??"",placeholder:D,disabled:R,onChange:T=>r(T.target.value)})})}function vi({descriptor:s,value:l,onChange:r,error:g,clearable:d}){const{key:k,label:O,help:p,scope:F,disabled:R,placeholder:D}=s;return e.jsx(Qe,{htmlFor:k,label:O,help:p,error:g,scope:F,disabled:R,clearable:d,onClear:()=>r(null),children:e.jsx("textarea",{id:k,className:"settings-textarea",value:l??"",placeholder:D,disabled:R,rows:3,onChange:T=>r(T.target.value)})})}const ji=["string","text","number","boolean","enum","multi-enum"],Os={string:["input"],text:["textarea","input"],number:["input"],boolean:["toggle"],enum:["select","radio","chips"],"multi-enum":["chips"]},Ni=["#4f7cff","#22c55e","#f59e0b","#ef4444","#a855f7","#06b6d4","#ec4899","#64748b"];function so(s){return s==="enum"||s==="multi-enum"}function yi(s){return s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}let Ds=0;function Ci(){return Ds+=1,`setting-${Date.now().toString(36)}-${Ds}`}function Si({settings:s,onChange:l,readOnly:r,addToast:g}){const{t:d}=Ne("app"),[k,O]=n.useState(null),p=n.useCallback((w,c)=>{l(s.map(A=>A.id===w?{...A,...c}:A))},[s,l]),F=n.useCallback(()=>{l([...s,{id:Ci(),name:d("workflowSettings.newSettingName","New setting"),type:"string"}])},[s,l,d]),R=n.useCallback(w=>l(s.filter(c=>c.id!==w)),[s,l]),D=n.useCallback((w,c)=>{const A=yi(c);if(A){if(A!==w&&s.some(N=>N.id===A)){g(d("workflowSettings.duplicateId","A setting with that id already exists"),"error");return}p(w,{id:A})}},[s,p,g,d]),T=n.useCallback((w,c)=>{const A=s.find($=>$.id===w);if(!A)return;const N={type:c};so(c)?(!A.options||A.options.length===0)&&(N.options=[{value:"option-1",label:d("workflowSettings.newOptionLabel","Option 1")}]):N.options=void 0,A.render?.widget&&!Os[c].includes(A.render.widget)&&(N.render=void 0),N.default=void 0,p(w,N)},[s,p,d]),C=n.useCallback((w,c)=>p(w,{options:c}),[p]),x=w=>{const c=$=>p(w.id,{default:$});if(w.type==="boolean")return e.jsxs("label",{className:"wf-setting--checkbox",children:[e.jsx("input",{type:"checkbox",checked:w.default===!0,disabled:r,onChange:$=>c($.target.checked)}),e.jsx("span",{children:d("workflowSettings.defaultTrue","Default on")})]});if(so(w.type)){const $=w.type==="multi-enum"?Array.isArray(w.default)?w.default[0]??"":"":typeof w.default=="string"?w.default:"";return e.jsxs("select",{"aria-label":d("workflowSettings.defaultLabel","Default value"),value:$,disabled:r,onChange:b=>{const I=b.target.value;if(I==="")return c(void 0);c(w.type==="multi-enum"?[I]:I)},children:[e.jsx("option",{value:"",children:d("workflowSettings.noDefault","— none —")}),(w.options??[]).map(b=>e.jsx("option",{value:b.value,children:b.label},b.value))]})}const A=w.type==="number"?"number":"text",N=w.type==="number"?typeof w.default=="number"?String(w.default):"":typeof w.default=="string"?w.default:"";return e.jsx("input",{type:A,"aria-label":d("workflowSettings.defaultLabel","Default value"),defaultValue:N,disabled:r,onBlur:$=>{const b=$.target.value;if(b==="")return c(void 0);c(w.type==="number"?Number(b):b)}})};return e.jsxs("div",{className:"wf-settings-tabpanel","data-testid":"wf-settings-definitions",children:[e.jsx("div",{className:"wf-settings-tabpanel-head",children:e.jsxs("button",{className:"wf-settings-add",onClick:F,disabled:r,title:r?d("workflowSettings.readOnlyHint","Built-in workflows are read-only — duplicate to edit"):void 0,children:[e.jsx(Pe,{size:13})," ",d("workflowSettings.add","Add setting")]})}),r&&e.jsx("p",{className:"wf-settings-note wf-settings-note--info",role:"note",children:d("workflowSettings.builtinDefinitionsReadOnly","Built-in workflow — declarations are read-only. Values are editable below.")}),s.length===0?e.jsx("p",{className:"wf-settings-empty",children:d("workflowSettings.empty","No settings declared yet. Add a setting to expose a typed, per-project knob.")}):e.jsx("ul",{className:"wf-settings-list",children:s.map(w=>{const c=Os[w.type],A=k===w.id;return e.jsxs("li",{className:"wf-setting-item","data-testid":`wf-setting-${w.id}`,children:[e.jsxs("div",{className:"wf-setting-item-head",children:[e.jsx("input",{className:"wf-setting-name","aria-label":d("workflowSettings.nameLabel","Setting name"),value:w.name,disabled:r,onChange:N=>p(w.id,{name:N.target.value})}),e.jsx("button",{className:"wf-setting-remove","aria-label":d("workflowSettings.remove","Remove setting"),disabled:r,onClick:()=>R(w.id),children:e.jsx(je,{size:13})})]}),e.jsx("div",{className:"wf-setting-id-row",children:A?e.jsxs(e.Fragment,{children:[e.jsx("input",{className:"wf-setting-id","aria-label":d("workflowSettings.idLabel","Setting id"),defaultValue:w.id,disabled:r,onBlur:N=>{D(w.id,N.target.value),O(null)}}),e.jsxs("p",{className:"wf-setting-id-warn",role:"note",children:[e.jsx(ze,{size:11,"aria-hidden":!0})," ",d("workflowSettings.idWarn","Changing the id discards values stored under the old id (remove + add).")]})]}):e.jsxs(e.Fragment,{children:[e.jsx("code",{className:"wf-setting-id-static",children:w.id}),e.jsx("button",{className:"wf-setting-id-edit",disabled:r,onClick:()=>O(w.id),children:d("workflowSettings.editId","Edit id")})]})}),e.jsxs("div",{className:"wf-setting-row",children:[e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.typeLabel","Type")}),e.jsx("select",{value:w.type,disabled:r,onChange:N=>T(w.id,N.target.value),children:ji.map(N=>e.jsx("option",{value:N,children:N},N))})]}),e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.widget","Widget")}),e.jsxs("select",{value:w.render?.widget??"",disabled:r,onChange:N=>p(w.id,{render:N.target.value?{widget:N.target.value}:void 0}),children:[e.jsx("option",{value:"",children:d("workflowSettings.widgetDefault","Default")}),c.map(N=>e.jsx("option",{value:N,children:N},N))]})]})]}),e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.default","Default")}),x(w)]}),e.jsxs("label",{className:"wf-setting-sub",children:[e.jsx("span",{children:d("workflowSettings.description","Description")}),e.jsx("input",{"aria-label":d("workflowSettings.descriptionLabel","Setting description"),value:w.description??"",disabled:r,onChange:N=>p(w.id,{description:N.target.value||void 0})})]}),so(w.type)&&e.jsxs("div",{className:"wf-setting-options","data-testid":`wf-setting-options-${w.id}`,children:[e.jsx("span",{className:"wf-setting-options-label",children:d("workflowSettings.options","Options")}),(w.options??[]).map((N,$)=>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:N.value,disabled:r,onChange:b=>{const I=[...w.options??[]];I[$]={...N,value:b.target.value},C(w.id,I)}}),e.jsx("input",{className:"wf-setting-option-label","aria-label":d("workflowSettings.optionLabel","Option label"),value:N.label,disabled:r,onChange:b=>{const I=[...w.options??[]];I[$]={...N,label:b.target.value},C(w.id,I)}}),e.jsx("div",{className:"wf-setting-option-colors",role:"group","aria-label":d("workflowSettings.optionColor","Option color"),children:Ni.map(b=>e.jsx("button",{type:"button",className:`wf-setting-color-swatch${N.color===b?" is-active":""}`,style:{backgroundColor:b},"aria-label":b,"aria-pressed":N.color===b,disabled:r,onClick:()=>{const I=[...w.options??[]];I[$]={...N,color:N.color===b?void 0:b},C(w.id,I)}},b))}),e.jsx("button",{className:"wf-setting-option-remove","aria-label":d("workflowSettings.removeOption","Remove option"),disabled:r,onClick:()=>C(w.id,(w.options??[]).filter((b,I)=>I!==$)),children:e.jsx(je,{size:12})})]},$)),e.jsxs("button",{className:"wf-setting-option-add",disabled:r,onClick:()=>{const N=(w.options??[]).length+1;C(w.id,[...w.options??[],{value:`option-${N}`,label:d("workflowSettings.optionN","Option {{n}}",{n:N})}])},children:[e.jsx(Pe,{size:12})," ",d("workflowSettings.addOption","Add option")]})]})]},w.id)})})]})}function Ei(s){if(typeof s=="string")return s;try{return JSON.stringify(s)}catch{return String(s)}}function Ai(s,l){return Object.is(s,l)?!0:Array.isArray(s)&&Array.isArray(l)?s.length===l.length&&s.every((r,g)=>Object.is(r,l[g])):!1}const Pi=[{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 Fi(s){if(!s)return null;const l=s.indexOf("/");return l<=0||l===s.length-1?null:{provider:s.slice(0,l),modelId:s.slice(l+1)}}function Ri({workflowId:s,settings:l,boundProjectId:r,currentProjectId:g,addToast:d}){const{t:k}=Ne("app"),[O,p]=n.useState(null),[F,R]=n.useState(!1),[D,T]=n.useState({}),[C,x]=n.useState({}),[w,c]=n.useState(!1),[A,N]=n.useState(!1),[$,b]=n.useState([]),[I,P]=n.useState(!1),[S,W]=n.useState([]),[fe,K]=n.useState([]),J=n.useRef(0),te=n.useRef(0),V=n.useMemo(()=>new Map(l.map(m=>[m.id,m])),[l]),j=n.useMemo(()=>Pi.filter(m=>{const _=V.get(m.providerId),H=V.get(m.modelId);return _?.type==="string"&&H?.type==="string"}),[V]),L=n.useMemo(()=>new Set(j.flatMap(m=>[m.providerId,m.modelId])),[j]),B=r!==void 0&&g!==void 0&&g!==r,G=n.useCallback(async()=>{if(r===void 0)return;const m=++J.current;R(!0);try{const _=await Ja(s,r);J.current===m&&(p(_),T({}),x({}))}catch{J.current===m&&d(k("workflowSettings.loadFailed","Failed to load setting values"),"error")}finally{J.current===m&&R(!1)}},[s,r,d,k]);if(n.useEffect(()=>{G()},[G]),n.useEffect(()=>{if(r===void 0||j.length===0){b([]),W([]),K([]),P(!1);return}const m=++te.current;P(!0),Pt().then(_=>{te.current===m&&(b(_.models??[]),W(_.favoriteProviders??[]),K(_.favoriteModels??[]))}).catch(()=>{te.current===m&&(b([]),W([]),K([]),d(k("workflowSettings.modelsLoadFailed","Failed to load available models"),"error"))}).finally(()=>{te.current===m&&P(!1)})},[r,j.length,d,k]),r===void 0)return e.jsx("div",{className:"wf-settings-tabpanel","data-testid":"wf-settings-values",children:e.jsx("p",{className:"wf-settings-note wf-settings-note--info",role:"note",children:k("workflowSettings.requiresProject","Open a project to view and edit per-project setting values.")})});const se=m=>{if(Object.prototype.hasOwnProperty.call(D,m.id)){const _=D[m.id];return _===null?m.default:_}return O?.effective?.[m.id]??m.default},pe=m=>Object.prototype.hasOwnProperty.call(D,m.id)?D[m.id]!==null:O?Object.prototype.hasOwnProperty.call(O.stored,m.id):!1,re=(m,_)=>{T(H=>({...H,[m]:_})),x(H=>{if(!H[m])return H;const Z={...H};return delete Z[m],Z})},X=m=>re(m,null),ie=(m,_)=>{const H=Fi(_);T(Z=>({...Z,[m.providerId]:H?.provider??null,[m.modelId]:H?.modelId??null})),x(Z=>{if(!Z[m.providerId]&&!Z[m.modelId])return Z;const oe={...Z};return delete oe[m.providerId],delete oe[m.modelId],oe})},de=Object.keys(D).length>0,ye=n.useCallback(async()=>{if(!de)return;const m={...D},_=Object.keys(m);c(!0);try{const H=await os(s,m,r);p(H),T(Z=>{const oe={...Z};for(const Y of _)Ai(Z[Y],m[Y])&&delete oe[Y];return oe}),x({}),d(k("workflowSettings.valuesSaved","Setting values saved"),"success")}catch(H){if(H instanceof Ys&&H.status===400&&H.details){const Z=H.details.rejections??[];if(Z.length>0){const oe={};for(const Y of Z)oe[Y.settingId]=Y;x(oe),d(k("workflowSettings.valuesRejected","Some values were rejected — see the highlighted fields"),"error");return}}d(k("workflowSettings.saveFailed","Failed to save setting values"),"error")}finally{c(!1)}},[de,s,D,r,d,k]),o=m=>{const _=V.get(m);return _?se(_):void 0},q=m=>{const _=V.get(m);return _?pe(_):!1},ue=m=>{const _=o(m.providerId),H=o(m.modelId),Z=typeof _=="string"&&typeof H=="string"?`${_}/${H}`:"",oe=C[m.providerId]?.message??C[m.modelId]?.message,Y=q(m.providerId)||q(m.modelId),be=I||$.length===0,Q=!I&&$.length===0?` ${k("workflowSettings.noModelsAvailable","No models are available. Configure authentication before selecting a workflow model.")}`:"";return e.jsxs("div",{className:"wf-settings-value-item","data-testid":`wf-settings-value-${m.id}`,children:[e.jsx(Qe,{htmlFor:`wf-model-lane-${m.id}`,label:m.label,help:`${m.help}${Q}`,error:oe,scope:"project",disabled:I,clearable:Y,onClear:()=>ie(m,""),children:e.jsx(ro,{id:`wf-model-lane-${m.id}`,label:m.label,models:$,value:Z,onChange:Se=>ie(m,Se),placeholder:k("workflowSettings.selectModel","Select a model…"),defaultOptionLabel:k("workflowSettings.useInheritedModel","Use inherited/default model"),disabled:be,favoriteProviders:S,favoriteModels:fe})}),Y&&e.jsx("span",{className:"wf-settings-customized","data-testid":`wf-settings-customized-${m.id}`,children:k("workflowSettings.customized","Customized")})]},m.id)},Ce=m=>{const _=se(m),H=C[m.id]?.message,Z=pe(m),oe=ta(m),Y={key:m.id,label:oe.label,help:oe.description??m.description,scope:"project"},be=Z;switch(m.type){case"boolean":return e.jsx(bi,{descriptor:Y,value:_===!0,error:H,clearable:be,onChange:Q=>Q===null?X(m.id):re(m.id,Q)});case"number":return e.jsx(ki,{descriptor:Y,value:typeof _=="number"?_:null,error:H,clearable:be,onChange:Q=>Q===null?X(m.id):re(m.id,Q)});case"enum":return e.jsx(Ms,{descriptor:{...Y,options:(m.options??[]).map(Q=>({value:Q.value,label:Q.label}))},value:typeof _=="string"?_:null,error:H,clearable:be,onChange:Q=>Q===null?X(m.id):re(m.id,Q)});case"multi-enum":{const Q=Array.isArray(_)?_[0]??null:null;return e.jsx(Ms,{descriptor:{...Y,options:(m.options??[]).map(Se=>({value:Se.value,label:Se.label}))},value:Q,error:H,clearable:be,onChange:Se=>Se===null?X(m.id):re(m.id,[Se])})}case"text":return e.jsx(vi,{descriptor:Y,value:typeof _=="string"?_:null,error:H,clearable:be,onChange:Q=>Q===null||Q===""?X(m.id):re(m.id,Q)});case"string":default:return e.jsx(xi,{descriptor:Y,value:typeof _=="string"?_:null,error:H,clearable:be,onChange:Q=>Q===null||Q===""?X(m.id):re(m.id,Q)})}},ge=O?.orphaned??[],le=n.useCallback(async m=>{try{const _=await os(s,{[m]:null},r);p(_),d(k("workflowSettings.orphanDeleted","Orphaned value removed"),"success")}catch{d(k("workflowSettings.saveFailed","Failed to save setting values"),"error")}},[s,r,d,k]);return e.jsxs("div",{className:"wf-settings-tabpanel","data-testid":"wf-settings-values",children:[B&&e.jsxs("p",{className:"wf-settings-note wf-settings-note--warn",role:"note","data-testid":"wf-settings-stale-notice",children:[e.jsx(ze,{size:12,"aria-hidden":!0})," ",k("workflowSettings.staleContext","Values shown are for project {{project}} — reopen the editor to edit values for the current project.",{project:r})]}),e.jsx("div",{className:"wf-settings-values-head",children:e.jsxs("button",{className:"wf-settings-save-values",onClick:ye,disabled:!de||w||B,"data-testid":"wf-settings-save-values",children:[e.jsx(lo,{size:13})," ",k("workflowSettings.saveValues","Save values")]})}),l.length===0?e.jsx("p",{className:"wf-settings-empty",children:F?e.jsx(Qa,{label:k("workflowSettings.loading","Loading…")}):k("workflowSettings.noDeclarations","This workflow declares no settings, so there are no values to edit.")}):e.jsx("div",{className:"wf-settings-values-list",children:gi(l).map(({group:m,settings:_})=>{const H=new Set(_.map(Y=>Y.id)),Z=m==="models"?j.filter(Y=>H.has(Y.providerId)&&H.has(Y.modelId)):[],oe=_.filter(Y=>!L.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:k(`workflowSettings.group.${m}`,hi[m])}),Z.map(Y=>ue(Y)),oe.map(Y=>e.jsxs("div",{className:"wf-settings-value-item","data-testid":`wf-settings-value-${Y.id}`,children:[Ce(Y),pe(Y)&&e.jsx("span",{className:"wf-settings-customized","data-testid":`wf-settings-customized-${Y.id}`,children:k("workflowSettings.customized","Customized")})]},Y.id))]},m)})}),ge.length>0&&e.jsxs("div",{className:"wf-settings-orphaned","data-testid":"wf-settings-orphaned",children:[e.jsxs("button",{className:"wf-settings-orphaned-toggle",onClick:()=>N(m=>!m),"aria-expanded":A,children:[A?e.jsx(Ae,{size:13}):e.jsx(Ie,{size:13})," ",k("workflowSettings.orphanedTitle","Orphaned values ({{count}})",{count:ge.length})]}),A&&e.jsxs("div",{className:"wf-settings-orphaned-body",children:[e.jsx("p",{className:"wf-settings-note wf-settings-note--muted",role:"note",children:k("workflowSettings.orphanedNote","These stored values no longer match a current declaration (the setting was retyped or removed). They are ignored by the engine; delete them to clean up.")}),e.jsx("ul",{className:"wf-settings-orphaned-list",children:ge.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:Ei(m.value)}),e.jsx("button",{className:"wf-settings-orphan-delete","aria-label":k("workflowSettings.deleteOrphan","Delete orphaned value"),disabled:B||w,onClick:()=>le(m.id),children:e.jsx(je,{size:12})})]},m.id))})]})]}),l.length>0&&e.jsxs("p",{className:"wf-settings-reset-hint",role:"note",children:[e.jsx(Ks,{size:11,"aria-hidden":!0})," ",k("workflowSettings.clearHint","Use the reset control on a row to clear a value back to its declaration default.")]})]})}function Ts({workflowId:s,settings:l,onChange:r,readOnly:g,projectId:d,addToast:k,initialTab:O}){const{t:p}=Ne("app"),[F,R]=n.useState(()=>O??(l.length>0?"values":"definitions")),D=n.useRef({workflowId:s,projectId:d});D.current.workflowId!==s&&(D.current={workflowId:s,projectId:d});const T=D.current.projectId;return e.jsxs("aside",{className:"wf-settings-panel","data-testid":"wf-settings-panel",children:[e.jsx("header",{className:"wf-settings-panel-header",children:e.jsx("h3",{children:p("workflowSettings.title","Settings")})}),e.jsxs("div",{className:"wf-settings-tabs",role:"tablist",children:[e.jsx("button",{role:"tab","aria-selected":F==="definitions",className:`wf-settings-tab${F==="definitions"?" is-active":""}`,onClick:()=>R("definitions"),"data-testid":"wf-settings-tab-definitions",children:p("workflowSettings.definitionsTab","Definitions")}),e.jsx("button",{role:"tab","aria-selected":F==="values",className:`wf-settings-tab${F==="values"?" is-active":""}`,onClick:()=>R("values"),"data-testid":"wf-settings-tab-values",children:p("workflowSettings.valuesTab","Values")})]}),F==="definitions"?e.jsx(Si,{settings:l,onChange:r,readOnly:g,addToast:k}):e.jsx(Ri,{workflowId:s,settings:l,boundProjectId:T,currentProjectId:d,addToast:k},s)]})}function oa(s,l){return s[l]?.editable?{up:s[l-1]?.editable===!0,down:s[l+1]?.editable===!0}:{up:!1,down:!1}}function sa({row:s,depth:l,selectedNodeId:r,selectedEdgeId:g,onSelectNode:d,onSelectEdge:k,onCreateConnection:O,canReorder:p,onMoveNode:F,canMoveUp:R,canMoveDown:D}){const{t:T}=Ne("app"),C=s.children.length>0,[x,w]=n.useState(l===0),[c,A]=n.useState(!1),N=r===s.id,$=s.connectionTargets??[],b=!!O&&s.editable&&$.length>0,I=!!p&&!!F&&s.editable;return e.jsxs("div",{className:"mobile-wf-node-group",children:[e.jsxs("div",{className:`mobile-wf-node-row${N?" mobile-wf-node-row--selected":""}`,style:{"--mobile-wf-depth":String(l)},"data-testid":`mobile-wf-node-${s.id}`,children:[e.jsxs("button",{type:"button",className:"mobile-wf-node-main",onClick:()=>d(s.id),"aria-current":N?"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(Xa,{size:14,"aria-hidden":!0}):null]}),C||I?e.jsxs("div",{className:"mobile-wf-node-actions",children:[I?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":T("workflowNodes.mobileMoveUp","Move up"),disabled:!R,onClick:()=>F?.(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":T("workflowNodes.mobileMoveDown","Move down"),disabled:!D,onClick:()=>F?.(s.id,"down"),children:e.jsx(en,{size:16,"aria-hidden":!0})})]}):null,C?e.jsx("button",{type:"button",className:"mobile-wf-node-expand","aria-expanded":x,"aria-label":x?T("common.collapse","Collapse"):T("common.expand","Expand"),onClick:()=>w(P=>!P),children:x?e.jsx(Ae,{size:16}):e.jsx(Ie,{size:16})}):null]}):null]}),b?e.jsx("div",{className:"mobile-wf-node-actions mobile-wf-node-actions--connect",style:{"--mobile-wf-depth":String(l)},children:e.jsxs("button",{type:"button",className:"mobile-wf-connect-button","data-testid":`mobile-wf-connect-${s.id}`,"aria-expanded":c,onClick:()=>A(P=>!P),children:[e.jsx(ss,{size:14,"aria-hidden":!0}),e.jsx("span",{children:T("workflowNodes.mobileConnect","Connect")})]})}):null,b&&c?e.jsxs("div",{className:"mobile-wf-connect-picker",style:{"--mobile-wf-depth":String(l)},children:[e.jsx("label",{className:"mobile-wf-connect-label",htmlFor:`mobile-wf-connect-target-${s.id}`,children:T("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:P=>{const S=P.currentTarget.value;S&&(O?.(s.id,S),P.currentTarget.value="",A(!1))},children:[e.jsx("option",{value:"",children:T("workflowNodes.mobileConnectChooseTarget","Choose a target…")}),$.map(P=>e.jsxs("option",{value:P.id,children:[P.label," (",P.kind,")"]},P.id))]})]}):null,(s.columnName||s.outgoing.length>0)&&e.jsxs("div",{className:"mobile-wf-node-meta",style:{"--mobile-wf-depth":String(l)},children:[s.columnName?e.jsx("span",{className:"mobile-wf-column-chip",children:s.columnName}):null,s.outgoing.map(P=>e.jsxs("button",{type:"button",className:`mobile-wf-edge-chip${g===P.id?" mobile-wf-edge-chip--selected":""}`,"data-testid":`mobile-wf-edge-${P.id}`,onClick:()=>k(P.id),children:[e.jsx(ss,{size:12,"aria-hidden":!0}),e.jsx("span",{children:P.label}),e.jsx("span",{className:"mobile-wf-edge-target",children:P.targetLabel})]},P.id))]}),C&&x?e.jsx("div",{className:"mobile-wf-node-children",children:s.children.map((P,S)=>{const W=oa(s.children,S);return e.jsx(sa,{row:P,depth:l+1,selectedNodeId:r,selectedEdgeId:g,onSelectNode:d,onSelectEdge:k,onCreateConnection:O,canReorder:p,onMoveNode:F,canMoveUp:W.up,canMoveDown:W.down},P.id)})}):null]})}function Ii({rows:s,selectedNodeId:l,selectedEdgeId:r,onSelectNode:g,onSelectEdge:d,onCreateConnection:k,canReorder:O,onMoveNode:p}){const{t:F}=Ne("app");return s.length===0?e.jsx("div",{className:"mobile-wf-graph-empty","data-testid":"mobile-wf-graph-empty",children:F("workflowNodes.mobileGraphEmpty","No graph nodes yet.")}):e.jsx("div",{className:"mobile-wf-graph","data-testid":"mobile-wf-graph",children:s.map((R,D)=>{const T=oa(s,D);return e.jsx(sa,{row:R,depth:0,selectedNodeId:l,selectedEdgeId:r,onSelectNode:g,onSelectEdge:d,onCreateConnection:k,canReorder:O,onMoveNode:p,canMoveUp:T.up,canMoveDown:T.down},R.id)})})}function Mi(s){return typeof s.label=="string"&&s.label.trim()?s.label:String(s.data?.condition??"success")}function Ls(s){return s.data.label||s.id}function co(s,l){const r=Math.round(s.position.y),g=Math.round(l.position.y);return r!==g?r-g:Math.round(s.position.x)-Math.round(l.position.x)}function zs(s){return s.data.kind!=="start"&&s.data.kind!=="end"&&!he(s.id)}function Oi(s,l){return he(l.id)?!1:s.parentId||l.parentId?s.parentId===l.parentId:s.data.column===l.data.column}function Di(s,l,r){const g=s.find(p=>p.id===l);if(!g||!zs(g))return s;const d=s.filter(p=>Oi(g,p)).sort(co),k=d.findIndex(p=>p.id===l),O=d[k+(r==="up"?-1:1)];return!O||!zs(O)?s:s.map(p=>p.id===g.id?{...p,position:{...O.position}}:p.id===O.id?{...p,position:{...g.position}}:p)}function Ti(s,l){const r=new Map(s.map(g=>[g.id,g.name||g.id]));for(const g of l){if(!he(g.id))continue;const d=on(g.id);r.has(d)||r.set(d,g.data.label||d)}return r}function Li(s,l,r=[],g={},d){const k=Ti(r,s),O=new Map(s.map(C=>[C.id,C])),p=new Map,F=new Map;for(const C of s){if(!C.parentId)continue;const x=p.get(C.parentId)??[];x.push(C),p.set(C.parentId,x)}for(const C of p.values())C.sort(co);for(const C of l){if(tn(C))continue;const x=F.get(C.source)??[];x.push(C),F.set(C.source,x)}const R=C=>{const x=O.get(C.target);return{id:C.id,source:C.source,target:C.target,targetLabel:x?Ls(x):C.target,label:Mi(C),kind:typeof C.data?.kind=="string"?C.data.kind:void 0}},D=C=>{const x=(p.get(C.id)??[]).map(D),w=C.data.column;return{id:C.id,label:Ls(C),kind:C.data.kind,summary:an(C.data,g,d),columnName:w?k.get(w)??w:void 0,editable:C.data.kind!=="start"&&C.data.kind!=="end"&&!he(C.id),parentId:C.parentId,templateLocalId:C.parentId?sn(C.parentId,C.id):void 0,outgoing:(F.get(C.id)??[]).map(R),children:x}};return s.filter(C=>!C.parentId&&!he(C.id)).sort(co).map(D)}function zi(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 Wi=[{id:"claude-code",name:"Claude Code",tier:"native"},{id:"codex",name:"Codex",tier:"hybrid"},{id:"droid",name:"Droid",tier:"hybrid"},{id:"pi",name:"Pi",tier:"hybrid"},{id:"generic",name:"Generic CLI",tier:"generic"}],We=s=>s.startsWith("builtin:");function Ws(s,l){return s&&l?`${s}/${l}`:""}function $s(s){if(!s)return{provider:"",modelId:""};const l=s.indexOf("/");return l===-1?{provider:"",modelId:""}:{provider:s.slice(0,l),modelId:s.slice(l+1)}}function $i(s){return he(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 _i(s){return he(s.id)?"transparent":"var(--border-strong, var(--border))"}function ao(s,l,r,g,d,k,O,p){const{ir:F,layout:R}=Js(s,g,d,k.length?k:void 0,O.length?O:void 0,p.length?p:void 0);return JSON.stringify({name:s,description:l,icon:r?.trim()||void 0,ir:F,layout:R})}let _s=0;function Bs(){return _s+=1,`n-${Date.now().toString(36)}-${_s}`}const Bi=["step-headings","json-steps"],Gi=["approve","revise","rethink","unavailable"],Gs=["in-review","merged","failed","awaiting-approval","task-created","workflow-notify"],no="__custom",qi="npm test -- --runInBand",Vi='export default async (ctx) => ({ outcome: "success" });',Hi="Task {{taskId}} reached {{workflowName}}",qs=[{kind:"prompt",label:"Prompt",icon:Rn},{kind:"ask-user",label:"Ask user question",icon:ea},{kind:"exit-gate",label:"Exit gate",icon:In},{kind:"script",label:"Script",icon:Mn},{kind:"gate",label:"Gate",icon:Zs},{kind:"merge",label:"Merge boundary",icon:On},{kind:"hold",label:"Hold",icon:Dn,presetConfig:{release:"manual"}},{kind:"split",label:"Split",icon:Tn},{kind:"join",label:"Join",icon:Ln,presetConfig:{mode:"all",onBranchFailure:"collect"}},{kind:"foreach",label:"For-each step",icon:xs,presetConfig:{source:"task-steps"}},{kind:"loop",label:"Loop",icon:xs,presetConfig:{maxIterations:3,exitWhen:{type:"output-contains",value:"DONE"}}},{kind:"optional-group",label:"Optional group",icon:zn,presetConfig:{defaultOn:!1}},{kind:"step-review",label:"Step review",icon:Wn,presetConfig:{type:"code"}},{kind:"parse-steps",label:"Parse steps",icon:Xs,presetConfig:{artifact:"PROMPT.md",parser:"step-headings"}},{kind:"code",label:"Code",icon:$n,presetConfig:{source:""}},{kind:"notify",label:"Notify",icon:_n,presetConfig:{event:"in-review",title:"{{taskTitle}}",message:""}}];function Vs(s){const l={name:s.name,gateMode:s.gateMode??"advisory"};return s.description&&(l.description=s.description),s.mode==="script"?(s.scriptName&&(l.scriptName=s.scriptName),{kind:"script",label:s.name,config:l}):(l.prompt=s.prompt??"",l.toolMode=s.toolMode==="coding"?"coding":"readonly",s.modelProvider&&s.modelId&&(l.modelProvider=s.modelProvider,l.modelId=s.modelId),{kind:"prompt",label:s.name,config:l})}const Ui=new Set(["prompt","script","gate","code","hold","split","join","foreach","loop","optional-group","step-review","parse-steps","notify","merge","ask-user","exit-gate"]);function Ki({workflows:s,onCreate:l,onDesign:r,onClose:g}){const{t:d}=Ne("app"),[k,O]=n.useState(""),[p,F]=n.useState(""),[R,D]=n.useState(""),[T,C]=n.useState(null),[x,w]=n.useState(!1),[c,A]=n.useState(!1),[N,$]=n.useState(""),[b,I]=n.useState(!1),[P,S]=n.useState(null),W=n.useRef(null),[fe,K]=n.useState(!1),J=n.useRef(null),te=n.useRef([]),V=n.useMemo(()=>{const o={id:null,name:d("workflows.templateBlank","Blank"),description:d("workflows.templateBlankDescription","Start from an empty start → end graph."),nodeCount:0,builtin:!1},q=s.filter(le=>le.kind!=="fragment"),ue=le=>({id:le.id,name:le.name,description:le.description??"",icon:le.icon,nodeCount:le.ir.nodes.length,source:le,builtin:We(le.id)}),Ce=q.filter(le=>We(le.id)).map(ue),ge=q.filter(le=>!We(le.id)).map(ue);return[o,...Ce,...ge]},[s,d]),[j,L]=n.useState(0),B=V[j]??V[0];n.useEffect(()=>{J.current?.focus()},[]);const G=n.useCallback(o=>{const q=V[o];q&&(L(o),q.id===null?(fe||O(""),F(""),D("")):(fe||O(d("workflows.templateCopyName","{{name}} copy",{name:q.name})),F(q.description),D(q.builtin||!q.icon?"✨":q.icon)),T&&C(null))},[V,fe,T,d]),se=n.useCallback(o=>{if(o.key==="ArrowDown"||o.key==="ArrowRight"){o.preventDefault();const q=Math.min(j+1,V.length-1);G(q),te.current[q]?.focus()}else if(o.key==="ArrowUp"||o.key==="ArrowLeft"){o.preventDefault();const q=Math.max(j-1,0);G(q),te.current[q]?.focus()}else(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),G(j),J.current?.focus())},[j,V.length,G]),pe=Un(g),re=n.useCallback(async o=>{o.preventDefault();const q=k.trim();if(!q){C(d("workflows.createNameRequired","Enter a workflow name"));return}w(!0),C(null);try{await l(q,p.trim(),R.trim(),B)}catch(ue){C(ae(ue)||d("workflows.createFailed","Failed to create workflow")),w(!1)}},[k,p,R,B,l,d]),X=n.useCallback(async()=>{const o=N.trim();if(!o){S(d("workflows.aiPromptRequired","Describe the workflow you want"));return}const q=new AbortController;W.current=q,I(!0),S(null);try{await r(o,k.trim(),q.signal)}catch(ue){if(q.signal.aborted)return;S(ae(ue)||d("workflows.aiFailed","Failed to design workflow"))}finally{W.current===q&&(W.current=null),I(!1)}},[N,k,r,d]),ie=n.useCallback(()=>{W.current?.abort(),I(!1)},[]),de=V.findIndex(o=>o.id!==null&&o.builtin),ye=V.findIndex(o=>o.id!==null&&!o.builtin);return e.jsx("div",{className:"modal-overlay open wf-create-overlay",...pe,children:e.jsxs("div",{className:"modal wf-create-modal","data-testid":"wf-create-dialog",role:"dialog","aria-modal":"true","aria-label":d("workflows.createTitle","New workflow"),onClick:o=>o.stopPropagation(),onKeyDown:o=>{o.key==="Escape"&&(o.stopPropagation(),g())},children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:d("workflows.createTitle","New workflow")}),e.jsx("button",{type:"button",className:"modal-close",onClick:g,"aria-label":d("actions.close","Close"),children:e.jsx(Qs,{size:16})})]}),e.jsxs("form",{onSubmit:re,children:[e.jsxs("div",{className:"modal-body",children:[e.jsxs("div",{className:"wf-ai-create","aria-busy":b,"data-testid":"wf-ai-create",children:[e.jsxs("button",{type:"button",className:"wf-ai-toggle","data-testid":"wf-ai-toggle","aria-expanded":c,onClick:()=>{A(o=>!o),S(null)},children:[e.jsx(Je,{size:13})," ",d("workflows.aiToggle","Describe it instead")]}),c&&e.jsxs("div",{className:"wf-ai-create-body",children:[e.jsx("textarea",{className:"wf-ai-prompt","data-testid":"wf-ai-prompt",rows:3,value:N,disabled:b,placeholder:d("workflows.aiPromptPlaceholder","e.g. Run lint and tests before merge, then post a changelog comment after merge"),onChange:o=>{$(o.target.value),P&&S(null)}}),P&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-ai-error",children:P}),e.jsxs("div",{className:"wf-ai-actions",children:[e.jsxs("button",{type:"button",className:"btn btn-primary wf-ai-submit","data-testid":"wf-ai-submit",disabled:b,onClick:()=>void X(),children:[b?e.jsx(Me,{size:13,className:"wf-spin"}):e.jsx(Je,{size:13})," ",d("workflows.aiSubmit","Design with AI")]}),b&&e.jsx("button",{type:"button",className:"btn wf-ai-cancel","data-testid":"wf-ai-cancel",onClick:ie,children:d("common.cancel","Cancel")})]})]})]}),e.jsxs("div",{className:"wf-field",children:[e.jsx("span",{id:"wf-template-label",children:d("workflows.templatePickerLabel","Start from")}),e.jsx("div",{className:"wf-template-list",role:"radiogroup","aria-labelledby":"wf-template-label","data-testid":"wf-template-list",children:V.map((o,q)=>{const ue=q===j,Ce=o.id??"blank";return e.jsxs("div",{children:[q===de&&de>=0&&e.jsxs("p",{className:"wf-template-section wf-template-section--icon",children:[e.jsx(Le,{workflowId:"builtin:template-section",decorative:!0}),e.jsx("span",{children:d("workflows.templateSectionBuiltin","Fusion workflows")})]}),q===ye&&ye>=0&&e.jsx("p",{className:"wf-template-section",children:d("workflows.templateSectionYours","Your workflows")}),e.jsxs("div",{ref:ge=>{te.current[q]=ge},role:"radio","aria-checked":ue,tabIndex:ue?0:-1,className:`wf-template-option${ue?" selected":""}`,"data-testid":o.id===null?"wf-template-option-blank":`wf-template-option-${o.id}`,onClick:()=>{G(q),te.current[q]?.focus()},onKeyDown:se,children:[e.jsxs("span",{className:"wf-template-option-heading",children:[e.jsx(Le,{workflowId:o.id??"",icon:o.icon,decorative:!0}),e.jsx("span",{className:"wf-template-option-name",children:o.name})]}),o.description&&e.jsx("span",{className:"wf-template-option-desc",children:o.description}),o.id!==null&&e.jsx("span",{className:"wf-template-option-count",children:d("workflows.templateNodeCount","{{count}} nodes",{count:o.nodeCount})})]})]},Ce)})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:d("workflows.createName","Name")}),e.jsx("input",{ref:J,"data-testid":"wf-create-name",value:k,onChange:o=>{O(o.target.value),K(!0),T&&C(null)}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:d("workflows.iconLabel","Icon (optional)")}),e.jsx("input",{"data-testid":"wf-create-icon",value:R,maxLength:16,placeholder:d("workflows.iconPlaceholder","e.g. 🚀"),onChange:o=>D(o.target.value)})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:d("workflows.createDescription","Description (optional)")}),e.jsx("textarea",{rows:2,"data-testid":"wf-create-description",value:p,onChange:o=>F(o.target.value)})]}),T&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-create-error",children:T})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{type:"button",className:"btn",onClick:g,children:d("common.cancel","Cancel")}),e.jsxs("button",{type:"submit",className:"btn btn-primary","data-testid":"wf-create-submit",disabled:x,children:[x?e.jsx(Me,{size:13,className:"wf-spin"}):null," ",d("workflows.createSubmit","Create")]})]})]})]})})}function Yi({onClose:s,addToast:l,projectId:r,initialPanel:g,initialAction:d,initialWorkflowId:k,modalRef:O,isEmbedded:p=!1}){const[F,R]=n.useState([]),[D,T]=n.useState(null),x=nn()==="mobile",[w,c]=n.useState(()=>as()),[A,N]=n.useState(!1),[$,b]=n.useState(!1),[I,P]=n.useState(null),[S,W,fe]=La([]),[K,J]=za([]),[te,V]=n.useState(null),[j,L]=n.useState(null),[B,G]=n.useState(!1),[se,pe]=n.useState(!1),[re,X]=n.useState(!1),[ie,de]=n.useState(()=>g==="settings"?"settings":"graph"),ye=x||re,{t:o}=Ne("app"),{confirm:q}=ln(),[ue,Ce]=n.useState(d==="create"),ge=n.useRef(null),le=n.useRef(null),[m,_]=n.useState(""),[H,Z]=n.useState(""),[oe,Y]=n.useState(void 0),[be,Q]=n.useState(!1),[Se,Xe]=n.useState(!1),Ze=n.useRef(null),[ee,et]=n.useState([]),[Fe,tt]=n.useState([]),[Re,ot]=n.useState([]),[$e,ft]=n.useState(null),[aa,_e]=n.useState(null),Rt=n.useRef(null),[uo,na]=n.useState([]),[ia,la]=n.useState([...Bi]),[It,ra]=n.useState([]),[Mt,da]=n.useState([]),fo="fusion:wf-templates-collapsed",[Be,ca]=n.useState(()=>{try{const t=localStorage.getItem(fo);return t!=null?t==="1":as()}catch{return!1}}),[pt,po]=n.useState(""),[mt,mo]=n.useState(null),Ot=n.useRef(!1),wo="fusion:wf-left-sidebar-collapsed",ho="fusion:wf-sidebar-columns-collapsed",go="fusion:wf-sidebar-fields-collapsed",bo="fusion:wf-sidebar-settings-collapsed",[st,ko]=n.useState(()=>{try{return localStorage.getItem(wo)==="1"}catch{return!1}}),[at,ua]=n.useState(()=>{try{return localStorage.getItem(ho)==="1"}catch{return!1}}),[nt,fa]=n.useState(()=>{try{return localStorage.getItem(go)==="1"}catch{return!1}}),[it,pa]=n.useState(()=>{try{return localStorage.getItem(bo)==="1"}catch{return!1}});n.useEffect(()=>{try{localStorage.setItem(wo,st?"1":"0")}catch{}},[st]),n.useEffect(()=>{try{localStorage.setItem(ho,at?"1":"0")}catch{}},[at]),n.useEffect(()=>{try{localStorage.setItem(go,nt?"1":"0")}catch{}},[nt]),n.useEffect(()=>{try{localStorage.setItem(bo,it?"1":"0")}catch{}},[it]);const{setViewport:xo}=Wa(),Dt=n.useRef(null),[vo,Tt]=n.useState(null),[jo,No]=n.useState([]),[yo,Co]=n.useState(!1),wt=n.useRef(null),[Lt,zt]=n.useState(!1),[ht,Wt]=n.useState(""),[ke,$t]=n.useState(!1),[Ge,qe]=n.useState(null),gt=n.useRef(null),y=n.useMemo(()=>F.find(t=>t.id===D),[F,D]),z=!!y&&We(y.id),So=y?.lifecycleWarnings??[],Eo=n.useRef(D);Eo.current=D;const ma=n.useMemo(()=>!y||z?!1:!S.some(t=>Ui.has(t.data.kind)),[y,z,S]),Ao=!0;n.useEffect(()=>{let t=!1;return Us(r).then(a=>{t||na(a)}).catch(()=>{}),()=>{t=!0}},[r]),n.useEffect(()=>{let t=!1;return rn(r).then(a=>{!t&&a.length>0&&la(a)}).catch(()=>{}),()=>{t=!0}},[r]),n.useEffect(()=>{let t=!1;return dn().then(a=>{t||ra(a.templates??[])}).catch(()=>{}),cn().then(a=>{t||da(a.templates??[])}).catch(()=>{}),()=>{t=!0}},[]),n.useEffect(()=>{try{localStorage.setItem(fo,Be?"1":"0")}catch{}},[Be]),n.useEffect(()=>{te&&G(!1)},[te]),n.useEffect(()=>{g==="settings"&&de("settings")},[g]);const _t=n.useMemo(()=>F.filter(t=>t.kind==="fragment"),[F]),me=n.useMemo(()=>{const t=pt.trim().toLowerCase(),a=v=>!t||v.toLowerCase().includes(t),i=(v,U)=>v.name.localeCompare(U.name),u=[..._t].sort(i).filter(v=>a(v.name)),h=[...It].sort(i).filter(v=>a(v.name)),E=[...Mt].sort((v,U)=>v.template.name.localeCompare(U.template.name)).filter(v=>a(v.template.name));return{fragmentEntries:u,stepEntries:h,pluginEntries:E}},[_t,It,Mt,pt]),Bt=_t.length+It.length+Mt.length,Po=Bt>0,Gt=n.useMemo(()=>ee.length?un(ee,uo):[],[ee,uo]),Oe=n.useMemo(()=>fn(S,ee),[S,ee]),Fo=Gt.filter(t=>t.severity==="error").length,lt=n.useMemo(()=>z||!y||Ze.current===null?!1:ao(m,H,oe,S,K,ee,Fe,Re)!==Ze.current,[z,y,m,H,oe,S,K,ee,Fe,Re]),Ve=n.useCallback(async t=>{N(!0);try{const a=await pn(r,t);R(a),T(i=>i&&a.some(u=>u.id===i)?i:d!=="create"&&k&&a.some(u=>u.id===k)?k:x?null:a[0]?.id??null)}catch(a){l(ae(a)||o("workflows.loadFailed","Failed to load workflows"),"error")}finally{N(!1)}},[r,l,x,d,k,o]);n.useEffect(()=>{Ve()},[Ve]),n.useEffect(()=>{const t=r?`?projectId=${encodeURIComponent(r)}`:"",a=()=>{Ve({forceFresh:!0})};return mn(`/api/events${t}`,{events:{"workflow:created":a,"workflow:updated":a,"workflow:deleted":a}})},[Ve,r]),n.useEffect(()=>{!k||!x||!w||D===k&&le.current!==k&&(le.current=k,c(!1))},[D,k,x,w]);const bt=n.useCallback(async()=>{if(y)try{await wn(y.id,r)}catch(t){l(ae(t)||o("workflows.exportFailed","Failed to export workflow"),"error")}},[y,r,l,o]),wa=n.useCallback(async t=>{const a=t.target.files?.[0];if(wt.current&&(wt.current.value=""),!!a){Tt(null),No([]),Co(!0);try{const i=await a.text();let u;try{u=JSON.parse(i)}catch{Tt(o("workflows.importInvalidJson","That file isn't valid JSON."));return}const h=await hn(u,r);await Ve(),T(h.workflow.id),c(!1),l(o("workflows.imported",'Imported workflow "{{name}}"',{name:h.workflow.name}),"success"),h.strippedApprovalFlags&&l(o("workflows.importStripped","Auto-approval flags were removed from imported nodes"),"warning"),h.warnings.length>0&&No(h.warnings)}catch(i){i instanceof Ys&&i.status>=400&&i.status<500?Tt(ae(i)||o("workflows.importFailed","Import failed")):l(ae(i)||o("workflows.importFailed","Import failed"),"error")}finally{Co(!1)}}},[r,Ve,l,o]);n.useEffect(()=>{if(Ot.current=!1,!y){W([]),J([]),et([]),tt([]),ot([]),ft(null),_e(null),_(""),Z(""),Y(void 0),Ze.current=null;return}const t=ns(y),a=is(y),i=ls(y),u=rs(y),h=Ss(t.nodes,t.edges,a),E=Es(t.nodes,h);W(E),J(t.edges),et(a),tt(i),ot(u),_(y.name),Z(y.description??""),Y(y.icon),Q(!1),Xe(!1),Ze.current=ao(y.name,y.description??"",y.icon,E,t.edges,a,i,u),V(null),L(null),P(null),xo({x:0,y:0,zoom:1},{duration:0})},[y,W,J,xo]),n.useEffect(()=>{S.length>0&&(Ot.current=!0)},[S]),n.useEffect(()=>{if(!y||!z){ft(null),_e(null);return}let t=!1;return ds(y.id,r).then(a=>{t||(ft(a),W(i=>i.map(u=>{if(u.data.kind!=="prompt"&&u.data.kind!=="gate")return u;const h=a.effective[u.id];return h===void 0?u:{...u,data:{...u.data,config:{...u.data.config??{},prompt:h}}}})))}).catch(a=>{t||l(ae(a)||o("workflowEditor.promptOverridesLoadFailed","Failed to load prompt overrides"),"error")}),()=>{t=!0}},[y,z,r,l,o,W]);const qt=n.useRef(!1);n.useEffect(()=>{if(g!=="settings"||qt.current||!y)return;const t=Rt.current;t&&(qt.current=!0,t.scrollIntoView({behavior:"smooth",inline:"end",block:"nearest"}))},[g,y]),n.useEffect(()=>()=>{qt.current=!1},[g]);const[Vt,Ro]=n.useState(null);n.useEffect(()=>{W(t=>{const a=t.filter(i=>!he(i.id)&&i.type!=="group");return[...gn(ee),...bn(a,ee)]})},[ee,W]);const kt=n.useCallback((t,a={})=>{const i=kn(t,K,S);if("error"in i){i.error==="cycle"?l(o("workflowNodes.cycleBlocked","That connection would create a cycle — only rework edges inside a for-each template may loop back"),"warning"):i.error==="duplicate"?l(o("workflowNodes.duplicateBlocked","That connection already exists"),"warning"):i.error==="reserved-handle"&&l(o("workflowNodes.reservedHandleBlocked","Optional-block boundary guides cannot be connected manually"),"warning");return}J(u=>{const h=ut(S,[...u,i.edge]);return W(h.nodes),h.edges}),a.selectCreatedEdge&&(L(i.edge.id),V(null),G(!1))},[K,S,J,W,l,o]),ha=n.useCallback(t=>{J(a=>{const i=$a(t,a),u=ut(S,i);return W(u.nodes),u.edges})},[S,J,W]),ga=n.useCallback(t=>{kt(t)},[kt]),ba=n.useCallback((t,a)=>{kt({source:t,target:a,sourceHandle:null,targetHandle:null},{selectCreatedEdge:!0})},[kt]),ka=n.useCallback((t,a)=>{W(i=>Di(i,t,a))},[W]),xa=n.useCallback((t,a)=>{if(he(a.id)||ee.length===0)return;const i=io(a.position.y,ee);i&&W(u=>u.map(h=>h.id===a.id?{...h,data:{...h.data,column:i}}:h))},[ee,W]),xt=n.useCallback((t,a,i)=>{const u=Bs(),h=a??(t==="merge"?"Merge boundary":t.charAt(0).toUpperCase()+t.slice(1)),E=t==="gate"?{gateMode:"gate"}:{},v=i?{...E,...i}:E;if(t==="foreach"||t==="loop"||t==="optional-group"){const U=xn(u,Bs()),ce=t==="foreach"?o("workflowNodes.stepExecuteLabel","Step execute"):t==="optional-group"?o("workflowNodes.optionalGroupStepLabel","Optional step"):o("workflowNodes.loopStepLabel","Loop step"),ne=t==="foreach"?{seam:"step-execute"}:{prompt:""};W(Ye=>{const ct=[...Ye,{id:u,type:t,position:{x:200+Ye.length*40,y:240+Ye.length%3*70},data:{kind:t,label:h,config:v,templateEmpty:!1},style:{width:jn,height:vn},deletable:!0},{id:U,type:"prompt",position:{x:yn,y:Nn},parentId:u,extent:"parent",data:{kind:"prompt",label:ce,config:ne},deletable:!0}],ts=ut(ct,K);return J(ts.edges),ts.nodes}),V(u);return}W(U=>[...U,{id:u,type:t,position:{x:200+U.length*40,y:240+U.length%3*70},data:{kind:t,label:h,config:v},deletable:!0}]),V(u)},[K,J,W,o]),vt=n.useCallback(t=>{if(z)return;const{kind:a,label:i,config:u}=Vs(t);xt(a,i,u)},[z,xt]),Io=n.useCallback(t=>{if(z)return;const{kind:a,config:i}=Vs(t),u=Cn({kind:a,config:i},{name:t.name,defaultOn:t.defaultOn??!1}),h=cs(S,K,u,{x:240,y:200+S.length%4*40});W(h.nodes),J(h.edges),V(h.insertedNodeIds[0]??null)},[z,S,K,W,J]),Mo=n.useCallback(t=>{if(z)return!1;const a=Ot.current?void 0:y?.ir,i=Sn(t.ir,S,a);if(i.length>0)return mo(i.join(", ")),!1;mo(null);const u=cs(S,K,t.ir,{x:240,y:200+S.length%4*40},t.layout);return W(u.nodes),J(u.edges),V(u.insertedNodeIds[0]??null),!0},[z,S,K,y,W,J]),Oo=n.useCallback(()=>{W(t=>Es(t,Ss(t,K,ee)))},[W,K,ee]),Do=n.useCallback(async()=>{if(!y||z)return;const t=ht.trim();if(!t){qe(o("workflows.aiPromptRequired","Describe the workflow you want"));return}const a=new AbortController;gt.current=a;const i=y;$t(!0),qe(null);try{const u=await us({prompt:t,workflowId:i.id},r,a.signal);if(Eo.current!==i.id){l(o("workflows.aiStaleDiscarded","Discarded AI design — you switched workflows"),"warning");return}if(!await q({title:o("workflows.aiReplaceTitle","Replace graph?"),message:o("workflows.aiReplaceConfirm","Replace the current graph with the AI design? Unsaved changes will be lost."),confirmLabel:o("workflows.aiReplaceConfirmLabel","Replace"),danger:!0}))return;const E=ns({...i,ir:u.ir,layout:u.layout});W(E.nodes),J(E.edges),et(is({...i,ir:u.ir})),tt(ls({...i,ir:u.ir})),ot(rs({...i,ir:u.ir})),V(null),L(null),P(null),u.strippedApprovalFlags&&l(o("workflows.importStripped","Auto-approval flags were removed from imported nodes"),"warning"),zt(!1),Wt("")}catch(u){if(a.signal.aborted)return;qe(ae(u)||o("workflows.aiFailed","Failed to design workflow"))}finally{gt.current===a&&(gt.current=null),$t(!1)}},[y,z,ht,r,q,o,W,J,l]),To=n.useCallback(()=>{gt.current?.abort(),$t(!1)},[]),M=n.useCallback(t=>{te&&W(a=>a.map(i=>i.id===te?{...i,data:{...i.data,..."config"in t?{config:typeof t.config=="function"?t.config(i.data.config??{}):{...i.data.config??{},...t.config}}:t}}:i))},[te,W]),rt=n.useCallback((t,a)=>{ft(a);const i=a.effective[t]??a.defaults[t]??"";W(u=>u.map(h=>h.id===t?{...h,data:{...h.data,config:{...h.data.config??{},prompt:i}}}:h))},[W]),Lo=n.useCallback(async(t,a)=>{if(!(!y||!z)){_e(t);try{const i=await fs(y.id,{[t]:a},r);rt(t,i),l(o("workflowEditor.promptOverrideSaved","Prompt override saved"),"success")}catch(i){l(ae(i)||o("workflowEditor.promptOverrideSaveFailed","Failed to save prompt override"),"error");try{const u=await ds(y.id,r);rt(t,u)}catch{}}finally{_e(i=>i===t?null:i)}}},[y,z,r,l,o,rt]),zo=n.useCallback(async t=>{if(!(!y||!z)){_e(t);try{const a=await fs(y.id,{[t]:null},r);rt(t,a),l(o("workflowEditor.promptOverrideReset","Prompt reset to default"),"success")}catch(a){l(ae(a)||o("workflowEditor.promptOverrideResetFailed","Failed to reset prompt"),"error")}finally{_e(a=>a===t?null:a)}}},[y,z,r,l,o,rt]),Ht=n.useCallback(t=>{j&&J(a=>{const i=a.map(h=>{if(h.id!==j)return h;const E=t.condition??h.data?.condition??"success",v=t.rework??h.data?.kind==="rework";return{...h,label:v?`${ps(E)} (rework)`:ps(E),data:{...h.data??{},condition:E,kind:v?"rework":void 0},type:v?"step":void 0,animated:v,className:En(E,v)}}),u=ut(S,i);return W(u.nodes),u.edges})},[S,j,J,W]),Wo=n.useCallback(t=>{const a=new Set(t);let i=null;W(u=>{const h=ms(u,K,a);return i=ut(h.nodes,h.edges),i.nodes}),i&&J(i.edges),te!==null&&a.has(te)&&V(null),j!==null&&a.has(j)&&L(null)},[K,W,J,te,j]),va=n.useCallback(async({nodes:t,edges:a})=>{if(z)return!1;const i=new Set([...t.map(v=>v.id),...a.map(v=>v.id)]),u=ms(S,K,i),h=new Set(S.map(v=>v.id));for(const v of u.nodes)h.delete(v.id);const E=new Set(K.map(v=>v.id));for(const v of u.edges)E.delete(v.id);return h.size===0&&E.size===0?!1:{nodes:S.filter(v=>h.has(v.id)),edges:K.filter(v=>E.has(v.id))}},[z,S,K]),ja=n.useCallback(()=>{V(null),Dt.current?.focus()},[]),Na=n.useCallback(()=>{L(null),Dt.current?.focus()},[]),dt=n.useCallback(()=>{Ce(!1),ge.current?.focus()},[]),ya=n.useCallback(async(t,a,i,u)=>{const h=u.source!==void 0?An(u.source.ir,u.source.layout):{ir:Yn(t),layout:Kn()},E=await eo({name:t,description:a||void 0,icon:i||void 0,kind:"workflow",ir:h.ir,layout:h.layout},r);R(v=>[...v,E]),T(E.id),c(!1),l(o("workflows.created",'Created workflow "{{name}}"',{name:E.name}),"success"),dt()},[r,l,o,dt]),Ca=n.useCallback(async(t,a,i)=>{const u=await us({prompt:t},r,i),h=`AI: ${t.slice(0,30)}`,v=await eo({name:a||h,kind:"workflow",ir:u.ir,layout:u.layout},r);R(U=>[...U,v]),T(v.id),c(!1),l(o("workflows.created",'Created workflow "{{name}}"',{name:v.name}),"success"),u.strippedApprovalFlags&&l(o("workflows.importStripped","Auto-approval flags were removed from imported nodes"),"warning"),dt()},[r,l,o,dt]),$o=n.useCallback(async()=>{if(!(!y||We(y.id)||!await q({title:o("workflows.deleteTitle","Delete workflow?"),message:o("workflows.deleteMessage",'Delete workflow "{{name}}"? This cannot be undone.',{name:y.name}),confirmLabel:o("common.delete","Delete"),danger:!0})))try{await Pn(y.id,r),R(a=>a.filter(i=>i.id!==y.id)),T(null),x&&c(!0),l(o("workflows.deleted","Workflow deleted"),"success")}catch(a){l(ae(a)||o("workflows.deleteFailed","Failed to delete workflow"),"error")}},[y,r,l,q,o,x]),_o=n.useCallback(async()=>{if(y)try{const t=await eo({name:`${y.name} (copy)`,description:y.description,icon:We(y.id)||!y.icon?"✨":y.icon,ir:y.ir,layout:y.layout},r);R(a=>[...a,t]),T(t.id),c(!1),l(o("workflows.duplicatedEditable",'Duplicated to "{{name}}" — editable',{name:t.name}),"success")}catch(t){l(ae(t)||o("workflows.duplicateFailed","Failed to duplicate workflow"),"error")}},[y,r,l,o]),Bo=n.useCallback(async()=>{if(y&&!We(y.id)){if(Oe.length>0){const t=o("workflowColumns.unplacedCount","{{count}} nodes not placed in a column",{count:Oe.length});P(t),l(t,"error");return}if(Fo>0){const t=o("workflowColumns.compositionBlocked","Resolve trait conflicts on highlighted columns before saving");P(t),l(t,"error");return}b(!0),P(null),Ro(null);try{const t=m.trim()||y.name,{ir:a,layout:i}=Js(t,S,K,ee.length?ee:void 0,Fe.length?Fe:void 0,Re.length?Re:void 0),u=t!==y.name,h=H!==(y.description??""),E=oe?.trim()||void 0,v=E!==y.icon,U=async ne=>{R(Ye=>Ye.map(ct=>ct.id===ne.id?ne:ct)),Ze.current=ao(ne.name,ne.description??"",ne.icon,S,K,ee,Fe,Re),_(ne.name),Z(ne.description??""),Y(ne.icon),l(o("workflows.saved","Workflow saved"),"success")},ce={ir:a,layout:i,...u?{name:t}:{},...h?{description:H}:{},...v?{icon:E??null}:{}};try{await U(await ws(y.id,ce,r))}catch(ne){if(!(ne?.details?.policyEscalation===!0))throw ne;if(!window.confirm(`${ae(ne)}
7
+
8
+ ${o("workflowColumns.confirmPolicyEscalation","Bind it anyway? The column agent will run with broader permissions than this project's default.")}`)){l(o("workflowColumns.escalationDeclined","Save cancelled — column agent binding not confirmed"),"error");return}await U(await ws(y.id,{...ce,confirmPolicyEscalation:!0},r))}}catch(t){const a=ae(t)||o("workflows.saveFailed","Failed to save workflow"),i=/node '([^']+)'/.exec(a);i&&S.some(u=>u.id===i[1])&&Ro({nodeId:i[1],message:a}),P(a),l(a,"error")}finally{b(!1)}}},[y,m,H,S,K,ee,Fe,Re,Oe,Fo,r,l,o]),He=n.useMemo(()=>{const t=new Set(Oe),a=new Map;for(const i of S)i.parentId&&a.set(i.parentId,(a.get(i.parentId)??0)+1);return S.map(i=>{let u;t.has(i.id)&&(u=o("workflowColumns.nodeUnplaced","Not placed in a column")),Vt?.nodeId===i.id&&(u=Vt.message);const h=i.data.kind==="foreach"||i.data.kind==="loop"||i.data.kind==="optional-group",E=i.data.kind==="loop"?o("workflowNodes.loopEmptyHint","Drag loop steps here"):i.data.kind==="optional-group"?o("workflowNodes.optionalGroupEmptyHint","Drag optional steps here"):o("workflowNodes.foreachEmptyHint","Drag a step-execute node here"),v=h?(a.get(i.id)??0)===0:void 0;return u===i.data.errorBadge&&(!h||v===i.data.templateEmpty&&i.data.emptyHint===E)?i:{...i,data:{...i.data,errorBadge:u,...h?{templateEmpty:v,emptyHint:E}:{}}}})},[S,Oe,Vt,o]),f=S.find(t=>t.id===te)??null,Go=f!==null&&f.data.kind!=="end",Ee=f!==null?oi(f.data):null,xe=K.find(t=>t.id===j)??null,Sa=x&&Go&&!B,Ea=x&&xe!==null,[Ut,qo]=n.useState(!1),Vo=n.useCallback(()=>{qo(t=>!t)},[]),Aa=n.useCallback(t=>{!Ut||t.key!=="Escape"||(t.preventDefault(),t.stopPropagation(),qo(!1))},[Ut]),Ue=f&&(f.data.kind==="prompt"||f.data.kind==="gate")?String(f.data.config?.prompt??$e?.effective[f.id]??(z?zi(f.data.config):"")):"",Kt=f?$e?.defaults[f.id]:void 0,Ho=f?$e?.stored[f.id]:void 0,Yt=Ho!==void 0,Uo=Yt&&Kt!==void 0&&Ho!==Kt,jt=!!f&&aa===f.id,Nt=!!f&&(f.data.kind==="prompt"||f.data.kind==="gate")&&(!z||Kt!==void 0),Ko=n.useCallback(t=>{Nt&&M({config:{prompt:t}})},[Nt,M]),Yo=n.useCallback(()=>{if(!z||!f||f.data.kind!=="prompt"&&f.data.kind!=="gate")return;const t=$e?.stored[f.id],a=$e?.defaults[f.id],i=Ue.trim()?Ue:"";t===void 0&&(a===void 0||i===a)||t===i||Lo(f.id,Ue)},[z,f,Ue,$e,Lo]),Jo=n.useCallback(()=>{f&&zo(f.id)},[f,zo]),Qo=n.useMemo(()=>{if(!xe)return"readonly";const t=S.find(a=>a.id===xe.source);return Fn(t?.data.kind)},[xe,S]),Jt=n.useMemo(()=>{const t=y?.ir;return t&&t.version==="v2"&&Array.isArray(t.artifacts)?t.artifacts.map(a=>a.key):[]},[y]),[De,Qt]=n.useState([]),[ve,yt]=n.useState([]);n.useEffect(()=>{yt([])},[r]);const[Ke,Xo]=n.useState([]),[Pa,Fa]=n.useState(Wi);n.useEffect(()=>{let t=!1;return Promise.resolve(Pt()).then(a=>{!t&&a?.models&&Qt(a.models)}).catch(()=>{}),Promise.resolve(At()).then(a=>{!t&&Array.isArray(a)&&yt(a)}).catch(()=>{}),Promise.resolve(hs(r)).then(a=>{!t&&Array.isArray(a)&&Xo(a)}).catch(()=>{}),()=>{t=!0}},[r]);const Xt=n.useMemo(()=>({models:De.map(t=>({provider:t.provider,id:t.id,name:t.name})),agents:ve.map(t=>({id:t.id,name:t.name})),skills:Ke.map(t=>({id:t.id,name:t.name}))}),[De,ve,Ke]),Zo=n.useMemo(()=>{const t=He.filter(i=>!he(i.id)&&i.data.kind!=="start").map(i=>({id:i.id,label:i.data.label||i.id,kind:i.data.kind})),a=new Map;for(const i of He){if(he(i.id)||i.data.kind==="start"||i.data.kind==="end")continue;const u=t.filter(h=>h.id!==i.id);u.length>0&&a.set(i.id,u)}return a},[He]),Ra=n.useMemo(()=>{const t=a=>a.map(i=>({...i,connectionTargets:z?[]:Zo.get(i.id)??[],children:t(i.children)}));return t(Li(He,K,ee,Xt,o))},[He,K,ee,Xt,o,z,Zo]),we=f?.data.config?.executor??"model",Te=n.useMemo(()=>{const t=f?.data.column??(f?.parentId?S.find(i=>i.id===f.parentId)?.data.column:void 0);if(!t)return;const a=ee.find(i=>i.id===t);if(!(!a?.agent||a.agent.mode!=="override"))return a.agent},[f?.data.column,f?.parentId,S,ee]),Ia=n.useMemo(()=>Te?ve.find(t=>t.id===Te.agentId):void 0,[Te,ve]);n.useEffect(()=>{if(we!=="cli-agent")return;let t=!1;return fetch("/api/cli-agents").then(a=>a.ok?a.json():null).then(a=>{t||!a?.adapters||Fa(a.adapters)}).catch(()=>{}),()=>{t=!0}},[we]),n.useEffect(()=>{if(f?.data.kind==="step-review"&&De.length===0){Pt().then(t=>Qt(t.models)).catch(t=>{l(ae(t)||o("workflowEditor.modelsLoadFailed","Failed to load models"),"error")});return}!f||f.data.kind!=="prompt"&&f.data.kind!=="gate"||(we==="model"&&De.length===0?Pt().then(t=>Qt(t.models)).catch(t=>{l(ae(t)||o("workflowEditor.modelsLoadFailed","Failed to load models"),"error")}):we==="agent"&&ve.length===0?At(void 0,r).then(yt).catch(t=>{l(ae(t)||o("workflowEditor.agentsLoadFailed","Failed to load agents"),"error")}):we==="skill"&&Ke.length===0&&hs(r).then(Xo).catch(t=>{l(ae(t)||o("workflowEditor.skillsLoadFailed","Failed to load skills"),"error")}))},[we,f?.id,f?.data.kind,r,l,De.length,ve.length,Ke.length,o]);const Ct=n.useCallback(t=>{if(!lt){t();return}q({title:o("workflows.discardTitle","Discard unsaved changes?"),message:o("workflows.discardMessage","You have unsaved changes to this workflow. Discard them?"),confirmLabel:o("workflows.discardConfirm","Discard"),danger:!0}).then(a=>{a&&t()})},[lt,q,o]),Zt=n.useCallback(()=>{Ct(s)},[Ct,s]),Ma=n.useCallback(t=>{if(t===D){c(!1);return}Ct(()=>{T(t),c(!1)})},[Ct,D]);n.useEffect(()=>{if(!Te||ve.length>0)return;let t=!1;return Promise.resolve(At(void 0,r)).then(a=>{t||yt(a??[])}).catch(a=>{t||l(ae(a)||o("workflowEditor.agentsLoadFailed","Failed to load agents"),"error")}),()=>{t=!0}},[Te,ve.length,r,l,o]);const Oa=Ut&&(f?.data.kind==="prompt"||f?.data.kind==="gate")?Da.createPortal(e.jsxs("div",{className:"wf-prompt-editor wf-prompt-editor--fullscreen",onKeyDown:Aa,children:[e.jsxs("div",{className:"wf-prompt-fullscreen-header",children:[e.jsx("span",{children:o("workflowEditor.editingPrompt","Editing Prompt")}),e.jsx("button",{type:"button",className:"btn btn-sm wf-prompt-expand-btn",onClick:Vo,"aria-label":o("workflowEditor.collapsePrompt","Collapse prompt editor"),title:o("workflowEditor.collapsePrompt","Collapse prompt editor"),children:e.jsx(gs,{size:14})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.prompt","Prompt")}),e.jsx("textarea",{rows:void 0,value:Ue,readOnly:!Nt,onChange:t=>Ko(t.target.value),onBlur:Yo,autoFocus:!0})]}),z?e.jsxs("div",{className:"wf-prompt-override-actions wf-prompt-override-actions--fullscreen",children:[Uo?e.jsx("span",{className:"wf-prompt-override-badge","data-testid":"wf-prompt-overridden",children:o("workflowEditor.promptOverridden","Overridden")}):null,e.jsx("button",{type:"button",className:"btn btn-sm",onClick:Jo,disabled:!Yt||jt,children:jt?o("workflowEditor.promptSaving","Saving…"):o("workflowEditor.resetPromptDefault","Reset to default")})]}):null]}),document.body):null,es=e.jsxs("div",{className:`modal wf-editor-modal${p?" wf-editor-modal--embedded":""}`,ref:O,onClick:t=>t.stopPropagation(),onKeyDown:t=>{if(t.key!=="Escape"||p||ue)return;const i=t.target.tagName;i==="INPUT"||i==="TEXTAREA"||i==="SELECT"||(t.stopPropagation(),Zt())},children:[e.jsxs("header",{className:"wf-editor-header",children:[e.jsxs("h2",{children:[e.jsx(bs,{size:20,"aria-hidden":"true"}),e.jsx("span",{children:o("workflows.title","Workflows")})]}),p?null:e.jsx("button",{className:"wf-editor-close",onClick:Zt,"aria-label":o("workflows.closeEditor","Close workflow editor"),children:e.jsx(Qs,{size:18})})]}),e.jsxs("div",{className:`wf-editor-body${w?" wf-editor-body--list-stage":" wf-editor-body--editor-stage"}${ye?" wf-editor-body--simple-layout":""}${Sa?" wf-editor-body--mobile-node-detail":""}${Ea?" wf-editor-body--mobile-edge-detail":""}${st?" wf-editor-body--sidebar-collapsed":""}`,children:[e.jsxs("aside",{className:"wf-editor-sidebar",children:[e.jsxs("div",{className:"wf-editor-sidebar-head",children:[e.jsxs("button",{className:"wf-editor-new",ref:ge,"data-testid":"wf-new-workflow",onClick:()=>Ce(!0),children:[e.jsx(Pe,{size:14})," ",o("workflows.newWorkflow","New workflow")]}),!x&&e.jsx("button",{type:"button",className:"wf-sidebar-shell-toggle","data-testid":"wf-sidebar-collapse","aria-expanded":!st,"aria-label":o("workflows.collapseSidebar","Collapse workflow sidebar"),title:o("workflows.collapseSidebar","Collapse workflow sidebar"),onClick:()=>ko(!0),children:e.jsx(ks,{size:14,"aria-hidden":!0})})]}),e.jsxs("button",{type:"button",className:"wf-editor-import","data-testid":"wf-import",disabled:yo,onClick:()=>wt.current?.click(),title:o("workflows.importTooltip","Import a workflow from a JSON file"),children:[yo?e.jsx(Me,{size:14,className:"wf-spin"}):e.jsx(Jn,{size:14})," ",o("workflows.import","Import")]}),e.jsx("input",{ref:wt,type:"file",accept:".json",className:"wf-editor-import-input","data-testid":"wf-import-input",style:{display:"none"},onChange:wa}),vo&&e.jsx("div",{className:"wf-editor-import-error",role:"alert","data-testid":"wf-import-error",children:vo}),jo.length>0&&e.jsx("div",{className:"wf-editor-import-warnings","data-testid":"wf-import-warnings",children:jo.map((t,a)=>e.jsx("p",{className:"wf-editor-import-warning",children:t},a))}),x&&F.length>0&&!y?e.jsx("div",{className:"wf-editor-select-note","data-testid":"wf-mobile-select-note",children:o("workflows.mobileSelectNote","Select a workflow to edit.")}):null,A?e.jsxs("div",{className:"wf-editor-empty",children:[e.jsx(Me,{size:16,className:"wf-spin"})," ",o("workflows.loading","Loading…")]}):F.length===0?e.jsx("div",{className:"wf-editor-empty",children:o("workflows.noneYet","No workflows yet.")}):e.jsx("ul",{className:"wf-editor-list",children:F.map(t=>e.jsx("li",{children:e.jsx("button",{className:`wf-editor-list-item${t.id===D?" active":""}`,onClick:()=>Ma(t.id),children:t.name})},t.id))}),y&&!ye&&e.jsxs("div",{className:"wf-sidebar-panels",children:[e.jsxs("section",{className:"wf-sidebar-section","data-testid":"wf-sidebar-columns-section",children:[e.jsxs("button",{type:"button",className:"wf-sidebar-section-toggle","aria-expanded":!at,"data-testid":"wf-sidebar-columns-toggle",onClick:()=>ua(t=>!t),children:[at?e.jsx(Ie,{size:13}):e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowColumns.title","Columns")})]}),!at&&e.jsx(Ps,{columns:ee,onChange:et,violations:Gt,readOnly:z,projectId:r,addToast:l,columnAgentsEnabled:Ao})]}),e.jsxs("section",{className:"wf-sidebar-section","data-testid":"wf-sidebar-fields-section",children:[e.jsxs("button",{type:"button",className:"wf-sidebar-section-toggle","aria-expanded":!nt,"data-testid":"wf-sidebar-fields-toggle",onClick:()=>fa(t=>!t),children:[nt?e.jsx(Ie,{size:13}):e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowFields.title","Fields")})]}),!nt&&e.jsx(Is,{fields:Fe,onChange:tt,readOnly:z,addToast:l})]}),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":!it,"data-testid":"wf-sidebar-settings-toggle",onClick:()=>pa(t=>!t),children:[it?e.jsx(Ie,{size:13}):e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowSettings.title","Settings")})]}),!it&&e.jsx("div",{ref:Rt,className:"wf-settings-panel-wrap",children:e.jsx(Ts,{workflowId:y.id,settings:Re,onChange:ot,readOnly:z,projectId:r,addToast:l,initialTab:"values"})})]})]})]}),e.jsxs("section",{className:"wf-editor-canvas-wrap",children:[e.jsxs("button",{type:"button",className:"wf-editor-mobile-back",onClick:()=>c(!0),"aria-label":o("workflows.backToWorkflowList","Back to workflows"),children:[e.jsx(ks,{size:16}),e.jsx("span",{children:o("common.back","Back")})]}),y?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"wf-name-strip",children:[st&&!x&&e.jsx("button",{type:"button",className:"wf-sidebar-shell-restore","data-testid":"wf-sidebar-restore","aria-expanded":"false","aria-label":o("workflows.showSidebar","Show workflow sidebar"),title:o("workflows.showSidebar","Show workflow sidebar"),onClick:()=>ko(!1),children:e.jsx(Ie,{size:14,"aria-hidden":!0})}),e.jsx(Le,{workflowId:y.id,icon:oe,decorative:!0}),z?e.jsx("span",{className:"wf-workflow-name wf-workflow-name--readonly","data-testid":"wf-workflow-name",children:y.name}):be?e.jsx("input",{className:"wf-workflow-name-input","data-testid":"wf-workflow-name-input",autoFocus:!0,value:m,"aria-label":o("workflows.nameLabel","Workflow name"),onChange:t=>_(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),m.trim()||_(y.name),Q(!1)):t.key==="Escape"&&(t.preventDefault(),_(y.name),Q(!1))},onBlur:()=>{m.trim()||_(y.name),Q(!1)}}):e.jsx("button",{type:"button",className:"wf-workflow-name","data-testid":"wf-workflow-name",onClick:()=>Q(!0),title:o("workflows.clickToRename","Click to rename"),children:m||y.name}),z?null:e.jsx("input",{className:"wf-workflow-icon-input","data-testid":"wf-workflow-icon-input",value:oe??"",maxLength:16,"aria-label":o("workflows.iconLabel","Icon (optional)"),placeholder:o("workflows.iconPlaceholder","e.g. 🚀"),onChange:t=>Y(t.target.value)}),z?y.description?e.jsx("span",{className:"wf-workflow-description wf-workflow-description--readonly","data-testid":"wf-workflow-description",children:y.description}):null:Se?e.jsx("input",{className:"wf-workflow-description-input","data-testid":"wf-workflow-description-input",autoFocus:!0,value:H,"aria-label":o("workflows.descriptionLabel","Workflow description"),placeholder:o("workflows.descriptionPlaceholder","Add a description"),onChange:t=>Z(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),Xe(!1)):t.key==="Escape"&&(t.preventDefault(),Z(y.description??""),Xe(!1))},onBlur:()=>Xe(!1)}):e.jsx("button",{type:"button",className:"wf-workflow-description","data-testid":"wf-workflow-description",onClick:()=>Xe(!0),title:o("workflows.clickToEditDescription","Click to edit description"),children:H||o("workflows.descriptionPlaceholder","Add a description")}),!x&&e.jsxs("button",{type:"button",className:"wf-layout-toggle","data-testid":"wf-layout-toggle","aria-pressed":re,onClick:()=>X(t=>!t),children:[re?e.jsx(to,{size:14}):e.jsx(Xs,{size:14}),e.jsx("span",{children:re?o("workflows.showCanvasEditor","Show canvas editor"):o("workflows.showSimpleEditor","Show simple editor")})]})]}),So.length>0&&e.jsxs("div",{className:"wf-lifecycle-warnings",role:"status","data-testid":"wf-lifecycle-warnings",children:[e.jsxs("div",{className:"wf-lifecycle-warnings-title",children:[e.jsx(Zs,{size:14,"aria-hidden":!0}),e.jsx("span",{children:o("workflows.lifecycleWarningsTitle","Lifecycle warnings")})]}),e.jsx("ul",{children:So.map((t,a)=>e.jsxs("li",{children:[e.jsx("span",{className:"wf-lifecycle-warning-code",children:t.code}),t.nodeId&&e.jsx("span",{className:"wf-lifecycle-warning-node",children:t.nodeId}),e.jsx("span",{children:t.message})]},`${t.code}:${t.nodeId??""}:${a}`))})]}),ye&&e.jsxs("div",{className:"wf-mobile-shell","data-testid":"wf-mobile-shell",children:[e.jsx("nav",{className:"wf-mobile-tabs","aria-label":o("workflows.mobileEditorNav","Workflow editor sections"),children:[["graph",o("workflowNodes.mobileGraph","Graph")],["add",o("workflowNodes.mobileAdd","Add")],["settings",o("workflowSettings.title","Settings")],["fields",o("workflowFields.title","Fields")],["columns",o("workflowColumns.title","Columns")],["actions",o("workflowNodes.mobileActions","Actions")]].map(([t,a])=>e.jsx("button",{type:"button",className:`wf-mobile-tab${ie===t?" wf-mobile-tab--active":""}`,"aria-current":ie===t?"page":void 0,"data-testid":`wf-mobile-tab-${t}`,onClick:()=>de(t),children:a},t))}),e.jsxs("div",{className:"wf-mobile-panel","data-testid":`wf-mobile-panel-${ie}`,children:[ie==="graph"&&e.jsx(Ii,{rows:Ra,selectedNodeId:te,selectedEdgeId:j,onSelectNode:t=>{V(t),L(null),G(!1)},onSelectEdge:t=>{L(t),V(null)},onCreateConnection:z?void 0:ba,canReorder:!z,onMoveNode:ka}),ie==="add"&&e.jsx("div",{className:"wf-mobile-add",children:z?e.jsxs("p",{className:"wf-inspector-note wf-inspector-note--info wf-inspector-note--with-icon",children:[e.jsx(Le,{workflowId:y.id,decorative:!0}),e.jsx("span",{children:o("workflows.readOnlyBuiltin","Workflow structure is read-only; prompts are editable.")})]}):e.jsxs(e.Fragment,{children:[e.jsxs("section",{className:"wf-mobile-add-section",children:[e.jsx("h3",{children:o("workflowNodes.mobileNodeKinds","Node types")}),e.jsx("div",{className:"wf-mobile-add-grid",children:qs.map(({kind:t,label:a,icon:i,presetConfig:u})=>e.jsxs("button",{type:"button",className:"wf-mobile-add-option","data-testid":`wf-mobile-add-${t}-${a.toLowerCase().replace(/[^a-z0-9]+/g,"-")}`,onClick:()=>{xt(t,a,u),de("graph")},children:[e.jsx(i,{size:16,"aria-hidden":!0}),e.jsx("span",{children:a})]},a))})]}),Po&&e.jsxs("section",{className:"wf-mobile-add-section",children:[e.jsx("h3",{children:o("workflowNodes.templatesSection","Templates")}),Bt>8&&e.jsx("input",{type:"text",className:"wf-templates-filter wf-mobile-template-filter","data-testid":"wf-mobile-template-filter",value:pt,onChange:t=>po(t.target.value),placeholder:o("workflowNodes.templateFilterPlaceholder","Filter templates"),"aria-label":o("workflowNodes.templateFilterLabel","Filter templates")}),mt&&e.jsx("div",{className:"wf-templates-conflict",role:"alert","data-testid":"wf-mobile-tpl-conflict",children:o("workflowNodes.templateSeamConflict",`This fragment duplicates the "{{seam}}" seam already on the canvas, so it can't be inserted.`,{seam:mt})}),me.fragmentEntries.length>0&&e.jsxs("div",{className:"wf-mobile-template-group",children:[e.jsx("h4",{children:o("workflowNodes.templatesFragments","Fragments")}),me.fragmentEntries.map(t=>e.jsx("button",{type:"button",className:"wf-mobile-template-option","data-testid":`wf-mobile-tpl-fragment-${t.id}`,onClick:()=>{Mo(t)&&de("graph")},children:t.name},t.id))]}),me.stepEntries.length>0&&e.jsxs("div",{className:"wf-mobile-template-group",children:[e.jsx("h4",{children:o("workflowNodes.templatesBuiltinSteps","Fusion steps")}),me.stepEntries.map(t=>e.jsxs("div",{className:"wf-mobile-template-option-row",children:[e.jsx("button",{type:"button",className:"wf-mobile-template-option","data-testid":`wf-mobile-tpl-step-${t.id}`,onClick:()=>{vt(t),de("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:()=>{Io(t),de("graph")},children:o("workflowNodes.asOptionalGroup","as optional group")})]},t.id))]}),me.pluginEntries.length>0&&e.jsxs("div",{className:"wf-mobile-template-group",children:[e.jsx("h4",{children:o("workflowNodes.templatesPluginSteps","Plugin steps")}),me.pluginEntries.map(({pluginId:t,template:a})=>e.jsxs("button",{type:"button",className:"wf-mobile-template-option","data-testid":`wf-mobile-tpl-plugin-${a.id}`,onClick:()=>{vt(a),de("graph")},children:[e.jsx("span",{children:a.name}),e.jsx("span",{className:"wf-templates-badge",children:t})]},`${t}:${a.id}`))]})]})]})}),ie==="settings"&&y&&e.jsx("div",{ref:Rt,className:"wf-mobile-destination",children:e.jsx(Ts,{workflowId:y.id,settings:Re,onChange:ot,readOnly:z,projectId:r,addToast:l,initialTab:"values"})}),ie==="fields"&&e.jsx("div",{className:"wf-mobile-destination",children:e.jsx(Is,{fields:Fe,onChange:tt,readOnly:z,addToast:l})}),ie==="columns"&&e.jsx("div",{className:"wf-mobile-destination",children:e.jsx(Ps,{columns:ee,onChange:et,violations:Gt,readOnly:z,projectId:r,addToast:l,columnAgentsEnabled:Ao})}),ie==="actions"&&e.jsx("div",{className:"wf-mobile-actions",children:z?e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"wf-inspector-note wf-inspector-note--info wf-inspector-note--with-icon",children:[e.jsx(Le,{workflowId:y.id,decorative:!0}),e.jsx("span",{children:o("workflows.readOnlyBuiltin","Workflow structure is read-only; prompts are editable.")})]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-export",onClick:bt,children:[e.jsx(St,{size:15})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-save wf-editor-duplicate-primary","data-testid":"wf-mobile-duplicate",onClick:_o,children:[e.jsx(Pe,{size:15})," ",o("workflows.duplicateToCustomize","Duplicate to customize")]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"wf-editor-save","data-testid":"wf-mobile-save",onClick:Bo,disabled:$,children:[$?e.jsx(Me,{size:15,className:"wf-spin"}):e.jsx(lo,{size:15}),o("common.save","Save")]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-ai-edit",onClick:()=>zt(t=>!t),children:[e.jsx(Je,{size:15})," ",o("workflows.aiEdit","Design with AI")]}),Lt&&e.jsxs("div",{className:"wf-ai-panel wf-mobile-ai-panel","data-testid":"wf-mobile-ai-panel",role:"dialog","aria-busy":ke,children:[e.jsx("textarea",{className:"wf-ai-prompt","data-testid":"wf-mobile-ai-edit-prompt",rows:4,value:ht,disabled:ke,placeholder:o("workflows.aiPromptPlaceholder","e.g. Run lint and tests before merge, then post a changelog comment after merge"),onChange:t=>{Wt(t.target.value),Ge&&qe(null)}}),Ge&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-mobile-ai-edit-error",children:Ge}),e.jsxs("div",{className:"wf-ai-actions",children:[e.jsxs("button",{type:"button",className:"btn btn-primary wf-ai-submit","data-testid":"wf-mobile-ai-edit-submit",disabled:ke,onClick:()=>void Do(),children:[ke?e.jsx(Me,{size:13,className:"wf-spin"}):e.jsx(Je,{size:13}),o("workflows.aiSubmit","Design with AI")]}),ke&&e.jsx("button",{type:"button",className:"btn wf-ai-cancel",onClick:To,children:o("common.cancel","Cancel")})]})]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-auto-layout",onClick:Oo,children:[e.jsx(to,{size:15})," ",o("workflowNodes.autoLayout","Auto-layout")]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-mobile-export",onClick:bt,disabled:lt,children:[e.jsx(St,{size:15})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-delete","data-testid":"wf-mobile-delete",onClick:$o,children:[e.jsx(je,{size:15})," ",o("common.delete","Delete")]})]})})]})]}),z?e.jsxs("div",{className:"wf-editor-readonly-banner",role:"status","data-testid":"wf-readonly-banner",children:[e.jsxs("span",{className:"wf-editor-readonly-note",children:[e.jsx(Le,{workflowId:y.id,decorative:!0}),e.jsx("span",{children:o("workflows.readOnlyBuiltin","Workflow structure is read-only; prompts are editable.")})]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-export",onClick:bt,title:o("workflows.exportTooltip","Download as JSON — contains your full prompt and command text"),children:[e.jsx(St,{size:13})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-save wf-editor-duplicate-primary",onClick:_o,children:[e.jsx(Pe,{size:13})," ",o("workflows.duplicateToCustomize","Duplicate to customize")]})]}):e.jsxs("div",{className:"wf-editor-toolbar",children:[e.jsx("div",{className:"wf-editor-palette",children:qs.map(({kind:t,label:a,icon:i,presetConfig:u})=>e.jsxs("button",{className:"wf-palette-btn",onClick:()=>xt(t,a,u),children:[e.jsx(i,{size:13})," ",a]},a))}),e.jsxs("div",{className:"wf-editor-actions",children:[e.jsxs("div",{className:"wf-ai-edit-wrap",children:[e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-ai-edit","aria-expanded":Lt,onClick:()=>{zt(t=>!t),qe(null)},children:[e.jsx(Je,{size:13})," ",o("workflows.aiEdit","Design with AI")]}),Lt&&e.jsxs("div",{className:"wf-ai-panel","data-testid":"wf-ai-panel",role:"dialog","aria-busy":ke,"aria-label":o("workflows.aiEdit","Design with AI"),children:[e.jsx("textarea",{className:"wf-ai-prompt","data-testid":"wf-ai-edit-prompt",rows:3,value:ht,disabled:ke,placeholder:o("workflows.aiPromptPlaceholder","e.g. Run lint and tests before merge, then post a changelog comment after merge"),onChange:t=>{Wt(t.target.value),Ge&&qe(null)}}),Ge&&e.jsx("p",{className:"wf-create-error",role:"alert","data-testid":"wf-ai-edit-error",children:Ge}),e.jsxs("div",{className:"wf-ai-actions",children:[e.jsxs("button",{type:"button",className:"btn btn-primary wf-ai-submit","data-testid":"wf-ai-edit-submit",disabled:ke,onClick:()=>void Do(),children:[ke?e.jsx(Me,{size:13,className:"wf-spin"}):e.jsx(Je,{size:13})," ",o("workflows.aiSubmit","Design with AI")]}),ke&&e.jsx("button",{type:"button",className:"btn wf-ai-cancel","data-testid":"wf-ai-edit-cancel",onClick:To,children:o("common.cancel","Cancel")})]})]})]}),e.jsxs("button",{className:"wf-editor-action",onClick:Oo,"data-testid":"wf-auto-layout",children:[e.jsx(to,{size:13})," ",o("workflowNodes.autoLayout","Auto-layout")]}),e.jsxs("button",{className:"wf-editor-action","data-testid":"wf-export",onClick:bt,disabled:lt,title:lt?o("workflows.exportDirtyTooltip","Save before exporting"):o("workflows.exportTooltip","Download as JSON — contains your full prompt and command text"),children:[e.jsx(St,{size:13})," ",o("workflows.export","Export")]}),e.jsxs("button",{className:"wf-editor-delete",onClick:$o,children:[e.jsx(je,{size:13})," ",o("common.delete","Delete")]}),e.jsxs("button",{className:"wf-editor-save",onClick:Bo,disabled:$,children:[$?e.jsx(Me,{size:13,className:"wf-spin"}):e.jsx(lo,{size:13})," ",o("common.save","Save")]})]})]}),Po&&e.jsxs("section",{className:"wf-templates","data-testid":"wf-palette-templates","aria-label":o("workflowNodes.templatesSection","Templates"),children:[e.jsxs("div",{className:"wf-templates-header",children:[e.jsxs("button",{type:"button",className:"wf-templates-toggle","aria-expanded":!Be,"data-testid":"wf-templates-toggle",onClick:()=>ca(t=>!t),children:[Be?e.jsx(Ie,{size:13}):e.jsx(Ae,{size:13}),e.jsx(Xn,{size:13})," ",o("workflowNodes.templatesSection","Templates")]}),!Be&&Bt>8&&e.jsx("input",{type:"text",className:"wf-templates-filter","data-testid":"wf-template-filter",value:pt,onChange:t=>po(t.target.value),placeholder:o("workflowNodes.templateFilterPlaceholder","Filter templates"),"aria-label":o("workflowNodes.templateFilterLabel","Filter templates")})]}),!Be&&e.jsxs("div",{className:"wf-templates-body",children:[mt&&e.jsx("div",{className:"wf-templates-conflict",role:"alert","data-testid":"wf-tpl-conflict",children:o("workflowNodes.templateSeamConflict",`This fragment duplicates the "{{seam}}" seam already on the canvas, so it can't be inserted.`,{seam:mt})}),me.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:me.fragmentEntries.map(t=>e.jsx("button",{type:"button",className:"wf-templates-entry","data-testid":`wf-tpl-fragment-${t.id}`,disabled:z,"aria-label":o("workflowNodes.insertTemplate","Insert template {{name}}",{name:t.name}),onClick:()=>Mo(t),children:t.name},t.id))})]}),me.stepEntries.length>0&&e.jsxs("div",{className:"wf-templates-group",children:[e.jsx("h4",{className:"wf-templates-group-title",children:o("workflowNodes.templatesBuiltinSteps","Fusion steps")}),e.jsx("div",{className:"wf-templates-entries",children:me.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:z,"aria-label":o("workflowNodes.insertTemplate","Insert template {{name}}",{name:t.name}),onClick:()=>vt(t),children:t.name}),e.jsx("button",{type:"button",className:"wf-templates-entry-optional","data-testid":`wf-tpl-step-${t.id}-optional-group`,disabled:z,title:o("workflowNodes.insertAsOptionalGroup","Insert as optional group"),"aria-label":o("workflowNodes.insertTemplateAsOptionalGroup","Insert {{name}} as optional group",{name:t.name}),onClick:()=>Io(t),children:o("workflowNodes.asOptionalGroup","as optional group")})]},t.id))})]}),me.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:me.pluginEntries.map(({pluginId:t,template:a})=>e.jsxs("button",{type:"button",className:"wf-templates-entry","data-testid":`wf-tpl-plugin-${a.id}`,disabled:z,"aria-label":o("workflowNodes.insertTemplate","Insert template {{name}}",{name:a.name}),onClick:()=>vt(a),children:[a.name,e.jsx("span",{className:"wf-templates-badge",children:t})]},`${t}:${a.id}`))})]})]})]}),I&&e.jsx("div",{className:"wf-editor-banner",role:"alert",children:I}),Oe.length>0&&e.jsx("div",{className:"wf-editor-banner wf-editor-banner--warn",role:"alert","data-testid":"wf-unplaced-summary",children:o("workflowColumns.unplacedCount","{{count}} nodes not placed in a column",{count:Oe.length})}),e.jsxs("div",{className:"wf-editor-canvas",ref:Dt,tabIndex:-1,children:[x&&B&&f&&f.data.kind!=="end"&&e.jsxs("button",{type:"button",className:"wf-inspector-toggle wf-inspector-toggle--collapsed","data-testid":"wf-inspector-toggle","aria-expanded":"false",onClick:()=>G(!1),children:[e.jsx(Ie,{size:13}),e.jsx("span",{children:o("workflowNodes.showInspector","Show node details")})]}),ma&&e.jsx("div",{className:"wf-trivial-hint",role:"status","data-testid":"wf-trivial-hint",children:o("workflowNodes.trivialGraphHint","This workflow only runs start → end. Add steps from the palette above to build it out.")}),e.jsx(Bn.Provider,{value:Xt,children:e.jsxs(_a,{nodes:He,edges:K,nodeTypes:qn,onNodesChange:fe,onEdgesChange:ha,onConnect:ga,onNodeDragStop:xa,deleteKeyCode:z?null:["Backspace","Delete"],onBeforeDelete:va,onNodesDelete:ja,onEdgesDelete:Na,onNodeClick:(t,a)=>{V(a.id),L(null),G(!1)},onEdgeClick:(t,a)=>{L(a.id),V(null)},onPaneClick:()=>{V(null),L(null)},defaultEdgeOptions:{interactionWidth:Gn},defaultViewport:{x:0,y:0,zoom:1},children:[e.jsx(Ba,{}),e.jsx(Ga,{}),e.jsxs("button",{type:"button",className:`wf-minimap-toggle nodrag nopan${se?" wf-minimap-toggle--collapsed":""}`,"aria-expanded":!se,"aria-controls":"wf-workflow-minimap","data-testid":"wf-minimap-toggle",onClick:()=>pe(t=>!t),children:[se?e.jsx(vs,{size:13,"aria-hidden":!0}):e.jsx(gs,{size:13,"aria-hidden":!0}),e.jsx("span",{children:se?o("workflowNodes.showMiniMap","Show mini map"):o("workflowNodes.hideMiniMap","Hide mini map")})]}),!se&&e.jsx(qa,{id:"wf-workflow-minimap",pannable:!0,zoomable:!0,nodeColor:$i,nodeStrokeColor:_i,maskColor:"color-mix(in srgb, var(--surface) 70%, transparent)",bgColor:"var(--surface)"})]})})]})]}):e.jsxs("div",{className:"wf-editor-empty wf-editor-canvas-empty wf-editor-onboard",children:[e.jsx(bs,{className:"wf-editor-onboard-icon",size:40,"aria-hidden":!0}),e.jsx("h3",{className:"wf-editor-onboard-title",children:o("workflows.emptyTitle","No workflow selected")}),e.jsx("p",{className:"wf-editor-onboard-text",children:o("workflows.emptyDescription","Workflows orchestrate the steps and gates that run around task execution. Create one to start arranging that flow.")}),e.jsxs("button",{className:"wf-editor-save wf-editor-onboard-cta","data-testid":"wf-empty-create",onClick:()=>Ce(!0),children:[e.jsx(Pe,{size:14})," ",o("workflows.newWorkflow","New workflow")]})]})]}),Go&&!(x&&B)&&e.jsxs("aside",{className:"wf-editor-inspector","data-testid":"wf-node-inspector",children:[e.jsxs("div",{className:"wf-inspector-heading",children:[e.jsx("h3",{children:Ee?.title??o("workflowNodes.nodeInspector","Node")}),x&&e.jsxs("button",{type:"button",className:"wf-inspector-toggle wf-inspector-toggle--expanded","data-testid":"wf-inspector-toggle","aria-expanded":"true",onClick:()=>{ye?V(null):G(!0)},children:[e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowNodes.collapseInspector","Collapse")})]})]}),Ee&&e.jsxs("details",{className:"wf-inspector-help","data-testid":"wf-node-help",children:[e.jsxs("summary",{className:"wf-inspector-help-summary",children:[e.jsx(ea,{size:13,"aria-hidden":!0}),e.jsx("span",{children:o("workflowNodes.helpTitle","What does this node do?")}),Ee.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:Ee.summary}),e.jsxs("dl",{className:"wf-inspector-help-dl",children:[Ee.configure&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:o("workflowNodes.helpConfigure","Configure")}),e.jsx("dd",{children:Ee.configure})]}),e.jsx("dt",{children:o("workflowNodes.helpInputs","Inputs")}),e.jsx("dd",{children:Ee.inputs}),e.jsx("dt",{children:o("workflowNodes.helpOutputs","Outputs")}),e.jsx("dd",{children:Ee.outputs}),e.jsx("dt",{children:o("workflowNodes.helpEdges","Edges")}),e.jsx("dd",{children:Ee.edges})]})]})]}),z&&e.jsxs("p",{className:"wf-inspector-note wf-inspector-note--info wf-inspector-note--with-icon",children:[e.jsx(Le,{workflowId:y.id,decorative:!0}),e.jsx("span",{children:o("workflowNodes.readOnlyDuplicateToEdit","Workflow structure is read-only — prompts on prompt and gate nodes can be edited here.")})]}),e.jsxs("fieldset",{className:"wf-inspector-fields",disabled:z,children:[f.data.kind!=="start"&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("common:labels.name","Name")}),e.jsx("input",{value:f.data.label,onChange:t=>M({label:t.target.value})})]}),f.data.kind==="start"&&e.jsxs("div",{"data-testid":"wf-start-inspector",children:[e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.startNote","The start node marks where a task enters the workflow.")}),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(f.data.column??""),onChange:t=>M({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))]})]})]})]}),f.data.kind==="prompt"||f.data.kind==="gate"?e.jsxs("div",{className:"wf-prompt-editor",children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.prompt","Prompt")}),e.jsx("textarea",{rows:5,value:Ue,readOnly:!Nt,onChange:t=>Ko(t.target.value),onBlur:Yo})]}),e.jsxs("div",{className:"wf-prompt-override-actions",children:[z&&Uo?e.jsx("span",{className:"wf-prompt-override-badge","data-testid":"wf-prompt-overridden",children:o("workflowEditor.promptOverridden","Overridden")}):null,z?e.jsx("button",{type:"button",className:"btn btn-sm",onClick:Jo,disabled:!Yt||jt,children:jt?o("workflowEditor.promptSaving","Saving…"):o("workflowEditor.resetPromptDefault","Reset to default")}):null]}),e.jsx("button",{type:"button",className:"btn btn-sm wf-prompt-expand-btn wf-prompt-expand-btn--inline",onClick:Vo,"aria-label":o("workflowEditor.expandPrompt","Expand prompt editor"),title:o("workflowEditor.expandPrompt","Expand prompt editor"),children:e.jsx(vs,{size:14})})]}):null,e.jsxs("fieldset",{className:"wf-inspector-fields",disabled:z,children:[f.data.kind==="prompt"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.executor","Executor")}),e.jsxs("select",{value:we,onChange:t=>M({config:{executor:t.target.value}}),children:[e.jsx("option",{value:"model",children:o("workflowEditor.model","Model")}),e.jsx("option",{value:"agent",children:o("workflowEditor.agent","Agent")}),e.jsx("option",{value:"skill",children:o("workflowEditor.skill","Skill")}),e.jsx("option",{value:"cli",children:o("workflowEditor.cliScript","CLI / script")}),e.jsx("option",{value:"cli-agent",children:o("workflowEditor.cliAgent.executorOption")})]})]}),Te&&e.jsx("p",{className:"wf-inspector-note wf-inspector-note--warn","data-testid":"wf-node-overridden-by-column-agent",children:o("workflowColumns.overriddenByColumnAgent","Overridden by column agent {{name}} — this node's executor settings are superseded.",{name:Ia?.name??o("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:Te.agentId})})}),we==="model"&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.model","Model")}),e.jsx(ro,{label:o("workflowEditor.model","Model"),models:De,value:Ws(String(f.data.config?.modelProvider??""),String(f.data.config?.modelId??"")),onChange:t=>{const{provider:a,modelId:i}=$s(t);M({config:{modelProvider:a||void 0,modelId:i||void 0}})}})]}),we==="agent"&&(()=>{const t=String(f.data.config?.agentId??""),a=t!==""&&!ve.some(i=>i.id===t);return e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.agent","Agent")}),e.jsxs("select",{value:t,onChange:i=>M({config:{agentId:i.target.value||void 0}}),children:[e.jsx("option",{value:"",children:o("workflowEditor.selectAgent","— select agent —")}),a&&e.jsx("option",{value:t,children:o("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:t})}),ve.map(i=>e.jsx("option",{value:i.id,children:i.name},i.id))]}),a&&e.jsx("p",{className:"wf-inspector-note wf-inspector-note--warn","data-testid":"wf-node-agent-stale",children:o("workflowColumns.agentNotFound","Agent not found — {{id}}",{id:t})})]})})(),we==="skill"&&(()=>{const t=String(f.data.config?.skillName??""),a=t?Ke.find(u=>js(u.name)===js(t)):void 0,i=a?a.name:t;return e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.skill","Skill")}),e.jsxs("select",{value:i,onChange:u=>M({config:{skillName:u.target.value||void 0}}),children:[e.jsx("option",{value:"",children:o("workflowEditor.selectSkill","— select skill —")}),Ke.map(u=>e.jsx("option",{value:u.name,children:u.name},u.id))]})]})})(),we==="cli"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.cliMode","CLI mode")}),e.jsxs("select",{value:String(f.data.config?.cliMode??"command"),onChange:t=>M({config:{cliMode:t.target.value}}),children:[e.jsx("option",{value:"command",children:o("workflowEditor.command","Command")}),e.jsx("option",{value:"script",children:o("workflowEditor.namedScript","Named script")})]})]}),(f.data.config?.cliMode??"command")==="command"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.command","Command")}),e.jsx("textarea",{rows:3,placeholder:qi,value:String(f.data.config?.cliCommand??""),onChange:t=>M({config:{cliCommand:t.target.value}})}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowEditor.cliCommandNote","Runs an arbitrary command in the task worktree. The first time this exact command runs, the task pauses for your approval. The node prompt is passed via FUSION_NODE_PROMPT.")}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:f.data.config?.cliSkipApproval===!0,onChange:t=>M({config:{cliSkipApproval:t.target.checked}})}),e.jsx("span",{children:o("workflowEditor.skipFirstRunApproval","Skip first-run approval (runs without pausing)")})]})]}):e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.scriptName","Script name")}),e.jsx("input",{value:String(f.data.config?.scriptName??""),onChange:t=>M({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.")})]})]}),we==="cli-agent"&&e.jsxs("div",{"data-testid":"cli-agent-config",children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.cliAgent.adapterLabel")}),e.jsxs("select",{"data-testid":"cli-agent-adapter",value:String(f.data.config?.cliAdapterId??""),onChange:t=>M({config:{cliAdapterId:t.target.value||void 0}}),children:[e.jsx("option",{value:"",children:o("workflowEditor.cliAgent.adapterPlaceholder")}),Pa.map(t=>e.jsxs("option",{value:t.id,children:[t.name," (",o(`workflowEditor.cliAgent.tier.${t.tier}`),")"]},t.id))]}),e.jsx("span",{className:"wf-inspector-note",children:o("workflowEditor.cliAgent.adapterNote")})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox","data-testid":"cli-agent-autonomy",checked:!!f.data.config?.cliAutonomy?.autoApprove,onChange:t=>M({config:{cliAutonomy:{...f.data.config?.cliAutonomy??{},autoApprove:t.target.checked}}})}),e.jsx("span",{children:o("workflowEditor.cliAgent.autonomyLabel")})]}),!!f.data.config?.cliAutonomy?.autoApprove&&e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowEditor.cliAgent.autonomyNote")}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.cliAgent.notifyLabel")}),e.jsxs("select",{"data-testid":"cli-agent-notify",value:String(f.data.config?.cliNotify?.mode??"banner"),onChange:t=>M({config:{cliNotify:{mode:t.target.value}}}),children:[e.jsx("option",{value:"banner",children:o("workflowEditor.cliAgent.notify.banner")}),e.jsx("option",{value:"banner+notify",children:o("workflowEditor.cliAgent.notify.bannerNotify")})]}),e.jsx("span",{className:"wf-inspector-note",children:o("workflowEditor.cliAgent.notifyNote")})]})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:!!f.data.config?.autoApprove,onChange:t=>M({config:{autoApprove:t.target.checked}})}),e.jsx("span",{children:o("workflowEditor.autoApproveRequests","Auto-approve requests")})]}),!!f.data.config?.autoApprove&&e.jsx("p",{className:"wf-inspector-note",children:o("workflowEditor.autoApproveRequestsNote","Runs without pausing for approval — e.g. a CLI command executes on its first run without waiting for your sign-off.")}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.maxRetries","Max retries")}),e.jsx("input",{type:"number",min:1,max:10,placeholder:"default",value:f.data.config?.maxRetries!=null?String(f.data.config.maxRetries):"",onChange:t=>{const a=t.target.value.trim();if(a==="")M({config:i=>{const u={...i};return delete u.maxRetries,u}});else{const i=parseInt(a,10);isNaN(i)||M({config:{maxRetries:i}})}}})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:!!f.data.config?.awaitInput,onChange:t=>M({config:{awaitInput:t.target.checked}})}),e.jsx("span",{children:o("workflowEditor.waitForUserInput","Wait for user input")})]}),!!f.data.config?.awaitInput&&e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowEditor.waitForUserInputNote","This node pauses the task until you reply in the task's comments and unpause. The Prompt field above is shown to the user as the question.")})]}):null,f.data.kind==="script"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowEditor.scriptName","Script name")}),e.jsx("input",{value:String(f.data.config?.scriptName??""),onChange:t=>M({config:{scriptName:t.target.value}})})]}):null,f.data.kind==="hold"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.releaseCondition","Release condition")}),e.jsxs("select",{value:String(f.data.config?.release??"manual"),onChange:t=>M({config:{release:t.target.value}}),children:[e.jsx("option",{value:"manual",children:o("workflowNodes.releaseManual","Manual promote")}),e.jsx("option",{value:"timer",children:o("workflowNodes.releaseTimer","Timer")}),e.jsx("option",{value:"capacity",children:o("workflowNodes.releaseCapacity","Downstream capacity")}),e.jsx("option",{value:"dependency",children:o("workflowNodes.releaseDependency","Dependency complete")}),e.jsx("option",{value:"external-event",children:o("workflowNodes.releaseExternal","External event")})]})]}):null,f.data.kind==="join"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.joinMode","Join mode")}),e.jsxs("select",{value:(()=>{const t=f.data.config?.mode;return t&&typeof t=="object"&&"quorum"in t?"quorum":typeof t=="string"?t:"all"})(),onChange:t=>{const a=t.target.value;M(a==="quorum"?{config:{mode:{quorum:2}}}:{config:{mode:a}})},children:[e.jsx("option",{value:"all",children:o("workflowNodes.joinAll","All branches")}),e.jsx("option",{value:"any",children:o("workflowNodes.joinAny","Any branch")}),e.jsx("option",{value:"quorum",children:o("workflowNodes.joinQuorum","Quorum (n)")})]})]}),(()=>{const t=f.data.config?.mode;return t&&typeof t=="object"&&"quorum"in t})()&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.quorumN","Quorum count (n)")}),e.jsx("input",{type:"number",min:1,value:String(f.data.config?.mode?.quorum??2),onChange:t=>{const a=parseInt(t.target.value,10);isNaN(a)||M({config:{mode:{quorum:a}}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.failurePolicy","On branch failure")}),e.jsxs("select",{value:String(f.data.config?.onBranchFailure??"collect"),onChange:t=>M({config:{onBranchFailure:t.target.value}}),children:[e.jsx("option",{value:"collect",children:o("workflowNodes.failureCollect","Collect (wait for all)")}),e.jsx("option",{value:"fail-fast",children:o("workflowNodes.failureFailFast","Fail-fast (cancel siblings)")})]})]})]}):null,f.data.kind==="split"?e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.splitNote","Branches run concurrently from this node. Execute and merge seams are not allowed inside a branch.")}):null,f.data.kind==="foreach"?(()=>{const t=String(f.data.config?.mode??"sequential"),a=t==="parallel";return e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.foreachMode","Mode")}),e.jsxs("select",{value:t,onChange:i=>{const u=i.target.value;M({config:h=>({...h,mode:u,...u==="parallel"&&h.isolation==="shared"?{isolation:"worktree"}:{}})})},children:[e.jsx("option",{value:"sequential",children:o("workflowNodes.foreachSequential","Sequential")}),e.jsx("option",{value:"parallel",children:o("workflowNodes.foreachParallel","Parallel")})]})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.foreachIsolation","Isolation")}),e.jsxs("select",{value:String(f.data.config?.isolation??(a?"worktree":"shared")),onChange:i=>M({config:{isolation:i.target.value}}),children:[e.jsx("option",{value:"shared",disabled:a,children:o("workflowNodes.foreachShared","Shared worktree")}),e.jsx("option",{value:"worktree",children:o("workflowNodes.foreachWorktree","Per-step worktree")})]})]}),a&&e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.foreachConcurrency","Concurrency")}),e.jsx("input",{type:"number",min:1,max:8,placeholder:"2",value:f.data.config?.concurrency!=null?String(f.data.config.concurrency):"",onChange:i=>{const u=i.target.value.trim();if(u==="")M({config:h=>{const E={...h};return delete E.concurrency,E}});else{const h=parseInt(u,10);isNaN(h)||M({config:{concurrency:h}})}}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.foreachMaxRework","Max rework cycles")}),e.jsx("input",{type:"number",min:1,max:10,placeholder:"3",value:f.data.config?.maxReworkCycles!=null?String(f.data.config.maxReworkCycles):"",onChange:i=>{const u=i.target.value.trim();if(u==="")M({config:h=>{const E={...h};return delete E.maxReworkCycles,E}});else{const h=parseInt(u,10);isNaN(h)||M({config:{maxReworkCycles:h}})}}})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.foreachNote","Expands once per planned step. Drop a step-execute node (and optional step-review) into the region.")})]})})():null,f.data.kind==="loop"?(()=>{const t=f.data.config?.exitWhen&&typeof f.data.config.exitWhen=="object"?f.data.config.exitWhen:{type:"output-contains",value:"DONE"},a=String(t.type??"output-contains"),i=String(a==="output-matches"?t.pattern??"":t.value??"");return e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.loopExitType","Exit condition")}),e.jsxs("select",{value:a,onChange:u=>{const h=u.target.value;M({config:E=>{const v=E.exitWhen&&typeof E.exitWhen=="object"?E.exitWhen:{},U=String(h==="output-matches"?v.pattern??v.value??"":v.value??v.pattern??""),ce={...v,type:h};return delete ce.pattern,delete ce.value,{...E,exitWhen:h==="output-matches"?{...ce,pattern:U}:{...ce,value:U}}}})},children:[e.jsx("option",{value:"output-contains",children:o("workflowNodes.loopOutputContains","Output contains")}),e.jsx("option",{value:"output-matches",children:o("workflowNodes.loopOutputMatches","Output matches regex")})]})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:a==="output-matches"?o("workflowNodes.loopPattern","Pattern"):o("workflowNodes.loopValue","Value")}),e.jsx("input",{value:i,placeholder:a==="output-matches"?"DONE|COMPLETE":"DONE",onChange:u=>{const h=u.target.value;M({config:E=>{const v=E.exitWhen&&typeof E.exitWhen=="object"?E.exitWhen:{};return{...E,exitWhen:a==="output-matches"?{...v,type:a,pattern:h}:{...v,type:a,value:h}}}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.loopNodeId","Watch node id (optional)")}),e.jsx("input",{value:String(t.nodeId??""),placeholder:o("workflowNodes.loopNodeIdPlaceholder","Template exit node"),onChange:u=>{const h=u.target.value.trim();M({config:E=>{const U={...E.exitWhen&&typeof E.exitWhen=="object"?E.exitWhen:{type:"output-contains",value:"DONE"}};return h?U.nodeId=h:delete U.nodeId,{...E,exitWhen:U}}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.loopMaxIterations","Max iterations")}),e.jsx("input",{type:"number",min:1,max:50,placeholder:"3",value:f.data.config?.maxIterations!=null?String(f.data.config.maxIterations):"",onChange:u=>{const h=u.target.value.trim();M({config:E=>{const v={...E};if(h==="")delete v.maxIterations;else{const U=parseInt(h,10);isNaN(U)||(v.maxIterations=U)}return v}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.loopTimeoutMs","Timeout (ms)")}),e.jsx("input",{type:"number",min:1,max:36e5,placeholder:"300000",value:f.data.config?.timeoutMs!=null?String(f.data.config.timeoutMs):"",onChange:u=>{const h=u.target.value.trim();M({config:E=>{const v={...E};if(h==="")delete v.timeoutMs;else{const U=parseInt(h,10);isNaN(U)||(v.timeoutMs=U)}return v}})}})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.loopNote","Repeats the template until the selected output matches, an iteration limit is reached, or the timeout expires.")})]})})():null,f.data.kind==="optional-group"?(()=>{const t=f.data.config?.maxRevisions,a=t==="unbounded";return e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox","data-testid":"wf-optional-group-default-on",checked:!!f.data.config?.defaultOn,onChange:i=>M({config:{defaultOn:i.target.checked}})}),e.jsx("span",{children:o("workflowNodes.optionalGroupDefaultOn","Enabled by default for new tasks")})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.optionalGroupMaxRevisions","Max revisions")}),e.jsx("input",{type:"number",min:0,placeholder:o("workflowNodes.optionalGroupMaxRevisionsPlaceholder","Use global setting"),"data-testid":"wf-optional-group-max-revisions",disabled:a,value:typeof t=="number"?String(t):"",onChange:i=>{const u=i.target.value.trim();M({config:h=>{const E={...h};if(u==="")delete E.maxRevisions;else{const v=parseInt(u,10);!isNaN(v)&&v>=0&&(E.maxRevisions=v)}return E}})}})]}),e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox","data-testid":"wf-optional-group-max-revisions-unbounded",checked:a,onChange:i=>{M({config:u=>{const h={...u};return i.target.checked?h.maxRevisions="unbounded":h.maxRevisions==="unbounded"&&delete h.maxRevisions,h}})}}),e.jsx("span",{children:o("workflowNodes.optionalGroupMaxRevisionsUnbounded","Unbounded")})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.optionalGroupNote","Runs the steps inside this group once when the task enables it (seeded from this default), and skips them when disabled. Drop the optional steps into the region.")})]})})():null,f.data.kind==="step-review"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.reviewType","Review type")}),e.jsxs("select",{value:String(f.data.config?.type??"code"),onChange:t=>M({config:{type:t.target.value}}),children:[e.jsx("option",{value:"plan",children:o("workflowNodes.reviewPlan","Plan review")}),e.jsx("option",{value:"code",children:o("workflowNodes.reviewCode","Code review")})]})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.reviewModel","Review model (optional)")}),e.jsx(ro,{label:o("workflowNodes.reviewModel","Review model (optional)"),models:De,value:Ws(String(f.data.config?.modelProvider??""),String(f.data.config?.modelId??"")),onChange:t=>{const{provider:a,modelId:i}=$s(t);M({config:{modelProvider:a||void 0,modelId:i||void 0,model:t||void 0}})}})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.reviewNote","Verdicts route as outcome edges. Click an outgoing edge to set its verdict and rework behavior.")})]}):null,f.data.kind==="parse-steps"?e.jsxs(e.Fragment,{children:[Jt.length>0?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.parseArtifact","Artifact")}),e.jsx("select",{value:String(f.data.config?.artifact??Jt[0]),onChange:t=>M({config:{artifact:t.target.value}}),children:Jt.map(t=>e.jsx("option",{value:t,children:t},t))})]}):e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.parseArtifact","Artifact")}),e.jsx("input",{placeholder:"PROMPT.md",value:String(f.data.config?.artifact??"PROMPT.md"),onChange:t=>M({config:{artifact:t.target.value}})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.parseParser","Parser")}),e.jsx("select",{value:String(f.data.config?.parser??"step-headings"),onChange:t=>M({config:{parser:t.target.value}}),children:Array.from(new Set([String(f.data.config?.parser??"step-headings"),...ia])).map(t=>e.jsx("option",{value:t,children:t},t))})]})]}):null,f.data.kind==="code"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.codeSource","Source (TypeScript)")}),e.jsx("textarea",{className:"wf-code-source",rows:8,spellCheck:!1,placeholder:Vi,value:String(f.data.config?.source??""),onChange:t=>M({config:{source:t.target.value}})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.codeTimeout","Timeout (ms)")}),e.jsx("input",{type:"number",min:1,placeholder:"30000",value:f.data.config?.timeoutMs!=null?String(f.data.config.timeoutMs):"",onChange:t=>{const a=t.target.value.trim();if(a==="")M({config:i=>{const u={...i};return delete u.timeoutMs,u}});else{const i=parseInt(a,10);isNaN(i)||M({config:{timeoutMs:i}})}}})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.codeNote","Runs sandboxed TypeScript. Syntax is validated at save.")})]}):null,f.data.kind==="notify"?(()=>{const t=String(f.data.config?.event??"workflow-notify"),a=!Gs.includes(t);return e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.notifyEvent","Event type")}),e.jsxs("select",{value:a?no:t,onChange:i=>{const u=i.target.value;M({config:{event:u===no?"custom-event":u}})},children:[Gs.map(i=>e.jsx("option",{value:i,children:i},i)),e.jsx("option",{value:no,children:o("workflowNodes.notifyCustom","Custom")})]})]}),a?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.notifyCustomEvent","Custom event")}),e.jsx("input",{value:t,placeholder:"custom-event",onChange:i=>M({config:{event:i.target.value}})})]}):null,e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.notifyTitle","Title (optional)")}),e.jsx("input",{value:String(f.data.config?.title??"{{taskTitle}}"),placeholder:"{{taskTitle}}",onChange:i=>M({config:{title:i.target.value}})})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.notifyMessage","Message (optional)")}),e.jsx("textarea",{rows:4,value:String(f.data.config?.message??""),placeholder:Hi,onChange:i=>M({config:{message:i.target.value}})})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.notifyNote","Templates may use {{taskTitle}}, {{taskId}}, {{workflowName}}, and {{context:key}}.")})]})})():null,f.data.kind==="ask-user"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.askUserQuestion","Question")}),e.jsx("textarea",{rows:3,placeholder:o("workflowNodes.askUserQuestionPlaceholder","This workflow is waiting for your input."),value:String(f.data.config?.question??""),onChange:t=>{const a=t.target.value;M({config:i=>{const u={...i};return a.trim()===""?delete u.question:u.question=a,u}})}})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.askUserNote","Parks the task and surfaces this question in the task chat/detail. Resumes once the user replies and unpauses.")})]}):null,f.data.kind==="exit-gate"?(()=>{const t=f.data.config?.condition!=null&&typeof f.data.config.condition=="object",a=t?f.data.config.condition:{type:"output-contains",value:""},i=String(a.type??"output-contains"),u=String(i==="output-matches"?a.pattern??"":a.value??"");return e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field wf-field--checkbox",children:[e.jsx("input",{type:"checkbox",checked:t,onChange:h=>{h.target.checked?M({config:{condition:{type:"output-contains",value:""}}}):M({config:E=>{const v={...E};return delete v.condition,v}})}}),e.jsx("span",{children:o("workflowNodes.exitGateConditional","Exit conditionally")})]}),t?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.exitGateNodeId","Watch node id")}),e.jsx("input",{value:String(a.nodeId??""),placeholder:o("workflowNodes.exitGateNodeIdPlaceholder","e.g. ask"),onChange:h=>{const E=h.target.value.trim();M({config:v=>{const ce={...v.condition&&typeof v.condition=="object"?v.condition:{type:"output-contains",value:""}};return E?ce.nodeId=E:delete ce.nodeId,{...v,condition:ce}}})}})]}),e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.exitGateConditionType","Exit when")}),e.jsxs("select",{value:i,onChange:h=>{const E=h.target.value;M({config:v=>{const U=v.condition&&typeof v.condition=="object"?v.condition:{},ce=String(E==="output-matches"?U.pattern??U.value??"":U.value??U.pattern??""),ne={...U,type:E};return delete ne.pattern,delete ne.value,{...v,condition:E==="output-matches"?{...ne,pattern:ce}:{...ne,value:ce}}}})},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:i==="output-matches"?o("workflowNodes.loopPattern","Pattern"):o("workflowNodes.loopValue","Value")}),e.jsx("input",{value:u,placeholder:i==="output-matches"?"looks good|approved":"looks good",onChange:h=>{const E=h.target.value;M({config:v=>{const U=v.condition&&typeof v.condition=="object"?v.condition:{};return{...v,condition:i==="output-matches"?{...U,type:i,pattern:E}:{...U,type:i,value:E}}}})}})]})]}):null,e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.exitGateNote","Routes early to End (outcome:exit) when the condition matches, or unconditionally when none is set. Falls through (outcome:continue) otherwise.")})]})})():null,f.data.kind==="prompt"||f.data.kind==="gate"||f.data.kind==="script"?e.jsxs("label",{className:"wf-field",children:[e.jsx("span",{children:o("workflowNodes.gateMode","Gate mode")}),e.jsxs("select",{value:String(f.data.config?.gateMode??(f.data.kind==="prompt"?"advisory":"gate")),onChange:t=>M({config:{gateMode:t.target.value}}),children:[e.jsx("option",{value:"advisory",children:o("workflowNodes.advisory","Advisory")}),e.jsx("option",{value:"gate",children:o("workflowNodes.gateBlocks","Gate (blocks)")})]})]}):f.data.kind==="merge"?e.jsx("p",{className:"wf-inspector-note",children:o("workflowNodes.mergeBoundaryNote","Steps before this marker run pre-merge; steps after run post-merge.")}):null]}),!z&&e.jsxs("button",{type:"button",className:"wf-editor-delete wf-inspector-delete","data-testid":"wf-delete-node",onClick:()=>{Wo([f.id]),V(null)},children:[e.jsx(je,{size:13})," ",o("workflowNodes.deleteNode","Delete node")]})]}),xe&&e.jsxs("aside",{className:"wf-editor-inspector","data-testid":"wf-edge-inspector",children:[e.jsxs("div",{className:"wf-inspector-heading",children:[e.jsx("h3",{children:o("workflowNodes.edgeInspector","Edge")}),x&&e.jsxs("button",{type:"button",className:"wf-inspector-toggle wf-inspector-toggle--expanded","data-testid":"wf-edge-inspector-close","aria-expanded":"true",onClick:()=>L(null),children:[e.jsx(Ae,{size:13}),e.jsx("span",{children:o("workflowNodes.collapseInspector","Collapse")})]})]}),e.jsx("fieldset",{className:"wf-inspector-fields",disabled:z,children:Qo==="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(xe.data?.condition??"success");return t.startsWith("outcome:")?t.slice(8):""})(),onChange:t=>{const a=t.target.value;Ht({condition:a?`outcome:${a}`:"success"})},children:[e.jsx("option",{value:"",children:o("workflowNodes.edgeNoVerdict","— success (no verdict) —")}),Gi.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:xe.data?.kind==="rework",onChange:t=>Ht({rework:t.target.checked})}),e.jsx("span",{children:o("workflowNodes.edgeRework","Rework edge (loop back, bounded)")})]}),e.jsx("p",{className:"wf-inspector-note wf-inspector-note--info",children:o("workflowNodes.edgeReworkNote","Rework edges are the only legal cycles — they loop back within the for-each step instance, bounded by Max rework cycles.")})]}):Qo==="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(xe.data?.condition??"success"),onChange:t=>Ht({condition:t.target.value}),children:[e.jsx("option",{value:"success",children:o("workflowNodes.conditionSuccess","success")}),e.jsx("option",{value:"failure",children:o("workflowNodes.conditionFailure","failure")})]})]}):e.jsx("p",{className:"wf-inspector-note",children:o("workflowNodes.edgeConditionLabel","Condition: {{condition}}",{condition:String(xe.data?.condition??"success")})})}),!z&&e.jsxs("button",{type:"button",className:"wf-editor-delete wf-inspector-delete","data-testid":"wf-delete-edge",onClick:()=>{Wo([xe.id]),L(null)},children:[e.jsx(je,{size:13})," ",o("workflowNodes.deleteEdge","Delete edge")]})]})]}),ue&&e.jsx(Ki,{workflows:F,onCreate:ya,onDesign:Ca,onClose:dt})]});return e.jsxs(e.Fragment,{children:[p?e.jsx("div",{className:"workflow-editor-embedded right-dock-embedded-view",children:es}):e.jsx(Vn,{title:o("workflows.title","Workflows"),onClose:Zt,windowKey:"workflow-node-editor",className:"floating-window--workflow-editor",hideHeader:!0,dragHandleSelector:".wf-editor-header",defaultSize:{width:1200,height:820},minSize:{width:640,height:480},persistGeometryKey:"fusion:workflow-node-editor-floating-geometry",children:es}),Oa]})}function sl({isOpen:s,onClose:l,addToast:r,projectId:g,initialPanel:d,initialAction:k,initialWorkflowId:O,presentation:p="modal"}){const F=n.useRef(null),{isEmbedded:R}=Hn(p);return s?e.jsx(Ta,{children:e.jsx(Yi,{onClose:l,addToast:r,projectId:g,initialPanel:d,initialAction:k,initialWorkflowId:O,modalRef:F,isEmbedded:R})}):null}export{sl as WorkflowNodeEditor};
@@ -1 +1 @@
1
- import{r as d,j as s}from"./vendor-react-SZ_qB27O.js";import{i as j,al as v}from"./index-B6ttSchA.js";import{u as N}from"./vendor-i18n-GF3RlKbq.js";function $({value:e,onChange:i,projectId:t,disabled:r=!1,id:n,label:o="Skills"}){const{t:a}=N("app"),[m,k]=d.useState([]),[f,u]=d.useState(!0);d.useEffect(()=>{let l=!1;return u(!0),j(t).then(c=>{l||k(c)}).catch(()=>{l||k([])}).finally(()=>{l||u(!1)}),()=>{l=!0}},[t]);const S=l=>{e.includes(l)||i([...e,l])},x=l=>{i(e.filter(c=>c!==l))},h=l=>m.find(g=>g.id===l)?.name??l,p=m.filter(l=>!e.includes(l.id));return s.jsxs("div",{className:"skill-multiselect","data-testid":"skill-multiselect",children:[o&&s.jsx("label",{htmlFor:n?`${n}-select`:void 0,className:"skill-multiselect-label",children:o}),e.length>0&&s.jsx("div",{className:"skill-multiselect-chips","data-testid":"skill-chips",children:e.map(l=>s.jsxs("span",{className:"skill-chip","data-testid":`skill-chip-${l}`,children:[s.jsx("span",{className:"skill-chip-name",children:h(l)}),s.jsx("button",{type:"button",className:"skill-chip-remove",onClick:()=>x(l),disabled:r,"aria-label":a("skills.removeSkill","Remove {{name}}",{name:h(l)}),"data-testid":`remove-skill-${l}`,children:"×"})]},l))}),s.jsx("div",{className:"skill-multiselect-add",children:f?s.jsx("span",{className:"skill-multiselect-loading","data-testid":"skills-loading",children:s.jsx(v,{label:a("skills.loading","Loading skills…")})}):p.length===0?s.jsx("span",{className:"skill-multiselect-empty","data-testid":"skills-empty",children:e.length===0?a("skills.noSkillsDiscovered","No skills discovered"):a("skills.allSkillsSelected","All skills selected")}):s.jsxs("select",{id:n?`${n}-select`:void 0,className:"select skill-multiselect-dropdown",value:"",onChange:l=>{l.target.value&&(S(l.target.value),l.target.value="")},disabled:r,"data-testid":"skill-dropdown",children:[s.jsx("option",{value:"",children:a("skills.addSkill","Add a skill…")}),p.map(l=>s.jsx("option",{value:l.id,children:l.name},l.id))]})})]})}const L=/(?:^|\/)skills\/([^/]+)\/SKILL\.md$/i;function y(e){const i=e.trim();if(!i)return e;const t=i.match(L);return t?.[1]?t[1]:i}export{$ as S,y as f};
1
+ import{r as d,j as s}from"./vendor-react-SZ_qB27O.js";import{i as j,an as v}from"./index-rfsTNfpA.js";import{u as N}from"./vendor-i18n-GF3RlKbq.js";function $({value:e,onChange:i,projectId:t,disabled:r=!1,id:n,label:o="Skills"}){const{t:a}=N("app"),[m,k]=d.useState([]),[f,u]=d.useState(!0);d.useEffect(()=>{let l=!1;return u(!0),j(t).then(c=>{l||k(c)}).catch(()=>{l||k([])}).finally(()=>{l||u(!1)}),()=>{l=!0}},[t]);const S=l=>{e.includes(l)||i([...e,l])},x=l=>{i(e.filter(c=>c!==l))},h=l=>m.find(g=>g.id===l)?.name??l,p=m.filter(l=>!e.includes(l.id));return s.jsxs("div",{className:"skill-multiselect","data-testid":"skill-multiselect",children:[o&&s.jsx("label",{htmlFor:n?`${n}-select`:void 0,className:"skill-multiselect-label",children:o}),e.length>0&&s.jsx("div",{className:"skill-multiselect-chips","data-testid":"skill-chips",children:e.map(l=>s.jsxs("span",{className:"skill-chip","data-testid":`skill-chip-${l}`,children:[s.jsx("span",{className:"skill-chip-name",children:h(l)}),s.jsx("button",{type:"button",className:"skill-chip-remove",onClick:()=>x(l),disabled:r,"aria-label":a("skills.removeSkill","Remove {{name}}",{name:h(l)}),"data-testid":`remove-skill-${l}`,children:"×"})]},l))}),s.jsx("div",{className:"skill-multiselect-add",children:f?s.jsx("span",{className:"skill-multiselect-loading","data-testid":"skills-loading",children:s.jsx(v,{label:a("skills.loading","Loading skills…")})}):p.length===0?s.jsx("span",{className:"skill-multiselect-empty","data-testid":"skills-empty",children:e.length===0?a("skills.noSkillsDiscovered","No skills discovered"):a("skills.allSkillsSelected","All skills selected")}):s.jsxs("select",{id:n?`${n}-select`:void 0,className:"select skill-multiselect-dropdown",value:"",onChange:l=>{l.target.value&&(S(l.target.value),l.target.value="")},disabled:r,"data-testid":"skill-dropdown",children:[s.jsx("option",{value:"",children:a("skills.addSkill","Add a skill…")}),p.map(l=>s.jsx("option",{value:l.id,children:l.name},l.id))]})})]})}const L=/(?:^|\/)skills\/([^/]+)\/SKILL\.md$/i;function y(e){const i=e.trim();if(!i)return e;const t=i.match(L);return t?.[1]?t[1]:i}export{$ as S,y as f};