@flowdrop/flowdrop 1.15.0 → 2.0.0-beta.2
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/CHANGELOG.md +508 -0
- package/MIGRATION-2.0.md +629 -0
- package/README.md +23 -23
- package/dist/adapters/WorkflowAdapter.d.ts +1 -1
- package/dist/adapters/WorkflowAdapter.js +14 -8
- package/dist/adapters/agentspec/AgentSpecAdapter.js +7 -7
- package/dist/api/enhanced-client.js +6 -11
- package/dist/chat/batchFeedback.d.ts +39 -0
- package/dist/chat/batchFeedback.js +51 -0
- package/dist/commands/executor.js +15 -1
- package/dist/commands/storeIntegration.svelte.d.ts +4 -1
- package/dist/commands/storeIntegration.svelte.js +26 -21
- package/dist/commands/types.d.ts +2 -0
- package/dist/components/App.svelte +163 -192
- package/dist/components/App.svelte.d.ts +47 -8
- package/dist/components/ConfigForm.svelte +77 -49
- package/dist/components/ConfigModal.svelte +7 -2
- package/dist/components/ConnectionLine.svelte +4 -2
- package/dist/components/Navbar.svelte +61 -1
- package/dist/components/NodeSidebar.svelte +27 -45
- package/dist/components/NodeStatusOverlay.svelte +94 -6
- package/dist/components/NodeSwapPicker.svelte +10 -8
- package/dist/components/PipelineStatus.svelte +22 -68
- package/dist/components/PipelineStatus.svelte.d.ts +3 -0
- package/dist/components/PortCoordinateTracker.svelte +5 -6
- package/dist/components/SchemaForm.stories.svelte +1 -3
- package/dist/components/SchemaForm.svelte +22 -27
- package/dist/components/SchemaForm.svelte.d.ts +0 -8
- package/dist/components/SettingsModal.svelte +8 -3
- package/dist/components/SettingsPanel.svelte +20 -4
- package/dist/components/SwapMappingEditor.svelte +67 -49
- package/dist/components/SwapMappingEditor.svelte.d.ts +0 -2
- package/dist/components/UniversalNode.svelte +9 -7
- package/dist/components/WorkflowEditor.svelte +121 -111
- package/dist/components/WorkflowEditor.svelte.d.ts +21 -10
- package/dist/components/chat/AIChatPanel.svelte +98 -89
- package/dist/components/chat/AIChatPanel.svelte.d.ts +0 -4
- package/dist/components/chat/CommandPreview.svelte +2 -1
- package/dist/components/console/CommandConsole.svelte +7 -5
- package/dist/components/console/ConsoleAutocomplete.svelte +10 -11
- package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +6 -0
- package/dist/components/console/ConsoleInput.svelte +15 -6
- package/dist/components/console/ConsoleOutput.svelte +2 -1
- package/dist/components/form/FormArray.svelte +5 -9
- package/dist/components/form/FormArray.svelte.d.ts +2 -1
- package/dist/components/form/FormAutocomplete.svelte +16 -15
- package/dist/components/form/FormField.svelte +4 -2
- package/dist/components/form/FormFieldLight.svelte +34 -3
- package/dist/components/form/FormFieldLight.svelte.d.ts +12 -0
- package/dist/components/form/FormMarkdownEditor.svelte +9 -4
- package/dist/components/form/FormRangeField.svelte +1 -0
- package/dist/components/form/FormTemplateEditor.svelte +11 -3
- package/dist/components/form/FormToggle.svelte +5 -12
- package/dist/components/form/FormToggle.svelte.d.ts +4 -2
- package/dist/components/form/FormUISchemaRenderer.svelte +3 -1
- package/dist/components/form/templateAutocomplete.js +1 -5
- package/dist/components/form/types.d.ts +1 -14
- package/dist/components/interrupt/FormPrompt.svelte +3 -2
- package/dist/components/interrupt/InterruptBubble.svelte +25 -17
- package/dist/components/interrupt/ReviewPrompt.svelte +10 -3
- package/dist/components/interrupt/TextInputPrompt.svelte +2 -1
- package/dist/components/layouts/MainLayout.svelte +20 -13
- package/dist/components/layouts/MainLayout.svelte.d.ts +4 -0
- package/dist/components/nodes/AtomNode.svelte +17 -5
- package/dist/components/nodes/GatewayNode.svelte +19 -10
- package/dist/components/nodes/IdeaNode.svelte +7 -0
- package/dist/components/nodes/SimpleNode.svelte +11 -6
- package/dist/components/nodes/SquareNode.svelte +15 -8
- package/dist/components/nodes/TerminalNode.svelte +9 -4
- package/dist/components/nodes/ToolNode.svelte +7 -1
- package/dist/components/nodes/WorkflowNode.svelte +16 -7
- package/dist/components/playground/ChatInput.svelte +11 -14
- package/dist/components/playground/ChatPanel.svelte +6 -49
- package/dist/components/playground/ChatPanel.svelte.d.ts +0 -14
- package/dist/components/playground/ControlPanel.svelte +134 -123
- package/dist/components/playground/ControlPanel.svelte.d.ts +3 -0
- package/dist/components/playground/ExecutionLogs.svelte +11 -9
- package/dist/components/playground/InputCollector.svelte +11 -9
- package/dist/components/playground/MessageStream.svelte +17 -23
- package/dist/components/playground/PipelineKanbanView.svelte +69 -8
- package/dist/components/playground/PipelineKanbanView.svelte.d.ts +2 -0
- package/dist/components/playground/PipelinePanel.svelte +31 -8
- package/dist/components/playground/PipelinePanel.svelte.d.ts +2 -0
- package/dist/components/playground/PipelineTableView.svelte +188 -44
- package/dist/components/playground/PipelineTableView.svelte.d.ts +2 -0
- package/dist/components/playground/Playground.svelte +154 -105
- package/dist/components/playground/Playground.svelte.d.ts +5 -0
- package/dist/components/playground/PlaygroundApp.svelte +11 -1
- package/dist/components/playground/PlaygroundApp.svelte.d.ts +6 -0
- package/dist/components/playground/PlaygroundModal.svelte +18 -3
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +6 -0
- package/dist/components/playground/PlaygroundStudio.svelte +40 -32
- package/dist/components/playground/PlaygroundStudio.svelte.d.ts +6 -0
- package/dist/components/playground/SessionManager.svelte +9 -12
- package/dist/components/playground/pipelineViewUtils.svelte.d.ts +30 -1
- package/dist/components/playground/pipelineViewUtils.svelte.js +40 -3
- package/dist/config/endpoints.d.ts +23 -7
- package/dist/config/endpoints.js +30 -10
- package/dist/core/index.d.ts +5 -6
- package/dist/core/index.js +8 -12
- package/dist/display/index.d.ts +6 -3
- package/dist/display/index.js +7 -5
- package/dist/editor/index.d.ts +20 -21
- package/dist/editor/index.js +26 -36
- package/dist/form/code.d.ts +25 -15
- package/dist/form/code.js +44 -41
- package/dist/form/fieldRegistry.d.ts +17 -13
- package/dist/form/fieldRegistry.js +32 -12
- package/dist/form/full.d.ts +19 -14
- package/dist/form/full.js +26 -28
- package/dist/form/index.d.ts +3 -4
- package/dist/form/index.js +6 -5
- package/dist/form/markdown.d.ts +13 -8
- package/dist/form/markdown.js +22 -23
- package/dist/helpers/proximityConnect.d.ts +3 -2
- package/dist/helpers/proximityConnect.js +2 -5
- package/dist/helpers/workflowEditorHelper.d.ts +14 -5
- package/dist/helpers/workflowEditorHelper.js +28 -25
- package/dist/index.d.ts +28 -24
- package/dist/index.js +27 -50
- package/dist/messages/defaults.d.ts +2 -5
- package/dist/messages/defaults.js +3 -6
- package/dist/messages/index.d.ts +0 -1
- package/dist/messages/index.js +0 -1
- package/dist/mocks/app-forms.d.ts +6 -2
- package/dist/mocks/app-forms.js +11 -4
- package/dist/openapi/v1/openapi.yaml +3 -3
- package/dist/playground/index.d.ts +4 -5
- package/dist/playground/index.js +4 -32
- package/dist/playground/mount.d.ts +25 -0
- package/dist/playground/mount.js +50 -20
- package/dist/registry/{BaseRegistry.d.ts → BaseRegistry.svelte.d.ts} +22 -1
- package/dist/registry/{BaseRegistry.js → BaseRegistry.svelte.js} +37 -1
- package/dist/registry/builtinFormats.d.ts +9 -18
- package/dist/registry/builtinFormats.js +9 -39
- package/dist/registry/builtinNodeTypes.d.ts +53 -0
- package/dist/registry/builtinNodeTypes.js +67 -0
- package/dist/registry/builtinNodes.d.ts +2 -64
- package/dist/registry/builtinNodes.js +7 -103
- package/dist/registry/index.d.ts +3 -4
- package/dist/registry/index.js +4 -6
- package/dist/registry/nodeComponentRegistry.d.ts +182 -15
- package/dist/registry/nodeComponentRegistry.js +235 -17
- package/dist/registry/workflowFormatRegistry.d.ts +14 -9
- package/dist/registry/workflowFormatRegistry.js +24 -8
- package/dist/{schema → schemas}/index.d.ts +2 -2
- package/dist/{schema → schemas}/index.js +2 -2
- package/dist/schemas/v1/workflow.schema.json +3 -3
- package/dist/services/agentSpecExecutionService.d.ts +0 -2
- package/dist/services/agentSpecExecutionService.js +0 -3
- package/dist/services/apiVariableService.d.ts +2 -1
- package/dist/services/apiVariableService.js +16 -47
- package/dist/services/autoSaveService.d.ts +7 -0
- package/dist/services/autoSaveService.js +6 -4
- package/dist/services/categoriesApi.js +3 -6
- package/dist/services/chatService.d.ts +9 -4
- package/dist/services/chatService.js +23 -28
- package/dist/services/draftStorage.d.ts +129 -13
- package/dist/services/draftStorage.js +185 -37
- package/dist/services/dynamicSchemaService.d.ts +2 -1
- package/dist/services/dynamicSchemaService.js +5 -22
- package/dist/services/globalSave.d.ts +13 -12
- package/dist/services/globalSave.js +29 -51
- package/dist/services/historyService.d.ts +9 -3
- package/dist/services/historyService.js +9 -3
- package/dist/services/interruptService.d.ts +15 -9
- package/dist/services/interruptService.js +35 -37
- package/dist/services/nodeExecutionService.d.ts +18 -3
- package/dist/services/nodeExecutionService.js +71 -45
- package/dist/services/playgroundService.d.ts +16 -10
- package/dist/services/playgroundService.js +42 -43
- package/dist/services/portConfigApi.js +3 -6
- package/dist/services/settingsService.d.ts +9 -4
- package/dist/services/settingsService.js +23 -12
- package/dist/services/variableService.d.ts +2 -1
- package/dist/services/variableService.js +2 -2
- package/dist/services/workflowStorage.js +6 -6
- package/dist/stores/apiContext.d.ts +56 -0
- package/dist/stores/apiContext.js +80 -0
- package/dist/stores/categoriesStore.svelte.d.ts +28 -23
- package/dist/stores/categoriesStore.svelte.js +69 -64
- package/dist/stores/getInstance.svelte.d.ts +39 -0
- package/dist/stores/getInstance.svelte.js +65 -0
- package/dist/stores/historyStore.svelte.d.ts +77 -93
- package/dist/stores/historyStore.svelte.js +134 -160
- package/dist/stores/instanceContainer.svelte.d.ts +111 -0
- package/dist/stores/instanceContainer.svelte.js +114 -0
- package/dist/stores/interruptStore.svelte.d.ts +112 -82
- package/dist/stores/interruptStore.svelte.js +253 -226
- package/dist/stores/pipelinePanelStore.svelte.d.ts +27 -3
- package/dist/stores/pipelinePanelStore.svelte.js +61 -14
- package/dist/stores/playgroundStore.svelte.d.ts +169 -222
- package/dist/stores/playgroundStore.svelte.js +513 -580
- package/dist/stores/portCoordinateStore.svelte.d.ts +57 -51
- package/dist/stores/portCoordinateStore.svelte.js +109 -98
- package/dist/stores/settingsStore.svelte.d.ts +4 -1
- package/dist/stores/settingsStore.svelte.js +47 -12
- package/dist/stores/workflowStore.svelte.d.ts +178 -213
- package/dist/stores/workflowStore.svelte.js +449 -501
- package/dist/stories/EdgeDecorator.svelte +5 -2
- package/dist/stories/NodeDecorator.svelte +5 -3
- package/dist/svelte-app.d.ts +60 -10
- package/dist/svelte-app.js +159 -54
- package/dist/types/auth.d.ts +9 -51
- package/dist/types/auth.js +4 -54
- package/dist/types/events.d.ts +6 -3
- package/dist/types/index.d.ts +37 -5
- package/dist/types/index.js +0 -1
- package/dist/types/navbar.d.ts +7 -0
- package/dist/types/playground.d.ts +18 -3
- package/dist/types/settings.d.ts +13 -0
- package/dist/types/settings.js +1 -0
- package/dist/utils/colors.d.ts +47 -21
- package/dist/utils/colors.js +69 -68
- package/dist/utils/connections.d.ts +9 -15
- package/dist/utils/connections.js +13 -32
- package/dist/utils/duration.d.ts +13 -0
- package/dist/utils/duration.js +45 -0
- package/dist/utils/edgeStyling.js +9 -5
- package/dist/utils/fetchWithAuth.d.ts +36 -15
- package/dist/utils/fetchWithAuth.js +53 -23
- package/dist/utils/icons.d.ts +5 -2
- package/dist/utils/icons.js +6 -5
- package/dist/utils/nodeSwap.d.ts +6 -2
- package/dist/utils/nodeSwap.js +62 -126
- package/dist/utils/nodeTypes.d.ts +17 -8
- package/dist/utils/nodeTypes.js +27 -20
- package/dist/utils/performanceUtils.js +7 -0
- package/package.json +7 -5
- package/dist/messages/deprecation.d.ts +0 -20
- package/dist/messages/deprecation.js +0 -33
- package/dist/registry/plugin.d.ts +0 -215
- package/dist/registry/plugin.js +0 -249
- package/dist/services/api.d.ts +0 -129
- package/dist/services/api.js +0 -217
|
@@ -21,23 +21,19 @@
|
|
|
21
21
|
getEditorSettings,
|
|
22
22
|
getBehaviorSettings
|
|
23
23
|
} from '../stores/settingsStore.svelte.js';
|
|
24
|
-
import type {
|
|
25
|
-
WorkflowNode as WorkflowNodeType,
|
|
26
|
-
NodeMetadata,
|
|
27
|
-
Workflow,
|
|
28
|
-
WorkflowEdge
|
|
29
|
-
} from '../types/index.js';
|
|
24
|
+
import type { WorkflowNode as WorkflowNodeType, Workflow, WorkflowEdge } from '../types/index.js';
|
|
30
25
|
import CanvasBanner from './CanvasBanner.svelte';
|
|
31
26
|
import CanvasController from './CanvasController.svelte';
|
|
32
27
|
import FlowDropZone from './FlowDropZone.svelte';
|
|
33
28
|
import EdgeRefresher from './EdgeRefresher.svelte';
|
|
34
29
|
import { tick, untrack } from 'svelte';
|
|
35
30
|
import type { EndpointConfig } from '../config/endpoints.js';
|
|
31
|
+
import type { AuthProvider } from '../types/auth.js';
|
|
36
32
|
import ConnectionLine from './ConnectionLine.svelte';
|
|
37
33
|
import FlowDropEdge from './FlowDropEdge.svelte';
|
|
38
34
|
import { m } from '../messages/index.js';
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
35
|
+
import { provideInstance } from '../stores/getInstance.svelte.js';
|
|
36
|
+
import type { FlowDropInstance } from '../stores/instanceContainer.svelte.js';
|
|
41
37
|
import UniversalNode from './UniversalNode.svelte';
|
|
42
38
|
import {
|
|
43
39
|
EdgeStylingHelper,
|
|
@@ -57,34 +53,52 @@
|
|
|
57
53
|
type ProximityEdgeCandidate
|
|
58
54
|
} from '../helpers/proximityConnect.js';
|
|
59
55
|
import PortCoordinateTracker from './PortCoordinateTracker.svelte';
|
|
60
|
-
import { getPortCoordinateSnapshot } from '../stores/portCoordinateStore.svelte.js';
|
|
61
56
|
import { logger } from '../utils/logger.js';
|
|
62
57
|
import { validateWorkflowData } from '../utils/validation.js';
|
|
63
58
|
import { createEditorStateMachine } from '../stores/editorStateMachine.svelte.js';
|
|
64
59
|
import Icon from '@iconify/svelte';
|
|
60
|
+
import { DEV } from 'esm-env';
|
|
65
61
|
|
|
66
62
|
interface Props {
|
|
67
|
-
nodes?: NodeMetadata[];
|
|
68
63
|
endpointConfig?: EndpointConfig;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
isConfigSidebarOpen?: boolean;
|
|
72
|
-
selectedNodeForConfig?: WorkflowNodeType | null;
|
|
64
|
+
/** Auth provider applied to this instance's API requests. */
|
|
65
|
+
authProvider?: AuthProvider;
|
|
73
66
|
openConfigSidebar?: (node: WorkflowNodeType) => void;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Editor interaction mode. `'edit'` allows node drag/connect/select and
|
|
69
|
+
* proximity-connect; `'readonly'` and `'locked'` disable all canvas
|
|
70
|
+
* editing (they behave identically today — see App's `mode` prop for the
|
|
71
|
+
* full matrix). Replaces the former `readOnly` + `lockWorkflow` booleans.
|
|
72
|
+
* @default 'edit'
|
|
73
|
+
*/
|
|
74
|
+
mode?: 'edit' | 'readonly' | 'locked';
|
|
79
75
|
// Pipeline ID for fetching node execution info from jobs
|
|
80
76
|
pipelineId?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Increments to force a re-fetch of node execution info from the server.
|
|
79
|
+
* Used by parents (e.g. PipelineStatus) to push poll ticks / chat-message
|
|
80
|
+
* arrivals down to the canvas without owning a separate status channel.
|
|
81
|
+
*/
|
|
82
|
+
refreshTrigger?: number;
|
|
81
83
|
// Console toggle
|
|
82
84
|
consoleOpen?: boolean;
|
|
83
85
|
onToggleConsole?: () => void;
|
|
86
|
+
/** Per-instance state container (created by mount functions). Defaults to the page-default instance. */
|
|
87
|
+
instance?: FlowDropInstance;
|
|
84
88
|
}
|
|
85
89
|
|
|
86
90
|
let props: Props = $props();
|
|
87
91
|
|
|
92
|
+
// Resolve (and provide to children) the per-instance state container.
|
|
93
|
+
// Must run during component init — provideInstance reads/sets Svelte context.
|
|
94
|
+
// The instance never changes for a mounted component, so capturing it once is correct.
|
|
95
|
+
// svelte-ignore state_referenced_locally
|
|
96
|
+
const fd = provideInstance(props.instance);
|
|
97
|
+
|
|
98
|
+
// `mode` is the public API; the canvas only needs to know whether editing is
|
|
99
|
+
// enabled. 'readonly' and 'locked' both disable interaction identically.
|
|
100
|
+
const canvasEditable = $derived((props.mode ?? 'edit') === 'edit');
|
|
101
|
+
|
|
88
102
|
// ---------------------------------------------------------------------------
|
|
89
103
|
// Editor State Machine
|
|
90
104
|
// Centralizes reactive guards — replaces scattered boolean flags
|
|
@@ -93,7 +107,7 @@
|
|
|
93
107
|
const machine = createEditorStateMachine();
|
|
94
108
|
|
|
95
109
|
// Dev-mode transition logging
|
|
96
|
-
if (
|
|
110
|
+
if (DEV) {
|
|
97
111
|
machine.onTransition((from, event, to) => {
|
|
98
112
|
logger.debug(`[EditorFSM] ${from} --${event}--> ${to}`);
|
|
99
113
|
});
|
|
@@ -122,7 +136,7 @@
|
|
|
122
136
|
* Key for SvelteFlow component — changes when workflow ID changes.
|
|
123
137
|
* Forces SvelteFlow to remount with fresh state, allowing fitView to work correctly.
|
|
124
138
|
*/
|
|
125
|
-
let svelteFlowKey = $derived(
|
|
139
|
+
let svelteFlowKey = $derived(fd.workflow.current?.id ?? 'default');
|
|
126
140
|
|
|
127
141
|
/**
|
|
128
142
|
* Derive snap grid configuration from editor settings
|
|
@@ -164,14 +178,14 @@
|
|
|
164
178
|
// Helper: sync current flowNodes/flowEdges back to the global store
|
|
165
179
|
// ---------------------------------------------------------------------------
|
|
166
180
|
function syncFlowToStore(): void {
|
|
167
|
-
const storeValue = untrack(() =>
|
|
181
|
+
const storeValue = untrack(() => fd.workflow.current);
|
|
168
182
|
if (!storeValue) return;
|
|
169
183
|
const updatedWorkflow = WorkflowOperationsHelper.updateWorkflow(
|
|
170
184
|
storeValue,
|
|
171
185
|
flowNodes,
|
|
172
186
|
flowEdges
|
|
173
187
|
);
|
|
174
|
-
|
|
188
|
+
fd.workflow.updateWorkflow(updatedWorkflow);
|
|
175
189
|
}
|
|
176
190
|
|
|
177
191
|
// ---------------------------------------------------------------------------
|
|
@@ -182,7 +196,7 @@
|
|
|
182
196
|
let previousSyncedWorkflowId: string | null = null;
|
|
183
197
|
|
|
184
198
|
$effect(() => {
|
|
185
|
-
const storeValue =
|
|
199
|
+
const storeValue = fd.workflow.current;
|
|
186
200
|
|
|
187
201
|
// Suppressed during operations — handlers write to flowNodes directly
|
|
188
202
|
if (untrack(() => machine.permissions.suppressEffect)) return;
|
|
@@ -228,7 +242,7 @@
|
|
|
228
242
|
let previousExecPipelineId: string | undefined = undefined;
|
|
229
243
|
|
|
230
244
|
$effect(() => {
|
|
231
|
-
const storeValue =
|
|
245
|
+
const storeValue = fd.workflow.current;
|
|
232
246
|
const pipelineId = props.pipelineId;
|
|
233
247
|
|
|
234
248
|
if (!storeValue || !pipelineId) return;
|
|
@@ -241,15 +255,12 @@
|
|
|
241
255
|
previousExecWorkflowId = storeValue.id;
|
|
242
256
|
previousExecPipelineId = pipelineId;
|
|
243
257
|
|
|
244
|
-
// Cancel any pending timeout
|
|
258
|
+
// Cancel any pending idle/timeout schedule. In-flight fetches are
|
|
259
|
+
// cancelled by loadNodeExecutionInfo() itself when it's re-entered.
|
|
245
260
|
if (loadExecutionInfoTimeout) {
|
|
246
261
|
clearTimeout(loadExecutionInfoTimeout);
|
|
247
262
|
loadExecutionInfoTimeout = null;
|
|
248
263
|
}
|
|
249
|
-
if (executionInfoAbortController) {
|
|
250
|
-
executionInfoAbortController.abort();
|
|
251
|
-
executionInfoAbortController = null;
|
|
252
|
-
}
|
|
253
264
|
|
|
254
265
|
// Schedule loading with requestIdleCallback (falls back to setTimeout)
|
|
255
266
|
if (typeof requestIdleCallback !== 'undefined') {
|
|
@@ -266,44 +277,26 @@
|
|
|
266
277
|
}
|
|
267
278
|
});
|
|
268
279
|
|
|
269
|
-
//
|
|
270
|
-
//
|
|
271
|
-
//
|
|
280
|
+
// Re-fetch node execution info when the parent bumps refreshTrigger
|
|
281
|
+
// (poll ticks, chat-message arrivals, manual refresh). loadNodeExecutionInfo()
|
|
282
|
+
// is the single writer of executionInfo on flowNodes — no parallel channel.
|
|
283
|
+
// svelte-ignore state_referenced_locally
|
|
284
|
+
let _prevExecRefreshTrigger = props.refreshTrigger ?? 0;
|
|
272
285
|
$effect(() => {
|
|
273
|
-
const
|
|
274
|
-
if (
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const rawStatus = statuses[node.id];
|
|
278
|
-
if (!rawStatus) return node;
|
|
279
|
-
|
|
280
|
-
const existing = node.data.executionInfo ?? {
|
|
281
|
-
status: 'idle' as const,
|
|
282
|
-
executionCount: 0,
|
|
283
|
-
isExecuting: false
|
|
284
|
-
};
|
|
285
|
-
return {
|
|
286
|
-
...node,
|
|
287
|
-
data: {
|
|
288
|
-
...node.data,
|
|
289
|
-
executionInfo: {
|
|
290
|
-
...existing,
|
|
291
|
-
status: rawStatus === 'error' ? ('failed' as const) : rawStatus,
|
|
292
|
-
isExecuting: rawStatus === 'running'
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
});
|
|
286
|
+
const t = props.refreshTrigger ?? 0;
|
|
287
|
+
if (t === 0 || t === _prevExecRefreshTrigger) return;
|
|
288
|
+
_prevExecRefreshTrigger = t;
|
|
289
|
+
loadNodeExecutionInfo();
|
|
297
290
|
});
|
|
298
291
|
|
|
299
292
|
// ---------------------------------------------------------------------------
|
|
300
293
|
// History restore callback
|
|
301
294
|
// ---------------------------------------------------------------------------
|
|
302
295
|
$effect(() => {
|
|
303
|
-
setOnRestoreCallback((restoredWorkflow: Workflow) => {
|
|
296
|
+
fd.historyBindings.setOnRestoreCallback((restoredWorkflow: Workflow) => {
|
|
304
297
|
machine.send('START_RESTORE');
|
|
305
298
|
// Update the store (effect is suppressed during 'restoring')
|
|
306
|
-
|
|
299
|
+
fd.workflow.restoreFromHistory(restoredWorkflow);
|
|
307
300
|
// Derive flowNodes/flowEdges directly for immediate visual update
|
|
308
301
|
const derived = buildFlowNodesFromStore(restoredWorkflow);
|
|
309
302
|
flowNodes = derived.nodes;
|
|
@@ -314,26 +307,38 @@
|
|
|
314
307
|
});
|
|
315
308
|
|
|
316
309
|
return () => {
|
|
317
|
-
|
|
310
|
+
// Reinstate the container's default wiring rather than nulling it: the
|
|
311
|
+
// default instance survives unmount, and a bare null would make legacy
|
|
312
|
+
// historyActions.undo() silently restore nothing afterwards.
|
|
313
|
+
fd.historyBindings.setOnRestoreCallback((restored: Workflow) =>
|
|
314
|
+
fd.workflow.restoreFromHistory(restored)
|
|
315
|
+
);
|
|
318
316
|
};
|
|
319
317
|
});
|
|
320
318
|
|
|
321
319
|
/**
|
|
322
|
-
* Load node execution information for all nodes in the workflow
|
|
320
|
+
* Load node execution information for all nodes in the workflow.
|
|
321
|
+
* Cancels any in-flight fetch so concurrent callers (pipelineId change
|
|
322
|
+
* and refreshTrigger bumps) can't race on flowNodes.
|
|
323
323
|
*/
|
|
324
324
|
async function loadNodeExecutionInfo(): Promise<void> {
|
|
325
|
-
const workflow = untrack(() =>
|
|
325
|
+
const workflow = untrack(() => fd.workflow.current);
|
|
326
326
|
if (!workflow?.nodes || !props.pipelineId) return;
|
|
327
327
|
|
|
328
|
-
|
|
329
|
-
executionInfoAbortController
|
|
328
|
+
if (executionInfoAbortController) {
|
|
329
|
+
executionInfoAbortController.abort();
|
|
330
|
+
}
|
|
331
|
+
const controller = new AbortController();
|
|
332
|
+
executionInfoAbortController = controller;
|
|
330
333
|
|
|
334
|
+
try {
|
|
331
335
|
const executionInfo = await NodeOperationsHelper.loadNodeExecutionInfo(
|
|
336
|
+
fd.api,
|
|
332
337
|
workflow,
|
|
333
338
|
props.pipelineId
|
|
334
339
|
);
|
|
335
340
|
|
|
336
|
-
if (
|
|
341
|
+
if (controller.signal.aborted) return;
|
|
337
342
|
|
|
338
343
|
const defaultExecutionInfo: NodeExecutionInfo = {
|
|
339
344
|
status: 'idle' as const,
|
|
@@ -350,7 +355,9 @@
|
|
|
350
355
|
}
|
|
351
356
|
}));
|
|
352
357
|
|
|
353
|
-
executionInfoAbortController
|
|
358
|
+
if (executionInfoAbortController === controller) {
|
|
359
|
+
executionInfoAbortController = null;
|
|
360
|
+
}
|
|
354
361
|
} catch (error) {
|
|
355
362
|
if (error instanceof Error && error.name !== 'AbortError') {
|
|
356
363
|
logger.error('Failed to load node execution info:', error);
|
|
@@ -401,12 +408,7 @@
|
|
|
401
408
|
nodes: WorkflowNodeType[];
|
|
402
409
|
event: MouseEvent | TouchEvent;
|
|
403
410
|
}): void {
|
|
404
|
-
if (
|
|
405
|
-
!getEditorSettings().proximityConnect ||
|
|
406
|
-
!targetNode ||
|
|
407
|
-
props.readOnly ||
|
|
408
|
-
props.lockWorkflow
|
|
409
|
-
) {
|
|
411
|
+
if (!getEditorSettings().proximityConnect || !targetNode || !canvasEditable) {
|
|
410
412
|
if (currentProximityCandidates.length > 0) {
|
|
411
413
|
flowEdges = ProximityConnectHelper.removePreviewEdges(flowEdges);
|
|
412
414
|
currentProximityCandidates = [];
|
|
@@ -422,16 +424,18 @@
|
|
|
422
424
|
const baseEdges = ProximityConnectHelper.removePreviewEdges(flowEdges);
|
|
423
425
|
|
|
424
426
|
// Find the best compatible edge using port-to-port distance
|
|
425
|
-
const portCoordinates =
|
|
427
|
+
const portCoordinates = fd.portCoordinates.coordinates;
|
|
426
428
|
const candidates =
|
|
427
429
|
portCoordinates.size > 0
|
|
428
430
|
? ProximityConnectHelper.findCompatibleEdgesByPortCoordinates(
|
|
431
|
+
fd.portCompatibility,
|
|
429
432
|
targetNode.id,
|
|
430
433
|
portCoordinates,
|
|
431
434
|
baseEdges,
|
|
432
435
|
getEditorSettings().proximityConnectDistance
|
|
433
436
|
)
|
|
434
437
|
: ProximityConnectHelper.findCompatibleEdges(
|
|
438
|
+
fd.portCompatibility,
|
|
435
439
|
targetNode,
|
|
436
440
|
flowNodes,
|
|
437
441
|
baseEdges,
|
|
@@ -478,9 +482,9 @@
|
|
|
478
482
|
syncFlowToStore();
|
|
479
483
|
|
|
480
484
|
// Push history AFTER the drag completed
|
|
481
|
-
const storeValue =
|
|
485
|
+
const storeValue = fd.workflow.current;
|
|
482
486
|
if (storeValue) {
|
|
483
|
-
|
|
487
|
+
fd.workflow.pushHistory('Move node', storeValue);
|
|
484
488
|
}
|
|
485
489
|
|
|
486
490
|
// Transition to idle — sync effect is now unblocked
|
|
@@ -488,14 +492,11 @@
|
|
|
488
492
|
}
|
|
489
493
|
|
|
490
494
|
/**
|
|
491
|
-
* Handle new connections between nodes
|
|
495
|
+
* Handle new connections between nodes.
|
|
496
|
+
* The connection details aren't needed — SvelteFlow auto-creates the edge
|
|
497
|
+
* via bind:edges; this only drives the state machine and history snapshot.
|
|
492
498
|
*/
|
|
493
|
-
async function handleConnect(
|
|
494
|
-
source: string;
|
|
495
|
-
target: string;
|
|
496
|
-
sourceHandle?: string;
|
|
497
|
-
targetHandle?: string;
|
|
498
|
-
}): Promise<void> {
|
|
499
|
+
async function handleConnect(): Promise<void> {
|
|
499
500
|
machine.send('START_CONNECT');
|
|
500
501
|
|
|
501
502
|
// SvelteFlow auto-creates the edge via bind:edges — wait for DOM update
|
|
@@ -507,9 +508,9 @@
|
|
|
507
508
|
// Sync to store
|
|
508
509
|
syncFlowToStore();
|
|
509
510
|
|
|
510
|
-
const storeValue =
|
|
511
|
+
const storeValue = fd.workflow.current;
|
|
511
512
|
if (storeValue) {
|
|
512
|
-
|
|
513
|
+
fd.workflow.pushHistory('Add connection', storeValue);
|
|
513
514
|
}
|
|
514
515
|
|
|
515
516
|
machine.send('CONNECTION_MADE');
|
|
@@ -585,9 +586,9 @@
|
|
|
585
586
|
} else if (edgeCount > 0) {
|
|
586
587
|
description = `Delete ${edgeCount} connection${edgeCount > 1 ? 's' : ''}`;
|
|
587
588
|
}
|
|
588
|
-
const storeValue =
|
|
589
|
+
const storeValue = fd.workflow.current;
|
|
589
590
|
if (storeValue) {
|
|
590
|
-
|
|
591
|
+
fd.workflow.pushHistory(description, storeValue);
|
|
591
592
|
}
|
|
592
593
|
|
|
593
594
|
machine.send('DELETE_COMPLETE');
|
|
@@ -598,7 +599,7 @@
|
|
|
598
599
|
// Configure endpoints when props change
|
|
599
600
|
$effect(() => {
|
|
600
601
|
if (props.endpointConfig) {
|
|
601
|
-
ConfigurationHelper.configureEndpoints(props.endpointConfig);
|
|
602
|
+
ConfigurationHelper.configureEndpoints(fd.api, props.endpointConfig, props.authProvider);
|
|
602
603
|
}
|
|
603
604
|
});
|
|
604
605
|
|
|
@@ -635,9 +636,9 @@
|
|
|
635
636
|
|
|
636
637
|
await tick();
|
|
637
638
|
|
|
638
|
-
const storeValue =
|
|
639
|
+
const storeValue = fd.workflow.current;
|
|
639
640
|
if (storeValue) {
|
|
640
|
-
|
|
641
|
+
fd.workflow.pushHistory('Add node', storeValue);
|
|
641
642
|
}
|
|
642
643
|
} else {
|
|
643
644
|
logger.warn('Failed to create node from drop data');
|
|
@@ -667,7 +668,7 @@
|
|
|
667
668
|
logger.warn('Workflow file drop validation failed:', validation.error);
|
|
668
669
|
return;
|
|
669
670
|
}
|
|
670
|
-
|
|
671
|
+
fd.workflow.initialize(data as Workflow);
|
|
671
672
|
} catch (error) {
|
|
672
673
|
const errorObj = error instanceof Error ? error : new Error('Unknown error occurred');
|
|
673
674
|
logger.error('Workflow file drop import failed:', errorObj);
|
|
@@ -693,7 +694,7 @@
|
|
|
693
694
|
/**
|
|
694
695
|
* Update a node's data in the local editor state.
|
|
695
696
|
* Called by App.svelte AFTER it has already updated the global store via
|
|
696
|
-
*
|
|
697
|
+
* fd.workflow.updateNode(). We only need to update flowNodes for
|
|
697
698
|
* immediate visual feedback — no store sync needed.
|
|
698
699
|
*
|
|
699
700
|
* @param nodeId - The ID of the node to update
|
|
@@ -774,15 +775,15 @@
|
|
|
774
775
|
* - Ctrl+Z (or Cmd+Z on Mac): Undo
|
|
775
776
|
* - Ctrl+Shift+Z (or Cmd+Shift+Z): Redo
|
|
776
777
|
* - Ctrl+Y (or Cmd+Y): Redo (Windows convention)
|
|
778
|
+
*
|
|
779
|
+
* Also suppresses WebKit's legacy default action for Backspace outside
|
|
780
|
+
* editable content — history back-navigation. SvelteFlow's KeyHandler
|
|
781
|
+
* deletes the selected elements on Backspace but never preventDefaults,
|
|
782
|
+
* so in embedded WebKit the page navigates away mid-delete. Scoped to
|
|
783
|
+
* keydowns originating inside the flow canvas so host-page behavior
|
|
784
|
+
* outside the editor is untouched.
|
|
777
785
|
*/
|
|
778
786
|
function handleKeydown(event: KeyboardEvent): void {
|
|
779
|
-
// Check for Ctrl (Windows/Linux) or Cmd (Mac)
|
|
780
|
-
const isModifierPressed = event.ctrlKey || event.metaKey;
|
|
781
|
-
|
|
782
|
-
if (!isModifierPressed) {
|
|
783
|
-
return;
|
|
784
|
-
}
|
|
785
|
-
|
|
786
787
|
// Don't handle shortcuts if user is typing in an input, textarea, or contenteditable
|
|
787
788
|
const target = event.target as HTMLElement;
|
|
788
789
|
const isInputElement =
|
|
@@ -792,17 +793,31 @@
|
|
|
792
793
|
return;
|
|
793
794
|
}
|
|
794
795
|
|
|
796
|
+
// Backspace/Delete on a canvas element: let SvelteFlow handle the
|
|
797
|
+
// deletion, but block the browser default (WebKit navigates back).
|
|
798
|
+
if ((event.key === 'Backspace' || event.key === 'Delete') && target.closest('.svelte-flow')) {
|
|
799
|
+
event.preventDefault();
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// Check for Ctrl (Windows/Linux) or Cmd (Mac)
|
|
804
|
+
const isModifierPressed = event.ctrlKey || event.metaKey;
|
|
805
|
+
|
|
806
|
+
if (!isModifierPressed) {
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
|
|
795
810
|
// Undo: Ctrl+Z (without Shift)
|
|
796
811
|
if (event.key === 'z' && !event.shiftKey) {
|
|
797
812
|
event.preventDefault();
|
|
798
|
-
|
|
813
|
+
fd.historyBindings.undo();
|
|
799
814
|
return;
|
|
800
815
|
}
|
|
801
816
|
|
|
802
817
|
// Redo: Ctrl+Shift+Z or Ctrl+Y
|
|
803
818
|
if ((event.key === 'z' && event.shiftKey) || event.key === 'y') {
|
|
804
819
|
event.preventDefault();
|
|
805
|
-
|
|
820
|
+
fd.historyBindings.redo();
|
|
806
821
|
return;
|
|
807
822
|
}
|
|
808
823
|
}
|
|
@@ -832,18 +847,13 @@
|
|
|
832
847
|
<FlowDropZone ondrop={handleNodeDrop} onfiledrop={handleWorkflowFileDrop}>
|
|
833
848
|
{#key svelteFlowKey}
|
|
834
849
|
<SvelteFlow
|
|
850
|
+
id={fd.id}
|
|
835
851
|
bind:nodes={flowNodes}
|
|
836
852
|
bind:edges={flowEdges}
|
|
837
853
|
{nodeTypes}
|
|
838
854
|
{edgeTypes}
|
|
839
855
|
{defaultEdgeOptions}
|
|
840
|
-
onconnect={(
|
|
841
|
-
void handleConnect({
|
|
842
|
-
source: connection.source,
|
|
843
|
-
target: connection.target,
|
|
844
|
-
sourceHandle: connection.sourceHandle ?? undefined,
|
|
845
|
-
targetHandle: connection.targetHandle ?? undefined
|
|
846
|
-
})}
|
|
856
|
+
onconnect={() => void handleConnect()}
|
|
847
857
|
onbeforedelete={handleBeforeDelete}
|
|
848
858
|
ondelete={handleNodesDelete}
|
|
849
859
|
onnodedragstart={handleNodeDragStart}
|
|
@@ -859,12 +869,12 @@
|
|
|
859
869
|
{initialViewport}
|
|
860
870
|
colorMode={getResolvedTheme() as ColorMode}
|
|
861
871
|
fitView={getEditorSettings().fitViewOnLoad}
|
|
862
|
-
nodesDraggable={
|
|
863
|
-
nodesConnectable={
|
|
864
|
-
elementsSelectable={
|
|
872
|
+
nodesDraggable={canvasEditable}
|
|
873
|
+
nodesConnectable={canvasEditable}
|
|
874
|
+
elementsSelectable={canvasEditable}
|
|
865
875
|
>
|
|
866
876
|
<Controls />
|
|
867
|
-
{#if
|
|
877
|
+
{#if canvasEditable && props.onToggleConsole}
|
|
868
878
|
<button
|
|
869
879
|
class="flowdrop-console-toggle"
|
|
870
880
|
class:flowdrop-console-toggle--active={props.consoleOpen}
|
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
import '@xyflow/svelte/dist/style.css';
|
|
2
|
-
import type { WorkflowNode as WorkflowNodeType
|
|
2
|
+
import type { WorkflowNode as WorkflowNodeType } from '../types/index.js';
|
|
3
3
|
import type { EndpointConfig } from '../config/endpoints.js';
|
|
4
|
+
import type { AuthProvider } from '../types/auth.js';
|
|
5
|
+
import type { FlowDropInstance } from '../stores/instanceContainer.svelte.js';
|
|
4
6
|
interface Props {
|
|
5
|
-
nodes?: NodeMetadata[];
|
|
6
7
|
endpointConfig?: EndpointConfig;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
isConfigSidebarOpen?: boolean;
|
|
10
|
-
selectedNodeForConfig?: WorkflowNodeType | null;
|
|
8
|
+
/** Auth provider applied to this instance's API requests. */
|
|
9
|
+
authProvider?: AuthProvider;
|
|
11
10
|
openConfigSidebar?: (node: WorkflowNodeType) => void;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Editor interaction mode. `'edit'` allows node drag/connect/select and
|
|
13
|
+
* proximity-connect; `'readonly'` and `'locked'` disable all canvas
|
|
14
|
+
* editing (they behave identically today — see App's `mode` prop for the
|
|
15
|
+
* full matrix). Replaces the former `readOnly` + `lockWorkflow` booleans.
|
|
16
|
+
* @default 'edit'
|
|
17
|
+
*/
|
|
18
|
+
mode?: 'edit' | 'readonly' | 'locked';
|
|
16
19
|
pipelineId?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Increments to force a re-fetch of node execution info from the server.
|
|
22
|
+
* Used by parents (e.g. PipelineStatus) to push poll ticks / chat-message
|
|
23
|
+
* arrivals down to the canvas without owning a separate status channel.
|
|
24
|
+
*/
|
|
25
|
+
refreshTrigger?: number;
|
|
17
26
|
consoleOpen?: boolean;
|
|
18
27
|
onToggleConsole?: () => void;
|
|
28
|
+
/** Per-instance state container (created by mount functions). Defaults to the page-default instance. */
|
|
29
|
+
instance?: FlowDropInstance;
|
|
19
30
|
}
|
|
20
31
|
declare const WorkflowEditor: import("svelte").Component<Props, {
|
|
21
32
|
updateNodeData: (nodeId: string, dataUpdates: Partial<WorkflowNodeType["data"]>) => void;
|