@flowdrop/flowdrop 1.4.0 → 1.6.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 (441) hide show
  1. package/README.md +94 -51
  2. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  3. package/dist/adapters/WorkflowAdapter.js +27 -47
  4. package/dist/adapters/agentspec/AgentSpecAdapter.d.ts +2 -2
  5. package/dist/adapters/agentspec/AgentSpecAdapter.js +122 -133
  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 +52 -6
  9. package/dist/adapters/agentspec/autoLayout.js +118 -23
  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 +20 -22
  18. package/dist/api/enhanced-client.d.ts +3 -3
  19. package/dist/api/enhanced-client.js +72 -73
  20. package/dist/chat/commandClassifier.d.ts +19 -0
  21. package/dist/chat/commandClassifier.js +30 -0
  22. package/dist/chat/index.d.ts +27 -0
  23. package/dist/chat/index.js +32 -0
  24. package/dist/chat/responseParser.d.ts +21 -0
  25. package/dist/chat/responseParser.js +91 -0
  26. package/dist/commands/batch.d.ts +18 -0
  27. package/dist/commands/batch.js +54 -0
  28. package/dist/commands/executor.d.ts +37 -0
  29. package/dist/commands/executor.js +1133 -0
  30. package/dist/commands/index.d.ts +14 -0
  31. package/dist/commands/index.js +17 -0
  32. package/dist/commands/parser.d.ts +16 -0
  33. package/dist/commands/parser.js +295 -0
  34. package/dist/commands/positioner.d.ts +19 -0
  35. package/dist/commands/positioner.js +33 -0
  36. package/dist/commands/storeIntegration.svelte.d.ts +16 -0
  37. package/dist/commands/storeIntegration.svelte.js +67 -0
  38. package/dist/commands/types.d.ts +343 -0
  39. package/dist/commands/types.js +45 -0
  40. package/dist/components/App.svelte +522 -237
  41. package/dist/components/App.svelte.d.ts +11 -8
  42. package/dist/components/CanvasBanner.stories.svelte +10 -16
  43. package/dist/components/CanvasBanner.stories.svelte.d.ts +1 -1
  44. package/dist/components/CanvasBanner.svelte +2 -2
  45. package/dist/components/CanvasBanner.svelte.d.ts +1 -1
  46. package/dist/components/CanvasController.svelte +37 -0
  47. package/dist/components/CanvasController.svelte.d.ts +32 -0
  48. package/dist/components/ConfigForm.svelte +118 -256
  49. package/dist/components/ConfigForm.svelte.d.ts +2 -2
  50. package/dist/components/ConfigMappingRow.svelte +128 -0
  51. package/dist/components/ConfigMappingRow.svelte.d.ts +8 -0
  52. package/dist/components/ConfigModal.svelte +3 -3
  53. package/dist/components/ConfigModal.svelte.d.ts +1 -1
  54. package/dist/components/ConfigPanel.stories.svelte +19 -19
  55. package/dist/components/ConfigPanel.stories.svelte.d.ts +1 -1
  56. package/dist/components/ConfigPanel.svelte +57 -19
  57. package/dist/components/ConfigPanel.svelte.d.ts +3 -1
  58. package/dist/components/ConnectionLine.svelte +4 -4
  59. package/dist/components/EdgeRefresher.svelte +1 -1
  60. package/dist/components/FlowDropEdge.stories.svelte +110 -110
  61. package/dist/components/FlowDropEdge.svelte +11 -19
  62. package/dist/components/FlowDropEdge.svelte.d.ts +1 -1
  63. package/dist/components/FlowDropZone.svelte +6 -9
  64. package/dist/components/FlowDropZone.svelte.d.ts +1 -1
  65. package/dist/components/LoadingSpinner.stories.svelte +13 -13
  66. package/dist/components/LoadingSpinner.stories.svelte.d.ts +1 -1
  67. package/dist/components/LoadingSpinner.svelte +3 -3
  68. package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
  69. package/dist/components/Logo.stories.svelte +4 -4
  70. package/dist/components/Logo.stories.svelte.d.ts +1 -1
  71. package/dist/components/Logo.svelte +3 -9
  72. package/dist/components/LogsSidebar.svelte +46 -53
  73. package/dist/components/LogsSidebar.svelte.d.ts +1 -1
  74. package/dist/components/MarkdownDisplay.stories.svelte +10 -14
  75. package/dist/components/MarkdownDisplay.stories.svelte.d.ts +1 -1
  76. package/dist/components/MarkdownDisplay.svelte +4 -6
  77. package/dist/components/Navbar.stories.svelte +19 -19
  78. package/dist/components/Navbar.stories.svelte.d.ts +1 -1
  79. package/dist/components/Navbar.svelte +28 -49
  80. package/dist/components/Navbar.svelte.d.ts +2 -2
  81. package/dist/components/NodeSidebar.svelte +55 -135
  82. package/dist/components/NodeSidebar.svelte.d.ts +1 -1
  83. package/dist/components/NodeStatusOverlay.stories.svelte +19 -31
  84. package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +1 -1
  85. package/dist/components/NodeStatusOverlay.svelte +40 -55
  86. package/dist/components/NodeStatusOverlay.svelte.d.ts +3 -3
  87. package/dist/components/NodeSwapPicker.svelte +493 -0
  88. package/dist/components/NodeSwapPicker.svelte.d.ts +16 -0
  89. package/dist/components/PipelineStatus.svelte +63 -89
  90. package/dist/components/PipelineStatus.svelte.d.ts +4 -4
  91. package/dist/components/PortCoordinateTracker.svelte +5 -7
  92. package/dist/components/PortCoordinateTracker.svelte.d.ts +1 -1
  93. package/dist/components/PortMappingRow.svelte +205 -0
  94. package/dist/components/PortMappingRow.svelte.d.ts +12 -0
  95. package/dist/components/ReadOnlyDetails.svelte +1 -1
  96. package/dist/components/SchemaForm.stories.svelte +53 -53
  97. package/dist/components/SchemaForm.stories.svelte.d.ts +1 -1
  98. package/dist/components/SchemaForm.svelte +24 -51
  99. package/dist/components/SchemaForm.svelte.d.ts +2 -2
  100. package/dist/components/SettingsModal.svelte +6 -9
  101. package/dist/components/SettingsModal.svelte.d.ts +1 -1
  102. package/dist/components/SettingsPanel.svelte +138 -158
  103. package/dist/components/SettingsPanel.svelte.d.ts +1 -1
  104. package/dist/components/StatusIcon.stories.svelte +16 -29
  105. package/dist/components/StatusIcon.stories.svelte.d.ts +1 -1
  106. package/dist/components/StatusIcon.svelte +19 -19
  107. package/dist/components/StatusIcon.svelte.d.ts +2 -2
  108. package/dist/components/StatusLabel.stories.svelte +8 -8
  109. package/dist/components/StatusLabel.stories.svelte.d.ts +1 -1
  110. package/dist/components/SwapMappingEditor.svelte +529 -0
  111. package/dist/components/SwapMappingEditor.svelte.d.ts +12 -0
  112. package/dist/components/ThemeToggle.stories.svelte +10 -10
  113. package/dist/components/ThemeToggle.stories.svelte.d.ts +1 -1
  114. package/dist/components/ThemeToggle.svelte +22 -33
  115. package/dist/components/ThemeToggle.svelte.d.ts +1 -1
  116. package/dist/components/UniversalNode.svelte +29 -41
  117. package/dist/components/UniversalNode.svelte.d.ts +3 -3
  118. package/dist/components/WorkflowEditor.svelte +210 -170
  119. package/dist/components/WorkflowEditor.svelte.d.ts +12 -4
  120. package/dist/components/chat/AIChatPanel.svelte +797 -0
  121. package/dist/components/chat/AIChatPanel.svelte.d.ts +13 -0
  122. package/dist/components/chat/CommandPreview.svelte +234 -0
  123. package/dist/components/chat/CommandPreview.svelte.d.ts +9 -0
  124. package/dist/components/console/CommandConsole.stories.svelte +111 -0
  125. package/dist/components/console/CommandConsole.stories.svelte.d.ts +27 -0
  126. package/dist/components/console/CommandConsole.svelte +263 -0
  127. package/dist/components/console/CommandConsole.svelte.d.ts +11 -0
  128. package/dist/components/console/ConsoleAutocomplete.svelte +142 -0
  129. package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +21 -0
  130. package/dist/components/console/ConsoleInput.svelte +771 -0
  131. package/dist/components/console/ConsoleInput.svelte.d.ts +16 -0
  132. package/dist/components/console/ConsoleOutput.svelte +116 -0
  133. package/dist/components/console/ConsoleOutput.svelte.d.ts +11 -0
  134. package/dist/components/console/formatters.d.ts +26 -0
  135. package/dist/components/console/formatters.js +116 -0
  136. package/dist/components/form/FormArray.svelte +75 -132
  137. package/dist/components/form/FormArray.svelte.d.ts +1 -1
  138. package/dist/components/form/FormAutocomplete.svelte +65 -108
  139. package/dist/components/form/FormAutocomplete.svelte.d.ts +1 -1
  140. package/dist/components/form/FormCheckboxGroup.stories.svelte +13 -16
  141. package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +1 -1
  142. package/dist/components/form/FormCheckboxGroup.svelte +2 -2
  143. package/dist/components/form/FormCodeEditor.svelte +42 -56
  144. package/dist/components/form/FormField.svelte +79 -90
  145. package/dist/components/form/FormField.svelte.d.ts +2 -2
  146. package/dist/components/form/FormFieldLight.svelte +72 -88
  147. package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
  148. package/dist/components/form/FormFieldWrapper.stories.svelte +14 -14
  149. package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +1 -1
  150. package/dist/components/form/FormFieldWrapper.svelte +2 -9
  151. package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
  152. package/dist/components/form/FormFieldset.svelte +3 -3
  153. package/dist/components/form/FormFieldset.svelte.d.ts +2 -2
  154. package/dist/components/form/FormMarkdownEditor.svelte +123 -156
  155. package/dist/components/form/FormNumberField.stories.svelte +18 -18
  156. package/dist/components/form/FormNumberField.stories.svelte.d.ts +1 -1
  157. package/dist/components/form/FormNumberField.svelte +6 -6
  158. package/dist/components/form/FormRangeField.stories.svelte +13 -13
  159. package/dist/components/form/FormRangeField.stories.svelte.d.ts +1 -1
  160. package/dist/components/form/FormRangeField.svelte +4 -12
  161. package/dist/components/form/FormSelect.stories.svelte +21 -21
  162. package/dist/components/form/FormSelect.stories.svelte.d.ts +1 -1
  163. package/dist/components/form/FormSelect.svelte +5 -5
  164. package/dist/components/form/FormSelect.svelte.d.ts +1 -1
  165. package/dist/components/form/FormTemplateEditor.svelte +126 -175
  166. package/dist/components/form/FormTemplateEditor.svelte.d.ts +1 -1
  167. package/dist/components/form/FormTextField.stories.svelte +17 -23
  168. package/dist/components/form/FormTextField.stories.svelte.d.ts +1 -1
  169. package/dist/components/form/FormTextField.svelte +4 -4
  170. package/dist/components/form/FormTextarea.stories.svelte +18 -21
  171. package/dist/components/form/FormTextarea.stories.svelte.d.ts +1 -1
  172. package/dist/components/form/FormTextarea.svelte +4 -4
  173. package/dist/components/form/FormToggle.stories.svelte +13 -16
  174. package/dist/components/form/FormToggle.stories.svelte.d.ts +1 -1
  175. package/dist/components/form/FormToggle.svelte +3 -3
  176. package/dist/components/form/FormUISchemaRenderer.svelte +12 -19
  177. package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +3 -3
  178. package/dist/components/form/index.d.ts +19 -19
  179. package/dist/components/form/index.js +18 -18
  180. package/dist/components/form/templateAutocomplete.d.ts +2 -2
  181. package/dist/components/form/templateAutocomplete.js +55 -64
  182. package/dist/components/form/types.d.ts +6 -6
  183. package/dist/components/form/types.js +4 -9
  184. package/dist/components/icons/AlertCircleIcon.svelte +1 -6
  185. package/dist/components/icons/CogIcon.svelte +1 -6
  186. package/dist/components/interrupt/ChoicePrompt.stories.svelte +27 -27
  187. package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +1 -1
  188. package/dist/components/interrupt/ChoicePrompt.svelte +17 -41
  189. package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +1 -1
  190. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +17 -17
  191. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +1 -1
  192. package/dist/components/interrupt/ConfirmationPrompt.svelte +10 -16
  193. package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +1 -1
  194. package/dist/components/interrupt/FormPrompt.svelte +10 -15
  195. package/dist/components/interrupt/FormPrompt.svelte.d.ts +1 -1
  196. package/dist/components/interrupt/InterruptBubble.svelte +87 -121
  197. package/dist/components/interrupt/InterruptBubble.svelte.d.ts +2 -2
  198. package/dist/components/interrupt/ReviewPrompt.stories.svelte +37 -37
  199. package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +1 -1
  200. package/dist/components/interrupt/ReviewPrompt.svelte +55 -75
  201. package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +1 -1
  202. package/dist/components/interrupt/TextInputPrompt.stories.svelte +16 -17
  203. package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +1 -1
  204. package/dist/components/interrupt/TextInputPrompt.svelte +13 -18
  205. package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +1 -1
  206. package/dist/components/interrupt/index.d.ts +6 -5
  207. package/dist/components/interrupt/index.js +6 -5
  208. package/dist/components/layouts/MainLayout.svelte +46 -84
  209. package/dist/components/layouts/MainLayout.svelte.d.ts +6 -6
  210. package/dist/components/nodes/GatewayNode.stories.svelte +64 -65
  211. package/dist/components/nodes/GatewayNode.svelte +37 -70
  212. package/dist/components/nodes/GatewayNode.svelte.d.ts +3 -3
  213. package/dist/components/nodes/IdeaNode.stories.svelte +25 -26
  214. package/dist/components/nodes/IdeaNode.svelte +22 -36
  215. package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
  216. package/dist/components/nodes/NotesNode.stories.svelte +37 -38
  217. package/dist/components/nodes/NotesNode.svelte +28 -39
  218. package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
  219. package/dist/components/nodes/SimpleNode.stories.svelte +137 -138
  220. package/dist/components/nodes/SimpleNode.svelte +44 -74
  221. package/dist/components/nodes/SimpleNode.svelte.d.ts +1 -1
  222. package/dist/components/nodes/SquareNode.stories.svelte +75 -75
  223. package/dist/components/nodes/SquareNode.svelte +42 -68
  224. package/dist/components/nodes/SquareNode.svelte.d.ts +1 -1
  225. package/dist/components/nodes/TerminalNode.stories.svelte +10 -10
  226. package/dist/components/nodes/TerminalNode.svelte +74 -112
  227. package/dist/components/nodes/TerminalNode.svelte.d.ts +1 -1
  228. package/dist/components/nodes/ToolNode.stories.svelte +115 -116
  229. package/dist/components/nodes/ToolNode.svelte +31 -64
  230. package/dist/components/nodes/ToolNode.svelte.d.ts +1 -1
  231. package/dist/components/nodes/WorkflowNode.stories.svelte +84 -89
  232. package/dist/components/nodes/WorkflowNode.svelte +50 -103
  233. package/dist/components/nodes/WorkflowNode.svelte.d.ts +3 -3
  234. package/dist/components/playground/ChatPanel.svelte +47 -103
  235. package/dist/components/playground/ExecutionLogs.svelte +45 -68
  236. package/dist/components/playground/InputCollector.svelte +32 -51
  237. package/dist/components/playground/MessageBubble.stories.svelte +25 -25
  238. package/dist/components/playground/MessageBubble.stories.svelte.d.ts +1 -1
  239. package/dist/components/playground/MessageBubble.svelte +54 -70
  240. package/dist/components/playground/MessageBubble.svelte.d.ts +1 -1
  241. package/dist/components/playground/Playground.svelte +60 -91
  242. package/dist/components/playground/Playground.svelte.d.ts +3 -3
  243. package/dist/components/playground/PlaygroundModal.svelte +8 -12
  244. package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
  245. package/dist/components/playground/SessionManager.svelte +34 -40
  246. package/dist/components/playground/SessionManager.svelte.d.ts +1 -1
  247. package/dist/config/agentSpecEndpoints.d.ts +1 -1
  248. package/dist/config/agentSpecEndpoints.js +20 -20
  249. package/dist/config/constants.js +2 -2
  250. package/dist/config/defaultCategories.d.ts +1 -1
  251. package/dist/config/defaultCategories.js +86 -86
  252. package/dist/config/defaultPortConfig.d.ts +1 -1
  253. package/dist/config/defaultPortConfig.js +144 -144
  254. package/dist/config/endpoints.d.ts +12 -4
  255. package/dist/config/endpoints.js +70 -65
  256. package/dist/config/runtimeConfig.d.ts +2 -2
  257. package/dist/config/runtimeConfig.js +8 -8
  258. package/dist/core/index.d.ts +68 -63
  259. package/dist/core/index.js +44 -35
  260. package/dist/display/index.d.ts +2 -2
  261. package/dist/display/index.js +2 -2
  262. package/dist/editor/index.d.ts +64 -62
  263. package/dist/editor/index.js +57 -55
  264. package/dist/form/code.d.ts +5 -5
  265. package/dist/form/code.js +14 -14
  266. package/dist/form/fieldRegistry.d.ts +3 -3
  267. package/dist/form/fieldRegistry.js +9 -11
  268. package/dist/form/full.d.ts +8 -8
  269. package/dist/form/full.js +9 -9
  270. package/dist/form/index.d.ts +18 -18
  271. package/dist/form/index.js +16 -16
  272. package/dist/form/markdown.d.ts +4 -4
  273. package/dist/form/markdown.js +8 -8
  274. package/dist/helpers/proximityConnect.d.ts +3 -3
  275. package/dist/helpers/proximityConnect.js +40 -35
  276. package/dist/helpers/workflowEditorHelper.d.ts +8 -58
  277. package/dist/helpers/workflowEditorHelper.js +73 -292
  278. package/dist/index.d.ts +6 -6
  279. package/dist/index.js +6 -6
  280. package/dist/mocks/app-environment.js +2 -2
  281. package/dist/mocks/app-forms.js +1 -1
  282. package/dist/mocks/app-navigation.js +2 -2
  283. package/dist/mocks/app-stores.js +3 -3
  284. package/dist/playground/index.d.ts +19 -19
  285. package/dist/playground/index.js +16 -16
  286. package/dist/playground/mount.d.ts +3 -3
  287. package/dist/playground/mount.js +24 -24
  288. package/dist/registry/builtinFormats.js +13 -13
  289. package/dist/registry/builtinNodes.d.ts +2 -2
  290. package/dist/registry/builtinNodes.js +77 -77
  291. package/dist/registry/index.d.ts +4 -4
  292. package/dist/registry/index.js +4 -4
  293. package/dist/registry/nodeComponentRegistry.d.ts +8 -8
  294. package/dist/registry/nodeComponentRegistry.js +9 -11
  295. package/dist/registry/plugin.d.ts +2 -2
  296. package/dist/registry/plugin.js +11 -11
  297. package/dist/registry/workflowFormatRegistry.d.ts +3 -3
  298. package/dist/registry/workflowFormatRegistry.js +2 -2
  299. package/dist/schema/index.d.ts +1 -1
  300. package/dist/schema/index.js +2 -2
  301. package/dist/schemas/v1/workflow.schema.json +107 -22
  302. package/dist/services/agentSpecExecutionService.d.ts +3 -3
  303. package/dist/services/agentSpecExecutionService.js +55 -56
  304. package/dist/services/api.d.ts +2 -2
  305. package/dist/services/api.js +37 -37
  306. package/dist/services/apiVariableService.d.ts +1 -1
  307. package/dist/services/apiVariableService.js +34 -41
  308. package/dist/services/autoSaveService.js +8 -8
  309. package/dist/services/categoriesApi.d.ts +2 -2
  310. package/dist/services/categoriesApi.js +8 -8
  311. package/dist/services/chatService.d.ts +65 -0
  312. package/dist/services/chatService.js +131 -0
  313. package/dist/services/draftStorage.d.ts +1 -1
  314. package/dist/services/draftStorage.js +11 -11
  315. package/dist/services/dynamicSchemaService.d.ts +1 -1
  316. package/dist/services/dynamicSchemaService.js +39 -41
  317. package/dist/services/globalSave.d.ts +2 -2
  318. package/dist/services/globalSave.js +38 -41
  319. package/dist/services/historyService.d.ts +7 -5
  320. package/dist/services/historyService.js +29 -14
  321. package/dist/services/interruptService.d.ts +1 -1
  322. package/dist/services/interruptService.js +29 -35
  323. package/dist/services/nodeExecutionService.d.ts +1 -1
  324. package/dist/services/nodeExecutionService.js +44 -45
  325. package/dist/services/playgroundService.d.ts +1 -1
  326. package/dist/services/playgroundService.js +29 -29
  327. package/dist/services/portConfigApi.d.ts +2 -2
  328. package/dist/services/portConfigApi.js +8 -8
  329. package/dist/services/settingsService.d.ts +2 -2
  330. package/dist/services/settingsService.js +19 -25
  331. package/dist/services/toastService.d.ts +4 -4
  332. package/dist/services/toastService.js +33 -33
  333. package/dist/services/variableService.d.ts +1 -1
  334. package/dist/services/variableService.js +36 -36
  335. package/dist/services/workflowStorage.d.ts +2 -2
  336. package/dist/services/workflowStorage.js +13 -13
  337. package/dist/settings/index.d.ts +7 -7
  338. package/dist/settings/index.js +6 -6
  339. package/dist/skins/default.d.ts +1 -1
  340. package/dist/skins/default.js +1 -1
  341. package/dist/skins/index.d.ts +3 -3
  342. package/dist/skins/index.js +7 -7
  343. package/dist/skins/slate.d.ts +1 -1
  344. package/dist/skins/slate.js +69 -69
  345. package/dist/stores/categoriesStore.svelte.d.ts +1 -1
  346. package/dist/stores/categoriesStore.svelte.js +5 -5
  347. package/dist/stores/editorStateMachine.svelte.d.ts +2 -2
  348. package/dist/stores/editorStateMachine.svelte.js +34 -34
  349. package/dist/stores/historyStore.svelte.d.ts +4 -4
  350. package/dist/stores/historyStore.svelte.js +4 -4
  351. package/dist/stores/interruptStore.svelte.d.ts +3 -3
  352. package/dist/stores/interruptStore.svelte.js +27 -22
  353. package/dist/stores/playgroundStore.svelte.d.ts +3 -3
  354. package/dist/stores/playgroundStore.svelte.js +29 -23
  355. package/dist/stores/portCoordinateStore.svelte.d.ts +6 -2
  356. package/dist/stores/portCoordinateStore.svelte.js +30 -39
  357. package/dist/stores/settingsStore.svelte.d.ts +2 -2
  358. package/dist/stores/settingsStore.svelte.js +57 -62
  359. package/dist/stores/workflowStore.svelte.d.ts +34 -5
  360. package/dist/stores/workflowStore.svelte.js +127 -108
  361. package/dist/stories/CanvasDecorator.svelte +7 -10
  362. package/dist/stories/CanvasDecorator.svelte.d.ts +2 -2
  363. package/dist/stories/EdgeDecorator.svelte +28 -31
  364. package/dist/stories/EdgeDecorator.svelte.d.ts +1 -1
  365. package/dist/stories/NodeDecorator.svelte +14 -20
  366. package/dist/stories/NodeDecorator.svelte.d.ts +1 -1
  367. package/dist/stories/utils.d.ts +2 -2
  368. package/dist/stories/utils.js +89 -93
  369. package/dist/styles/base.css +16 -50
  370. package/dist/styles/tokens.css +10 -28
  371. package/dist/svelte-app.d.ts +10 -10
  372. package/dist/svelte-app.js +39 -39
  373. package/dist/themes/default.d.ts +1 -1
  374. package/dist/themes/default.js +4 -4
  375. package/dist/themes/index.d.ts +3 -3
  376. package/dist/themes/index.js +11 -11
  377. package/dist/themes/minimal.d.ts +1 -1
  378. package/dist/themes/minimal.js +5 -5
  379. package/dist/types/agentspec.d.ts +18 -18
  380. package/dist/types/agentspec.js +2 -2
  381. package/dist/types/auth.d.ts +1 -1
  382. package/dist/types/auth.js +6 -6
  383. package/dist/types/chat.d.ts +63 -0
  384. package/dist/types/chat.js +9 -0
  385. package/dist/types/config.d.ts +6 -6
  386. package/dist/types/events.d.ts +28 -2
  387. package/dist/types/events.js +2 -1
  388. package/dist/types/index.d.ts +40 -32
  389. package/dist/types/index.js +6 -6
  390. package/dist/types/interrupt.d.ts +6 -6
  391. package/dist/types/interrupt.js +21 -21
  392. package/dist/types/interruptState.d.ts +12 -12
  393. package/dist/types/interruptState.js +66 -66
  394. package/dist/types/playground.d.ts +7 -7
  395. package/dist/types/playground.js +14 -14
  396. package/dist/types/settings.d.ts +12 -4
  397. package/dist/types/settings.js +21 -23
  398. package/dist/types/skin.d.ts +1 -1
  399. package/dist/types/theme.d.ts +2 -2
  400. package/dist/types/uischema.d.ts +4 -4
  401. package/dist/types/uischema.js +3 -3
  402. package/dist/utils/colors.d.ts +1 -1
  403. package/dist/utils/colors.js +95 -97
  404. package/dist/utils/config.d.ts +2 -2
  405. package/dist/utils/config.js +48 -48
  406. package/dist/utils/connections.d.ts +2 -2
  407. package/dist/utils/connections.js +15 -15
  408. package/dist/utils/edgeStyling.d.ts +42 -0
  409. package/dist/utils/edgeStyling.js +173 -0
  410. package/dist/utils/errors.js +3 -3
  411. package/dist/utils/fetchWithAuth.d.ts +1 -1
  412. package/dist/utils/fetchWithAuth.js +2 -2
  413. package/dist/utils/handleIds.d.ts +2 -2
  414. package/dist/utils/handleIds.js +8 -8
  415. package/dist/utils/handlePositioning.d.ts +1 -1
  416. package/dist/utils/handlePositioning.js +2 -2
  417. package/dist/utils/icons.d.ts +1 -1
  418. package/dist/utils/icons.js +74 -74
  419. package/dist/utils/logger.d.ts +1 -1
  420. package/dist/utils/logger.js +7 -7
  421. package/dist/utils/nodeIds.d.ts +31 -0
  422. package/dist/utils/nodeIds.js +42 -0
  423. package/dist/utils/nodeStatus.d.ts +1 -1
  424. package/dist/utils/nodeStatus.js +48 -48
  425. package/dist/utils/nodeSwap.d.ts +221 -0
  426. package/dist/utils/nodeSwap.js +680 -0
  427. package/dist/utils/nodeTypes.d.ts +1 -1
  428. package/dist/utils/nodeTypes.js +20 -21
  429. package/dist/utils/nodeWrapper.d.ts +7 -7
  430. package/dist/utils/nodeWrapper.js +19 -21
  431. package/dist/utils/performanceUtils.d.ts +1 -1
  432. package/dist/utils/performanceUtils.js +1 -2
  433. package/dist/utils/portUtils.d.ts +2 -2
  434. package/dist/utils/portUtils.js +1 -1
  435. package/dist/utils/sanitize.js +1 -1
  436. package/dist/utils/uischema.d.ts +2 -2
  437. package/dist/utils/uischema.js +8 -8
  438. package/dist/utils/validation.js +8 -8
  439. package/package.json +12 -11
  440. package/dist/helpers/nodeLayoutHelper.d.ts +0 -14
  441. package/dist/helpers/nodeLayoutHelper.js +0 -19
