@d34dman/flowdrop 0.0.30 → 0.0.32
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 +54 -6
- package/dist/components/NodeSidebar.svelte +1 -1
- package/dist/components/SchemaForm.svelte +14 -14
- package/dist/components/SchemaForm.svelte.d.ts +1 -1
- package/dist/components/form/FormFieldLight.svelte +66 -66
- package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
- package/dist/components/form/types.d.ts +1 -1
- package/dist/components/playground/ChatPanel.svelte +523 -0
- package/dist/components/playground/ChatPanel.svelte.d.ts +20 -0
- package/dist/components/playground/ExecutionLogs.svelte +486 -0
- package/dist/components/playground/ExecutionLogs.svelte.d.ts +14 -0
- package/dist/components/playground/InputCollector.svelte +444 -0
- package/dist/components/playground/InputCollector.svelte.d.ts +16 -0
- package/dist/components/playground/MessageBubble.svelte +398 -0
- package/dist/components/playground/MessageBubble.svelte.d.ts +15 -0
- package/dist/components/playground/Playground.svelte +861 -0
- package/dist/components/playground/Playground.svelte.d.ts +25 -0
- package/dist/components/playground/PlaygroundModal.svelte +220 -0
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +25 -0
- package/dist/components/playground/SessionManager.svelte +537 -0
- package/dist/components/playground/SessionManager.svelte.d.ts +20 -0
- package/dist/config/endpoints.d.ts +16 -0
- package/dist/config/endpoints.js +9 -0
- package/dist/core/index.d.ts +25 -23
- package/dist/core/index.js +13 -12
- package/dist/display/index.d.ts +2 -2
- package/dist/display/index.js +2 -2
- package/dist/editor/index.d.ts +58 -49
- package/dist/editor/index.js +53 -42
- package/dist/form/code.d.ts +4 -4
- package/dist/form/code.js +11 -11
- package/dist/form/fieldRegistry.d.ts +2 -2
- package/dist/form/fieldRegistry.js +8 -10
- package/dist/form/full.d.ts +5 -5
- package/dist/form/full.js +7 -7
- package/dist/form/index.d.ts +16 -16
- package/dist/form/index.js +14 -14
- package/dist/form/markdown.d.ts +3 -3
- package/dist/form/markdown.js +6 -6
- package/dist/index.d.ts +6 -4
- package/dist/index.js +9 -4
- package/dist/playground/index.d.ts +125 -0
- package/dist/playground/index.js +147 -0
- package/dist/playground/mount.d.ts +184 -0
- package/dist/playground/mount.js +209 -0
- package/dist/services/playgroundService.d.ts +129 -0
- package/dist/services/playgroundService.js +317 -0
- package/dist/stores/playgroundStore.d.ts +199 -0
- package/dist/stores/playgroundStore.js +350 -0
- package/dist/types/playground.d.ts +230 -0
- package/dist/types/playground.js +28 -0
- package/dist/utils/colors.js +4 -4
- package/package.json +6 -1
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playground Store
|
|
3
|
+
*
|
|
4
|
+
* Svelte stores for managing playground state including sessions,
|
|
5
|
+
* messages, and execution status.
|
|
6
|
+
*
|
|
7
|
+
* @module stores/playgroundStore
|
|
8
|
+
*/
|
|
9
|
+
import type { PlaygroundSession, PlaygroundMessage, PlaygroundInputField, PlaygroundSessionStatus } from '../types/playground.js';
|
|
10
|
+
import type { Workflow } from '../types/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Currently active playground session
|
|
13
|
+
*/
|
|
14
|
+
export declare const currentSession: import("svelte/store").Writable<PlaygroundSession>;
|
|
15
|
+
/**
|
|
16
|
+
* List of all sessions for the current workflow
|
|
17
|
+
*/
|
|
18
|
+
export declare const sessions: import("svelte/store").Writable<PlaygroundSession[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Messages in the current session
|
|
21
|
+
*/
|
|
22
|
+
export declare const messages: import("svelte/store").Writable<PlaygroundMessage[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Whether an execution is currently running
|
|
25
|
+
*/
|
|
26
|
+
export declare const isExecuting: import("svelte/store").Writable<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Whether we are currently loading data
|
|
29
|
+
*/
|
|
30
|
+
export declare const isLoading: import("svelte/store").Writable<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Current error message, if any
|
|
33
|
+
*/
|
|
34
|
+
export declare const error: import("svelte/store").Writable<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Current workflow being tested
|
|
37
|
+
*/
|
|
38
|
+
export declare const currentWorkflow: import("svelte/store").Writable<Workflow>;
|
|
39
|
+
/**
|
|
40
|
+
* Last polling timestamp for incremental message fetching
|
|
41
|
+
*/
|
|
42
|
+
export declare const lastPollTimestamp: import("svelte/store").Writable<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Derived store for current session status
|
|
45
|
+
*/
|
|
46
|
+
export declare const sessionStatus: import("svelte/store").Readable<PlaygroundSessionStatus>;
|
|
47
|
+
/**
|
|
48
|
+
* Derived store for message count
|
|
49
|
+
*/
|
|
50
|
+
export declare const messageCount: import("svelte/store").Readable<number>;
|
|
51
|
+
/**
|
|
52
|
+
* Derived store for chat messages (excludes log messages)
|
|
53
|
+
*/
|
|
54
|
+
export declare const chatMessages: import("svelte/store").Readable<PlaygroundMessage[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Derived store for log messages only
|
|
57
|
+
*/
|
|
58
|
+
export declare const logMessages: import("svelte/store").Readable<PlaygroundMessage[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Derived store for the latest message
|
|
61
|
+
*/
|
|
62
|
+
export declare const latestMessage: import("svelte/store").Readable<PlaygroundMessage>;
|
|
63
|
+
/**
|
|
64
|
+
* Derived store for input fields from workflow input nodes
|
|
65
|
+
*
|
|
66
|
+
* Analyzes the workflow to extract input nodes and their configuration
|
|
67
|
+
* schemas for auto-generating input forms.
|
|
68
|
+
*/
|
|
69
|
+
export declare const inputFields: import("svelte/store").Readable<PlaygroundInputField[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Derived store for detecting if workflow has a chat input
|
|
72
|
+
*/
|
|
73
|
+
export declare const hasChatInput: import("svelte/store").Readable<boolean>;
|
|
74
|
+
/**
|
|
75
|
+
* Derived store for session count
|
|
76
|
+
*/
|
|
77
|
+
export declare const sessionCount: import("svelte/store").Readable<number>;
|
|
78
|
+
/**
|
|
79
|
+
* Playground store actions for modifying state
|
|
80
|
+
*/
|
|
81
|
+
export declare const playgroundActions: {
|
|
82
|
+
/**
|
|
83
|
+
* Set the current workflow
|
|
84
|
+
*
|
|
85
|
+
* @param workflow - The workflow to test
|
|
86
|
+
*/
|
|
87
|
+
setWorkflow: (workflow: Workflow | null) => void;
|
|
88
|
+
/**
|
|
89
|
+
* Set the current session
|
|
90
|
+
*
|
|
91
|
+
* @param session - The session to set as active
|
|
92
|
+
*/
|
|
93
|
+
setCurrentSession: (session: PlaygroundSession | null) => void;
|
|
94
|
+
/**
|
|
95
|
+
* Update session status
|
|
96
|
+
*
|
|
97
|
+
* @param status - The new status
|
|
98
|
+
*/
|
|
99
|
+
updateSessionStatus: (status: PlaygroundSessionStatus) => void;
|
|
100
|
+
/**
|
|
101
|
+
* Set the sessions list
|
|
102
|
+
*
|
|
103
|
+
* @param sessionList - Array of sessions
|
|
104
|
+
*/
|
|
105
|
+
setSessions: (sessionList: PlaygroundSession[]) => void;
|
|
106
|
+
/**
|
|
107
|
+
* Add a new session to the list
|
|
108
|
+
*
|
|
109
|
+
* @param session - The session to add
|
|
110
|
+
*/
|
|
111
|
+
addSession: (session: PlaygroundSession) => void;
|
|
112
|
+
/**
|
|
113
|
+
* Remove a session from the list
|
|
114
|
+
*
|
|
115
|
+
* @param sessionId - The session ID to remove
|
|
116
|
+
*/
|
|
117
|
+
removeSession: (sessionId: string) => void;
|
|
118
|
+
/**
|
|
119
|
+
* Set messages for the current session
|
|
120
|
+
*
|
|
121
|
+
* @param messageList - Array of messages
|
|
122
|
+
*/
|
|
123
|
+
setMessages: (messageList: PlaygroundMessage[]) => void;
|
|
124
|
+
/**
|
|
125
|
+
* Add a message to the current session
|
|
126
|
+
*
|
|
127
|
+
* @param message - The message to add
|
|
128
|
+
*/
|
|
129
|
+
addMessage: (message: PlaygroundMessage) => void;
|
|
130
|
+
/**
|
|
131
|
+
* Add multiple messages to the current session
|
|
132
|
+
*
|
|
133
|
+
* @param newMessages - Array of messages to add
|
|
134
|
+
*/
|
|
135
|
+
addMessages: (newMessages: PlaygroundMessage[]) => void;
|
|
136
|
+
/**
|
|
137
|
+
* Clear all messages
|
|
138
|
+
*/
|
|
139
|
+
clearMessages: () => void;
|
|
140
|
+
/**
|
|
141
|
+
* Set the executing state
|
|
142
|
+
*
|
|
143
|
+
* @param executing - Whether execution is in progress
|
|
144
|
+
*/
|
|
145
|
+
setExecuting: (executing: boolean) => void;
|
|
146
|
+
/**
|
|
147
|
+
* Set the loading state
|
|
148
|
+
*
|
|
149
|
+
* @param loading - Whether loading is in progress
|
|
150
|
+
*/
|
|
151
|
+
setLoading: (loading: boolean) => void;
|
|
152
|
+
/**
|
|
153
|
+
* Set an error message
|
|
154
|
+
*
|
|
155
|
+
* @param errorMessage - The error message or null to clear
|
|
156
|
+
*/
|
|
157
|
+
setError: (errorMessage: string | null) => void;
|
|
158
|
+
/**
|
|
159
|
+
* Update the last poll timestamp
|
|
160
|
+
*
|
|
161
|
+
* @param timestamp - ISO 8601 timestamp
|
|
162
|
+
*/
|
|
163
|
+
updateLastPollTimestamp: (timestamp: string) => void;
|
|
164
|
+
/**
|
|
165
|
+
* Reset all playground state
|
|
166
|
+
*/
|
|
167
|
+
reset: () => void;
|
|
168
|
+
/**
|
|
169
|
+
* Switch to a different session
|
|
170
|
+
*
|
|
171
|
+
* @param sessionId - The session ID to switch to
|
|
172
|
+
*/
|
|
173
|
+
switchSession: (sessionId: string) => void;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Get the current session ID
|
|
177
|
+
*
|
|
178
|
+
* @returns The current session ID or null
|
|
179
|
+
*/
|
|
180
|
+
export declare function getCurrentSessionId(): string | null;
|
|
181
|
+
/**
|
|
182
|
+
* Check if a specific session is selected
|
|
183
|
+
*
|
|
184
|
+
* @param sessionId - The session ID to check
|
|
185
|
+
* @returns True if the session is currently selected
|
|
186
|
+
*/
|
|
187
|
+
export declare function isSessionSelected(sessionId: string): boolean;
|
|
188
|
+
/**
|
|
189
|
+
* Get all messages as a snapshot
|
|
190
|
+
*
|
|
191
|
+
* @returns Array of all messages
|
|
192
|
+
*/
|
|
193
|
+
export declare function getMessagesSnapshot(): PlaygroundMessage[];
|
|
194
|
+
/**
|
|
195
|
+
* Get the latest message timestamp for polling
|
|
196
|
+
*
|
|
197
|
+
* @returns ISO 8601 timestamp of the latest message, or null
|
|
198
|
+
*/
|
|
199
|
+
export declare function getLatestMessageTimestamp(): string | null;
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playground Store
|
|
3
|
+
*
|
|
4
|
+
* Svelte stores for managing playground state including sessions,
|
|
5
|
+
* messages, and execution status.
|
|
6
|
+
*
|
|
7
|
+
* @module stores/playgroundStore
|
|
8
|
+
*/
|
|
9
|
+
import { writable, derived, get } from 'svelte/store';
|
|
10
|
+
import { isChatInputNode } from '../types/playground.js';
|
|
11
|
+
// =========================================================================
|
|
12
|
+
// Core Stores
|
|
13
|
+
// =========================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Currently active playground session
|
|
16
|
+
*/
|
|
17
|
+
export const currentSession = writable(null);
|
|
18
|
+
/**
|
|
19
|
+
* List of all sessions for the current workflow
|
|
20
|
+
*/
|
|
21
|
+
export const sessions = writable([]);
|
|
22
|
+
/**
|
|
23
|
+
* Messages in the current session
|
|
24
|
+
*/
|
|
25
|
+
export const messages = writable([]);
|
|
26
|
+
/**
|
|
27
|
+
* Whether an execution is currently running
|
|
28
|
+
*/
|
|
29
|
+
export const isExecuting = writable(false);
|
|
30
|
+
/**
|
|
31
|
+
* Whether we are currently loading data
|
|
32
|
+
*/
|
|
33
|
+
export const isLoading = writable(false);
|
|
34
|
+
/**
|
|
35
|
+
* Current error message, if any
|
|
36
|
+
*/
|
|
37
|
+
export const error = writable(null);
|
|
38
|
+
/**
|
|
39
|
+
* Current workflow being tested
|
|
40
|
+
*/
|
|
41
|
+
export const currentWorkflow = writable(null);
|
|
42
|
+
/**
|
|
43
|
+
* Last polling timestamp for incremental message fetching
|
|
44
|
+
*/
|
|
45
|
+
export const lastPollTimestamp = writable(null);
|
|
46
|
+
// =========================================================================
|
|
47
|
+
// Derived Stores
|
|
48
|
+
// =========================================================================
|
|
49
|
+
/**
|
|
50
|
+
* Derived store for current session status
|
|
51
|
+
*/
|
|
52
|
+
export const sessionStatus = derived(currentSession, ($session) => $session?.status ?? 'idle');
|
|
53
|
+
/**
|
|
54
|
+
* Derived store for message count
|
|
55
|
+
*/
|
|
56
|
+
export const messageCount = derived(messages, ($messages) => $messages.length);
|
|
57
|
+
/**
|
|
58
|
+
* Derived store for chat messages (excludes log messages)
|
|
59
|
+
*/
|
|
60
|
+
export const chatMessages = derived(messages, ($messages) => $messages.filter((m) => m.role !== 'log'));
|
|
61
|
+
/**
|
|
62
|
+
* Derived store for log messages only
|
|
63
|
+
*/
|
|
64
|
+
export const logMessages = derived(messages, ($messages) => $messages.filter((m) => m.role === 'log'));
|
|
65
|
+
/**
|
|
66
|
+
* Derived store for the latest message
|
|
67
|
+
*/
|
|
68
|
+
export const latestMessage = derived(messages, ($messages) => $messages.length > 0 ? $messages[$messages.length - 1] : null);
|
|
69
|
+
/**
|
|
70
|
+
* Derived store for input fields from workflow input nodes
|
|
71
|
+
*
|
|
72
|
+
* Analyzes the workflow to extract input nodes and their configuration
|
|
73
|
+
* schemas for auto-generating input forms.
|
|
74
|
+
*/
|
|
75
|
+
export const inputFields = derived(currentWorkflow, ($workflow) => {
|
|
76
|
+
if (!$workflow) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
const fields = [];
|
|
80
|
+
// Find input nodes in the workflow
|
|
81
|
+
$workflow.nodes.forEach((node) => {
|
|
82
|
+
const category = node.data.metadata?.category;
|
|
83
|
+
const nodeTypeId = node.data.metadata?.id ?? node.type;
|
|
84
|
+
// Check if this is an input-type node
|
|
85
|
+
// The category can be "inputs" (standard) or variations like "input"
|
|
86
|
+
const categoryStr = String(category || '');
|
|
87
|
+
const isInputCategory = categoryStr === 'inputs' || categoryStr === 'input';
|
|
88
|
+
if (isInputCategory || isChatInputNode(nodeTypeId)) {
|
|
89
|
+
// Get output ports that provide data
|
|
90
|
+
const outputs = node.data.metadata?.outputs ?? [];
|
|
91
|
+
outputs.forEach((output) => {
|
|
92
|
+
if (output.type === 'output') {
|
|
93
|
+
// Create a field for each output
|
|
94
|
+
const field = {
|
|
95
|
+
nodeId: node.id,
|
|
96
|
+
fieldId: output.id,
|
|
97
|
+
label: node.data.label || output.name || nodeTypeId,
|
|
98
|
+
type: output.dataType || 'string',
|
|
99
|
+
defaultValue: node.data.config?.[output.id],
|
|
100
|
+
required: output.required ?? false
|
|
101
|
+
};
|
|
102
|
+
// Check for schema in configSchema
|
|
103
|
+
const configSchema = node.data.metadata?.configSchema;
|
|
104
|
+
if (configSchema?.properties?.[output.id]) {
|
|
105
|
+
field.schema = configSchema.properties[output.id];
|
|
106
|
+
}
|
|
107
|
+
fields.push(field);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
// If no outputs defined, create a default field based on node config
|
|
111
|
+
if (outputs.length === 0) {
|
|
112
|
+
const configSchema = node.data.metadata?.configSchema;
|
|
113
|
+
if (configSchema?.properties) {
|
|
114
|
+
Object.entries(configSchema.properties).forEach(([key, schema]) => {
|
|
115
|
+
const field = {
|
|
116
|
+
nodeId: node.id,
|
|
117
|
+
fieldId: key,
|
|
118
|
+
label: schema.title || key,
|
|
119
|
+
type: schema.type || 'string',
|
|
120
|
+
defaultValue: node.data.config?.[key] ?? schema.default,
|
|
121
|
+
required: configSchema.required?.includes(key) ?? false,
|
|
122
|
+
schema
|
|
123
|
+
};
|
|
124
|
+
fields.push(field);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return fields;
|
|
131
|
+
});
|
|
132
|
+
/**
|
|
133
|
+
* Derived store for detecting if workflow has a chat input
|
|
134
|
+
*/
|
|
135
|
+
export const hasChatInput = derived(inputFields, ($fields) => $fields.some((field) => isChatInputNode(field.nodeId) || field.type === 'string'));
|
|
136
|
+
/**
|
|
137
|
+
* Derived store for session count
|
|
138
|
+
*/
|
|
139
|
+
export const sessionCount = derived(sessions, ($sessions) => $sessions.length);
|
|
140
|
+
// =========================================================================
|
|
141
|
+
// Actions
|
|
142
|
+
// =========================================================================
|
|
143
|
+
/**
|
|
144
|
+
* Playground store actions for modifying state
|
|
145
|
+
*/
|
|
146
|
+
export const playgroundActions = {
|
|
147
|
+
/**
|
|
148
|
+
* Set the current workflow
|
|
149
|
+
*
|
|
150
|
+
* @param workflow - The workflow to test
|
|
151
|
+
*/
|
|
152
|
+
setWorkflow: (workflow) => {
|
|
153
|
+
currentWorkflow.set(workflow);
|
|
154
|
+
},
|
|
155
|
+
/**
|
|
156
|
+
* Set the current session
|
|
157
|
+
*
|
|
158
|
+
* @param session - The session to set as active
|
|
159
|
+
*/
|
|
160
|
+
setCurrentSession: (session) => {
|
|
161
|
+
currentSession.set(session);
|
|
162
|
+
if (session) {
|
|
163
|
+
// Update session in the list
|
|
164
|
+
sessions.update(($sessions) => $sessions.map((s) => (s.id === session.id ? session : s)));
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
/**
|
|
168
|
+
* Update session status
|
|
169
|
+
*
|
|
170
|
+
* @param status - The new status
|
|
171
|
+
*/
|
|
172
|
+
updateSessionStatus: (status) => {
|
|
173
|
+
currentSession.update(($session) => {
|
|
174
|
+
if (!$session)
|
|
175
|
+
return null;
|
|
176
|
+
return { ...$session, status, updatedAt: new Date().toISOString() };
|
|
177
|
+
});
|
|
178
|
+
// Also update in sessions list
|
|
179
|
+
const session = get(currentSession);
|
|
180
|
+
if (session) {
|
|
181
|
+
sessions.update(($sessions) => $sessions.map((s) => (s.id === session.id ? { ...s, status } : s)));
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
/**
|
|
185
|
+
* Set the sessions list
|
|
186
|
+
*
|
|
187
|
+
* @param sessionList - Array of sessions
|
|
188
|
+
*/
|
|
189
|
+
setSessions: (sessionList) => {
|
|
190
|
+
sessions.set(sessionList);
|
|
191
|
+
},
|
|
192
|
+
/**
|
|
193
|
+
* Add a new session to the list
|
|
194
|
+
*
|
|
195
|
+
* @param session - The session to add
|
|
196
|
+
*/
|
|
197
|
+
addSession: (session) => {
|
|
198
|
+
sessions.update(($sessions) => [session, ...$sessions]);
|
|
199
|
+
},
|
|
200
|
+
/**
|
|
201
|
+
* Remove a session from the list
|
|
202
|
+
*
|
|
203
|
+
* @param sessionId - The session ID to remove
|
|
204
|
+
*/
|
|
205
|
+
removeSession: (sessionId) => {
|
|
206
|
+
sessions.update(($sessions) => $sessions.filter((s) => s.id !== sessionId));
|
|
207
|
+
// Clear current session if it was removed
|
|
208
|
+
const current = get(currentSession);
|
|
209
|
+
if (current?.id === sessionId) {
|
|
210
|
+
currentSession.set(null);
|
|
211
|
+
messages.set([]);
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
/**
|
|
215
|
+
* Set messages for the current session
|
|
216
|
+
*
|
|
217
|
+
* @param messageList - Array of messages
|
|
218
|
+
*/
|
|
219
|
+
setMessages: (messageList) => {
|
|
220
|
+
messages.set(messageList);
|
|
221
|
+
},
|
|
222
|
+
/**
|
|
223
|
+
* Add a message to the current session
|
|
224
|
+
*
|
|
225
|
+
* @param message - The message to add
|
|
226
|
+
*/
|
|
227
|
+
addMessage: (message) => {
|
|
228
|
+
messages.update(($messages) => [...$messages, message]);
|
|
229
|
+
},
|
|
230
|
+
/**
|
|
231
|
+
* Add multiple messages to the current session
|
|
232
|
+
*
|
|
233
|
+
* @param newMessages - Array of messages to add
|
|
234
|
+
*/
|
|
235
|
+
addMessages: (newMessages) => {
|
|
236
|
+
if (newMessages.length === 0)
|
|
237
|
+
return;
|
|
238
|
+
messages.update(($messages) => {
|
|
239
|
+
// Deduplicate by message ID
|
|
240
|
+
const existingIds = new Set($messages.map((m) => m.id));
|
|
241
|
+
const uniqueNewMessages = newMessages.filter((m) => !existingIds.has(m.id));
|
|
242
|
+
return [...$messages, ...uniqueNewMessages];
|
|
243
|
+
});
|
|
244
|
+
},
|
|
245
|
+
/**
|
|
246
|
+
* Clear all messages
|
|
247
|
+
*/
|
|
248
|
+
clearMessages: () => {
|
|
249
|
+
messages.set([]);
|
|
250
|
+
lastPollTimestamp.set(null);
|
|
251
|
+
},
|
|
252
|
+
/**
|
|
253
|
+
* Set the executing state
|
|
254
|
+
*
|
|
255
|
+
* @param executing - Whether execution is in progress
|
|
256
|
+
*/
|
|
257
|
+
setExecuting: (executing) => {
|
|
258
|
+
isExecuting.set(executing);
|
|
259
|
+
},
|
|
260
|
+
/**
|
|
261
|
+
* Set the loading state
|
|
262
|
+
*
|
|
263
|
+
* @param loading - Whether loading is in progress
|
|
264
|
+
*/
|
|
265
|
+
setLoading: (loading) => {
|
|
266
|
+
isLoading.set(loading);
|
|
267
|
+
},
|
|
268
|
+
/**
|
|
269
|
+
* Set an error message
|
|
270
|
+
*
|
|
271
|
+
* @param errorMessage - The error message or null to clear
|
|
272
|
+
*/
|
|
273
|
+
setError: (errorMessage) => {
|
|
274
|
+
error.set(errorMessage);
|
|
275
|
+
},
|
|
276
|
+
/**
|
|
277
|
+
* Update the last poll timestamp
|
|
278
|
+
*
|
|
279
|
+
* @param timestamp - ISO 8601 timestamp
|
|
280
|
+
*/
|
|
281
|
+
updateLastPollTimestamp: (timestamp) => {
|
|
282
|
+
lastPollTimestamp.set(timestamp);
|
|
283
|
+
},
|
|
284
|
+
/**
|
|
285
|
+
* Reset all playground state
|
|
286
|
+
*/
|
|
287
|
+
reset: () => {
|
|
288
|
+
currentSession.set(null);
|
|
289
|
+
sessions.set([]);
|
|
290
|
+
messages.set([]);
|
|
291
|
+
isExecuting.set(false);
|
|
292
|
+
isLoading.set(false);
|
|
293
|
+
error.set(null);
|
|
294
|
+
currentWorkflow.set(null);
|
|
295
|
+
lastPollTimestamp.set(null);
|
|
296
|
+
},
|
|
297
|
+
/**
|
|
298
|
+
* Switch to a different session
|
|
299
|
+
*
|
|
300
|
+
* @param sessionId - The session ID to switch to
|
|
301
|
+
*/
|
|
302
|
+
switchSession: (sessionId) => {
|
|
303
|
+
const sessionList = get(sessions);
|
|
304
|
+
const session = sessionList.find((s) => s.id === sessionId);
|
|
305
|
+
if (session) {
|
|
306
|
+
currentSession.set(session);
|
|
307
|
+
messages.set([]);
|
|
308
|
+
lastPollTimestamp.set(null);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
// =========================================================================
|
|
313
|
+
// Utilities
|
|
314
|
+
// =========================================================================
|
|
315
|
+
/**
|
|
316
|
+
* Get the current session ID
|
|
317
|
+
*
|
|
318
|
+
* @returns The current session ID or null
|
|
319
|
+
*/
|
|
320
|
+
export function getCurrentSessionId() {
|
|
321
|
+
return get(currentSession)?.id ?? null;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Check if a specific session is selected
|
|
325
|
+
*
|
|
326
|
+
* @param sessionId - The session ID to check
|
|
327
|
+
* @returns True if the session is currently selected
|
|
328
|
+
*/
|
|
329
|
+
export function isSessionSelected(sessionId) {
|
|
330
|
+
return get(currentSession)?.id === sessionId;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Get all messages as a snapshot
|
|
334
|
+
*
|
|
335
|
+
* @returns Array of all messages
|
|
336
|
+
*/
|
|
337
|
+
export function getMessagesSnapshot() {
|
|
338
|
+
return get(messages);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Get the latest message timestamp for polling
|
|
342
|
+
*
|
|
343
|
+
* @returns ISO 8601 timestamp of the latest message, or null
|
|
344
|
+
*/
|
|
345
|
+
export function getLatestMessageTimestamp() {
|
|
346
|
+
const msgs = get(messages);
|
|
347
|
+
if (msgs.length === 0)
|
|
348
|
+
return null;
|
|
349
|
+
return msgs[msgs.length - 1].timestamp;
|
|
350
|
+
}
|