@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.
Files changed (34) hide show
  1. package/dist/api/enhanced-client.js +5 -1
  2. package/dist/components/PipelineStatus.svelte +31 -8
  3. package/dist/components/PipelineStatus.svelte.d.ts +5 -0
  4. package/dist/components/WorkflowEditor.svelte +26 -0
  5. package/dist/components/chat/AIChatPanel.svelte +16 -5
  6. package/dist/components/playground/ChatPanel.svelte +31 -108
  7. package/dist/components/playground/ChatPanel.svelte.d.ts +3 -1
  8. package/dist/components/playground/ExecutionList.svelte +138 -0
  9. package/dist/components/playground/ExecutionList.svelte.d.ts +10 -0
  10. package/dist/components/playground/MessageBubble.svelte +281 -156
  11. package/dist/components/playground/PipelinePanel.svelte +382 -0
  12. package/dist/components/playground/PipelinePanel.svelte.d.ts +20 -0
  13. package/dist/components/playground/Playground.svelte +707 -174
  14. package/dist/components/playground/Playground.svelte.d.ts +6 -0
  15. package/dist/components/playground/PlaygroundStudio.svelte +404 -0
  16. package/dist/components/playground/PlaygroundStudio.svelte.d.ts +30 -0
  17. package/dist/editor/index.d.ts +1 -1
  18. package/dist/editor/index.js +1 -1
  19. package/dist/playground/index.d.ts +7 -3
  20. package/dist/playground/index.js +14 -5
  21. package/dist/playground/mount.d.ts +7 -0
  22. package/dist/playground/mount.js +78 -81
  23. package/dist/services/globalSave.d.ts +7 -0
  24. package/dist/services/globalSave.js +5 -1
  25. package/dist/services/nodeExecutionService.js +4 -2
  26. package/dist/services/playgroundService.d.ts +11 -4
  27. package/dist/services/playgroundService.js +22 -12
  28. package/dist/stores/pipelinePanelStore.svelte.d.ts +6 -0
  29. package/dist/stores/pipelinePanelStore.svelte.js +24 -0
  30. package/dist/stores/playgroundStore.svelte.d.ts +26 -21
  31. package/dist/stores/playgroundStore.svelte.js +134 -55
  32. package/dist/svelte-app.js +25 -2
  33. package/dist/types/playground.d.ts +15 -5
  34. package/package.json +1 -1
@@ -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, createPollingCallback, subscribeToSessionStatus } from '../stores/playgroundStore.svelte.js';
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
- // Set endpoint configuration if provided
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
- // Store state for cleanup
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 pipelineData = await response.json();
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 result = await response.json();
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 lastMessageTimestamp;
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 since - Optional timestamp to fetch only newer messages (ISO 8601)
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, since?: string, limit?: number): Promise<PlaygroundMessagesApiResponse>;
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
- lastMessageTimestamp = null;
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 since - Optional timestamp to fetch only newer messages (ISO 8601)
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, since, limit) {
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 (since) {
186
- params.append('since', 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.lastMessageTimestamp = null;
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.lastMessageTimestamp ?? undefined);
261
- // Update last message timestamp
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
- this.lastMessageTimestamp = lastMessage.timestamp;
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.lastMessageTimestamp = null;
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,6 @@
1
+ export declare function getPipelinePanelOpen(): boolean;
2
+ export declare const pipelinePanelActions: {
3
+ init(): void;
4
+ toggle(): void;
5
+ setOpen(value: boolean): void;
6
+ };
@@ -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 timestamp
40
+ * Get the last poll sequence number cursor
41
41
  */
42
- export declare function getLastPollTimestamp(): string | null;
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
- updateLastPollTimestamp: (timestamp: string) => void;
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
- * 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()
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 createPollingCallback(isTerminalStatus?: (status: PlaygroundSessionStatus) => boolean): (response: PlaygroundMessagesApiResponse) => void;
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 timestamp for polling
213
+ * Get the sequence number of the latest message, used to seed incremental polling.
208
214
  *
209
- * @returns ISO 8601 timestamp of the latest message, or null
215
+ * @returns Sequence number of the last message, or null
210
216
  */
211
- export declare function getLatestMessageTimestamp(): string | null;
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>, isTerminalStatus?: (status: PlaygroundSessionStatus) => boolean): Promise<void>;
235
+ export declare function refreshSessionMessages(fetchMessages: (sessionId: string) => Promise<PlaygroundMessagesApiResponse>): Promise<void>;