@kiberon-labs/behave-graph-flow 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. package/.fallowrc.json +16 -0
  2. package/.storybook/main.ts +32 -0
  3. package/.storybook/preview.ts +16 -0
  4. package/.storybook/styles.css +10 -0
  5. package/.storybook/vscode.css +814 -0
  6. package/.turbo/turbo-build.log +7 -0
  7. package/LICENSE +6 -0
  8. package/README.md +2 -2
  9. package/data/Polynomial.json +510 -0
  10. package/data/sequence.json +337 -0
  11. package/data/trigger-event.json +241 -0
  12. package/data/variable-change.json +210 -0
  13. package/dist/entry.css +4 -0
  14. package/dist/index.css +39 -0
  15. package/dist/index.css.map +1 -0
  16. package/dist/index.d.ts +2282 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +14873 -0
  19. package/dist/index.js.map +1 -0
  20. package/docs/notifications.md +246 -0
  21. package/docs/protocol.md +679 -0
  22. package/docs/specifics.md +191 -0
  23. package/package.json +85 -21
  24. package/postcss.config.ts +3 -4
  25. package/src/annotations/index.ts +32 -0
  26. package/src/components/FloatingToolbar/index.module.css +45 -0
  27. package/src/components/FloatingToolbar/index.tsx +256 -0
  28. package/src/components/Flow.tsx +276 -75
  29. package/src/components/contextMenus/NodePicker.module.css +274 -0
  30. package/src/components/contextMenus/NodePicker.tsx +481 -0
  31. package/src/components/contextMenus/edge.tsx +108 -0
  32. package/src/components/contextMenus/node.tsx +155 -0
  33. package/src/components/contextMenus/selection.tsx +77 -0
  34. package/src/components/controls/any/index.tsx +8 -0
  35. package/src/components/controls/boolean/index.tsx +13 -0
  36. package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
  37. package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
  38. package/src/components/controls/colorPicker/index.module.css +18 -0
  39. package/src/components/controls/colorPicker/index.tsx +61 -0
  40. package/src/components/controls/number/index.tsx +35 -0
  41. package/src/components/controls/string/index.tsx +16 -0
  42. package/src/components/edges/index.tsx +469 -0
  43. package/src/components/edges/offsetBezier.ts +134 -0
  44. package/src/components/hotKeys.tsx +20 -0
  45. package/src/components/layoutController/index.module.css +10 -0
  46. package/src/components/layoutController/index.tsx +117 -0
  47. package/src/components/layoutController/utils.ts +205 -0
  48. package/src/components/menubar/defaults.tsx +480 -0
  49. package/src/components/menubar/index.tsx +49 -0
  50. package/src/components/menubar/menuItem.module.css +16 -0
  51. package/src/components/menubar/menuItem.tsx +32 -0
  52. package/src/components/nodes/behave/Node.module.css +23 -0
  53. package/src/components/nodes/behave/Node.tsx +176 -0
  54. package/src/components/nodes/behave/NodeContainer.module.css +87 -0
  55. package/src/components/nodes/behave/NodeContainer.tsx +46 -0
  56. package/src/components/nodes/behave/index.tsx +14 -0
  57. package/src/components/nodes/comment/FormatToolbar.tsx +118 -0
  58. package/src/components/nodes/comment/comment.tsx +103 -0
  59. package/src/components/nodes/comment/styles.module.css +150 -0
  60. package/src/components/nodes/group/index.tsx +109 -0
  61. package/src/components/nodes/wrapper/index.tsx +73 -0
  62. package/src/components/nodes/wrapper/styles.module.css +113 -0
  63. package/src/components/notifications/NotificationProvider.tsx +81 -0
  64. package/src/components/notifications/index.ts +2 -0
  65. package/src/components/notifications/utils.ts +71 -0
  66. package/src/components/panels/alignment/index.module.css +20 -0
  67. package/src/components/panels/alignment/index.tsx +244 -0
  68. package/src/components/panels/base/index.tsx +5 -0
  69. package/src/components/panels/base/styles.module.css +12 -0
  70. package/src/components/panels/conversation/index.module.css +151 -0
  71. package/src/components/panels/conversation/index.tsx +162 -0
  72. package/src/components/panels/events/CustomEventsEditor.tsx +384 -0
  73. package/src/components/panels/events/EditEventPanel.tsx +315 -0
  74. package/src/components/panels/events/ManageEventsPanel.tsx +98 -0
  75. package/src/components/panels/events/index.tsx +23 -0
  76. package/src/components/panels/events/styles.module.css +236 -0
  77. package/src/components/panels/history/index.tsx +92 -0
  78. package/src/components/panels/history/styles.module.css +106 -0
  79. package/src/components/panels/keymaps/index.module.css +78 -0
  80. package/src/components/panels/keymaps/index.tsx +167 -0
  81. package/src/components/panels/layers/index.tsx +240 -0
  82. package/src/components/panels/layers/styles.module.css +110 -0
  83. package/src/components/panels/legend/index.module.css +6 -0
  84. package/src/components/panels/legend/index.tsx +76 -0
  85. package/src/components/panels/logs/index.module.css +212 -0
  86. package/src/components/panels/logs/index.tsx +288 -0
  87. package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
  88. package/src/components/panels/nodeInputs/InputsGroup.tsx +64 -0
  89. package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
  90. package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
  91. package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
  92. package/src/components/panels/nodeInputs/OutputsGroup.tsx +65 -0
  93. package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
  94. package/src/components/panels/nodeInputs/index.module.css +284 -0
  95. package/src/components/panels/nodeInputs/index.tsx +339 -0
  96. package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
  97. package/src/components/panels/nodeInputs/useNodeInputsData.ts +173 -0
  98. package/src/components/panels/nodePicker/index.tsx +115 -0
  99. package/src/components/panels/panel/index.module.css +66 -0
  100. package/src/components/panels/panel/index.tsx +88 -0
  101. package/src/components/panels/search/index.module.css +66 -0
  102. package/src/components/panels/search/index.tsx +215 -0
  103. package/src/components/panels/systemSettings/index.tsx +206 -0
  104. package/src/components/panels/systemSettings/styles.module.css +11 -0
  105. package/src/components/panels/traces/GridLines.tsx +38 -0
  106. package/src/components/panels/traces/TimeGrid.tsx +48 -0
  107. package/src/components/panels/traces/TraceLane.tsx +62 -0
  108. package/src/components/panels/traces/TraceTooltip.tsx +22 -0
  109. package/src/components/panels/traces/TracesHeader.tsx +56 -0
  110. package/src/components/panels/traces/index.module.css +166 -0
  111. package/src/components/panels/traces/index.tsx +294 -0
  112. package/src/components/panels/traces/types.ts +48 -0
  113. package/src/components/panels/traces/useDerivedSpans.ts +212 -0
  114. package/src/components/panels/traces/utils.ts +25 -0
  115. package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
  116. package/src/components/panels/variables/ManageVariablesScreen.tsx +144 -0
  117. package/src/components/panels/variables/index.tsx +125 -0
  118. package/src/components/panels/variables/styles.module.css +236 -0
  119. package/src/components/primitives/icon.module.css +45 -0
  120. package/src/components/primitives/icon.tsx +38 -0
  121. package/src/components/sockets/input/index.tsx +76 -0
  122. package/src/components/sockets/input/styles.module.css +27 -0
  123. package/src/components/sockets/output/index.tsx +61 -0
  124. package/src/components/sockets/output/styles.module.css +27 -0
  125. package/src/css/prosemirror.css +57 -0
  126. package/src/css/rc-dock.css +112 -0
  127. package/src/css/rc-menu.css +100 -0
  128. package/src/css/vars.css +14 -0
  129. package/src/css/vscode.css +13 -0
  130. package/src/entry.css +4 -0
  131. package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
  132. package/src/generators/SequenceGenerator.tsx +104 -0
  133. package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
  134. package/src/generators/SwitchOnStringGenerator.tsx +263 -0
  135. package/src/generators/registerDefaultGenerators.ts +34 -0
  136. package/src/hooks/useBehaveGraphFlow.ts +17 -16
  137. package/src/hooks/useDetachNodes.ts +39 -0
  138. package/src/hooks/useFlowHandlers.ts +115 -29
  139. package/src/hooks/useWasdPan.ts +188 -0
  140. package/src/index.css +146 -0
  141. package/src/index.ts +36 -18
  142. package/src/layout/dagre.tsx +119 -0
  143. package/src/layout/elk.ts +200 -0
  144. package/src/plugin/alignment/index.ts +81 -0
  145. package/src/plugin/docs/index.tsx +299 -0
  146. package/src/plugin/docs/panel/index.tsx +200 -0
  147. package/src/plugin/docs/panel/styles.module.css +174 -0
  148. package/src/plugin/graphrunner/actions.ts +253 -0
  149. package/src/plugin/graphrunner/buttons.tsx +87 -0
  150. package/src/plugin/graphrunner/client.ts +704 -0
  151. package/src/plugin/graphrunner/index.tsx +255 -0
  152. package/src/plugin/graphrunner/panel.tsx +386 -0
  153. package/src/plugin/graphrunner/runner.ts +358 -0
  154. package/src/plugin/graphrunner/session.ts +243 -0
  155. package/src/plugin/graphrunner/store.ts +206 -0
  156. package/src/plugin/graphrunner/styles.module.css +211 -0
  157. package/src/plugin/graphrunner/transport.ts +224 -0
  158. package/src/plugin/graphrunner/types.ts +672 -0
  159. package/src/plugin/graphrunner-local/execution-utils.ts +457 -0
  160. package/src/plugin/graphrunner-local/index.tsx +166 -0
  161. package/src/plugin/graphrunner-local/panel.tsx +231 -0
  162. package/src/plugin/graphrunner-local/store.ts +41 -0
  163. package/src/plugin/graphrunner-local/styles.module.css +101 -0
  164. package/src/plugin/graphrunner-local/transport.ts +1372 -0
  165. package/src/plugin/graphrunner-local/types.ts +10 -0
  166. package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +633 -0
  167. package/src/plugin/graphrunner-webworker/index.tsx +146 -0
  168. package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
  169. package/src/plugin/graphrunner-webworker/store.ts +89 -0
  170. package/src/plugin/graphrunner-webworker/types.ts +17 -0
  171. package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
  172. package/src/plugin/realtime/realtimeRunner.ts +570 -0
  173. package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
  174. package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
  175. package/src/specifics/VariableGetSpecific.tsx +110 -0
  176. package/src/specifics/VariableSetSpecific.tsx +110 -0
  177. package/src/specifics/registerDefaultSpecifics.ts +5 -0
  178. package/src/store/actions.tsx +698 -0
  179. package/src/store/chat.ts +73 -0
  180. package/src/store/controls.tsx +62 -0
  181. package/src/store/documentation.tsx +69 -0
  182. package/src/store/events.tsx +116 -0
  183. package/src/store/flow.tsx +245 -0
  184. package/src/store/graphRunnerClient.ts +110 -0
  185. package/src/store/hotKeys.tsx +323 -0
  186. package/src/store/layers.ts +259 -0
  187. package/src/store/legend.tsx +76 -0
  188. package/src/store/logs.ts +28 -0
  189. package/src/store/menubar.ts +41 -0
  190. package/src/store/refs.ts +84 -0
  191. package/src/store/registry.ts +43 -0
  192. package/src/store/selection.ts +22 -0
  193. package/src/store/settings.ts +99 -0
  194. package/src/store/socketGenerator.tsx +54 -0
  195. package/src/store/specific.tsx +75 -0
  196. package/src/store/specs.tsx +35 -0
  197. package/src/store/tabs.ts +278 -0
  198. package/src/store/toolbar.tsx +45 -0
  199. package/src/store/traces.ts +240 -0
  200. package/src/store/variables.ts +37 -0
  201. package/src/system/graph.ts +134 -0
  202. package/src/system/index.ts +3 -0
  203. package/src/system/notifications.ts +98 -0
  204. package/src/system/plugin.ts +27 -0
  205. package/src/system/provider.tsx +22 -0
  206. package/src/system/pubsub.ts +323 -0
  207. package/src/system/system.ts +223 -0
  208. package/src/system/tabLoader.tsx +265 -0
  209. package/src/system/undoRedo.ts +103 -0
  210. package/src/transformers/Uigraph.ts +60 -0
  211. package/src/transformers/behaveToFlow.ts +16 -4
  212. package/src/transformers/flowToBehave.ts +32 -12
  213. package/src/types/NodeMetadata.ts +27 -0
  214. package/src/types/graph.ts +49 -0
  215. package/src/types/nodes.ts +45 -0
  216. package/src/types.ts +16 -0
  217. package/src/util/colors.ts +1 -29
  218. package/src/util/downloadJson.ts +18 -0
  219. package/src/util/extractNodeMetadata.ts +16 -0
  220. package/src/util/getPickerFilters.ts +1 -1
  221. package/src/util/isBehaveNode.ts +6 -0
  222. package/src/util/isValidConnection.ts +28 -15
  223. package/src/util/mergeSockets.ts +29 -0
  224. package/src/util/serializeVariables.ts +66 -0
  225. package/src/util/sockets.ts +43 -0
  226. package/stories/apex/layoutController/example-graph.worker.ts +39 -0
  227. package/stories/apex/layoutController/index.stories.tsx +48 -0
  228. package/stories/apex/layoutController/webworker.stories.tsx +103 -0
  229. package/stories/apex/menubar/menubar.stories.tsx +19 -0
  230. package/stories/components/colorpicker/index.stories.tsx +20 -0
  231. package/stories/components/contextMenus/edge.stories.tsx +32 -0
  232. package/stories/components/contextMenus/node.stories.tsx +26 -0
  233. package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
  234. package/stories/components/controls/any/index.stories.tsx +19 -0
  235. package/stories/components/controls/boolean/index.stories.tsx +19 -0
  236. package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
  237. package/stories/components/controls/number/index.stories.tsx +19 -0
  238. package/stories/components/controls/string/index.stories.tsx +19 -0
  239. package/stories/components/nodes/behaveNode.stories.tsx +108 -0
  240. package/stories/components/nodes/comment.stories.tsx +106 -0
  241. package/stories/components/panels/alignment.stories.tsx +24 -0
  242. package/stories/components/panels/events.stories.tsx +38 -0
  243. package/stories/components/panels/graphRunner.stories.tsx +317 -0
  244. package/stories/components/panels/history.stories.tsx +37 -0
  245. package/stories/components/panels/keymaps.stories.tsx +21 -0
  246. package/stories/components/panels/legend.stories.tsx +37 -0
  247. package/stories/components/panels/logs.stories.tsx +24 -0
  248. package/stories/components/panels/nodeInputs.stories.tsx +21 -0
  249. package/stories/components/panels/nodePicker.stories.tsx +37 -0
  250. package/stories/components/panels/panel.stories.tsx +39 -0
  251. package/stories/components/panels/search.stories.tsx +24 -0
  252. package/stories/components/panels/systemSettings.stories.tsx +26 -0
  253. package/stories/components/panels/traces.stories.tsx +225 -0
  254. package/stories/components/panels/variables.stories.tsx +24 -0
  255. package/stories/defaults/defaultStoryProvider.tsx +167 -0
  256. package/stories/defaults/systemGenerator.ts +38 -0
  257. package/tests/components/edges/offsetBezier.test.ts +51 -0
  258. package/tests/components/layoutController/utils.test.ts +68 -0
  259. package/tests/components/panels/traces/utils.test.ts +52 -0
  260. package/tests/flowToBehave.test.ts +26 -4
  261. package/tests/notifications.test.ts +87 -0
  262. package/tests/saveLoad.test.ts +372 -0
  263. package/tests/util/calculateNewEdge.test.ts +98 -0
  264. package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
  265. package/tests/util/hasPositionMetaData.test.ts +33 -0
  266. package/tests/util/isBehaveNode.test.ts +22 -0
  267. package/tests/util/isHandleConnected.test.ts +37 -0
  268. package/tests/util/mergeSockets.test.ts +43 -0
  269. package/tests/visual/README.md +64 -0
  270. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
  271. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
  272. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
  273. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
  274. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
  275. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
  276. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
  277. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
  278. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
  279. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
  280. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
  281. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
  282. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
  283. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
  284. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
  285. package/tests/visual/panels.visual.test.tsx +76 -0
  286. package/tsconfig.base.json +39 -0
  287. package/tsconfig.json +18 -59
  288. package/tsconfig.prod.json +23 -0
  289. package/tsdown.config.ts +15 -3
  290. package/typedoc.json +7 -7
  291. package/vite.config.js +7 -0
  292. package/vitest.config.ts +5 -2
  293. package/vitest.visual.config.ts +48 -0
  294. package/src/components/AutoSizeInput.tsx +0 -65
  295. package/src/components/Controls.tsx +0 -87
  296. package/src/components/InputSocket.tsx +0 -142
  297. package/src/components/Node.tsx +0 -68
  298. package/src/components/NodeContainer.tsx +0 -46
  299. package/src/components/NodePicker.tsx +0 -77
  300. package/src/components/OutputSocket.tsx +0 -58
  301. package/src/components/modals/ClearModal.tsx +0 -40
  302. package/src/components/modals/HelpModal.tsx +0 -36
  303. package/src/components/modals/LoadModal.tsx +0 -96
  304. package/src/components/modals/Modal.tsx +0 -64
  305. package/src/components/modals/SaveModal.tsx +0 -60
  306. package/src/hooks/useCustomNodeTypes.tsx +0 -31
  307. package/src/hooks/useGraphRunner.ts +0 -104
  308. package/src/hooks/useMergeMap.ts +0 -14
  309. package/src/hooks/useNodeSpecJson.ts +0 -20
  310. package/src/hooks/useQueriableDefinitions.ts +0 -22
  311. package/src/styles.css +0 -8
  312. package/tailwind.config.ts +0 -19
  313. package/tests/tsconfig.json +0 -10
  314. /package/src/{types.d.ts → types-declarations.d.ts} +0 -0