@@ -0,0 +1,771 @@
1
+ <!--
2
+ ConsoleInput Component
3
+ Single-line command input with prompt prefix, Enter-to-submit, Escape-to-close
4
+ Includes autocomplete for command verbs and node type IDs
5
+ Styled with BEM syntax matching CommandConsole pattern
6
+ -->
7
+
8
+ <script lang="ts">
9
+ import type { NodeMetadata } from '../../types/index.js';
10
+ import { getWorkflowStore } from '../../stores/workflowStore.svelte.js';
11
+ import { toShortId, resolveNode } from '../../commands/index.js';
12
+ import ConsoleAutocomplete, { type Suggestion } from './ConsoleAutocomplete.svelte';
13
+
14
+ interface Props {
15
+ /** Whether the console is currently visible/open */
16
+ open: boolean;
17
+ /** Available node types for autocomplete suggestions */
18
+ nodeTypes?: NodeMetadata[];
19
+ /** Called when user submits a command (Enter key) */
20
+ onSubmit: (value: string) => void;
21
+ /** Called when user pastes multiple lines */
22
+ onBatchSubmit?: (lines: string[]) => void;
23
+ /** Called when user presses Escape to close the console */
24
+ onClose: () => void;
25
+ }
26
+
27
+ let { open, nodeTypes = [], onSubmit, onBatchSubmit, onClose }: Props = $props();
28
+
29
+ let inputValue = $state('');
30
+ let inputElement: HTMLInputElement | undefined = $state();
31
+
32
+ // Multiline value entry state
33
+ let multilineMode = $state(false);
34
+ let multilinePrefix = $state(''); // e.g. "set node1:prompt"
35
+ let textareaValue = $state('');
36
+ let textareaElement: HTMLTextAreaElement | undefined = $state();
37
+
38
+ // Command history state
39
+ const MAX_HISTORY = 100;
40
+ let history: string[] = $state([]);
41
+ let historyIndex = $state(-1);
42
+ let savedInput = $state('');
43
+
44
+ // Autocomplete state
45
+ let acVisible = $state(false);
46
+ let acSelectedIndex = $state(0);
47
+ let acSuggestions: Suggestion[] = $state([]);
48
+
49
+ const COMMAND_VERBS = [
50
+ 'add',
51
+ 'delete',
52
+ 'rename',
53
+ 'set',
54
+ 'get',
55
+ 'info',
56
+ 'config',
57
+ 'select',
58
+ 'connect',
59
+ 'disconnect',
60
+ 'list',
61
+ 'undo',
62
+ 'redo',
63
+ 'help',
64
+ 'clear',
65
+ 'cls',
66
+ 'swap',
67
+ 'move',
68
+ 'layout',
69
+ 'canvas'
70
+ ];
71
+
72
+ /** Verbs that take a nodeId as their first argument */
73
+ const NODE_ID_VERBS = [
74
+ 'delete',
75
+ 'rename',
76
+ 'info',
77
+ 'config',
78
+ 'select',
79
+ 'set',
80
+ 'get',
81
+ 'disconnect',
82
+ 'swap',
83
+ 'move'
84
+ ];
85
+
86
+ $effect(() => {
87
+ if (open && inputElement) {
88
+ inputElement.focus();
89
+ }
90
+ });
91
+
92
+ /**
93
+ * Get node suggestions from the live workflow store.
94
+ * Returns suggestions with short IDs and labels.
95
+ */
96
+ function getWorkflowNodeSuggestions(prefix: string): Suggestion[] {
97
+ const workflow = getWorkflowStore();
98
+ if (!workflow) return [];
99
+
100
+ const lowerPrefix = prefix.toLowerCase();
101
+ return workflow.nodes
102
+ .map((node) => {
103
+ const shortId = toShortId(node.id);
104
+ return {
105
+ value: shortId,
106
+ label: shortId,
107
+ detail: node.data.label
108
+ };
109
+ })
110
+ .filter((s) => s.value.toLowerCase().startsWith(lowerPrefix))
111
+ .slice(0, 50);
112
+ }
113
+
114
+ /**
115
+ * Detect if cursor is at a position expecting a node ID.
116
+ * Returns the partial text typed so far, or null if not at a nodeId position.
117
+ */
118
+ function getNodeIdContext(value: string): {
119
+ partial: string;
120
+ type: 'nodeId' | 'connectSource' | 'connectTarget';
121
+ } | null {
122
+ // "connect <source> to <partial>" — target node ID
123
+ const connectToMatch = value.match(/^connect\s+\S+\s+to\s+(.*)$/i);
124
+ if (connectToMatch) return { partial: connectToMatch[1], type: 'connectTarget' };
125
+
126
+ // "connect <partial>" — source node ID (only if no "to" keyword yet)
127
+ const connectMatch = value.match(/^connect\s+(?!.*\bto\b)(.*)$/i);
128
+ if (connectMatch) return { partial: connectMatch[1], type: 'connectSource' };
129
+
130
+ // Verbs that take nodeId as first arg: "verb <partial>"
131
+ for (const verb of NODE_ID_VERBS) {
132
+ const regex = new RegExp(`^${verb}\\s+(.*)$`, 'i');
133
+ const match = value.match(regex);
134
+ if (match) {
135
+ // Only suggest if the partial doesn't already contain a space
136
+ // (user has moved past the nodeId arg to further args)
137
+ const partial = match[1];
138
+ if (!partial.includes(' ') && !partial.includes(':')) {
139
+ return { partial, type: 'nodeId' };
140
+ }
141
+ return null;
142
+ }
143
+ }
144
+
145
+ return null;
146
+ }
147
+
148
+ /**
149
+ * Detect if cursor is after a "<nodeId>:" pattern, indicating port or config key position.
150
+ * Returns the nodeId, partial text after colon, and context type.
151
+ */
152
+ function getPortOrConfigContext(value: string): {
153
+ nodeId: string;
154
+ partial: string;
155
+ type: 'outputPort' | 'inputPort' | 'configKey' | 'port';
156
+ } | null {
157
+ // "connect <nodeId>:<partial>" — output ports (source position, no "to" yet)
158
+ const connectSourcePort = value.match(/^connect\s+(\S+?):(\S*)$/i);
159
+ if (connectSourcePort && !/\bto\b/i.test(value)) {
160
+ return {
161
+ nodeId: connectSourcePort[1],
162
+ partial: connectSourcePort[2],
163
+ type: 'outputPort'
164
+ };
165
+ }
166
+
167
+ // "connect <source> to <nodeId>:<partial>" — input ports (target position)
168
+ const connectTargetPort = value.match(/^connect\s+\S+\s+to\s+(\S+?):(\S*)$/i);
169
+ if (connectTargetPort) {
170
+ return {
171
+ nodeId: connectTargetPort[1],
172
+ partial: connectTargetPort[2],
173
+ type: 'inputPort'
174
+ };
175
+ }
176
+
177
+ // "set <nodeId>:<partial>" — config keys
178
+ const setMatch = value.match(/^set\s+(\S+?):(\S*)$/i);
179
+ if (setMatch) {
180
+ return { nodeId: setMatch[1], partial: setMatch[2], type: 'configKey' };
181
+ }
182
+
183
+ // "get <nodeId>:<partial>" — config keys
184
+ const getMatch = value.match(/^get\s+(\S+?):(\S*)$/i);
185
+ if (getMatch) {
186
+ return { nodeId: getMatch[1], partial: getMatch[2], type: 'configKey' };
187
+ }
188
+
189
+ // "disconnect <nodeId>:<partial>" — all ports
190
+ const disconnectMatch = value.match(/^disconnect\s+(\S+?):(\S*)$/i);
191
+ if (disconnectMatch) {
192
+ return {
193
+ nodeId: disconnectMatch[1],
194
+ partial: disconnectMatch[2],
195
+ type: 'port'
196
+ };
197
+ }
198
+
199
+ return null;
200
+ }
201
+
202
+ /**
203
+ * Get port suggestions for a resolved node, filtered by direction and prefix.
204
+ */
205
+ function getPortSuggestions(
206
+ nodeId: string,
207
+ partial: string,
208
+ filter: 'input' | 'output' | 'all'
209
+ ): Suggestion[] {
210
+ const workflow = getWorkflowStore();
211
+ if (!workflow) return [];
212
+
213
+ const node = resolveNode(nodeId, workflow.nodes);
214
+ if (!node) return [];
215
+
216
+ const metadata = node.data.metadata;
217
+ if (!metadata) return [];
218
+
219
+ const lowerPartial = partial.toLowerCase();
220
+ const ports = [
221
+ ...(filter === 'input' || filter === 'all' ? metadata.inputs : []),
222
+ ...(filter === 'output' || filter === 'all' ? metadata.outputs : [])
223
+ ];
224
+
225
+ const staticSuggestions = ports
226
+ .filter((p) => p.id.toLowerCase().startsWith(lowerPartial))
227
+ .map((p) => ({
228
+ value: p.id,
229
+ label: p.id,
230
+ detail: `${p.name} (${p.dataType})`
231
+ }));
232
+
233
+ // Gateway nodes (e.g. if_else) have dynamic branch outputs stored in config, not metadata
234
+ const branchSuggestions: Suggestion[] = [];
235
+ if ((filter === 'output' || filter === 'all') && metadata.type === 'gateway') {
236
+ const branches = node.data.config?.branches as
237
+ | Array<{ name: string; label?: string }>
238
+ | undefined;
239
+ if (branches) {
240
+ for (const branch of branches) {
241
+ if (branch.name.toLowerCase().startsWith(lowerPartial)) {
242
+ branchSuggestions.push({
243
+ value: branch.name,
244
+ label: branch.name,
245
+ detail: branch.label ? `branch: ${branch.label}` : 'branch'
246
+ });
247
+ }
248
+ }
249
+ }
250
+ }
251
+
252
+ return [...staticSuggestions, ...branchSuggestions].slice(0, 50);
253
+ }
254
+
255
+ /**
256
+ * Get config key suggestions for a resolved node, filtered by prefix.
257
+ */
258
+ function getConfigKeySuggestions(nodeId: string, partial: string): Suggestion[] {
259
+ const workflow = getWorkflowStore();
260
+ if (!workflow) return [];
261
+
262
+ const node = resolveNode(nodeId, workflow.nodes);
263
+ if (!node) return [];
264
+
265
+ const metadata = node.data.metadata;
266
+ if (!metadata?.configSchema?.properties) return [];
267
+
268
+ const lowerPartial = partial.toLowerCase();
269
+ return Object.entries(metadata.configSchema.properties)
270
+ .filter(([key]) => key.toLowerCase().startsWith(lowerPartial))
271
+ .map(([key, prop]) => ({
272
+ value: key,
273
+ label: key,
274
+ detail: typeof prop === 'object' && 'type' in prop ? String(prop.type) : undefined
275
+ }))
276
+ .slice(0, 50);
277
+ }
278
+
279
+ /** Sub-commands for verbs that have them */
280
+ const SUBCOMMAND_MAP: Record<string, Array<{ value: string; detail?: string }>> = {
281
+ layout: [
282
+ { value: 'auto', detail: 'Re-arrange all nodes from scratch' },
283
+ { value: 'beautify', detail: 'Normalize spacing, preserve arrangement' }
284
+ ],
285
+ list: [
286
+ { value: 'nodes', detail: 'List all workflow nodes' },
287
+ { value: 'edges', detail: 'List all connections' },
288
+ { value: 'types', detail: 'List available node types' }
289
+ ],
290
+ canvas: [
291
+ { value: 'fitview', detail: 'Fit all nodes into the viewport' },
292
+ { value: 'zoom in', detail: 'Zoom in on the canvas' },
293
+ { value: 'zoom out', detail: 'Zoom out on the canvas' },
294
+ { value: 'zoom', detail: 'Set zoom level (e.g. canvas zoom 1.5)' },
295
+ { value: 'pan', detail: 'Pan to position (e.g. canvas pan 100,200)' },
296
+ { value: 'reset', detail: 'Reset viewport to default' }
297
+ ]
298
+ };
299
+
300
+ function computeSuggestions(value: string): Suggestion[] {
301
+ if (!value) return [];
302
+
303
+ // Check if we're after "<nodeId>:" — port names or config keys
304
+ const portConfigCtx = getPortOrConfigContext(value);
305
+ if (portConfigCtx !== null) {
306
+ if (portConfigCtx.type === 'configKey') {
307
+ return getConfigKeySuggestions(portConfigCtx.nodeId, portConfigCtx.partial);
308
+ }
309
+ const filter =
310
+ portConfigCtx.type === 'outputPort'
311
+ ? 'output'
312
+ : portConfigCtx.type === 'inputPort'
313
+ ? 'input'
314
+ : 'all';
315
+ return getPortSuggestions(portConfigCtx.nodeId, portConfigCtx.partial, filter);
316
+ }
317
+
318
+ // Check if we're at a sub-command position (e.g. "layout <partial>")
319
+ const subCmdContext = getSubcommandContext(value);
320
+ if (subCmdContext !== null) {
321
+ const prefix = subCmdContext.partial.toLowerCase();
322
+ return subCmdContext.options
323
+ .filter((opt) => opt.value.toLowerCase().startsWith(prefix))
324
+ .map((opt) => ({
325
+ value: opt.value,
326
+ label: opt.value,
327
+ detail: opt.detail
328
+ }));
329
+ }
330
+
331
+ // Check if we're in a position where node type IDs should be suggested
332
+ const nodeTypeContext = getNodeTypeContext(value);
333
+ if (nodeTypeContext !== null) {
334
+ const prefix = nodeTypeContext.toLowerCase();
335
+ return nodeTypes
336
+ .filter((nt) => nt.id.toLowerCase().startsWith(prefix))
337
+ .map((nt) => ({
338
+ value: nt.id,
339
+ label: nt.id,
340
+ detail: `${nt.name} (${nt.category})`
341
+ }))
342
+ .slice(0, 50);
343
+ }
344
+
345
+ // Check if we're at a position expecting a node ID from the workflow
346
+ const nodeIdContext = getNodeIdContext(value);
347
+ if (nodeIdContext !== null) {
348
+ return getWorkflowNodeSuggestions(nodeIdContext.partial);
349
+ }
350
+
351
+ // Check if we're at verb position (no space in input yet)
352
+ if (!value.includes(' ')) {
353
+ const prefix = value.toLowerCase();
354
+ return COMMAND_VERBS.filter((v) => v.startsWith(prefix)).map((v) => ({
355
+ value: v,
356
+ label: v
357
+ }));
358
+ }
359
+
360
+ return [];
361
+ }
362
+
363
+ /**
364
+ * Detect if cursor is at a sub-command position (e.g. "layout <partial>").
365
+ * Returns the verb's sub-command options and the partial typed so far, or null.
366
+ */
367
+ function getSubcommandContext(value: string): {
368
+ partial: string;
369
+ options: Array<{ value: string; detail?: string }>;
370
+ } | null {
371
+ const match = value.match(/^(\w+)\s+(.*)$/i);
372
+ if (!match) return null;
373
+ const verb = match[1].toLowerCase();
374
+ const partial = match[2];
375
+ const options = SUBCOMMAND_MAP[verb];
376
+ if (!options) return null;
377
+ // Only suggest if the partial has no further spaces (still on sub-command)
378
+ if (partial.includes(' ')) return null;
379
+ return { partial, options };
380
+ }
381
+
382
+ /**
383
+ * Returns the partial text after "add " or "swap <nodeId> with " if at a
384
+ * node-type position, or null otherwise.
385
+ */
386
+ function getNodeTypeContext(value: string): string | null {
387
+ // "add <partial>"
388
+ const addMatch = value.match(/^add\s+(.*)$/i);
389
+ if (addMatch) return addMatch[1];
390
+
391
+ // "swap <nodeId> with <partial>"
392
+ const swapMatch = value.match(/^swap\s+\S+\s+with\s+(.*)$/i);
393
+ if (swapMatch) return swapMatch[1];
394
+
395
+ return null;
396
+ }
397
+
398
+ let debounceTimer: ReturnType<typeof setTimeout> | undefined;
399
+
400
+ function updateAutocomplete() {
401
+ clearTimeout(debounceTimer);
402
+ debounceTimer = setTimeout(() => {
403
+ const suggestions = computeSuggestions(inputValue);
404
+ acSuggestions = suggestions;
405
+ acSelectedIndex = 0;
406
+ acVisible = suggestions.length > 0;
407
+ }, 100);
408
+ }
409
+
410
+ function dismissAutocomplete() {
411
+ acVisible = false;
412
+ acSuggestions = [];
413
+ acSelectedIndex = 0;
414
+ }
415
+
416
+ function acceptSuggestion(suggestion: Suggestion) {
417
+ // Replace the relevant part of input with the suggestion value
418
+ const portConfigCtx = getPortOrConfigContext(inputValue);
419
+ if (portConfigCtx !== null) {
420
+ // Replace the partial after the colon
421
+ const prefixEnd = inputValue.length - portConfigCtx.partial.length;
422
+ inputValue = inputValue.slice(0, prefixEnd) + suggestion.value;
423
+ dismissAutocomplete();
424
+ inputElement?.focus();
425
+ return;
426
+ }
427
+
428
+ const subCmdContext = getSubcommandContext(inputValue);
429
+ if (subCmdContext !== null) {
430
+ // Replace the partial after the verb
431
+ const prefixEnd = inputValue.length - subCmdContext.partial.length;
432
+ inputValue = inputValue.slice(0, prefixEnd) + suggestion.value;
433
+ } else {
434
+ const nodeTypeContext = getNodeTypeContext(inputValue);
435
+ if (nodeTypeContext !== null) {
436
+ // Replace the partial after the command prefix (node type context)
437
+ const prefixEnd = inputValue.length - nodeTypeContext.length;
438
+ inputValue = inputValue.slice(0, prefixEnd) + suggestion.value;
439
+ } else {
440
+ const nodeIdContext = getNodeIdContext(inputValue);
441
+ if (nodeIdContext !== null) {
442
+ // Replace the partial after the command prefix (node ID context)
443
+ const prefixEnd = inputValue.length - nodeIdContext.partial.length;
444
+ inputValue = inputValue.slice(0, prefixEnd) + suggestion.value;
445
+ } else {
446
+ // Replace the whole input (verb position)
447
+ inputValue = suggestion.value;
448
+ }
449
+ }
450
+ }
451
+ dismissAutocomplete();
452
+ inputElement?.focus();
453
+ }
454
+
455
+ function addToHistory(command: string) {
456
+ // Don't store duplicate consecutive commands
457
+ if (history.length > 0 && history[history.length - 1] === command) {
458
+ return;
459
+ }
460
+ history.push(command);
461
+ // Drop oldest when full
462
+ if (history.length > MAX_HISTORY) {
463
+ history.shift();
464
+ }
465
+ }
466
+
467
+ /**
468
+ * Enter multiline textarea mode for the given set-command prefix.
469
+ * prefixText: e.g. "set node1:prompt", initialValue: partial value already typed
470
+ */
471
+ function enterMultilineMode(prefixText: string, initialValue: string) {
472
+ multilinePrefix = prefixText;
473
+ textareaValue = initialValue;
474
+ multilineMode = true;
475
+ inputValue = '';
476
+ dismissAutocomplete();
477
+ setTimeout(() => textareaElement?.focus(), 0);
478
+ }
479
+
480
+ function exitMultilineMode() {
481
+ multilineMode = false;
482
+ multilinePrefix = '';
483
+ textareaValue = '';
484
+ setTimeout(() => inputElement?.focus(), 0);
485
+ }
486
+
487
+ function submitMultilineValue() {
488
+ const value = textareaValue;
489
+ const prefix = multilinePrefix; // capture before exitMultilineMode clears it
490
+ exitMultilineMode();
491
+ if (!value.trim()) return;
492
+ const command = `${prefix} """\n${value}\n"""`;
493
+ addToHistory(command);
494
+ onSubmit(command);
495
+ }
496
+
497
+ function handleTextareaKeydown(event: KeyboardEvent) {
498
+ if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
499
+ event.preventDefault();
500
+ submitMultilineValue();
501
+ } else if (event.key === 'Escape') {
502
+ event.preventDefault();
503
+ exitMultilineMode();
504
+ }
505
+ }
506
+
507
+ function handlePaste(event: ClipboardEvent) {
508
+ const text = event.clipboardData?.getData('text/plain');
509
+ if (!text || !text.includes('\n')) return;
510
+
511
+ // If already typing a set command, treat multiline paste as the value
512
+ const setMatch = inputValue.match(/^(set\s+\S+?:\S+)\s*(.*)$/i);
513
+ if (setMatch) {
514
+ event.preventDefault();
515
+ enterMultilineMode(setMatch[1], (setMatch[2] ? setMatch[2] + '\n' : '') + text);
516
+ historyIndex = -1;
517
+ savedInput = '';
518
+ return;
519
+ }
520
+
521
+ // Multi-line paste: prevent default and batch-submit
522
+ event.preventDefault();
523
+ const lines = text
524
+ .split('\n')
525
+ .map((l) => l.trim())
526
+ .filter((l) => l.length > 0);
527
+ if (lines.length <= 1) return;
528
+
529
+ // Add each line to history
530
+ for (const line of lines) {
531
+ addToHistory(line);
532
+ }
533
+
534
+ if (onBatchSubmit) {
535
+ onBatchSubmit(lines);
536
+ }
537
+
538
+ inputValue = '';
539
+ historyIndex = -1;
540
+ savedInput = '';
541
+ dismissAutocomplete();
542
+ }
543
+
544
+ function handleKeydown(event: KeyboardEvent) {
545
+ // When autocomplete is visible, intercept navigation keys
546
+ if (acVisible && acSuggestions.length > 0) {
547
+ if (event.key === 'ArrowUp') {
548
+ event.preventDefault();
549
+ acSelectedIndex = acSelectedIndex > 0 ? acSelectedIndex - 1 : acSuggestions.length - 1;
550
+ return;
551
+ }
552
+ if (event.key === 'ArrowDown') {
553
+ event.preventDefault();
554
+ acSelectedIndex = acSelectedIndex < acSuggestions.length - 1 ? acSelectedIndex + 1 : 0;
555
+ return;
556
+ }
557
+ if (event.key === 'Tab') {
558
+ event.preventDefault();
559
+ acceptSuggestion(acSuggestions[acSelectedIndex]);
560
+ return;
561
+ }
562
+ if (event.key === 'Enter') {
563
+ const selected = acSuggestions[acSelectedIndex];
564
+ // If accepting the suggestion wouldn't change the input, execute directly
565
+ const before = inputValue;
566
+ acceptSuggestion(selected);
567
+ if (inputValue !== before) {
568
+ event.preventDefault();
569
+ return;
570
+ }
571
+ // Input unchanged — fall through to submit handler below
572
+ }
573
+ if (event.key === 'Escape') {
574
+ event.preventDefault();
575
+ dismissAutocomplete();
576
+ return;
577
+ }
578
+ }
579
+
580
+ if (event.key === 'Enter' && event.shiftKey) {
581
+ // Shift+Enter on a set command → expand to multiline textarea
582
+ const setMatch = inputValue.match(/^(set\s+\S+?:\S+)\s*(.*)$/i);
583
+ if (setMatch) {
584
+ event.preventDefault();
585
+ enterMultilineMode(setMatch[1], setMatch[2]);
586
+ return;
587
+ }
588
+ }
589
+
590
+ if (event.key === 'Enter' && !event.shiftKey) {
591
+ event.preventDefault();
592
+ const value = inputValue.trim();
593
+ if (value) {
594
+ addToHistory(value);
595
+ onSubmit(value);
596
+ inputValue = '';
597
+ historyIndex = -1;
598
+ savedInput = '';
599
+ dismissAutocomplete();
600
+ }
601
+ } else if (event.key === 'Escape') {
602
+ event.preventDefault();
603
+ onClose();
604
+ } else if (event.key === 'ArrowUp') {
605
+ event.preventDefault();
606
+ if (history.length === 0) return;
607
+ if (historyIndex === -1) {
608
+ // Save current input before navigating history
609
+ savedInput = inputValue;
610
+ historyIndex = history.length - 1;
611
+ } else if (historyIndex > 0) {
612
+ historyIndex--;
613
+ }
614
+ inputValue = history[historyIndex];
615
+ dismissAutocomplete();
616
+ } else if (event.key === 'ArrowDown') {
617
+ event.preventDefault();
618
+ if (historyIndex === -1) return;
619
+ if (historyIndex < history.length - 1) {
620
+ historyIndex++;
621
+ inputValue = history[historyIndex];
622
+ } else {
623
+ // Past newest entry — return to saved input
624
+ historyIndex = -1;
625
+ inputValue = savedInput;
626
+ }
627
+ dismissAutocomplete();
628
+ }
629
+ }
630
+
631
+ function handleInput() {
632
+ // Typing resets history navigation
633
+ historyIndex = -1;
634
+ updateAutocomplete();
635
+ }
636
+ </script>
637
+
638
+ <div class="console-input" class:console-input--multiline={multilineMode}>
639
+ <span class="console-input__prompt">&gt;</span>
640
+ <div class="console-input__wrapper">
641
+ {#if multilineMode}
642
+ <div class="console-input__multiline-header">
643
+ <span class="console-input__multiline-label">{multilinePrefix}</span>
644
+ <span class="console-input__multiline-hint">Ctrl+Enter to submit · Esc to cancel</span>
645
+ </div>
646
+ <textarea
647
+ bind:this={textareaElement}
648
+ bind:value={textareaValue}
649
+ class="console-input__textarea"
650
+ rows={5}
651
+ spellcheck={false}
652
+ onkeydown={handleTextareaKeydown}
653
+ ></textarea>
654
+ {:else}
655
+ <ConsoleAutocomplete
656
+ suggestions={acSuggestions}
657
+ visible={acVisible}
658
+ selectedIndex={acSelectedIndex}
659
+ onAccept={acceptSuggestion}
660
+ />
661
+ <input
662
+ bind:this={inputElement}
663
+ bind:value={inputValue}
664
+ class="console-input__field"
665
+ type="text"
666
+ placeholder="Type a command... (set node:key + Shift+Enter for multiline)"
667
+ spellcheck="false"
668
+ autocomplete="off"
669
+ role="combobox"
670
+ aria-expanded={acVisible}
671
+ aria-controls="console-autocomplete-listbox"
672
+ aria-activedescendant={acVisible && acSuggestions.length > 0
673
+ ? `console-autocomplete-option-${acSelectedIndex}`
674
+ : undefined}
675
+ onkeydown={handleKeydown}
676
+ oninput={handleInput}
677
+ onpaste={handlePaste}
678
+ onblur={() => dismissAutocomplete()}
679
+ />
680
+ {/if}
681
+ </div>
682
+ </div>
683
+
684
+ <style>
685
+ .console-input {
686
+ display: flex;
687
+ align-items: center;
688
+ padding: 0.5rem 1rem;
689
+ border-top: 1px solid var(--fd-border-muted);
690
+ background-color: var(--fd-background);
691
+ flex-shrink: 0;
692
+ }
693
+
694
+ .console-input__prompt {
695
+ font-family: monospace;
696
+ font-size: 0.875rem;
697
+ color: var(--fd-muted-foreground);
698
+ margin-right: 0.5rem;
699
+ user-select: none;
700
+ }
701
+
702
+ .console-input__wrapper {
703
+ flex: 1;
704
+ position: relative;
705
+ }
706
+
707
+ .console-input__field {
708
+ width: 100%;
709
+ background: none;
710
+ border: none;
711
+ outline: none;
712
+ font-family: monospace;
713
+ font-size: 0.875rem;
714
+ color: var(--fd-foreground);
715
+ padding: 0;
716
+ line-height: 1.5;
717
+ }
718
+
719
+ .console-input__field::placeholder {
720
+ color: var(--fd-muted-foreground);
721
+ opacity: 0.6;
722
+ }
723
+
724
+ .console-input--multiline {
725
+ align-items: flex-start;
726
+ }
727
+
728
+ .console-input--multiline .console-input__prompt {
729
+ margin-top: 0.125rem;
730
+ }
731
+
732
+ .console-input__multiline-header {
733
+ display: flex;
734
+ justify-content: space-between;
735
+ align-items: baseline;
736
+ margin-bottom: 0.25rem;
737
+ }
738
+
739
+ .console-input__multiline-label {
740
+ font-family: monospace;
741
+ font-size: 0.875rem;
742
+ color: var(--fd-foreground);
743
+ font-weight: 500;
744
+ }
745
+
746
+ .console-input__multiline-hint {
747
+ font-family: monospace;
748
+ font-size: 0.75rem;
749
+ color: var(--fd-muted-foreground);
750
+ opacity: 0.7;
751
+ }
752
+
753
+ .console-input__textarea {
754
+ width: 100%;
755
+ background: none;
756
+ border: 1px solid var(--fd-border-muted);
757
+ border-radius: var(--fd-radius-sm);
758
+ outline: none;
759
+ font-family: monospace;
760
+ font-size: 0.875rem;
761
+ color: var(--fd-foreground);
762
+ padding: 0.375rem 0.5rem;
763
+ line-height: 1.5;
764
+ resize: vertical;
765
+ min-height: 5rem;
766
+ }
767
+
768
+ .console-input__textarea:focus {
769
+ border-color: var(--fd-border);
770
+ }
771
+ </style>