@stigmer/react 0.5.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (691) hide show
  1. package/activity/group-activity.d.ts +13 -0
  2. package/activity/group-activity.d.ts.map +1 -0
  3. package/activity/group-activity.js +54 -0
  4. package/activity/group-activity.js.map +1 -0
  5. package/activity/index.d.ts +4 -0
  6. package/activity/index.d.ts.map +1 -0
  7. package/activity/index.js +3 -0
  8. package/activity/index.js.map +1 -0
  9. package/activity/types.d.ts +34 -0
  10. package/activity/types.d.ts.map +1 -0
  11. package/activity/types.js +2 -0
  12. package/activity/types.js.map +1 -0
  13. package/activity/useRecentActivity.d.ts +35 -0
  14. package/activity/useRecentActivity.d.ts.map +1 -0
  15. package/activity/useRecentActivity.js +73 -0
  16. package/activity/useRecentActivity.js.map +1 -0
  17. package/agent/AgentPicker.d.ts.map +1 -1
  18. package/agent/AgentPicker.js +4 -2
  19. package/agent/AgentPicker.js.map +1 -1
  20. package/billing/BillingSection.d.ts.map +1 -1
  21. package/billing/BillingSection.js +1 -1
  22. package/billing/BillingSection.js.map +1 -1
  23. package/composer/ComposerToolbar.d.ts +5 -1
  24. package/composer/ComposerToolbar.d.ts.map +1 -1
  25. package/composer/ComposerToolbar.js +4 -3
  26. package/composer/ComposerToolbar.js.map +1 -1
  27. package/composer/ContextChip.d.ts +7 -2
  28. package/composer/ContextChip.d.ts.map +1 -1
  29. package/composer/ContextChip.js +2 -1
  30. package/composer/ContextChip.js.map +1 -1
  31. package/composer/InteractionModePicker.d.ts +40 -0
  32. package/composer/InteractionModePicker.d.ts.map +1 -0
  33. package/composer/InteractionModePicker.js +76 -0
  34. package/composer/InteractionModePicker.js.map +1 -0
  35. package/composer/SessionComposer.d.ts +64 -64
  36. package/composer/SessionComposer.d.ts.map +1 -1
  37. package/composer/SessionComposer.js +52 -11
  38. package/composer/SessionComposer.js.map +1 -1
  39. package/composer/__tests__/SessionComposer-memo.test.js +10 -5
  40. package/composer/__tests__/SessionComposer-memo.test.js.map +1 -1
  41. package/composer/index.d.ts +3 -1
  42. package/composer/index.d.ts.map +1 -1
  43. package/composer/index.js +1 -0
  44. package/composer/index.js.map +1 -1
  45. package/dashboard/DashboardFailedRuns.d.ts +19 -0
  46. package/dashboard/DashboardFailedRuns.d.ts.map +1 -0
  47. package/dashboard/DashboardFailedRuns.js +35 -0
  48. package/dashboard/DashboardFailedRuns.js.map +1 -0
  49. package/dashboard/DashboardKPICards.d.ts +19 -0
  50. package/dashboard/DashboardKPICards.d.ts.map +1 -0
  51. package/dashboard/DashboardKPICards.js +80 -0
  52. package/dashboard/DashboardKPICards.js.map +1 -0
  53. package/dashboard/OperationalDashboard.d.ts +37 -0
  54. package/dashboard/OperationalDashboard.d.ts.map +1 -0
  55. package/dashboard/OperationalDashboard.js +48 -0
  56. package/dashboard/OperationalDashboard.js.map +1 -0
  57. package/dashboard/index.d.ts +8 -0
  58. package/dashboard/index.d.ts.map +1 -0
  59. package/dashboard/index.js +9 -0
  60. package/dashboard/index.js.map +1 -0
  61. package/dashboard/types.d.ts +49 -0
  62. package/dashboard/types.d.ts.map +1 -0
  63. package/dashboard/types.js +2 -0
  64. package/dashboard/types.js.map +1 -0
  65. package/dashboard/useAgentExecutionSummary.d.ts +33 -0
  66. package/dashboard/useAgentExecutionSummary.d.ts.map +1 -0
  67. package/dashboard/useAgentExecutionSummary.js +32 -0
  68. package/dashboard/useAgentExecutionSummary.js.map +1 -0
  69. package/dashboard/useDashboardFailedRuns.d.ts +18 -0
  70. package/dashboard/useDashboardFailedRuns.d.ts.map +1 -0
  71. package/dashboard/useDashboardFailedRuns.js +86 -0
  72. package/dashboard/useDashboardFailedRuns.js.map +1 -0
  73. package/dashboard/useDashboardSummary.d.ts +32 -0
  74. package/dashboard/useDashboardSummary.d.ts.map +1 -0
  75. package/dashboard/useDashboardSummary.js +67 -0
  76. package/dashboard/useDashboardSummary.js.map +1 -0
  77. package/environment/usePersonalEnvironment.d.ts.map +1 -1
  78. package/environment/usePersonalEnvironment.js +1 -0
  79. package/environment/usePersonalEnvironment.js.map +1 -1
  80. package/execution/ContextGauge.d.ts +45 -0
  81. package/execution/ContextGauge.d.ts.map +1 -0
  82. package/execution/ContextGauge.js +82 -0
  83. package/execution/ContextGauge.js.map +1 -0
  84. package/execution/InteractionModeBadge.d.ts +24 -0
  85. package/execution/InteractionModeBadge.d.ts.map +1 -0
  86. package/execution/InteractionModeBadge.js +29 -0
  87. package/execution/InteractionModeBadge.js.map +1 -0
  88. package/execution/MessageThread.d.ts +33 -3
  89. package/execution/MessageThread.d.ts.map +1 -1
  90. package/execution/MessageThread.js +51 -9
  91. package/execution/MessageThread.js.map +1 -1
  92. package/execution/PlanCompletionCard.d.ts +23 -0
  93. package/execution/PlanCompletionCard.d.ts.map +1 -0
  94. package/execution/PlanCompletionCard.js +28 -0
  95. package/execution/PlanCompletionCard.js.map +1 -0
  96. package/execution/SummarizationBadge.d.ts +30 -0
  97. package/execution/SummarizationBadge.d.ts.map +1 -0
  98. package/execution/SummarizationBadge.js +61 -0
  99. package/execution/SummarizationBadge.js.map +1 -0
  100. package/execution/SummarizationCard.d.ts +27 -0
  101. package/execution/SummarizationCard.d.ts.map +1 -0
  102. package/execution/SummarizationCard.js +47 -0
  103. package/execution/SummarizationCard.js.map +1 -0
  104. package/execution/__tests__/PlanCompletionCard.test.d.ts +2 -0
  105. package/execution/__tests__/PlanCompletionCard.test.d.ts.map +1 -0
  106. package/execution/__tests__/PlanCompletionCard.test.js +53 -0
  107. package/execution/__tests__/PlanCompletionCard.test.js.map +1 -0
  108. package/execution/__tests__/buildThreadItems-plan-completion.test.d.ts +2 -0
  109. package/execution/__tests__/buildThreadItems-plan-completion.test.d.ts.map +1 -0
  110. package/execution/__tests__/buildThreadItems-plan-completion.test.js +137 -0
  111. package/execution/__tests__/buildThreadItems-plan-completion.test.js.map +1 -0
  112. package/execution/__tests__/useContextWindow.test.d.ts +2 -0
  113. package/execution/__tests__/useContextWindow.test.d.ts.map +1 -0
  114. package/execution/__tests__/useContextWindow.test.js +121 -0
  115. package/execution/__tests__/useContextWindow.test.js.map +1 -0
  116. package/execution/index.d.ts +12 -0
  117. package/execution/index.d.ts.map +1 -1
  118. package/execution/index.js +6 -0
  119. package/execution/index.js.map +1 -1
  120. package/execution/useContextWindow.d.ts +71 -0
  121. package/execution/useContextWindow.d.ts.map +1 -0
  122. package/execution/useContextWindow.js +91 -0
  123. package/execution/useContextWindow.js.map +1 -0
  124. package/execution/useCreateAgentExecution.d.ts +9 -0
  125. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  126. package/execution/useCreateAgentExecution.js +15 -3
  127. package/execution/useCreateAgentExecution.js.map +1 -1
  128. package/index.d.ts +11 -6
  129. package/index.d.ts.map +1 -1
  130. package/index.js +13 -3
  131. package/index.js.map +1 -1
  132. package/inline-edit/InlineEditKeyValue.d.ts +5 -1
  133. package/inline-edit/InlineEditKeyValue.d.ts.map +1 -1
  134. package/inline-edit/InlineEditKeyValue.js +3 -3
  135. package/inline-edit/InlineEditKeyValue.js.map +1 -1
  136. package/internal/VirtualizedThread.d.ts +2 -1
  137. package/internal/VirtualizedThread.d.ts.map +1 -1
  138. package/internal/VirtualizedThread.js +3 -2
  139. package/internal/VirtualizedThread.js.map +1 -1
  140. package/internal/store/index.d.ts +1 -0
  141. package/internal/store/index.d.ts.map +1 -1
  142. package/internal/store/index.js +1 -0
  143. package/internal/store/index.js.map +1 -1
  144. package/internal/store/workflow-execution-event-store.d.ts +92 -0
  145. package/internal/store/workflow-execution-event-store.d.ts.map +1 -0
  146. package/internal/store/workflow-execution-event-store.js +298 -0
  147. package/internal/store/workflow-execution-event-store.js.map +1 -0
  148. package/internal/useFetch.js +2 -2
  149. package/internal/useFetch.js.map +1 -1
  150. package/library/ScopeToggle.d.ts +13 -9
  151. package/library/ScopeToggle.d.ts.map +1 -1
  152. package/library/ScopeToggle.js +43 -22
  153. package/library/ScopeToggle.js.map +1 -1
  154. package/library/VisibilityToggle.js +14 -5
  155. package/library/VisibilityToggle.js.map +1 -1
  156. package/library/index.d.ts +1 -0
  157. package/library/index.d.ts.map +1 -1
  158. package/library/index.js +1 -0
  159. package/library/index.js.map +1 -1
  160. package/library/useExportResource.d.ts +3 -2
  161. package/library/useExportResource.d.ts.map +1 -1
  162. package/library/useExportResource.js +11 -6
  163. package/library/useExportResource.js.map +1 -1
  164. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  165. package/mcp-server/McpServerDetailView.js +169 -58
  166. package/mcp-server/McpServerDetailView.js.map +1 -1
  167. package/mcp-server/McpServerPicker.d.ts.map +1 -1
  168. package/mcp-server/McpServerPicker.js +4 -2
  169. package/mcp-server/McpServerPicker.js.map +1 -1
  170. package/models/ModelRegistryContext.d.ts +2 -0
  171. package/models/ModelRegistryContext.d.ts.map +1 -1
  172. package/models/ModelRegistryContext.js +1 -0
  173. package/models/ModelRegistryContext.js.map +1 -1
  174. package/models/ModelSelector.d.ts.map +1 -1
  175. package/models/ModelSelector.js +2 -2
  176. package/models/ModelSelector.js.map +1 -1
  177. package/models/__tests__/useModelRegistry.test.js +4 -3
  178. package/models/__tests__/useModelRegistry.test.js.map +1 -1
  179. package/models/useModelRegistry.d.ts +2 -0
  180. package/models/useModelRegistry.d.ts.map +1 -1
  181. package/models/useModelRegistry.js +3 -2
  182. package/models/useModelRegistry.js.map +1 -1
  183. package/package.json +16 -5
  184. package/provider.d.ts.map +1 -1
  185. package/provider.js +232 -22
  186. package/provider.js.map +1 -1
  187. package/resource-detail/ResourceDetailShell.d.ts +1 -1
  188. package/resource-detail/ResourceDetailShell.d.ts.map +1 -1
  189. package/resource-detail/ResourceDetailShell.js +6 -6
  190. package/resource-detail/ResourceDetailShell.js.map +1 -1
  191. package/resource-detail/types.d.ts +23 -0
  192. package/resource-detail/types.d.ts.map +1 -1
  193. package/resource-detail/useDeleteResource.d.ts +1 -1
  194. package/resource-detail/useDeleteResource.d.ts.map +1 -1
  195. package/resource-detail/useDeleteResource.js +5 -0
  196. package/resource-detail/useDeleteResource.js.map +1 -1
  197. package/resource-workbench/components/ResourceWorkbench.d.ts.map +1 -1
  198. package/resource-workbench/components/ResourceWorkbench.js +2 -1
  199. package/resource-workbench/components/ResourceWorkbench.js.map +1 -1
  200. package/session/__tests__/session-spec-converters.test.d.ts +2 -0
  201. package/session/__tests__/session-spec-converters.test.d.ts.map +1 -0
  202. package/session/__tests__/session-spec-converters.test.js +162 -0
  203. package/session/__tests__/session-spec-converters.test.js.map +1 -0
  204. package/session/__tests__/useNewSessionFlow.test.js +2 -2
  205. package/session/__tests__/useNewSessionFlow.test.js.map +1 -1
  206. package/session/__tests__/usePersistedModel.test.js +1 -1
  207. package/session/__tests__/usePersistedModel.test.js.map +1 -1
  208. package/session/group-sessions.d.ts +17 -0
  209. package/session/group-sessions.d.ts.map +1 -1
  210. package/session/group-sessions.js +46 -0
  211. package/session/group-sessions.js.map +1 -1
  212. package/session/index.d.ts +4 -2
  213. package/session/index.d.ts.map +1 -1
  214. package/session/index.js +2 -1
  215. package/session/index.js.map +1 -1
  216. package/session/session-spec-converters.d.ts +24 -0
  217. package/session/session-spec-converters.d.ts.map +1 -0
  218. package/session/session-spec-converters.js +72 -0
  219. package/session/session-spec-converters.js.map +1 -0
  220. package/session/useNewSessionFlow.d.ts.map +1 -1
  221. package/session/useNewSessionFlow.js +1 -0
  222. package/session/useNewSessionFlow.js.map +1 -1
  223. package/session/useSessionConversation.d.ts +7 -0
  224. package/session/useSessionConversation.d.ts.map +1 -1
  225. package/session/useSessionConversation.js +2 -56
  226. package/session/useSessionConversation.js.map +1 -1
  227. package/session/useSessionPageFlow.d.ts +5 -0
  228. package/session/useSessionPageFlow.d.ts.map +1 -1
  229. package/session/useSessionPageFlow.js +21 -6
  230. package/session/useSessionPageFlow.js.map +1 -1
  231. package/session/useSessionSearch.d.ts +57 -0
  232. package/session/useSessionSearch.d.ts.map +1 -0
  233. package/session/useSessionSearch.js +94 -0
  234. package/session/useSessionSearch.js.map +1 -0
  235. package/session/useSessionUsage.d.ts.map +1 -1
  236. package/session/useSessionUsage.js +65 -4
  237. package/session/useSessionUsage.js.map +1 -1
  238. package/settings/UsageSection.d.ts.map +1 -1
  239. package/settings/UsageSection.js +1 -4
  240. package/settings/UsageSection.js.map +1 -1
  241. package/skill/SkillPicker.d.ts.map +1 -1
  242. package/skill/SkillPicker.js +4 -2
  243. package/skill/SkillPicker.js.map +1 -1
  244. package/src/activity/group-activity.ts +65 -0
  245. package/src/activity/index.ts +13 -0
  246. package/src/activity/types.ts +35 -0
  247. package/src/activity/useRecentActivity.ts +131 -0
  248. package/src/agent/AgentPicker.tsx +6 -1
  249. package/src/billing/BillingSection.tsx +3 -2
  250. package/src/composer/ComposerToolbar.tsx +19 -1
  251. package/src/composer/ContextChip.tsx +20 -11
  252. package/src/composer/InteractionModePicker.tsx +189 -0
  253. package/src/composer/SessionComposer.tsx +137 -11
  254. package/src/composer/__tests__/SessionComposer-memo.test.ts +11 -6
  255. package/src/composer/index.ts +7 -0
  256. package/src/dashboard/DashboardFailedRuns.tsx +109 -0
  257. package/src/dashboard/DashboardKPICards.tsx +128 -0
  258. package/src/dashboard/OperationalDashboard.tsx +96 -0
  259. package/src/dashboard/index.ts +37 -0
  260. package/src/dashboard/types.ts +50 -0
  261. package/src/dashboard/useAgentExecutionSummary.ts +71 -0
  262. package/src/dashboard/useDashboardFailedRuns.ts +122 -0
  263. package/src/dashboard/useDashboardSummary.ts +109 -0
  264. package/src/environment/usePersonalEnvironment.ts +1 -0
  265. package/src/execution/ContextGauge.tsx +243 -0
  266. package/src/execution/InteractionModeBadge.tsx +70 -0
  267. package/src/execution/MessageThread.tsx +88 -3
  268. package/src/execution/PlanCompletionCard.tsx +105 -0
  269. package/src/execution/SummarizationBadge.tsx +188 -0
  270. package/src/execution/SummarizationCard.tsx +126 -0
  271. package/src/execution/__tests__/PlanCompletionCard.test.tsx +67 -0
  272. package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +197 -0
  273. package/src/execution/__tests__/useContextWindow.test.ts +167 -0
  274. package/src/execution/index.ts +22 -0
  275. package/src/execution/useContextWindow.ts +148 -0
  276. package/src/execution/useCreateAgentExecution.ts +26 -3
  277. package/src/index.ts +227 -0
  278. package/src/inline-edit/InlineEditKeyValue.tsx +23 -0
  279. package/src/internal/VirtualizedThread.tsx +4 -1
  280. package/src/internal/store/index.ts +6 -0
  281. package/src/internal/store/workflow-execution-event-store.ts +391 -0
  282. package/src/internal/useFetch.ts +2 -2
  283. package/src/library/ScopeToggle.tsx +88 -20
  284. package/src/library/VisibilityToggle.tsx +54 -13
  285. package/src/library/index.ts +2 -0
  286. package/src/library/useExportResource.ts +12 -9
  287. package/src/mcp-server/McpServerDetailView.tsx +509 -203
  288. package/src/mcp-server/McpServerPicker.tsx +6 -1
  289. package/src/models/ModelRegistryContext.ts +3 -0
  290. package/src/models/ModelSelector.tsx +25 -2
  291. package/src/models/__tests__/useModelRegistry.test.tsx +5 -3
  292. package/src/models/useModelRegistry.ts +5 -2
  293. package/src/provider.tsx +264 -26
  294. package/src/resource-detail/ResourceDetailShell.tsx +21 -4
  295. package/src/resource-detail/types.ts +25 -0
  296. package/src/resource-detail/useDeleteResource.ts +6 -1
  297. package/src/resource-workbench/components/ResourceWorkbench.tsx +4 -0
  298. package/src/session/__tests__/session-spec-converters.test.ts +185 -0
  299. package/src/session/__tests__/useNewSessionFlow.test.tsx +2 -2
  300. package/src/session/__tests__/usePersistedModel.test.tsx +1 -1
  301. package/src/session/group-sessions.ts +65 -0
  302. package/src/session/index.ts +8 -2
  303. package/src/session/session-spec-converters.ts +86 -0
  304. package/src/session/useNewSessionFlow.ts +1 -0
  305. package/src/session/useSessionConversation.ts +13 -64
  306. package/src/session/useSessionPageFlow.ts +29 -7
  307. package/src/session/useSessionSearch.ts +149 -0
  308. package/src/session/useSessionUsage.ts +72 -4
  309. package/src/settings/UsageSection.tsx +1 -9
  310. package/src/skill/SkillPicker.tsx +6 -1
  311. package/src/workflow/ApprovalFormBuilder.tsx +1017 -0
  312. package/src/workflow/BranchConditionBuilder.tsx +451 -0
  313. package/src/workflow/CanvasActionsContext.ts +12 -0
  314. package/src/workflow/CanvasContextMenu.tsx +364 -0
  315. package/src/workflow/CanvasTaskNode.tsx +372 -0
  316. package/src/workflow/CanvasTransitionEdge.tsx +122 -0
  317. package/src/workflow/CostByWorkflowChart.tsx +120 -0
  318. package/src/workflow/ExecutionSummaryWidget.tsx +194 -0
  319. package/src/workflow/ExecutionTrendChart.tsx +157 -0
  320. package/src/workflow/FailedRunsWidget.tsx +109 -0
  321. package/src/workflow/PendingApprovalsWidget.tsx +115 -0
  322. package/src/workflow/TaskConfigForm.tsx +618 -0
  323. package/src/workflow/TaskKindRegistryContext.ts +36 -0
  324. package/src/workflow/TaskPickerPopover.tsx +326 -0
  325. package/src/workflow/WorkflowArchitectDialog.tsx +505 -0
  326. package/src/workflow/WorkflowCanvasEditor.tsx +651 -0
  327. package/src/workflow/WorkflowCanvasInner.tsx +160 -0
  328. package/src/workflow/WorkflowDashboard.tsx +124 -0
  329. package/src/workflow/WorkflowDetailView.tsx +527 -0
  330. package/src/workflow/WorkflowEditorView.tsx +547 -0
  331. package/src/workflow/WorkflowExecutionApprovalCard.tsx +129 -0
  332. package/src/workflow/WorkflowExecutionArtifactPanel.tsx +112 -0
  333. package/src/workflow/WorkflowExecutionCostPanel.tsx +131 -0
  334. package/src/workflow/WorkflowExecutionHeader.tsx +194 -0
  335. package/src/workflow/WorkflowExecutionPhaseBadge.tsx +188 -0
  336. package/src/workflow/WorkflowExecutionTaskPanel.tsx +135 -0
  337. package/src/workflow/WorkflowExecutionTimeline.tsx +118 -0
  338. package/src/workflow/WorkflowExecutionTimelineEvent.tsx +488 -0
  339. package/src/workflow/WorkflowExecutionViewer.tsx +248 -0
  340. package/src/workflow/WorkflowInspectorPanel.tsx +568 -0
  341. package/src/workflow/WorkflowRefinePanel.tsx +411 -0
  342. package/src/workflow/WorkflowRepairCard.tsx +433 -0
  343. package/src/workflow/WorkflowRunDialog.tsx +220 -0
  344. package/src/workflow/WorkflowRunForm.tsx +245 -0
  345. package/src/workflow/WorkflowTaskList.tsx +177 -0
  346. package/src/workflow/WorkflowTaskPalette.tsx +248 -0
  347. package/src/workflow/WorkflowTopologyGraph.tsx +250 -0
  348. package/src/workflow/WorkflowYamlEditor.tsx +271 -0
  349. package/src/workflow/__tests__/starter-workflow-yaml.test.ts +57 -0
  350. package/src/workflow/canvas-constants.ts +87 -0
  351. package/src/workflow/canvas-icons.tsx +36 -0
  352. package/src/workflow/extract-workflow-yaml.ts +87 -0
  353. package/src/workflow/graph-commands.ts +675 -0
  354. package/src/workflow/index.ts +375 -0
  355. package/src/workflow/serialize-workflow-yaml.ts +546 -0
  356. package/src/workflow/starter-workflow-yaml.ts +29 -0
  357. package/src/workflow/types.ts +99 -0
  358. package/src/workflow/useCanvasKeyboardShortcuts.ts +134 -0
  359. package/src/workflow/useDiagnoseExecutionFlow.ts +378 -0
  360. package/src/workflow/useGraphHistory.ts +138 -0
  361. package/src/workflow/usePendingApprovals.ts +89 -0
  362. package/src/workflow/useRefineWorkflowFlow.ts +321 -0
  363. package/src/workflow/useResolveAgentExecutionSession.ts +57 -0
  364. package/src/workflow/useRunWorkflowFlow.ts +235 -0
  365. package/src/workflow/useTaskKindRegistry.ts +135 -0
  366. package/src/workflow/useWorkflow.ts +78 -0
  367. package/src/workflow/useWorkflowArchitectFlow.ts +303 -0
  368. package/src/workflow/useWorkflowCanvas.ts +882 -0
  369. package/src/workflow/useWorkflowCount.ts +66 -0
  370. package/src/workflow/useWorkflowDashboardSummary.ts +71 -0
  371. package/src/workflow/useWorkflowEditor.ts +106 -0
  372. package/src/workflow/useWorkflowExecution.ts +67 -0
  373. package/src/workflow/useWorkflowExecutionActions.ts +179 -0
  374. package/src/workflow/useWorkflowExecutionArtifacts.ts +57 -0
  375. package/src/workflow/useWorkflowExecutionEventLog.ts +111 -0
  376. package/src/workflow/useWorkflowExecutionEventStream.ts +244 -0
  377. package/src/workflow/useWorkflowExecutionList.ts +121 -0
  378. package/src/workflow/useWorkflowInstances.ts +62 -0
  379. package/src/workflow/useWorkflowList.ts +79 -0
  380. package/src/workflow/useWorkflowSave.ts +84 -0
  381. package/src/workflow/useWorkflowTopology.ts +229 -0
  382. package/src/workflow/useWorkflowValidation.ts +329 -0
  383. package/src/workflow/useWorkflowYaml.ts +49 -0
  384. package/src/workflow/workflow-graph-conversions.ts +796 -0
  385. package/src/workflow/workflow-graph-model.ts +83 -0
  386. package/src/workflow/workflow-yaml-diff.ts +132 -0
  387. package/styles.css +1 -1
  388. package/workflow/ApprovalFormBuilder.d.ts +24 -0
  389. package/workflow/ApprovalFormBuilder.d.ts.map +1 -0
  390. package/workflow/ApprovalFormBuilder.js +347 -0
  391. package/workflow/ApprovalFormBuilder.js.map +1 -0
  392. package/workflow/BranchConditionBuilder.d.ts +29 -0
  393. package/workflow/BranchConditionBuilder.d.ts.map +1 -0
  394. package/workflow/BranchConditionBuilder.js +170 -0
  395. package/workflow/BranchConditionBuilder.js.map +1 -0
  396. package/workflow/CanvasActionsContext.d.ts +8 -0
  397. package/workflow/CanvasActionsContext.d.ts.map +1 -0
  398. package/workflow/CanvasActionsContext.js +4 -0
  399. package/workflow/CanvasActionsContext.js.map +1 -0
  400. package/workflow/CanvasContextMenu.d.ts +59 -0
  401. package/workflow/CanvasContextMenu.d.ts.map +1 -0
  402. package/workflow/CanvasContextMenu.js +98 -0
  403. package/workflow/CanvasContextMenu.js.map +1 -0
  404. package/workflow/CanvasTaskNode.d.ts +21 -0
  405. package/workflow/CanvasTaskNode.d.ts.map +1 -0
  406. package/workflow/CanvasTaskNode.js +125 -0
  407. package/workflow/CanvasTaskNode.js.map +1 -0
  408. package/workflow/CanvasTransitionEdge.d.ts +24 -0
  409. package/workflow/CanvasTransitionEdge.d.ts.map +1 -0
  410. package/workflow/CanvasTransitionEdge.js +50 -0
  411. package/workflow/CanvasTransitionEdge.js.map +1 -0
  412. package/workflow/CostByWorkflowChart.d.ts +15 -0
  413. package/workflow/CostByWorkflowChart.d.ts.map +1 -0
  414. package/workflow/CostByWorkflowChart.js +45 -0
  415. package/workflow/CostByWorkflowChart.js.map +1 -0
  416. package/workflow/ExecutionSummaryWidget.d.ts +16 -0
  417. package/workflow/ExecutionSummaryWidget.d.ts.map +1 -0
  418. package/workflow/ExecutionSummaryWidget.js +93 -0
  419. package/workflow/ExecutionSummaryWidget.js.map +1 -0
  420. package/workflow/ExecutionTrendChart.d.ts +14 -0
  421. package/workflow/ExecutionTrendChart.d.ts.map +1 -0
  422. package/workflow/ExecutionTrendChart.js +67 -0
  423. package/workflow/ExecutionTrendChart.js.map +1 -0
  424. package/workflow/FailedRunsWidget.d.ts +19 -0
  425. package/workflow/FailedRunsWidget.d.ts.map +1 -0
  426. package/workflow/FailedRunsWidget.js +37 -0
  427. package/workflow/FailedRunsWidget.js.map +1 -0
  428. package/workflow/PendingApprovalsWidget.d.ts +19 -0
  429. package/workflow/PendingApprovalsWidget.d.ts.map +1 -0
  430. package/workflow/PendingApprovalsWidget.js +35 -0
  431. package/workflow/PendingApprovalsWidget.js.map +1 -0
  432. package/workflow/TaskConfigForm.d.ts +29 -0
  433. package/workflow/TaskConfigForm.d.ts.map +1 -0
  434. package/workflow/TaskConfigForm.js +230 -0
  435. package/workflow/TaskConfigForm.js.map +1 -0
  436. package/workflow/TaskKindRegistryContext.d.ts +24 -0
  437. package/workflow/TaskKindRegistryContext.d.ts.map +1 -0
  438. package/workflow/TaskKindRegistryContext.js +25 -0
  439. package/workflow/TaskKindRegistryContext.js.map +1 -0
  440. package/workflow/TaskPickerPopover.d.ts +33 -0
  441. package/workflow/TaskPickerPopover.d.ts.map +1 -0
  442. package/workflow/TaskPickerPopover.js +110 -0
  443. package/workflow/TaskPickerPopover.js.map +1 -0
  444. package/workflow/WorkflowArchitectDialog.d.ts +48 -0
  445. package/workflow/WorkflowArchitectDialog.d.ts.map +1 -0
  446. package/workflow/WorkflowArchitectDialog.js +129 -0
  447. package/workflow/WorkflowArchitectDialog.js.map +1 -0
  448. package/workflow/WorkflowCanvasEditor.d.ts +38 -0
  449. package/workflow/WorkflowCanvasEditor.d.ts.map +1 -0
  450. package/workflow/WorkflowCanvasEditor.js +287 -0
  451. package/workflow/WorkflowCanvasEditor.js.map +1 -0
  452. package/workflow/WorkflowCanvasInner.d.ts +32 -0
  453. package/workflow/WorkflowCanvasInner.d.ts.map +1 -0
  454. package/workflow/WorkflowCanvasInner.js +49 -0
  455. package/workflow/WorkflowCanvasInner.js.map +1 -0
  456. package/workflow/WorkflowDashboard.d.ts +35 -0
  457. package/workflow/WorkflowDashboard.d.ts.map +1 -0
  458. package/workflow/WorkflowDashboard.js +59 -0
  459. package/workflow/WorkflowDashboard.js.map +1 -0
  460. package/workflow/WorkflowDetailView.d.ts +63 -0
  461. package/workflow/WorkflowDetailView.d.ts.map +1 -0
  462. package/workflow/WorkflowDetailView.js +202 -0
  463. package/workflow/WorkflowDetailView.js.map +1 -0
  464. package/workflow/WorkflowEditorView.d.ts +43 -0
  465. package/workflow/WorkflowEditorView.d.ts.map +1 -0
  466. package/workflow/WorkflowEditorView.js +165 -0
  467. package/workflow/WorkflowEditorView.js.map +1 -0
  468. package/workflow/WorkflowExecutionApprovalCard.d.ts +27 -0
  469. package/workflow/WorkflowExecutionApprovalCard.d.ts.map +1 -0
  470. package/workflow/WorkflowExecutionApprovalCard.js +32 -0
  471. package/workflow/WorkflowExecutionApprovalCard.js.map +1 -0
  472. package/workflow/WorkflowExecutionArtifactPanel.d.ts +15 -0
  473. package/workflow/WorkflowExecutionArtifactPanel.d.ts.map +1 -0
  474. package/workflow/WorkflowExecutionArtifactPanel.js +53 -0
  475. package/workflow/WorkflowExecutionArtifactPanel.js.map +1 -0
  476. package/workflow/WorkflowExecutionCostPanel.d.ts +18 -0
  477. package/workflow/WorkflowExecutionCostPanel.d.ts.map +1 -0
  478. package/workflow/WorkflowExecutionCostPanel.js +44 -0
  479. package/workflow/WorkflowExecutionCostPanel.js.map +1 -0
  480. package/workflow/WorkflowExecutionHeader.d.ts +26 -0
  481. package/workflow/WorkflowExecutionHeader.d.ts.map +1 -0
  482. package/workflow/WorkflowExecutionHeader.js +68 -0
  483. package/workflow/WorkflowExecutionHeader.js.map +1 -0
  484. package/workflow/WorkflowExecutionPhaseBadge.d.ts +23 -0
  485. package/workflow/WorkflowExecutionPhaseBadge.d.ts.map +1 -0
  486. package/workflow/WorkflowExecutionPhaseBadge.js +99 -0
  487. package/workflow/WorkflowExecutionPhaseBadge.js.map +1 -0
  488. package/workflow/WorkflowExecutionTaskPanel.d.ts +24 -0
  489. package/workflow/WorkflowExecutionTaskPanel.d.ts.map +1 -0
  490. package/workflow/WorkflowExecutionTaskPanel.js +59 -0
  491. package/workflow/WorkflowExecutionTaskPanel.js.map +1 -0
  492. package/workflow/WorkflowExecutionTimeline.d.ts +27 -0
  493. package/workflow/WorkflowExecutionTimeline.d.ts.map +1 -0
  494. package/workflow/WorkflowExecutionTimeline.js +51 -0
  495. package/workflow/WorkflowExecutionTimeline.js.map +1 -0
  496. package/workflow/WorkflowExecutionTimelineEvent.d.ts +18 -0
  497. package/workflow/WorkflowExecutionTimelineEvent.d.ts.map +1 -0
  498. package/workflow/WorkflowExecutionTimelineEvent.js +210 -0
  499. package/workflow/WorkflowExecutionTimelineEvent.js.map +1 -0
  500. package/workflow/WorkflowExecutionViewer.d.ts +45 -0
  501. package/workflow/WorkflowExecutionViewer.d.ts.map +1 -0
  502. package/workflow/WorkflowExecutionViewer.js +75 -0
  503. package/workflow/WorkflowExecutionViewer.js.map +1 -0
  504. package/workflow/WorkflowInspectorPanel.d.ts +46 -0
  505. package/workflow/WorkflowInspectorPanel.d.ts.map +1 -0
  506. package/workflow/WorkflowInspectorPanel.js +152 -0
  507. package/workflow/WorkflowInspectorPanel.js.map +1 -0
  508. package/workflow/WorkflowRefinePanel.d.ts +30 -0
  509. package/workflow/WorkflowRefinePanel.d.ts.map +1 -0
  510. package/workflow/WorkflowRefinePanel.js +107 -0
  511. package/workflow/WorkflowRefinePanel.js.map +1 -0
  512. package/workflow/WorkflowRepairCard.d.ts +35 -0
  513. package/workflow/WorkflowRepairCard.d.ts.map +1 -0
  514. package/workflow/WorkflowRepairCard.js +113 -0
  515. package/workflow/WorkflowRepairCard.js.map +1 -0
  516. package/workflow/WorkflowRunDialog.d.ts +51 -0
  517. package/workflow/WorkflowRunDialog.d.ts.map +1 -0
  518. package/workflow/WorkflowRunDialog.js +75 -0
  519. package/workflow/WorkflowRunDialog.js.map +1 -0
  520. package/workflow/WorkflowRunForm.d.ts +62 -0
  521. package/workflow/WorkflowRunForm.d.ts.map +1 -0
  522. package/workflow/WorkflowRunForm.js +64 -0
  523. package/workflow/WorkflowRunForm.js.map +1 -0
  524. package/workflow/WorkflowTaskList.d.ts +25 -0
  525. package/workflow/WorkflowTaskList.d.ts.map +1 -0
  526. package/workflow/WorkflowTaskList.js +89 -0
  527. package/workflow/WorkflowTaskList.js.map +1 -0
  528. package/workflow/WorkflowTaskPalette.d.ts +22 -0
  529. package/workflow/WorkflowTaskPalette.d.ts.map +1 -0
  530. package/workflow/WorkflowTaskPalette.js +83 -0
  531. package/workflow/WorkflowTaskPalette.js.map +1 -0
  532. package/workflow/WorkflowTopologyGraph.d.ts +22 -0
  533. package/workflow/WorkflowTopologyGraph.d.ts.map +1 -0
  534. package/workflow/WorkflowTopologyGraph.js +123 -0
  535. package/workflow/WorkflowTopologyGraph.js.map +1 -0
  536. package/workflow/WorkflowYamlEditor.d.ts +43 -0
  537. package/workflow/WorkflowYamlEditor.d.ts.map +1 -0
  538. package/workflow/WorkflowYamlEditor.js +215 -0
  539. package/workflow/WorkflowYamlEditor.js.map +1 -0
  540. package/workflow/__tests__/starter-workflow-yaml.test.d.ts +2 -0
  541. package/workflow/__tests__/starter-workflow-yaml.test.d.ts.map +1 -0
  542. package/workflow/__tests__/starter-workflow-yaml.test.js +44 -0
  543. package/workflow/__tests__/starter-workflow-yaml.test.js.map +1 -0
  544. package/workflow/canvas-constants.d.ts +56 -0
  545. package/workflow/canvas-constants.d.ts.map +1 -0
  546. package/workflow/canvas-constants.js +74 -0
  547. package/workflow/canvas-constants.js.map +1 -0
  548. package/workflow/canvas-icons.d.ts +13 -0
  549. package/workflow/canvas-icons.d.ts.map +1 -0
  550. package/workflow/canvas-icons.js +21 -0
  551. package/workflow/canvas-icons.js.map +1 -0
  552. package/workflow/extract-workflow-yaml.d.ts +22 -0
  553. package/workflow/extract-workflow-yaml.d.ts.map +1 -0
  554. package/workflow/extract-workflow-yaml.js +63 -0
  555. package/workflow/extract-workflow-yaml.js.map +1 -0
  556. package/workflow/graph-commands.d.ts +209 -0
  557. package/workflow/graph-commands.d.ts.map +1 -0
  558. package/workflow/graph-commands.js +516 -0
  559. package/workflow/graph-commands.js.map +1 -0
  560. package/workflow/index.d.ts +66 -0
  561. package/workflow/index.d.ts.map +1 -0
  562. package/workflow/index.js +88 -0
  563. package/workflow/index.js.map +1 -0
  564. package/workflow/serialize-workflow-yaml.d.ts +39 -0
  565. package/workflow/serialize-workflow-yaml.d.ts.map +1 -0
  566. package/workflow/serialize-workflow-yaml.js +413 -0
  567. package/workflow/serialize-workflow-yaml.js.map +1 -0
  568. package/workflow/starter-workflow-yaml.d.ts +12 -0
  569. package/workflow/starter-workflow-yaml.d.ts.map +1 -0
  570. package/workflow/starter-workflow-yaml.js +30 -0
  571. package/workflow/starter-workflow-yaml.js.map +1 -0
  572. package/workflow/types.d.ts +80 -0
  573. package/workflow/types.d.ts.map +1 -0
  574. package/workflow/types.js +2 -0
  575. package/workflow/types.js.map +1 -0
  576. package/workflow/useCanvasKeyboardShortcuts.d.ts +34 -0
  577. package/workflow/useCanvasKeyboardShortcuts.d.ts.map +1 -0
  578. package/workflow/useCanvasKeyboardShortcuts.js +108 -0
  579. package/workflow/useCanvasKeyboardShortcuts.js.map +1 -0
  580. package/workflow/useDiagnoseExecutionFlow.d.ts +87 -0
  581. package/workflow/useDiagnoseExecutionFlow.d.ts.map +1 -0
  582. package/workflow/useDiagnoseExecutionFlow.js +257 -0
  583. package/workflow/useDiagnoseExecutionFlow.js.map +1 -0
  584. package/workflow/useGraphHistory.d.ts +28 -0
  585. package/workflow/useGraphHistory.d.ts.map +1 -0
  586. package/workflow/useGraphHistory.js +106 -0
  587. package/workflow/useGraphHistory.js.map +1 -0
  588. package/workflow/usePendingApprovals.d.ts +35 -0
  589. package/workflow/usePendingApprovals.d.ts.map +1 -0
  590. package/workflow/usePendingApprovals.js +50 -0
  591. package/workflow/usePendingApprovals.js.map +1 -0
  592. package/workflow/useRefineWorkflowFlow.d.ts +75 -0
  593. package/workflow/useRefineWorkflowFlow.d.ts.map +1 -0
  594. package/workflow/useRefineWorkflowFlow.js +216 -0
  595. package/workflow/useRefineWorkflowFlow.js.map +1 -0
  596. package/workflow/useResolveAgentExecutionSession.d.ts +33 -0
  597. package/workflow/useResolveAgentExecutionSession.d.ts.map +1 -0
  598. package/workflow/useResolveAgentExecutionSession.js +37 -0
  599. package/workflow/useResolveAgentExecutionSession.js.map +1 -0
  600. package/workflow/useRunWorkflowFlow.d.ts +82 -0
  601. package/workflow/useRunWorkflowFlow.d.ts.map +1 -0
  602. package/workflow/useRunWorkflowFlow.js +145 -0
  603. package/workflow/useRunWorkflowFlow.js.map +1 -0
  604. package/workflow/useTaskKindRegistry.d.ts +96 -0
  605. package/workflow/useTaskKindRegistry.d.ts.map +1 -0
  606. package/workflow/useTaskKindRegistry.js +75 -0
  607. package/workflow/useTaskKindRegistry.js.map +1 -0
  608. package/workflow/useWorkflow.d.ts +47 -0
  609. package/workflow/useWorkflow.d.ts.map +1 -0
  610. package/workflow/useWorkflow.js +53 -0
  611. package/workflow/useWorkflow.js.map +1 -0
  612. package/workflow/useWorkflowArchitectFlow.d.ts +96 -0
  613. package/workflow/useWorkflowArchitectFlow.d.ts.map +1 -0
  614. package/workflow/useWorkflowArchitectFlow.js +179 -0
  615. package/workflow/useWorkflowArchitectFlow.js.map +1 -0
  616. package/workflow/useWorkflowCanvas.d.ts +66 -0
  617. package/workflow/useWorkflowCanvas.d.ts.map +1 -0
  618. package/workflow/useWorkflowCanvas.js +628 -0
  619. package/workflow/useWorkflowCanvas.js.map +1 -0
  620. package/workflow/useWorkflowCount.d.ts +47 -0
  621. package/workflow/useWorkflowCount.d.ts.map +1 -0
  622. package/workflow/useWorkflowCount.js +26 -0
  623. package/workflow/useWorkflowCount.js.map +1 -0
  624. package/workflow/useWorkflowDashboardSummary.d.ts +34 -0
  625. package/workflow/useWorkflowDashboardSummary.d.ts.map +1 -0
  626. package/workflow/useWorkflowDashboardSummary.js +33 -0
  627. package/workflow/useWorkflowDashboardSummary.js.map +1 -0
  628. package/workflow/useWorkflowEditor.d.ts +45 -0
  629. package/workflow/useWorkflowEditor.d.ts.map +1 -0
  630. package/workflow/useWorkflowEditor.js +52 -0
  631. package/workflow/useWorkflowEditor.js.map +1 -0
  632. package/workflow/useWorkflowExecution.d.ts +37 -0
  633. package/workflow/useWorkflowExecution.d.ts.map +1 -0
  634. package/workflow/useWorkflowExecution.js +43 -0
  635. package/workflow/useWorkflowExecution.js.map +1 -0
  636. package/workflow/useWorkflowExecutionActions.d.ts +41 -0
  637. package/workflow/useWorkflowExecutionActions.d.ts.map +1 -0
  638. package/workflow/useWorkflowExecutionActions.js +86 -0
  639. package/workflow/useWorkflowExecutionActions.js.map +1 -0
  640. package/workflow/useWorkflowExecutionArtifacts.d.ts +26 -0
  641. package/workflow/useWorkflowExecutionArtifacts.d.ts.map +1 -0
  642. package/workflow/useWorkflowExecutionArtifacts.js +29 -0
  643. package/workflow/useWorkflowExecutionArtifacts.js.map +1 -0
  644. package/workflow/useWorkflowExecutionEventLog.d.ts +47 -0
  645. package/workflow/useWorkflowExecutionEventLog.d.ts.map +1 -0
  646. package/workflow/useWorkflowExecutionEventLog.js +59 -0
  647. package/workflow/useWorkflowExecutionEventLog.js.map +1 -0
  648. package/workflow/useWorkflowExecutionEventStream.d.ts +61 -0
  649. package/workflow/useWorkflowExecutionEventStream.d.ts.map +1 -0
  650. package/workflow/useWorkflowExecutionEventStream.js +161 -0
  651. package/workflow/useWorkflowExecutionEventStream.js.map +1 -0
  652. package/workflow/useWorkflowExecutionList.d.ts +49 -0
  653. package/workflow/useWorkflowExecutionList.d.ts.map +1 -0
  654. package/workflow/useWorkflowExecutionList.js +65 -0
  655. package/workflow/useWorkflowExecutionList.js.map +1 -0
  656. package/workflow/useWorkflowInstances.d.ts +30 -0
  657. package/workflow/useWorkflowInstances.d.ts.map +1 -0
  658. package/workflow/useWorkflowInstances.js +33 -0
  659. package/workflow/useWorkflowInstances.js.map +1 -0
  660. package/workflow/useWorkflowList.d.ts +57 -0
  661. package/workflow/useWorkflowList.d.ts.map +1 -0
  662. package/workflow/useWorkflowList.js +29 -0
  663. package/workflow/useWorkflowList.js.map +1 -0
  664. package/workflow/useWorkflowSave.d.ts +25 -0
  665. package/workflow/useWorkflowSave.d.ts.map +1 -0
  666. package/workflow/useWorkflowSave.js +61 -0
  667. package/workflow/useWorkflowSave.js.map +1 -0
  668. package/workflow/useWorkflowTopology.d.ts +40 -0
  669. package/workflow/useWorkflowTopology.d.ts.map +1 -0
  670. package/workflow/useWorkflowTopology.js +163 -0
  671. package/workflow/useWorkflowTopology.js.map +1 -0
  672. package/workflow/useWorkflowValidation.d.ts +27 -0
  673. package/workflow/useWorkflowValidation.d.ts.map +1 -0
  674. package/workflow/useWorkflowValidation.js +253 -0
  675. package/workflow/useWorkflowValidation.js.map +1 -0
  676. package/workflow/useWorkflowYaml.d.ts +26 -0
  677. package/workflow/useWorkflowYaml.d.ts.map +1 -0
  678. package/workflow/useWorkflowYaml.js +26 -0
  679. package/workflow/useWorkflowYaml.js.map +1 -0
  680. package/workflow/workflow-graph-conversions.d.ts +70 -0
  681. package/workflow/workflow-graph-conversions.d.ts.map +1 -0
  682. package/workflow/workflow-graph-conversions.js +634 -0
  683. package/workflow/workflow-graph-conversions.js.map +1 -0
  684. package/workflow/workflow-graph-model.d.ts +83 -0
  685. package/workflow/workflow-graph-model.d.ts.map +1 -0
  686. package/workflow/workflow-graph-model.js +5 -0
  687. package/workflow/workflow-graph-model.js.map +1 -0
  688. package/workflow/workflow-yaml-diff.d.ts +24 -0
  689. package/workflow/workflow-yaml-diff.d.ts.map +1 -0
  690. package/workflow/workflow-yaml-diff.js +96 -0
  691. package/workflow/workflow-yaml-diff.js.map +1 -0
