@flowdrop/flowdrop 1.10.0 → 1.12.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 (53) hide show
  1. package/dist/api/enhanced-client.d.ts +29 -16
  2. package/dist/api/enhanced-client.js +0 -14
  3. package/dist/components/Navbar.svelte +1 -10
  4. package/dist/components/Navbar.svelte.d.ts +1 -9
  5. package/dist/components/PipelineStatus.svelte +9 -12
  6. package/dist/components/WorkflowEditor.svelte +3 -0
  7. package/dist/components/interrupt/ChoicePrompt.svelte +24 -5
  8. package/dist/components/interrupt/ConfirmationPrompt.svelte +5 -0
  9. package/dist/components/interrupt/InterruptBubble.svelte +12 -0
  10. package/dist/components/interrupt/ReviewPrompt.svelte +20 -0
  11. package/dist/components/interrupt/TextInputPrompt.svelte +5 -0
  12. package/dist/components/nodes/GatewayNode.svelte +2 -6
  13. package/dist/components/nodes/WorkflowNode.svelte +2 -6
  14. package/dist/components/playground/ChatInput.svelte +359 -0
  15. package/dist/components/playground/ChatInput.svelte.d.ts +14 -0
  16. package/dist/components/playground/ChatPanel.svelte +100 -724
  17. package/dist/components/playground/ChatPanel.svelte.d.ts +9 -26
  18. package/dist/components/playground/ControlPanel.svelte +496 -0
  19. package/dist/components/playground/ControlPanel.svelte.d.ts +20 -0
  20. package/dist/components/playground/ExecutionConsole.svelte +163 -0
  21. package/dist/components/playground/ExecutionConsole.svelte.d.ts +14 -0
  22. package/dist/components/playground/MessageStream.svelte +283 -0
  23. package/dist/components/playground/MessageStream.svelte.d.ts +27 -0
  24. package/dist/components/playground/PipelineKanbanView.svelte +284 -0
  25. package/dist/components/playground/PipelineKanbanView.svelte.d.ts +11 -0
  26. package/dist/components/playground/PipelinePanel.svelte +204 -65
  27. package/dist/components/playground/PipelinePanel.svelte.d.ts +3 -1
  28. package/dist/components/playground/PipelineTableView.svelte +376 -0
  29. package/dist/components/playground/PipelineTableView.svelte.d.ts +11 -0
  30. package/dist/components/playground/Playground.svelte +262 -1200
  31. package/dist/components/playground/Playground.svelte.d.ts +0 -13
  32. package/dist/components/playground/PlaygroundApp.svelte +110 -0
  33. package/dist/components/playground/PlaygroundApp.svelte.d.ts +28 -0
  34. package/dist/components/playground/PlaygroundStudio.svelte +35 -61
  35. package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -1
  36. package/dist/components/playground/pipelineViewUtils.svelte.d.ts +22 -0
  37. package/dist/components/playground/pipelineViewUtils.svelte.js +77 -0
  38. package/dist/messages/defaults.d.ts +24 -0
  39. package/dist/messages/defaults.js +24 -0
  40. package/dist/playground/index.d.ts +8 -2
  41. package/dist/playground/index.js +8 -1
  42. package/dist/playground/mount.d.ts +59 -4
  43. package/dist/playground/mount.js +102 -9
  44. package/dist/stores/playgroundStore.svelte.d.ts +6 -0
  45. package/dist/stores/playgroundStore.svelte.js +21 -1
  46. package/dist/svelte-app.d.ts +2 -10
  47. package/dist/types/index.d.ts +28 -2
  48. package/dist/types/navbar.d.ts +14 -0
  49. package/dist/types/navbar.js +1 -0
  50. package/dist/types/playground.d.ts +5 -2
  51. package/dist/types/playground.js +5 -7
  52. package/dist/utils/nodeStatus.js +15 -5
  53. package/package.json +1 -1
