@flowdrop/flowdrop 1.8.1 → 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.
- package/dist/api/enhanced-client.js +5 -1
- package/dist/components/PipelineStatus.svelte +31 -8
- package/dist/components/PipelineStatus.svelte.d.ts +5 -0
- package/dist/components/WorkflowEditor.svelte +26 -0
- package/dist/components/chat/AIChatPanel.svelte +16 -5
- package/dist/components/playground/ChatPanel.svelte +31 -108
- package/dist/components/playground/ChatPanel.svelte.d.ts +3 -1
- package/dist/components/playground/ExecutionList.svelte +138 -0
- package/dist/components/playground/ExecutionList.svelte.d.ts +10 -0
- package/dist/components/playground/MessageBubble.svelte +281 -156
- package/dist/components/playground/PipelinePanel.svelte +382 -0
- package/dist/components/playground/PipelinePanel.svelte.d.ts +20 -0
- package/dist/components/playground/Playground.svelte +707 -174
- package/dist/components/playground/Playground.svelte.d.ts +6 -0
- package/dist/components/playground/PlaygroundStudio.svelte +404 -0
- package/dist/components/playground/PlaygroundStudio.svelte.d.ts +30 -0
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.js +1 -1
- package/dist/playground/index.d.ts +7 -3
- package/dist/playground/index.js +14 -5
- package/dist/playground/mount.d.ts +7 -0
- package/dist/playground/mount.js +78 -81
- package/dist/services/globalSave.d.ts +7 -0
- package/dist/services/globalSave.js +5 -1
- package/dist/services/nodeExecutionService.js +4 -2
- package/dist/services/playgroundService.d.ts +11 -4
- package/dist/services/playgroundService.js +22 -12
- package/dist/stores/pipelinePanelStore.svelte.d.ts +6 -0
- package/dist/stores/pipelinePanelStore.svelte.js +24 -0
- package/dist/stores/playgroundStore.svelte.d.ts +26 -21
- package/dist/stores/playgroundStore.svelte.js +134 -55
- package/dist/svelte-app.js +25 -2
- package/dist/types/playground.d.ts +15 -5
- package/package.json +1 -1
package/dist/playground/mount.js
CHANGED
|
@@ -46,9 +46,52 @@
|
|
|
46
46
|
import { mount, unmount } from 'svelte';
|
|
47
47
|
import Playground from '../components/playground/Playground.svelte';
|
|
48
48
|
import PlaygroundModal from '../components/playground/PlaygroundModal.svelte';
|
|
49
|
+
import PlaygroundStudio from '../components/playground/PlaygroundStudio.svelte';
|
|
49
50
|
import { setEndpointConfig } from '../services/api.js';
|
|
50
51
|
import { playgroundService } from '../services/playgroundService.js';
|
|
51
|
-
import { getCurrentSession, getSessions, getMessages, playgroundActions,
|
|
52
|
+
import { getCurrentSession, getSessions, getMessages, getIsExecuting, playgroundActions, applyServerResponse, subscribeToSessionStatus } from '../stores/playgroundStore.svelte.js';
|
|
53
|
+
async function resolveEndpointConfig(endpointConfig) {
|
|
54
|
+
if (!endpointConfig)
|
|
55
|
+
return undefined;
|
|
56
|
+
const { defaultEndpointConfig } = await import('../config/endpoints.js');
|
|
57
|
+
const resolved = {
|
|
58
|
+
...defaultEndpointConfig,
|
|
59
|
+
...endpointConfig,
|
|
60
|
+
endpoints: { ...defaultEndpointConfig.endpoints, ...endpointConfig.endpoints }
|
|
61
|
+
};
|
|
62
|
+
setEndpointConfig(resolved);
|
|
63
|
+
return resolved;
|
|
64
|
+
}
|
|
65
|
+
function buildMountedPlayground(svelteApp, workflowId, config, onSessionStatusChange) {
|
|
66
|
+
const pollingInterval = config.pollingInterval ?? 1500;
|
|
67
|
+
const unsubscribeStatus = onSessionStatusChange
|
|
68
|
+
? subscribeToSessionStatus(onSessionStatusChange)
|
|
69
|
+
: undefined;
|
|
70
|
+
return {
|
|
71
|
+
destroy: () => {
|
|
72
|
+
unsubscribeStatus?.();
|
|
73
|
+
playgroundService.stopPolling();
|
|
74
|
+
playgroundActions.reset();
|
|
75
|
+
unmount(svelteApp);
|
|
76
|
+
},
|
|
77
|
+
getCurrentSession: () => getCurrentSession(),
|
|
78
|
+
getSessions: () => getSessions(),
|
|
79
|
+
getMessageCount: () => getMessages().length,
|
|
80
|
+
isExecuting: () => getIsExecuting(),
|
|
81
|
+
stopPolling: () => playgroundService.stopPolling(),
|
|
82
|
+
startPolling: () => {
|
|
83
|
+
const session = getCurrentSession();
|
|
84
|
+
if (session) {
|
|
85
|
+
playgroundService.startPolling(session.id, (response) => applyServerResponse(response), pollingInterval, config.shouldStopPolling, playgroundService.getLastSequenceNumber());
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
pushMessages: (response) => applyServerResponse(response),
|
|
89
|
+
reset: () => {
|
|
90
|
+
playgroundService.stopPolling();
|
|
91
|
+
playgroundActions.reset();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
52
95
|
/**
|
|
53
96
|
* Mount the Playground component in a container
|
|
54
97
|
*
|
|
@@ -91,37 +134,15 @@ export async function mountPlayground(container, options) {
|
|
|
91
134
|
if (mode === 'modal' && !onClose) {
|
|
92
135
|
throw new Error('onClose callback is required for modal mode');
|
|
93
136
|
}
|
|
94
|
-
|
|
95
|
-
let finalEndpointConfig;
|
|
96
|
-
if (endpointConfig) {
|
|
97
|
-
// Merge with default configuration to ensure all required endpoints are present
|
|
98
|
-
const { defaultEndpointConfig } = await import('../config/endpoints.js');
|
|
99
|
-
finalEndpointConfig = {
|
|
100
|
-
...defaultEndpointConfig,
|
|
101
|
-
...endpointConfig,
|
|
102
|
-
endpoints: {
|
|
103
|
-
...defaultEndpointConfig.endpoints,
|
|
104
|
-
...endpointConfig.endpoints
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
setEndpointConfig(finalEndpointConfig);
|
|
108
|
-
}
|
|
109
|
-
// Handle modal mode differently
|
|
110
|
-
// For modal mode, PlaygroundModal creates its own backdrop, so we mount directly to body
|
|
111
|
-
// For other modes, use the provided container
|
|
137
|
+
const finalEndpointConfig = await resolveEndpointConfig(endpointConfig);
|
|
112
138
|
let targetContainer = container;
|
|
113
139
|
if (mode === 'modal') {
|
|
114
|
-
// For modal mode, create a container in the body
|
|
115
|
-
// PlaygroundModal will handle the backdrop itself
|
|
116
140
|
targetContainer = document.body;
|
|
117
141
|
}
|
|
118
142
|
else {
|
|
119
|
-
// Apply container styling for non-modal modes
|
|
120
143
|
container.style.height = height;
|
|
121
144
|
container.style.width = width;
|
|
122
145
|
}
|
|
123
|
-
// Mount the appropriate component
|
|
124
|
-
// Separate the mount calls to avoid TypeScript inference issues with different props types
|
|
125
146
|
let svelteApp;
|
|
126
147
|
if (mode === 'modal') {
|
|
127
148
|
svelteApp = mount(PlaygroundModal, {
|
|
@@ -155,63 +176,7 @@ export async function mountPlayground(container, options) {
|
|
|
155
176
|
}
|
|
156
177
|
});
|
|
157
178
|
}
|
|
158
|
-
|
|
159
|
-
const state = {
|
|
160
|
-
svelteApp,
|
|
161
|
-
container: targetContainer,
|
|
162
|
-
originalContainer: mode === 'modal' ? container : undefined,
|
|
163
|
-
workflowId
|
|
164
|
-
};
|
|
165
|
-
// Create shared polling callback using lifecycle hooks from config
|
|
166
|
-
const pollingCallback = createPollingCallback(config.isTerminalStatus);
|
|
167
|
-
const pollingInterval = config.pollingInterval ?? 1500;
|
|
168
|
-
// Subscribe to session status changes if callback provided
|
|
169
|
-
let unsubscribeStatus;
|
|
170
|
-
if (onSessionStatusChange) {
|
|
171
|
-
unsubscribeStatus = subscribeToSessionStatus(onSessionStatusChange);
|
|
172
|
-
}
|
|
173
|
-
// Create the mounted playground interface
|
|
174
|
-
const mountedPlayground = {
|
|
175
|
-
destroy: () => {
|
|
176
|
-
// Unsubscribe from status changes
|
|
177
|
-
unsubscribeStatus?.();
|
|
178
|
-
// Stop any active polling
|
|
179
|
-
playgroundService.stopPolling();
|
|
180
|
-
// Reset playground state
|
|
181
|
-
playgroundActions.reset();
|
|
182
|
-
// Unmount Svelte component
|
|
183
|
-
unmount(state.svelteApp);
|
|
184
|
-
},
|
|
185
|
-
getCurrentSession: () => {
|
|
186
|
-
return getCurrentSession();
|
|
187
|
-
},
|
|
188
|
-
getSessions: () => {
|
|
189
|
-
return getSessions();
|
|
190
|
-
},
|
|
191
|
-
getMessageCount: () => {
|
|
192
|
-
return getMessages().length;
|
|
193
|
-
},
|
|
194
|
-
isExecuting: () => {
|
|
195
|
-
return playgroundService.isPolling();
|
|
196
|
-
},
|
|
197
|
-
stopPolling: () => {
|
|
198
|
-
playgroundService.stopPolling();
|
|
199
|
-
},
|
|
200
|
-
startPolling: () => {
|
|
201
|
-
const session = getCurrentSession();
|
|
202
|
-
if (session) {
|
|
203
|
-
playgroundService.startPolling(session.id, pollingCallback, pollingInterval, config.shouldStopPolling);
|
|
204
|
-
}
|
|
205
|
-
},
|
|
206
|
-
pushMessages: (response) => {
|
|
207
|
-
pollingCallback(response);
|
|
208
|
-
},
|
|
209
|
-
reset: () => {
|
|
210
|
-
playgroundService.stopPolling();
|
|
211
|
-
playgroundActions.reset();
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
return mountedPlayground;
|
|
179
|
+
return buildMountedPlayground(svelteApp, workflowId, config, onSessionStatusChange);
|
|
215
180
|
}
|
|
216
181
|
/**
|
|
217
182
|
* Unmount a Playground instance
|
|
@@ -233,3 +198,35 @@ export function unmountPlayground(app) {
|
|
|
233
198
|
app.destroy();
|
|
234
199
|
}
|
|
235
200
|
}
|
|
201
|
+
export async function mountPlaygroundStudio(container, options) {
|
|
202
|
+
const { workflowId, workflow, mode = 'standalone', initialSessionId, endpointConfig, config = {}, height = '100%', width = '100%', initialPipelineOpen, minChatWidth, initialPipelineWidth, onClose, onSessionNavigate, onSessionStatusChange } = options;
|
|
203
|
+
if (!workflowId) {
|
|
204
|
+
throw new Error('workflowId is required for mountPlaygroundStudio()');
|
|
205
|
+
}
|
|
206
|
+
if (!container) {
|
|
207
|
+
throw new Error('container element is required for mountPlaygroundStudio()');
|
|
208
|
+
}
|
|
209
|
+
if (mode === 'modal') {
|
|
210
|
+
throw new Error('modal mode is not supported by mountPlaygroundStudio() — use mountPlayground() instead');
|
|
211
|
+
}
|
|
212
|
+
const finalEndpointConfig = await resolveEndpointConfig(endpointConfig);
|
|
213
|
+
container.style.height = height;
|
|
214
|
+
container.style.width = width;
|
|
215
|
+
const svelteApp = mount(PlaygroundStudio, {
|
|
216
|
+
target: container,
|
|
217
|
+
props: {
|
|
218
|
+
workflowId,
|
|
219
|
+
workflow,
|
|
220
|
+
mode,
|
|
221
|
+
initialSessionId,
|
|
222
|
+
endpointConfig: finalEndpointConfig,
|
|
223
|
+
config,
|
|
224
|
+
onClose,
|
|
225
|
+
onSessionNavigate,
|
|
226
|
+
initialPipelineOpen,
|
|
227
|
+
minChatWidth,
|
|
228
|
+
initialPipelineWidth
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
return buildMountedPlayground(svelteApp, workflowId, config, onSessionStatusChange);
|
|
232
|
+
}
|
|
@@ -34,6 +34,13 @@ export interface GlobalSaveOptions {
|
|
|
34
34
|
* Pass workflowStore's markAsSaved here when calling from App.svelte.
|
|
35
35
|
*/
|
|
36
36
|
onMarkAsSaved?: () => void;
|
|
37
|
+
/**
|
|
38
|
+
* Callback invoked after a successful save with the persisted workflow.
|
|
39
|
+
* Receives the server-returned workflow (which may have a different ID than
|
|
40
|
+
* the one sent, e.g. server-assigned integer vs client UUID).
|
|
41
|
+
* Use this to update draft storage keys or other ID-dependent state.
|
|
42
|
+
*/
|
|
43
|
+
onSaved?: (savedWorkflow: Workflow) => void;
|
|
37
44
|
}
|
|
38
45
|
/**
|
|
39
46
|
* Options accepted by globalExportWorkflow().
|
|
@@ -85,7 +85,7 @@ async function flushPendingFormChanges() {
|
|
|
85
85
|
* 7. Show toast notifications (respecting features.showToasts)
|
|
86
86
|
*/
|
|
87
87
|
export async function globalSaveWorkflow(options = {}) {
|
|
88
|
-
const { apiClient, eventHandlers, onMarkAsSaved } = options;
|
|
88
|
+
const { apiClient, eventHandlers, onMarkAsSaved, onSaved } = options;
|
|
89
89
|
const features = { ...DEFAULT_FEATURES, ...options.features };
|
|
90
90
|
// Step 1 — Flush pending form changes (single location for this logic)
|
|
91
91
|
await flushPendingFormChanges();
|
|
@@ -170,6 +170,10 @@ export async function globalSaveWorkflow(options = {}) {
|
|
|
170
170
|
// Fallback: call the store's own markAsSaved if no callback was provided
|
|
171
171
|
storeMarkAsSaved();
|
|
172
172
|
}
|
|
173
|
+
// Notify caller with the definitive saved workflow (server-assigned ID)
|
|
174
|
+
if (onSaved) {
|
|
175
|
+
onSaved(savedWorkflow);
|
|
176
|
+
}
|
|
173
177
|
// Show success toast
|
|
174
178
|
if (loadingToast)
|
|
175
179
|
dismissToast(loadingToast);
|
|
@@ -41,7 +41,8 @@ export class NodeExecutionService {
|
|
|
41
41
|
if (!response.ok) {
|
|
42
42
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
43
43
|
}
|
|
44
|
-
const
|
|
44
|
+
const raw = await response.json();
|
|
45
|
+
const pipelineData = raw.data ?? raw;
|
|
45
46
|
const jobs = pipelineData.jobs || [];
|
|
46
47
|
const nodeStatuses = pipelineData.node_statuses || {};
|
|
47
48
|
// Find the job for this node
|
|
@@ -116,7 +117,8 @@ export class NodeExecutionService {
|
|
|
116
117
|
}
|
|
117
118
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
118
119
|
}
|
|
119
|
-
const
|
|
120
|
+
const raw = await response.json();
|
|
121
|
+
const result = raw.data ?? raw;
|
|
120
122
|
const jobs = result.jobs || [];
|
|
121
123
|
const executionInfoMap = {};
|
|
122
124
|
// Initialize all nodes with default values
|
|
@@ -18,7 +18,7 @@ export declare class PlaygroundService {
|
|
|
18
18
|
private pollingInterval;
|
|
19
19
|
private pollingSessionId;
|
|
20
20
|
private currentBackoff;
|
|
21
|
-
private
|
|
21
|
+
private lastSequenceNumber;
|
|
22
22
|
private constructor();
|
|
23
23
|
/**
|
|
24
24
|
* Get the singleton instance of PlaygroundService
|
|
@@ -78,11 +78,11 @@ export declare class PlaygroundService {
|
|
|
78
78
|
* Get messages from a playground session
|
|
79
79
|
*
|
|
80
80
|
* @param sessionId - The session UUID
|
|
81
|
-
* @param
|
|
81
|
+
* @param afterSequence - Optional sequence number cursor — returns only messages with sequenceNumber > this value
|
|
82
82
|
* @param limit - Maximum number of messages to return
|
|
83
83
|
* @returns Messages and session status
|
|
84
84
|
*/
|
|
85
|
-
getMessages(sessionId: string,
|
|
85
|
+
getMessages(sessionId: string, afterSequence?: number, limit?: number): Promise<PlaygroundMessagesApiResponse>;
|
|
86
86
|
/**
|
|
87
87
|
* Send a message to a playground session
|
|
88
88
|
*
|
|
@@ -105,8 +105,9 @@ export declare class PlaygroundService {
|
|
|
105
105
|
* @param callback - Callback function to handle new messages
|
|
106
106
|
* @param interval - Polling interval in milliseconds (default: 1500)
|
|
107
107
|
* @param shouldStopPolling - Optional override for stop conditions (default: defaultShouldStopPolling)
|
|
108
|
+
* @param initialSequenceNumber - Optional sequence number to seed polling from (avoids re-fetching already loaded messages)
|
|
108
109
|
*/
|
|
109
|
-
startPolling(sessionId: string, callback: (response: PlaygroundMessagesApiResponse) => void, interval?: number, shouldStopPolling?: (status: PlaygroundSessionStatus) => boolean): void;
|
|
110
|
+
startPolling(sessionId: string, callback: (response: PlaygroundMessagesApiResponse) => void, interval?: number, shouldStopPolling?: (status: PlaygroundSessionStatus) => boolean, initialSequenceNumber?: number | null): void;
|
|
110
111
|
/**
|
|
111
112
|
* Stop polling for messages
|
|
112
113
|
*/
|
|
@@ -123,6 +124,12 @@ export declare class PlaygroundService {
|
|
|
123
124
|
* @returns The session ID being polled, or null
|
|
124
125
|
*/
|
|
125
126
|
getPollingSessionId(): string | null;
|
|
127
|
+
/**
|
|
128
|
+
* Get the last sequence number used as cursor for incremental polling
|
|
129
|
+
*
|
|
130
|
+
* @returns The last sequence number, or null
|
|
131
|
+
*/
|
|
132
|
+
getLastSequenceNumber(): number | null;
|
|
126
133
|
}
|
|
127
134
|
/**
|
|
128
135
|
* Export singleton instance
|
|
@@ -29,7 +29,7 @@ export class PlaygroundService {
|
|
|
29
29
|
pollingInterval = null;
|
|
30
30
|
pollingSessionId = null;
|
|
31
31
|
currentBackoff = DEFAULT_POLLING_INTERVAL;
|
|
32
|
-
|
|
32
|
+
lastSequenceNumber = null;
|
|
33
33
|
constructor() { }
|
|
34
34
|
/**
|
|
35
35
|
* Get the singleton instance of PlaygroundService
|
|
@@ -171,19 +171,18 @@ export class PlaygroundService {
|
|
|
171
171
|
* Get messages from a playground session
|
|
172
172
|
*
|
|
173
173
|
* @param sessionId - The session UUID
|
|
174
|
-
* @param
|
|
174
|
+
* @param afterSequence - Optional sequence number cursor — returns only messages with sequenceNumber > this value
|
|
175
175
|
* @param limit - Maximum number of messages to return
|
|
176
176
|
* @returns Messages and session status
|
|
177
177
|
*/
|
|
178
|
-
async getMessages(sessionId,
|
|
178
|
+
async getMessages(sessionId, afterSequence, limit) {
|
|
179
179
|
const config = this.getConfig();
|
|
180
180
|
let url = buildEndpointUrl(config, config.endpoints.playground.getMessages, {
|
|
181
181
|
sessionId
|
|
182
182
|
});
|
|
183
|
-
// Add query parameters
|
|
184
183
|
const params = new URLSearchParams();
|
|
185
|
-
if (
|
|
186
|
-
params.append('since',
|
|
184
|
+
if (afterSequence !== undefined) {
|
|
185
|
+
params.append('since', afterSequence.toString());
|
|
187
186
|
}
|
|
188
187
|
if (limit !== undefined) {
|
|
189
188
|
params.append('limit', limit.toString());
|
|
@@ -244,24 +243,27 @@ export class PlaygroundService {
|
|
|
244
243
|
* @param callback - Callback function to handle new messages
|
|
245
244
|
* @param interval - Polling interval in milliseconds (default: 1500)
|
|
246
245
|
* @param shouldStopPolling - Optional override for stop conditions (default: defaultShouldStopPolling)
|
|
246
|
+
* @param initialSequenceNumber - Optional sequence number to seed polling from (avoids re-fetching already loaded messages)
|
|
247
247
|
*/
|
|
248
|
-
startPolling(sessionId, callback, interval = DEFAULT_POLLING_INTERVAL, shouldStopPolling) {
|
|
248
|
+
startPolling(sessionId, callback, interval = DEFAULT_POLLING_INTERVAL, shouldStopPolling, initialSequenceNumber) {
|
|
249
249
|
// Stop any existing polling
|
|
250
250
|
this.stopPolling();
|
|
251
251
|
this.pollingSessionId = sessionId;
|
|
252
252
|
this.currentBackoff = interval;
|
|
253
|
-
this.
|
|
253
|
+
this.lastSequenceNumber = initialSequenceNumber ?? null;
|
|
254
254
|
const shouldStop = shouldStopPolling ?? defaultShouldStopPolling;
|
|
255
255
|
const poll = async () => {
|
|
256
256
|
if (this.pollingSessionId !== sessionId) {
|
|
257
257
|
return;
|
|
258
258
|
}
|
|
259
259
|
try {
|
|
260
|
-
const response = await this.getMessages(sessionId, this.
|
|
261
|
-
// Update last
|
|
260
|
+
const response = await this.getMessages(sessionId, this.lastSequenceNumber ?? undefined);
|
|
261
|
+
// Update last sequence number cursor
|
|
262
262
|
if (response.data && response.data.length > 0) {
|
|
263
263
|
const lastMessage = response.data[response.data.length - 1];
|
|
264
|
-
|
|
264
|
+
if (lastMessage.sequenceNumber !== undefined) {
|
|
265
|
+
this.lastSequenceNumber = lastMessage.sequenceNumber;
|
|
266
|
+
}
|
|
265
267
|
}
|
|
266
268
|
// Reset backoff on successful request
|
|
267
269
|
this.currentBackoff = interval;
|
|
@@ -295,7 +297,7 @@ export class PlaygroundService {
|
|
|
295
297
|
this.pollingInterval = null;
|
|
296
298
|
}
|
|
297
299
|
this.pollingSessionId = null;
|
|
298
|
-
this.
|
|
300
|
+
this.lastSequenceNumber = null;
|
|
299
301
|
this.currentBackoff = DEFAULT_POLLING_INTERVAL;
|
|
300
302
|
}
|
|
301
303
|
/**
|
|
@@ -314,6 +316,14 @@ export class PlaygroundService {
|
|
|
314
316
|
getPollingSessionId() {
|
|
315
317
|
return this.pollingSessionId;
|
|
316
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Get the last sequence number used as cursor for incremental polling
|
|
321
|
+
*
|
|
322
|
+
* @returns The last sequence number, or null
|
|
323
|
+
*/
|
|
324
|
+
getLastSequenceNumber() {
|
|
325
|
+
return this.lastSequenceNumber;
|
|
326
|
+
}
|
|
317
327
|
}
|
|
318
328
|
/**
|
|
319
329
|
* Export singleton instance
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const STORAGE_KEY = 'fd-pipeline-panel-open';
|
|
2
|
+
let _isOpen = $state(false);
|
|
3
|
+
export function getPipelinePanelOpen() {
|
|
4
|
+
return _isOpen;
|
|
5
|
+
}
|
|
6
|
+
export const pipelinePanelActions = {
|
|
7
|
+
init() {
|
|
8
|
+
if (typeof localStorage !== 'undefined') {
|
|
9
|
+
_isOpen = localStorage.getItem(STORAGE_KEY) === 'true';
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
toggle() {
|
|
13
|
+
_isOpen = !_isOpen;
|
|
14
|
+
if (typeof localStorage !== 'undefined') {
|
|
15
|
+
localStorage.setItem(STORAGE_KEY, String(_isOpen));
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
setOpen(value) {
|
|
19
|
+
_isOpen = value;
|
|
20
|
+
if (typeof localStorage !== 'undefined') {
|
|
21
|
+
localStorage.setItem(STORAGE_KEY, String(value));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -37,13 +37,18 @@ export declare function getError(): string | null;
|
|
|
37
37
|
*/
|
|
38
38
|
export declare function getCurrentWorkflow(): Workflow | null;
|
|
39
39
|
/**
|
|
40
|
-
* Get the last poll
|
|
40
|
+
* Get the last poll sequence number cursor
|
|
41
41
|
*/
|
|
42
|
-
export declare function
|
|
42
|
+
export declare function getLastPollSequenceNumber(): number | null;
|
|
43
43
|
/**
|
|
44
44
|
* Get current session status
|
|
45
45
|
*/
|
|
46
46
|
export declare function getSessionStatus(): PlaygroundSessionStatus;
|
|
47
|
+
/**
|
|
48
|
+
* Whether the user can currently send a message.
|
|
49
|
+
* False when executing, when awaiting input, or when no session exists.
|
|
50
|
+
*/
|
|
51
|
+
export declare function getCanSendMessage(): boolean;
|
|
47
52
|
/**
|
|
48
53
|
* Get message count
|
|
49
54
|
*/
|
|
@@ -75,6 +80,15 @@ export declare function getHasChatInput(): boolean;
|
|
|
75
80
|
* Get session count
|
|
76
81
|
*/
|
|
77
82
|
export declare function getSessionCount(): number;
|
|
83
|
+
export declare function getPinnedExecutionId(): string | null;
|
|
84
|
+
export declare function getLatestExecutionId(): string | null;
|
|
85
|
+
export declare function getActiveExecutionId(): string | null;
|
|
86
|
+
/**
|
|
87
|
+
* Counter that increments whenever new messages arrive and the pipeline display
|
|
88
|
+
* should re-fetch — i.e. when following latest or pinned to the latest execution.
|
|
89
|
+
* Pass to PipelinePanel's refreshTrigger prop.
|
|
90
|
+
*/
|
|
91
|
+
export declare function getPipelineRefreshTrigger(): number;
|
|
78
92
|
/**
|
|
79
93
|
* Playground store actions for modifying state
|
|
80
94
|
*/
|
|
@@ -140,12 +154,6 @@ export declare const playgroundActions: {
|
|
|
140
154
|
* Clear all messages
|
|
141
155
|
*/
|
|
142
156
|
clearMessages: () => void;
|
|
143
|
-
/**
|
|
144
|
-
* Set the executing state
|
|
145
|
-
*
|
|
146
|
-
* @param executing - Whether execution is in progress
|
|
147
|
-
*/
|
|
148
|
-
setExecuting: (executing: boolean) => void;
|
|
149
157
|
/**
|
|
150
158
|
* Set the loading state
|
|
151
159
|
*
|
|
@@ -163,7 +171,7 @@ export declare const playgroundActions: {
|
|
|
163
171
|
*
|
|
164
172
|
* @param timestamp - ISO 8601 timestamp
|
|
165
173
|
*/
|
|
166
|
-
|
|
174
|
+
updateLastPollSequenceNumber: (seq: number) => void;
|
|
167
175
|
/**
|
|
168
176
|
* Reset all playground state
|
|
169
177
|
*/
|
|
@@ -174,16 +182,14 @@ export declare const playgroundActions: {
|
|
|
174
182
|
* @param sessionId - The session ID to switch to
|
|
175
183
|
*/
|
|
176
184
|
switchSession: (sessionId: string) => void;
|
|
185
|
+
pinExecution(executionId: string | null): void;
|
|
177
186
|
};
|
|
178
187
|
/**
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* @param isTerminalStatus - Function to determine if a status clears isExecuting (default: defaultIsTerminalStatus)
|
|
184
|
-
* @returns A callback suitable for playgroundService.startPolling() or pushMessages()
|
|
188
|
+
* Apply a server response to the store. All message and status updates from
|
|
189
|
+
* the server flow through here — polling callback, manual fetches, interrupt
|
|
190
|
+
* resolution. Nothing updates messages or session status except this function.
|
|
185
191
|
*/
|
|
186
|
-
export declare function
|
|
192
|
+
export declare function applyServerResponse(response: PlaygroundMessagesApiResponse): void;
|
|
187
193
|
/**
|
|
188
194
|
* Get the current session ID
|
|
189
195
|
*
|
|
@@ -204,11 +210,11 @@ export declare function isSessionSelected(sessionId: string): boolean;
|
|
|
204
210
|
*/
|
|
205
211
|
export declare function getMessagesSnapshot(): PlaygroundMessage[];
|
|
206
212
|
/**
|
|
207
|
-
* Get the latest message
|
|
213
|
+
* Get the sequence number of the latest message, used to seed incremental polling.
|
|
208
214
|
*
|
|
209
|
-
* @returns
|
|
215
|
+
* @returns Sequence number of the last message, or null
|
|
210
216
|
*/
|
|
211
|
-
export declare function
|
|
217
|
+
export declare function getLatestSequenceNumber(): number | null;
|
|
212
218
|
/**
|
|
213
219
|
* Subscribe to session status changes using $effect.root.
|
|
214
220
|
* This is designed for use in non-component contexts (e.g., mount.ts).
|
|
@@ -224,7 +230,6 @@ export declare function subscribeToSessionStatus(callback: (status: PlaygroundSe
|
|
|
224
230
|
* has stopped but new messages may exist on the server.
|
|
225
231
|
*
|
|
226
232
|
* @param fetchMessages - Async function to fetch messages from the API
|
|
227
|
-
* @param isTerminalStatus - Optional override for terminal status check
|
|
228
233
|
* @returns Promise that resolves when messages are refreshed
|
|
229
234
|
*/
|
|
230
|
-
export declare function refreshSessionMessages(fetchMessages: (sessionId: string) => Promise<PlaygroundMessagesApiResponse
|
|
235
|
+
export declare function refreshSessionMessages(fetchMessages: (sessionId: string) => Promise<PlaygroundMessagesApiResponse>): Promise<void>;
|