@@ -0,0 +1,796 @@
1
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
2
+ import { WorkflowTaskKind, BudgetExceededPolicy } from "@stigmer/protos/ai/stigmer/agentic/workflow/v1/enum_pb";
3
+ import type { JsonObject } from "@bufbuild/protobuf";
4
+ import type { Node, Edge } from "@xyflow/react";
5
+ import type {
6
+ WorkflowInput,
7
+ WorkflowTaskInput,
8
+ WorkflowDocumentInput,
9
+ ExportInput,
10
+ FlowControlInput,
11
+ } from "@stigmer/sdk";
12
+ import type { TopologyNodeCategory } from "./useWorkflowTopology";
13
+ import type {
14
+ WorkflowGraphModel,
15
+ WorkflowGraphNode,
16
+ WorkflowGraphEdge,
17
+ WorkflowGraphDocument,
18
+ WorkflowGraphBudget,
19
+ WorkflowGraphEnvVar,
20
+ } from "./workflow-graph-model";
21
+ import { START_NODE_ID, END_NODE_ID } from "./workflow-graph-model";
22
+ import { CANVAS_NODE_WIDTH, CANVAS_NODE_HEIGHT, SENTINEL_NODE_WIDTH, SENTINEL_NODE_HEIGHT } from "./canvas-constants";
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // React Flow node/edge type identifiers
26
+ // ---------------------------------------------------------------------------
27
+
28
+ export const CANVAS_TASK_NODE_TYPE = "canvasTask" as const;
29
+ export const CANVAS_TRANSITION_EDGE_TYPE = "canvasTransition" as const;
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // Category classification (mirrors useWorkflowTopology)
33
+ // ---------------------------------------------------------------------------
34
+
35
+ const AI_KINDS = new Set(["agent_call", "llm_call", "eval"]);
36
+ const CONTROL_FLOW_KINDS = new Set(["switch_case", "for_each", "fork", "try_catch"]);
37
+ const INVOCATION_KINDS = new Set(["http_call", "grpc_call", "activity_call", "run_workflow"]);
38
+ const DATA_KINDS = new Set(["set_vars", "transform"]);
39
+ const GOVERNANCE_KINDS = new Set(["human_input", "validate"]);
40
+ const EVENT_KINDS = new Set(["listen", "wait", "emit_event", "notification", "raise_error"]);
41
+
42
+ export function categorizeKind(kind: string): TopologyNodeCategory {
43
+ if (AI_KINDS.has(kind)) return "ai";
44
+ if (CONTROL_FLOW_KINDS.has(kind)) return "control_flow";
45
+ if (INVOCATION_KINDS.has(kind)) return "invocation";
46
+ if (DATA_KINDS.has(kind)) return "data";
47
+ if (GOVERNANCE_KINDS.has(kind)) return "governance";
48
+ if (EVENT_KINDS.has(kind)) return "event";
49
+ return "unspecified";
50
+ }
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Enum maps (reuse the same logic as serialize-workflow-yaml.ts)
54
+ // ---------------------------------------------------------------------------
55
+
56
+ const TASK_KIND_STRINGS: ReadonlyMap<WorkflowTaskKind, string> = new Map(
57
+ Object.entries(WorkflowTaskKind)
58
+ .filter(
59
+ (entry): entry is [string, WorkflowTaskKind] =>
60
+ typeof entry[1] === "number" &&
61
+ entry[1] !== WorkflowTaskKind.workflow_task_kind_unspecified,
62
+ )
63
+ .map(([name, value]) => [value, name]),
64
+ );
65
+
66
+ const STRING_TO_TASK_KIND: ReadonlyMap<string, WorkflowTaskKind> = new Map(
67
+ Array.from(TASK_KIND_STRINGS.entries()).map(([value, name]) => [name, value]),
68
+ );
69
+
70
+ export function taskKindToString(kind: WorkflowTaskKind): string {
71
+ return TASK_KIND_STRINGS.get(kind) ?? `unknown_${kind}`;
72
+ }
73
+
74
+ export function stringToTaskKind(str: string): WorkflowTaskKind {
75
+ return STRING_TO_TASK_KIND.get(str) ?? WorkflowTaskKind.workflow_task_kind_unspecified;
76
+ }
77
+
78
+ const BUDGET_POLICY_STRINGS: ReadonlyMap<BudgetExceededPolicy, string> = new Map([
79
+ [BudgetExceededPolicy.budget_exceeded_terminate, "budget_exceeded_terminate"],
80
+ [BudgetExceededPolicy.budget_exceeded_human_review, "budget_exceeded_human_review"],
81
+ [BudgetExceededPolicy.budget_exceeded_warn, "budget_exceeded_warn"],
82
+ ]);
83
+
84
+ const STRING_TO_BUDGET_POLICY: ReadonlyMap<string, BudgetExceededPolicy> = new Map(
85
+ Array.from(BUDGET_POLICY_STRINGS.entries()).map(([v, n]) => [n, v]),
86
+ );
87
+
88
+ // ---------------------------------------------------------------------------
89
+ // yamlToGraph
90
+ // ---------------------------------------------------------------------------
91
+
92
+ interface RawTask {
93
+ name: string;
94
+ kind: string;
95
+ task_config?: Record<string, unknown>;
96
+ taskConfig?: Record<string, unknown>;
97
+ flow?: { then?: string };
98
+ export?: { as?: string };
99
+ }
100
+
101
+ /**
102
+ * Parses a Stigmer Workflow YAML string into an editable graph model.
103
+ *
104
+ * Builds nodes from `spec.tasks` with full configuration data, and infers
105
+ * edges from sequential ordering, explicit `flow.then`, `switch_case`
106
+ * branches, `human_input` outcomes, and fallback task references.
107
+ *
108
+ * @throws {Error} When the YAML is fundamentally unparseable or lacks required structure.
109
+ *
110
+ * @since T15 (Visual Canvas Editor)
111
+ */
112
+ export function yamlToGraph(yaml: string): WorkflowGraphModel {
113
+ const parsed = parseYamlSafe(yaml);
114
+ const spec = requireObj(parsed.spec, "spec");
115
+ const rawDocument = requireObj(spec.document, "spec.document");
116
+
117
+ const document: WorkflowGraphDocument = {
118
+ dsl: typeof rawDocument.dsl === "string" ? rawDocument.dsl : "1.0.0",
119
+ namespace: requireString(rawDocument, "namespace"),
120
+ name: requireString(rawDocument, "name"),
121
+ version: requireString(rawDocument, "version"),
122
+ ...(typeof rawDocument.description === "string" && { description: rawDocument.description }),
123
+ };
124
+
125
+ const description = typeof spec.description === "string" ? spec.description : undefined;
126
+ const env = extractEnv(spec);
127
+ const budget = extractBudget(spec);
128
+
129
+ const rawTasks = spec.tasks;
130
+ if (!Array.isArray(rawTasks) || rawTasks.length === 0) {
131
+ throw new Error("Workflow YAML is missing required field: spec.tasks.");
132
+ }
133
+
134
+ const tasks = rawTasks.filter(
135
+ (t): t is RawTask =>
136
+ t != null && typeof t === "object" && typeof (t as RawTask).name === "string",
137
+ );
138
+
139
+ if (tasks.length === 0) {
140
+ throw new Error("Workflow YAML: spec.tasks contains no valid task entries.");
141
+ }
142
+
143
+ const taskNameSet = new Set(tasks.map((t) => t.name));
144
+ const nodes: WorkflowGraphNode[] = [];
145
+ const edges: WorkflowGraphEdge[] = [];
146
+ let edgeCounter = 0;
147
+
148
+ const makeEdgeId = () => `e_${edgeCounter++}`;
149
+
150
+ // Sentinel: Start node
151
+ nodes.push({
152
+ id: START_NODE_ID,
153
+ taskName: "Start",
154
+ kind: WorkflowTaskKind.workflow_task_kind_unspecified,
155
+ category: "start",
156
+ config: {} as JsonObject,
157
+ position: { x: 0, y: 0 },
158
+ });
159
+
160
+ // Task nodes
161
+ for (const task of tasks) {
162
+ const config = (task.task_config ?? task.taskConfig ?? {}) as JsonObject;
163
+ const kindEnum = stringToTaskKind(task.kind);
164
+ const kindStr = kindEnum !== WorkflowTaskKind.workflow_task_kind_unspecified ? task.kind : task.kind;
165
+
166
+ nodes.push({
167
+ id: task.name,
168
+ taskName: task.name,
169
+ kind: kindEnum,
170
+ category: categorizeKind(task.kind),
171
+ config,
172
+ ...(task.export?.as && { export: { as: task.export.as } }),
173
+ ...(task.flow?.then && { flow: { then: task.flow.then } }),
174
+ position: { x: 0, y: 0 },
175
+ });
176
+ }
177
+
178
+ // Edge: start → first task
179
+ edges.push({ id: makeEdgeId(), source: START_NODE_ID, target: tasks[0].name });
180
+
181
+ const tasksWithEndFlow = new Set<string>();
182
+
183
+ for (let i = 0; i < tasks.length; i++) {
184
+ const task = tasks[i];
185
+ const thenTarget = task.flow?.then;
186
+
187
+ if (thenTarget === "end") {
188
+ tasksWithEndFlow.add(task.name);
189
+ continue;
190
+ }
191
+
192
+ if (thenTarget && taskNameSet.has(thenTarget)) {
193
+ edges.push({ id: makeEdgeId(), source: task.name, target: thenTarget });
194
+ continue;
195
+ }
196
+
197
+ // switch_case: edges per case branch
198
+ const config = task.task_config ?? task.taskConfig;
199
+ if (task.kind === "switch_case" && config) {
200
+ const cases = (config as Record<string, unknown>).cases;
201
+ if (Array.isArray(cases)) {
202
+ let hasDefault = false;
203
+ for (const c of cases) {
204
+ if (c && typeof c === "object") {
205
+ const caseObj = c as Record<string, unknown>;
206
+ const caseName = caseObj.name as string | undefined;
207
+ const caseThen = caseObj.then as string | undefined;
208
+ if (caseName && caseThen && taskNameSet.has(caseThen)) {
209
+ edges.push({
210
+ id: makeEdgeId(),
211
+ source: task.name,
212
+ target: caseThen,
213
+ label: caseName,
214
+ sourceHandle: `case_${caseName}`,
215
+ });
216
+ if (!(caseObj.when as string)) hasDefault = true;
217
+ }
218
+ }
219
+ }
220
+ if (!hasDefault && i < tasks.length - 1) {
221
+ edges.push({ id: makeEdgeId(), source: task.name, target: tasks[i + 1].name });
222
+ }
223
+ continue;
224
+ }
225
+ }
226
+
227
+ // human_input: edges per outcome
228
+ if (task.kind === "human_input" && config) {
229
+ const outcomes = (config as Record<string, unknown>).outcomes;
230
+ if (Array.isArray(outcomes)) {
231
+ let hasOutcomeEdges = false;
232
+ for (const outcome of outcomes) {
233
+ if (outcome && typeof outcome === "object") {
234
+ const outObj = outcome as Record<string, unknown>;
235
+ const outName = outObj.name as string | undefined;
236
+ const outThen = outObj.then as string | undefined;
237
+ if (outName && outThen && taskNameSet.has(outThen)) {
238
+ edges.push({
239
+ id: makeEdgeId(),
240
+ source: task.name,
241
+ target: outThen,
242
+ label: outName,
243
+ sourceHandle: `outcome_${outName}`,
244
+ });
245
+ hasOutcomeEdges = true;
246
+ }
247
+ }
248
+ }
249
+ if (hasOutcomeEdges) continue;
250
+ }
251
+ }
252
+
253
+ // Default: sequential to next task
254
+ if (i < tasks.length - 1) {
255
+ edges.push({ id: makeEdgeId(), source: task.name, target: tasks[i + 1].name });
256
+ } else {
257
+ tasksWithEndFlow.add(task.name);
258
+ }
259
+ }
260
+
261
+ // Sentinel: End node
262
+ if (tasksWithEndFlow.size > 0) {
263
+ nodes.push({
264
+ id: END_NODE_ID,
265
+ taskName: "End",
266
+ kind: WorkflowTaskKind.workflow_task_kind_unspecified,
267
+ category: "end",
268
+ config: {} as JsonObject,
269
+ position: { x: 0, y: 0 },
270
+ });
271
+
272
+ for (const name of tasksWithEndFlow) {
273
+ edges.push({ id: makeEdgeId(), source: name, target: END_NODE_ID });
274
+ }
275
+ }
276
+
277
+ return { document, description, env, budget, nodes, edges };
278
+ }
279
+
280
+ // ---------------------------------------------------------------------------
281
+ // graphToYaml
282
+ // ---------------------------------------------------------------------------
283
+
284
+ /**
285
+ * Serializes a graph model back to canonical Stigmer Workflow YAML.
286
+ *
287
+ * Uses topological sort to determine task ordering. Sequential transitions
288
+ * (task N → task N+1 in sorted order) are implicit and omitted from YAML.
289
+ * Non-sequential transitions emit explicit `flow.then` directives.
290
+ *
291
+ * @since T15 (Visual Canvas Editor)
292
+ */
293
+ export function graphToYaml(graph: WorkflowGraphModel): string {
294
+ const taskNodes = graph.nodes.filter(
295
+ (n) => n.id !== START_NODE_ID && n.id !== END_NODE_ID,
296
+ );
297
+
298
+ const sortedTasks = topologicalSort(taskNodes, graph.edges);
299
+
300
+ const tasks: Record<string, unknown>[] = sortedTasks.map((node, idx) => {
301
+ const kindStr = taskKindToString(node.kind);
302
+ const result: Record<string, unknown> = {
303
+ name: node.taskName,
304
+ kind: kindStr,
305
+ };
306
+
307
+ if (Object.keys(node.config).length > 0) {
308
+ result.task_config = structToPlain(node.config);
309
+
310
+ if (kindStr === "switch_case") {
311
+ reconstructSwitchCaseThen(node, graph.edges, result);
312
+ }
313
+ if (kindStr === "human_input") {
314
+ reconstructHumanInputOutcomeThen(node, graph.edges, result);
315
+ }
316
+ }
317
+
318
+ if (node.export?.as) {
319
+ result.export = { as: node.export.as };
320
+ }
321
+
322
+ // Determine flow.then
323
+ const outgoingEdges = graph.edges.filter(
324
+ (e) => e.source === node.id && !e.sourceHandle,
325
+ );
326
+
327
+ if (outgoingEdges.length === 1) {
328
+ const target = outgoingEdges[0].target;
329
+ if (target === END_NODE_ID) {
330
+ result.flow = { then: "end" };
331
+ } else {
332
+ const nextInOrder = sortedTasks[idx + 1];
333
+ if (!nextInOrder || target !== nextInOrder.id) {
334
+ result.flow = { then: target };
335
+ }
336
+ }
337
+ } else if (outgoingEdges.length === 0 && idx < sortedTasks.length - 1) {
338
+ // Terminal task that isn't last in sort order — explicit end
339
+ const hasHandledEdges = graph.edges.some(
340
+ (e) => e.source === node.id && e.sourceHandle,
341
+ );
342
+ if (!hasHandledEdges) {
343
+ result.flow = { then: "end" };
344
+ }
345
+ }
346
+
347
+ return result;
348
+ });
349
+
350
+ const doc: Record<string, unknown> = {
351
+ apiVersion: "agentic.stigmer.ai/v1",
352
+ kind: "Workflow",
353
+ metadata: { name: graph.document.name },
354
+ spec: {
355
+ document: {
356
+ dsl: graph.document.dsl,
357
+ namespace: graph.document.namespace,
358
+ name: graph.document.name,
359
+ version: graph.document.version,
360
+ ...(graph.document.description && { description: graph.document.description }),
361
+ },
362
+ ...(graph.description && { description: graph.description }),
363
+ tasks,
364
+ ...(graph.env && Object.keys(graph.env).length > 0 && { env: serializeEnv(graph.env) }),
365
+ ...(graph.budget && hasBudgetValues(graph.budget) && { budget: serializeBudget(graph.budget) }),
366
+ },
367
+ };
368
+
369
+ return stringifyYaml(doc, { lineWidth: 0, blockQuote: "literal" });
370
+ }
371
+
372
+ // ---------------------------------------------------------------------------
373
+ // graphToWorkflowInput
374
+ // ---------------------------------------------------------------------------
375
+
376
+ /**
377
+ * Converts a graph model into a `WorkflowInput` suitable for
378
+ * `stigmer.workflow.apply()`.
379
+ *
380
+ * This will be the primary save path in Batch 3 when `useWorkflowSave`
381
+ * is extended to accept `WorkflowInput` directly.
382
+ *
383
+ * @since T15 (Visual Canvas Editor)
384
+ */
385
+ export function graphToWorkflowInput(
386
+ graph: WorkflowGraphModel,
387
+ org: string,
388
+ ): WorkflowInput {
389
+ const taskNodes = graph.nodes.filter(
390
+ (n) => n.id !== START_NODE_ID && n.id !== END_NODE_ID,
391
+ );
392
+
393
+ const sortedTasks = topologicalSort(taskNodes, graph.edges);
394
+
395
+ const tasks: WorkflowTaskInput[] = sortedTasks.map((node, idx) => {
396
+ const result: WorkflowTaskInput = {
397
+ name: node.taskName,
398
+ kind: node.kind,
399
+ taskConfig: node.config,
400
+ };
401
+
402
+ if (node.export?.as) {
403
+ (result as { export?: ExportInput }).export = { as: node.export.as };
404
+ }
405
+
406
+ // Determine flow.then
407
+ const outgoingEdges = graph.edges.filter(
408
+ (e) => e.source === node.id && !e.sourceHandle,
409
+ );
410
+
411
+ if (outgoingEdges.length === 1) {
412
+ const target = outgoingEdges[0].target;
413
+ if (target === END_NODE_ID) {
414
+ (result as { flow?: FlowControlInput }).flow = { then: "end" };
415
+ } else {
416
+ const nextInOrder = sortedTasks[idx + 1];
417
+ if (!nextInOrder || target !== nextInOrder.id) {
418
+ (result as { flow?: FlowControlInput }).flow = { then: target };
419
+ }
420
+ }
421
+ }
422
+
423
+ return result;
424
+ });
425
+
426
+ const document: WorkflowDocumentInput = {
427
+ dsl: graph.document.dsl,
428
+ namespace: graph.document.namespace,
429
+ name: graph.document.name,
430
+ version: graph.document.version,
431
+ ...(graph.document.description && { description: graph.document.description }),
432
+ };
433
+
434
+ const budget = graph.budget && hasBudgetValues(graph.budget)
435
+ ? buildBudgetInput(graph.budget)
436
+ : undefined;
437
+
438
+ const env = graph.env && Object.keys(graph.env).length > 0
439
+ ? buildEnvInput(graph.env)
440
+ : undefined;
441
+
442
+ return {
443
+ name: graph.document.name,
444
+ org,
445
+ ...(graph.description && { description: graph.description }),
446
+ document,
447
+ tasks,
448
+ ...(env && { env }),
449
+ ...(budget && { budget }),
450
+ };
451
+ }
452
+
453
+ // ---------------------------------------------------------------------------
454
+ // toReactFlowElements
455
+ // ---------------------------------------------------------------------------
456
+
457
+ /** Data payload attached to canvas task nodes. */
458
+ export interface CanvasTaskNodeData extends Record<string, unknown> {
459
+ taskName: string;
460
+ kind: WorkflowTaskKind;
461
+ kindString: string;
462
+ category: TopologyNodeCategory;
463
+ config: JsonObject;
464
+ exportAs?: string;
465
+ isSentinel: boolean;
466
+ errorCount?: number;
467
+ }
468
+
469
+ /** Data payload attached to canvas transition edges. */
470
+ export interface CanvasTransitionEdgeData extends Record<string, unknown> {
471
+ label?: string;
472
+ }
473
+
474
+ /**
475
+ * Converts a `WorkflowGraphModel` into React Flow node and edge arrays
476
+ * with the custom type identifiers used by `CanvasTaskNode` and
477
+ * `CanvasTransitionEdge`.
478
+ *
479
+ * @since T15 (Visual Canvas Editor)
480
+ */
481
+ export function toReactFlowElements(graph: WorkflowGraphModel): {
482
+ nodes: Node[];
483
+ edges: Edge[];
484
+ } {
485
+ const nodes: Node[] = graph.nodes.map((node) => {
486
+ const isSentinel = node.id === START_NODE_ID || node.id === END_NODE_ID;
487
+ return {
488
+ id: node.id,
489
+ type: CANVAS_TASK_NODE_TYPE,
490
+ position: { x: node.position.x, y: node.position.y },
491
+ data: {
492
+ taskName: node.taskName,
493
+ kind: node.kind,
494
+ kindString: taskKindToString(node.kind),
495
+ category: node.category,
496
+ config: node.config,
497
+ exportAs: node.export?.as,
498
+ isSentinel,
499
+ },
500
+ width: isSentinel ? SENTINEL_NODE_WIDTH : CANVAS_NODE_WIDTH,
501
+ height: isSentinel ? SENTINEL_NODE_HEIGHT : CANVAS_NODE_HEIGHT,
502
+ draggable: !isSentinel,
503
+ selectable: !isSentinel,
504
+ deletable: !isSentinel,
505
+ };
506
+ });
507
+
508
+ const edges: Edge[] = graph.edges.map((edge) => ({
509
+ id: edge.id,
510
+ type: CANVAS_TRANSITION_EDGE_TYPE,
511
+ source: edge.source,
512
+ target: edge.target,
513
+ sourceHandle: edge.sourceHandle,
514
+ data: { label: edge.label },
515
+ animated: false,
516
+ }));
517
+
518
+ return { nodes, edges };
519
+ }
520
+
521
+ // ---------------------------------------------------------------------------
522
+ // Topological sort
523
+ // ---------------------------------------------------------------------------
524
+
525
+ function topologicalSort(
526
+ nodes: readonly WorkflowGraphNode[],
527
+ edges: readonly WorkflowGraphEdge[],
528
+ ): WorkflowGraphNode[] {
529
+ const nodeMap = new Map(nodes.map((n) => [n.id, n]));
530
+ const inDegree = new Map<string, number>();
531
+ const adjacency = new Map<string, string[]>();
532
+
533
+ for (const node of nodes) {
534
+ inDegree.set(node.id, 0);
535
+ adjacency.set(node.id, []);
536
+ }
537
+
538
+ for (const edge of edges) {
539
+ if (!nodeMap.has(edge.source) || !nodeMap.has(edge.target)) continue;
540
+ adjacency.get(edge.source)!.push(edge.target);
541
+ inDegree.set(edge.target, (inDegree.get(edge.target) ?? 0) + 1);
542
+ }
543
+
544
+ // Also consider edges from __start__ to find the first task
545
+ const startEdges = edges.filter((e) => e.source === START_NODE_ID);
546
+ for (const se of startEdges) {
547
+ if (inDegree.has(se.target)) {
548
+ inDegree.set(se.target, Math.max(0, (inDegree.get(se.target) ?? 1) - 1));
549
+ }
550
+ }
551
+
552
+ const queue: string[] = [];
553
+ for (const [id, degree] of inDegree.entries()) {
554
+ if (degree === 0) queue.push(id);
555
+ }
556
+
557
+ const sorted: WorkflowGraphNode[] = [];
558
+ const visited = new Set<string>();
559
+
560
+ while (queue.length > 0) {
561
+ const id = queue.shift()!;
562
+ if (visited.has(id)) continue;
563
+ visited.add(id);
564
+
565
+ const node = nodeMap.get(id);
566
+ if (node) sorted.push(node);
567
+
568
+ for (const neighbor of adjacency.get(id) ?? []) {
569
+ if (visited.has(neighbor)) continue;
570
+ const newDegree = (inDegree.get(neighbor) ?? 1) - 1;
571
+ inDegree.set(neighbor, newDegree);
572
+ if (newDegree <= 0) queue.push(neighbor);
573
+ }
574
+ }
575
+
576
+ // Append any nodes not reached (cycle protection — preserves original order)
577
+ for (const node of nodes) {
578
+ if (!visited.has(node.id)) {
579
+ sorted.push(node);
580
+ }
581
+ }
582
+
583
+ return sorted;
584
+ }
585
+
586
+ // ---------------------------------------------------------------------------
587
+ // Serialization helpers
588
+ // ---------------------------------------------------------------------------
589
+
590
+ function reconstructSwitchCaseThen(
591
+ node: WorkflowGraphNode,
592
+ edges: readonly WorkflowGraphEdge[],
593
+ result: Record<string, unknown>,
594
+ ): void {
595
+ const taskConfig = result.task_config as Record<string, unknown> | undefined;
596
+ if (!taskConfig) return;
597
+
598
+ const cases = taskConfig.cases;
599
+ if (!Array.isArray(cases)) return;
600
+
601
+ const caseEdges = edges.filter(
602
+ (e) => e.source === node.id && e.sourceHandle?.startsWith("case_"),
603
+ );
604
+
605
+ for (const edge of caseEdges) {
606
+ const caseName = edge.sourceHandle!.slice(5); // "case_".length
607
+ const caseEntry = cases.find(
608
+ (c) => c && typeof c === "object" && (c as Record<string, unknown>).name === caseName,
609
+ );
610
+ if (caseEntry) {
611
+ (caseEntry as Record<string, unknown>).then = edge.target;
612
+ }
613
+ }
614
+ }
615
+
616
+ function reconstructHumanInputOutcomeThen(
617
+ node: WorkflowGraphNode,
618
+ edges: readonly WorkflowGraphEdge[],
619
+ result: Record<string, unknown>,
620
+ ): void {
621
+ const taskConfig = result.task_config as Record<string, unknown> | undefined;
622
+ if (!taskConfig) return;
623
+
624
+ const outcomes = taskConfig.outcomes;
625
+ if (!Array.isArray(outcomes)) return;
626
+
627
+ const outcomeEdges = edges.filter(
628
+ (e) => e.source === node.id && e.sourceHandle?.startsWith("outcome_"),
629
+ );
630
+
631
+ for (const edge of outcomeEdges) {
632
+ const outcomeName = edge.sourceHandle!.slice(8); // "outcome_".length
633
+ const outcomeEntry = outcomes.find(
634
+ (o) => o && typeof o === "object" && (o as Record<string, unknown>).name === outcomeName,
635
+ );
636
+ if (outcomeEntry) {
637
+ (outcomeEntry as Record<string, unknown>).then = edge.target;
638
+ }
639
+ }
640
+ }
641
+
642
+ function structToPlain(obj: unknown): unknown {
643
+ if (obj === null || obj === undefined) return obj;
644
+ if (typeof obj === "bigint") return Number(obj);
645
+ if (typeof obj !== "object") return obj;
646
+ if (Array.isArray(obj)) return obj.map(structToPlain);
647
+
648
+ const result: Record<string, unknown> = {};
649
+ for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {
650
+ result[k] = structToPlain(v);
651
+ }
652
+ return result;
653
+ }
654
+
655
+ function serializeEnv(env: Readonly<Record<string, WorkflowGraphEnvVar>>): Record<string, Record<string, unknown>> {
656
+ const result: Record<string, Record<string, unknown>> = {};
657
+ for (const [key, decl] of Object.entries(env)) {
658
+ const entry: Record<string, unknown> = {};
659
+ if (decl.isSecret) entry.is_secret = true;
660
+ if (decl.description) entry.description = decl.description;
661
+ if (decl.optional) entry.optional = true;
662
+ result[key] = entry;
663
+ }
664
+ return result;
665
+ }
666
+
667
+ function serializeBudget(budget: WorkflowGraphBudget): Record<string, unknown> {
668
+ const result: Record<string, unknown> = {};
669
+ if (budget.maxCostMicros && budget.maxCostMicros > 0) result.max_cost_micros = budget.maxCostMicros;
670
+ if (budget.maxTotalTokens && budget.maxTotalTokens > 0) result.max_total_tokens = budget.maxTotalTokens;
671
+ if (budget.maxDurationSeconds && budget.maxDurationSeconds > 0) result.max_duration_seconds = budget.maxDurationSeconds;
672
+ if (budget.onExceeded) result.on_exceeded = budget.onExceeded;
673
+ return result;
674
+ }
675
+
676
+ function hasBudgetValues(budget: WorkflowGraphBudget): boolean {
677
+ return (
678
+ (budget.maxCostMicros != null && budget.maxCostMicros > 0) ||
679
+ (budget.maxTotalTokens != null && budget.maxTotalTokens > 0) ||
680
+ (budget.maxDurationSeconds != null && budget.maxDurationSeconds > 0)
681
+ );
682
+ }
683
+
684
+ function buildBudgetInput(budget: WorkflowGraphBudget): NonNullable<WorkflowInput["budget"]> {
685
+ const result: NonNullable<WorkflowInput["budget"]> = {};
686
+ if (budget.maxCostMicros && budget.maxCostMicros > 0) {
687
+ result.maxCostMicros = BigInt(budget.maxCostMicros);
688
+ }
689
+ if (budget.maxTotalTokens && budget.maxTotalTokens > 0) {
690
+ result.maxTotalTokens = BigInt(budget.maxTotalTokens);
691
+ }
692
+ if (budget.maxDurationSeconds && budget.maxDurationSeconds > 0) {
693
+ result.maxDurationSeconds = budget.maxDurationSeconds;
694
+ }
695
+ if (budget.onExceeded) {
696
+ const policy = STRING_TO_BUDGET_POLICY.get(budget.onExceeded);
697
+ if (policy !== undefined) result.onExceeded = policy;
698
+ }
699
+ return result;
700
+ }
701
+
702
+ function buildEnvInput(env: Readonly<Record<string, WorkflowGraphEnvVar>>): WorkflowInput["env"] {
703
+ const result: NonNullable<WorkflowInput["env"]> = {};
704
+ for (const [key, decl] of Object.entries(env)) {
705
+ result[key] = {
706
+ ...(decl.isSecret && { isSecret: true }),
707
+ ...(decl.description && { description: decl.description }),
708
+ ...(decl.optional && { optional: true }),
709
+ };
710
+ }
711
+ return result;
712
+ }
713
+
714
+ // ---------------------------------------------------------------------------
715
+ // Parse helpers
716
+ // ---------------------------------------------------------------------------
717
+
718
+ function extractEnv(spec: Record<string, unknown>): Record<string, WorkflowGraphEnvVar> | undefined {
719
+ const raw = spec.env;
720
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return undefined;
721
+
722
+ const result: Record<string, WorkflowGraphEnvVar> = {};
723
+ let hasEntries = false;
724
+
725
+ for (const [key, val] of Object.entries(raw as Record<string, unknown>)) {
726
+ if (!val || typeof val !== "object" || Array.isArray(val)) continue;
727
+ const v = val as Record<string, unknown>;
728
+ result[key] = {
729
+ ...(typeof (v.is_secret ?? v.isSecret) === "boolean" && { isSecret: (v.is_secret ?? v.isSecret) as boolean }),
730
+ ...(typeof v.description === "string" && { description: v.description }),
731
+ ...(typeof v.optional === "boolean" && { optional: v.optional }),
732
+ };
733
+ hasEntries = true;
734
+ }
735
+
736
+ return hasEntries ? result : undefined;
737
+ }
738
+
739
+ function extractBudget(spec: Record<string, unknown>): WorkflowGraphBudget | undefined {
740
+ const raw = spec.budget;
741
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return undefined;
742
+
743
+ const b = raw as Record<string, unknown>;
744
+ const maxCostMicros = toNumber(b.max_cost_micros ?? b.maxCostMicros);
745
+ const maxTotalTokens = toNumber(b.max_total_tokens ?? b.maxTotalTokens);
746
+ const maxDurationSeconds = toNumber(b.max_duration_seconds ?? b.maxDurationSeconds);
747
+ const onExceeded = typeof (b.on_exceeded ?? b.onExceeded) === "string"
748
+ ? (b.on_exceeded ?? b.onExceeded) as string
749
+ : undefined;
750
+
751
+ if (!maxCostMicros && !maxTotalTokens && !maxDurationSeconds) return undefined;
752
+
753
+ return {
754
+ ...(maxCostMicros && { maxCostMicros }),
755
+ ...(maxTotalTokens && { maxTotalTokens }),
756
+ ...(maxDurationSeconds && { maxDurationSeconds }),
757
+ ...(onExceeded && { onExceeded }),
758
+ };
759
+ }
760
+
761
+ function parseYamlSafe(content: string): Record<string, unknown> {
762
+ let parsed: unknown;
763
+ try {
764
+ parsed = parseYaml(content);
765
+ } catch {
766
+ throw new Error("Failed to parse content as YAML.");
767
+ }
768
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
769
+ throw new Error("YAML must be a mapping document.");
770
+ }
771
+ return parsed as Record<string, unknown>;
772
+ }
773
+
774
+ function requireObj(value: unknown, path: string): Record<string, unknown> {
775
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
776
+ throw new Error(`Workflow YAML is missing required field: ${path}.`);
777
+ }
778
+ return value as Record<string, unknown>;
779
+ }
780
+
781
+ function requireString(obj: Record<string, unknown>, key: string): string {
782
+ const val = obj[key];
783
+ if (typeof val !== "string" || val.length === 0) {
784
+ throw new Error(`Workflow YAML is missing required string field: ${key}.`);
785
+ }
786
+ return val;
787
+ }
788
+
789
+ function toNumber(val: unknown): number | undefined {
790
+ if (typeof val === "number" && Number.isFinite(val) && val > 0) return val;
791
+ if (typeof val === "string") {
792
+ const n = Number(val);
793
+ return Number.isFinite(n) && n > 0 ? n : undefined;
794
+ }
795
+ return undefined;
796
+ }