@@ -0,0 +1,376 @@
1
+ <script module lang="ts">
2
+ import type { NodeStatus } from './pipelineViewUtils.svelte.js';
3
+
4
+ const STATUS_ORDER: Record<NodeStatus, number> = {
5
+ running: 0,
6
+ paused: 1,
7
+ interrupted: 2,
8
+ pending: 3,
9
+ idle: 4,
10
+ completed: 5,
11
+ skipped: 6,
12
+ cancelled: 7,
13
+ failed: 8
14
+ };
15
+
16
+ const STATUS_ICON: Record<NodeStatus, string> = {
17
+ running: 'mdi:play-circle-outline',
18
+ paused: 'mdi:pause-circle-outline',
19
+ interrupted: 'mdi:account-clock-outline',
20
+ completed: 'mdi:check-circle',
21
+ skipped: 'mdi:skip-next-circle-outline',
22
+ failed: 'mdi:alert-circle',
23
+ cancelled: 'mdi:cancel',
24
+ pending: 'mdi:clock-outline',
25
+ idle: 'mdi:circle-outline'
26
+ };
27
+
28
+ function formatDuration(ms: number | null | undefined): string | null {
29
+ if (ms == null) return null;
30
+ if (ms < 1000) return `${ms}ms`;
31
+ if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;
32
+ const mins = Math.floor(ms / 60000);
33
+ const secs = Math.floor((ms % 60000) / 1000);
34
+ return `${mins}m ${secs}s`;
35
+ }
36
+
37
+ function formatDateTime(iso: string | null | undefined): string | null {
38
+ if (!iso) return null;
39
+ return new Date(iso).toLocaleString();
40
+ }
41
+ </script>
42
+
43
+ <script lang="ts">
44
+ import { onMount } from 'svelte';
45
+ import Icon from '@iconify/svelte';
46
+ import { createPipelineDataFetcher, resolveStatus } from './pipelineViewUtils.svelte.js';
47
+ import { getStatusTextColor } from '../../utils/nodeStatus.js';
48
+ import type { NodeStatusData } from './pipelineViewUtils.svelte.js';
49
+ import type { Workflow, WorkflowNode } from '../../types/index.js';
50
+ import type { EndpointConfig } from '../../config/endpoints.js';
51
+
52
+ interface Props {
53
+ pipelineId: string;
54
+ workflow: Workflow;
55
+ endpointConfig: EndpointConfig;
56
+ refreshTrigger?: number;
57
+ }
58
+
59
+ let { pipelineId, workflow, endpointConfig, refreshTrigger = 0 }: Props = $props();
60
+
61
+ interface NodeRow {
62
+ node: WorkflowNode;
63
+ status: NodeStatus;
64
+ statusData: NodeStatusData | undefined;
65
+ }
66
+
67
+ const fetcher = createPipelineDataFetcher(() => pipelineId, endpointConfig);
68
+
69
+ $effect(() => {
70
+ if (refreshTrigger <= 0) return;
71
+ const timer = setTimeout(() => fetcher.fetchData(), 300);
72
+ return () => clearTimeout(timer);
73
+ });
74
+
75
+ const sortedRows = $derived.by((): NodeRow[] =>
76
+ workflow.nodes
77
+ .map((node) => {
78
+ const statusData = fetcher.nodeStatusMap[node.id];
79
+ return { node, status: resolveStatus(statusData), statusData };
80
+ })
81
+ .sort((a, b) => (STATUS_ORDER[a.status] ?? Infinity) - (STATUS_ORDER[b.status] ?? Infinity))
82
+ );
83
+
84
+ let expandedIds = $state(new Set<string>());
85
+
86
+ function hasDetails(row: NodeRow): boolean {
87
+ return !!(row.statusData?.last_executed || row.statusData?.error);
88
+ }
89
+
90
+ function toggleRow(row: NodeRow) {
91
+ if (!hasDetails(row)) return;
92
+ const next = new Set(expandedIds);
93
+ if (next.has(row.node.id)) {
94
+ next.delete(row.node.id);
95
+ } else {
96
+ next.add(row.node.id);
97
+ }
98
+ expandedIds = next;
99
+ }
100
+
101
+ onMount(() => {
102
+ fetcher.fetchData();
103
+ });
104
+ </script>
105
+
106
+ <div class="pipeline-table">
107
+ {#if fetcher.isError}
108
+ <div class="pipeline-table__error">Could not refresh status data</div>
109
+ {/if}
110
+ {#if fetcher.isLoading && Object.keys(fetcher.nodeStatusMap).length === 0}
111
+ <div class="pipeline-table__loading">
112
+ <Icon icon="mdi:loading" class="pipeline-table__spinner" />
113
+ </div>
114
+ {:else}
115
+ <div class="pipeline-table__wrap">
116
+ <table class="pipeline-table__table">
117
+ <thead class="pipeline-table__thead">
118
+ <tr>
119
+ <th class="pipeline-table__th pipeline-table__th--expand"></th>
120
+ <th class="pipeline-table__th">Node</th>
121
+ <th class="pipeline-table__th">Type</th>
122
+ <th class="pipeline-table__th">Status</th>
123
+ <th class="pipeline-table__th pipeline-table__th--id">ID</th>
124
+ </tr>
125
+ </thead>
126
+ <tbody>
127
+ {#each sortedRows as row (row.node.id)}
128
+ {@const expanded = expandedIds.has(row.node.id)}
129
+ {@const expandable = hasDetails(row)}
130
+ <tr
131
+ class="pipeline-table__row"
132
+ class:pipeline-table__row--expandable={expandable}
133
+ class:pipeline-table__row--expanded={expanded}
134
+ onclick={() => toggleRow(row)}
135
+ >
136
+ <td class="pipeline-table__td pipeline-table__td--expand">
137
+ {#if expandable}
138
+ <Icon
139
+ icon="mdi:chevron-right"
140
+ class="pipeline-table__chevron {expanded ? 'pipeline-table__chevron--open' : ''}"
141
+ />
142
+ {/if}
143
+ </td>
144
+ <td class="pipeline-table__td pipeline-table__td--label" title={row.node.data.label}>{row.node.data.label}</td>
145
+ <td class="pipeline-table__td pipeline-table__td--muted" title={row.node.data.metadata.id}>{row.node.data.metadata.id}</td>
146
+ <td class="pipeline-table__td">
147
+ <span class="pipeline-table__status" style="color: {getStatusTextColor(row.status)}">
148
+ <Icon
149
+ icon={STATUS_ICON[row.status] ?? 'mdi:circle-outline'}
150
+ class="pipeline-table__status-icon"
151
+ />
152
+ {row.status}
153
+ </span>
154
+ </td>
155
+ <td class="pipeline-table__td pipeline-table__td--id" title={row.node.id}>{row.node.id}</td>
156
+ </tr>
157
+ {#if expanded && expandable}
158
+ <tr class="pipeline-table__detail-row">
159
+ <td colspan="5" class="pipeline-table__detail-cell">
160
+ <dl class="pipeline-table__details">
161
+ {#if row.statusData?.last_executed}
162
+ <div class="pipeline-table__detail-item">
163
+ <dt>Last executed</dt>
164
+ <dd>{formatDateTime(row.statusData.last_executed)}</dd>
165
+ </div>
166
+ {/if}
167
+ {#if row.statusData?.execution_time != null}
168
+ <div class="pipeline-table__detail-item">
169
+ <dt>Duration</dt>
170
+ <dd>{formatDuration(row.statusData.execution_time)}</dd>
171
+ </div>
172
+ {/if}
173
+ {#if row.statusData?.error}
174
+ <div class="pipeline-table__detail-item pipeline-table__detail-item--error">
175
+ <dt>Error</dt>
176
+ <dd>{row.statusData.error}</dd>
177
+ </div>
178
+ {/if}
179
+ </dl>
180
+ </td>
181
+ </tr>
182
+ {/if}
183
+ {/each}
184
+ </tbody>
185
+ </table>
186
+ </div>
187
+ {/if}
188
+ </div>
189
+
190
+ <style>
191
+ .pipeline-table {
192
+ height: 100%;
193
+ overflow: hidden;
194
+ display: flex;
195
+ flex-direction: column;
196
+ }
197
+
198
+ .pipeline-table__error {
199
+ padding: var(--fd-space-xs) var(--fd-space-md);
200
+ font-size: var(--fd-text-2xs);
201
+ color: var(--fd-error);
202
+ background-color: color-mix(in srgb, var(--fd-error) 8%, transparent);
203
+ border-bottom: 1px solid color-mix(in srgb, var(--fd-error) 20%, transparent);
204
+ flex-shrink: 0;
205
+ }
206
+
207
+ .pipeline-table__loading {
208
+ display: flex;
209
+ align-items: center;
210
+ justify-content: center;
211
+ flex: 1;
212
+ color: var(--fd-muted-foreground);
213
+ }
214
+
215
+ :global(.pipeline-table__spinner) {
216
+ font-size: 1.5rem;
217
+ animation: table-spin 1s linear infinite;
218
+ }
219
+
220
+ @keyframes table-spin {
221
+ to {
222
+ transform: rotate(360deg);
223
+ }
224
+ }
225
+
226
+ .pipeline-table__wrap {
227
+ flex: 1;
228
+ overflow-y: auto;
229
+ }
230
+
231
+ .pipeline-table__table {
232
+ width: 100%;
233
+ border-collapse: collapse;
234
+ font-size: var(--fd-text-xs);
235
+ }
236
+
237
+ .pipeline-table__thead {
238
+ position: sticky;
239
+ top: 0;
240
+ background-color: var(--fd-muted);
241
+ z-index: 1;
242
+ }
243
+
244
+ .pipeline-table__th {
245
+ text-align: left;
246
+ padding: var(--fd-space-sm) var(--fd-space-md);
247
+ font-size: var(--fd-text-2xs);
248
+ font-weight: 600;
249
+ text-transform: uppercase;
250
+ letter-spacing: 0.05em;
251
+ color: var(--fd-muted-foreground);
252
+ border-bottom: 1px solid var(--fd-border);
253
+ white-space: nowrap;
254
+ }
255
+
256
+ .pipeline-table__th--id {
257
+ font-family: var(--fd-font-mono, monospace);
258
+ }
259
+
260
+ .pipeline-table__th--expand {
261
+ width: 1.5rem;
262
+ padding-right: 0;
263
+ }
264
+
265
+ .pipeline-table__row--expandable {
266
+ cursor: pointer;
267
+ }
268
+
269
+ .pipeline-table__row--expandable:hover,
270
+ .pipeline-table__row--expanded:hover {
271
+ background-color: var(--fd-muted);
272
+ }
273
+
274
+ .pipeline-table__row--expanded {
275
+ background-color: color-mix(in srgb, var(--fd-muted) 60%, transparent);
276
+ }
277
+
278
+ .pipeline-table__td {
279
+ padding: var(--fd-space-sm) var(--fd-space-md);
280
+ color: var(--fd-foreground);
281
+ border-bottom: 1px solid var(--fd-border);
282
+ }
283
+
284
+ .pipeline-table__td--expand {
285
+ padding-right: 0;
286
+ width: 1.5rem;
287
+ color: var(--fd-muted-foreground);
288
+ }
289
+
290
+ .pipeline-table__td--label,
291
+ .pipeline-table__td--muted {
292
+ max-width: 200px;
293
+ overflow: hidden;
294
+ text-overflow: ellipsis;
295
+ white-space: nowrap;
296
+ }
297
+
298
+ .pipeline-table__td--muted {
299
+ color: var(--fd-muted-foreground);
300
+ }
301
+
302
+ .pipeline-table__td--id {
303
+ font-family: var(--fd-font-mono, monospace);
304
+ font-size: var(--fd-text-2xs);
305
+ color: var(--fd-muted-foreground);
306
+ }
307
+
308
+ :global(.pipeline-table__chevron) {
309
+ font-size: var(--fd-text-sm);
310
+ transition: transform 0.15s ease;
311
+ display: block;
312
+ }
313
+
314
+ :global(.pipeline-table__chevron--open) {
315
+ transform: rotate(90deg);
316
+ }
317
+
318
+ .pipeline-table__detail-row {
319
+ background-color: color-mix(in srgb, var(--fd-muted) 40%, transparent);
320
+ }
321
+
322
+ .pipeline-table__detail-cell {
323
+ padding: var(--fd-space-sm) var(--fd-space-md) var(--fd-space-sm) calc(1.5rem + var(--fd-space-md));
324
+ border-bottom: 1px solid var(--fd-border);
325
+ }
326
+
327
+ .pipeline-table__details {
328
+ display: flex;
329
+ flex-wrap: wrap;
330
+ gap: var(--fd-space-sm) var(--fd-space-xl);
331
+ margin: 0;
332
+ }
333
+
334
+ .pipeline-table__detail-item {
335
+ display: flex;
336
+ flex-direction: column;
337
+ gap: 2px;
338
+ }
339
+
340
+ .pipeline-table__detail-item dt {
341
+ font-size: var(--fd-text-2xs);
342
+ font-weight: 600;
343
+ text-transform: uppercase;
344
+ letter-spacing: 0.05em;
345
+ color: var(--fd-muted-foreground);
346
+ }
347
+
348
+ .pipeline-table__detail-item dd {
349
+ font-size: var(--fd-text-xs);
350
+ color: var(--fd-foreground);
351
+ margin: 0;
352
+ }
353
+
354
+ .pipeline-table__detail-item--error dt {
355
+ color: var(--fd-error);
356
+ }
357
+
358
+ .pipeline-table__detail-item--error dd {
359
+ color: var(--fd-error);
360
+ font-family: var(--fd-font-mono, monospace);
361
+ font-size: var(--fd-text-2xs);
362
+ }
363
+
364
+ .pipeline-table__status {
365
+ display: inline-flex;
366
+ align-items: center;
367
+ gap: var(--fd-space-3xs);
368
+ font-weight: 500;
369
+ text-transform: capitalize;
370
+ }
371
+
372
+ :global(.pipeline-table__status-icon) {
373
+ font-size: var(--fd-text-sm);
374
+ flex-shrink: 0;
375
+ }
376
+ </style>
@@ -0,0 +1,11 @@
1
+ import type { Workflow } from '../../types/index.js';
2
+ import type { EndpointConfig } from '../../config/endpoints.js';
3
+ interface Props {
4
+ pipelineId: string;
5
+ workflow: Workflow;
6
+ endpointConfig: EndpointConfig;
7
+ refreshTrigger?: number;
8
+ }
9
+ declare const PipelineTableView: import("svelte").Component<Props, {}, "">;
10
+ type PipelineTableView = ReturnType<typeof PipelineTableView>;
11
+ export default PipelineTableView;