@flowdrop/flowdrop 1.0.0 → 1.1.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 (388) hide show
  1. package/README.md +50 -50
  2. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  3. package/dist/adapters/WorkflowAdapter.js +25 -25
  4. package/dist/adapters/agentspec/AgentSpecAdapter.d.ts +2 -2
  5. package/dist/adapters/agentspec/AgentSpecAdapter.js +133 -122
  6. package/dist/adapters/agentspec/agentAdapter.d.ts +2 -2
  7. package/dist/adapters/agentspec/agentAdapter.js +10 -10
  8. package/dist/adapters/agentspec/autoLayout.d.ts +1 -1
  9. package/dist/adapters/agentspec/autoLayout.js +2 -2
  10. package/dist/adapters/agentspec/componentTypeDefaults.d.ts +1 -1
  11. package/dist/adapters/agentspec/componentTypeDefaults.js +120 -120
  12. package/dist/adapters/agentspec/defaultNodeTypes.d.ts +2 -2
  13. package/dist/adapters/agentspec/defaultNodeTypes.js +307 -307
  14. package/dist/adapters/agentspec/index.d.ts +10 -10
  15. package/dist/adapters/agentspec/index.js +6 -6
  16. package/dist/adapters/agentspec/validator.d.ts +2 -2
  17. package/dist/adapters/agentspec/validator.js +22 -20
  18. package/dist/api/enhanced-client.d.ts +3 -3
  19. package/dist/api/enhanced-client.js +73 -72
  20. package/dist/components/App.svelte +1081 -961
  21. package/dist/components/App.svelte.d.ts +9 -6
  22. package/dist/components/CanvasBanner.stories.svelte +23 -20
  23. package/dist/components/CanvasBanner.stories.svelte.d.ts +1 -1
  24. package/dist/components/CanvasBanner.svelte +46 -46
  25. package/dist/components/ConfigForm.svelte +1164 -1065
  26. package/dist/components/ConfigForm.svelte.d.ts +2 -2
  27. package/dist/components/ConfigModal.svelte +180 -180
  28. package/dist/components/ConfigModal.svelte.d.ts +1 -1
  29. package/dist/components/ConfigPanel.stories.svelte +35 -35
  30. package/dist/components/ConfigPanel.stories.svelte.d.ts +1 -1
  31. package/dist/components/ConfigPanel.svelte +178 -167
  32. package/dist/components/ConfigPanel.svelte.d.ts +1 -1
  33. package/dist/components/ConnectionLine.svelte +25 -25
  34. package/dist/components/EdgeRefresher.svelte +26 -26
  35. package/dist/components/FlowDropEdge.stories.svelte +197 -0
  36. package/dist/components/FlowDropEdge.stories.svelte.d.ts +26 -0
  37. package/dist/components/FlowDropEdge.svelte +168 -0
  38. package/dist/components/FlowDropEdge.svelte.d.ts +4 -0
  39. package/dist/components/FlowDropZone.svelte +63 -60
  40. package/dist/components/FlowDropZone.svelte.d.ts +1 -1
  41. package/dist/components/LoadingSpinner.stories.svelte +19 -19
  42. package/dist/components/LoadingSpinner.stories.svelte.d.ts +1 -1
  43. package/dist/components/LoadingSpinner.svelte +21 -21
  44. package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
  45. package/dist/components/Logo.stories.svelte +13 -13
  46. package/dist/components/Logo.stories.svelte.d.ts +1 -1
  47. package/dist/components/Logo.svelte +101 -95
  48. package/dist/components/LogsSidebar.svelte +553 -546
  49. package/dist/components/LogsSidebar.svelte.d.ts +1 -1
  50. package/dist/components/MarkdownDisplay.stories.svelte +29 -23
  51. package/dist/components/MarkdownDisplay.stories.svelte.d.ts +1 -1
  52. package/dist/components/MarkdownDisplay.svelte +16 -14
  53. package/dist/components/Navbar.stories.svelte +43 -38
  54. package/dist/components/Navbar.stories.svelte.d.ts +1 -1
  55. package/dist/components/Navbar.svelte +760 -706
  56. package/dist/components/Navbar.svelte.d.ts +1 -1
  57. package/dist/components/NodeSidebar.svelte +900 -746
  58. package/dist/components/NodeSidebar.svelte.d.ts +3 -1
  59. package/dist/components/NodeStatusOverlay.stories.svelte +82 -70
  60. package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +1 -1
  61. package/dist/components/NodeStatusOverlay.svelte +295 -280
  62. package/dist/components/NodeStatusOverlay.svelte.d.ts +3 -3
  63. package/dist/components/PipelineStatus.svelte +326 -300
  64. package/dist/components/PipelineStatus.svelte.d.ts +4 -4
  65. package/dist/components/PortCoordinateTracker.svelte +49 -47
  66. package/dist/components/PortCoordinateTracker.svelte.d.ts +1 -1
  67. package/dist/components/ReadOnlyDetails.svelte +156 -156
  68. package/dist/components/SchemaForm.stories.svelte +106 -98
  69. package/dist/components/SchemaForm.stories.svelte.d.ts +1 -1
  70. package/dist/components/SchemaForm.svelte +490 -463
  71. package/dist/components/SchemaForm.svelte.d.ts +2 -2
  72. package/dist/components/SettingsModal.svelte +226 -223
  73. package/dist/components/SettingsModal.svelte.d.ts +1 -1
  74. package/dist/components/SettingsPanel.svelte +637 -601
  75. package/dist/components/SettingsPanel.svelte.d.ts +1 -1
  76. package/dist/components/StatusIcon.stories.svelte +62 -49
  77. package/dist/components/StatusIcon.stories.svelte.d.ts +1 -1
  78. package/dist/components/StatusIcon.svelte +87 -87
  79. package/dist/components/StatusIcon.svelte.d.ts +2 -2
  80. package/dist/components/StatusLabel.stories.svelte +12 -12
  81. package/dist/components/StatusLabel.stories.svelte.d.ts +1 -1
  82. package/dist/components/StatusLabel.svelte +19 -19
  83. package/dist/components/ThemeToggle.stories.svelte +16 -16
  84. package/dist/components/ThemeToggle.stories.svelte.d.ts +1 -1
  85. package/dist/components/ThemeToggle.svelte +180 -169
  86. package/dist/components/ThemeToggle.svelte.d.ts +1 -1
  87. package/dist/components/UniversalNode.svelte +150 -138
  88. package/dist/components/UniversalNode.svelte.d.ts +3 -3
  89. package/dist/components/WorkflowEditor.svelte +1069 -1007
  90. package/dist/components/WorkflowEditor.svelte.d.ts +4 -4
  91. package/dist/components/form/FormArray.svelte +1034 -973
  92. package/dist/components/form/FormArray.svelte.d.ts +1 -1
  93. package/dist/components/form/FormAutocomplete.svelte +1021 -978
  94. package/dist/components/form/FormAutocomplete.svelte.d.ts +1 -1
  95. package/dist/components/form/FormCheckboxGroup.stories.svelte +23 -20
  96. package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +1 -1
  97. package/dist/components/form/FormCheckboxGroup.svelte +136 -136
  98. package/dist/components/form/FormCodeEditor.svelte +452 -434
  99. package/dist/components/form/FormField.svelte +366 -355
  100. package/dist/components/form/FormField.svelte.d.ts +2 -2
  101. package/dist/components/form/FormFieldLight.svelte +400 -384
  102. package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
  103. package/dist/components/form/FormFieldWrapper.stories.svelte +42 -42
  104. package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +1 -1
  105. package/dist/components/form/FormFieldWrapper.svelte +100 -93
  106. package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
  107. package/dist/components/form/FormFieldset.svelte +108 -108
  108. package/dist/components/form/FormFieldset.svelte.d.ts +2 -2
  109. package/dist/components/form/FormMarkdownEditor.svelte +758 -725
  110. package/dist/components/form/FormNumberField.stories.svelte +25 -25
  111. package/dist/components/form/FormNumberField.stories.svelte.d.ts +1 -1
  112. package/dist/components/form/FormNumberField.svelte +88 -88
  113. package/dist/components/form/FormRangeField.stories.svelte +20 -20
  114. package/dist/components/form/FormRangeField.stories.svelte.d.ts +1 -1
  115. package/dist/components/form/FormRangeField.svelte +234 -226
  116. package/dist/components/form/FormSelect.stories.svelte +38 -38
  117. package/dist/components/form/FormSelect.stories.svelte.d.ts +1 -1
  118. package/dist/components/form/FormSelect.svelte +101 -101
  119. package/dist/components/form/FormSelect.svelte.d.ts +1 -1
  120. package/dist/components/form/FormTemplateEditor.svelte +847 -798
  121. package/dist/components/form/FormTemplateEditor.svelte.d.ts +1 -1
  122. package/dist/components/form/FormTextField.stories.svelte +29 -23
  123. package/dist/components/form/FormTextField.stories.svelte.d.ts +1 -1
  124. package/dist/components/form/FormTextField.svelte +68 -68
  125. package/dist/components/form/FormTextarea.stories.svelte +28 -25
  126. package/dist/components/form/FormTextarea.stories.svelte.d.ts +1 -1
  127. package/dist/components/form/FormTextarea.svelte +74 -74
  128. package/dist/components/form/FormToggle.stories.svelte +23 -20
  129. package/dist/components/form/FormToggle.stories.svelte.d.ts +1 -1
  130. package/dist/components/form/FormToggle.svelte +98 -98
  131. package/dist/components/form/FormUISchemaRenderer.svelte +120 -113
  132. package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +3 -3
  133. package/dist/components/form/index.d.ts +19 -19
  134. package/dist/components/form/index.js +18 -18
  135. package/dist/components/form/templateAutocomplete.d.ts +2 -2
  136. package/dist/components/form/templateAutocomplete.js +64 -55
  137. package/dist/components/form/types.d.ts +6 -6
  138. package/dist/components/form/types.js +9 -4
  139. package/dist/components/icons/AlertCircleIcon.svelte +11 -0
  140. package/dist/components/icons/AlertCircleIcon.svelte.d.ts +26 -0
  141. package/dist/components/icons/CogIcon.svelte +11 -0
  142. package/dist/components/icons/CogIcon.svelte.d.ts +26 -0
  143. package/dist/components/interrupt/ChoicePrompt.stories.svelte +54 -38
  144. package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +1 -1
  145. package/dist/components/interrupt/ChoicePrompt.svelte +407 -383
  146. package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +1 -1
  147. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +48 -48
  148. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +1 -1
  149. package/dist/components/interrupt/ConfirmationPrompt.svelte +280 -274
  150. package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +1 -1
  151. package/dist/components/interrupt/FormPrompt.svelte +223 -218
  152. package/dist/components/interrupt/FormPrompt.svelte.d.ts +1 -1
  153. package/dist/components/interrupt/InterruptBubble.svelte +617 -583
  154. package/dist/components/interrupt/InterruptBubble.svelte.d.ts +2 -2
  155. package/dist/components/interrupt/ReviewPrompt.stories.svelte +66 -56
  156. package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +1 -1
  157. package/dist/components/interrupt/ReviewPrompt.svelte +861 -841
  158. package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +1 -1
  159. package/dist/components/interrupt/TextInputPrompt.stories.svelte +38 -33
  160. package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +1 -1
  161. package/dist/components/interrupt/TextInputPrompt.svelte +333 -328
  162. package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +1 -1
  163. package/dist/components/interrupt/index.d.ts +5 -5
  164. package/dist/components/interrupt/index.js +5 -5
  165. package/dist/components/layouts/MainLayout.svelte +724 -691
  166. package/dist/components/layouts/MainLayout.svelte.d.ts +6 -6
  167. package/dist/components/nodes/GatewayNode.stories.svelte +100 -99
  168. package/dist/components/nodes/GatewayNode.svelte +605 -571
  169. package/dist/components/nodes/GatewayNode.svelte.d.ts +3 -3
  170. package/dist/components/nodes/IdeaNode.stories.svelte +44 -43
  171. package/dist/components/nodes/IdeaNode.svelte +451 -437
  172. package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
  173. package/dist/components/nodes/NotesNode.stories.svelte +65 -64
  174. package/dist/components/nodes/NotesNode.svelte +380 -369
  175. package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
  176. package/dist/components/nodes/SimpleNode.stories.svelte +145 -144
  177. package/dist/components/nodes/SimpleNode.svelte +486 -424
  178. package/dist/components/nodes/SimpleNode.svelte.d.ts +1 -1
  179. package/dist/components/nodes/SquareNode.stories.svelte +73 -73
  180. package/dist/components/nodes/SquareNode.svelte +439 -380
  181. package/dist/components/nodes/SquareNode.svelte.d.ts +1 -1
  182. package/dist/components/nodes/TerminalNode.stories.svelte +13 -13
  183. package/dist/components/nodes/TerminalNode.svelte +709 -670
  184. package/dist/components/nodes/TerminalNode.svelte.d.ts +1 -1
  185. package/dist/components/nodes/ToolNode.stories.svelte +181 -180
  186. package/dist/components/nodes/ToolNode.svelte +505 -447
  187. package/dist/components/nodes/ToolNode.svelte.d.ts +1 -1
  188. package/dist/components/nodes/WorkflowNode.stories.svelte +70 -46
  189. package/dist/components/nodes/WorkflowNode.svelte +621 -551
  190. package/dist/components/nodes/WorkflowNode.svelte.d.ts +3 -3
  191. package/dist/components/playground/ChatPanel.svelte +945 -889
  192. package/dist/components/playground/ExecutionLogs.svelte +495 -472
  193. package/dist/components/playground/InputCollector.svelte +449 -428
  194. package/dist/components/playground/MessageBubble.stories.svelte +47 -47
  195. package/dist/components/playground/MessageBubble.stories.svelte.d.ts +1 -1
  196. package/dist/components/playground/MessageBubble.svelte +626 -610
  197. package/dist/components/playground/MessageBubble.svelte.d.ts +1 -1
  198. package/dist/components/playground/Playground.svelte +1088 -1057
  199. package/dist/components/playground/Playground.svelte.d.ts +3 -3
  200. package/dist/components/playground/PlaygroundModal.svelte +208 -204
  201. package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
  202. package/dist/components/playground/SessionManager.svelte +527 -521
  203. package/dist/components/playground/SessionManager.svelte.d.ts +1 -1
  204. package/dist/config/agentSpecEndpoints.d.ts +1 -1
  205. package/dist/config/agentSpecEndpoints.js +20 -20
  206. package/dist/config/constants.d.ts +8 -0
  207. package/dist/config/constants.js +10 -2
  208. package/dist/config/defaultCategories.d.ts +1 -1
  209. package/dist/config/defaultCategories.js +86 -86
  210. package/dist/config/defaultPortConfig.d.ts +1 -1
  211. package/dist/config/defaultPortConfig.js +144 -144
  212. package/dist/config/endpoints.d.ts +4 -4
  213. package/dist/config/endpoints.js +65 -65
  214. package/dist/config/runtimeConfig.d.ts +2 -2
  215. package/dist/config/runtimeConfig.js +8 -8
  216. package/dist/core/index.d.ts +63 -59
  217. package/dist/core/index.js +35 -33
  218. package/dist/display/index.d.ts +2 -2
  219. package/dist/display/index.js +2 -2
  220. package/dist/editor/index.d.ts +62 -62
  221. package/dist/editor/index.js +53 -53
  222. package/dist/form/code.d.ts +5 -5
  223. package/dist/form/code.js +14 -14
  224. package/dist/form/fieldRegistry.d.ts +3 -3
  225. package/dist/form/fieldRegistry.js +11 -9
  226. package/dist/form/full.d.ts +8 -8
  227. package/dist/form/full.js +9 -9
  228. package/dist/form/index.d.ts +18 -18
  229. package/dist/form/index.js +16 -16
  230. package/dist/form/markdown.d.ts +4 -4
  231. package/dist/form/markdown.js +8 -8
  232. package/dist/helpers/proximityConnect.d.ts +3 -3
  233. package/dist/helpers/proximityConnect.js +34 -32
  234. package/dist/helpers/workflowEditorHelper.d.ts +5 -5
  235. package/dist/helpers/workflowEditorHelper.js +108 -96
  236. package/dist/index.d.ts +6 -6
  237. package/dist/index.js +6 -6
  238. package/dist/mocks/app-environment.js +2 -2
  239. package/dist/mocks/app-forms.js +9 -9
  240. package/dist/mocks/app-navigation.js +11 -11
  241. package/dist/mocks/app-stores.js +8 -8
  242. package/dist/playground/index.d.ts +19 -19
  243. package/dist/playground/index.js +16 -16
  244. package/dist/playground/mount.d.ts +3 -3
  245. package/dist/playground/mount.js +24 -24
  246. package/dist/registry/builtinFormats.js +13 -13
  247. package/dist/registry/builtinNodes.d.ts +2 -2
  248. package/dist/registry/builtinNodes.js +77 -77
  249. package/dist/registry/index.d.ts +4 -4
  250. package/dist/registry/index.js +4 -4
  251. package/dist/registry/nodeComponentRegistry.d.ts +8 -8
  252. package/dist/registry/nodeComponentRegistry.js +11 -9
  253. package/dist/registry/plugin.d.ts +2 -2
  254. package/dist/registry/plugin.js +11 -11
  255. package/dist/registry/workflowFormatRegistry.d.ts +3 -3
  256. package/dist/registry/workflowFormatRegistry.js +2 -2
  257. package/dist/schema/index.d.ts +1 -1
  258. package/dist/schema/index.js +2 -2
  259. package/dist/schemas/v1/workflow.schema.json +22 -107
  260. package/dist/services/agentSpecExecutionService.d.ts +3 -3
  261. package/dist/services/agentSpecExecutionService.js +59 -55
  262. package/dist/services/api.d.ts +18 -4
  263. package/dist/services/api.js +46 -43
  264. package/dist/services/apiVariableService.d.ts +1 -1
  265. package/dist/services/apiVariableService.js +41 -34
  266. package/dist/services/autoSaveService.js +8 -8
  267. package/dist/services/categoriesApi.d.ts +2 -2
  268. package/dist/services/categoriesApi.js +8 -8
  269. package/dist/services/draftStorage.d.ts +1 -1
  270. package/dist/services/draftStorage.js +11 -11
  271. package/dist/services/dynamicSchemaService.d.ts +1 -1
  272. package/dist/services/dynamicSchemaService.js +41 -39
  273. package/dist/services/globalSave.d.ts +2 -2
  274. package/dist/services/globalSave.js +53 -42
  275. package/dist/services/historyService.d.ts +1 -1
  276. package/dist/services/historyService.js +8 -8
  277. package/dist/services/interruptService.d.ts +1 -1
  278. package/dist/services/interruptService.js +35 -29
  279. package/dist/services/nodeExecutionService.d.ts +1 -1
  280. package/dist/services/nodeExecutionService.js +45 -44
  281. package/dist/services/playgroundService.d.ts +1 -1
  282. package/dist/services/playgroundService.js +29 -29
  283. package/dist/services/portConfigApi.d.ts +2 -2
  284. package/dist/services/portConfigApi.js +8 -8
  285. package/dist/services/settingsService.d.ts +2 -2
  286. package/dist/services/settingsService.js +25 -19
  287. package/dist/services/toastService.d.ts +4 -4
  288. package/dist/services/toastService.js +33 -33
  289. package/dist/services/variableService.d.ts +1 -1
  290. package/dist/services/variableService.js +36 -36
  291. package/dist/services/workflowStorage.d.ts +2 -2
  292. package/dist/services/workflowStorage.js +13 -13
  293. package/dist/settings/index.d.ts +7 -7
  294. package/dist/settings/index.js +6 -6
  295. package/dist/skins/default.d.ts +2 -0
  296. package/dist/skins/default.js +1 -0
  297. package/dist/skins/index.d.ts +13 -0
  298. package/dist/skins/index.js +30 -0
  299. package/dist/skins/slate.d.ts +2 -0
  300. package/dist/skins/slate.js +78 -0
  301. package/dist/stores/categoriesStore.svelte.d.ts +1 -1
  302. package/dist/stores/categoriesStore.svelte.js +5 -5
  303. package/dist/stores/editorStateMachine.svelte.d.ts +2 -2
  304. package/dist/stores/editorStateMachine.svelte.js +65 -33
  305. package/dist/stores/historyStore.svelte.d.ts +4 -4
  306. package/dist/stores/historyStore.svelte.js +4 -4
  307. package/dist/stores/interruptStore.svelte.d.ts +3 -3
  308. package/dist/stores/interruptStore.svelte.js +21 -21
  309. package/dist/stores/playgroundStore.svelte.d.ts +2 -2
  310. package/dist/stores/playgroundStore.svelte.js +25 -18
  311. package/dist/stores/portCoordinateStore.svelte.d.ts +2 -2
  312. package/dist/stores/portCoordinateStore.svelte.js +15 -8
  313. package/dist/stores/settingsStore.svelte.d.ts +2 -2
  314. package/dist/stores/settingsStore.svelte.js +62 -57
  315. package/dist/stores/workflowStore.svelte.d.ts +3 -3
  316. package/dist/stores/workflowStore.svelte.js +50 -47
  317. package/dist/stories/CanvasDecorator.svelte +35 -32
  318. package/dist/stories/CanvasDecorator.svelte.d.ts +2 -2
  319. package/dist/stories/EdgeDecorator.svelte +125 -0
  320. package/dist/stories/EdgeDecorator.svelte.d.ts +17 -0
  321. package/dist/stories/NodeDecorator.svelte +59 -53
  322. package/dist/stories/NodeDecorator.svelte.d.ts +1 -1
  323. package/dist/stories/utils.d.ts +2 -2
  324. package/dist/stories/utils.js +105 -67
  325. package/dist/styles/base.css +599 -595
  326. package/dist/styles/toast.css +14 -14
  327. package/dist/styles/tokens.css +409 -378
  328. package/dist/svelte-app.d.ts +9 -9
  329. package/dist/svelte-app.js +39 -39
  330. package/dist/themes/default.d.ts +2 -0
  331. package/dist/themes/default.js +9 -0
  332. package/dist/themes/index.d.ts +13 -0
  333. package/dist/themes/index.js +44 -0
  334. package/dist/themes/minimal.d.ts +2 -0
  335. package/dist/themes/minimal.js +11 -0
  336. package/dist/types/agentspec.d.ts +18 -18
  337. package/dist/types/agentspec.js +2 -2
  338. package/dist/types/auth.d.ts +1 -1
  339. package/dist/types/auth.js +6 -6
  340. package/dist/types/config.d.ts +6 -6
  341. package/dist/types/events.d.ts +2 -2
  342. package/dist/types/events.js +2 -2
  343. package/dist/types/index.d.ts +32 -32
  344. package/dist/types/index.js +6 -6
  345. package/dist/types/interrupt.d.ts +6 -6
  346. package/dist/types/interrupt.js +21 -21
  347. package/dist/types/interruptState.d.ts +12 -12
  348. package/dist/types/interruptState.js +66 -66
  349. package/dist/types/playground.d.ts +7 -7
  350. package/dist/types/playground.js +14 -14
  351. package/dist/types/settings.d.ts +5 -3
  352. package/dist/types/settings.js +25 -18
  353. package/dist/types/skin.d.ts +31 -0
  354. package/dist/types/skin.js +1 -0
  355. package/dist/types/theme.d.ts +35 -0
  356. package/dist/types/theme.js +1 -0
  357. package/dist/types/uischema.d.ts +4 -4
  358. package/dist/types/uischema.js +3 -3
  359. package/dist/utils/colors.d.ts +1 -1
  360. package/dist/utils/colors.js +97 -95
  361. package/dist/utils/config.d.ts +2 -2
  362. package/dist/utils/config.js +48 -48
  363. package/dist/utils/connections.d.ts +2 -2
  364. package/dist/utils/connections.js +15 -15
  365. package/dist/utils/errors.js +3 -3
  366. package/dist/utils/fetchWithAuth.d.ts +1 -1
  367. package/dist/utils/fetchWithAuth.js +2 -2
  368. package/dist/utils/handleIds.d.ts +2 -2
  369. package/dist/utils/handleIds.js +8 -8
  370. package/dist/utils/handlePositioning.d.ts +1 -1
  371. package/dist/utils/handlePositioning.js +2 -2
  372. package/dist/utils/icons.d.ts +1 -1
  373. package/dist/utils/icons.js +74 -74
  374. package/dist/utils/logger.d.ts +1 -1
  375. package/dist/utils/logger.js +7 -7
  376. package/dist/utils/nodeStatus.d.ts +1 -1
  377. package/dist/utils/nodeStatus.js +48 -48
  378. package/dist/utils/nodeTypes.d.ts +1 -1
  379. package/dist/utils/nodeTypes.js +21 -20
  380. package/dist/utils/nodeWrapper.d.ts +7 -7
  381. package/dist/utils/nodeWrapper.js +21 -19
  382. package/dist/utils/performanceUtils.d.ts +1 -1
  383. package/dist/utils/performanceUtils.js +2 -1
  384. package/dist/utils/sanitize.js +1 -1
  385. package/dist/utils/uischema.d.ts +2 -2
  386. package/dist/utils/uischema.js +8 -8
  387. package/dist/utils/validation.js +20 -8
  388. package/package.json +296 -291