@@ -0,0 +1,73 @@
1
+ import { create } from 'zustand';
2
+
3
+ export interface AgentConfig {
4
+ model?: string;
5
+ systemPrompt?: string;
6
+ }
7
+
8
+ export interface ChatMessage {
9
+ id: string;
10
+ role: 'user' | 'assistant' | 'system';
11
+ content: string;
12
+ timestamp: Date;
13
+ isStreaming?: boolean;
14
+ }
15
+
16
+ export type ChatStore = {
17
+ messages: ChatMessage[];
18
+ agent: AgentConfig | undefined;
19
+ isStreaming: boolean;
20
+ inputValue: string;
21
+
22
+ setAgent: (agent: AgentConfig) => void;
23
+ clearAgent: () => void;
24
+ addMessage: (message: ChatMessage) => void;
25
+ updateStreamingMessage: (id: string, content: string) => void;
26
+ finalizeStreamingMessage: (id: string) => void;
27
+ setIsStreaming: (streaming: boolean) => void;
28
+ setInputValue: (value: string) => void;
29
+ clearMessages: () => void;
30
+ };
31
+
32
+ let messageCounter = 0;
33
+
34
+ export function createMessageId(): string {
35
+ messageCounter += 1;
36
+ return `msg-${Date.now()}-${String(messageCounter)}`;
37
+ }
38
+
39
+ export const chatStoreFactory = () =>
40
+ create<ChatStore>((set) => ({
41
+ messages: [],
42
+ agent: undefined,
43
+ isStreaming: false,
44
+ inputValue: '',
45
+
46
+ setAgent: (agent: AgentConfig) => set({ agent }),
47
+ clearAgent: () => set({ agent: undefined }),
48
+
49
+ addMessage: (message: ChatMessage) =>
50
+ set((state) => ({
51
+ messages: [...state.messages, message]
52
+ })),
53
+
54
+ updateStreamingMessage: (id: string, content: string) =>
55
+ set((state) => ({
56
+ messages: state.messages.map((msg) =>
57
+ msg.id === id ? { ...msg, content } : msg
58
+ )
59
+ })),
60
+
61
+ finalizeStreamingMessage: (id: string) =>
62
+ set((state) => ({
63
+ messages: state.messages.map((msg) =>
64
+ msg.id === id ? { ...msg, isStreaming: false } : msg
65
+ )
66
+ })),
67
+
68
+ setIsStreaming: (streaming: boolean) => set({ isStreaming: streaming }),
69
+
70
+ setInputValue: (value: string) => set({ inputValue: value }),
71
+
72
+ clearMessages: () => set({ messages: [] })
73
+ }));
@@ -0,0 +1,62 @@
1
+ import { AnyControl } from '@/components/controls/any';
2
+ import { BooleanControl } from '@/components/controls/boolean';
3
+ import { NumberControl } from '@/components/controls/number';
4
+ import { StringControl } from '@/components/controls/string';
5
+ import { ColorControl } from '@/components/controls/colorPicker';
6
+ import {
7
+ Cube,
8
+ Droplet,
9
+ EaseCurveControlPoints,
10
+ Hashtag,
11
+ InputOutput,
12
+ SelectPoint3d,
13
+ Text
14
+ } from 'iconoir-react';
15
+ import { create } from 'zustand';
16
+
17
+ export interface ControlProps<T = any> {
18
+ value: T;
19
+ onChange: (value: T) => void;
20
+ valueType?: string;
21
+ }
22
+
23
+ export type ControlComponent<T = any> = React.FC<ControlProps<T>>;
24
+
25
+ export type ControlsStore = {
26
+ icons: Record<string, React.ComponentType>;
27
+ controls: Record<string, React.FC<ControlProps>>;
28
+ defaultControl: React.FC<ControlProps>;
29
+ registerControl: (name: string, control: React.FC<ControlProps>) => void;
30
+ };
31
+
32
+ export const controlsStoreFactory = () =>
33
+ create<ControlsStore>((set) => ({
34
+ // store the component references (not instantiated elements)
35
+ defaultIcon: SelectPoint3d,
36
+
37
+ defaultControl: AnyControl,
38
+ controls: {
39
+ color: ColorControl,
40
+ string: StringControl,
41
+ number: NumberControl,
42
+ float: NumberControl,
43
+ integer: NumberControl,
44
+ boolean: BooleanControl
45
+ },
46
+ icons: {
47
+ color: Droplet,
48
+ curve: EaseCurveControlPoints,
49
+ string: Text,
50
+ boolean: InputOutput,
51
+ float: Hashtag,
52
+ integer: Hashtag,
53
+ object: Cube
54
+ },
55
+ registerControl: (name: string, control: React.FC<ControlProps>) =>
56
+ set((state) => ({
57
+ controls: {
58
+ ...state.controls,
59
+ [name]: control
60
+ }
61
+ }))
62
+ }));
@@ -0,0 +1,69 @@
1
+ import { create } from 'zustand';
2
+ import type React from 'react';
3
+
4
+ /**
5
+ * Documentation metadata for a node type
6
+ */
7
+ export type NodeDocumentation = {
8
+ /** The node type this documentation applies to */
9
+ type: string;
10
+ /** Optional icon to display for the node */
11
+ icon?: React.ReactNode;
12
+ /** Short description (one line) */
13
+ shortDescription?: string;
14
+ /** Tags for categorization and search */
15
+ tags?: string[];
16
+ /** Long rich markdown description */
17
+ markdownDescription?: string;
18
+ };
19
+
20
+ export type DocumentationStore = {
21
+ /** Map of node type to documentation */
22
+ docs: Map<string, NodeDocumentation>;
23
+ /** Set documentation for a specific node type */
24
+ setDocumentation: (
25
+ type: string,
26
+ doc: Omit<NodeDocumentation, 'type'>
27
+ ) => void;
28
+ /** Set documentation for multiple node types at once */
29
+ setMultipleDocumentation: (docs: NodeDocumentation[]) => void;
30
+ /** Get documentation for a specific node type */
31
+ getDocumentation: (type: string) => NodeDocumentation | undefined;
32
+ /** Clear all documentation */
33
+ clearDocumentation: () => void;
34
+ /** Remove documentation for a specific type */
35
+ removeDocumentation: (type: string) => void;
36
+ };
37
+
38
+ export const documentationStoreFactory = () => {
39
+ return create<DocumentationStore>((set, get) => ({
40
+ docs: new Map(),
41
+
42
+ setDocumentation: (type: string, doc: Omit<NodeDocumentation, 'type'>) =>
43
+ set((state) => {
44
+ const newDocs = new Map(state.docs);
45
+ newDocs.set(type, { type, ...doc });
46
+ return { docs: newDocs };
47
+ }),
48
+
49
+ setMultipleDocumentation: (docs: NodeDocumentation[]) =>
50
+ set((state) => {
51
+ const newDocs = new Map(state.docs);
52
+ for (const doc of docs) {
53
+ newDocs.set(doc.type, doc);
54
+ }
55
+ return { docs: newDocs };
56
+ }),
57
+
58
+ getDocumentation: (type: string) => get().docs.get(type),
59
+
60
+ clearDocumentation: () => set({ docs: new Map() }),
61
+
62
+ removeDocumentation: (type: string) =>
63
+ set((state) => {
64
+ const newDocs = new Map(state.docs);
65
+ newDocs.delete(type);
66
+ return { docs: newDocs };
67
+ })
68
+ }));
69
+ };
@@ -0,0 +1,116 @@
1
+ import { create } from 'zustand';
2
+ import type {
3
+ CustomEventJSON,
4
+ CustomEventParameterJSON
5
+ } from '@kiberon-labs/behave-graph';
6
+ export type ExtendedCustomEventJSON = CustomEventJSON & {
7
+ readonly?: boolean;
8
+ };
9
+
10
+ export type EventsStore = {
11
+ customEvents: Record<string, ExtendedCustomEventJSON>;
12
+ setCustomEvents: (
13
+ customEvents: Record<string, ExtendedCustomEventJSON>
14
+ ) => void;
15
+ getCustomEvents: () => ExtendedCustomEventJSON[];
16
+ addCustomEvent: (customEvent: ExtendedCustomEventJSON) => void;
17
+ removeCustomEvent: (id: string) => void;
18
+
19
+ addParameter: (
20
+ eventId: string,
21
+ parameter?: Partial<CustomEventParameterJSON>
22
+ ) => void;
23
+ updateParameter: (
24
+ eventId: string,
25
+ index: number,
26
+ patch: Partial<CustomEventParameterJSON>
27
+ ) => void;
28
+ removeParameter: (eventId: string, index: number) => void;
29
+ };
30
+
31
+ export const eventsStoreFactory = () =>
32
+ create<EventsStore>((set, get) => ({
33
+ customEvents: {},
34
+ setCustomEvents: (customEvents) => {
35
+ set({ customEvents });
36
+ },
37
+ getCustomEvents: () => Object.values(get().customEvents ?? {}),
38
+
39
+ addCustomEvent: (customEvent) => {
40
+ set((t) => ({
41
+ customEvents: { ...t.customEvents, [customEvent.id]: customEvent }
42
+ }));
43
+ },
44
+
45
+ removeCustomEvent: (id) => {
46
+ const current = get().customEvents ?? {};
47
+ const next = { ...current };
48
+ delete next[String(id)];
49
+
50
+ set({ customEvents: next });
51
+ },
52
+ addParameter: (eventId, parameter) => {
53
+ const current = get().customEvents;
54
+
55
+ const newEvent = current[eventId];
56
+ if (!newEvent) return;
57
+
58
+ const withUpdated = {
59
+ ...newEvent,
60
+ parameters: [
61
+ ...((newEvent.parameters ?? []) as CustomEventParameterJSON[]),
62
+ {
63
+ name: parameter?.name ? String(parameter.name) : 'param',
64
+ valueTypeName: parameter?.valueTypeName
65
+ ? String(parameter.valueTypeName)
66
+ : 'string',
67
+ defaultValue: parameter?.defaultValue
68
+ }
69
+ ]
70
+ } as CustomEventJSON;
71
+ set({
72
+ customEvents: {
73
+ ...current,
74
+ [eventId]: withUpdated
75
+ }
76
+ });
77
+ },
78
+
79
+ updateParameter: (eventId, index, patch) => {
80
+ const current = get().customEvents;
81
+
82
+ const ev = current[eventId];
83
+ if (!ev) return;
84
+
85
+ set({
86
+ customEvents: {
87
+ ...current,
88
+ [eventId]: {
89
+ ...ev,
90
+ parameters: ev.parameters?.map((param, i) => {
91
+ if (i !== index) return param;
92
+
93
+ return { ...param, ...patch };
94
+ })
95
+ }
96
+ }
97
+ });
98
+ },
99
+
100
+ removeParameter: (eventId, index) => {
101
+ const current = get().customEvents;
102
+
103
+ const ev = current[eventId];
104
+ if (!ev) return;
105
+
106
+ set({
107
+ customEvents: {
108
+ ...current,
109
+ [eventId]: {
110
+ ...ev,
111
+ parameters: ev.parameters?.filter((_, i) => i !== index) ?? []
112
+ }
113
+ }
114
+ });
115
+ }
116
+ }));
@@ -0,0 +1,245 @@
1
+ import { CustomEdge } from '@/components/edges';
2
+ import type { System } from '@/system';
3
+ import { behaveToFlow } from '@/transformers/behaveToFlow';
4
+ import { flowToBehave } from '@/transformers/flowToBehave';
5
+ import { autoLayout } from '@/util/autoLayout';
6
+ import { hasPositionMetaData } from '@/util/hasPositionMetaData';
7
+ import type { GraphJSON } from '@kiberon-labs/behave-graph';
8
+ import {
9
+ applyEdgeChanges,
10
+ type Edge,
11
+ type Node,
12
+ type EdgeChange,
13
+ type NodeChange,
14
+ applyNodeChanges as nativeNodeChanges,
15
+ type EdgeProps,
16
+ type NodeProps
17
+ } from 'reactflow';
18
+ import { create } from 'zustand';
19
+ import { nonDeletable } from '@/annotations';
20
+ import GroupNode from '@/components/nodes/group';
21
+ import { CommentNode } from '@/components/nodes/comment/comment';
22
+ import { BehaveNode } from '@/components/nodes/behave';
23
+
24
+ export type FlowStore = {
25
+ graphJson: GraphJSON | null;
26
+ setGraph: (graph: GraphJSON, options?: { skipLayout?: boolean }) => void;
27
+ getGraph: () => GraphJSON;
28
+ nodeTypes: Record<string, React.ComponentType<NodeProps>>;
29
+ edgeTypes: Record<string, React.ComponentType<EdgeProps>>;
30
+ invalidateCache: () => void;
31
+ registerNodeType: (
32
+ type: string,
33
+ component: React.ComponentType<NodeProps>
34
+ ) => void;
35
+ registerEdgeType: (
36
+ type: string,
37
+ component: React.ComponentType<EdgeProps>
38
+ ) => void;
39
+ };
40
+
41
+ // const specJson = useStore(sys.specStore, (s) => s.specs);
42
+ // const [customNodeTypes, setCustomNodeTypes] = useState<NodeTypes>();
43
+ // useEffect(() => {
44
+ // if (!specJson) return;
45
+ // const customNodeTypes: Record<
46
+ // AnyNodeType,
47
+ // React.ComponentType<any>
48
+ // > = getCustomNodeTypes(specJson);
49
+
50
+ // customNodeTypes['commentNode'] = CommentNode;
51
+ // customNodeTypes['group'] = GroupNode;
52
+ // // customNodeTypes['behaveNode:ai'] = AINode;
53
+
54
+ // setCustomNodeTypes(customNodeTypes);
55
+ // }, [specJson]);
56
+
57
+ export const flowStoreFactory = (system: System) => {
58
+ const flowStore = create<FlowStore>((set, get) => ({
59
+ graphJson: null,
60
+ nodeTypes: {
61
+ group: GroupNode,
62
+ commentNode: CommentNode,
63
+ behaveNode: BehaveNode
64
+ },
65
+ invalidateCache: () => set({ graphJson: null }),
66
+ getGraph: () => {
67
+ const cached = get().graphJson;
68
+ if (cached) {
69
+ return cached;
70
+ }
71
+
72
+ const nodes = system.nodeStore.getState().nodes;
73
+ const edges = system.edgeStore.getState().edges;
74
+ const _variables = system.variableStore.getState().variables;
75
+ const specs = system.specStore.getState().specs;
76
+
77
+ const computed = flowToBehave(system, nodes, edges, specs);
78
+
79
+ set({ graphJson: computed });
80
+ return computed;
81
+ },
82
+
83
+ setGraph: (graphJson: GraphJSON, options?: { skipLayout?: boolean }) => {
84
+ system.eventsStore
85
+ .getState()
86
+ .setCustomEvents(
87
+ Object.fromEntries(
88
+ (graphJson.customEvents ?? []).map((evt) => [evt.id, evt])
89
+ )
90
+ );
91
+
92
+ // Parse variables from JSON directly (no need to instantiate graph)
93
+ const variables: Record<string, any> = {};
94
+ if (graphJson.variables) {
95
+ graphJson.variables.forEach((varJson) => {
96
+ const valueType =
97
+ system.registry.getState().values[varJson.valueTypeName];
98
+ const initialValue = valueType?.deserialize
99
+ ? valueType.deserialize(varJson.initialValue)
100
+ : varJson.initialValue;
101
+
102
+ variables[varJson.id] = {
103
+ id: varJson.id,
104
+ name: varJson.name,
105
+ valueTypeName: varJson.valueTypeName,
106
+ initialValue
107
+ };
108
+ });
109
+ }
110
+
111
+ // Only convert and set nodes/edges if not skipping layout
112
+ // (when loading UIGraphJSON, nodes/edges are already set by deseralize)
113
+ if (!options?.skipLayout) {
114
+ const [nodes, edges] = behaveToFlow(graphJson);
115
+
116
+ if (!hasPositionMetaData(graphJson)) {
117
+ autoLayout(nodes, edges);
118
+ }
119
+ system.nodeStore.getState().setNodes(nodes);
120
+ system.edgeStore.getState().setEdges(edges);
121
+ }
122
+
123
+ // custom events stored in system.eventsStore
124
+ system.variableStore.getState().setVariables(variables);
125
+ get().invalidateCache();
126
+ },
127
+ edgeTypes: {
128
+ default: CustomEdge as React.ComponentType<EdgeProps>
129
+ },
130
+
131
+ registerNodeType(type: string, component: React.ComponentType<NodeProps>) {
132
+ set((state) => ({
133
+ nodeTypes: {
134
+ ...state.nodeTypes,
135
+ [type]: component
136
+ }
137
+ }));
138
+ },
139
+ registerEdgeType(type: string, component: React.ComponentType<EdgeProps>) {
140
+ set((state) => ({
141
+ edgeTypes: {
142
+ ...state.edgeTypes,
143
+ [type]: component
144
+ }
145
+ }));
146
+ }
147
+ }));
148
+
149
+ system.nodeStore.subscribe(() => {
150
+ flowStore.getState().invalidateCache();
151
+ });
152
+
153
+ system.eventsStore.subscribe(() => {
154
+ flowStore.getState().invalidateCache();
155
+ });
156
+
157
+ return flowStore;
158
+ };
159
+
160
+ export type NodeStore = {
161
+ nodes: Node[];
162
+ addNode: (node: Node) => void;
163
+ setNodes: (nodes: Node[] | ((existing: Node[]) => Node[])) => void;
164
+ clearNodes: () => void;
165
+ applyNodeChanges: (changes: NodeChange[]) => void;
166
+ };
167
+
168
+ export const nodeStoreFactory = (system: System) =>
169
+ create<NodeStore>((set) => ({
170
+ nodes: [],
171
+ addNode(node) {
172
+ set((x) => ({ nodes: [...x.nodes, node] }));
173
+ system.pubsub.publish('node:added', node);
174
+ },
175
+ applyNodeChanges(changes: NodeChange[]) {
176
+ set((p) => {
177
+ // Filter out remove changes for nodes with nonDeletable annotation
178
+ const filteredChanges = changes.filter((change) => {
179
+ if (change.type === 'remove') {
180
+ const node = p.nodes.find((n) => n.id === change.id);
181
+ if (node?.data?.metadata?.[nonDeletable]) {
182
+ return false;
183
+ }
184
+ // Publish nodeRemoved event for deletable nodes
185
+ if (node) {
186
+ system.pubsub.publish('node:removed', node);
187
+ }
188
+ }
189
+ return true;
190
+ });
191
+ return {
192
+ nodes: nativeNodeChanges(filteredChanges, p.nodes)
193
+ };
194
+ });
195
+ },
196
+ setNodes(nodes) {
197
+ set((p) => ({
198
+ nodes: typeof nodes === 'function' ? nodes(p.nodes) : nodes
199
+ }));
200
+ },
201
+ clearNodes() {
202
+ set(() => ({ nodes: [] }));
203
+ }
204
+ }));
205
+
206
+ export type EdgeStore = {
207
+ edges: Edge[];
208
+ addEdge: (edge: Edge) => void;
209
+ setEdges: (edges: Edge[]) => void;
210
+ clearEdges: () => void;
211
+ applyEdgeChanges: (changes: EdgeChange[]) => void;
212
+ };
213
+
214
+ export const edgeStoreFactory = (_system: System) =>
215
+ create<EdgeStore>((set) => ({
216
+ edges: [],
217
+
218
+ addEdge(edge) {
219
+ set((x) => ({ edges: [...x.edges, edge] }));
220
+ },
221
+ applyEdgeChanges(changes: EdgeChange[]) {
222
+ set((p) => {
223
+ // Publish events for edge removals
224
+ changes.forEach((change) => {
225
+ if (change.type === 'remove') {
226
+ const edge = p.edges.find((e) => e.id === change.id);
227
+ if (edge) {
228
+ _system.pubsub.publish('edge:removed', edge);
229
+ }
230
+ }
231
+ });
232
+ return {
233
+ edges: applyEdgeChanges(changes, p.edges)
234
+ };
235
+ });
236
+ },
237
+
238
+ setEdges(edges) {
239
+ set(() => ({ edges }));
240
+ },
241
+
242
+ clearEdges() {
243
+ set(() => ({ edges: [] }));
244
+ }
245
+ }));
@@ -0,0 +1,110 @@
1
+ import { createStore } from 'zustand/vanilla';
2
+ import type { GraphRunnerClient } from '../plugin/graphrunner/client';
3
+ import type {
4
+ AuthCredentials,
5
+ GraphRunnerCapabilities,
6
+ ServerVariable,
7
+ ServerEvent
8
+ } from '../plugin/graphrunner/types';
9
+ import type { NodeSpecJSON } from '@kiberon-labs/behave-graph';
10
+
11
+ export interface ConnectionConfig {
12
+ url: string;
13
+ auth: AuthCredentials;
14
+ autoReconnect: boolean;
15
+ }
16
+
17
+ export interface ConnectionInfo {
18
+ serverId: string | null;
19
+ userId: string | null;
20
+ sessionId: string | null;
21
+ authenticated: boolean;
22
+ capabilities: GraphRunnerCapabilities | null;
23
+ }
24
+
25
+ export interface GraphRunnerClientStore {
26
+ // Connection state
27
+ connectionState:
28
+ | 'disconnected'
29
+ | 'connecting'
30
+ | 'authenticating'
31
+ | 'connected';
32
+ connectionConfig: ConnectionConfig;
33
+ connectionInfo: ConnectionInfo;
34
+ error: string | null;
35
+
36
+ // Client instance
37
+ client: GraphRunnerClient | null;
38
+
39
+ // Server metadata
40
+ serverVariables: ServerVariable[];
41
+ serverEvents: ServerEvent[];
42
+ nodeTypes: NodeSpecJSON[];
43
+
44
+ // Actions
45
+ setConnectionConfig: (config: Partial<ConnectionConfig>) => void;
46
+ setClient: (client: GraphRunnerClient | null) => void;
47
+ setConnectionState: (
48
+ state: 'disconnected' | 'connecting' | 'authenticating' | 'connected'
49
+ ) => void;
50
+ setConnectionInfo: (info: Partial<ConnectionInfo>) => void;
51
+ setError: (error: string | null) => void;
52
+ setServerVariables: (variables: ServerVariable[]) => void;
53
+ setServerEvents: (events: ServerEvent[]) => void;
54
+ setNodeTypes: (nodeTypes: NodeSpecJSON[]) => void;
55
+ clearServerMetadata: () => void;
56
+ }
57
+
58
+ export const graphRunnerClientStoreFactory = () => {
59
+ return createStore<GraphRunnerClientStore>((set) => ({
60
+ // Initial state
61
+ connectionState: 'disconnected',
62
+ connectionConfig: {
63
+ url: '',
64
+ auth: { type: 'none' },
65
+ autoReconnect: true
66
+ },
67
+ connectionInfo: {
68
+ serverId: null,
69
+ userId: null,
70
+ sessionId: null,
71
+ authenticated: false,
72
+ capabilities: null
73
+ },
74
+ error: null,
75
+ client: null,
76
+ serverVariables: [],
77
+ serverEvents: [],
78
+ nodeTypes: [],
79
+
80
+ // Actions
81
+ setConnectionConfig: (config) =>
82
+ set((state) => ({
83
+ connectionConfig: { ...state.connectionConfig, ...config }
84
+ })),
85
+
86
+ setClient: (client) => set({ client }),
87
+
88
+ setConnectionState: (connectionState) => set({ connectionState }),
89
+
90
+ setConnectionInfo: (info) =>
91
+ set((state) => ({
92
+ connectionInfo: { ...state.connectionInfo, ...info }
93
+ })),
94
+
95
+ setError: (error) => set({ error }),
96
+
97
+ setServerVariables: (serverVariables) => set({ serverVariables }),
98
+
99
+ setServerEvents: (serverEvents) => set({ serverEvents }),
100
+
101
+ setNodeTypes: (nodeTypes) => set({ nodeTypes }),
102
+
103
+ clearServerMetadata: () =>
104
+ set({
105
+ serverVariables: [],
106
+ serverEvents: [],
107
+ nodeTypes: []
108
+ })
109
+ }));
110
+ };