@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.
@@ -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 if we have an initial workflow
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 && !$page.url.pathname.includes('/edit')}
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
- (response: PlaygroundMessagesApiResponse) => {
420
- // Add new messages
421
- if (response.data && response.data.length > 0) {
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';
@@ -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
@@ -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 session is idle, completed, or failed
267
- // "idle" means no processing is happening (execution finished)
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>): Promise<void>;
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
- // Add new messages (deduplicates automatically)
405
- if (response.data && response.data.length > 0) {
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.
@@ -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.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@d34dman/flowdrop",
3
3
  "license": "MIT",
4
4
  "private": false,
5
- "version": "0.0.59",
5
+ "version": "0.0.61",
6
6
  "scripts": {
7
7
  "dev": "vite dev",
8
8
  "build": "vite build && pnpm run prepack",