@@ -8,594 +8,628 @@
8
8
  -->
9
9
 
10
10
  <script lang="ts">
11
- import Icon from '@iconify/svelte';
12
- import ConfirmationPrompt from './ConfirmationPrompt.svelte';
13
- import ChoicePrompt from './ChoicePrompt.svelte';
14
- import TextInputPrompt from './TextInputPrompt.svelte';
15
- import FormPrompt from './FormPrompt.svelte';
16
- import ReviewPrompt from './ReviewPrompt.svelte';
17
- import type {
18
- Interrupt,
19
- InterruptType,
20
- ConfirmationConfig,
21
- ChoiceConfig,
22
- TextConfig,
23
- FormConfig,
24
- ReviewConfig,
25
- ReviewResolution
26
- } from '../../types/interrupt.js';
27
- import {
28
- isTerminalState,
29
- isSubmitting as checkIsSubmitting,
30
- getErrorMessage,
31
- getResolvedValue
32
- } from '../../types/interruptState.js';
33
- import {
34
- getInterruptsMap,
35
- interruptActions,
36
- type InterruptWithState
37
- } from '../../stores/interruptStore.svelte.js';
38
- import { interruptService } from '../../services/interruptService.js';
39
- import { logger } from '../../utils/logger.js';
40
-
41
- /**
42
- * Component props
43
- */
44
- interface Props {
45
- /** The interrupt to display (initial data, used for ID lookup) */
46
- interrupt: Interrupt | InterruptWithState;
47
- /** Whether to show the timestamp */
48
- showTimestamp?: boolean;
49
- /** Callback to refresh messages after interrupt resolution */
50
- onResolved?: () => void;
51
- }
52
-
53
- let { interrupt: initialInterrupt, showTimestamp = true, onResolved }: Props = $props();
54
-
55
- /**
56
- * Get the current interrupt state from the store.
57
- * This ensures we react to store updates (like status changes).
58
- */
59
- const currentInterrupt = $derived(
60
- getInterruptsMap().get(initialInterrupt.id) ?? addMachineState(initialInterrupt)
61
- );
62
-
63
- /**
64
- * Helper to ensure interrupt has machine state
65
- */
66
- function addMachineState(interrupt: Interrupt | InterruptWithState): InterruptWithState {
67
- if ('machineState' in interrupt) {
68
- return interrupt;
69
- }
70
- return {
71
- ...interrupt,
72
- machineState: { status: 'idle' }
73
- };
74
- }
75
-
76
- /** Whether this interrupt is in a terminal state (resolved or cancelled) */
77
- const isResolved = $derived(isTerminalState(currentInterrupt.machineState));
78
-
79
- /** Whether this interrupt is currently submitting */
80
- const isSubmitting = $derived(checkIsSubmitting(currentInterrupt.machineState));
81
-
82
- /** Error message for this interrupt */
83
- const error = $derived(getErrorMessage(currentInterrupt.machineState));
84
-
85
- /** Resolved value for display */
86
- const resolvedValue = $derived(getResolvedValue(currentInterrupt.machineState));
87
-
88
- /**
89
- * Get the icon for the interrupt type
90
- */
91
- function getTypeIcon(type: InterruptType): string {
92
- switch (type) {
93
- case 'confirmation':
94
- return 'mdi:help-circle';
95
- case 'choice':
96
- return 'mdi:format-list-bulleted';
97
- case 'text':
98
- return 'mdi:text-box';
99
- case 'form':
100
- return 'mdi:form-select';
101
- case 'review':
102
- return 'mdi:file-compare';
103
- default:
104
- return 'mdi:bell';
105
- }
106
- }
107
-
108
- /**
109
- * Get the label for the interrupt type
110
- */
111
- function getTypeLabel(type: InterruptType): string {
112
- switch (type) {
113
- case 'confirmation':
114
- return 'Confirmation Required';
115
- case 'choice':
116
- return 'Selection Required';
117
- case 'text':
118
- return 'Input Required';
119
- case 'form':
120
- return 'Form Required';
121
- case 'review':
122
- return 'Review Required';
123
- default:
124
- return 'Action Required';
125
- }
126
- }
127
-
128
- /** Get resolved label for the header when resolved */
129
- function getResolvedLabel(type: InterruptType): string {
130
- switch (type) {
131
- case 'confirmation':
132
- return 'Confirmation Submitted';
133
- case 'choice':
134
- return 'Selection Made';
135
- case 'text':
136
- return 'Input Submitted';
137
- case 'form':
138
- return 'Form Submitted';
139
- case 'review':
140
- return 'Review Submitted';
141
- default:
142
- return 'Response Submitted';
143
- }
144
- }
145
-
146
- /**
147
- * Format timestamp for display
148
- */
149
- function formatTimestamp(timestamp: string): string {
150
- const date = new Date(timestamp);
151
- return date.toLocaleTimeString('en-US', {
152
- hour12: false,
153
- hour: '2-digit',
154
- minute: '2-digit',
155
- second: '2-digit'
156
- });
157
- }
158
-
159
- /**
160
- * Handle resolve action using state machine
161
- */
162
- async function handleResolve(value: unknown): Promise<void> {
163
- // Start the submission - state machine validates this transition
164
- const startResult = interruptActions.startSubmit(currentInterrupt.id, value);
165
- if (!startResult.valid) {
166
- logger.warn('[InterruptBubble] Cannot submit:', startResult.error);
167
- return;
168
- }
169
-
170
- try {
171
- // Call API if service is configured
172
- if (interruptService.isConfigured()) {
173
- await interruptService.resolveInterrupt(currentInterrupt.id, value);
174
- }
175
-
176
- // Mark as successful - transitions to resolved state
177
- interruptActions.submitSuccess(currentInterrupt.id);
178
-
179
- // Notify parent to refresh messages
180
- onResolved?.();
181
- } catch (err) {
182
- // Mark as failed - transitions to error state (can retry)
183
- const errorMessage = err instanceof Error ? err.message : 'Failed to submit response';
184
- interruptActions.submitFailure(currentInterrupt.id, errorMessage);
185
- logger.error('[InterruptBubble] Resolve error:', err);
186
- }
187
- }
188
-
189
- /**
190
- * Handle cancel action using state machine
191
- */
192
- async function handleCancel(): Promise<void> {
193
- // Start the cancel - state machine validates this transition
194
- const startResult = interruptActions.startCancel(currentInterrupt.id);
195
- if (!startResult.valid) {
196
- logger.warn('[InterruptBubble] Cannot cancel:', startResult.error);
197
- return;
198
- }
199
-
200
- try {
201
- // Call API if service is configured
202
- if (interruptService.isConfigured()) {
203
- await interruptService.cancelInterrupt(currentInterrupt.id);
204
- }
205
-
206
- // Mark as successful - transitions to cancelled state
207
- interruptActions.submitSuccess(currentInterrupt.id);
208
-
209
- // Notify parent to refresh messages
210
- onResolved?.();
211
- } catch (err) {
212
- // Mark as failed - transitions to error state (can retry)
213
- const errorMessage = err instanceof Error ? err.message : 'Failed to cancel';
214
- interruptActions.submitFailure(currentInterrupt.id, errorMessage);
215
- logger.error('[InterruptBubble] Cancel error:', err);
216
- }
217
- }
218
-
219
- /**
220
- * Handle retry after error
221
- */
222
- function handleRetry(): void {
223
- interruptActions.retry(currentInterrupt.id);
224
- }
225
-
226
- // Typed config getters for each prompt type
227
- const confirmationConfig = $derived(currentInterrupt.config as ConfirmationConfig);
228
- const choiceConfig = $derived(currentInterrupt.config as ChoiceConfig);
229
- const textConfig = $derived(currentInterrupt.config as TextConfig);
230
- const formConfig = $derived(currentInterrupt.config as FormConfig);
231
- const reviewConfig = $derived(currentInterrupt.config as ReviewConfig);
232
-
233
- // Determine the actual resolved value to pass to prompt components
234
- const displayResolvedValue = $derived(resolvedValue ?? currentInterrupt.responseValue);
235
-
236
- /**
237
- * Extract the username of who resolved the interrupt from metadata.
238
- * This is provided by the backend when the interrupt is resolved.
239
- */
240
- const resolvedByUserName = $derived(
241
- typeof currentInterrupt.metadata?.resolvedByUserName === 'string'
242
- ? currentInterrupt.metadata.resolvedByUserName
243
- : undefined
244
- );
11
+ import Icon from "@iconify/svelte";
12
+ import ConfirmationPrompt from "./ConfirmationPrompt.svelte";
13
+ import ChoicePrompt from "./ChoicePrompt.svelte";
14
+ import TextInputPrompt from "./TextInputPrompt.svelte";
15
+ import FormPrompt from "./FormPrompt.svelte";
16
+ import ReviewPrompt from "./ReviewPrompt.svelte";
17
+ import type {
18
+ Interrupt,
19
+ InterruptType,
20
+ ConfirmationConfig,
21
+ ChoiceConfig,
22
+ TextConfig,
23
+ FormConfig,
24
+ ReviewConfig,
25
+ ReviewResolution,
26
+ } from "../../types/interrupt.js";
27
+ import {
28
+ isTerminalState,
29
+ isSubmitting as checkIsSubmitting,
30
+ getErrorMessage,
31
+ getResolvedValue,
32
+ } from "../../types/interruptState.js";
33
+ import {
34
+ getInterruptsMap,
35
+ interruptActions,
36
+ type InterruptWithState,
37
+ } from "../../stores/interruptStore.svelte.js";
38
+ import { interruptService } from "../../services/interruptService.js";
39
+ import { logger } from "../../utils/logger.js";
40
+
41
+ /**
42
+ * Component props
43
+ */
44
+ interface Props {
45
+ /** The interrupt to display (initial data, used for ID lookup) */
46
+ interrupt: Interrupt | InterruptWithState;
47
+ /** Whether to show the timestamp */
48
+ showTimestamp?: boolean;
49
+ /** Callback to refresh messages after interrupt resolution */
50
+ onResolved?: () => void;
51
+ }
52
+
53
+ let {
54
+ interrupt: initialInterrupt,
55
+ showTimestamp = true,
56
+ onResolved,
57
+ }: Props = $props();
58
+
59
+ /**
60
+ * Get the current interrupt state from the store.
61
+ * This ensures we react to store updates (like status changes).
62
+ */
63
+ const currentInterrupt = $derived(
64
+ getInterruptsMap().get(initialInterrupt.id) ??
65
+ addMachineState(initialInterrupt),
66
+ );
67
+
68
+ /**
69
+ * Helper to ensure interrupt has machine state
70
+ */
71
+ function addMachineState(
72
+ interrupt: Interrupt | InterruptWithState,
73
+ ): InterruptWithState {
74
+ if ("machineState" in interrupt) {
75
+ return interrupt;
76
+ }
77
+ return {
78
+ ...interrupt,
79
+ machineState: { status: "idle" },
80
+ };
81
+ }
82
+
83
+ /** Whether this interrupt is in a terminal state (resolved or cancelled) */
84
+ const isResolved = $derived(isTerminalState(currentInterrupt.machineState));
85
+
86
+ /** Whether this interrupt is currently submitting */
87
+ const isSubmitting = $derived(
88
+ checkIsSubmitting(currentInterrupt.machineState),
89
+ );
90
+
91
+ /** Error message for this interrupt */
92
+ const error = $derived(getErrorMessage(currentInterrupt.machineState));
93
+
94
+ /** Resolved value for display */
95
+ const resolvedValue = $derived(
96
+ getResolvedValue(currentInterrupt.machineState),
97
+ );
98
+
99
+ /**
100
+ * Get the icon for the interrupt type
101
+ */
102
+ function getTypeIcon(type: InterruptType): string {
103
+ switch (type) {
104
+ case "confirmation":
105
+ return "mdi:help-circle";
106
+ case "choice":
107
+ return "mdi:format-list-bulleted";
108
+ case "text":
109
+ return "mdi:text-box";
110
+ case "form":
111
+ return "mdi:form-select";
112
+ case "review":
113
+ return "mdi:file-compare";
114
+ default:
115
+ return "mdi:bell";
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Get the label for the interrupt type
121
+ */
122
+ function getTypeLabel(type: InterruptType): string {
123
+ switch (type) {
124
+ case "confirmation":
125
+ return "Confirmation Required";
126
+ case "choice":
127
+ return "Selection Required";
128
+ case "text":
129
+ return "Input Required";
130
+ case "form":
131
+ return "Form Required";
132
+ case "review":
133
+ return "Review Required";
134
+ default:
135
+ return "Action Required";
136
+ }
137
+ }
138
+
139
+ /** Get resolved label for the header when resolved */
140
+ function getResolvedLabel(type: InterruptType): string {
141
+ switch (type) {
142
+ case "confirmation":
143
+ return "Confirmation Submitted";
144
+ case "choice":
145
+ return "Selection Made";
146
+ case "text":
147
+ return "Input Submitted";
148
+ case "form":
149
+ return "Form Submitted";
150
+ case "review":
151
+ return "Review Submitted";
152
+ default:
153
+ return "Response Submitted";
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Format timestamp for display
159
+ */
160
+ function formatTimestamp(timestamp: string): string {
161
+ const date = new Date(timestamp);
162
+ return date.toLocaleTimeString("en-US", {
163
+ hour12: false,
164
+ hour: "2-digit",
165
+ minute: "2-digit",
166
+ second: "2-digit",
167
+ });
168
+ }
169
+
170
+ /**
171
+ * Handle resolve action using state machine
172
+ */
173
+ async function handleResolve(value: unknown): Promise<void> {
174
+ // Start the submission - state machine validates this transition
175
+ const startResult = interruptActions.startSubmit(
176
+ currentInterrupt.id,
177
+ value,
178
+ );
179
+ if (!startResult.valid) {
180
+ logger.warn("[InterruptBubble] Cannot submit:", startResult.error);
181
+ return;
182
+ }
183
+
184
+ try {
185
+ // Call API if service is configured
186
+ if (interruptService.isConfigured()) {
187
+ await interruptService.resolveInterrupt(currentInterrupt.id, value);
188
+ }
189
+
190
+ // Mark as successful - transitions to resolved state
191
+ interruptActions.submitSuccess(currentInterrupt.id);
192
+
193
+ // Notify parent to refresh messages
194
+ onResolved?.();
195
+ } catch (err) {
196
+ // Mark as failed - transitions to error state (can retry)
197
+ const errorMessage =
198
+ err instanceof Error ? err.message : "Failed to submit response";
199
+ interruptActions.submitFailure(currentInterrupt.id, errorMessage);
200
+ logger.error("[InterruptBubble] Resolve error:", err);
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Handle cancel action using state machine
206
+ */
207
+ async function handleCancel(): Promise<void> {
208
+ // Start the cancel - state machine validates this transition
209
+ const startResult = interruptActions.startCancel(currentInterrupt.id);
210
+ if (!startResult.valid) {
211
+ logger.warn("[InterruptBubble] Cannot cancel:", startResult.error);
212
+ return;
213
+ }
214
+
215
+ try {
216
+ // Call API if service is configured
217
+ if (interruptService.isConfigured()) {
218
+ await interruptService.cancelInterrupt(currentInterrupt.id);
219
+ }
220
+
221
+ // Mark as successful - transitions to cancelled state
222
+ interruptActions.submitSuccess(currentInterrupt.id);
223
+
224
+ // Notify parent to refresh messages
225
+ onResolved?.();
226
+ } catch (err) {
227
+ // Mark as failed - transitions to error state (can retry)
228
+ const errorMessage =
229
+ err instanceof Error ? err.message : "Failed to cancel";
230
+ interruptActions.submitFailure(currentInterrupt.id, errorMessage);
231
+ logger.error("[InterruptBubble] Cancel error:", err);
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Handle retry after error
237
+ */
238
+ function handleRetry(): void {
239
+ interruptActions.retry(currentInterrupt.id);
240
+ }
241
+
242
+ // Typed config getters for each prompt type
243
+ const confirmationConfig = $derived(
244
+ currentInterrupt.config as ConfirmationConfig,
245
+ );
246
+ const choiceConfig = $derived(currentInterrupt.config as ChoiceConfig);
247
+ const textConfig = $derived(currentInterrupt.config as TextConfig);
248
+ const formConfig = $derived(currentInterrupt.config as FormConfig);
249
+ const reviewConfig = $derived(currentInterrupt.config as ReviewConfig);
250
+
251
+ // Determine the actual resolved value to pass to prompt components
252
+ const displayResolvedValue = $derived(
253
+ resolvedValue ?? currentInterrupt.responseValue,
254
+ );
255
+
256
+ /**
257
+ * Extract the username of who resolved the interrupt from metadata.
258
+ * This is provided by the backend when the interrupt is resolved.
259
+ */
260
+ const resolvedByUserName = $derived(
261
+ typeof currentInterrupt.metadata?.resolvedByUserName === "string"
262
+ ? currentInterrupt.metadata.resolvedByUserName
263
+ : undefined,
264
+ );
245
265
  </script>
246
266
 
247
267
  <div
248
- class="interrupt-bubble"
249
- class:interrupt-bubble--completed={currentInterrupt.machineState.status === 'resolved'}
250
- class:interrupt-bubble--cancelled={currentInterrupt.machineState.status === 'cancelled'}
251
- class:interrupt-bubble--submitting={isSubmitting}
252
- class:interrupt-bubble--error={currentInterrupt.machineState.status === 'error'}
268
+ class="interrupt-bubble"
269
+ class:interrupt-bubble--completed={currentInterrupt.machineState.status ===
270
+ "resolved"}
271
+ class:interrupt-bubble--cancelled={currentInterrupt.machineState.status ===
272
+ "cancelled"}
273
+ class:interrupt-bubble--submitting={isSubmitting}
274
+ class:interrupt-bubble--error={currentInterrupt.machineState.status ===
275
+ "error"}
253
276
  >
254
- <!-- Header -->
255
- <div class="interrupt-bubble__header">
256
- <span class="interrupt-bubble__type">
257
- <Icon icon={getTypeIcon(currentInterrupt.type)} />
258
- {#if isResolved}
259
- {currentInterrupt.machineState.status === 'cancelled'
260
- ? 'Cancelled'
261
- : getResolvedLabel(currentInterrupt.type)}
262
- {:else if currentInterrupt.machineState.status === 'error'}
263
- Error - Click to Retry
264
- {:else}
265
- {getTypeLabel(currentInterrupt.type)}
266
- {/if}
267
- </span>
268
- {#if showTimestamp}
269
- <span class="interrupt-bubble__timestamp">
270
- {formatTimestamp(currentInterrupt.resolvedAt ?? currentInterrupt.createdAt)}
271
- </span>
272
- {/if}
273
- </div>
274
-
275
- <!-- Error message with retry button -->
276
- {#if currentInterrupt.machineState.status === 'error'}
277
- <div class="interrupt-bubble__error">
278
- <Icon icon="mdi:alert-circle" />
279
- <span>{error}</span>
280
- <button type="button" class="interrupt-bubble__retry-btn" onclick={handleRetry}>
281
- <Icon icon="mdi:refresh" />
282
- Retry
283
- </button>
284
- </div>
285
- {/if}
286
-
287
- <!-- Prompt content based on type -->
288
- <div class="interrupt-bubble__body">
289
- {#if currentInterrupt.type === 'confirmation'}
290
- <ConfirmationPrompt
291
- config={confirmationConfig}
292
- {isResolved}
293
- resolvedValue={displayResolvedValue as boolean | undefined}
294
- {isSubmitting}
295
- {error}
296
- {resolvedByUserName}
297
- onConfirm={() => handleResolve(true)}
298
- onDecline={() => handleResolve(false)}
299
- />
300
- {:else if currentInterrupt.type === 'choice'}
301
- <ChoicePrompt
302
- config={choiceConfig}
303
- {isResolved}
304
- resolvedValue={displayResolvedValue as string | string[] | undefined}
305
- {isSubmitting}
306
- {error}
307
- {resolvedByUserName}
308
- onSubmit={(value) => handleResolve(value)}
309
- />
310
- {:else if currentInterrupt.type === 'text'}
311
- <TextInputPrompt
312
- config={textConfig}
313
- {isResolved}
314
- resolvedValue={displayResolvedValue as string | undefined}
315
- {isSubmitting}
316
- {error}
317
- {resolvedByUserName}
318
- onSubmit={(value) => handleResolve(value)}
319
- />
320
- {:else if currentInterrupt.type === 'form'}
321
- <FormPrompt
322
- config={formConfig}
323
- {isResolved}
324
- resolvedValue={displayResolvedValue as Record<string, unknown> | undefined}
325
- {isSubmitting}
326
- {error}
327
- {resolvedByUserName}
328
- onSubmit={(value) => handleResolve(value)}
329
- />
330
- {:else if currentInterrupt.type === 'review'}
331
- <ReviewPrompt
332
- config={reviewConfig}
333
- {isResolved}
334
- resolvedValue={displayResolvedValue as ReviewResolution | undefined}
335
- {isSubmitting}
336
- {error}
337
- {resolvedByUserName}
338
- onSubmit={(value) => handleResolve(value)}
339
- />
340
- {/if}
341
- </div>
342
-
343
- <!-- Footer -->
344
- {#if currentInterrupt.nodeId || (currentInterrupt.allowCancel && !isResolved && currentInterrupt.type !== 'confirmation')}
345
- <div class="interrupt-bubble__footer">
346
- {#if currentInterrupt.nodeId}
347
- <span class="interrupt-bubble__node" title="Node ID: {currentInterrupt.nodeId}">
348
- <Icon icon="mdi:graph" />
349
- <span>From workflow node</span>
350
- </span>
351
- {/if}
352
- {#if currentInterrupt.allowCancel && !isResolved && currentInterrupt.type !== 'confirmation'}
353
- <button
354
- type="button"
355
- class="interrupt-bubble__cancel-btn"
356
- onclick={handleCancel}
357
- disabled={isSubmitting}
358
- >
359
- <Icon icon="mdi:close" />
360
- <span>Cancel</span>
361
- </button>
362
- {/if}
363
- </div>
364
- {/if}
277
+ <!-- Header -->
278
+ <div class="interrupt-bubble__header">
279
+ <span class="interrupt-bubble__type">
280
+ <Icon icon={getTypeIcon(currentInterrupt.type)} />
281
+ {#if isResolved}
282
+ {currentInterrupt.machineState.status === "cancelled"
283
+ ? "Cancelled"
284
+ : getResolvedLabel(currentInterrupt.type)}
285
+ {:else if currentInterrupt.machineState.status === "error"}
286
+ Error - Click to Retry
287
+ {:else}
288
+ {getTypeLabel(currentInterrupt.type)}
289
+ {/if}
290
+ </span>
291
+ {#if showTimestamp}
292
+ <span class="interrupt-bubble__timestamp">
293
+ {formatTimestamp(
294
+ currentInterrupt.resolvedAt ?? currentInterrupt.createdAt,
295
+ )}
296
+ </span>
297
+ {/if}
298
+ </div>
299
+
300
+ <!-- Error message with retry button -->
301
+ {#if currentInterrupt.machineState.status === "error"}
302
+ <div class="interrupt-bubble__error">
303
+ <Icon icon="mdi:alert-circle" />
304
+ <span>{error}</span>
305
+ <button
306
+ type="button"
307
+ class="interrupt-bubble__retry-btn"
308
+ onclick={handleRetry}
309
+ >
310
+ <Icon icon="mdi:refresh" />
311
+ Retry
312
+ </button>
313
+ </div>
314
+ {/if}
315
+
316
+ <!-- Prompt content based on type -->
317
+ <div class="interrupt-bubble__body">
318
+ {#if currentInterrupt.type === "confirmation"}
319
+ <ConfirmationPrompt
320
+ config={confirmationConfig}
321
+ {isResolved}
322
+ resolvedValue={displayResolvedValue as boolean | undefined}
323
+ {isSubmitting}
324
+ {error}
325
+ {resolvedByUserName}
326
+ onConfirm={() => handleResolve(true)}
327
+ onDecline={() => handleResolve(false)}
328
+ />
329
+ {:else if currentInterrupt.type === "choice"}
330
+ <ChoicePrompt
331
+ config={choiceConfig}
332
+ {isResolved}
333
+ resolvedValue={displayResolvedValue as string | string[] | undefined}
334
+ {isSubmitting}
335
+ {error}
336
+ {resolvedByUserName}
337
+ onSubmit={(value) => handleResolve(value)}
338
+ />
339
+ {:else if currentInterrupt.type === "text"}
340
+ <TextInputPrompt
341
+ config={textConfig}
342
+ {isResolved}
343
+ resolvedValue={displayResolvedValue as string | undefined}
344
+ {isSubmitting}
345
+ {error}
346
+ {resolvedByUserName}
347
+ onSubmit={(value) => handleResolve(value)}
348
+ />
349
+ {:else if currentInterrupt.type === "form"}
350
+ <FormPrompt
351
+ config={formConfig}
352
+ {isResolved}
353
+ resolvedValue={displayResolvedValue as
354
+ | Record<string, unknown>
355
+ | undefined}
356
+ {isSubmitting}
357
+ {error}
358
+ {resolvedByUserName}
359
+ onSubmit={(value) => handleResolve(value)}
360
+ />
361
+ {:else if currentInterrupt.type === "review"}
362
+ <ReviewPrompt
363
+ config={reviewConfig}
364
+ {isResolved}
365
+ resolvedValue={displayResolvedValue as ReviewResolution | undefined}
366
+ {isSubmitting}
367
+ {error}
368
+ {resolvedByUserName}
369
+ onSubmit={(value) => handleResolve(value)}
370
+ />
371
+ {/if}
372
+ </div>
373
+
374
+ <!-- Footer -->
375
+ {#if currentInterrupt.nodeId || (currentInterrupt.allowCancel && !isResolved && currentInterrupt.type !== "confirmation")}
376
+ <div class="interrupt-bubble__footer">
377
+ {#if currentInterrupt.nodeId}
378
+ <span
379
+ class="interrupt-bubble__node"
380
+ title="Node ID: {currentInterrupt.nodeId}"
381
+ >
382
+ <Icon icon="mdi:graph" />
383
+ <span>From workflow node</span>
384
+ </span>
385
+ {/if}
386
+ {#if currentInterrupt.allowCancel && !isResolved && currentInterrupt.type !== "confirmation"}
387
+ <button
388
+ type="button"
389
+ class="interrupt-bubble__cancel-btn"
390
+ onclick={handleCancel}
391
+ disabled={isSubmitting}
392
+ >
393
+ <Icon icon="mdi:close" />
394
+ <span>Cancel</span>
395
+ </button>
396
+ {/if}
397
+ </div>
398
+ {/if}
365
399
  </div>
366
400
 
367
401
  <style>
368
- /* Uses design tokens from base.css: --fd-interrupt-* */
369
- .interrupt-bubble {
370
- display: flex;
371
- flex-direction: column;
372
- margin: var(--fd-space-md) var(--fd-space-xl);
373
- border-radius: var(--fd-radius-xl);
374
- background-color: var(--fd-interrupt-prompt-bg);
375
- border: 1px solid var(--fd-interrupt-prompt-border-pending);
376
- box-shadow: 0 2px 8px var(--fd-interrupt-pending-shadow);
377
- animation: interruptSlideIn 0.3s ease-out;
378
- overflow: hidden;
379
- }
380
-
381
- @keyframes interruptSlideIn {
382
- from {
383
- opacity: 0;
384
- transform: translateY(12px);
385
- }
386
- to {
387
- opacity: 1;
388
- transform: translateY(0);
389
- }
390
- }
391
-
392
- /* State border colors */
393
- .interrupt-bubble--completed {
394
- border-color: var(--fd-interrupt-prompt-border-completed);
395
- box-shadow: 0 2px 8px var(--fd-interrupt-completed-shadow);
396
- }
397
-
398
- .interrupt-bubble--cancelled {
399
- border-color: var(--fd-interrupt-prompt-border-cancelled);
400
- box-shadow: 0 2px 8px var(--fd-interrupt-cancelled-shadow);
401
- }
402
-
403
- .interrupt-bubble--error {
404
- border-color: var(--fd-interrupt-prompt-border-error);
405
- box-shadow: 0 2px 8px var(--fd-interrupt-error-shadow);
406
- }
407
-
408
- .interrupt-bubble--submitting {
409
- opacity: 0.9;
410
- }
411
-
412
- /* Header */
413
- .interrupt-bubble__header {
414
- display: flex;
415
- align-items: center;
416
- justify-content: space-between;
417
- gap: var(--fd-space-xs);
418
- padding: var(--fd-space-md) var(--fd-space-xl);
419
- background: var(--fd-interrupt-pending-bg);
420
- border-bottom: 1px solid var(--fd-interrupt-prompt-border-pending);
421
- }
422
-
423
- .interrupt-bubble--completed .interrupt-bubble__header {
424
- background: var(--fd-interrupt-completed-bg);
425
- border-bottom-color: var(--fd-interrupt-prompt-border-completed);
426
- }
427
-
428
- .interrupt-bubble--cancelled .interrupt-bubble__header {
429
- background: var(--fd-interrupt-cancelled-bg);
430
- border-bottom-color: var(--fd-interrupt-prompt-border-cancelled);
431
- }
432
-
433
- .interrupt-bubble--error .interrupt-bubble__header {
434
- background: var(--fd-interrupt-error-bg);
435
- border-bottom-color: var(--fd-interrupt-prompt-border-error);
436
- }
437
-
438
- .interrupt-bubble__type {
439
- display: flex;
440
- align-items: center;
441
- gap: var(--fd-space-2xs);
442
- font-weight: 600;
443
- font-size: var(--fd-text-sm);
444
- color: var(--fd-interrupt-pending-text);
445
- }
446
-
447
- .interrupt-bubble--completed .interrupt-bubble__type {
448
- color: var(--fd-interrupt-completed-text);
449
- }
450
-
451
- .interrupt-bubble--cancelled .interrupt-bubble__type {
452
- color: var(--fd-interrupt-cancelled-text);
453
- }
454
-
455
- .interrupt-bubble--error .interrupt-bubble__type {
456
- color: var(--fd-interrupt-error-text);
457
- }
458
-
459
- .interrupt-bubble__timestamp {
460
- font-size: var(--fd-text-2xs);
461
- color: var(--fd-interrupt-pending-text-light);
462
- font-family: var(--fd-font-mono);
463
- }
464
-
465
- .interrupt-bubble--completed .interrupt-bubble__timestamp {
466
- color: var(--fd-interrupt-completed-text-light);
467
- }
468
-
469
- .interrupt-bubble--cancelled .interrupt-bubble__timestamp {
470
- color: var(--fd-interrupt-cancelled-text-light);
471
- }
472
-
473
- .interrupt-bubble--error .interrupt-bubble__timestamp {
474
- color: var(--fd-interrupt-error-text-light);
475
- }
476
-
477
- /* Error message */
478
- .interrupt-bubble__error {
479
- display: flex;
480
- align-items: center;
481
- gap: var(--fd-space-xs);
482
- margin: var(--fd-space-md) var(--fd-space-xl) 0;
483
- padding: var(--fd-space-xs) var(--fd-space-md);
484
- background-color: var(--fd-error-muted);
485
- border-radius: var(--fd-radius-md);
486
- color: var(--fd-interrupt-error-text);
487
- font-size: var(--fd-interrupt-font-error);
488
- }
489
-
490
- .interrupt-bubble__retry-btn {
491
- display: inline-flex;
492
- align-items: center;
493
- gap: var(--fd-space-3xs);
494
- margin-left: auto;
495
- padding: var(--fd-space-3xs) var(--fd-space-xs);
496
- font-size: var(--fd-text-xs);
497
- font-weight: 500;
498
- font-family: inherit;
499
- color: var(--fd-error-foreground);
500
- background-color: var(--fd-interrupt-error-avatar);
501
- border: none;
502
- border-radius: var(--fd-radius-sm);
503
- cursor: pointer;
504
- transition: background-color var(--fd-transition-fast);
505
- }
506
-
507
- .interrupt-bubble__retry-btn:hover {
508
- background-color: var(--fd-error-hover);
509
- }
510
-
511
- /* Body - prompt content area, full width */
512
- .interrupt-bubble__body {
513
- padding: var(--fd-space-xl);
514
- }
515
-
516
- .interrupt-bubble--cancelled .interrupt-bubble__body {
517
- opacity: 0.75;
518
- }
519
-
520
- /* Desaturate body content in error state to reduce visual noise from green/red colors */
521
- .interrupt-bubble--error .interrupt-bubble__body {
522
- filter: saturate(0.2);
523
- opacity: 0.7;
524
- }
525
-
526
- /* Footer */
527
- .interrupt-bubble__footer {
528
- display: flex;
529
- align-items: center;
530
- justify-content: space-between;
531
- gap: var(--fd-space-xs);
532
- padding: var(--fd-space-md) var(--fd-space-xl);
533
- background: var(--fd-interrupt-pending-bg);
534
- border-top: 1px solid var(--fd-interrupt-prompt-border-pending);
535
- }
536
-
537
- .interrupt-bubble--completed .interrupt-bubble__footer {
538
- background: var(--fd-interrupt-completed-bg);
539
- border-top-color: var(--fd-interrupt-prompt-border-completed);
540
- }
541
-
542
- .interrupt-bubble--cancelled .interrupt-bubble__footer {
543
- background: var(--fd-interrupt-cancelled-bg);
544
- border-top-color: var(--fd-interrupt-prompt-border-cancelled);
545
- }
546
-
547
- .interrupt-bubble--error .interrupt-bubble__footer {
548
- background: var(--fd-interrupt-error-bg);
549
- border-top-color: var(--fd-interrupt-prompt-border-error);
550
- }
551
-
552
- .interrupt-bubble__node {
553
- display: flex;
554
- align-items: center;
555
- gap: var(--fd-space-3xs);
556
- font-size: var(--fd-text-2xs);
557
- color: var(--fd-muted-foreground);
558
- }
559
-
560
- .interrupt-bubble__cancel-btn {
561
- display: inline-flex;
562
- align-items: center;
563
- gap: var(--fd-space-2xs);
564
- margin-left: auto;
565
- padding: var(--fd-space-2xs) var(--fd-space-md);
566
- font-size: var(--fd-text-xs);
567
- font-weight: 500;
568
- font-family: inherit;
569
- color: var(--fd-muted-foreground);
570
- background-color: transparent;
571
- border: 1px solid var(--fd-border);
572
- border-radius: var(--fd-radius-md);
573
- cursor: pointer;
574
- transition: all var(--fd-transition-fast);
575
- }
576
-
577
- .interrupt-bubble__cancel-btn:hover:not(:disabled) {
578
- color: var(--fd-error);
579
- border-color: var(--fd-error);
580
- background-color: var(--fd-error-muted);
581
- }
582
-
583
- .interrupt-bubble__cancel-btn:disabled {
584
- opacity: 0.5;
585
- cursor: not-allowed;
586
- }
587
-
588
- /* Responsive */
589
- @media (max-width: 640px) {
590
- .interrupt-bubble {
591
- margin: var(--fd-space-xs);
592
- }
593
-
594
- .interrupt-bubble__header,
595
- .interrupt-bubble__body,
596
- .interrupt-bubble__footer {
597
- padding-left: var(--fd-space-lg);
598
- padding-right: var(--fd-space-lg);
599
- }
600
- }
402
+ /* Uses design tokens from base.css: --fd-interrupt-* */
403
+ .interrupt-bubble {
404
+ display: flex;
405
+ flex-direction: column;
406
+ margin: var(--fd-space-md) var(--fd-space-xl);
407
+ border-radius: var(--fd-radius-xl);
408
+ background-color: var(--fd-interrupt-prompt-bg);
409
+ border: 1px solid var(--fd-interrupt-prompt-border-pending);
410
+ box-shadow: 0 2px 8px var(--fd-interrupt-pending-shadow);
411
+ animation: interruptSlideIn 0.3s ease-out;
412
+ overflow: hidden;
413
+ }
414
+
415
+ @keyframes interruptSlideIn {
416
+ from {
417
+ opacity: 0;
418
+ transform: translateY(12px);
419
+ }
420
+ to {
421
+ opacity: 1;
422
+ transform: translateY(0);
423
+ }
424
+ }
425
+
426
+ /* State border colors */
427
+ .interrupt-bubble--completed {
428
+ border-color: var(--fd-interrupt-prompt-border-completed);
429
+ box-shadow: 0 2px 8px var(--fd-interrupt-completed-shadow);
430
+ }
431
+
432
+ .interrupt-bubble--cancelled {
433
+ border-color: var(--fd-interrupt-prompt-border-cancelled);
434
+ box-shadow: 0 2px 8px var(--fd-interrupt-cancelled-shadow);
435
+ }
436
+
437
+ .interrupt-bubble--error {
438
+ border-color: var(--fd-interrupt-prompt-border-error);
439
+ box-shadow: 0 2px 8px var(--fd-interrupt-error-shadow);
440
+ }
441
+
442
+ .interrupt-bubble--submitting {
443
+ opacity: 0.9;
444
+ }
445
+
446
+ /* Header */
447
+ .interrupt-bubble__header {
448
+ display: flex;
449
+ align-items: center;
450
+ justify-content: space-between;
451
+ gap: var(--fd-space-xs);
452
+ padding: var(--fd-space-md) var(--fd-space-xl);
453
+ background: var(--fd-interrupt-pending-bg);
454
+ border-bottom: 1px solid var(--fd-interrupt-prompt-border-pending);
455
+ }
456
+
457
+ .interrupt-bubble--completed .interrupt-bubble__header {
458
+ background: var(--fd-interrupt-completed-bg);
459
+ border-bottom-color: var(--fd-interrupt-prompt-border-completed);
460
+ }
461
+
462
+ .interrupt-bubble--cancelled .interrupt-bubble__header {
463
+ background: var(--fd-interrupt-cancelled-bg);
464
+ border-bottom-color: var(--fd-interrupt-prompt-border-cancelled);
465
+ }
466
+
467
+ .interrupt-bubble--error .interrupt-bubble__header {
468
+ background: var(--fd-interrupt-error-bg);
469
+ border-bottom-color: var(--fd-interrupt-prompt-border-error);
470
+ }
471
+
472
+ .interrupt-bubble__type {
473
+ display: flex;
474
+ align-items: center;
475
+ gap: var(--fd-space-2xs);
476
+ font-weight: 600;
477
+ font-size: var(--fd-text-sm);
478
+ color: var(--fd-interrupt-pending-text);
479
+ }
480
+
481
+ .interrupt-bubble--completed .interrupt-bubble__type {
482
+ color: var(--fd-interrupt-completed-text);
483
+ }
484
+
485
+ .interrupt-bubble--cancelled .interrupt-bubble__type {
486
+ color: var(--fd-interrupt-cancelled-text);
487
+ }
488
+
489
+ .interrupt-bubble--error .interrupt-bubble__type {
490
+ color: var(--fd-interrupt-error-text);
491
+ }
492
+
493
+ .interrupt-bubble__timestamp {
494
+ font-size: var(--fd-text-2xs);
495
+ color: var(--fd-interrupt-pending-text-light);
496
+ font-family: var(--fd-font-mono);
497
+ }
498
+
499
+ .interrupt-bubble--completed .interrupt-bubble__timestamp {
500
+ color: var(--fd-interrupt-completed-text-light);
501
+ }
502
+
503
+ .interrupt-bubble--cancelled .interrupt-bubble__timestamp {
504
+ color: var(--fd-interrupt-cancelled-text-light);
505
+ }
506
+
507
+ .interrupt-bubble--error .interrupt-bubble__timestamp {
508
+ color: var(--fd-interrupt-error-text-light);
509
+ }
510
+
511
+ /* Error message */
512
+ .interrupt-bubble__error {
513
+ display: flex;
514
+ align-items: center;
515
+ gap: var(--fd-space-xs);
516
+ margin: var(--fd-space-md) var(--fd-space-xl) 0;
517
+ padding: var(--fd-space-xs) var(--fd-space-md);
518
+ background-color: var(--fd-error-muted);
519
+ border-radius: var(--fd-radius-md);
520
+ color: var(--fd-interrupt-error-text);
521
+ font-size: var(--fd-interrupt-font-error);
522
+ }
523
+
524
+ .interrupt-bubble__retry-btn {
525
+ display: inline-flex;
526
+ align-items: center;
527
+ gap: var(--fd-space-3xs);
528
+ margin-left: auto;
529
+ padding: var(--fd-space-3xs) var(--fd-space-xs);
530
+ font-size: var(--fd-text-xs);
531
+ font-weight: 500;
532
+ font-family: inherit;
533
+ color: var(--fd-error-foreground);
534
+ background-color: var(--fd-interrupt-error-avatar);
535
+ border: none;
536
+ border-radius: var(--fd-radius-sm);
537
+ cursor: pointer;
538
+ transition: background-color var(--fd-transition-fast);
539
+ }
540
+
541
+ .interrupt-bubble__retry-btn:hover {
542
+ background-color: var(--fd-error-hover);
543
+ }
544
+
545
+ /* Body - prompt content area, full width */
546
+ .interrupt-bubble__body {
547
+ padding: var(--fd-space-xl);
548
+ }
549
+
550
+ .interrupt-bubble--cancelled .interrupt-bubble__body {
551
+ opacity: 0.75;
552
+ }
553
+
554
+ /* Desaturate body content in error state to reduce visual noise from green/red colors */
555
+ .interrupt-bubble--error .interrupt-bubble__body {
556
+ filter: saturate(0.2);
557
+ opacity: 0.7;
558
+ }
559
+
560
+ /* Footer */
561
+ .interrupt-bubble__footer {
562
+ display: flex;
563
+ align-items: center;
564
+ justify-content: space-between;
565
+ gap: var(--fd-space-xs);
566
+ padding: var(--fd-space-md) var(--fd-space-xl);
567
+ background: var(--fd-interrupt-pending-bg);
568
+ border-top: 1px solid var(--fd-interrupt-prompt-border-pending);
569
+ }
570
+
571
+ .interrupt-bubble--completed .interrupt-bubble__footer {
572
+ background: var(--fd-interrupt-completed-bg);
573
+ border-top-color: var(--fd-interrupt-prompt-border-completed);
574
+ }
575
+
576
+ .interrupt-bubble--cancelled .interrupt-bubble__footer {
577
+ background: var(--fd-interrupt-cancelled-bg);
578
+ border-top-color: var(--fd-interrupt-prompt-border-cancelled);
579
+ }
580
+
581
+ .interrupt-bubble--error .interrupt-bubble__footer {
582
+ background: var(--fd-interrupt-error-bg);
583
+ border-top-color: var(--fd-interrupt-prompt-border-error);
584
+ }
585
+
586
+ .interrupt-bubble__node {
587
+ display: flex;
588
+ align-items: center;
589
+ gap: var(--fd-space-3xs);
590
+ font-size: var(--fd-text-2xs);
591
+ color: var(--fd-muted-foreground);
592
+ }
593
+
594
+ .interrupt-bubble__cancel-btn {
595
+ display: inline-flex;
596
+ align-items: center;
597
+ gap: var(--fd-space-2xs);
598
+ margin-left: auto;
599
+ padding: var(--fd-space-2xs) var(--fd-space-md);
600
+ font-size: var(--fd-text-xs);
601
+ font-weight: 500;
602
+ font-family: inherit;
603
+ color: var(--fd-muted-foreground);
604
+ background-color: transparent;
605
+ border: 1px solid var(--fd-border);
606
+ border-radius: var(--fd-radius-md);
607
+ cursor: pointer;
608
+ transition: all var(--fd-transition-fast);
609
+ }
610
+
611
+ .interrupt-bubble__cancel-btn:hover:not(:disabled) {
612
+ color: var(--fd-error);
613
+ border-color: var(--fd-error);
614
+ background-color: var(--fd-error-muted);
615
+ }
616
+
617
+ .interrupt-bubble__cancel-btn:disabled {
618
+ opacity: 0.5;
619
+ cursor: not-allowed;
620
+ }
621
+
622
+ /* Responsive */
623
+ @media (max-width: 640px) {
624
+ .interrupt-bubble {
625
+ margin: var(--fd-space-xs);
626
+ }
627
+
628
+ .interrupt-bubble__header,
629
+ .interrupt-bubble__body,
630
+ .interrupt-bubble__footer {
631
+ padding-left: var(--fd-space-lg);
632
+ padding-right: var(--fd-space-lg);
633
+ }
634
+ }
601
635
  </style>