@flowdrop/flowdrop 1.15.0 → 2.0.0-beta.1
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 +475 -0
- package/MIGRATION-2.0.md +472 -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/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 +162 -192
- package/dist/components/App.svelte.d.ts +47 -8
- package/dist/components/ConfigForm.svelte +71 -47
- 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 +16 -67
- package/dist/components/PortCoordinateTracker.svelte +5 -6
- package/dist/components/SchemaForm.stories.svelte +1 -3
- package/dist/components/SchemaForm.svelte +18 -25
- 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 +118 -111
- package/dist/components/WorkflowEditor.svelte.d.ts +18 -10
- package/dist/components/chat/AIChatPanel.svelte +93 -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 +8 -6
- package/dist/components/form/FormField.svelte +4 -2
- package/dist/components/form/FormFieldLight.svelte +4 -2
- 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/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 +16 -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 +65 -6
- package/dist/components/playground/PipelinePanel.svelte +11 -5
- package/dist/components/playground/PipelineTableView.svelte +186 -44
- package/dist/components/playground/Playground.svelte +90 -92
- package/dist/components/playground/Playground.svelte.d.ts +2 -0
- package/dist/components/playground/PlaygroundApp.svelte +6 -1
- package/dist/components/playground/PlaygroundApp.svelte.d.ts +3 -0
- package/dist/components/playground/PlaygroundModal.svelte +13 -3
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -0
- package/dist/components/playground/PlaygroundStudio.svelte +34 -32
- package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -0
- package/dist/components/playground/SessionManager.svelte +9 -12
- package/dist/components/playground/pipelineViewUtils.svelte.d.ts +28 -0
- package/dist/components/playground/pipelineViewUtils.svelte.js +38 -1
- package/dist/config/endpoints.d.ts +0 -7
- package/dist/config/endpoints.js +2 -10
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.js +6 -6
- package/dist/display/index.d.ts +0 -2
- package/dist/display/index.js +0 -6
- package/dist/editor/index.d.ts +19 -20
- package/dist/editor/index.js +25 -35
- 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 +17 -13
- package/dist/form/full.js +22 -27
- package/dist/form/index.d.ts +3 -3
- package/dist/form/index.js +3 -3
- 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 +12 -5
- package/dist/helpers/workflowEditorHelper.js +27 -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 +2 -3
- package/dist/playground/index.js +2 -30
- package/dist/playground/mount.d.ts +15 -0
- package/dist/playground/mount.js +46 -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/builtinNodes.d.ts +0 -25
- package/dist/registry/builtinNodes.js +1 -50
- 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.js +0 -1
- package/dist/services/apiVariableService.d.ts +2 -1
- package/dist/services/apiVariableService.js +5 -22
- package/dist/services/autoSaveService.d.ts +7 -0
- package/dist/services/autoSaveService.js +6 -4
- package/dist/services/chatService.d.ts +8 -4
- package/dist/services/chatService.js +15 -15
- 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 +14 -9
- package/dist/services/interruptService.js +27 -27
- package/dist/services/nodeExecutionService.d.ts +18 -3
- package/dist/services/nodeExecutionService.js +71 -45
- package/dist/services/playgroundService.d.ts +14 -9
- package/dist/services/playgroundService.js +31 -30
- 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 +45 -0
- package/dist/stores/apiContext.js +65 -0
- package/dist/stores/categoriesStore.svelte.d.ts +28 -23
- package/dist/stores/categoriesStore.svelte.js +70 -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 +515 -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 +157 -53
- package/dist/types/events.d.ts +6 -3
- package/dist/types/index.d.ts +33 -3
- 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/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 +26 -19
- package/dist/utils/performanceUtils.js +7 -0
- package/package.json +6 -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
|
@@ -24,21 +24,9 @@
|
|
|
24
24
|
} from '../../types/playground.js';
|
|
25
25
|
import { playgroundService } from '../../services/playgroundService.js';
|
|
26
26
|
import { interruptService } from '../../services/interruptService.js';
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
getCurrentSession,
|
|
30
|
-
getSessions,
|
|
31
|
-
getIsExecuting,
|
|
32
|
-
getIsLoading,
|
|
33
|
-
getError,
|
|
34
|
-
playgroundActions,
|
|
35
|
-
applyServerResponse,
|
|
36
|
-
getLatestSequenceNumber,
|
|
37
|
-
getOldestSequenceNumber,
|
|
38
|
-
setHasOlder
|
|
39
|
-
} from '../../stores/playgroundStore.svelte.js';
|
|
27
|
+
import { provideInstance } from '../../stores/getInstance.svelte.js';
|
|
28
|
+
import type { FlowDropInstance } from '../../stores/instanceContainer.svelte.js';
|
|
40
29
|
import type { PlaygroundMessagesApiResponse } from '../../types/playground.js';
|
|
41
|
-
import { interruptActions } from '../../stores/interruptStore.svelte.js';
|
|
42
30
|
import { logger } from '../../utils/logger.js';
|
|
43
31
|
|
|
44
32
|
interface Props {
|
|
@@ -52,6 +40,7 @@
|
|
|
52
40
|
onTogglePanel?: () => void;
|
|
53
41
|
isPipelinePanelOpen?: boolean;
|
|
54
42
|
onSessionNavigate?: (sessionId: string) => void;
|
|
43
|
+
instance?: FlowDropInstance;
|
|
55
44
|
}
|
|
56
45
|
|
|
57
46
|
let {
|
|
@@ -64,9 +53,14 @@
|
|
|
64
53
|
onClose,
|
|
65
54
|
onTogglePanel,
|
|
66
55
|
isPipelinePanelOpen = false,
|
|
67
|
-
onSessionNavigate
|
|
56
|
+
onSessionNavigate,
|
|
57
|
+
instance
|
|
68
58
|
}: Props = $props();
|
|
69
59
|
|
|
60
|
+
// Resolve/provide once at init; the instance prop is a fixed mount-time choice.
|
|
61
|
+
// svelte-ignore state_referenced_locally
|
|
62
|
+
const fd = provideInstance(instance);
|
|
63
|
+
|
|
70
64
|
let loadedInitialSessionId = $state<string | undefined>(undefined);
|
|
71
65
|
let autoRunTriggered = $state(false);
|
|
72
66
|
let isRefreshing = $state(false);
|
|
@@ -78,7 +72,7 @@
|
|
|
78
72
|
|
|
79
73
|
// Vertical resizer state for the ExecutionConsole ↔ ControlPanel split.
|
|
80
74
|
let playgroundContentEl = $state<HTMLElement | null>(null);
|
|
81
|
-
let controlPanelHeight = $state(
|
|
75
|
+
let controlPanelHeight = $state(140);
|
|
82
76
|
let isVerticalResizing = $state(false);
|
|
83
77
|
let containerHeight = $state(0);
|
|
84
78
|
let dragContainerBottom = 0;
|
|
@@ -132,18 +126,18 @@
|
|
|
132
126
|
}
|
|
133
127
|
|
|
134
128
|
onMount(() => {
|
|
135
|
-
if (endpointConfig)
|
|
136
|
-
if (workflow)
|
|
129
|
+
if (endpointConfig) fd.api.configure(endpointConfig);
|
|
130
|
+
if (workflow) fd.playground.setWorkflow(workflow);
|
|
137
131
|
|
|
138
132
|
const handleVisibility = () => {
|
|
139
133
|
if (document.visibilityState === 'visible' && playgroundService.isPolling()) {
|
|
140
|
-
const sessionId =
|
|
134
|
+
const sessionId = fd.playground.currentSession?.id;
|
|
141
135
|
if (sessionId) {
|
|
142
136
|
void playgroundService
|
|
143
|
-
.getMessages(sessionId, {
|
|
137
|
+
.getMessages(fd.api.config, sessionId, {
|
|
144
138
|
since: playgroundService.getLastSequenceNumber() ?? undefined
|
|
145
139
|
})
|
|
146
|
-
.then((response) => applyServerResponse(response, sessionId))
|
|
140
|
+
.then((response) => fd.playground.applyServerResponse(response, sessionId))
|
|
147
141
|
.catch((err) => logger.error('[Playground] Visibility catchup failed:', err));
|
|
148
142
|
}
|
|
149
143
|
}
|
|
@@ -168,7 +162,7 @@
|
|
|
168
162
|
if (!initialSessionId) return;
|
|
169
163
|
if (loadedInitialSessionId === initialSessionId) return;
|
|
170
164
|
|
|
171
|
-
const sessionList =
|
|
165
|
+
const sessionList = fd.playground.sessions;
|
|
172
166
|
if (sessionList.length === 0) return;
|
|
173
167
|
|
|
174
168
|
void loadInitialSession(initialSessionId);
|
|
@@ -194,7 +188,7 @@
|
|
|
194
188
|
}
|
|
195
189
|
|
|
196
190
|
async function loadInitialSession(sessionId: string): Promise<void> {
|
|
197
|
-
const sessionList =
|
|
191
|
+
const sessionList = fd.playground.sessions;
|
|
198
192
|
const sessionExists = sessionList.some((s) => s.id === sessionId);
|
|
199
193
|
|
|
200
194
|
if (!sessionExists) {
|
|
@@ -217,48 +211,48 @@
|
|
|
217
211
|
onDestroy(() => {
|
|
218
212
|
playgroundService.stopPolling();
|
|
219
213
|
interruptService.stopPolling();
|
|
220
|
-
|
|
221
|
-
|
|
214
|
+
fd.playground.reset();
|
|
215
|
+
fd.interrupts.reset();
|
|
222
216
|
});
|
|
223
217
|
|
|
224
218
|
async function loadSessions(): Promise<void> {
|
|
225
|
-
|
|
226
|
-
|
|
219
|
+
fd.playground.setLoading(true);
|
|
220
|
+
fd.playground.setError(null);
|
|
227
221
|
|
|
228
222
|
try {
|
|
229
|
-
const sessionList = await playgroundService.listSessions(workflowId);
|
|
230
|
-
|
|
223
|
+
const sessionList = await playgroundService.listSessions(fd.api.config, workflowId);
|
|
224
|
+
fd.playground.setSessions(sessionList);
|
|
231
225
|
} catch (err) {
|
|
232
226
|
const errorMessage = err instanceof Error ? err.message : 'Failed to load sessions';
|
|
233
|
-
|
|
227
|
+
fd.playground.setError(errorMessage);
|
|
234
228
|
logger.error('Failed to load sessions:', err);
|
|
235
229
|
} finally {
|
|
236
|
-
|
|
230
|
+
fd.playground.setLoading(false);
|
|
237
231
|
}
|
|
238
232
|
}
|
|
239
233
|
|
|
240
234
|
async function loadSession(sessionId: string): Promise<void> {
|
|
241
|
-
|
|
242
|
-
|
|
235
|
+
fd.playground.setLoading(true);
|
|
236
|
+
fd.playground.setError(null);
|
|
243
237
|
const token = ++loadToken;
|
|
244
238
|
|
|
245
239
|
try {
|
|
246
|
-
const session = await playgroundService.getSession(sessionId);
|
|
240
|
+
const session = await playgroundService.getSession(fd.api.config, sessionId);
|
|
247
241
|
if (token !== loadToken) return; // a newer session load superseded us
|
|
248
|
-
|
|
242
|
+
fd.playground.setCurrentSession(session);
|
|
249
243
|
|
|
250
244
|
// Load only the most recent page; older messages load on demand when the
|
|
251
245
|
// user scrolls up (loadOlderMessages). Clear right before applying the
|
|
252
246
|
// fresh page — not before the await — so switching sessions doesn't blank
|
|
253
247
|
// the view for the duration of the fetch.
|
|
254
|
-
const response = await playgroundService.getMessages(sessionId, {
|
|
248
|
+
const response = await playgroundService.getMessages(fd.api.config, sessionId, {
|
|
255
249
|
latest: true,
|
|
256
250
|
limit: messagePageSize
|
|
257
251
|
});
|
|
258
252
|
if (token !== loadToken) return;
|
|
259
|
-
|
|
260
|
-
applyServerResponse(response, sessionId);
|
|
261
|
-
setHasOlder(deriveHasOlder(response));
|
|
253
|
+
fd.playground.clearMessages();
|
|
254
|
+
fd.playground.applyServerResponse(response, sessionId);
|
|
255
|
+
fd.playground.setHasOlder(deriveHasOlder(response));
|
|
262
256
|
|
|
263
257
|
if (session.status !== 'idle') {
|
|
264
258
|
// Seed polling from the newest loaded message so it tails live updates
|
|
@@ -268,10 +262,10 @@
|
|
|
268
262
|
} catch (err) {
|
|
269
263
|
if (token !== loadToken) return; // don't surface a superseded load's error
|
|
270
264
|
const errorMessage = err instanceof Error ? err.message : 'Failed to load session';
|
|
271
|
-
|
|
265
|
+
fd.playground.setError(errorMessage);
|
|
272
266
|
logger.error('Failed to load session:', err);
|
|
273
267
|
} finally {
|
|
274
|
-
if (token === loadToken)
|
|
268
|
+
if (token === loadToken) fd.playground.setLoading(false);
|
|
275
269
|
}
|
|
276
270
|
}
|
|
277
271
|
|
|
@@ -282,22 +276,22 @@
|
|
|
282
276
|
* historical fetch never disturbs the live polling cursor or pipeline view.
|
|
283
277
|
*/
|
|
284
278
|
async function loadOlderMessages(): Promise<void> {
|
|
285
|
-
const sessionId =
|
|
286
|
-
const before =
|
|
279
|
+
const sessionId = fd.playground.currentSession?.id;
|
|
280
|
+
const before = fd.playground.oldestSequenceNumber;
|
|
287
281
|
if (!sessionId || before === null) return;
|
|
288
282
|
|
|
289
283
|
try {
|
|
290
|
-
const response = await playgroundService.getMessages(sessionId, {
|
|
284
|
+
const response = await playgroundService.getMessages(fd.api.config, sessionId, {
|
|
291
285
|
before,
|
|
292
286
|
limit: messagePageSize
|
|
293
287
|
});
|
|
294
288
|
// The session may have changed while the fetch was in flight — don't
|
|
295
289
|
// splice an old session's page into the new session's store.
|
|
296
|
-
if (
|
|
290
|
+
if (fd.playground.currentSession?.id !== sessionId) return;
|
|
297
291
|
if (response.data && response.data.length > 0) {
|
|
298
|
-
|
|
292
|
+
fd.playground.addMessages(response.data);
|
|
299
293
|
}
|
|
300
|
-
setHasOlder(deriveHasOlder(response));
|
|
294
|
+
fd.playground.setHasOlder(deriveHasOlder(response));
|
|
301
295
|
} catch (err) {
|
|
302
296
|
logger.error('[Playground] Failed to load older messages:', err);
|
|
303
297
|
}
|
|
@@ -314,12 +308,12 @@
|
|
|
314
308
|
}
|
|
315
309
|
|
|
316
310
|
async function handleCreateSession(): Promise<void> {
|
|
317
|
-
|
|
318
|
-
|
|
311
|
+
fd.playground.setLoading(true);
|
|
312
|
+
fd.playground.setError(null);
|
|
319
313
|
|
|
320
314
|
try {
|
|
321
|
-
const sessionName = `Session ${
|
|
322
|
-
const session = await playgroundService.createSession(workflowId, sessionName);
|
|
315
|
+
const sessionName = `Session ${fd.playground.sessions.length + 1}`;
|
|
316
|
+
const session = await playgroundService.createSession(fd.api.config, workflowId, sessionName);
|
|
323
317
|
|
|
324
318
|
// Stop polling the previous (possibly running) session before switching,
|
|
325
319
|
// mirroring handleSelectSession. Otherwise its next poll keeps the old
|
|
@@ -331,60 +325,60 @@
|
|
|
331
325
|
return;
|
|
332
326
|
}
|
|
333
327
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
328
|
+
fd.playground.addSession(session);
|
|
329
|
+
fd.playground.setCurrentSession(session);
|
|
330
|
+
fd.playground.clearMessages();
|
|
337
331
|
} catch (err) {
|
|
338
332
|
const errorMessage = err instanceof Error ? err.message : 'Failed to create session';
|
|
339
|
-
|
|
333
|
+
fd.playground.setError(errorMessage);
|
|
340
334
|
logger.error('Failed to create session:', err);
|
|
341
335
|
} finally {
|
|
342
|
-
|
|
336
|
+
fd.playground.setLoading(false);
|
|
343
337
|
}
|
|
344
338
|
}
|
|
345
339
|
|
|
346
340
|
async function handleSelectSession(sessionId: string): Promise<void> {
|
|
347
|
-
|
|
348
|
-
const currentSessionId =
|
|
341
|
+
fd.playground.pinExecution(null);
|
|
342
|
+
const currentSessionId = fd.playground.currentSession?.id;
|
|
349
343
|
if (currentSessionId === sessionId) return;
|
|
350
344
|
|
|
351
345
|
playgroundService.stopPolling();
|
|
352
|
-
|
|
346
|
+
fd.playground.updateSessionStatus('idle');
|
|
353
347
|
await loadSession(sessionId);
|
|
354
348
|
}
|
|
355
349
|
|
|
356
350
|
async function handleDeleteSession(sessionId: string): Promise<void> {
|
|
357
351
|
try {
|
|
358
|
-
await playgroundService.deleteSession(sessionId);
|
|
359
|
-
|
|
352
|
+
await playgroundService.deleteSession(fd.api.config, sessionId);
|
|
353
|
+
fd.playground.removeSession(sessionId);
|
|
360
354
|
|
|
361
|
-
if (
|
|
355
|
+
if (fd.playground.currentSession?.id === sessionId) {
|
|
362
356
|
playgroundService.stopPolling();
|
|
363
357
|
}
|
|
364
358
|
} catch (err) {
|
|
365
359
|
const errorMessage = err instanceof Error ? err.message : 'Failed to delete session';
|
|
366
|
-
|
|
360
|
+
fd.playground.setError(errorMessage);
|
|
367
361
|
logger.error('Failed to delete session:', err);
|
|
368
362
|
}
|
|
369
363
|
}
|
|
370
364
|
|
|
371
365
|
async function handleSendMessage(content: string): Promise<void> {
|
|
372
|
-
if (
|
|
366
|
+
if (fd.playground.isExecuting) return;
|
|
373
367
|
|
|
374
|
-
if (!
|
|
368
|
+
if (!fd.playground.currentSession) {
|
|
375
369
|
await handleCreateSession();
|
|
376
|
-
if (!
|
|
370
|
+
if (!fd.playground.currentSession) return;
|
|
377
371
|
}
|
|
378
372
|
|
|
379
|
-
const sessionId =
|
|
373
|
+
const sessionId = fd.playground.currentSession!.id;
|
|
380
374
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
375
|
+
fd.playground.updateSessionStatus('running');
|
|
376
|
+
fd.playground.pinExecution(null);
|
|
377
|
+
fd.playground.setError(null);
|
|
384
378
|
|
|
385
379
|
try {
|
|
386
|
-
const message = await playgroundService.sendMessage(sessionId, content, {});
|
|
387
|
-
|
|
380
|
+
const message = await playgroundService.sendMessage(fd.api.config, sessionId, content, {});
|
|
381
|
+
fd.playground.addMessage(message);
|
|
388
382
|
// Only start polling if not already active — avoids resetting the cursor
|
|
389
383
|
// mid-session and re-fetching messages that are already in the store.
|
|
390
384
|
// Seed from the newest loaded message so polling tails live updates
|
|
@@ -394,25 +388,25 @@
|
|
|
394
388
|
}
|
|
395
389
|
} catch (err) {
|
|
396
390
|
const errorMessage = err instanceof Error ? err.message : 'Failed to send message';
|
|
397
|
-
|
|
398
|
-
|
|
391
|
+
fd.playground.setError(errorMessage);
|
|
392
|
+
fd.playground.updateSessionStatus('idle');
|
|
399
393
|
logger.error('Failed to send message:', err);
|
|
400
394
|
}
|
|
401
395
|
}
|
|
402
396
|
|
|
403
397
|
async function handleStopExecution(): Promise<void> {
|
|
404
|
-
const sessionId =
|
|
398
|
+
const sessionId = fd.playground.currentSession?.id;
|
|
405
399
|
if (!sessionId) return;
|
|
406
400
|
|
|
407
401
|
try {
|
|
408
|
-
await playgroundService.stopExecution(sessionId);
|
|
402
|
+
await playgroundService.stopExecution(fd.api.config, sessionId);
|
|
409
403
|
playgroundService.stopPolling();
|
|
410
|
-
|
|
404
|
+
fd.playground.updateSessionStatus('idle');
|
|
411
405
|
} catch (err) {
|
|
412
406
|
const errorMessage = err instanceof Error ? err.message : 'Failed to stop execution';
|
|
413
|
-
|
|
407
|
+
fd.playground.setError(errorMessage);
|
|
414
408
|
playgroundService.stopPolling();
|
|
415
|
-
|
|
409
|
+
fd.playground.updateSessionStatus('idle');
|
|
416
410
|
logger.error('Failed to stop execution:', err);
|
|
417
411
|
}
|
|
418
412
|
}
|
|
@@ -423,11 +417,12 @@
|
|
|
423
417
|
overrideShouldStopPolling?: (status: PlaygroundSessionStatus) => boolean
|
|
424
418
|
): void {
|
|
425
419
|
const pollingInterval = config.pollingInterval ?? 1500;
|
|
426
|
-
const initialSequenceNumber = seedSequence ?
|
|
420
|
+
const initialSequenceNumber = seedSequence ? fd.playground.latestSequenceNumber : null;
|
|
427
421
|
|
|
428
422
|
playgroundService.startPolling(
|
|
423
|
+
fd.api.config,
|
|
429
424
|
sessionId,
|
|
430
|
-
(response) => applyServerResponse(response, sessionId),
|
|
425
|
+
(response) => fd.playground.applyServerResponse(response, sessionId),
|
|
431
426
|
pollingInterval,
|
|
432
427
|
overrideShouldStopPolling ?? config.shouldStopPolling,
|
|
433
428
|
initialSequenceNumber
|
|
@@ -435,14 +430,14 @@
|
|
|
435
430
|
}
|
|
436
431
|
|
|
437
432
|
async function refreshFromServer(): Promise<void> {
|
|
438
|
-
const sessionId =
|
|
433
|
+
const sessionId = fd.playground.currentSession?.id;
|
|
439
434
|
if (!sessionId || isRefreshing) return;
|
|
440
435
|
isRefreshing = true;
|
|
441
436
|
try {
|
|
442
|
-
const response = await playgroundService.getMessages(sessionId, {
|
|
437
|
+
const response = await playgroundService.getMessages(fd.api.config, sessionId, {
|
|
443
438
|
since: playgroundService.getLastSequenceNumber() ?? undefined
|
|
444
439
|
});
|
|
445
|
-
applyServerResponse(response, sessionId);
|
|
440
|
+
fd.playground.applyServerResponse(response, sessionId);
|
|
446
441
|
if (response.sessionStatus === 'running' && !playgroundService.isPolling()) {
|
|
447
442
|
startPolling(sessionId, true);
|
|
448
443
|
}
|
|
@@ -454,16 +449,16 @@
|
|
|
454
449
|
}
|
|
455
450
|
|
|
456
451
|
async function handleInterruptResolved(): Promise<void> {
|
|
457
|
-
const sessionId =
|
|
452
|
+
const sessionId = fd.playground.currentSession?.id;
|
|
458
453
|
if (!sessionId) return;
|
|
459
454
|
|
|
460
455
|
try {
|
|
461
456
|
// Catch up immediately rather than waiting for the next poll interval.
|
|
462
457
|
// Use the service's sequence cursor so we only fetch new messages.
|
|
463
|
-
const response = await playgroundService.getMessages(sessionId, {
|
|
458
|
+
const response = await playgroundService.getMessages(fd.api.config, sessionId, {
|
|
464
459
|
since: playgroundService.getLastSequenceNumber() ?? undefined
|
|
465
460
|
});
|
|
466
|
-
applyServerResponse(response, sessionId);
|
|
461
|
+
fd.playground.applyServerResponse(response, sessionId);
|
|
467
462
|
} catch (err) {
|
|
468
463
|
logger.error('[Playground] Failed to refresh after interrupt:', err);
|
|
469
464
|
}
|
|
@@ -483,14 +478,14 @@
|
|
|
483
478
|
class:playground--modal={mode === 'modal'}
|
|
484
479
|
>
|
|
485
480
|
<main class="playground__main">
|
|
486
|
-
{#if
|
|
481
|
+
{#if fd.playground.error}
|
|
487
482
|
<div class="playground__error">
|
|
488
483
|
<Icon icon="mdi:alert-circle" />
|
|
489
|
-
<span>{
|
|
484
|
+
<span>{fd.playground.error}</span>
|
|
490
485
|
<button
|
|
491
486
|
type="button"
|
|
492
487
|
class="playground__error-dismiss"
|
|
493
|
-
onclick={() =>
|
|
488
|
+
onclick={() => fd.playground.setError(null)}
|
|
494
489
|
>
|
|
495
490
|
<Icon icon="mdi:close" />
|
|
496
491
|
</button>
|
|
@@ -498,7 +493,7 @@
|
|
|
498
493
|
{/if}
|
|
499
494
|
|
|
500
495
|
<div class="playground__content" bind:this={playgroundContentEl}>
|
|
501
|
-
{#if
|
|
496
|
+
{#if fd.playground.isLoading && !fd.playground.currentSession}
|
|
502
497
|
<div class="playground__loading">
|
|
503
498
|
<Icon icon="mdi:loading" class="playground__loading-icon" />
|
|
504
499
|
<span>Loading...</span>
|
|
@@ -509,7 +504,7 @@
|
|
|
509
504
|
autoScroll={config.autoScroll ?? true}
|
|
510
505
|
enableMarkdown={config.enableMarkdown ?? true}
|
|
511
506
|
onInterruptResolved={handleInterruptResolved}
|
|
512
|
-
onCreateSession={
|
|
507
|
+
onCreateSession={fd.playground.sessions.length === 0 ? handleCreateSession : undefined}
|
|
513
508
|
onLoadOlder={loadOlderMessages}
|
|
514
509
|
/>
|
|
515
510
|
|
|
@@ -550,6 +545,9 @@
|
|
|
550
545
|
showChatInput={config.showChatInput ?? true}
|
|
551
546
|
showRunButton={config.showRunButton ?? true}
|
|
552
547
|
predefinedMessage={config.predefinedMessage}
|
|
548
|
+
showSessionHeader={config.showSessionHeader ?? true}
|
|
549
|
+
showNewSessionButton={config.showNewSessionButton ?? true}
|
|
550
|
+
showSessionList={config.showSessionList ?? true}
|
|
553
551
|
/>
|
|
554
552
|
{/if}
|
|
555
553
|
</div>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Workflow } from '../../types/index.js';
|
|
2
2
|
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
3
3
|
import type { PlaygroundMode, PlaygroundConfig } from '../../types/playground.js';
|
|
4
|
+
import type { FlowDropInstance } from '../../stores/instanceContainer.svelte.js';
|
|
4
5
|
interface Props {
|
|
5
6
|
workflowId: string;
|
|
6
7
|
workflow?: Workflow;
|
|
@@ -12,6 +13,7 @@ interface Props {
|
|
|
12
13
|
onTogglePanel?: () => void;
|
|
13
14
|
isPipelinePanelOpen?: boolean;
|
|
14
15
|
onSessionNavigate?: (sessionId: string) => void;
|
|
16
|
+
instance?: FlowDropInstance;
|
|
15
17
|
}
|
|
16
18
|
declare const Playground: import("svelte").Component<Props, {}, "">;
|
|
17
19
|
type Playground = ReturnType<typeof Playground>;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import Navbar from '../Navbar.svelte';
|
|
14
14
|
import PlaygroundStudio from './PlaygroundStudio.svelte';
|
|
15
15
|
import type { Workflow } from '../../types/index.js';
|
|
16
|
+
import type { FlowDropInstance } from '../../stores/instanceContainer.svelte.js';
|
|
16
17
|
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
17
18
|
import type { PlaygroundConfig } from '../../types/playground.js';
|
|
18
19
|
import type { SettingsCategory } from '../../types/settings.js';
|
|
@@ -37,6 +38,8 @@
|
|
|
37
38
|
initialPipelineWidth?: number;
|
|
38
39
|
onClose?: () => void;
|
|
39
40
|
onSessionNavigate?: (sessionId: string) => void;
|
|
41
|
+
/** Per-instance state container — forwarded to the inner PlaygroundStudio */
|
|
42
|
+
instance?: FlowDropInstance;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
let {
|
|
@@ -57,7 +60,8 @@
|
|
|
57
60
|
minChatWidth,
|
|
58
61
|
initialPipelineWidth,
|
|
59
62
|
onClose,
|
|
60
|
-
onSessionNavigate
|
|
63
|
+
onSessionNavigate,
|
|
64
|
+
instance
|
|
61
65
|
}: Props = $props();
|
|
62
66
|
|
|
63
67
|
const displayTitle = $derived(navbarTitle ?? workflow?.name ?? 'Playground');
|
|
@@ -77,6 +81,7 @@
|
|
|
77
81
|
{/if}
|
|
78
82
|
<div class="fd-playground-app__content">
|
|
79
83
|
<PlaygroundStudio
|
|
84
|
+
{instance}
|
|
80
85
|
{workflowId}
|
|
81
86
|
{workflow}
|
|
82
87
|
{mode}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Workflow } from '../../types/index.js';
|
|
2
|
+
import type { FlowDropInstance } from '../../stores/instanceContainer.svelte.js';
|
|
2
3
|
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
3
4
|
import type { PlaygroundConfig } from '../../types/playground.js';
|
|
4
5
|
import type { SettingsCategory } from '../../types/settings.js';
|
|
@@ -22,6 +23,8 @@ interface Props {
|
|
|
22
23
|
initialPipelineWidth?: number;
|
|
23
24
|
onClose?: () => void;
|
|
24
25
|
onSessionNavigate?: (sessionId: string) => void;
|
|
26
|
+
/** Per-instance state container — forwarded to the inner PlaygroundStudio */
|
|
27
|
+
instance?: FlowDropInstance;
|
|
25
28
|
}
|
|
26
29
|
declare const PlaygroundApp: import("svelte").Component<Props, {}, "">;
|
|
27
30
|
type PlaygroundApp = ReturnType<typeof PlaygroundApp>;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import Icon from '@iconify/svelte';
|
|
11
11
|
import Playground from './Playground.svelte';
|
|
12
12
|
import type { Workflow } from '../../types/index.js';
|
|
13
|
+
import type { FlowDropInstance } from '../../stores/instanceContainer.svelte.js';
|
|
13
14
|
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
14
15
|
import type { PlaygroundConfig } from '../../types/playground.js';
|
|
15
16
|
import { m } from '../../messages/index.js';
|
|
@@ -30,6 +31,8 @@
|
|
|
30
31
|
endpointConfig?: EndpointConfig;
|
|
31
32
|
/** Playground configuration options */
|
|
32
33
|
config?: PlaygroundConfig;
|
|
34
|
+
/** Per-instance state container — forwarded to the inner Playground */
|
|
35
|
+
instance?: FlowDropInstance;
|
|
33
36
|
/** Callback when modal is closed */
|
|
34
37
|
onClose: () => void;
|
|
35
38
|
}
|
|
@@ -41,9 +44,15 @@
|
|
|
41
44
|
initialSessionId,
|
|
42
45
|
endpointConfig,
|
|
43
46
|
config = {},
|
|
47
|
+
instance,
|
|
44
48
|
onClose
|
|
45
49
|
}: Props = $props();
|
|
46
50
|
|
|
51
|
+
// Unique per component instance so two FlowDrop editors on one page
|
|
52
|
+
// don't render colliding DOM ids (a11y).
|
|
53
|
+
const uid = $props.id();
|
|
54
|
+
const titleId = `${uid}-playground-modal-title`;
|
|
55
|
+
|
|
47
56
|
/**
|
|
48
57
|
* Close modal on Escape key
|
|
49
58
|
*/
|
|
@@ -71,15 +80,15 @@
|
|
|
71
80
|
onkeydown={handleKeydown}
|
|
72
81
|
role="dialog"
|
|
73
82
|
aria-modal="true"
|
|
74
|
-
aria-labelledby=
|
|
83
|
+
aria-labelledby={titleId}
|
|
75
84
|
tabindex="-1"
|
|
76
85
|
>
|
|
77
86
|
<!-- Modal Container -->
|
|
78
|
-
<!--
|
|
87
|
+
<!-- role="presentation" container stops backdrop click propagation -->
|
|
79
88
|
<div class="playground-modal" onclick={(e) => e.stopPropagation()} role="presentation">
|
|
80
89
|
<!-- Modal Header -->
|
|
81
90
|
<div class="playground-modal__header">
|
|
82
|
-
<div class="playground-modal__title" id=
|
|
91
|
+
<div class="playground-modal__title" id={titleId}>
|
|
83
92
|
<Icon icon="mdi:play-circle-outline" />
|
|
84
93
|
<span>Playground</span>
|
|
85
94
|
</div>
|
|
@@ -96,6 +105,7 @@
|
|
|
96
105
|
<!-- Modal Content -->
|
|
97
106
|
<div class="playground-modal__content">
|
|
98
107
|
<Playground
|
|
108
|
+
{instance}
|
|
99
109
|
{workflowId}
|
|
100
110
|
{workflow}
|
|
101
111
|
mode="modal"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Workflow } from '../../types/index.js';
|
|
2
|
+
import type { FlowDropInstance } from '../../stores/instanceContainer.svelte.js';
|
|
2
3
|
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
3
4
|
import type { PlaygroundConfig } from '../../types/playground.js';
|
|
4
5
|
/**
|
|
@@ -17,6 +18,8 @@ interface Props {
|
|
|
17
18
|
endpointConfig?: EndpointConfig;
|
|
18
19
|
/** Playground configuration options */
|
|
19
20
|
config?: PlaygroundConfig;
|
|
21
|
+
/** Per-instance state container — forwarded to the inner Playground */
|
|
22
|
+
instance?: FlowDropInstance;
|
|
20
23
|
/** Callback when modal is closed */
|
|
21
24
|
onClose: () => void;
|
|
22
25
|
}
|