@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
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
* construction happen in exactly one place.
|
|
9
9
|
*/
|
|
10
10
|
import { tick } from 'svelte';
|
|
11
|
-
import {
|
|
12
|
-
import { workflowApi, setEndpointConfig } from './api.js';
|
|
11
|
+
import { getDefaultInstance } from '../stores/instanceContainer.svelte.js';
|
|
13
12
|
import { createEndpointConfig } from '../config/endpoints.js';
|
|
14
13
|
import { v4 as uuidv4 } from 'uuid';
|
|
15
14
|
import { DEFAULT_WORKFLOW_FORMAT } from '../types/index.js';
|
|
@@ -19,29 +18,19 @@ import { DEFAULT_FEATURES } from '../types/events.js';
|
|
|
19
18
|
// Internal helpers
|
|
20
19
|
// ---------------------------------------------------------------------------
|
|
21
20
|
/**
|
|
22
|
-
* Ensure API
|
|
23
|
-
* This is needed when the global save function is called from the layout
|
|
24
|
-
* which doesn't initialize the API configuration like
|
|
21
|
+
* Ensure the instance's API context is configured.
|
|
22
|
+
* This is needed when the global save function is called from the layout
|
|
23
|
+
* component which doesn't initialize the API configuration like <App> does.
|
|
25
24
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const currentConfig = getEndpointConfig();
|
|
30
|
-
if (currentConfig && currentConfig.baseUrl) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
// Could not check existing API configuration, initializing
|
|
25
|
+
function ensureApiConfiguration(fd) {
|
|
26
|
+
if (fd.api.isConfigured() && fd.api.config?.baseUrl) {
|
|
27
|
+
return;
|
|
36
28
|
}
|
|
37
29
|
// API configuration is not initialized — derive URL from window.location when available
|
|
38
30
|
const apiBaseUrl = typeof window !== 'undefined'
|
|
39
31
|
? `${window.location.protocol}//${window.location.host}/api/flowdrop`
|
|
40
32
|
: '/api/flowdrop';
|
|
41
33
|
const config = createEndpointConfig(apiBaseUrl, {
|
|
42
|
-
auth: {
|
|
43
|
-
type: 'none'
|
|
44
|
-
},
|
|
45
34
|
timeout: 10000,
|
|
46
35
|
retry: {
|
|
47
36
|
enabled: true,
|
|
@@ -50,7 +39,7 @@ async function ensureApiConfiguration() {
|
|
|
50
39
|
backoff: 'exponential'
|
|
51
40
|
}
|
|
52
41
|
});
|
|
53
|
-
|
|
42
|
+
fd.api.configure(config);
|
|
54
43
|
}
|
|
55
44
|
/**
|
|
56
45
|
* Flush any pending form changes by blurring the active element.
|
|
@@ -79,18 +68,21 @@ async function flushPendingFormChanges() {
|
|
|
79
68
|
* 1. Flush pending form changes (blur active element + tick)
|
|
80
69
|
* 2. Optionally call onBeforeSave — return false cancels the save
|
|
81
70
|
* 3. Build the canonical Workflow object (preserving metadata, format, etc.)
|
|
82
|
-
* 4. Persist via
|
|
71
|
+
* 4. Persist via the instance's API client (fd.api.client)
|
|
83
72
|
* 5. Update the store if the server assigned a new ID
|
|
84
73
|
* 6. Call onMarkAsSaved / onAfterSave hooks
|
|
85
74
|
* 7. Show toast notifications (respecting features.showToasts)
|
|
86
75
|
*/
|
|
87
76
|
export async function globalSaveWorkflow(options = {}) {
|
|
88
|
-
const {
|
|
77
|
+
const { eventHandlers, onMarkAsSaved, onSaved } = options;
|
|
89
78
|
const features = { ...DEFAULT_FEATURES, ...options.features };
|
|
79
|
+
// Resolve the target instance; defaults to the page-default instance.
|
|
80
|
+
const fd = options.instance ?? getDefaultInstance();
|
|
81
|
+
const readWorkflow = () => fd.workflow.current;
|
|
90
82
|
// Step 1 — Flush pending form changes (single location for this logic)
|
|
91
83
|
await flushPendingFormChanges();
|
|
92
|
-
// Get current workflow from
|
|
93
|
-
const currentWorkflow =
|
|
84
|
+
// Get current workflow from the instance's store after flush
|
|
85
|
+
const currentWorkflow = readWorkflow();
|
|
94
86
|
if (!currentWorkflow) {
|
|
95
87
|
if (features.showToasts) {
|
|
96
88
|
apiToasts.error('Save workflow', 'No workflow to save');
|
|
@@ -107,7 +99,7 @@ export async function globalSaveWorkflow(options = {}) {
|
|
|
107
99
|
const loadingToast = features.showToasts ? apiToasts.loading('Saving workflow') : null;
|
|
108
100
|
try {
|
|
109
101
|
// Ensure API configuration is initialised (needed when called outside App.svelte)
|
|
110
|
-
|
|
102
|
+
ensureApiConfiguration(fd);
|
|
111
103
|
// Step 3 — Build the canonical workflow object.
|
|
112
104
|
// Preserve all existing metadata fields (format, tags, etc.) so nothing is dropped.
|
|
113
105
|
//
|
|
@@ -124,35 +116,21 @@ export async function globalSaveWorkflow(options = {}) {
|
|
|
124
116
|
edges: currentWorkflow.edges || [],
|
|
125
117
|
metadata: {
|
|
126
118
|
...currentWorkflow.metadata,
|
|
127
|
-
|
|
119
|
+
schemaVersion: currentWorkflow.metadata?.schemaVersion || '1.0.0',
|
|
128
120
|
format: currentWorkflow.metadata?.format || DEFAULT_WORKFLOW_FORMAT,
|
|
129
121
|
createdAt: currentWorkflow.metadata?.createdAt || new Date().toISOString(),
|
|
130
122
|
updatedAt: new Date().toISOString()
|
|
131
123
|
}
|
|
132
124
|
};
|
|
133
|
-
// Step 4 — Persist
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
else {
|
|
140
|
-
savedWorkflow = await apiClient.saveWorkflow(finalWorkflow);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
// Legacy path
|
|
145
|
-
if (isExistingWorkflow) {
|
|
146
|
-
savedWorkflow = await workflowApi.updateWorkflow(finalWorkflow.id, finalWorkflow);
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
const { id: _id, ...workflowData } = finalWorkflow;
|
|
150
|
-
savedWorkflow = await workflowApi.createWorkflow(workflowData);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
125
|
+
// Step 4 — Persist via this instance's API client.
|
|
126
|
+
// id-presence (computed above) decides update vs create — never UUID-regex.
|
|
127
|
+
const apiClient = fd.api.client;
|
|
128
|
+
const savedWorkflow = isExistingWorkflow
|
|
129
|
+
? await apiClient.updateWorkflow(finalWorkflow.id, finalWorkflow)
|
|
130
|
+
: await apiClient.saveWorkflow(finalWorkflow);
|
|
153
131
|
// Step 5 — If the server assigned a new ID, sync the store
|
|
154
132
|
if (savedWorkflow.id && savedWorkflow.id !== finalWorkflow.id) {
|
|
155
|
-
|
|
133
|
+
fd.workflow.batchUpdate({
|
|
156
134
|
nodes: finalWorkflow.nodes,
|
|
157
135
|
edges: finalWorkflow.edges,
|
|
158
136
|
name: finalWorkflow.name,
|
|
@@ -167,8 +145,7 @@ export async function globalSaveWorkflow(options = {}) {
|
|
|
167
145
|
onMarkAsSaved();
|
|
168
146
|
}
|
|
169
147
|
else {
|
|
170
|
-
|
|
171
|
-
storeMarkAsSaved();
|
|
148
|
+
fd.workflow.markAsSaved();
|
|
172
149
|
}
|
|
173
150
|
// Notify caller with the definitive saved workflow (server-assigned ID)
|
|
174
151
|
if (onSaved) {
|
|
@@ -190,7 +167,7 @@ export async function globalSaveWorkflow(options = {}) {
|
|
|
190
167
|
dismissToast(loadingToast);
|
|
191
168
|
const errorObj = error instanceof Error ? error : new Error('Unknown error occurred');
|
|
192
169
|
// onSaveError hook
|
|
193
|
-
const currentWorkflowForError =
|
|
170
|
+
const currentWorkflowForError = readWorkflow();
|
|
194
171
|
if (eventHandlers?.onSaveError && currentWorkflowForError) {
|
|
195
172
|
await eventHandlers.onSaveError(errorObj, currentWorkflowForError);
|
|
196
173
|
}
|
|
@@ -218,7 +195,8 @@ export async function globalExportWorkflow(options = {}) {
|
|
|
218
195
|
try {
|
|
219
196
|
// Flush pending changes before exporting (same discipline as save)
|
|
220
197
|
await flushPendingFormChanges();
|
|
221
|
-
const
|
|
198
|
+
const fd = options.instance ?? getDefaultInstance();
|
|
199
|
+
const currentWorkflow = fd.workflow.current;
|
|
222
200
|
if (!currentWorkflow) {
|
|
223
201
|
if (features.showToasts) {
|
|
224
202
|
apiToasts.error('Export workflow', 'No workflow to export');
|
|
@@ -234,7 +212,7 @@ export async function globalExportWorkflow(options = {}) {
|
|
|
234
212
|
edges: currentWorkflow.edges || [],
|
|
235
213
|
metadata: {
|
|
236
214
|
...currentWorkflow.metadata,
|
|
237
|
-
|
|
215
|
+
schemaVersion: currentWorkflow.metadata?.schemaVersion || '1.0.0',
|
|
238
216
|
format: currentWorkflow.metadata?.format || DEFAULT_WORKFLOW_FORMAT,
|
|
239
217
|
createdAt: currentWorkflow.metadata?.createdAt || new Date().toISOString(),
|
|
240
218
|
updatedAt: new Date().toISOString()
|
|
@@ -202,9 +202,15 @@ export declare class HistoryService {
|
|
|
202
202
|
private notifyChange;
|
|
203
203
|
}
|
|
204
204
|
/**
|
|
205
|
-
*
|
|
205
|
+
* History service of the page-default FlowDrop instance.
|
|
206
206
|
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
207
|
+
* Kept as a module-level export for backward compatibility (re-exported via
|
|
208
|
+
* `@flowdrop/flowdrop/editor`) — `createFlowDropInstance({ isDefault: true })`
|
|
209
|
+
* adopts this exact object, so legacy `historyService.undo()` calls keep
|
|
210
|
+
* operating on the default editor's history stack. Holds no reactive state,
|
|
211
|
+
* so module-level construction is SSR-safe.
|
|
212
|
+
*
|
|
213
|
+
* For additional editor instances, the instance container creates a fresh
|
|
214
|
+
* `new HistoryService()` — use `getInstance().history` in components.
|
|
209
215
|
*/
|
|
210
216
|
export declare const historyService: HistoryService;
|
|
@@ -328,9 +328,15 @@ export class HistoryService {
|
|
|
328
328
|
// Singleton Instance
|
|
329
329
|
// =========================================================================
|
|
330
330
|
/**
|
|
331
|
-
*
|
|
331
|
+
* History service of the page-default FlowDrop instance.
|
|
332
332
|
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
333
|
+
* Kept as a module-level export for backward compatibility (re-exported via
|
|
334
|
+
* `@flowdrop/flowdrop/editor`) — `createFlowDropInstance({ isDefault: true })`
|
|
335
|
+
* adopts this exact object, so legacy `historyService.undo()` calls keep
|
|
336
|
+
* operating on the default editor's history stack. Holds no reactive state,
|
|
337
|
+
* so module-level construction is SSR-safe.
|
|
338
|
+
*
|
|
339
|
+
* For additional editor instances, the instance container creates a fresh
|
|
340
|
+
* `new HistoryService()` — use `getInstance().history` in components.
|
|
335
341
|
*/
|
|
336
342
|
export const historyService = new HistoryService();
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* @module services/interruptService
|
|
9
9
|
*/
|
|
10
10
|
import type { Interrupt, InterruptPollingConfig } from '../types/interrupt.js';
|
|
11
|
+
import type { EndpointConfig } from '../config/endpoints.js';
|
|
12
|
+
import type { AuthProvider } from '../types/auth.js';
|
|
11
13
|
/**
|
|
12
14
|
* Interrupt Service class
|
|
13
15
|
*
|
|
@@ -46,19 +48,23 @@ export declare class InterruptService {
|
|
|
46
48
|
/**
|
|
47
49
|
* Check if interrupt endpoints are configured
|
|
48
50
|
*
|
|
51
|
+
* @param config - The instance's endpoint configuration (from fd.api.config)
|
|
49
52
|
* @returns True if interrupt endpoints are available
|
|
50
53
|
*/
|
|
51
|
-
isConfigured(): boolean;
|
|
54
|
+
isConfigured(config: EndpointConfig | null): boolean;
|
|
52
55
|
/**
|
|
53
|
-
*
|
|
56
|
+
* Validate and return the caller-supplied endpoint configuration.
|
|
54
57
|
*
|
|
55
|
-
*
|
|
58
|
+
* Callers thread the config from `getInstance().api.config`.
|
|
59
|
+
*
|
|
60
|
+
* @throws Error if endpoint configuration is not set or lacks interrupts
|
|
56
61
|
* @returns The endpoint configuration
|
|
57
62
|
*/
|
|
58
63
|
private getConfig;
|
|
59
64
|
/**
|
|
60
65
|
* Generic API request helper
|
|
61
66
|
*
|
|
67
|
+
* @param config - The endpoint configuration
|
|
62
68
|
* @param url - The URL to fetch
|
|
63
69
|
* @param options - Fetch options
|
|
64
70
|
* @returns The parsed JSON response
|
|
@@ -70,7 +76,7 @@ export declare class InterruptService {
|
|
|
70
76
|
* @param interruptId - The interrupt UUID
|
|
71
77
|
* @returns The interrupt details
|
|
72
78
|
*/
|
|
73
|
-
getInterrupt(interruptId: string): Promise<Interrupt>;
|
|
79
|
+
getInterrupt(endpointConfig: EndpointConfig | null, interruptId: string, authProvider?: AuthProvider): Promise<Interrupt>;
|
|
74
80
|
/**
|
|
75
81
|
* Resolve an interrupt with user response
|
|
76
82
|
*
|
|
@@ -78,28 +84,28 @@ export declare class InterruptService {
|
|
|
78
84
|
* @param value - The user's response value
|
|
79
85
|
* @returns The updated interrupt
|
|
80
86
|
*/
|
|
81
|
-
resolveInterrupt(interruptId: string, value: unknown): Promise<Interrupt>;
|
|
87
|
+
resolveInterrupt(endpointConfig: EndpointConfig | null, interruptId: string, value: unknown, authProvider?: AuthProvider): Promise<Interrupt>;
|
|
82
88
|
/**
|
|
83
89
|
* Cancel a pending interrupt
|
|
84
90
|
*
|
|
85
91
|
* @param interruptId - The interrupt UUID
|
|
86
92
|
* @returns The updated interrupt
|
|
87
93
|
*/
|
|
88
|
-
cancelInterrupt(interruptId: string): Promise<Interrupt>;
|
|
94
|
+
cancelInterrupt(endpointConfig: EndpointConfig | null, interruptId: string, authProvider?: AuthProvider): Promise<Interrupt>;
|
|
89
95
|
/**
|
|
90
96
|
* List interrupts for a playground session
|
|
91
97
|
*
|
|
92
98
|
* @param sessionId - The session UUID
|
|
93
99
|
* @returns Array of interrupts for the session
|
|
94
100
|
*/
|
|
95
|
-
listSessionInterrupts(sessionId: string): Promise<Interrupt[]>;
|
|
101
|
+
listSessionInterrupts(endpointConfig: EndpointConfig | null, sessionId: string, authProvider?: AuthProvider): Promise<Interrupt[]>;
|
|
96
102
|
/**
|
|
97
103
|
* List interrupts for a pipeline
|
|
98
104
|
*
|
|
99
105
|
* @param pipelineId - The pipeline UUID
|
|
100
106
|
* @returns Array of interrupts for the pipeline
|
|
101
107
|
*/
|
|
102
|
-
listPipelineInterrupts(pipelineId: string): Promise<Interrupt[]>;
|
|
108
|
+
listPipelineInterrupts(endpointConfig: EndpointConfig | null, pipelineId: string, authProvider?: AuthProvider): Promise<Interrupt[]>;
|
|
103
109
|
/**
|
|
104
110
|
* Start polling for interrupts in a session
|
|
105
111
|
*
|
|
@@ -109,7 +115,7 @@ export declare class InterruptService {
|
|
|
109
115
|
* @param sessionId - The session UUID to poll
|
|
110
116
|
* @param callback - Callback function to handle new interrupts
|
|
111
117
|
*/
|
|
112
|
-
startPolling(sessionId: string, callback: (interrupts: Interrupt[]) => void): void;
|
|
118
|
+
startPolling(endpointConfig: EndpointConfig | null, sessionId: string, callback: (interrupts: Interrupt[]) => void, authProvider?: AuthProvider): void;
|
|
113
119
|
/**
|
|
114
120
|
* Stop polling for interrupts
|
|
115
121
|
*/
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* @module services/interruptService
|
|
9
9
|
*/
|
|
10
10
|
import { defaultInterruptPollingConfig } from '../types/interrupt.js';
|
|
11
|
-
import { buildEndpointUrl
|
|
12
|
-
import {
|
|
11
|
+
import { buildEndpointUrl } from '../config/endpoints.js';
|
|
12
|
+
import { authenticatedFetch } from '../utils/fetchWithAuth.js';
|
|
13
13
|
import { logger } from '../utils/logger.js';
|
|
14
14
|
/**
|
|
15
15
|
* Interrupt Service class
|
|
@@ -62,22 +62,23 @@ export class InterruptService {
|
|
|
62
62
|
/**
|
|
63
63
|
* Check if interrupt endpoints are configured
|
|
64
64
|
*
|
|
65
|
+
* @param config - The instance's endpoint configuration (from fd.api.config)
|
|
65
66
|
* @returns True if interrupt endpoints are available
|
|
66
67
|
*/
|
|
67
|
-
isConfigured() {
|
|
68
|
-
const config = getEndpointConfig();
|
|
68
|
+
isConfigured(config) {
|
|
69
69
|
return Boolean(config?.endpoints?.interrupts);
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
|
-
*
|
|
72
|
+
* Validate and return the caller-supplied endpoint configuration.
|
|
73
73
|
*
|
|
74
|
-
*
|
|
74
|
+
* Callers thread the config from `getInstance().api.config`.
|
|
75
|
+
*
|
|
76
|
+
* @throws Error if endpoint configuration is not set or lacks interrupts
|
|
75
77
|
* @returns The endpoint configuration
|
|
76
78
|
*/
|
|
77
|
-
getConfig() {
|
|
78
|
-
const config = getEndpointConfig();
|
|
79
|
+
getConfig(config) {
|
|
79
80
|
if (!config) {
|
|
80
|
-
throw new Error('Endpoint configuration not set.
|
|
81
|
+
throw new Error('Endpoint configuration not set. Configure the instance via fd.api.configure().');
|
|
81
82
|
}
|
|
82
83
|
if (!config.endpoints.interrupts) {
|
|
83
84
|
throw new Error('Interrupt endpoints not configured.');
|
|
@@ -87,19 +88,16 @@ export class InterruptService {
|
|
|
87
88
|
/**
|
|
88
89
|
* Generic API request helper
|
|
89
90
|
*
|
|
91
|
+
* @param config - The endpoint configuration
|
|
90
92
|
* @param url - The URL to fetch
|
|
91
93
|
* @param options - Fetch options
|
|
92
94
|
* @returns The parsed JSON response
|
|
93
95
|
*/
|
|
94
|
-
async request(url, options = {}) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
headers: {
|
|
100
|
-
...headers,
|
|
101
|
-
...options.headers
|
|
102
|
-
}
|
|
96
|
+
async request(config, url, options = {}, authProvider) {
|
|
97
|
+
const response = await authenticatedFetch(url, options, {
|
|
98
|
+
config,
|
|
99
|
+
endpointKey: 'interrupts',
|
|
100
|
+
authProvider
|
|
103
101
|
});
|
|
104
102
|
if (!response.ok) {
|
|
105
103
|
const errorData = await response.json().catch(() => ({}));
|
|
@@ -119,12 +117,12 @@ export class InterruptService {
|
|
|
119
117
|
* @param interruptId - The interrupt UUID
|
|
120
118
|
* @returns The interrupt details
|
|
121
119
|
*/
|
|
122
|
-
async getInterrupt(interruptId) {
|
|
123
|
-
const config = this.getConfig();
|
|
120
|
+
async getInterrupt(endpointConfig, interruptId, authProvider) {
|
|
121
|
+
const config = this.getConfig(endpointConfig);
|
|
124
122
|
const url = buildEndpointUrl(config, config.endpoints.interrupts.get, {
|
|
125
123
|
interruptId
|
|
126
124
|
});
|
|
127
|
-
const response = await this.request(url);
|
|
125
|
+
const response = await this.request(config, url, {}, authProvider);
|
|
128
126
|
if (!response.data) {
|
|
129
127
|
throw new Error('Interrupt not found');
|
|
130
128
|
}
|
|
@@ -137,16 +135,16 @@ export class InterruptService {
|
|
|
137
135
|
* @param value - The user's response value
|
|
138
136
|
* @returns The updated interrupt
|
|
139
137
|
*/
|
|
140
|
-
async resolveInterrupt(interruptId, value) {
|
|
141
|
-
const config = this.getConfig();
|
|
138
|
+
async resolveInterrupt(endpointConfig, interruptId, value, authProvider) {
|
|
139
|
+
const config = this.getConfig(endpointConfig);
|
|
142
140
|
const url = buildEndpointUrl(config, config.endpoints.interrupts.resolve, {
|
|
143
141
|
interruptId
|
|
144
142
|
});
|
|
145
143
|
const resolution = { value };
|
|
146
|
-
const response = await this.request(url, {
|
|
144
|
+
const response = await this.request(config, url, {
|
|
147
145
|
method: 'POST',
|
|
148
146
|
body: JSON.stringify(resolution)
|
|
149
|
-
});
|
|
147
|
+
}, authProvider);
|
|
150
148
|
if (!response.data) {
|
|
151
149
|
throw new Error('Failed to resolve interrupt: No data returned');
|
|
152
150
|
}
|
|
@@ -158,14 +156,14 @@ export class InterruptService {
|
|
|
158
156
|
* @param interruptId - The interrupt UUID
|
|
159
157
|
* @returns The updated interrupt
|
|
160
158
|
*/
|
|
161
|
-
async cancelInterrupt(interruptId) {
|
|
162
|
-
const config = this.getConfig();
|
|
159
|
+
async cancelInterrupt(endpointConfig, interruptId, authProvider) {
|
|
160
|
+
const config = this.getConfig(endpointConfig);
|
|
163
161
|
const url = buildEndpointUrl(config, config.endpoints.interrupts.cancel, {
|
|
164
162
|
interruptId
|
|
165
163
|
});
|
|
166
|
-
const response = await this.request(url, {
|
|
164
|
+
const response = await this.request(config, url, {
|
|
167
165
|
method: 'POST'
|
|
168
|
-
});
|
|
166
|
+
}, authProvider);
|
|
169
167
|
if (!response.data) {
|
|
170
168
|
throw new Error('Failed to cancel interrupt: No data returned');
|
|
171
169
|
}
|
|
@@ -177,12 +175,12 @@ export class InterruptService {
|
|
|
177
175
|
* @param sessionId - The session UUID
|
|
178
176
|
* @returns Array of interrupts for the session
|
|
179
177
|
*/
|
|
180
|
-
async listSessionInterrupts(sessionId) {
|
|
181
|
-
const config = this.getConfig();
|
|
178
|
+
async listSessionInterrupts(endpointConfig, sessionId, authProvider) {
|
|
179
|
+
const config = this.getConfig(endpointConfig);
|
|
182
180
|
const url = buildEndpointUrl(config, config.endpoints.interrupts.listBySession, {
|
|
183
181
|
sessionId
|
|
184
182
|
});
|
|
185
|
-
const response = await this.request(url);
|
|
183
|
+
const response = await this.request(config, url, {}, authProvider);
|
|
186
184
|
return response.data ?? [];
|
|
187
185
|
}
|
|
188
186
|
/**
|
|
@@ -191,12 +189,12 @@ export class InterruptService {
|
|
|
191
189
|
* @param pipelineId - The pipeline UUID
|
|
192
190
|
* @returns Array of interrupts for the pipeline
|
|
193
191
|
*/
|
|
194
|
-
async listPipelineInterrupts(pipelineId) {
|
|
195
|
-
const config = this.getConfig();
|
|
192
|
+
async listPipelineInterrupts(endpointConfig, pipelineId, authProvider) {
|
|
193
|
+
const config = this.getConfig(endpointConfig);
|
|
196
194
|
const url = buildEndpointUrl(config, config.endpoints.interrupts.listByPipeline, {
|
|
197
195
|
pipelineId
|
|
198
196
|
});
|
|
199
|
-
const response = await this.request(url);
|
|
197
|
+
const response = await this.request(config, url, {}, authProvider);
|
|
200
198
|
return response.data ?? [];
|
|
201
199
|
}
|
|
202
200
|
// =========================================================================
|
|
@@ -211,7 +209,7 @@ export class InterruptService {
|
|
|
211
209
|
* @param sessionId - The session UUID to poll
|
|
212
210
|
* @param callback - Callback function to handle new interrupts
|
|
213
211
|
*/
|
|
214
|
-
startPolling(sessionId, callback) {
|
|
212
|
+
startPolling(endpointConfig, sessionId, callback, authProvider) {
|
|
215
213
|
if (!this.pollingConfig.enabled) {
|
|
216
214
|
logger.warn('[InterruptService] Polling is disabled. Enable via setPollingConfig().');
|
|
217
215
|
return;
|
|
@@ -225,7 +223,7 @@ export class InterruptService {
|
|
|
225
223
|
return;
|
|
226
224
|
}
|
|
227
225
|
try {
|
|
228
|
-
const interrupts = await this.listSessionInterrupts(sessionId);
|
|
226
|
+
const interrupts = await this.listSessionInterrupts(endpointConfig, sessionId, authProvider);
|
|
229
227
|
const pendingInterrupts = interrupts.filter((i) => i.status === 'pending');
|
|
230
228
|
// Reset backoff on successful request
|
|
231
229
|
this.currentBackoff = this.pollingConfig.interval ?? defaultInterruptPollingConfig.interval;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Handles fetching and managing node execution information from the backend
|
|
4
4
|
*/
|
|
5
5
|
import type { NodeExecutionInfo } from '../types/index.js';
|
|
6
|
+
import type { EndpointConfig } from '../config/endpoints.js';
|
|
6
7
|
/**
|
|
7
8
|
* Service for managing node execution information
|
|
8
9
|
*/
|
|
@@ -18,15 +19,15 @@ export declare class NodeExecutionService {
|
|
|
18
19
|
/**
|
|
19
20
|
* Get execution information for a specific node from pipeline data
|
|
20
21
|
*/
|
|
21
|
-
getNodeExecutionInfo(nodeId: string, pipelineId?: string): Promise<NodeExecutionInfo | null>;
|
|
22
|
+
getNodeExecutionInfo(endpointConfig: EndpointConfig | null, nodeId: string, pipelineId?: string): Promise<NodeExecutionInfo | null>;
|
|
22
23
|
/**
|
|
23
24
|
* Get execution information for multiple nodes from pipeline data
|
|
24
25
|
*/
|
|
25
|
-
getMultipleNodeExecutionInfo(nodeIds: string[], pipelineId?: string): Promise<Record<string, NodeExecutionInfo>>;
|
|
26
|
+
getMultipleNodeExecutionInfo(endpointConfig: EndpointConfig | null, nodeIds: string[], pipelineId?: string): Promise<Record<string, NodeExecutionInfo>>;
|
|
26
27
|
/**
|
|
27
28
|
* Get all node execution counts
|
|
28
29
|
*/
|
|
29
|
-
getAllNodeExecutionCounts(): Promise<Record<string, number>>;
|
|
30
|
+
getAllNodeExecutionCounts(endpointConfig: EndpointConfig | null): Promise<Record<string, number>>;
|
|
30
31
|
/**
|
|
31
32
|
* Get cached execution info for a node
|
|
32
33
|
*/
|
|
@@ -47,6 +48,20 @@ export declare class NodeExecutionService {
|
|
|
47
48
|
* Update execution info for a node (for real-time updates)
|
|
48
49
|
*/
|
|
49
50
|
updateNodeExecutionInfo(nodeId: string, executionInfo: Partial<NodeExecutionInfo>): void;
|
|
51
|
+
/**
|
|
52
|
+
* Build execution info for one node from the pipeline payload.
|
|
53
|
+
*
|
|
54
|
+
* The `node_statuses` entry is the backend-resolved summary (latest job's
|
|
55
|
+
* status, timing from the most recent run, `executions` count); the per-job
|
|
56
|
+
* history is attached from the `jobs` array so loop iterations stay
|
|
57
|
+
* inspectable. Falls back to the node's jobs when no entry exists (older
|
|
58
|
+
* backends).
|
|
59
|
+
*/
|
|
60
|
+
private buildNodeExecutionInfo;
|
|
61
|
+
/**
|
|
62
|
+
* Map a pipeline job payload entry to a NodeJobExecution history item.
|
|
63
|
+
*/
|
|
64
|
+
private mapJobToNodeJobExecution;
|
|
50
65
|
/**
|
|
51
66
|
* Map job status to execution status
|
|
52
67
|
*/
|