@flowdrop/flowdrop 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,404 @@
1
+ <!--
2
+ PlaygroundStudio Component
3
+
4
+ Drop-in embeddable split-pane layout: PipelinePanel (left, resizable) + Playground
5
+ chat (right). Provides the same integrated experience as the FlowDrop demo app with a
6
+ single import and zero layout glue code.
7
+
8
+ @example Basic usage — workflow fetched automatically
9
+ ```svelte
10
+ <script>
11
+ import { PlaygroundStudio, createEndpointConfig } from '@flowdrop/flowdrop/playground';
12
+ import '@flowdrop/flowdrop/styles';
13
+ </script>
14
+
15
+ <PlaygroundStudio
16
+ workflowId="wf-123"
17
+ endpointConfig={createEndpointConfig('/api/flowdrop')}
18
+ />
19
+ ```
20
+
21
+ @example With pre-loaded workflow and URL-based session routing
22
+ ```svelte
23
+ <script>
24
+ import { PlaygroundStudio, createEndpointConfig } from '@flowdrop/flowdrop/playground';
25
+
26
+ let { data } = $props(); // workflow from server load
27
+ let sessionId = $derived($page.params.sessionId);
28
+
29
+ function handleSessionNavigate(id) {
30
+ goto(`/playground/${id}`);
31
+ }
32
+ </script>
33
+
34
+ <PlaygroundStudio
35
+ workflowId={data.workflow.id}
36
+ workflow={data.workflow}
37
+ endpointConfig={createEndpointConfig('/api/flowdrop')}
38
+ initialSessionId={sessionId}
39
+ onSessionNavigate={handleSessionNavigate}
40
+ />
41
+ ```
42
+ -->
43
+
44
+ <script lang="ts">
45
+ import { onMount } from 'svelte';
46
+ import Icon from '@iconify/svelte';
47
+ import Playground from './Playground.svelte';
48
+ import PipelinePanel from './PipelinePanel.svelte';
49
+ import { getPipelinePanelOpen, pipelinePanelActions } from '../../stores/pipelinePanelStore.svelte.js';
50
+ import {
51
+ getActiveExecutionId,
52
+ getPinnedExecutionId,
53
+ getLatestExecutionId,
54
+ getPipelineRefreshTrigger,
55
+ getCurrentSession,
56
+ playgroundActions,
57
+ } from '../../stores/playgroundStore.svelte.js';
58
+ import { setEndpointConfig, workflowApi } from '../../services/api.js';
59
+ import { logger } from '../../utils/logger.js';
60
+ import type { Workflow } from '../../types/index.js';
61
+ import type { EndpointConfig } from '../../config/endpoints.js';
62
+ import type { PlaygroundConfig, PlaygroundMode } from '../../types/playground.js';
63
+
64
+ interface Props {
65
+ /** Target workflow ID */
66
+ workflowId: string;
67
+ /** Pre-loaded workflow — skips internal fetch when provided */
68
+ workflow?: Workflow;
69
+ /** API endpoint configuration */
70
+ endpointConfig?: EndpointConfig;
71
+ /** Display mode (default: standalone) */
72
+ mode?: PlaygroundMode;
73
+ /** Session ID to activate on mount. Changing this prop remounts the Playground. */
74
+ initialSessionId?: string;
75
+ /** Playground configuration options */
76
+ config?: PlaygroundConfig;
77
+ /** Whether the pipeline panel starts open. When omitted the stored preference is used. */
78
+ initialPipelineOpen?: boolean;
79
+ /** Minimum chat panel width in px (default: 760) */
80
+ minChatWidth?: number;
81
+ /** Initial pipeline panel width in px (default: 500) */
82
+ initialPipelineWidth?: number;
83
+ /** Called when session navigation is requested — use for URL-based routing */
84
+ onSessionNavigate?: (sessionId: string) => void;
85
+ /** Called when the playground is closed (embedded / modal mode) */
86
+ onClose?: () => void;
87
+ }
88
+
89
+ let {
90
+ workflowId,
91
+ workflow: workflowProp,
92
+ endpointConfig,
93
+ mode = 'standalone',
94
+ initialSessionId,
95
+ config = {},
96
+ initialPipelineOpen,
97
+ minChatWidth = 760,
98
+ initialPipelineWidth = 500,
99
+ onSessionNavigate,
100
+ onClose,
101
+ }: Props = $props();
102
+
103
+ // svelte-ignore state_referenced_locally
104
+ let resolvedWorkflow = $state<Workflow | null>(workflowProp ?? null);
105
+ // svelte-ignore state_referenced_locally
106
+ let workflowLoading = $state(workflowProp === undefined);
107
+ let workflowError = $state<string | null>(null);
108
+
109
+ let splitEl = $state<HTMLElement | null>(null);
110
+ // svelte-ignore state_referenced_locally
111
+ let pipelineWidth = $state(initialPipelineWidth);
112
+ let isResizing = $state(false);
113
+ let containerWidth = $state(0);
114
+
115
+ $effect(() => {
116
+ if (!splitEl) return;
117
+ const observer = new ResizeObserver(([entry]) => {
118
+ containerWidth = entry.contentRect.width;
119
+ });
120
+ observer.observe(splitEl);
121
+ return () => observer.disconnect();
122
+ });
123
+
124
+ onMount(() => {
125
+ pipelinePanelActions.init();
126
+ if (initialPipelineOpen !== undefined) {
127
+ pipelinePanelActions.setOpen(initialPipelineOpen);
128
+ }
129
+ if (endpointConfig) {
130
+ setEndpointConfig(endpointConfig);
131
+ }
132
+ if (!workflowProp) {
133
+ void loadWorkflow();
134
+ }
135
+ });
136
+
137
+ async function loadWorkflow(): Promise<void> {
138
+ if (!endpointConfig) {
139
+ workflowError = 'Provide a workflow prop or an endpointConfig so the workflow can be fetched.';
140
+ workflowLoading = false;
141
+ return;
142
+ }
143
+
144
+ try {
145
+ workflowLoading = true;
146
+ workflowError = null;
147
+ resolvedWorkflow = await workflowApi.getWorkflow(workflowId);
148
+ } catch (err) {
149
+ workflowError = err instanceof Error ? err.message : 'Failed to load workflow';
150
+ logger.error('[PlaygroundStudio] Workflow load failed:', err);
151
+ } finally {
152
+ workflowLoading = false;
153
+ }
154
+ }
155
+
156
+ function handleResizerPointerDown(e: PointerEvent) {
157
+ isResizing = true;
158
+ (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
159
+ }
160
+
161
+ function handleResizerPointerMove(e: PointerEvent) {
162
+ if (!isResizing || !splitEl) return;
163
+ const rect = splitEl.getBoundingClientRect();
164
+ pipelineWidth = Math.min(
165
+ Math.max(e.clientX - rect.left, rect.width - minChatWidth),
166
+ rect.width * 0.75
167
+ );
168
+ }
169
+
170
+ function handleResizerPointerUp() {
171
+ isResizing = false;
172
+ }
173
+ </script>
174
+
175
+ <div class="playground-studio" class:playground-studio--resizing={isResizing} style="--playground-studio-min-chat-width: {minChatWidth}px">
176
+ <div class="playground-studio__panes" bind:this={splitEl}>
177
+ {#if getPipelinePanelOpen() && resolvedWorkflow && endpointConfig}
178
+ {@const activeId = getActiveExecutionId()}
179
+ {@const executions = getCurrentSession()?.executions ?? []}
180
+
181
+ <div class="playground-studio__pipeline" style="width: {pipelineWidth}px;">
182
+ <PipelinePanel
183
+ pipelineId={activeId}
184
+ workflow={resolvedWorkflow}
185
+ {endpointConfig}
186
+ isPinned={getPinnedExecutionId() !== null}
187
+ {executions}
188
+ latestExecutionId={getLatestExecutionId()}
189
+ onSelectExecution={(id) => playgroundActions.pinExecution(id)}
190
+ refreshTrigger={getPipelineRefreshTrigger()}
191
+ />
192
+ </div>
193
+
194
+ <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
195
+ <div
196
+ class="playground-studio__resizer"
197
+ class:playground-studio__resizer--active={isResizing}
198
+ role="separator"
199
+ aria-orientation="vertical"
200
+ aria-valuenow={Math.round(pipelineWidth)}
201
+ aria-valuemin={0}
202
+ aria-valuemax={Math.round(containerWidth * 0.75)}
203
+ tabindex="0"
204
+ onpointerdown={handleResizerPointerDown}
205
+ onpointermove={handleResizerPointerMove}
206
+ onpointerup={handleResizerPointerUp}
207
+ onpointercancel={handleResizerPointerUp}
208
+ >
209
+ <div class="playground-studio__resizer-handle"></div>
210
+ </div>
211
+ {/if}
212
+
213
+ <div
214
+ class="playground-studio__chat"
215
+ class:playground-studio__chat--solo={!getPipelinePanelOpen()}
216
+ >
217
+ {#if workflowLoading}
218
+ <div class="playground-studio__loading">
219
+ <Icon icon="mdi:loading" class="playground-studio__loading-icon" />
220
+ <p>Loading workflow...</p>
221
+ </div>
222
+ {:else if workflowError}
223
+ <div class="playground-studio__error">
224
+ <Icon icon="mdi:alert-circle" class="playground-studio__error-icon" />
225
+ <p class="playground-studio__error-text">{workflowError}</p>
226
+ <button type="button" class="playground-studio__retry-btn" onclick={loadWorkflow}>
227
+ <Icon icon="mdi:refresh" />
228
+ Retry
229
+ </button>
230
+ </div>
231
+ {:else if resolvedWorkflow}
232
+ {#key initialSessionId}
233
+ <Playground
234
+ {workflowId}
235
+ workflow={resolvedWorkflow}
236
+ {endpointConfig}
237
+ {mode}
238
+ {initialSessionId}
239
+ {config}
240
+ {onClose}
241
+ {onSessionNavigate}
242
+ onTogglePanel={pipelinePanelActions.toggle}
243
+ isPipelinePanelOpen={getPipelinePanelOpen()}
244
+ />
245
+ {/key}
246
+ {/if}
247
+ </div>
248
+ </div>
249
+ </div>
250
+
251
+ <style>
252
+ .playground-studio {
253
+ display: flex;
254
+ flex-direction: column;
255
+ height: 100%;
256
+ min-height: 0;
257
+ overflow: hidden;
258
+ background-color: var(--fd-background);
259
+ }
260
+
261
+ .playground-studio--resizing {
262
+ cursor: col-resize;
263
+ user-select: none;
264
+ }
265
+
266
+ .playground-studio__panes {
267
+ display: flex;
268
+ flex-direction: row;
269
+ flex: 1;
270
+ min-height: 0;
271
+ overflow: hidden;
272
+ }
273
+
274
+ /* Pipeline pane — explicit width set via inline style */
275
+ .playground-studio__pipeline {
276
+ min-width: calc(100% - var(--playground-studio-min-chat-width));
277
+ max-width: 75%;
278
+ overflow: hidden;
279
+ flex-shrink: 0;
280
+ }
281
+
282
+ /* Drag handle between the two panes */
283
+ .playground-studio__resizer {
284
+ width: 8px;
285
+ flex-shrink: 0;
286
+ cursor: col-resize;
287
+ background-color: var(--fd-background);
288
+ border-right: 1px solid var(--fd-border);
289
+ border-left: 1px solid var(--fd-border);
290
+ display: flex;
291
+ align-items: center;
292
+ justify-content: center;
293
+ touch-action: none;
294
+ z-index: 1;
295
+ transition: background-color var(--fd-transition-normal);
296
+ }
297
+
298
+ .playground-studio__resizer:hover,
299
+ .playground-studio__resizer--active {
300
+ background-color: var(--fd-primary-muted);
301
+ }
302
+
303
+ .playground-studio__resizer-handle {
304
+ width: 4px;
305
+ height: 48px;
306
+ background-color: var(--fd-border-strong);
307
+ border-radius: var(--fd-radius-sm);
308
+ transition:
309
+ background-color var(--fd-transition-normal),
310
+ transform var(--fd-transition-normal);
311
+ }
312
+
313
+ .playground-studio__resizer:hover .playground-studio__resizer-handle {
314
+ background-color: var(--fd-primary);
315
+ transform: scaleY(1.2);
316
+ }
317
+
318
+ .playground-studio__resizer--active .playground-studio__resizer-handle {
319
+ background-color: var(--fd-primary-hover);
320
+ transform: scaleY(1.4);
321
+ }
322
+
323
+ /* Chat pane — fills remaining space */
324
+ .playground-studio__chat {
325
+ flex: 1;
326
+ min-width: 0;
327
+ overflow: hidden;
328
+ display: flex;
329
+ flex-direction: column;
330
+ }
331
+
332
+ .playground-studio__chat--solo {
333
+ border-left: 1px solid var(--fd-border);
334
+ border-right: 1px solid var(--fd-border);
335
+ }
336
+
337
+ /* Loading state */
338
+ .playground-studio__loading {
339
+ display: flex;
340
+ flex-direction: column;
341
+ align-items: center;
342
+ justify-content: center;
343
+ height: 100%;
344
+ color: var(--fd-muted-foreground);
345
+ gap: var(--fd-space-md);
346
+ }
347
+
348
+ :global(.playground-studio__loading-icon) {
349
+ font-size: var(--fd-space-6xl);
350
+ animation: studio-spin 1s linear infinite;
351
+ }
352
+
353
+ @keyframes studio-spin {
354
+ from {
355
+ transform: rotate(0deg);
356
+ }
357
+ to {
358
+ transform: rotate(360deg);
359
+ }
360
+ }
361
+
362
+ /* Error state */
363
+ .playground-studio__error {
364
+ display: flex;
365
+ flex-direction: column;
366
+ align-items: center;
367
+ justify-content: center;
368
+ height: 100%;
369
+ padding: var(--fd-space-4xl);
370
+ text-align: center;
371
+ gap: var(--fd-space-md);
372
+ }
373
+
374
+ :global(.playground-studio__error-icon) {
375
+ font-size: var(--fd-space-7xl);
376
+ color: var(--fd-error);
377
+ }
378
+
379
+ .playground-studio__error-text {
380
+ font-size: var(--fd-text-base);
381
+ color: var(--fd-muted-foreground);
382
+ margin: 0;
383
+ max-width: 400px;
384
+ }
385
+
386
+ .playground-studio__retry-btn {
387
+ display: inline-flex;
388
+ align-items: center;
389
+ gap: var(--fd-space-xs);
390
+ padding: var(--fd-space-md) var(--fd-space-3xl);
391
+ border: none;
392
+ border-radius: var(--fd-radius-lg);
393
+ background-color: var(--fd-primary);
394
+ color: var(--fd-primary-foreground);
395
+ font-size: var(--fd-text-base);
396
+ font-weight: 500;
397
+ cursor: pointer;
398
+ transition: background-color var(--fd-transition-normal);
399
+ }
400
+
401
+ .playground-studio__retry-btn:hover {
402
+ background-color: var(--fd-primary-hover);
403
+ }
404
+ </style>
@@ -0,0 +1,30 @@
1
+ import type { Workflow } from '../../types/index.js';
2
+ import type { EndpointConfig } from '../../config/endpoints.js';
3
+ import type { PlaygroundConfig, PlaygroundMode } from '../../types/playground.js';
4
+ interface Props {
5
+ /** Target workflow ID */
6
+ workflowId: string;
7
+ /** Pre-loaded workflow — skips internal fetch when provided */
8
+ workflow?: Workflow;
9
+ /** API endpoint configuration */
10
+ endpointConfig?: EndpointConfig;
11
+ /** Display mode (default: standalone) */
12
+ mode?: PlaygroundMode;
13
+ /** Session ID to activate on mount. Changing this prop remounts the Playground. */
14
+ initialSessionId?: string;
15
+ /** Playground configuration options */
16
+ config?: PlaygroundConfig;
17
+ /** Whether the pipeline panel starts open. When omitted the stored preference is used. */
18
+ initialPipelineOpen?: boolean;
19
+ /** Minimum chat panel width in px (default: 760) */
20
+ minChatWidth?: number;
21
+ /** Initial pipeline panel width in px (default: 500) */
22
+ initialPipelineWidth?: number;
23
+ /** Called when session navigation is requested — use for URL-based routing */
24
+ onSessionNavigate?: (sessionId: string) => void;
25
+ /** Called when the playground is closed (embedded / modal mode) */
26
+ onClose?: () => void;
27
+ }
28
+ declare const PlaygroundStudio: import("svelte").Component<Props, {}, "">;
29
+ type PlaygroundStudio = ReturnType<typeof PlaygroundStudio>;
30
+ export default PlaygroundStudio;
@@ -76,7 +76,7 @@ export { setEndpointConfig, getEndpointConfig, nodeApi, workflowApi, api } from
76
76
  export { showSuccess, showError, showWarning, showInfo, showLoading, dismissToast, dismissAllToasts, showPromise, showConfirmation, apiToasts, workflowToasts, pipelineToasts } from '../services/toastService.js';
77
77
  export { NodeExecutionService, nodeExecutionService } from '../services/nodeExecutionService.js';
78
78
  export { PlaygroundService, playgroundService } from '../services/playgroundService.js';
79
- export { getCurrentSession, getSessions, getMessages, getIsExecuting, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollTimestamp, getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount, playgroundActions, createPollingCallback, subscribeToSessionStatus, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestMessageTimestamp } from '../stores/playgroundStore.svelte.js';
79
+ export { getCurrentSession, getSessions, getMessages, getIsExecuting, getCanSendMessage, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollSequenceNumber, getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount, playgroundActions, applyServerResponse, subscribeToSessionStatus, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestSequenceNumber } from '../stores/playgroundStore.svelte.js';
80
80
  export { saveWorkflow, updateWorkflow, getWorkflow, getWorkflows, deleteWorkflow, getWorkflowCount, initializeSampleWorkflows } from '../services/workflowStorage.js';
81
81
  export { globalSaveWorkflow, globalExportWorkflow } from '../services/globalSave.js';
82
82
  export { fetchPortConfig, validatePortConfig } from '../services/portConfigApi.js';
@@ -119,7 +119,7 @@ export { showSuccess, showError, showWarning, showInfo, showLoading, dismissToas
119
119
  export { NodeExecutionService, nodeExecutionService } from '../services/nodeExecutionService.js';
120
120
  // Playground Service and Store
121
121
  export { PlaygroundService, playgroundService } from '../services/playgroundService.js';
122
- export { getCurrentSession, getSessions, getMessages, getIsExecuting, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollTimestamp, getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount, playgroundActions, createPollingCallback, subscribeToSessionStatus, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestMessageTimestamp } from '../stores/playgroundStore.svelte.js';
122
+ export { getCurrentSession, getSessions, getMessages, getIsExecuting, getCanSendMessage, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollSequenceNumber, getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount, playgroundActions, applyServerResponse, subscribeToSessionStatus, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestSequenceNumber } from '../stores/playgroundStore.svelte.js';
123
123
  export { saveWorkflow, updateWorkflow, getWorkflow, getWorkflows, deleteWorkflow, getWorkflowCount, initializeSampleWorkflows } from '../services/workflowStorage.js';
124
124
  export { globalSaveWorkflow, globalExportWorkflow } from '../services/globalSave.js';
125
125
  export { fetchPortConfig, validatePortConfig } from '../services/portConfigApi.js';
@@ -111,8 +111,11 @@
111
111
  * ```
112
112
  */
113
113
  export { default as Playground } from '../components/playground/Playground.svelte';
114
+ export { default as PlaygroundStudio } from '../components/playground/PlaygroundStudio.svelte';
114
115
  export { default as PlaygroundModal } from '../components/playground/PlaygroundModal.svelte';
115
116
  export { default as ChatPanel } from '../components/playground/ChatPanel.svelte';
117
+ export { default as PipelinePanel } from '../components/playground/PipelinePanel.svelte';
118
+ export { default as ExecutionList } from '../components/playground/ExecutionList.svelte';
116
119
  export { default as SessionManager } from '../components/playground/SessionManager.svelte';
117
120
  export { default as InputCollector } from '../components/playground/InputCollector.svelte';
118
121
  export { default as ExecutionLogs } from '../components/playground/ExecutionLogs.svelte';
@@ -120,12 +123,13 @@ export { default as MessageBubble } from '../components/playground/MessageBubble
120
123
  export { InterruptBubble, ConfirmationPrompt, ChoicePrompt, TextInputPrompt, FormPrompt, ReviewPrompt } from '../components/interrupt/index.js';
121
124
  export { PlaygroundService, playgroundService } from '../services/playgroundService.js';
122
125
  export { InterruptService, interruptService } from '../services/interruptService.js';
123
- export { getCurrentSession, getSessions, getMessages, getIsExecuting, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollTimestamp, getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount, playgroundActions, createPollingCallback, subscribeToSessionStatus, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestMessageTimestamp } from '../stores/playgroundStore.svelte.js';
124
- export type { PlaygroundSession, PlaygroundMessage, PlaygroundInputField, PlaygroundMessageRequest, PlaygroundMessagesResult, PlaygroundConfig, PlaygroundMode, PlaygroundSessionStatus, PlaygroundMessageRole, PlaygroundMessageLevel, PlaygroundMessageMetadata, PlaygroundApiResponse, PlaygroundSessionsResponse, PlaygroundSessionResponse, PlaygroundMessageResponse, PlaygroundMessagesApiResponse } from '../types/playground.js';
126
+ export { getCurrentSession, getSessions, getMessages, getIsExecuting, getCanSendMessage, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollSequenceNumber, getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount, getActiveExecutionId, getPinnedExecutionId, getLatestExecutionId, playgroundActions, applyServerResponse, subscribeToSessionStatus, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestSequenceNumber } from '../stores/playgroundStore.svelte.js';
127
+ export { getPipelinePanelOpen, pipelinePanelActions } from '../stores/pipelinePanelStore.svelte.js';
128
+ export type { PlaygroundSession, PlaygroundMessage, PlaygroundInputField, PlaygroundMessageRequest, PlaygroundMessagesResult, PlaygroundConfig, PlaygroundMode, PlaygroundSessionStatus, PlaygroundMessageRole, PlaygroundMessageLevel, PlaygroundMessageMetadata, PlaygroundApiResponse, PlaygroundSessionsResponse, PlaygroundSessionResponse, PlaygroundMessageResponse, PlaygroundMessagesApiResponse, PlaygroundExecution } from '../types/playground.js';
125
129
  export { isChatInputNode, CHAT_INPUT_PATTERNS, defaultShouldStopPolling, defaultIsTerminalStatus, DEFAULT_STOP_POLLING_STATUSES, DEFAULT_TERMINAL_STATUSES } from '../types/playground.js';
126
130
  export type { InterruptType, InterruptStatus, Interrupt, InterruptChoice, InterruptConfig, ConfirmationConfig, ChoiceConfig, TextConfig, FormConfig, ReviewConfig, ReviewChange, ReviewFieldDecision, ReviewResolution, InterruptResolution, InterruptApiResponse, InterruptListResponse, InterruptResponse, InterruptMessageMetadata, InterruptPollingConfig } from '../types/interrupt.js';
127
131
  export { isInterruptMetadata, extractInterruptMetadata, metadataToInterrupt, defaultInterruptPollingConfig } from '../types/interrupt.js';
128
132
  export { getInterruptsMap, getPendingInterruptIds, getPendingInterrupts, getPendingInterruptCount, getResolvedInterrupts, getIsAnySubmitting, interruptActions, getInterrupt, isInterruptPending, isInterruptSubmitting, getInterruptError, getInterruptByMessageId, interruptHasError } from '../stores/interruptStore.svelte.js';
129
133
  export type { InterruptWithState } from '../stores/interruptStore.svelte.js';
130
- export { mountPlayground, unmountPlayground, type PlaygroundMountOptions, type MountedPlayground } from './mount.js';
134
+ export { mountPlayground, unmountPlayground, mountPlaygroundStudio, type PlaygroundMountOptions, type PlaygroundStudioMountOptions, type MountedPlayground } from './mount.js';
131
135
  export { createEndpointConfig, defaultEndpointConfig, buildEndpointUrl, type EndpointConfig } from '../config/endpoints.js';
@@ -114,8 +114,11 @@
114
114
  // Playground Components
115
115
  // ============================================================================
116
116
  export { default as Playground } from '../components/playground/Playground.svelte';
117
+ export { default as PlaygroundStudio } from '../components/playground/PlaygroundStudio.svelte';
117
118
  export { default as PlaygroundModal } from '../components/playground/PlaygroundModal.svelte';
118
119
  export { default as ChatPanel } from '../components/playground/ChatPanel.svelte';
120
+ export { default as PipelinePanel } from '../components/playground/PipelinePanel.svelte';
121
+ export { default as ExecutionList } from '../components/playground/ExecutionList.svelte';
119
122
  export { default as SessionManager } from '../components/playground/SessionManager.svelte';
120
123
  export { default as InputCollector } from '../components/playground/InputCollector.svelte';
121
124
  export { default as ExecutionLogs } from '../components/playground/ExecutionLogs.svelte';
@@ -137,17 +140,23 @@ export { InterruptService, interruptService } from '../services/interruptService
137
140
  // ============================================================================
138
141
  export {
139
142
  // Core state getters
140
- getCurrentSession, getSessions, getMessages, getIsExecuting, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollTimestamp,
143
+ getCurrentSession, getSessions, getMessages, getIsExecuting, getCanSendMessage, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollSequenceNumber,
141
144
  // Derived getters
142
145
  getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount,
146
+ // Execution getters (used with PipelinePanel / PlaygroundSplit)
147
+ getActiveExecutionId, getPinnedExecutionId, getLatestExecutionId,
143
148
  // Actions
144
149
  playgroundActions,
145
- // Polling callback factory
146
- createPollingCallback,
150
+ // Server response application (single update path)
151
+ applyServerResponse,
147
152
  // Subscription utility
148
153
  subscribeToSessionStatus,
149
154
  // Utilities
150
- getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestMessageTimestamp } from '../stores/playgroundStore.svelte.js';
155
+ getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestSequenceNumber } from '../stores/playgroundStore.svelte.js';
156
+ // ============================================================================
157
+ // Pipeline Panel Store (open/close state, persisted to localStorage)
158
+ // ============================================================================
159
+ export { getPipelinePanelOpen, pipelinePanelActions } from '../stores/pipelinePanelStore.svelte.js';
151
160
  export { isChatInputNode, CHAT_INPUT_PATTERNS, defaultShouldStopPolling, defaultIsTerminalStatus, DEFAULT_STOP_POLLING_STATUSES, DEFAULT_TERMINAL_STATUSES } from '../types/playground.js';
152
161
  export { isInterruptMetadata, extractInterruptMetadata, metadataToInterrupt, defaultInterruptPollingConfig } from '../types/interrupt.js';
153
162
  // ============================================================================
@@ -165,7 +174,7 @@ getInterrupt, isInterruptPending, isInterruptSubmitting, getInterruptError, getI
165
174
  // ============================================================================
166
175
  // Playground Mount Functions (for vanilla JS / Drupal / IIFE integration)
167
176
  // ============================================================================
168
- export { mountPlayground, unmountPlayground } from './mount.js';
177
+ export { mountPlayground, unmountPlayground, mountPlaygroundStudio } from './mount.js';
169
178
  // ============================================================================
170
179
  // Endpoint Configuration (re-exported for convenience)
171
180
  // ============================================================================
@@ -201,3 +201,10 @@ export declare function mountPlayground(container: HTMLElement, options: Playgro
201
201
  * ```
202
202
  */
203
203
  export declare function unmountPlayground(app: MountedPlayground): void;
204
+ export interface PlaygroundStudioMountOptions extends PlaygroundMountOptions {
205
+ initialPipelineOpen?: boolean;
206
+ minChatWidth?: number;
207
+ initialPipelineWidth?: number;
208
+ onSessionNavigate?: (sessionId: string) => void;
209
+ }
210
+ export declare function mountPlaygroundStudio(container: HTMLElement, options: PlaygroundStudioMountOptions): Promise<MountedPlayground>;