@d34dman/flowdrop 0.0.59 → 0.0.61
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/components/App.svelte +18 -3
- package/dist/components/playground/Playground.svelte +10 -44
- package/dist/playground/index.d.ts +2 -2
- package/dist/playground/index.js +3 -1
- package/dist/playground/mount.d.ts +20 -1
- package/dist/playground/mount.js +27 -2
- package/dist/services/playgroundService.d.ts +3 -2
- package/dist/services/playgroundService.js +6 -6
- package/dist/stores/playgroundStore.d.ts +11 -1
- package/dist/stores/playgroundStore.js +29 -16
- package/dist/types/playground.d.ts +37 -1
- package/dist/types/playground.js +38 -0
- package/package.json +1 -1
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
<script lang="ts">
|
|
8
8
|
import { onMount, tick } from 'svelte';
|
|
9
|
-
import { page } from '$app/stores';
|
|
10
9
|
import MainLayout from './layouts/MainLayout.svelte';
|
|
11
10
|
import WorkflowEditor from './WorkflowEditor.svelte';
|
|
12
11
|
import NodeSidebar from './NodeSidebar.svelte';
|
|
@@ -617,7 +616,7 @@
|
|
|
617
616
|
|
|
618
617
|
await fetchNodeTypes();
|
|
619
618
|
|
|
620
|
-
// Initialize the workflow store
|
|
619
|
+
// Initialize the workflow store
|
|
621
620
|
if (initialWorkflow) {
|
|
622
621
|
workflowActions.initialize(initialWorkflow);
|
|
623
622
|
|
|
@@ -625,6 +624,22 @@
|
|
|
625
624
|
if (eventHandlers?.onWorkflowLoad) {
|
|
626
625
|
eventHandlers.onWorkflowLoad(initialWorkflow);
|
|
627
626
|
}
|
|
627
|
+
} else {
|
|
628
|
+
// Initialize with a default empty workflow so the editor is functional
|
|
629
|
+
// (e.g., drag-and-drop requires a non-null workflow in the store)
|
|
630
|
+
const defaultWorkflow: Workflow = {
|
|
631
|
+
id: '',
|
|
632
|
+
name: 'Untitled Workflow',
|
|
633
|
+
nodes: [],
|
|
634
|
+
edges: [],
|
|
635
|
+
metadata: {
|
|
636
|
+
version: '1.0.0',
|
|
637
|
+
format: DEFAULT_WORKFLOW_FORMAT,
|
|
638
|
+
createdAt: new Date().toISOString(),
|
|
639
|
+
updatedAt: new Date().toISOString()
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
workflowActions.initialize(defaultWorkflow);
|
|
628
643
|
}
|
|
629
644
|
})();
|
|
630
645
|
|
|
@@ -684,7 +699,7 @@
|
|
|
684
699
|
|
|
685
700
|
<!-- MainLayout wrapper for workflow editor -->
|
|
686
701
|
<MainLayout
|
|
687
|
-
showHeader={showNavbar
|
|
702
|
+
showHeader={showNavbar}
|
|
688
703
|
showLeftSidebar={!disableSidebar}
|
|
689
704
|
showRightSidebar={showRightPanel}
|
|
690
705
|
showBottomPanel={false}
|
|
@@ -15,8 +15,7 @@
|
|
|
15
15
|
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
16
16
|
import type {
|
|
17
17
|
PlaygroundMode,
|
|
18
|
-
PlaygroundConfig
|
|
19
|
-
PlaygroundMessagesApiResponse
|
|
18
|
+
PlaygroundConfig
|
|
20
19
|
} from '../../types/playground.js';
|
|
21
20
|
import { playgroundService } from '../../services/playgroundService.js';
|
|
22
21
|
import { interruptService } from '../../services/interruptService.js';
|
|
@@ -29,7 +28,8 @@
|
|
|
29
28
|
isLoading,
|
|
30
29
|
error,
|
|
31
30
|
playgroundActions,
|
|
32
|
-
inputFields
|
|
31
|
+
inputFields,
|
|
32
|
+
createPollingCallback
|
|
33
33
|
} from '../../stores/playgroundStore.js';
|
|
34
34
|
import { interruptActions } from '../../stores/interruptStore.js';
|
|
35
35
|
import { get } from 'svelte/store';
|
|
@@ -408,6 +408,9 @@
|
|
|
408
408
|
}
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
+
/** Shared polling callback created from config lifecycle hooks */
|
|
412
|
+
const pollingCallback = createPollingCallback(config.isTerminalStatus);
|
|
413
|
+
|
|
411
414
|
/**
|
|
412
415
|
* Start polling for messages
|
|
413
416
|
*/
|
|
@@ -416,28 +419,9 @@
|
|
|
416
419
|
|
|
417
420
|
playgroundService.startPolling(
|
|
418
421
|
sessionId,
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
playgroundActions.addMessages(response.data);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// Update session status
|
|
426
|
-
if (response.sessionStatus) {
|
|
427
|
-
playgroundActions.updateSessionStatus(response.sessionStatus);
|
|
428
|
-
|
|
429
|
-
// Stop executing if idle, completed, or failed
|
|
430
|
-
// "idle" means no processing is happening (execution finished)
|
|
431
|
-
if (
|
|
432
|
-
response.sessionStatus === 'idle' ||
|
|
433
|
-
response.sessionStatus === 'completed' ||
|
|
434
|
-
response.sessionStatus === 'failed'
|
|
435
|
-
) {
|
|
436
|
-
playgroundActions.setExecuting(false);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
},
|
|
440
|
-
pollingInterval
|
|
422
|
+
pollingCallback,
|
|
423
|
+
pollingInterval,
|
|
424
|
+
config.shouldStopPolling
|
|
441
425
|
);
|
|
442
426
|
}
|
|
443
427
|
|
|
@@ -451,25 +435,7 @@
|
|
|
451
435
|
|
|
452
436
|
try {
|
|
453
437
|
const response = await playgroundService.getMessages(sessionId);
|
|
454
|
-
|
|
455
|
-
// Add new messages (deduplicates automatically)
|
|
456
|
-
if (response.data && response.data.length > 0) {
|
|
457
|
-
playgroundActions.addMessages(response.data);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// Update session status
|
|
461
|
-
if (response.sessionStatus) {
|
|
462
|
-
playgroundActions.updateSessionStatus(response.sessionStatus);
|
|
463
|
-
|
|
464
|
-
// Update executing state based on session status
|
|
465
|
-
if (
|
|
466
|
-
response.sessionStatus === 'idle' ||
|
|
467
|
-
response.sessionStatus === 'completed' ||
|
|
468
|
-
response.sessionStatus === 'failed'
|
|
469
|
-
) {
|
|
470
|
-
playgroundActions.setExecuting(false);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
438
|
+
pollingCallback(response);
|
|
473
439
|
} catch (err) {
|
|
474
440
|
console.error('[Playground] Failed to refresh messages after interrupt:', err);
|
|
475
441
|
}
|
|
@@ -120,9 +120,9 @@ export { default as MessageBubble } from '../components/playground/MessageBubble
|
|
|
120
120
|
export { InterruptBubble, ConfirmationPrompt, ChoicePrompt, TextInputPrompt, FormPrompt } from '../components/interrupt/index.js';
|
|
121
121
|
export { PlaygroundService, playgroundService } from '../services/playgroundService.js';
|
|
122
122
|
export { InterruptService, interruptService } from '../services/interruptService.js';
|
|
123
|
-
export { currentSession, sessions, messages, isExecuting, isLoading, error as playgroundError, currentWorkflow, lastPollTimestamp, sessionStatus, messageCount, chatMessages, logMessages, latestMessage, inputFields, hasChatInput, sessionCount, playgroundActions, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestMessageTimestamp } from '../stores/playgroundStore.js';
|
|
123
|
+
export { currentSession, sessions, messages, isExecuting, isLoading, error as playgroundError, currentWorkflow, lastPollTimestamp, sessionStatus, messageCount, chatMessages, logMessages, latestMessage, inputFields, hasChatInput, sessionCount, playgroundActions, createPollingCallback, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestMessageTimestamp } from '../stores/playgroundStore.js';
|
|
124
124
|
export type { PlaygroundSession, PlaygroundMessage, PlaygroundInputField, PlaygroundMessageRequest, PlaygroundMessagesResult, PlaygroundConfig, PlaygroundMode, PlaygroundSessionStatus, PlaygroundMessageRole, PlaygroundMessageLevel, PlaygroundMessageMetadata, PlaygroundApiResponse, PlaygroundSessionsResponse, PlaygroundSessionResponse, PlaygroundMessageResponse, PlaygroundMessagesApiResponse } from '../types/playground.js';
|
|
125
|
-
export { isChatInputNode, CHAT_INPUT_PATTERNS } from '../types/playground.js';
|
|
125
|
+
export { isChatInputNode, CHAT_INPUT_PATTERNS, defaultShouldStopPolling, defaultIsTerminalStatus, DEFAULT_STOP_POLLING_STATUSES, DEFAULT_TERMINAL_STATUSES } from '../types/playground.js';
|
|
126
126
|
export type { InterruptType, InterruptStatus, Interrupt, InterruptChoice, InterruptConfig, ConfirmationConfig, ChoiceConfig, TextConfig, FormConfig, InterruptResolution, InterruptApiResponse, InterruptListResponse, InterruptResponse, InterruptMessageMetadata, InterruptPollingConfig } from '../types/interrupt.js';
|
|
127
127
|
export { isInterruptMetadata, extractInterruptMetadata, metadataToInterrupt, defaultInterruptPollingConfig } from '../types/interrupt.js';
|
|
128
128
|
export { interrupts, pendingInterruptIds, pendingInterrupts, pendingInterruptCount, resolvedInterrupts, isAnySubmitting, interruptActions, getInterrupt, isInterruptPending, isInterruptSubmitting, getInterruptError, getInterruptByMessageId } from '../stores/interruptStore.js';
|
package/dist/playground/index.js
CHANGED
|
@@ -142,9 +142,11 @@ currentSession, sessions, messages, isExecuting, isLoading, error as playgroundE
|
|
|
142
142
|
sessionStatus, messageCount, chatMessages, logMessages, latestMessage, inputFields, hasChatInput, sessionCount,
|
|
143
143
|
// Actions
|
|
144
144
|
playgroundActions,
|
|
145
|
+
// Polling callback factory
|
|
146
|
+
createPollingCallback,
|
|
145
147
|
// Utilities
|
|
146
148
|
getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestMessageTimestamp } from '../stores/playgroundStore.js';
|
|
147
|
-
export { isChatInputNode, CHAT_INPUT_PATTERNS } from '../types/playground.js';
|
|
149
|
+
export { isChatInputNode, CHAT_INPUT_PATTERNS, defaultShouldStopPolling, defaultIsTerminalStatus, DEFAULT_STOP_POLLING_STATUSES, DEFAULT_TERMINAL_STATUSES } from '../types/playground.js';
|
|
148
150
|
export { isInterruptMetadata, extractInterruptMetadata, metadataToInterrupt, defaultInterruptPollingConfig } from '../types/interrupt.js';
|
|
149
151
|
// ============================================================================
|
|
150
152
|
// Interrupt Store (Human-in-the-Loop)
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
*/
|
|
46
46
|
import type { Workflow } from '../types/index.js';
|
|
47
47
|
import type { EndpointConfig } from '../config/endpoints.js';
|
|
48
|
-
import type { PlaygroundMode, PlaygroundConfig, PlaygroundSession } from '../types/playground.js';
|
|
48
|
+
import type { PlaygroundMode, PlaygroundConfig, PlaygroundSession, PlaygroundMessagesApiResponse, PlaygroundSessionStatus } from '../types/playground.js';
|
|
49
49
|
/**
|
|
50
50
|
* Mount options for Playground component
|
|
51
51
|
*/
|
|
@@ -96,6 +96,13 @@ export interface PlaygroundMountOptions {
|
|
|
96
96
|
* Callback when playground is closed (required for embedded and modal modes)
|
|
97
97
|
*/
|
|
98
98
|
onClose?: () => void;
|
|
99
|
+
/**
|
|
100
|
+
* Called when session status changes (from polling or actions)
|
|
101
|
+
*
|
|
102
|
+
* @param status - The new session status
|
|
103
|
+
* @param previousStatus - The previous session status
|
|
104
|
+
*/
|
|
105
|
+
onSessionStatusChange?: (status: PlaygroundSessionStatus, previousStatus: PlaygroundSessionStatus) => void;
|
|
99
106
|
}
|
|
100
107
|
/**
|
|
101
108
|
* Return type for mounted Playground instance
|
|
@@ -130,6 +137,18 @@ export interface MountedPlayground {
|
|
|
130
137
|
* Stop any active polling
|
|
131
138
|
*/
|
|
132
139
|
stopPolling: () => void;
|
|
140
|
+
/**
|
|
141
|
+
* Restart polling for the current session
|
|
142
|
+
* Useful after polling stops (e.g., on awaiting_input) and you want to resume
|
|
143
|
+
*/
|
|
144
|
+
startPolling: () => void;
|
|
145
|
+
/**
|
|
146
|
+
* Push a poll response into the store pipeline.
|
|
147
|
+
* Use with custom transports (WebSocket/SSE) instead of built-in polling.
|
|
148
|
+
*
|
|
149
|
+
* @param response - A PlaygroundMessagesApiResponse to process
|
|
150
|
+
*/
|
|
151
|
+
pushMessages: (response: PlaygroundMessagesApiResponse) => void;
|
|
133
152
|
/**
|
|
134
153
|
* Reset the playground state
|
|
135
154
|
* Clears the current session and messages
|
package/dist/playground/mount.js
CHANGED
|
@@ -48,7 +48,7 @@ import Playground from '../components/playground/Playground.svelte';
|
|
|
48
48
|
import PlaygroundModal from '../components/playground/PlaygroundModal.svelte';
|
|
49
49
|
import { setEndpointConfig } from '../services/api.js';
|
|
50
50
|
import { playgroundService } from '../services/playgroundService.js';
|
|
51
|
-
import { currentSession, sessions, messages, playgroundActions } from '../stores/playgroundStore.js';
|
|
51
|
+
import { currentSession, sessions, messages, sessionStatus, playgroundActions, createPollingCallback } from '../stores/playgroundStore.js';
|
|
52
52
|
import { get } from 'svelte/store';
|
|
53
53
|
/**
|
|
54
54
|
* Mount the Playground component in a container
|
|
@@ -80,7 +80,7 @@ import { get } from 'svelte/store';
|
|
|
80
80
|
* ```
|
|
81
81
|
*/
|
|
82
82
|
export async function mountPlayground(container, options) {
|
|
83
|
-
const { workflowId, workflow, mode = 'standalone', initialSessionId, endpointConfig, config = {}, height = '100%', width = '100%', onClose } = options;
|
|
83
|
+
const { workflowId, workflow, mode = 'standalone', initialSessionId, endpointConfig, config = {}, height = '100%', width = '100%', onClose, onSessionStatusChange } = options;
|
|
84
84
|
// Validate required parameters
|
|
85
85
|
if (!workflowId) {
|
|
86
86
|
throw new Error('workflowId is required for mountPlayground()');
|
|
@@ -163,9 +163,25 @@ export async function mountPlayground(container, options) {
|
|
|
163
163
|
originalContainer: mode === 'modal' ? container : undefined,
|
|
164
164
|
workflowId
|
|
165
165
|
};
|
|
166
|
+
// Create shared polling callback using lifecycle hooks from config
|
|
167
|
+
const pollingCallback = createPollingCallback(config.isTerminalStatus);
|
|
168
|
+
const pollingInterval = config.pollingInterval ?? 1500;
|
|
169
|
+
// Subscribe to session status changes if callback provided
|
|
170
|
+
let unsubscribeStatus;
|
|
171
|
+
if (onSessionStatusChange) {
|
|
172
|
+
let previousStatus = get(sessionStatus);
|
|
173
|
+
unsubscribeStatus = sessionStatus.subscribe((status) => {
|
|
174
|
+
if (status !== previousStatus) {
|
|
175
|
+
onSessionStatusChange(status, previousStatus);
|
|
176
|
+
previousStatus = status;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
166
180
|
// Create the mounted playground interface
|
|
167
181
|
const mountedPlayground = {
|
|
168
182
|
destroy: () => {
|
|
183
|
+
// Unsubscribe from status changes
|
|
184
|
+
unsubscribeStatus?.();
|
|
169
185
|
// Stop any active polling
|
|
170
186
|
playgroundService.stopPolling();
|
|
171
187
|
// Reset playground state
|
|
@@ -188,6 +204,15 @@ export async function mountPlayground(container, options) {
|
|
|
188
204
|
stopPolling: () => {
|
|
189
205
|
playgroundService.stopPolling();
|
|
190
206
|
},
|
|
207
|
+
startPolling: () => {
|
|
208
|
+
const session = get(currentSession);
|
|
209
|
+
if (session) {
|
|
210
|
+
playgroundService.startPolling(session.id, pollingCallback, pollingInterval, config.shouldStopPolling);
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
pushMessages: (response) => {
|
|
214
|
+
pollingCallback(response);
|
|
215
|
+
},
|
|
191
216
|
reset: () => {
|
|
192
217
|
playgroundService.stopPolling();
|
|
193
218
|
playgroundActions.reset();
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module services/playgroundService
|
|
8
8
|
*/
|
|
9
|
-
import type { PlaygroundSession, PlaygroundMessage, PlaygroundMessagesApiResponse } from '../types/playground.js';
|
|
9
|
+
import type { PlaygroundSession, PlaygroundMessage, PlaygroundMessagesApiResponse, PlaygroundSessionStatus } from '../types/playground.js';
|
|
10
10
|
/**
|
|
11
11
|
* Playground Service class
|
|
12
12
|
*
|
|
@@ -104,8 +104,9 @@ export declare class PlaygroundService {
|
|
|
104
104
|
* @param sessionId - The session UUID to poll
|
|
105
105
|
* @param callback - Callback function to handle new messages
|
|
106
106
|
* @param interval - Polling interval in milliseconds (default: 1500)
|
|
107
|
+
* @param shouldStopPolling - Optional override for stop conditions (default: defaultShouldStopPolling)
|
|
107
108
|
*/
|
|
108
|
-
startPolling(sessionId: string, callback: (response: PlaygroundMessagesApiResponse) => void, interval?: number): void;
|
|
109
|
+
startPolling(sessionId: string, callback: (response: PlaygroundMessagesApiResponse) => void, interval?: number, shouldStopPolling?: (status: PlaygroundSessionStatus) => boolean): void;
|
|
109
110
|
/**
|
|
110
111
|
* Stop polling for messages
|
|
111
112
|
*/
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module services/playgroundService
|
|
8
8
|
*/
|
|
9
|
+
import { defaultShouldStopPolling } from '../types/playground.js';
|
|
9
10
|
import { buildEndpointUrl, getEndpointHeaders } from '../config/endpoints.js';
|
|
10
11
|
import { getEndpointConfig } from './api.js';
|
|
11
12
|
/**
|
|
@@ -241,13 +242,15 @@ export class PlaygroundService {
|
|
|
241
242
|
* @param sessionId - The session UUID to poll
|
|
242
243
|
* @param callback - Callback function to handle new messages
|
|
243
244
|
* @param interval - Polling interval in milliseconds (default: 1500)
|
|
245
|
+
* @param shouldStopPolling - Optional override for stop conditions (default: defaultShouldStopPolling)
|
|
244
246
|
*/
|
|
245
|
-
startPolling(sessionId, callback, interval = DEFAULT_POLLING_INTERVAL) {
|
|
247
|
+
startPolling(sessionId, callback, interval = DEFAULT_POLLING_INTERVAL, shouldStopPolling) {
|
|
246
248
|
// Stop any existing polling
|
|
247
249
|
this.stopPolling();
|
|
248
250
|
this.pollingSessionId = sessionId;
|
|
249
251
|
this.currentBackoff = interval;
|
|
250
252
|
this.lastMessageTimestamp = null;
|
|
253
|
+
const shouldStop = shouldStopPolling ?? defaultShouldStopPolling;
|
|
251
254
|
const poll = async () => {
|
|
252
255
|
if (this.pollingSessionId !== sessionId) {
|
|
253
256
|
return;
|
|
@@ -263,11 +266,8 @@ export class PlaygroundService {
|
|
|
263
266
|
this.currentBackoff = interval;
|
|
264
267
|
// Call the callback with new messages
|
|
265
268
|
callback(response);
|
|
266
|
-
// Stop polling if
|
|
267
|
-
|
|
268
|
-
if (response.sessionStatus === 'idle' ||
|
|
269
|
-
response.sessionStatus === 'completed' ||
|
|
270
|
-
response.sessionStatus === 'failed') {
|
|
269
|
+
// Stop polling if the status matches the stop condition
|
|
270
|
+
if (response.sessionStatus && shouldStop(response.sessionStatus)) {
|
|
271
271
|
this.stopPolling();
|
|
272
272
|
return;
|
|
273
273
|
}
|
|
@@ -175,6 +175,15 @@ export declare const playgroundActions: {
|
|
|
175
175
|
*/
|
|
176
176
|
switchSession: (sessionId: string) => void;
|
|
177
177
|
};
|
|
178
|
+
/**
|
|
179
|
+
* Create a polling callback that processes poll responses.
|
|
180
|
+
* This is the single source of truth for how poll responses update stores.
|
|
181
|
+
* Used by mount.ts, Playground.svelte, and refreshSessionMessages.
|
|
182
|
+
*
|
|
183
|
+
* @param isTerminalStatus - Function to determine if a status clears isExecuting (default: defaultIsTerminalStatus)
|
|
184
|
+
* @returns A callback suitable for playgroundService.startPolling() or pushMessages()
|
|
185
|
+
*/
|
|
186
|
+
export declare function createPollingCallback(isTerminalStatus?: (status: PlaygroundSessionStatus) => boolean): (response: PlaygroundMessagesApiResponse) => void;
|
|
178
187
|
/**
|
|
179
188
|
* Get the current session ID
|
|
180
189
|
*
|
|
@@ -207,6 +216,7 @@ export declare function getLatestMessageTimestamp(): string | null;
|
|
|
207
216
|
* has stopped but new messages may exist on the server.
|
|
208
217
|
*
|
|
209
218
|
* @param fetchMessages - Async function to fetch messages from the API
|
|
219
|
+
* @param isTerminalStatus - Optional override for terminal status check
|
|
210
220
|
* @returns Promise that resolves when messages are refreshed
|
|
211
221
|
*/
|
|
212
|
-
export declare function refreshSessionMessages(fetchMessages: (sessionId: string) => Promise<PlaygroundMessagesApiResponse
|
|
222
|
+
export declare function refreshSessionMessages(fetchMessages: (sessionId: string) => Promise<PlaygroundMessagesApiResponse>, isTerminalStatus?: (status: PlaygroundSessionStatus) => boolean): Promise<void>;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @module stores/playgroundStore
|
|
8
8
|
*/
|
|
9
9
|
import { writable, derived, get } from 'svelte/store';
|
|
10
|
-
import { isChatInputNode } from '../types/playground.js';
|
|
10
|
+
import { isChatInputNode, defaultIsTerminalStatus } from '../types/playground.js';
|
|
11
11
|
// =========================================================================
|
|
12
12
|
// Core Stores
|
|
13
13
|
// =========================================================================
|
|
@@ -348,6 +348,30 @@ export const playgroundActions = {
|
|
|
348
348
|
}
|
|
349
349
|
};
|
|
350
350
|
// =========================================================================
|
|
351
|
+
// Polling Callback Factory
|
|
352
|
+
// =========================================================================
|
|
353
|
+
/**
|
|
354
|
+
* Create a polling callback that processes poll responses.
|
|
355
|
+
* This is the single source of truth for how poll responses update stores.
|
|
356
|
+
* Used by mount.ts, Playground.svelte, and refreshSessionMessages.
|
|
357
|
+
*
|
|
358
|
+
* @param isTerminalStatus - Function to determine if a status clears isExecuting (default: defaultIsTerminalStatus)
|
|
359
|
+
* @returns A callback suitable for playgroundService.startPolling() or pushMessages()
|
|
360
|
+
*/
|
|
361
|
+
export function createPollingCallback(isTerminalStatus = defaultIsTerminalStatus) {
|
|
362
|
+
return (response) => {
|
|
363
|
+
if (response.data && response.data.length > 0) {
|
|
364
|
+
playgroundActions.addMessages(response.data);
|
|
365
|
+
}
|
|
366
|
+
if (response.sessionStatus) {
|
|
367
|
+
playgroundActions.updateSessionStatus(response.sessionStatus);
|
|
368
|
+
if (isTerminalStatus(response.sessionStatus)) {
|
|
369
|
+
playgroundActions.setExecuting(false);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
// =========================================================================
|
|
351
375
|
// Utilities
|
|
352
376
|
// =========================================================================
|
|
353
377
|
/**
|
|
@@ -393,28 +417,17 @@ export function getLatestMessageTimestamp() {
|
|
|
393
417
|
* has stopped but new messages may exist on the server.
|
|
394
418
|
*
|
|
395
419
|
* @param fetchMessages - Async function to fetch messages from the API
|
|
420
|
+
* @param isTerminalStatus - Optional override for terminal status check
|
|
396
421
|
* @returns Promise that resolves when messages are refreshed
|
|
397
422
|
*/
|
|
398
|
-
export async function refreshSessionMessages(fetchMessages) {
|
|
423
|
+
export async function refreshSessionMessages(fetchMessages, isTerminalStatus) {
|
|
399
424
|
const session = get(currentSession);
|
|
400
425
|
if (!session)
|
|
401
426
|
return;
|
|
402
427
|
try {
|
|
403
428
|
const response = await fetchMessages(session.id);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
playgroundActions.addMessages(response.data);
|
|
407
|
-
}
|
|
408
|
-
// Update session status
|
|
409
|
-
if (response.sessionStatus) {
|
|
410
|
-
playgroundActions.updateSessionStatus(response.sessionStatus);
|
|
411
|
-
// Update executing state based on session status
|
|
412
|
-
if (response.sessionStatus === 'idle' ||
|
|
413
|
-
response.sessionStatus === 'completed' ||
|
|
414
|
-
response.sessionStatus === 'failed') {
|
|
415
|
-
isExecuting.set(false);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
429
|
+
const callback = createPollingCallback(isTerminalStatus);
|
|
430
|
+
callback(response);
|
|
418
431
|
}
|
|
419
432
|
catch (err) {
|
|
420
433
|
console.error('[playgroundStore] Failed to refresh messages:', err);
|
|
@@ -10,7 +10,31 @@ import type { ConfigProperty } from './index.js';
|
|
|
10
10
|
/**
|
|
11
11
|
* Status of a playground session
|
|
12
12
|
*/
|
|
13
|
-
export type PlaygroundSessionStatus = 'idle' | 'running' | 'completed' | 'failed';
|
|
13
|
+
export type PlaygroundSessionStatus = 'idle' | 'running' | 'awaiting_input' | 'completed' | 'failed';
|
|
14
|
+
/**
|
|
15
|
+
* Statuses that stop polling by default (resource efficiency)
|
|
16
|
+
*/
|
|
17
|
+
export declare const DEFAULT_STOP_POLLING_STATUSES: PlaygroundSessionStatus[];
|
|
18
|
+
/**
|
|
19
|
+
* Statuses that are considered terminal by default (clears isExecuting)
|
|
20
|
+
*/
|
|
21
|
+
export declare const DEFAULT_TERMINAL_STATUSES: PlaygroundSessionStatus[];
|
|
22
|
+
/**
|
|
23
|
+
* Default implementation for determining if polling should stop.
|
|
24
|
+
* Consumers can override this via PlaygroundConfig.shouldStopPolling.
|
|
25
|
+
*
|
|
26
|
+
* @param status - The current session status
|
|
27
|
+
* @returns True if polling should stop
|
|
28
|
+
*/
|
|
29
|
+
export declare function defaultShouldStopPolling(status: PlaygroundSessionStatus): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Default implementation for determining if a status is terminal (clears isExecuting).
|
|
32
|
+
* Consumers can override this via PlaygroundConfig.isTerminalStatus.
|
|
33
|
+
*
|
|
34
|
+
* @param status - The current session status
|
|
35
|
+
* @returns True if the status is terminal
|
|
36
|
+
*/
|
|
37
|
+
export declare function defaultIsTerminalStatus(status: PlaygroundSessionStatus): boolean;
|
|
14
38
|
/**
|
|
15
39
|
* Role of a message sender in the playground
|
|
16
40
|
*
|
|
@@ -231,6 +255,18 @@ export interface PlaygroundConfig {
|
|
|
231
255
|
* Typically used together with showSidebar: false for minimal UI.
|
|
232
256
|
*/
|
|
233
257
|
showSessionHeader?: boolean;
|
|
258
|
+
/**
|
|
259
|
+
* Determines if polling should stop for a given session status.
|
|
260
|
+
* Override to customize which statuses pause polling.
|
|
261
|
+
* @default defaultShouldStopPolling (stops on idle, completed, failed, awaiting_input)
|
|
262
|
+
*/
|
|
263
|
+
shouldStopPolling?: (status: PlaygroundSessionStatus) => boolean;
|
|
264
|
+
/**
|
|
265
|
+
* Determines if a session status is terminal (clears isExecuting).
|
|
266
|
+
* Override to customize which statuses end the executing state.
|
|
267
|
+
* @default defaultIsTerminalStatus (terminal on idle, completed, failed, awaiting_input)
|
|
268
|
+
*/
|
|
269
|
+
isTerminalStatus?: (status: PlaygroundSessionStatus) => boolean;
|
|
234
270
|
}
|
|
235
271
|
/**
|
|
236
272
|
* Metadata field to control Run button state from backend.
|
package/dist/types/playground.js
CHANGED
|
@@ -6,6 +6,44 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module types/playground
|
|
8
8
|
*/
|
|
9
|
+
/**
|
|
10
|
+
* Statuses that stop polling by default (resource efficiency)
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_STOP_POLLING_STATUSES = [
|
|
13
|
+
'idle',
|
|
14
|
+
'completed',
|
|
15
|
+
'failed',
|
|
16
|
+
'awaiting_input'
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Statuses that are considered terminal by default (clears isExecuting)
|
|
20
|
+
*/
|
|
21
|
+
export const DEFAULT_TERMINAL_STATUSES = [
|
|
22
|
+
'idle',
|
|
23
|
+
'completed',
|
|
24
|
+
'failed',
|
|
25
|
+
'awaiting_input'
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Default implementation for determining if polling should stop.
|
|
29
|
+
* Consumers can override this via PlaygroundConfig.shouldStopPolling.
|
|
30
|
+
*
|
|
31
|
+
* @param status - The current session status
|
|
32
|
+
* @returns True if polling should stop
|
|
33
|
+
*/
|
|
34
|
+
export function defaultShouldStopPolling(status) {
|
|
35
|
+
return DEFAULT_STOP_POLLING_STATUSES.includes(status);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Default implementation for determining if a status is terminal (clears isExecuting).
|
|
39
|
+
* Consumers can override this via PlaygroundConfig.isTerminalStatus.
|
|
40
|
+
*
|
|
41
|
+
* @param status - The current session status
|
|
42
|
+
* @returns True if the status is terminal
|
|
43
|
+
*/
|
|
44
|
+
export function defaultIsTerminalStatus(status) {
|
|
45
|
+
return DEFAULT_TERMINAL_STATUSES.includes(status);
|
|
46
|
+
}
|
|
9
47
|
/**
|
|
10
48
|
* Metadata field to control Run button state from backend.
|
|
11
49
|
* When a message contains this field set to true, the Run button becomes enabled.
|