@d34dman/flowdrop 0.0.37 → 0.0.39
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/LICENSE +21 -0
- package/dist/components/NodeSidebar.svelte +1 -0
- package/dist/components/form/FormCodeEditor.svelte +6 -1
- package/dist/components/interrupt/ChoicePrompt.svelte +389 -0
- package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +21 -0
- package/dist/components/interrupt/ConfirmationPrompt.svelte +280 -0
- package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +23 -0
- package/dist/components/interrupt/FormPrompt.svelte +223 -0
- package/dist/components/interrupt/FormPrompt.svelte.d.ts +21 -0
- package/dist/components/interrupt/InterruptBubble.svelte +621 -0
- package/dist/components/interrupt/InterruptBubble.svelte.d.ts +16 -0
- package/dist/components/interrupt/TextInputPrompt.svelte +333 -0
- package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +21 -0
- package/dist/components/interrupt/index.d.ts +13 -0
- package/dist/components/interrupt/index.js +15 -0
- package/dist/components/nodes/GatewayNode.svelte +1 -3
- package/dist/components/nodes/IdeaNode.svelte +30 -35
- package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
- package/dist/components/nodes/SimpleNode.svelte +1 -3
- package/dist/components/nodes/TerminalNode.svelte +1 -3
- package/dist/components/nodes/ToolNode.svelte +2 -2
- package/dist/components/nodes/WorkflowNode.svelte +1 -3
- package/dist/components/playground/ChatPanel.svelte +144 -7
- package/dist/components/playground/ChatPanel.svelte.d.ts +2 -0
- package/dist/components/playground/MessageBubble.svelte +1 -3
- package/dist/components/playground/Playground.svelte +50 -5
- package/dist/components/playground/PlaygroundModal.svelte +8 -7
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
- package/dist/config/endpoints.d.ts +12 -0
- package/dist/config/endpoints.js +7 -0
- package/dist/playground/index.d.ts +5 -0
- package/dist/playground/index.js +21 -0
- package/dist/playground/mount.d.ts +3 -3
- package/dist/playground/mount.js +30 -22
- package/dist/services/interruptService.d.ts +133 -0
- package/dist/services/interruptService.js +279 -0
- package/dist/stores/interruptStore.d.ts +200 -0
- package/dist/stores/interruptStore.js +424 -0
- package/dist/stores/playgroundStore.d.ts +11 -1
- package/dist/stores/playgroundStore.js +34 -0
- package/dist/styles/base.css +89 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/interrupt.d.ts +305 -0
- package/dist/types/interrupt.js +126 -0
- package/dist/types/interruptState.d.ts +211 -0
- package/dist/types/interruptState.js +308 -0
- package/dist/utils/colors.js +1 -0
- package/dist/utils/connections.js +2 -2
- package/dist/utils/icons.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interrupt Store
|
|
3
|
+
*
|
|
4
|
+
* Svelte stores for managing interrupt state using a lightweight state machine.
|
|
5
|
+
* Ensures valid state transitions and prevents deadlocks.
|
|
6
|
+
*
|
|
7
|
+
* @module stores/interruptStore
|
|
8
|
+
*/
|
|
9
|
+
import { writable, derived, get } from 'svelte/store';
|
|
10
|
+
import { initialState, transition, isTerminalState, isSubmitting as checkIsSubmitting, hasError as checkHasError, getErrorMessage, getResolvedValue, toLegacyStatus } from '../types/interruptState.js';
|
|
11
|
+
// =========================================================================
|
|
12
|
+
// Core Stores
|
|
13
|
+
// =========================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Map of all interrupts by ID
|
|
16
|
+
* Key: interrupt ID, Value: Interrupt object with state
|
|
17
|
+
*/
|
|
18
|
+
export const interrupts = writable(new Map());
|
|
19
|
+
// =========================================================================
|
|
20
|
+
// Derived Stores
|
|
21
|
+
// =========================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Derived store for pending interrupt IDs
|
|
24
|
+
*/
|
|
25
|
+
export const pendingInterruptIds = derived(interrupts, ($interrupts) => {
|
|
26
|
+
const pending = [];
|
|
27
|
+
$interrupts.forEach((interrupt, id) => {
|
|
28
|
+
if (!isTerminalState(interrupt.machineState)) {
|
|
29
|
+
pending.push(id);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return pending;
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Derived store for pending interrupts array
|
|
36
|
+
*/
|
|
37
|
+
export const pendingInterrupts = derived(interrupts, ($interrupts) => {
|
|
38
|
+
const pending = [];
|
|
39
|
+
$interrupts.forEach((interrupt) => {
|
|
40
|
+
if (!isTerminalState(interrupt.machineState)) {
|
|
41
|
+
pending.push(interrupt);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
return pending;
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Derived store for count of pending interrupts
|
|
48
|
+
*/
|
|
49
|
+
export const pendingInterruptCount = derived(pendingInterruptIds, ($pendingIds) => $pendingIds.length);
|
|
50
|
+
/**
|
|
51
|
+
* Derived store for resolved interrupts
|
|
52
|
+
*/
|
|
53
|
+
export const resolvedInterrupts = derived(interrupts, ($interrupts) => {
|
|
54
|
+
const resolved = [];
|
|
55
|
+
$interrupts.forEach((interrupt) => {
|
|
56
|
+
if (interrupt.machineState.status === 'resolved') {
|
|
57
|
+
resolved.push(interrupt);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
return resolved;
|
|
61
|
+
});
|
|
62
|
+
/**
|
|
63
|
+
* Derived store to check if any interrupt is currently submitting
|
|
64
|
+
*/
|
|
65
|
+
export const isAnySubmitting = derived(interrupts, ($interrupts) => {
|
|
66
|
+
for (const interrupt of $interrupts.values()) {
|
|
67
|
+
if (checkIsSubmitting(interrupt.machineState)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* Legacy derived store for submitting interrupt IDs
|
|
75
|
+
* @deprecated Use interrupt.machineState.status === "submitting" instead
|
|
76
|
+
*/
|
|
77
|
+
export const submittingInterrupts = derived(interrupts, ($interrupts) => {
|
|
78
|
+
const submitting = new Set();
|
|
79
|
+
$interrupts.forEach((interrupt, id) => {
|
|
80
|
+
if (checkIsSubmitting(interrupt.machineState)) {
|
|
81
|
+
submitting.add(id);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return submitting;
|
|
85
|
+
});
|
|
86
|
+
/**
|
|
87
|
+
* Legacy derived store for interrupt errors
|
|
88
|
+
* @deprecated Use interrupt.machineState.error instead
|
|
89
|
+
*/
|
|
90
|
+
export const interruptErrors = derived(interrupts, ($interrupts) => {
|
|
91
|
+
const errors = new Map();
|
|
92
|
+
$interrupts.forEach((interrupt, id) => {
|
|
93
|
+
const errorMsg = getErrorMessage(interrupt.machineState);
|
|
94
|
+
if (errorMsg) {
|
|
95
|
+
errors.set(id, errorMsg);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return errors;
|
|
99
|
+
});
|
|
100
|
+
// =========================================================================
|
|
101
|
+
// State Machine Actions
|
|
102
|
+
// =========================================================================
|
|
103
|
+
/**
|
|
104
|
+
* Apply a state machine action to an interrupt
|
|
105
|
+
*
|
|
106
|
+
* @param interruptId - The interrupt ID
|
|
107
|
+
* @param action - The action to apply
|
|
108
|
+
* @returns Transition result with validity and any errors
|
|
109
|
+
*/
|
|
110
|
+
function applyAction(interruptId, action) {
|
|
111
|
+
const currentInterrupts = get(interrupts);
|
|
112
|
+
const interrupt = currentInterrupts.get(interruptId);
|
|
113
|
+
if (!interrupt) {
|
|
114
|
+
return {
|
|
115
|
+
state: initialState,
|
|
116
|
+
valid: false,
|
|
117
|
+
error: `Interrupt not found: ${interruptId}`
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const result = transition(interrupt.machineState, action);
|
|
121
|
+
if (result.valid) {
|
|
122
|
+
interrupts.update(($interrupts) => {
|
|
123
|
+
const updated = new Map($interrupts);
|
|
124
|
+
const current = updated.get(interruptId);
|
|
125
|
+
if (current) {
|
|
126
|
+
// Update machine state and sync legacy fields
|
|
127
|
+
const newInterrupt = {
|
|
128
|
+
...current,
|
|
129
|
+
machineState: result.state,
|
|
130
|
+
status: toLegacyStatus(result.state),
|
|
131
|
+
responseValue: getResolvedValue(result.state) ?? current.responseValue,
|
|
132
|
+
resolvedAt: result.state.status === 'resolved'
|
|
133
|
+
? result.state.resolvedAt
|
|
134
|
+
: result.state.status === 'cancelled'
|
|
135
|
+
? result.state.cancelledAt
|
|
136
|
+
: current.resolvedAt
|
|
137
|
+
};
|
|
138
|
+
updated.set(interruptId, newInterrupt);
|
|
139
|
+
}
|
|
140
|
+
return updated;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
console.warn(`[InterruptStore] Invalid transition: ${result.error}`);
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
// =========================================================================
|
|
149
|
+
// Public Actions
|
|
150
|
+
// =========================================================================
|
|
151
|
+
/**
|
|
152
|
+
* Interrupt store actions for modifying state
|
|
153
|
+
*/
|
|
154
|
+
export const interruptActions = {
|
|
155
|
+
/**
|
|
156
|
+
* Add or update an interrupt in the store
|
|
157
|
+
*
|
|
158
|
+
* @param interrupt - The interrupt to add or update
|
|
159
|
+
*/
|
|
160
|
+
addInterrupt: (interrupt) => {
|
|
161
|
+
interrupts.update(($interrupts) => {
|
|
162
|
+
const updated = new Map($interrupts);
|
|
163
|
+
const existing = updated.get(interrupt.id);
|
|
164
|
+
// Preserve existing machine state if interrupt already exists
|
|
165
|
+
const machineState = existing?.machineState ?? initialState;
|
|
166
|
+
const interruptWithState = {
|
|
167
|
+
...interrupt,
|
|
168
|
+
machineState
|
|
169
|
+
};
|
|
170
|
+
updated.set(interrupt.id, interruptWithState);
|
|
171
|
+
return updated;
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
/**
|
|
175
|
+
* Add multiple interrupts to the store
|
|
176
|
+
*
|
|
177
|
+
* @param interruptList - Array of interrupts to add
|
|
178
|
+
*/
|
|
179
|
+
addInterrupts: (interruptList) => {
|
|
180
|
+
if (interruptList.length === 0)
|
|
181
|
+
return;
|
|
182
|
+
interrupts.update(($interrupts) => {
|
|
183
|
+
const updated = new Map($interrupts);
|
|
184
|
+
interruptList.forEach((interrupt) => {
|
|
185
|
+
const existing = updated.get(interrupt.id);
|
|
186
|
+
const machineState = existing?.machineState ?? initialState;
|
|
187
|
+
const interruptWithState = {
|
|
188
|
+
...interrupt,
|
|
189
|
+
machineState
|
|
190
|
+
};
|
|
191
|
+
updated.set(interrupt.id, interruptWithState);
|
|
192
|
+
});
|
|
193
|
+
return updated;
|
|
194
|
+
});
|
|
195
|
+
},
|
|
196
|
+
/**
|
|
197
|
+
* Start submitting an interrupt (user clicked submit)
|
|
198
|
+
*
|
|
199
|
+
* @param interruptId - The interrupt ID
|
|
200
|
+
* @param value - The value being submitted
|
|
201
|
+
* @returns Transition result
|
|
202
|
+
*/
|
|
203
|
+
startSubmit: (interruptId, value) => {
|
|
204
|
+
return applyAction(interruptId, { type: 'SUBMIT', value });
|
|
205
|
+
},
|
|
206
|
+
/**
|
|
207
|
+
* Start cancelling an interrupt (user clicked cancel)
|
|
208
|
+
*
|
|
209
|
+
* @param interruptId - The interrupt ID
|
|
210
|
+
* @returns Transition result
|
|
211
|
+
*/
|
|
212
|
+
startCancel: (interruptId) => {
|
|
213
|
+
return applyAction(interruptId, { type: 'CANCEL' });
|
|
214
|
+
},
|
|
215
|
+
/**
|
|
216
|
+
* Mark submission as successful
|
|
217
|
+
*
|
|
218
|
+
* @param interruptId - The interrupt ID
|
|
219
|
+
* @returns Transition result
|
|
220
|
+
*/
|
|
221
|
+
submitSuccess: (interruptId) => {
|
|
222
|
+
return applyAction(interruptId, { type: 'SUCCESS' });
|
|
223
|
+
},
|
|
224
|
+
/**
|
|
225
|
+
* Mark submission as failed
|
|
226
|
+
*
|
|
227
|
+
* @param interruptId - The interrupt ID
|
|
228
|
+
* @param error - Error message
|
|
229
|
+
* @returns Transition result
|
|
230
|
+
*/
|
|
231
|
+
submitFailure: (interruptId, error) => {
|
|
232
|
+
return applyAction(interruptId, { type: 'FAILURE', error });
|
|
233
|
+
},
|
|
234
|
+
/**
|
|
235
|
+
* Retry a failed submission
|
|
236
|
+
*
|
|
237
|
+
* @param interruptId - The interrupt ID
|
|
238
|
+
* @returns Transition result
|
|
239
|
+
*/
|
|
240
|
+
retry: (interruptId) => {
|
|
241
|
+
return applyAction(interruptId, { type: 'RETRY' });
|
|
242
|
+
},
|
|
243
|
+
/**
|
|
244
|
+
* Reset an interrupt to idle state
|
|
245
|
+
*
|
|
246
|
+
* @param interruptId - The interrupt ID
|
|
247
|
+
* @returns Transition result
|
|
248
|
+
*/
|
|
249
|
+
resetInterrupt: (interruptId) => {
|
|
250
|
+
return applyAction(interruptId, { type: 'RESET' });
|
|
251
|
+
},
|
|
252
|
+
// =========================================================================
|
|
253
|
+
// Legacy Actions (for backward compatibility)
|
|
254
|
+
// =========================================================================
|
|
255
|
+
/**
|
|
256
|
+
* Update an interrupt's status (legacy)
|
|
257
|
+
* @deprecated Use startSubmit/submitSuccess/submitFailure instead
|
|
258
|
+
*/
|
|
259
|
+
updateStatus: (interruptId, status, responseValue) => {
|
|
260
|
+
// Map legacy status to state machine actions
|
|
261
|
+
if (status === 'resolved' && responseValue !== undefined) {
|
|
262
|
+
const submitResult = applyAction(interruptId, { type: 'SUBMIT', value: responseValue });
|
|
263
|
+
if (submitResult.valid) {
|
|
264
|
+
applyAction(interruptId, { type: 'SUCCESS' });
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
else if (status === 'cancelled') {
|
|
268
|
+
const cancelResult = applyAction(interruptId, { type: 'CANCEL' });
|
|
269
|
+
if (cancelResult.valid) {
|
|
270
|
+
applyAction(interruptId, { type: 'SUCCESS' });
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
/**
|
|
275
|
+
* Mark an interrupt as resolved with the user's response (legacy)
|
|
276
|
+
* @deprecated Use startSubmit + submitSuccess instead
|
|
277
|
+
*/
|
|
278
|
+
resolveInterrupt: (interruptId, value) => {
|
|
279
|
+
// For backward compatibility, immediately resolve
|
|
280
|
+
// (assumes sync operation or already completed API call)
|
|
281
|
+
const submitResult = applyAction(interruptId, { type: 'SUBMIT', value });
|
|
282
|
+
if (submitResult.valid) {
|
|
283
|
+
applyAction(interruptId, { type: 'SUCCESS' });
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
/**
|
|
287
|
+
* Mark an interrupt as cancelled (legacy)
|
|
288
|
+
* @deprecated Use startCancel + submitSuccess instead
|
|
289
|
+
*/
|
|
290
|
+
cancelInterrupt: (interruptId) => {
|
|
291
|
+
const cancelResult = applyAction(interruptId, { type: 'CANCEL' });
|
|
292
|
+
if (cancelResult.valid) {
|
|
293
|
+
applyAction(interruptId, { type: 'SUCCESS' });
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
/**
|
|
297
|
+
* Set submitting state for an interrupt (legacy)
|
|
298
|
+
* @deprecated State is automatically managed by startSubmit/submitSuccess
|
|
299
|
+
*/
|
|
300
|
+
setSubmitting: (interruptId, isSubmitting) => {
|
|
301
|
+
// This is now a no-op - state is managed by the state machine
|
|
302
|
+
// Kept for backward compatibility
|
|
303
|
+
if (isSubmitting) {
|
|
304
|
+
console.warn('[InterruptStore] setSubmitting(true) is deprecated. Use startSubmit() instead.');
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
/**
|
|
308
|
+
* Set error for an interrupt (legacy)
|
|
309
|
+
* @deprecated Use submitFailure() instead
|
|
310
|
+
*/
|
|
311
|
+
setError: (interruptId, error) => {
|
|
312
|
+
if (error) {
|
|
313
|
+
applyAction(interruptId, { type: 'FAILURE', error });
|
|
314
|
+
}
|
|
315
|
+
// Clearing error is not directly supported - use retry or reset
|
|
316
|
+
},
|
|
317
|
+
/**
|
|
318
|
+
* Remove an interrupt from the store
|
|
319
|
+
*
|
|
320
|
+
* @param interruptId - The interrupt ID to remove
|
|
321
|
+
*/
|
|
322
|
+
removeInterrupt: (interruptId) => {
|
|
323
|
+
interrupts.update(($interrupts) => {
|
|
324
|
+
const updated = new Map($interrupts);
|
|
325
|
+
updated.delete(interruptId);
|
|
326
|
+
return updated;
|
|
327
|
+
});
|
|
328
|
+
},
|
|
329
|
+
/**
|
|
330
|
+
* Clear all interrupts for a specific session
|
|
331
|
+
*
|
|
332
|
+
* @param sessionId - The session ID to clear interrupts for
|
|
333
|
+
*/
|
|
334
|
+
clearSessionInterrupts: (sessionId) => {
|
|
335
|
+
interrupts.update(($interrupts) => {
|
|
336
|
+
const updated = new Map($interrupts);
|
|
337
|
+
$interrupts.forEach((interrupt, id) => {
|
|
338
|
+
if (interrupt.sessionId === sessionId) {
|
|
339
|
+
updated.delete(id);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
return updated;
|
|
343
|
+
});
|
|
344
|
+
},
|
|
345
|
+
/**
|
|
346
|
+
* Alias for clearSessionInterrupts
|
|
347
|
+
*/
|
|
348
|
+
clearInterrupts: () => {
|
|
349
|
+
interrupts.set(new Map());
|
|
350
|
+
},
|
|
351
|
+
/**
|
|
352
|
+
* Reset all interrupt state
|
|
353
|
+
*/
|
|
354
|
+
reset: () => {
|
|
355
|
+
interrupts.set(new Map());
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
// =========================================================================
|
|
359
|
+
// Utilities
|
|
360
|
+
// =========================================================================
|
|
361
|
+
/**
|
|
362
|
+
* Get an interrupt by ID
|
|
363
|
+
*
|
|
364
|
+
* @param interruptId - The interrupt ID
|
|
365
|
+
* @returns The interrupt or undefined
|
|
366
|
+
*/
|
|
367
|
+
export function getInterrupt(interruptId) {
|
|
368
|
+
return get(interrupts).get(interruptId);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Check if an interrupt is pending (not resolved or cancelled)
|
|
372
|
+
*
|
|
373
|
+
* @param interruptId - The interrupt ID
|
|
374
|
+
* @returns True if the interrupt exists and is pending
|
|
375
|
+
*/
|
|
376
|
+
export function isInterruptPending(interruptId) {
|
|
377
|
+
const interrupt = get(interrupts).get(interruptId);
|
|
378
|
+
return interrupt ? !isTerminalState(interrupt.machineState) : false;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Check if an interrupt is currently submitting
|
|
382
|
+
*
|
|
383
|
+
* @param interruptId - The interrupt ID
|
|
384
|
+
* @returns True if the interrupt is being submitted
|
|
385
|
+
*/
|
|
386
|
+
export function isInterruptSubmitting(interruptId) {
|
|
387
|
+
const interrupt = get(interrupts).get(interruptId);
|
|
388
|
+
return interrupt ? checkIsSubmitting(interrupt.machineState) : false;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Get the error for an interrupt
|
|
392
|
+
*
|
|
393
|
+
* @param interruptId - The interrupt ID
|
|
394
|
+
* @returns The error message or undefined
|
|
395
|
+
*/
|
|
396
|
+
export function getInterruptError(interruptId) {
|
|
397
|
+
const interrupt = get(interrupts).get(interruptId);
|
|
398
|
+
return interrupt ? getErrorMessage(interrupt.machineState) : undefined;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Get an interrupt by its associated message ID
|
|
402
|
+
*
|
|
403
|
+
* @param messageId - The message ID
|
|
404
|
+
* @returns The interrupt or undefined
|
|
405
|
+
*/
|
|
406
|
+
export function getInterruptByMessageId(messageId) {
|
|
407
|
+
const interruptMap = get(interrupts);
|
|
408
|
+
for (const interrupt of interruptMap.values()) {
|
|
409
|
+
if (interrupt.messageId === messageId) {
|
|
410
|
+
return interrupt;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return undefined;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Check if an interrupt has an error
|
|
417
|
+
*
|
|
418
|
+
* @param interruptId - The interrupt ID
|
|
419
|
+
* @returns True if the interrupt has an error
|
|
420
|
+
*/
|
|
421
|
+
export function interruptHasError(interruptId) {
|
|
422
|
+
const interrupt = get(interrupts).get(interruptId);
|
|
423
|
+
return interrupt ? checkHasError(interrupt.machineState) : false;
|
|
424
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module stores/playgroundStore
|
|
8
8
|
*/
|
|
9
|
-
import type { PlaygroundSession, PlaygroundMessage, PlaygroundInputField, PlaygroundSessionStatus } from '../types/playground.js';
|
|
9
|
+
import type { PlaygroundSession, PlaygroundMessage, PlaygroundInputField, PlaygroundSessionStatus, PlaygroundMessagesApiResponse } from '../types/playground.js';
|
|
10
10
|
import type { Workflow } from '../types/index.js';
|
|
11
11
|
/**
|
|
12
12
|
* Currently active playground session
|
|
@@ -200,3 +200,13 @@ export declare function getMessagesSnapshot(): PlaygroundMessage[];
|
|
|
200
200
|
* @returns ISO 8601 timestamp of the latest message, or null
|
|
201
201
|
*/
|
|
202
202
|
export declare function getLatestMessageTimestamp(): string | null;
|
|
203
|
+
/**
|
|
204
|
+
* Refresh messages for the current session
|
|
205
|
+
*
|
|
206
|
+
* This function is useful after interrupt resolution when polling
|
|
207
|
+
* has stopped but new messages may exist on the server.
|
|
208
|
+
*
|
|
209
|
+
* @param fetchMessages - Async function to fetch messages from the API
|
|
210
|
+
* @returns Promise that resolves when messages are refreshed
|
|
211
|
+
*/
|
|
212
|
+
export declare function refreshSessionMessages(fetchMessages: (sessionId: string) => Promise<PlaygroundMessagesApiResponse>): Promise<void>;
|
|
@@ -386,3 +386,37 @@ export function getLatestMessageTimestamp() {
|
|
|
386
386
|
return null;
|
|
387
387
|
return msgs[msgs.length - 1].timestamp;
|
|
388
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Refresh messages for the current session
|
|
391
|
+
*
|
|
392
|
+
* This function is useful after interrupt resolution when polling
|
|
393
|
+
* has stopped but new messages may exist on the server.
|
|
394
|
+
*
|
|
395
|
+
* @param fetchMessages - Async function to fetch messages from the API
|
|
396
|
+
* @returns Promise that resolves when messages are refreshed
|
|
397
|
+
*/
|
|
398
|
+
export async function refreshSessionMessages(fetchMessages) {
|
|
399
|
+
const session = get(currentSession);
|
|
400
|
+
if (!session)
|
|
401
|
+
return;
|
|
402
|
+
try {
|
|
403
|
+
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
|
+
}
|
|
418
|
+
}
|
|
419
|
+
catch (err) {
|
|
420
|
+
console.error('[playgroundStore] Failed to refresh messages:', err);
|
|
421
|
+
}
|
|
422
|
+
}
|
package/dist/styles/base.css
CHANGED
|
@@ -1180,6 +1180,95 @@
|
|
|
1180
1180
|
--flowdrop-text-color-primary: var(--color-ref-gray-900);
|
|
1181
1181
|
--flowdrop-text-color-secondary: var(--color-ref-gray-600);
|
|
1182
1182
|
|
|
1183
|
+
/* =========================================================================
|
|
1184
|
+
Interrupt Component Tokens
|
|
1185
|
+
========================================================================= */
|
|
1186
|
+
|
|
1187
|
+
/* Interrupt state: Pending (awaiting user response) */
|
|
1188
|
+
--flowdrop-interrupt-pending-bg: linear-gradient(
|
|
1189
|
+
135deg,
|
|
1190
|
+
var(--color-ref-amber-100) 0%,
|
|
1191
|
+
var(--color-ref-amber-200) 100%
|
|
1192
|
+
);
|
|
1193
|
+
--flowdrop-interrupt-pending-border: var(--color-ref-amber-500);
|
|
1194
|
+
--flowdrop-interrupt-pending-shadow: rgba(245, 158, 11, 0.15);
|
|
1195
|
+
--flowdrop-interrupt-pending-avatar: var(--color-ref-amber-500);
|
|
1196
|
+
--flowdrop-interrupt-pending-text: var(--color-ref-amber-800);
|
|
1197
|
+
--flowdrop-interrupt-pending-text-light: var(--color-ref-amber-700);
|
|
1198
|
+
|
|
1199
|
+
/* Interrupt state: Completed (response received - neutral) */
|
|
1200
|
+
--flowdrop-interrupt-completed-bg: linear-gradient(
|
|
1201
|
+
135deg,
|
|
1202
|
+
var(--color-ref-blue-50) 0%,
|
|
1203
|
+
var(--color-ref-blue-100) 100%
|
|
1204
|
+
);
|
|
1205
|
+
--flowdrop-interrupt-completed-border: var(--color-ref-blue-500);
|
|
1206
|
+
--flowdrop-interrupt-completed-shadow: rgba(59, 130, 246, 0.15);
|
|
1207
|
+
--flowdrop-interrupt-completed-avatar: var(--color-ref-blue-500);
|
|
1208
|
+
--flowdrop-interrupt-completed-text: var(--color-ref-blue-800);
|
|
1209
|
+
--flowdrop-interrupt-completed-text-light: var(--color-ref-blue-600);
|
|
1210
|
+
|
|
1211
|
+
/* Interrupt state: Cancelled (dismissed without responding) */
|
|
1212
|
+
--flowdrop-interrupt-cancelled-bg: linear-gradient(
|
|
1213
|
+
135deg,
|
|
1214
|
+
var(--color-ref-gray-100) 0%,
|
|
1215
|
+
var(--color-ref-gray-200) 100%
|
|
1216
|
+
);
|
|
1217
|
+
--flowdrop-interrupt-cancelled-border: var(--color-ref-gray-400);
|
|
1218
|
+
--flowdrop-interrupt-cancelled-shadow: rgba(107, 114, 128, 0.15);
|
|
1219
|
+
--flowdrop-interrupt-cancelled-avatar: var(--color-ref-gray-500);
|
|
1220
|
+
--flowdrop-interrupt-cancelled-text: var(--color-ref-gray-600);
|
|
1221
|
+
--flowdrop-interrupt-cancelled-text-light: var(--color-ref-gray-500);
|
|
1222
|
+
|
|
1223
|
+
/* Interrupt state: Error */
|
|
1224
|
+
--flowdrop-interrupt-error-bg: linear-gradient(
|
|
1225
|
+
135deg,
|
|
1226
|
+
var(--color-ref-red-50) 0%,
|
|
1227
|
+
var(--color-ref-red-100) 100%
|
|
1228
|
+
);
|
|
1229
|
+
--flowdrop-interrupt-error-border: var(--color-ref-red-500);
|
|
1230
|
+
--flowdrop-interrupt-error-shadow: rgba(239, 68, 68, 0.15);
|
|
1231
|
+
--flowdrop-interrupt-error-avatar: var(--color-ref-red-500);
|
|
1232
|
+
--flowdrop-interrupt-error-text: var(--color-ref-red-700);
|
|
1233
|
+
--flowdrop-interrupt-error-text-light: var(--color-ref-red-600);
|
|
1234
|
+
|
|
1235
|
+
/* Interrupt prompt inner styling */
|
|
1236
|
+
--flowdrop-interrupt-prompt-bg: rgba(255, 255, 255, 0.85);
|
|
1237
|
+
--flowdrop-interrupt-prompt-border-pending: rgba(245, 158, 11, 0.2);
|
|
1238
|
+
--flowdrop-interrupt-prompt-border-completed: rgba(59, 130, 246, 0.2);
|
|
1239
|
+
--flowdrop-interrupt-prompt-border-cancelled: rgba(107, 114, 128, 0.2);
|
|
1240
|
+
--flowdrop-interrupt-prompt-border-error: rgba(239, 68, 68, 0.2);
|
|
1241
|
+
|
|
1242
|
+
/* Interrupt button tokens */
|
|
1243
|
+
--flowdrop-interrupt-btn-primary-bg: linear-gradient(
|
|
1244
|
+
135deg,
|
|
1245
|
+
var(--color-ref-blue-500) 0%,
|
|
1246
|
+
var(--color-ref-blue-600) 100%
|
|
1247
|
+
);
|
|
1248
|
+
--flowdrop-interrupt-btn-primary-bg-hover: linear-gradient(
|
|
1249
|
+
135deg,
|
|
1250
|
+
var(--color-ref-blue-600) 0%,
|
|
1251
|
+
var(--color-ref-blue-700) 100%
|
|
1252
|
+
);
|
|
1253
|
+
--flowdrop-interrupt-btn-primary-shadow: rgba(59, 130, 246, 0.3);
|
|
1254
|
+
--flowdrop-interrupt-btn-secondary-bg: var(--color-ref-gray-100);
|
|
1255
|
+
--flowdrop-interrupt-btn-secondary-border: var(--color-ref-gray-300);
|
|
1256
|
+
--flowdrop-interrupt-btn-secondary-text: var(--color-ref-gray-700);
|
|
1257
|
+
|
|
1258
|
+
/* Interrupt selection tokens (for confirmation/choice) */
|
|
1259
|
+
--flowdrop-interrupt-selected-confirm-bg: var(--flowdrop-interrupt-btn-primary-bg);
|
|
1260
|
+
--flowdrop-interrupt-selected-confirm-border: var(--color-ref-blue-700);
|
|
1261
|
+
--flowdrop-interrupt-selected-confirm-glow: rgba(59, 130, 246, 0.3);
|
|
1262
|
+
--flowdrop-interrupt-selected-decline-bg: var(--color-ref-red-50);
|
|
1263
|
+
--flowdrop-interrupt-selected-decline-border: var(--color-ref-red-400);
|
|
1264
|
+
--flowdrop-interrupt-selected-decline-text: var(--color-ref-red-600);
|
|
1265
|
+
--flowdrop-interrupt-selected-decline-glow: rgba(248, 113, 113, 0.2);
|
|
1266
|
+
--flowdrop-interrupt-not-selected-opacity: 0.4;
|
|
1267
|
+
|
|
1268
|
+
/* Interrupt badge tokens */
|
|
1269
|
+
--flowdrop-interrupt-badge-completed-bg: var(--color-ref-blue-50);
|
|
1270
|
+
--flowdrop-interrupt-badge-completed-text: var(--color-ref-blue-600);
|
|
1271
|
+
|
|
1183
1272
|
/* NotesNode component variables */
|
|
1184
1273
|
--notes-node-width: 500px;
|
|
1185
1274
|
--notes-node-min-width: 250px;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import type { EndpointConfig } from '../config/endpoints.js';
|
|
|
8
8
|
* Node category types for organizing nodes in the sidebar
|
|
9
9
|
* Based on actual API response categories
|
|
10
10
|
*/
|
|
11
|
-
export type NodeCategory = 'inputs' | 'outputs' | 'prompts' | 'models' | 'processing' | 'logic' | 'data' | 'tools' | 'helpers' | 'vector stores' | 'embeddings' | 'memories' | 'agents' | 'ai' | 'bundles';
|
|
11
|
+
export type NodeCategory = 'triggers' | 'inputs' | 'outputs' | 'prompts' | 'models' | 'processing' | 'logic' | 'data' | 'tools' | 'helpers' | 'vector stores' | 'embeddings' | 'memories' | 'agents' | 'ai' | 'bundles';
|
|
12
12
|
/**
|
|
13
13
|
* Port data type configuration
|
|
14
14
|
*/
|