@flowdrop/flowdrop 1.14.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 +110 -66
- 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 +45 -40
- 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 +29 -13
- 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 +292 -0
- package/dist/components/nodes/AtomNode.svelte.d.ts +26 -0
- 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 +95 -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 +7 -3
- package/dist/helpers/proximityConnect.js +19 -6
- 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 +227 -164
- 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 +1 -26
- package/dist/registry/builtinNodes.js +14 -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 +53 -6
- 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 -216
- package/dist/stores/playgroundStore.svelte.js +515 -572
- 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 +71 -6
- 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/formMerge.d.ts +36 -0
- package/dist/utils/formMerge.js +70 -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 +27 -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))
|
|
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);
|
|
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,72 +308,77 @@
|
|
|
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);
|
|
317
|
+
|
|
318
|
+
// Stop polling the previous (possibly running) session before switching,
|
|
319
|
+
// mirroring handleSelectSession. Otherwise its next poll keeps the old
|
|
320
|
+
// 'running' status alive and the new session's chat input stays disabled.
|
|
321
|
+
playgroundService.stopPolling();
|
|
323
322
|
|
|
324
323
|
if (onSessionNavigate) {
|
|
325
324
|
onSessionNavigate(session.id);
|
|
326
325
|
return;
|
|
327
326
|
}
|
|
328
327
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
328
|
+
fd.playground.addSession(session);
|
|
329
|
+
fd.playground.setCurrentSession(session);
|
|
330
|
+
fd.playground.clearMessages();
|
|
332
331
|
} catch (err) {
|
|
333
332
|
const errorMessage = err instanceof Error ? err.message : 'Failed to create session';
|
|
334
|
-
|
|
333
|
+
fd.playground.setError(errorMessage);
|
|
335
334
|
logger.error('Failed to create session:', err);
|
|
336
335
|
} finally {
|
|
337
|
-
|
|
336
|
+
fd.playground.setLoading(false);
|
|
338
337
|
}
|
|
339
338
|
}
|
|
340
339
|
|
|
341
340
|
async function handleSelectSession(sessionId: string): Promise<void> {
|
|
342
|
-
|
|
343
|
-
const currentSessionId =
|
|
341
|
+
fd.playground.pinExecution(null);
|
|
342
|
+
const currentSessionId = fd.playground.currentSession?.id;
|
|
344
343
|
if (currentSessionId === sessionId) return;
|
|
345
344
|
|
|
346
345
|
playgroundService.stopPolling();
|
|
347
|
-
|
|
346
|
+
fd.playground.updateSessionStatus('idle');
|
|
348
347
|
await loadSession(sessionId);
|
|
349
348
|
}
|
|
350
349
|
|
|
351
350
|
async function handleDeleteSession(sessionId: string): Promise<void> {
|
|
352
351
|
try {
|
|
353
|
-
await playgroundService.deleteSession(sessionId);
|
|
354
|
-
|
|
352
|
+
await playgroundService.deleteSession(fd.api.config, sessionId);
|
|
353
|
+
fd.playground.removeSession(sessionId);
|
|
355
354
|
|
|
356
|
-
if (
|
|
355
|
+
if (fd.playground.currentSession?.id === sessionId) {
|
|
357
356
|
playgroundService.stopPolling();
|
|
358
357
|
}
|
|
359
358
|
} catch (err) {
|
|
360
359
|
const errorMessage = err instanceof Error ? err.message : 'Failed to delete session';
|
|
361
|
-
|
|
360
|
+
fd.playground.setError(errorMessage);
|
|
362
361
|
logger.error('Failed to delete session:', err);
|
|
363
362
|
}
|
|
364
363
|
}
|
|
365
364
|
|
|
366
365
|
async function handleSendMessage(content: string): Promise<void> {
|
|
367
|
-
if (
|
|
366
|
+
if (fd.playground.isExecuting) return;
|
|
368
367
|
|
|
369
|
-
if (!
|
|
368
|
+
if (!fd.playground.currentSession) {
|
|
370
369
|
await handleCreateSession();
|
|
371
|
-
if (!
|
|
370
|
+
if (!fd.playground.currentSession) return;
|
|
372
371
|
}
|
|
373
372
|
|
|
374
|
-
const sessionId =
|
|
373
|
+
const sessionId = fd.playground.currentSession!.id;
|
|
375
374
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
375
|
+
fd.playground.updateSessionStatus('running');
|
|
376
|
+
fd.playground.pinExecution(null);
|
|
377
|
+
fd.playground.setError(null);
|
|
379
378
|
|
|
380
379
|
try {
|
|
381
|
-
const message = await playgroundService.sendMessage(sessionId, content, {});
|
|
382
|
-
|
|
380
|
+
const message = await playgroundService.sendMessage(fd.api.config, sessionId, content, {});
|
|
381
|
+
fd.playground.addMessage(message);
|
|
383
382
|
// Only start polling if not already active — avoids resetting the cursor
|
|
384
383
|
// mid-session and re-fetching messages that are already in the store.
|
|
385
384
|
// Seed from the newest loaded message so polling tails live updates
|
|
@@ -389,25 +388,25 @@
|
|
|
389
388
|
}
|
|
390
389
|
} catch (err) {
|
|
391
390
|
const errorMessage = err instanceof Error ? err.message : 'Failed to send message';
|
|
392
|
-
|
|
393
|
-
|
|
391
|
+
fd.playground.setError(errorMessage);
|
|
392
|
+
fd.playground.updateSessionStatus('idle');
|
|
394
393
|
logger.error('Failed to send message:', err);
|
|
395
394
|
}
|
|
396
395
|
}
|
|
397
396
|
|
|
398
397
|
async function handleStopExecution(): Promise<void> {
|
|
399
|
-
const sessionId =
|
|
398
|
+
const sessionId = fd.playground.currentSession?.id;
|
|
400
399
|
if (!sessionId) return;
|
|
401
400
|
|
|
402
401
|
try {
|
|
403
|
-
await playgroundService.stopExecution(sessionId);
|
|
402
|
+
await playgroundService.stopExecution(fd.api.config, sessionId);
|
|
404
403
|
playgroundService.stopPolling();
|
|
405
|
-
|
|
404
|
+
fd.playground.updateSessionStatus('idle');
|
|
406
405
|
} catch (err) {
|
|
407
406
|
const errorMessage = err instanceof Error ? err.message : 'Failed to stop execution';
|
|
408
|
-
|
|
407
|
+
fd.playground.setError(errorMessage);
|
|
409
408
|
playgroundService.stopPolling();
|
|
410
|
-
|
|
409
|
+
fd.playground.updateSessionStatus('idle');
|
|
411
410
|
logger.error('Failed to stop execution:', err);
|
|
412
411
|
}
|
|
413
412
|
}
|
|
@@ -418,11 +417,12 @@
|
|
|
418
417
|
overrideShouldStopPolling?: (status: PlaygroundSessionStatus) => boolean
|
|
419
418
|
): void {
|
|
420
419
|
const pollingInterval = config.pollingInterval ?? 1500;
|
|
421
|
-
const initialSequenceNumber = seedSequence ?
|
|
420
|
+
const initialSequenceNumber = seedSequence ? fd.playground.latestSequenceNumber : null;
|
|
422
421
|
|
|
423
422
|
playgroundService.startPolling(
|
|
423
|
+
fd.api.config,
|
|
424
424
|
sessionId,
|
|
425
|
-
(response) => applyServerResponse(response),
|
|
425
|
+
(response) => fd.playground.applyServerResponse(response, sessionId),
|
|
426
426
|
pollingInterval,
|
|
427
427
|
overrideShouldStopPolling ?? config.shouldStopPolling,
|
|
428
428
|
initialSequenceNumber
|
|
@@ -430,14 +430,14 @@
|
|
|
430
430
|
}
|
|
431
431
|
|
|
432
432
|
async function refreshFromServer(): Promise<void> {
|
|
433
|
-
const sessionId =
|
|
433
|
+
const sessionId = fd.playground.currentSession?.id;
|
|
434
434
|
if (!sessionId || isRefreshing) return;
|
|
435
435
|
isRefreshing = true;
|
|
436
436
|
try {
|
|
437
|
-
const response = await playgroundService.getMessages(sessionId, {
|
|
437
|
+
const response = await playgroundService.getMessages(fd.api.config, sessionId, {
|
|
438
438
|
since: playgroundService.getLastSequenceNumber() ?? undefined
|
|
439
439
|
});
|
|
440
|
-
applyServerResponse(response);
|
|
440
|
+
fd.playground.applyServerResponse(response, sessionId);
|
|
441
441
|
if (response.sessionStatus === 'running' && !playgroundService.isPolling()) {
|
|
442
442
|
startPolling(sessionId, true);
|
|
443
443
|
}
|
|
@@ -449,16 +449,16 @@
|
|
|
449
449
|
}
|
|
450
450
|
|
|
451
451
|
async function handleInterruptResolved(): Promise<void> {
|
|
452
|
-
const sessionId =
|
|
452
|
+
const sessionId = fd.playground.currentSession?.id;
|
|
453
453
|
if (!sessionId) return;
|
|
454
454
|
|
|
455
455
|
try {
|
|
456
456
|
// Catch up immediately rather than waiting for the next poll interval.
|
|
457
457
|
// Use the service's sequence cursor so we only fetch new messages.
|
|
458
|
-
const response = await playgroundService.getMessages(sessionId, {
|
|
458
|
+
const response = await playgroundService.getMessages(fd.api.config, sessionId, {
|
|
459
459
|
since: playgroundService.getLastSequenceNumber() ?? undefined
|
|
460
460
|
});
|
|
461
|
-
applyServerResponse(response);
|
|
461
|
+
fd.playground.applyServerResponse(response, sessionId);
|
|
462
462
|
} catch (err) {
|
|
463
463
|
logger.error('[Playground] Failed to refresh after interrupt:', err);
|
|
464
464
|
}
|
|
@@ -478,14 +478,14 @@
|
|
|
478
478
|
class:playground--modal={mode === 'modal'}
|
|
479
479
|
>
|
|
480
480
|
<main class="playground__main">
|
|
481
|
-
{#if
|
|
481
|
+
{#if fd.playground.error}
|
|
482
482
|
<div class="playground__error">
|
|
483
483
|
<Icon icon="mdi:alert-circle" />
|
|
484
|
-
<span>{
|
|
484
|
+
<span>{fd.playground.error}</span>
|
|
485
485
|
<button
|
|
486
486
|
type="button"
|
|
487
487
|
class="playground__error-dismiss"
|
|
488
|
-
onclick={() =>
|
|
488
|
+
onclick={() => fd.playground.setError(null)}
|
|
489
489
|
>
|
|
490
490
|
<Icon icon="mdi:close" />
|
|
491
491
|
</button>
|
|
@@ -493,7 +493,7 @@
|
|
|
493
493
|
{/if}
|
|
494
494
|
|
|
495
495
|
<div class="playground__content" bind:this={playgroundContentEl}>
|
|
496
|
-
{#if
|
|
496
|
+
{#if fd.playground.isLoading && !fd.playground.currentSession}
|
|
497
497
|
<div class="playground__loading">
|
|
498
498
|
<Icon icon="mdi:loading" class="playground__loading-icon" />
|
|
499
499
|
<span>Loading...</span>
|
|
@@ -504,7 +504,7 @@
|
|
|
504
504
|
autoScroll={config.autoScroll ?? true}
|
|
505
505
|
enableMarkdown={config.enableMarkdown ?? true}
|
|
506
506
|
onInterruptResolved={handleInterruptResolved}
|
|
507
|
-
onCreateSession={
|
|
507
|
+
onCreateSession={fd.playground.sessions.length === 0 ? handleCreateSession : undefined}
|
|
508
508
|
onLoadOlder={loadOlderMessages}
|
|
509
509
|
/>
|
|
510
510
|
|
|
@@ -545,6 +545,9 @@
|
|
|
545
545
|
showChatInput={config.showChatInput ?? true}
|
|
546
546
|
showRunButton={config.showRunButton ?? true}
|
|
547
547
|
predefinedMessage={config.predefinedMessage}
|
|
548
|
+
showSessionHeader={config.showSessionHeader ?? true}
|
|
549
|
+
showNewSessionButton={config.showNewSessionButton ?? true}
|
|
550
|
+
showSessionList={config.showSessionList ?? true}
|
|
548
551
|
/>
|
|
549
552
|
{/if}
|
|
550
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
|
}
|