@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.
- package/.fallowrc.json +16 -0
- package/.storybook/main.ts +32 -0
- package/.storybook/preview.ts +16 -0
- package/.storybook/styles.css +10 -0
- package/.storybook/vscode.css +814 -0
- package/.turbo/turbo-build.log +7 -0
- package/LICENSE +6 -0
- package/README.md +2 -2
- package/data/Polynomial.json +510 -0
- package/data/sequence.json +337 -0
- package/data/trigger-event.json +241 -0
- package/data/variable-change.json +210 -0
- package/dist/entry.css +4 -0
- package/dist/index.css +39 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +2282 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14873 -0
- package/dist/index.js.map +1 -0
- package/docs/notifications.md +246 -0
- package/docs/protocol.md +679 -0
- package/docs/specifics.md +191 -0
- package/package.json +85 -21
- package/postcss.config.ts +3 -4
- package/src/annotations/index.ts +32 -0
- package/src/components/FloatingToolbar/index.module.css +45 -0
- package/src/components/FloatingToolbar/index.tsx +256 -0
- package/src/components/Flow.tsx +276 -75
- package/src/components/contextMenus/NodePicker.module.css +274 -0
- package/src/components/contextMenus/NodePicker.tsx +481 -0
- package/src/components/contextMenus/edge.tsx +108 -0
- package/src/components/contextMenus/node.tsx +155 -0
- package/src/components/contextMenus/selection.tsx +77 -0
- package/src/components/controls/any/index.tsx +8 -0
- package/src/components/controls/boolean/index.tsx +13 -0
- package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
- package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
- package/src/components/controls/colorPicker/index.module.css +18 -0
- package/src/components/controls/colorPicker/index.tsx +61 -0
- package/src/components/controls/number/index.tsx +35 -0
- package/src/components/controls/string/index.tsx +16 -0
- package/src/components/edges/index.tsx +469 -0
- package/src/components/edges/offsetBezier.ts +134 -0
- package/src/components/hotKeys.tsx +20 -0
- package/src/components/layoutController/index.module.css +10 -0
- package/src/components/layoutController/index.tsx +117 -0
- package/src/components/layoutController/utils.ts +205 -0
- package/src/components/menubar/defaults.tsx +480 -0
- package/src/components/menubar/index.tsx +49 -0
- package/src/components/menubar/menuItem.module.css +16 -0
- package/src/components/menubar/menuItem.tsx +32 -0
- package/src/components/nodes/behave/Node.module.css +23 -0
- package/src/components/nodes/behave/Node.tsx +176 -0
- package/src/components/nodes/behave/NodeContainer.module.css +87 -0
- package/src/components/nodes/behave/NodeContainer.tsx +46 -0
- package/src/components/nodes/behave/index.tsx +14 -0
- package/src/components/nodes/comment/FormatToolbar.tsx +118 -0
- package/src/components/nodes/comment/comment.tsx +103 -0
- package/src/components/nodes/comment/styles.module.css +150 -0
- package/src/components/nodes/group/index.tsx +109 -0
- package/src/components/nodes/wrapper/index.tsx +73 -0
- package/src/components/nodes/wrapper/styles.module.css +113 -0
- package/src/components/notifications/NotificationProvider.tsx +81 -0
- package/src/components/notifications/index.ts +2 -0
- package/src/components/notifications/utils.ts +71 -0
- package/src/components/panels/alignment/index.module.css +20 -0
- package/src/components/panels/alignment/index.tsx +244 -0
- package/src/components/panels/base/index.tsx +5 -0
- package/src/components/panels/base/styles.module.css +12 -0
- package/src/components/panels/conversation/index.module.css +151 -0
- package/src/components/panels/conversation/index.tsx +162 -0
- package/src/components/panels/events/CustomEventsEditor.tsx +384 -0
- package/src/components/panels/events/EditEventPanel.tsx +315 -0
- package/src/components/panels/events/ManageEventsPanel.tsx +98 -0
- package/src/components/panels/events/index.tsx +23 -0
- package/src/components/panels/events/styles.module.css +236 -0
- package/src/components/panels/history/index.tsx +92 -0
- package/src/components/panels/history/styles.module.css +106 -0
- package/src/components/panels/keymaps/index.module.css +78 -0
- package/src/components/panels/keymaps/index.tsx +167 -0
- package/src/components/panels/layers/index.tsx +240 -0
- package/src/components/panels/layers/styles.module.css +110 -0
- package/src/components/panels/legend/index.module.css +6 -0
- package/src/components/panels/legend/index.tsx +76 -0
- package/src/components/panels/logs/index.module.css +212 -0
- package/src/components/panels/logs/index.tsx +288 -0
- package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
- package/src/components/panels/nodeInputs/InputsGroup.tsx +64 -0
- package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
- package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
- package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
- package/src/components/panels/nodeInputs/OutputsGroup.tsx +65 -0
- package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
- package/src/components/panels/nodeInputs/index.module.css +284 -0
- package/src/components/panels/nodeInputs/index.tsx +339 -0
- package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
- package/src/components/panels/nodeInputs/useNodeInputsData.ts +173 -0
- package/src/components/panels/nodePicker/index.tsx +115 -0
- package/src/components/panels/panel/index.module.css +66 -0
- package/src/components/panels/panel/index.tsx +88 -0
- package/src/components/panels/search/index.module.css +66 -0
- package/src/components/panels/search/index.tsx +215 -0
- package/src/components/panels/systemSettings/index.tsx +206 -0
- package/src/components/panels/systemSettings/styles.module.css +11 -0
- package/src/components/panels/traces/GridLines.tsx +38 -0
- package/src/components/panels/traces/TimeGrid.tsx +48 -0
- package/src/components/panels/traces/TraceLane.tsx +62 -0
- package/src/components/panels/traces/TraceTooltip.tsx +22 -0
- package/src/components/panels/traces/TracesHeader.tsx +56 -0
- package/src/components/panels/traces/index.module.css +166 -0
- package/src/components/panels/traces/index.tsx +294 -0
- package/src/components/panels/traces/types.ts +48 -0
- package/src/components/panels/traces/useDerivedSpans.ts +212 -0
- package/src/components/panels/traces/utils.ts +25 -0
- package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
- package/src/components/panels/variables/ManageVariablesScreen.tsx +144 -0
- package/src/components/panels/variables/index.tsx +125 -0
- package/src/components/panels/variables/styles.module.css +236 -0
- package/src/components/primitives/icon.module.css +45 -0
- package/src/components/primitives/icon.tsx +38 -0
- package/src/components/sockets/input/index.tsx +76 -0
- package/src/components/sockets/input/styles.module.css +27 -0
- package/src/components/sockets/output/index.tsx +61 -0
- package/src/components/sockets/output/styles.module.css +27 -0
- package/src/css/prosemirror.css +57 -0
- package/src/css/rc-dock.css +112 -0
- package/src/css/rc-menu.css +100 -0
- package/src/css/vars.css +14 -0
- package/src/css/vscode.css +13 -0
- package/src/entry.css +4 -0
- package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
- package/src/generators/SequenceGenerator.tsx +104 -0
- package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
- package/src/generators/SwitchOnStringGenerator.tsx +263 -0
- package/src/generators/registerDefaultGenerators.ts +34 -0
- package/src/hooks/useBehaveGraphFlow.ts +17 -16
- package/src/hooks/useDetachNodes.ts +39 -0
- package/src/hooks/useFlowHandlers.ts +115 -29
- package/src/hooks/useWasdPan.ts +188 -0
- package/src/index.css +146 -0
- package/src/index.ts +36 -18
- package/src/layout/dagre.tsx +119 -0
- package/src/layout/elk.ts +200 -0
- package/src/plugin/alignment/index.ts +81 -0
- package/src/plugin/docs/index.tsx +299 -0
- package/src/plugin/docs/panel/index.tsx +200 -0
- package/src/plugin/docs/panel/styles.module.css +174 -0
- package/src/plugin/graphrunner/actions.ts +253 -0
- package/src/plugin/graphrunner/buttons.tsx +87 -0
- package/src/plugin/graphrunner/client.ts +704 -0
- package/src/plugin/graphrunner/index.tsx +255 -0
- package/src/plugin/graphrunner/panel.tsx +386 -0
- package/src/plugin/graphrunner/runner.ts +358 -0
- package/src/plugin/graphrunner/session.ts +243 -0
- package/src/plugin/graphrunner/store.ts +206 -0
- package/src/plugin/graphrunner/styles.module.css +211 -0
- package/src/plugin/graphrunner/transport.ts +224 -0
- package/src/plugin/graphrunner/types.ts +672 -0
- package/src/plugin/graphrunner-local/execution-utils.ts +457 -0
- package/src/plugin/graphrunner-local/index.tsx +166 -0
- package/src/plugin/graphrunner-local/panel.tsx +231 -0
- package/src/plugin/graphrunner-local/store.ts +41 -0
- package/src/plugin/graphrunner-local/styles.module.css +101 -0
- package/src/plugin/graphrunner-local/transport.ts +1372 -0
- package/src/plugin/graphrunner-local/types.ts +10 -0
- package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +633 -0
- package/src/plugin/graphrunner-webworker/index.tsx +146 -0
- package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
- package/src/plugin/graphrunner-webworker/store.ts +89 -0
- package/src/plugin/graphrunner-webworker/types.ts +17 -0
- package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
- package/src/plugin/realtime/realtimeRunner.ts +570 -0
- package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
- package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
- package/src/specifics/VariableGetSpecific.tsx +110 -0
- package/src/specifics/VariableSetSpecific.tsx +110 -0
- package/src/specifics/registerDefaultSpecifics.ts +5 -0
- package/src/store/actions.tsx +698 -0
- package/src/store/chat.ts +73 -0
- package/src/store/controls.tsx +62 -0
- package/src/store/documentation.tsx +69 -0
- package/src/store/events.tsx +116 -0
- package/src/store/flow.tsx +245 -0
- package/src/store/graphRunnerClient.ts +110 -0
- package/src/store/hotKeys.tsx +323 -0
- package/src/store/layers.ts +259 -0
- package/src/store/legend.tsx +76 -0
- package/src/store/logs.ts +28 -0
- package/src/store/menubar.ts +41 -0
- package/src/store/refs.ts +84 -0
- package/src/store/registry.ts +43 -0
- package/src/store/selection.ts +22 -0
- package/src/store/settings.ts +99 -0
- package/src/store/socketGenerator.tsx +54 -0
- package/src/store/specific.tsx +75 -0
- package/src/store/specs.tsx +35 -0
- package/src/store/tabs.ts +278 -0
- package/src/store/toolbar.tsx +45 -0
- package/src/store/traces.ts +240 -0
- package/src/store/variables.ts +37 -0
- package/src/system/graph.ts +134 -0
- package/src/system/index.ts +3 -0
- package/src/system/notifications.ts +98 -0
- package/src/system/plugin.ts +27 -0
- package/src/system/provider.tsx +22 -0
- package/src/system/pubsub.ts +323 -0
- package/src/system/system.ts +223 -0
- package/src/system/tabLoader.tsx +265 -0
- package/src/system/undoRedo.ts +103 -0
- package/src/transformers/Uigraph.ts +60 -0
- package/src/transformers/behaveToFlow.ts +16 -4
- package/src/transformers/flowToBehave.ts +32 -12
- package/src/types/NodeMetadata.ts +27 -0
- package/src/types/graph.ts +49 -0
- package/src/types/nodes.ts +45 -0
- package/src/types.ts +16 -0
- package/src/util/colors.ts +1 -29
- package/src/util/downloadJson.ts +18 -0
- package/src/util/extractNodeMetadata.ts +16 -0
- package/src/util/getPickerFilters.ts +1 -1
- package/src/util/isBehaveNode.ts +6 -0
- package/src/util/isValidConnection.ts +28 -15
- package/src/util/mergeSockets.ts +29 -0
- package/src/util/serializeVariables.ts +66 -0
- package/src/util/sockets.ts +43 -0
- package/stories/apex/layoutController/example-graph.worker.ts +39 -0
- package/stories/apex/layoutController/index.stories.tsx +48 -0
- package/stories/apex/layoutController/webworker.stories.tsx +103 -0
- package/stories/apex/menubar/menubar.stories.tsx +19 -0
- package/stories/components/colorpicker/index.stories.tsx +20 -0
- package/stories/components/contextMenus/edge.stories.tsx +32 -0
- package/stories/components/contextMenus/node.stories.tsx +26 -0
- package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
- package/stories/components/controls/any/index.stories.tsx +19 -0
- package/stories/components/controls/boolean/index.stories.tsx +19 -0
- package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
- package/stories/components/controls/number/index.stories.tsx +19 -0
- package/stories/components/controls/string/index.stories.tsx +19 -0
- package/stories/components/nodes/behaveNode.stories.tsx +108 -0
- package/stories/components/nodes/comment.stories.tsx +106 -0
- package/stories/components/panels/alignment.stories.tsx +24 -0
- package/stories/components/panels/events.stories.tsx +38 -0
- package/stories/components/panels/graphRunner.stories.tsx +317 -0
- package/stories/components/panels/history.stories.tsx +37 -0
- package/stories/components/panels/keymaps.stories.tsx +21 -0
- package/stories/components/panels/legend.stories.tsx +37 -0
- package/stories/components/panels/logs.stories.tsx +24 -0
- package/stories/components/panels/nodeInputs.stories.tsx +21 -0
- package/stories/components/panels/nodePicker.stories.tsx +37 -0
- package/stories/components/panels/panel.stories.tsx +39 -0
- package/stories/components/panels/search.stories.tsx +24 -0
- package/stories/components/panels/systemSettings.stories.tsx +26 -0
- package/stories/components/panels/traces.stories.tsx +225 -0
- package/stories/components/panels/variables.stories.tsx +24 -0
- package/stories/defaults/defaultStoryProvider.tsx +167 -0
- package/stories/defaults/systemGenerator.ts +38 -0
- package/tests/components/edges/offsetBezier.test.ts +51 -0
- package/tests/components/layoutController/utils.test.ts +68 -0
- package/tests/components/panels/traces/utils.test.ts +52 -0
- package/tests/flowToBehave.test.ts +26 -4
- package/tests/notifications.test.ts +87 -0
- package/tests/saveLoad.test.ts +372 -0
- package/tests/util/calculateNewEdge.test.ts +98 -0
- package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
- package/tests/util/hasPositionMetaData.test.ts +33 -0
- package/tests/util/isBehaveNode.test.ts +22 -0
- package/tests/util/isHandleConnected.test.ts +37 -0
- package/tests/util/mergeSockets.test.ts +43 -0
- package/tests/visual/README.md +64 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
- package/tests/visual/panels.visual.test.tsx +76 -0
- package/tsconfig.base.json +39 -0
- package/tsconfig.json +18 -59
- package/tsconfig.prod.json +23 -0
- package/tsdown.config.ts +15 -3
- package/typedoc.json +7 -7
- package/vite.config.js +7 -0
- package/vitest.config.ts +5 -2
- package/vitest.visual.config.ts +48 -0
- package/src/components/AutoSizeInput.tsx +0 -65
- package/src/components/Controls.tsx +0 -87
- package/src/components/InputSocket.tsx +0 -142
- package/src/components/Node.tsx +0 -68
- package/src/components/NodeContainer.tsx +0 -46
- package/src/components/NodePicker.tsx +0 -77
- package/src/components/OutputSocket.tsx +0 -58
- package/src/components/modals/ClearModal.tsx +0 -40
- package/src/components/modals/HelpModal.tsx +0 -36
- package/src/components/modals/LoadModal.tsx +0 -96
- package/src/components/modals/Modal.tsx +0 -64
- package/src/components/modals/SaveModal.tsx +0 -60
- package/src/hooks/useCustomNodeTypes.tsx +0 -31
- package/src/hooks/useGraphRunner.ts +0 -104
- package/src/hooks/useMergeMap.ts +0 -14
- package/src/hooks/useNodeSpecJson.ts +0 -20
- package/src/hooks/useQueriableDefinitions.ts +0 -22
- package/src/styles.css +0 -8
- package/tailwind.config.ts +0 -19
- package/tests/tsconfig.json +0 -10
- /package/src/{types.d.ts → types-declarations.d.ts} +0 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket client plugin for the Behave-Graph Execution Protocol
|
|
3
|
+
* Provides UI and store integration for remote graph execution
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { type System } from '../../system/system';
|
|
7
|
+
import { graphRunnerClientStoreFactory } from './store';
|
|
8
|
+
import { GraphRunnerClient } from './client';
|
|
9
|
+
import { GraphRunnerPanel } from './panel';
|
|
10
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
11
|
+
import { MenuItemElement } from '../../components/menubar/menuItem';
|
|
12
|
+
import type { StoreApi } from 'zustand';
|
|
13
|
+
import type { GraphRunnerClientStore } from './store';
|
|
14
|
+
import { GraphRunnerButtons } from './buttons';
|
|
15
|
+
import { plugin } from '@/system/plugin';
|
|
16
|
+
import { isBehaveNode } from '@/util/isBehaveNode';
|
|
17
|
+
import type { Node } from 'reactflow';
|
|
18
|
+
import { GraphRunner } from './runner';
|
|
19
|
+
|
|
20
|
+
export * from './types';
|
|
21
|
+
export * from './client';
|
|
22
|
+
export * from './transport';
|
|
23
|
+
export * from './panel';
|
|
24
|
+
export * from './runner';
|
|
25
|
+
export * from './store';
|
|
26
|
+
export * from './session';
|
|
27
|
+
/**
|
|
28
|
+
* Options for the GraphRunner plugin
|
|
29
|
+
*/
|
|
30
|
+
export interface GraphRunnerClientPluginOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Preconfigured GraphRunner client instance.
|
|
33
|
+
* If provided, the plugin will use this client instead of creating a new one.
|
|
34
|
+
* Useful when the client is already connected via a custom transport (e.g., VSCode IPC).
|
|
35
|
+
*/
|
|
36
|
+
client?: GraphRunnerClient;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Preconfigured store instance.
|
|
40
|
+
* If provided, the plugin will use this store instead of creating a new one.
|
|
41
|
+
* Useful for sharing state with external components.
|
|
42
|
+
*/
|
|
43
|
+
store?: StoreApi<GraphRunnerClientStore>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Whether to skip automatic connection.
|
|
47
|
+
* Default: false (will attempt to connect if client is not provided or not connected)
|
|
48
|
+
*/
|
|
49
|
+
skipAutoConnect?: boolean;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Whether to add the menu item to the Window menu.
|
|
53
|
+
* Default: true
|
|
54
|
+
*/
|
|
55
|
+
addMenuItem?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Plugin initialization function
|
|
60
|
+
* Registers the GraphRunnerClient store and actions with the system
|
|
61
|
+
*/
|
|
62
|
+
export async function graphRunnerClientPluginLoader(
|
|
63
|
+
system: System,
|
|
64
|
+
options: GraphRunnerClientPluginOptions = {}
|
|
65
|
+
) {
|
|
66
|
+
// Use provided store or create a new one
|
|
67
|
+
const store = options.store ?? graphRunnerClientStoreFactory(system);
|
|
68
|
+
|
|
69
|
+
// If a preconfigured client is provided, set it in the store
|
|
70
|
+
if (options.client) {
|
|
71
|
+
store.getState().setClient(options.client);
|
|
72
|
+
|
|
73
|
+
// If client is already connected, update connection state
|
|
74
|
+
if (options.client.isConnected()) {
|
|
75
|
+
store.getState().setConnectionState('connected');
|
|
76
|
+
|
|
77
|
+
// Populate connection info if available
|
|
78
|
+
const connectionInfo = {
|
|
79
|
+
serverId: options.client.getServerId(),
|
|
80
|
+
userId: options.client.getUserId(),
|
|
81
|
+
authenticated: options.client.isAuthenticated(),
|
|
82
|
+
capabilities: options.client.getCachedCapabilities(),
|
|
83
|
+
sessionId: null // Session management is external when client is provided
|
|
84
|
+
};
|
|
85
|
+
store.getState().setConnectionInfo(connectionInfo);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Create and decorate actions
|
|
90
|
+
const runner = new GraphRunner(system, store);
|
|
91
|
+
system.decorate('runner', runner);
|
|
92
|
+
|
|
93
|
+
// Add toolbar buttons for graph execution control
|
|
94
|
+
system.toolbarStore.getState().addGroup({
|
|
95
|
+
id: 'graph-runner-controls',
|
|
96
|
+
label: 'Graph Runner',
|
|
97
|
+
buttons: [
|
|
98
|
+
<GraphRunnerButtons
|
|
99
|
+
key="graph-runner-buttons"
|
|
100
|
+
store={store}
|
|
101
|
+
onPlay={() => runner.play()}
|
|
102
|
+
onPause={() => runner.pause()}
|
|
103
|
+
onResume={() => runner.resume()}
|
|
104
|
+
onStep={() => runner.step()}
|
|
105
|
+
onStop={() => runner.stop()}
|
|
106
|
+
/>
|
|
107
|
+
]
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
system.hotKeyStore.getState().register({
|
|
111
|
+
action: 'PLAY',
|
|
112
|
+
description: 'Triggers playing the graph',
|
|
113
|
+
trigger: 'p',
|
|
114
|
+
handler: () => {
|
|
115
|
+
if (runner.store.getState().isExecuting) {
|
|
116
|
+
runner.stop();
|
|
117
|
+
} else {
|
|
118
|
+
runner.play();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Register the panel with TabLoader
|
|
124
|
+
system.tabLoader.register('graphRunner', () => {
|
|
125
|
+
return {
|
|
126
|
+
id: 'graphRunner',
|
|
127
|
+
closable: true,
|
|
128
|
+
title: 'Remote Graph Runner',
|
|
129
|
+
group: 'default',
|
|
130
|
+
content: () => (
|
|
131
|
+
<ErrorBoundary fallback={'Error loading Graph Runner panel'}>
|
|
132
|
+
<GraphRunnerPanel system={system} />
|
|
133
|
+
</ErrorBoundary>
|
|
134
|
+
)
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Add menu item to Window menu (unless disabled)
|
|
139
|
+
if (options.addMenuItem !== false) {
|
|
140
|
+
const menuStore = system.menubarStore;
|
|
141
|
+
const currentItems = menuStore.getState().items;
|
|
142
|
+
const windowMenu = currentItems.find((menu) => menu.name === 'window');
|
|
143
|
+
|
|
144
|
+
if (windowMenu) {
|
|
145
|
+
// Add the Graph Runner menu item to the Window menu
|
|
146
|
+
const newMenuItem = {
|
|
147
|
+
name: 'graphRunner',
|
|
148
|
+
render: function GraphRunnerMenuItem() {
|
|
149
|
+
return (
|
|
150
|
+
<MenuItemElement
|
|
151
|
+
onClick={() => system.tabStore.getState().openTab('graphRunner')}
|
|
152
|
+
key="graphRunner"
|
|
153
|
+
>
|
|
154
|
+
Remote Graph Runner
|
|
155
|
+
</MenuItemElement>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
menuStore
|
|
161
|
+
.getState()
|
|
162
|
+
.setSubMenuItems('window', [...windowMenu.items, newMenuItem]);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
system.pubsub.subscribe('node:added', (_, node: Node) => {
|
|
167
|
+
if (!isBehaveNode(node)) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const client = runner.store.getState().client;
|
|
172
|
+
const currentRunId = runner.store.getState().currentRunId;
|
|
173
|
+
const graphId = runner.store.getState().currentGraphId;
|
|
174
|
+
|
|
175
|
+
// Only send if we have an active run and realtime is enabled
|
|
176
|
+
if (client && currentRunId && graphId) {
|
|
177
|
+
const capabilities = runner.store.getState().connectionInfo.capabilities;
|
|
178
|
+
if (capabilities?.realtime) {
|
|
179
|
+
client.addNode(
|
|
180
|
+
currentRunId,
|
|
181
|
+
node.id,
|
|
182
|
+
node.data.type,
|
|
183
|
+
node.data as Record<string, unknown>,
|
|
184
|
+
node.position
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
system.pubsub.subscribe('edge:added', (_, edge) => {
|
|
191
|
+
const client = runner.store.getState().client;
|
|
192
|
+
const currentRunId = runner.store.getState().currentRunId;
|
|
193
|
+
const graphId = runner.store.getState().currentGraphId;
|
|
194
|
+
|
|
195
|
+
// Only send if we have an active run and realtime is enabled
|
|
196
|
+
if (client && currentRunId && graphId && edge.source && edge.target) {
|
|
197
|
+
const capabilities = runner.store.getState().connectionInfo.capabilities;
|
|
198
|
+
if (capabilities?.realtime) {
|
|
199
|
+
client.createLink(
|
|
200
|
+
currentRunId,
|
|
201
|
+
edge.source,
|
|
202
|
+
edge.sourceHandle || '',
|
|
203
|
+
edge.target,
|
|
204
|
+
edge.targetHandle || ''
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
system.pubsub.subscribe('edge:removed', (_, edge) => {
|
|
211
|
+
const client = runner.store.getState().client;
|
|
212
|
+
const currentRunId = runner.store.getState().currentRunId;
|
|
213
|
+
const graphId = runner.store.getState().currentGraphId;
|
|
214
|
+
|
|
215
|
+
// Only send if we have an active run and realtime is enabled
|
|
216
|
+
if (client && currentRunId && graphId && edge.source && edge.target) {
|
|
217
|
+
const capabilities = runner.store.getState().connectionInfo.capabilities;
|
|
218
|
+
if (capabilities?.realtime) {
|
|
219
|
+
client.removeLink(
|
|
220
|
+
currentRunId,
|
|
221
|
+
edge.source,
|
|
222
|
+
edge.sourceHandle || '',
|
|
223
|
+
edge.target,
|
|
224
|
+
edge.targetHandle || ''
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
system.pubsub.subscribe('node:removed', (_, node: Node) => {
|
|
231
|
+
if (!isBehaveNode(node)) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const client = runner.store.getState().client;
|
|
236
|
+
const currentRunId = runner.store.getState().currentRunId;
|
|
237
|
+
const graphId = runner.store.getState().currentGraphId;
|
|
238
|
+
|
|
239
|
+
// Only send if we have an active run and realtime is enabled
|
|
240
|
+
if (client && currentRunId && graphId) {
|
|
241
|
+
const capabilities = runner.store.getState().connectionInfo.capabilities;
|
|
242
|
+
if (capabilities?.realtime) {
|
|
243
|
+
client.removeNode(currentRunId, node.id);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
if (!options.skipAutoConnect) {
|
|
249
|
+
await runner.connect();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export const graphRunnerClientPlugin = plugin(graphRunnerClientPluginLoader, {
|
|
254
|
+
name: 'graph-runner-client'
|
|
255
|
+
});
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { useStore } from 'zustand';
|
|
3
|
+
import type { System } from '../../system/system';
|
|
4
|
+
import type { AuthCredentials } from './types';
|
|
5
|
+
import {
|
|
6
|
+
VscodeButton,
|
|
7
|
+
VscodeTextfield,
|
|
8
|
+
VscodeCheckbox,
|
|
9
|
+
VscodeSingleSelect,
|
|
10
|
+
VscodeOption,
|
|
11
|
+
VscodeLabel,
|
|
12
|
+
VscodeBadge,
|
|
13
|
+
VscodeTree,
|
|
14
|
+
VscodeTreeItem,
|
|
15
|
+
VscodeCollapsible
|
|
16
|
+
} from '@vscode-elements/react-elements';
|
|
17
|
+
import styles from './styles.module.css';
|
|
18
|
+
|
|
19
|
+
interface GraphRunnerPanelProps {
|
|
20
|
+
system: System;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const GraphRunnerPanel: React.FC<GraphRunnerPanelProps> = ({
|
|
24
|
+
system
|
|
25
|
+
}) => {
|
|
26
|
+
const store = system.runner.store;
|
|
27
|
+
|
|
28
|
+
const connectionState = useStore(store, (state) => state.connectionState);
|
|
29
|
+
const connectionConfig = useStore(store, (state) => state.connectionConfig);
|
|
30
|
+
const connectionInfo = useStore(store, (state) => state.connectionInfo);
|
|
31
|
+
const error = useStore(store, (state) => state.error);
|
|
32
|
+
const serverVariables = useStore(store, (state) => state.serverVariables);
|
|
33
|
+
const serverEvents = useStore(store, (state) => state.serverEvents);
|
|
34
|
+
const nodeTypes = useStore(store, (state) => state.nodeTypes);
|
|
35
|
+
const messageActivity = useStore(store, (state) => state.messageActivity);
|
|
36
|
+
const clearLogsOnRun = useStore(store, (state) => state.clearLogsOnRun);
|
|
37
|
+
const clearTracesOnRun = useStore(store, (state) => state.clearTracesOnRun);
|
|
38
|
+
const enableTracing = useStore(store, (state) => state.enableTracing);
|
|
39
|
+
|
|
40
|
+
const icons = useStore(system.legendStore, (state) => state.icons);
|
|
41
|
+
const defaultIcon = useStore(
|
|
42
|
+
system.legendStore,
|
|
43
|
+
(state) => state.defaultIcon
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const [url, setUrl] = useState(connectionConfig.url);
|
|
47
|
+
const [authType, setAuthType] = useState<'none' | 'bearer' | 'apiKey'>(
|
|
48
|
+
connectionConfig.auth.type
|
|
49
|
+
);
|
|
50
|
+
const [authToken, setAuthToken] = useState('');
|
|
51
|
+
const [autoReconnect, setAutoReconnect] = useState(
|
|
52
|
+
connectionConfig.autoReconnect
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const handleConnect = async () => {
|
|
56
|
+
const auth: AuthCredentials =
|
|
57
|
+
authType === 'bearer'
|
|
58
|
+
? { type: 'bearer', token: authToken }
|
|
59
|
+
: authType === 'apiKey'
|
|
60
|
+
? { type: 'apiKey', key: authToken }
|
|
61
|
+
: { type: 'none' };
|
|
62
|
+
|
|
63
|
+
store.getState().setConnectionConfig({ url, auth, autoReconnect });
|
|
64
|
+
|
|
65
|
+
await system.runner.connect();
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const handleDisconnect = async () => {
|
|
69
|
+
await system.runner.disconnect();
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const handleRefreshMetadata = async () => {
|
|
73
|
+
await system.runner.refreshMetadata();
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const handleClearMessages = () => {
|
|
77
|
+
store.getState().clearMessageActivity();
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const isConnected = connectionState === 'connected';
|
|
81
|
+
const isConnecting =
|
|
82
|
+
connectionState === 'connecting' || connectionState === 'authenticating';
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div className={styles.panel}>
|
|
86
|
+
{/* Scrollable Content Container */}
|
|
87
|
+
<div className={styles.scrollContainer}>
|
|
88
|
+
<h3 className={styles.title}>
|
|
89
|
+
Remote Graph Runner
|
|
90
|
+
<VscodeBadge variant="tab-header-counter">
|
|
91
|
+
{isConnected ? 'Connected' : 'Disconnected'}
|
|
92
|
+
</VscodeBadge>
|
|
93
|
+
</h3>
|
|
94
|
+
|
|
95
|
+
<div>
|
|
96
|
+
{/* Connection Form */}
|
|
97
|
+
<VscodeCollapsible heading="Connection Settings">
|
|
98
|
+
<div className={styles.connectionForm}>
|
|
99
|
+
<div>
|
|
100
|
+
<VscodeLabel>Server URL</VscodeLabel>
|
|
101
|
+
<VscodeTextfield
|
|
102
|
+
value={url}
|
|
103
|
+
onChange={(e: any) => setUrl(e.target.value)}
|
|
104
|
+
placeholder="ws://localhost:8080"
|
|
105
|
+
disabled={isConnected || isConnecting}
|
|
106
|
+
className={styles.formField}
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div>
|
|
111
|
+
<VscodeLabel>Authentication</VscodeLabel>
|
|
112
|
+
<VscodeSingleSelect
|
|
113
|
+
value={authType}
|
|
114
|
+
onChange={(e: any) =>
|
|
115
|
+
setAuthType(e.target.value as 'none' | 'bearer' | 'apiKey')
|
|
116
|
+
}
|
|
117
|
+
disabled={isConnected || isConnecting}
|
|
118
|
+
className={styles.formField}
|
|
119
|
+
>
|
|
120
|
+
<VscodeOption value="none">None</VscodeOption>
|
|
121
|
+
<VscodeOption value="bearer">Bearer Token</VscodeOption>
|
|
122
|
+
<VscodeOption value="apiKey">API Key</VscodeOption>
|
|
123
|
+
</VscodeSingleSelect>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
{authType !== 'none' && (
|
|
127
|
+
<div>
|
|
128
|
+
<VscodeLabel>
|
|
129
|
+
{authType === 'bearer' ? 'Token' : 'API Key'}
|
|
130
|
+
</VscodeLabel>
|
|
131
|
+
<VscodeTextfield
|
|
132
|
+
type="password"
|
|
133
|
+
value={authToken}
|
|
134
|
+
onChange={(e: any) => setAuthToken(e.target.value)}
|
|
135
|
+
placeholder={
|
|
136
|
+
authType === 'bearer'
|
|
137
|
+
? 'Enter bearer token'
|
|
138
|
+
: 'Enter API key'
|
|
139
|
+
}
|
|
140
|
+
disabled={isConnected || isConnecting}
|
|
141
|
+
className={styles.formField}
|
|
142
|
+
/>
|
|
143
|
+
</div>
|
|
144
|
+
)}
|
|
145
|
+
|
|
146
|
+
<VscodeCheckbox
|
|
147
|
+
checked={autoReconnect}
|
|
148
|
+
onChange={(e: any) => setAutoReconnect(e.target.checked)}
|
|
149
|
+
disabled={isConnected || isConnecting}
|
|
150
|
+
>
|
|
151
|
+
Auto-reconnect
|
|
152
|
+
</VscodeCheckbox>
|
|
153
|
+
|
|
154
|
+
<div className={styles.section}>
|
|
155
|
+
<h4 className={styles.sectionTitle}>Execution Preferences</h4>
|
|
156
|
+
<VscodeCheckbox
|
|
157
|
+
checked={enableTracing}
|
|
158
|
+
onChange={(e: any) =>
|
|
159
|
+
store.getState().setEnableTracing(e.target.checked)
|
|
160
|
+
}
|
|
161
|
+
>
|
|
162
|
+
Enable execution tracing
|
|
163
|
+
</VscodeCheckbox>
|
|
164
|
+
<VscodeCheckbox
|
|
165
|
+
checked={clearLogsOnRun}
|
|
166
|
+
onChange={(e: any) =>
|
|
167
|
+
store.getState().setClearLogsOnRun(e.target.checked)
|
|
168
|
+
}
|
|
169
|
+
>
|
|
170
|
+
Clear logs on new run
|
|
171
|
+
</VscodeCheckbox>
|
|
172
|
+
<VscodeCheckbox
|
|
173
|
+
checked={clearTracesOnRun}
|
|
174
|
+
onChange={(e: any) =>
|
|
175
|
+
store.getState().setClearTracesOnRun(e.target.checked)
|
|
176
|
+
}
|
|
177
|
+
>
|
|
178
|
+
Clear traces on new run
|
|
179
|
+
</VscodeCheckbox>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<div className={styles.buttonGroup}>
|
|
183
|
+
{!isConnected && (
|
|
184
|
+
<VscodeButton
|
|
185
|
+
onClick={handleConnect}
|
|
186
|
+
disabled={isConnecting || !url}
|
|
187
|
+
className={styles.button}
|
|
188
|
+
>
|
|
189
|
+
{isConnecting ? 'Connecting...' : 'Connect'}
|
|
190
|
+
</VscodeButton>
|
|
191
|
+
)}
|
|
192
|
+
{isConnected && (
|
|
193
|
+
<>
|
|
194
|
+
<VscodeButton
|
|
195
|
+
onClick={handleDisconnect}
|
|
196
|
+
className={styles.button}
|
|
197
|
+
>
|
|
198
|
+
Disconnect
|
|
199
|
+
</VscodeButton>
|
|
200
|
+
<VscodeButton
|
|
201
|
+
onClick={handleRefreshMetadata}
|
|
202
|
+
className={styles.button}
|
|
203
|
+
>
|
|
204
|
+
Refresh
|
|
205
|
+
</VscodeButton>
|
|
206
|
+
</>
|
|
207
|
+
)}
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
</VscodeCollapsible>
|
|
211
|
+
|
|
212
|
+
{/* Error Display */}
|
|
213
|
+
{error && (
|
|
214
|
+
<div className={styles.errorBox}>
|
|
215
|
+
<strong>Error:</strong> {error}
|
|
216
|
+
</div>
|
|
217
|
+
)}
|
|
218
|
+
|
|
219
|
+
{/* Connection Info */}
|
|
220
|
+
{isConnected && (
|
|
221
|
+
<VscodeCollapsible heading="Status">
|
|
222
|
+
<div className={styles.infoBox}>
|
|
223
|
+
<div>
|
|
224
|
+
<strong>Status:</strong> Connected
|
|
225
|
+
</div>
|
|
226
|
+
{connectionInfo.serverId && (
|
|
227
|
+
<div className={styles.infoField}>
|
|
228
|
+
<strong>Server:</strong> {connectionInfo.serverId}
|
|
229
|
+
</div>
|
|
230
|
+
)}
|
|
231
|
+
{connectionInfo.sessionId && (
|
|
232
|
+
<div className={styles.infoField}>
|
|
233
|
+
<strong>Session:</strong> {connectionInfo.sessionId}
|
|
234
|
+
</div>
|
|
235
|
+
)}
|
|
236
|
+
{connectionInfo.userId && (
|
|
237
|
+
<div className={styles.infoField}>
|
|
238
|
+
<strong>User:</strong> {connectionInfo.userId}
|
|
239
|
+
</div>
|
|
240
|
+
)}
|
|
241
|
+
{connectionInfo.capabilities && (
|
|
242
|
+
<div className={styles.infoField}>
|
|
243
|
+
<strong>Capabilities:</strong>{' '}
|
|
244
|
+
{Object.entries(connectionInfo.capabilities)
|
|
245
|
+
.filter(([_, v]) => v === true)
|
|
246
|
+
.map(([k]) => k)
|
|
247
|
+
.join(', ')}
|
|
248
|
+
</div>
|
|
249
|
+
)}
|
|
250
|
+
</div>
|
|
251
|
+
</VscodeCollapsible>
|
|
252
|
+
)}
|
|
253
|
+
{isConnected && (
|
|
254
|
+
<>
|
|
255
|
+
<VscodeCollapsible heading="Variables">
|
|
256
|
+
<VscodeBadge slot="decorations">
|
|
257
|
+
{serverVariables.length}
|
|
258
|
+
</VscodeBadge>
|
|
259
|
+
<VscodeTree>
|
|
260
|
+
{serverVariables.map((variable) => {
|
|
261
|
+
const Icon = icons[variable.valueTypeName] ?? defaultIcon;
|
|
262
|
+
const IconComponent = Icon as React.FC<{ slot?: string }>;
|
|
263
|
+
return (
|
|
264
|
+
<VscodeTreeItem key={variable.name}>
|
|
265
|
+
<IconComponent slot="icon-leaf" />
|
|
266
|
+
<span>{variable.name}</span>
|
|
267
|
+
</VscodeTreeItem>
|
|
268
|
+
);
|
|
269
|
+
})}
|
|
270
|
+
</VscodeTree>
|
|
271
|
+
</VscodeCollapsible>
|
|
272
|
+
|
|
273
|
+
<VscodeCollapsible heading="Events">
|
|
274
|
+
<VscodeBadge slot="decorations">
|
|
275
|
+
{serverEvents.length}
|
|
276
|
+
</VscodeBadge>
|
|
277
|
+
|
|
278
|
+
<div className={styles.tabPanelGap}>
|
|
279
|
+
{serverEvents.length === 0 ? (
|
|
280
|
+
<p className={styles.emptyMessage}>
|
|
281
|
+
No server events available
|
|
282
|
+
</p>
|
|
283
|
+
) : (
|
|
284
|
+
<VscodeTree>
|
|
285
|
+
{serverEvents.map((event) => (
|
|
286
|
+
<VscodeTreeItem key={event.name}>
|
|
287
|
+
<span className={styles.treeItemTitle}>
|
|
288
|
+
{event.name}
|
|
289
|
+
</span>
|
|
290
|
+
<VscodeTreeItem key={event.name}>
|
|
291
|
+
<span slot="description">{event.description}</span>
|
|
292
|
+
{event.payloadSchema != null ? (
|
|
293
|
+
<pre className={styles.codeBlock}>
|
|
294
|
+
{JSON.stringify(event.payloadSchema, null, 2)}
|
|
295
|
+
</pre>
|
|
296
|
+
) : null}
|
|
297
|
+
</VscodeTreeItem>
|
|
298
|
+
</VscodeTreeItem>
|
|
299
|
+
))}
|
|
300
|
+
</VscodeTree>
|
|
301
|
+
)}
|
|
302
|
+
</div>
|
|
303
|
+
</VscodeCollapsible>
|
|
304
|
+
|
|
305
|
+
<VscodeCollapsible heading="Nodes">
|
|
306
|
+
<VscodeBadge slot="decorations">{nodeTypes.length}</VscodeBadge>
|
|
307
|
+
<div className={styles.tabPanelGap}>
|
|
308
|
+
{nodeTypes.length === 0 ? (
|
|
309
|
+
<p className={styles.emptyMessage}>
|
|
310
|
+
No node types available
|
|
311
|
+
</p>
|
|
312
|
+
) : (
|
|
313
|
+
<VscodeTree>
|
|
314
|
+
{nodeTypes.map((node) => (
|
|
315
|
+
<VscodeTreeItem>
|
|
316
|
+
{node.type}
|
|
317
|
+
|
|
318
|
+
<span slot="description">{node.category}</span>
|
|
319
|
+
</VscodeTreeItem>
|
|
320
|
+
))}
|
|
321
|
+
</VscodeTree>
|
|
322
|
+
)}
|
|
323
|
+
</div>
|
|
324
|
+
</VscodeCollapsible>
|
|
325
|
+
<VscodeCollapsible heading="Message Activity">
|
|
326
|
+
<VscodeBadge slot="decorations">
|
|
327
|
+
{messageActivity.length}
|
|
328
|
+
</VscodeBadge>
|
|
329
|
+
<div className={styles.tabPanelGapLarge}>
|
|
330
|
+
<div className={styles.messagesToolbar}>
|
|
331
|
+
<div className={styles.messagesCount}>
|
|
332
|
+
{messageActivity.length} message
|
|
333
|
+
{messageActivity.length !== 1 ? 's' : ''}
|
|
334
|
+
</div>
|
|
335
|
+
{messageActivity.length > 0 && (
|
|
336
|
+
<VscodeButton onClick={handleClearMessages}>
|
|
337
|
+
Clear
|
|
338
|
+
</VscodeButton>
|
|
339
|
+
)}
|
|
340
|
+
</div>
|
|
341
|
+
{messageActivity.length === 0 ? (
|
|
342
|
+
<p className={styles.emptyMessage}>No messages yet</p>
|
|
343
|
+
) : (
|
|
344
|
+
<div className={styles.tabPanelGap}>
|
|
345
|
+
{messageActivity.map((activity) => {
|
|
346
|
+
const time = new Date(
|
|
347
|
+
activity.timestamp
|
|
348
|
+
).toLocaleTimeString();
|
|
349
|
+
const directionColor =
|
|
350
|
+
activity.direction === 'sent'
|
|
351
|
+
? 'var(--vscode-gitDecoration-modifiedResourceForeground)'
|
|
352
|
+
: 'var(--vscode-gitDecoration-addedResourceForeground)';
|
|
353
|
+
|
|
354
|
+
return (
|
|
355
|
+
<div key={activity.id} className={styles.messageCard}>
|
|
356
|
+
<div className={styles.messageHeader}>
|
|
357
|
+
<div className={styles.messageDirection}>
|
|
358
|
+
<span
|
|
359
|
+
className={styles.messageDirectionIcon}
|
|
360
|
+
style={{ color: directionColor }}
|
|
361
|
+
>
|
|
362
|
+
{activity.direction === 'sent' ? '→' : '←'}
|
|
363
|
+
</span>
|
|
364
|
+
<span className={styles.messageType}>
|
|
365
|
+
{activity.message.type}
|
|
366
|
+
</span>
|
|
367
|
+
</div>
|
|
368
|
+
<span className={styles.messageTime}>{time}</span>
|
|
369
|
+
</div>
|
|
370
|
+
<pre className={styles.messageContent}>
|
|
371
|
+
{JSON.stringify(activity.message, null, 2)}
|
|
372
|
+
</pre>
|
|
373
|
+
</div>
|
|
374
|
+
);
|
|
375
|
+
})}
|
|
376
|
+
</div>
|
|
377
|
+
)}
|
|
378
|
+
</div>
|
|
379
|
+
</VscodeCollapsible>
|
|
380
|
+
</>
|
|
381
|
+
)}
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
</div>
|
|
385
|
+
);
|
|
386
|
+
};
|