@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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/dist/components/NodeSidebar.svelte +1 -0
  3. package/dist/components/form/FormCodeEditor.svelte +6 -1
  4. package/dist/components/interrupt/ChoicePrompt.svelte +389 -0
  5. package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +21 -0
  6. package/dist/components/interrupt/ConfirmationPrompt.svelte +280 -0
  7. package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +23 -0
  8. package/dist/components/interrupt/FormPrompt.svelte +223 -0
  9. package/dist/components/interrupt/FormPrompt.svelte.d.ts +21 -0
  10. package/dist/components/interrupt/InterruptBubble.svelte +621 -0
  11. package/dist/components/interrupt/InterruptBubble.svelte.d.ts +16 -0
  12. package/dist/components/interrupt/TextInputPrompt.svelte +333 -0
  13. package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +21 -0
  14. package/dist/components/interrupt/index.d.ts +13 -0
  15. package/dist/components/interrupt/index.js +15 -0
  16. package/dist/components/nodes/GatewayNode.svelte +1 -3
  17. package/dist/components/nodes/IdeaNode.svelte +30 -35
  18. package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
  19. package/dist/components/nodes/SimpleNode.svelte +1 -3
  20. package/dist/components/nodes/TerminalNode.svelte +1 -3
  21. package/dist/components/nodes/ToolNode.svelte +2 -2
  22. package/dist/components/nodes/WorkflowNode.svelte +1 -3
  23. package/dist/components/playground/ChatPanel.svelte +144 -7
  24. package/dist/components/playground/ChatPanel.svelte.d.ts +2 -0
  25. package/dist/components/playground/MessageBubble.svelte +1 -3
  26. package/dist/components/playground/Playground.svelte +50 -5
  27. package/dist/components/playground/PlaygroundModal.svelte +8 -7
  28. package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
  29. package/dist/config/endpoints.d.ts +12 -0
  30. package/dist/config/endpoints.js +7 -0
  31. package/dist/playground/index.d.ts +5 -0
  32. package/dist/playground/index.js +21 -0
  33. package/dist/playground/mount.d.ts +3 -3
  34. package/dist/playground/mount.js +30 -22
  35. package/dist/services/interruptService.d.ts +133 -0
  36. package/dist/services/interruptService.js +279 -0
  37. package/dist/stores/interruptStore.d.ts +200 -0
  38. package/dist/stores/interruptStore.js +424 -0
  39. package/dist/stores/playgroundStore.d.ts +11 -1
  40. package/dist/stores/playgroundStore.js +34 -0
  41. package/dist/styles/base.css +89 -0
  42. package/dist/types/index.d.ts +1 -1
  43. package/dist/types/interrupt.d.ts +305 -0
  44. package/dist/types/interrupt.js +126 -0
  45. package/dist/types/interruptState.d.ts +211 -0
  46. package/dist/types/interruptState.js +308 -0
  47. package/dist/utils/colors.js +1 -0
  48. package/dist/utils/connections.js +2 -2
  49. package/dist/utils/icons.js +1 -0
  50. package/package.json +1 -1
@@ -0,0 +1,280 @@
1
+ <!--
2
+ ConfirmationPrompt Component
3
+
4
+ Renders a Yes/No confirmation prompt for confirmation-type interrupts.
5
+ Displays the message and two action buttons with customizable labels.
6
+ Shows the selected response when resolved.
7
+ Styled with BEM syntax.
8
+ -->
9
+
10
+ <script lang="ts">
11
+ import Icon from '@iconify/svelte';
12
+ import type { ConfirmationConfig } from '../../types/interrupt.js';
13
+
14
+ /**
15
+ * Component props
16
+ */
17
+ interface Props {
18
+ /** Confirmation configuration from the interrupt */
19
+ config: ConfirmationConfig;
20
+ /** Whether this interrupt has been resolved */
21
+ isResolved: boolean;
22
+ /** The resolved value (true/false) if resolved */
23
+ resolvedValue?: boolean;
24
+ /** Whether the form is currently submitting */
25
+ isSubmitting: boolean;
26
+ /** Error message if submission failed */
27
+ error?: string;
28
+ /** Callback when user confirms (Yes) */
29
+ onConfirm: () => void;
30
+ /** Callback when user declines (No) */
31
+ onDecline: () => void;
32
+ }
33
+
34
+ let { config, isResolved, resolvedValue, isSubmitting, error, onConfirm, onDecline }: Props =
35
+ $props();
36
+
37
+ /** Computed label for confirm button */
38
+ const confirmLabel = $derived(config.confirmLabel ?? 'Yes');
39
+
40
+ /** Computed label for decline/cancel button */
41
+ const declineLabel = $derived(config.cancelLabel ?? 'No');
42
+ </script>
43
+
44
+ <div
45
+ class="confirmation-prompt"
46
+ class:confirmation-prompt--resolved={isResolved}
47
+ class:confirmation-prompt--submitting={isSubmitting}
48
+ >
49
+ <!-- Message -->
50
+ <p class="confirmation-prompt__message">{config.message}</p>
51
+
52
+ <!-- Error message -->
53
+ {#if error}
54
+ <div class="confirmation-prompt__error">
55
+ <Icon icon="mdi:alert-circle" />
56
+ <span>{error}</span>
57
+ </div>
58
+ {/if}
59
+
60
+ <!-- Actions -->
61
+ <div class="confirmation-prompt__actions">
62
+ <button
63
+ type="button"
64
+ class="confirmation-prompt__button confirmation-prompt__button--decline"
65
+ class:confirmation-prompt__button--selected={isResolved && resolvedValue === false}
66
+ class:confirmation-prompt__button--not-selected={isResolved && resolvedValue !== false}
67
+ onclick={onDecline}
68
+ disabled={isResolved || isSubmitting}
69
+ aria-label={declineLabel}
70
+ >
71
+ {#if isSubmitting && !isResolved}
72
+ <span class="confirmation-prompt__spinner"></span>
73
+ {:else if isResolved && resolvedValue === false}
74
+ <Icon icon="mdi:check-circle" />
75
+ {:else if isResolved}
76
+ <!-- Not selected - show dimmed X icon -->
77
+ <Icon icon="mdi:close" />
78
+ {:else}
79
+ <Icon icon="mdi:close" />
80
+ {/if}
81
+ <span>{declineLabel}</span>
82
+ </button>
83
+
84
+ <button
85
+ type="button"
86
+ class="confirmation-prompt__button confirmation-prompt__button--confirm"
87
+ class:confirmation-prompt__button--selected={isResolved && resolvedValue === true}
88
+ class:confirmation-prompt__button--not-selected={isResolved && resolvedValue !== true}
89
+ onclick={onConfirm}
90
+ disabled={isResolved || isSubmitting}
91
+ aria-label={confirmLabel}
92
+ >
93
+ {#if isSubmitting && !isResolved}
94
+ <span class="confirmation-prompt__spinner"></span>
95
+ {:else if isResolved && resolvedValue === true}
96
+ <Icon icon="mdi:check-circle" />
97
+ {:else if isResolved}
98
+ <!-- Not selected - show dimmed check icon -->
99
+ <Icon icon="mdi:check" />
100
+ {:else}
101
+ <Icon icon="mdi:check" />
102
+ {/if}
103
+ <span>{confirmLabel}</span>
104
+ </button>
105
+ </div>
106
+
107
+ <!-- Resolved indicator -->
108
+ {#if isResolved}
109
+ <div class="confirmation-prompt__resolved-badge">
110
+ <Icon icon="mdi:check-circle" />
111
+ <span>Response submitted</span>
112
+ </div>
113
+ {/if}
114
+ </div>
115
+
116
+ <style>
117
+ .confirmation-prompt {
118
+ display: flex;
119
+ flex-direction: column;
120
+ gap: 0.75rem;
121
+ }
122
+
123
+ .confirmation-prompt--resolved {
124
+ opacity: 0.85;
125
+ }
126
+
127
+ .confirmation-prompt--submitting {
128
+ pointer-events: none;
129
+ }
130
+
131
+ .confirmation-prompt__message {
132
+ margin: 0;
133
+ font-size: 0.9375rem;
134
+ line-height: 1.5;
135
+ color: var(--color-ref-gray-800, #1f2937);
136
+ }
137
+
138
+ .confirmation-prompt__error {
139
+ display: flex;
140
+ align-items: center;
141
+ gap: 0.375rem;
142
+ padding: 0.5rem 0.75rem;
143
+ background-color: var(--color-ref-red-50, #fef2f2);
144
+ border-radius: 0.375rem;
145
+ color: var(--color-ref-red-600, #dc2626);
146
+ font-size: 0.8125rem;
147
+ }
148
+
149
+ .confirmation-prompt__actions {
150
+ display: flex;
151
+ gap: 0.75rem;
152
+ flex-wrap: wrap;
153
+ }
154
+
155
+ .confirmation-prompt__button {
156
+ display: inline-flex;
157
+ align-items: center;
158
+ justify-content: center;
159
+ gap: 0.5rem;
160
+ padding: 0.625rem 1.25rem;
161
+ border-radius: 0.5rem;
162
+ font-size: 0.875rem;
163
+ font-weight: 600;
164
+ font-family: inherit;
165
+ cursor: pointer;
166
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
167
+ border: 1px solid transparent;
168
+ min-height: 2.5rem;
169
+ min-width: 100px;
170
+ }
171
+
172
+ .confirmation-prompt__button:disabled {
173
+ cursor: not-allowed;
174
+ }
175
+
176
+ /* Uses design tokens from base.css: --flowdrop-interrupt-* */
177
+ .confirmation-prompt__button--decline {
178
+ background-color: var(--flowdrop-interrupt-btn-secondary-bg);
179
+ border-color: var(--flowdrop-interrupt-btn-secondary-border);
180
+ color: var(--flowdrop-interrupt-btn-secondary-text);
181
+ }
182
+
183
+ .confirmation-prompt__button--decline:hover:not(:disabled) {
184
+ background-color: var(--color-ref-gray-200, #e5e7eb);
185
+ border-color: var(--color-ref-gray-400, #9ca3af);
186
+ }
187
+
188
+ .confirmation-prompt__button--decline:disabled {
189
+ opacity: 0.6;
190
+ }
191
+
192
+ /* Non-selected decline button when resolved - very dimmed */
193
+ .confirmation-prompt__button--decline.confirmation-prompt__button--not-selected {
194
+ opacity: var(--flowdrop-interrupt-not-selected-opacity);
195
+ background-color: var(--color-ref-gray-50, #f9fafb);
196
+ border-color: var(--color-ref-gray-200, #e5e7eb);
197
+ color: var(--color-ref-gray-400, #9ca3af);
198
+ }
199
+
200
+ /* Selected decline button - highlighted with border and background */
201
+ .confirmation-prompt__button--decline.confirmation-prompt__button--selected {
202
+ opacity: 1;
203
+ background-color: var(--flowdrop-interrupt-selected-decline-bg);
204
+ border-color: var(--flowdrop-interrupt-selected-decline-border);
205
+ border-width: 2px;
206
+ color: var(--flowdrop-interrupt-selected-decline-text);
207
+ box-shadow: 0 0 0 3px var(--flowdrop-interrupt-selected-decline-glow);
208
+ }
209
+
210
+ .confirmation-prompt__button--confirm {
211
+ background: var(--flowdrop-interrupt-btn-primary-bg);
212
+ color: #ffffff;
213
+ box-shadow: 0 1px 3px var(--flowdrop-interrupt-btn-primary-shadow);
214
+ }
215
+
216
+ .confirmation-prompt__button--confirm:hover:not(:disabled) {
217
+ background: var(--flowdrop-interrupt-btn-primary-bg-hover);
218
+ box-shadow: 0 4px 12px var(--flowdrop-interrupt-btn-primary-shadow);
219
+ transform: translateY(-1px);
220
+ }
221
+
222
+ .confirmation-prompt__button--confirm:disabled {
223
+ opacity: 0.6;
224
+ transform: none;
225
+ box-shadow: none;
226
+ }
227
+
228
+ /* Non-selected confirm button when resolved - very dimmed */
229
+ .confirmation-prompt__button--confirm.confirmation-prompt__button--not-selected {
230
+ opacity: var(--flowdrop-interrupt-not-selected-opacity);
231
+ background: var(--color-ref-gray-200, #e5e7eb);
232
+ color: var(--color-ref-gray-400, #9ca3af);
233
+ box-shadow: none;
234
+ }
235
+
236
+ /* Selected confirm button - highlighted with glow */
237
+ .confirmation-prompt__button--confirm.confirmation-prompt__button--selected {
238
+ opacity: 1;
239
+ background: var(--flowdrop-interrupt-selected-confirm-bg);
240
+ border-width: 2px;
241
+ border-color: var(--flowdrop-interrupt-selected-confirm-border);
242
+ box-shadow:
243
+ 0 0 0 3px var(--flowdrop-interrupt-selected-confirm-glow),
244
+ 0 2px 8px var(--flowdrop-interrupt-btn-primary-shadow);
245
+ }
246
+
247
+ .confirmation-prompt__spinner {
248
+ width: 1rem;
249
+ height: 1rem;
250
+ border: 2px solid rgba(255, 255, 255, 0.3);
251
+ border-top-color: currentColor;
252
+ border-radius: 50%;
253
+ animation: confirmation-spin 0.6s linear infinite;
254
+ }
255
+
256
+ .confirmation-prompt__button--decline .confirmation-prompt__spinner {
257
+ border-color: rgba(55, 65, 81, 0.3);
258
+ border-top-color: #374151;
259
+ }
260
+
261
+ @keyframes confirmation-spin {
262
+ to {
263
+ transform: rotate(360deg);
264
+ }
265
+ }
266
+
267
+ /* Resolved badge - neutral blue theme */
268
+ .confirmation-prompt__resolved-badge {
269
+ display: inline-flex;
270
+ align-items: center;
271
+ gap: 0.375rem;
272
+ padding: 0.375rem 0.75rem;
273
+ background-color: var(--flowdrop-interrupt-badge-completed-bg);
274
+ border-radius: 9999px;
275
+ color: var(--flowdrop-interrupt-badge-completed-text);
276
+ font-size: 0.75rem;
277
+ font-weight: 500;
278
+ align-self: flex-start;
279
+ }
280
+ </style>
@@ -0,0 +1,23 @@
1
+ import type { ConfirmationConfig } from '../../types/interrupt.js';
2
+ /**
3
+ * Component props
4
+ */
5
+ interface Props {
6
+ /** Confirmation configuration from the interrupt */
7
+ config: ConfirmationConfig;
8
+ /** Whether this interrupt has been resolved */
9
+ isResolved: boolean;
10
+ /** The resolved value (true/false) if resolved */
11
+ resolvedValue?: boolean;
12
+ /** Whether the form is currently submitting */
13
+ isSubmitting: boolean;
14
+ /** Error message if submission failed */
15
+ error?: string;
16
+ /** Callback when user confirms (Yes) */
17
+ onConfirm: () => void;
18
+ /** Callback when user declines (No) */
19
+ onDecline: () => void;
20
+ }
21
+ declare const ConfirmationPrompt: import("svelte").Component<Props, {}, "">;
22
+ type ConfirmationPrompt = ReturnType<typeof ConfirmationPrompt>;
23
+ export default ConfirmationPrompt;
@@ -0,0 +1,223 @@
1
+ <!--
2
+ FormPrompt Component
3
+
4
+ Renders a JSON Schema-based form for form-type interrupts.
5
+ Wraps the existing SchemaForm component for consistent form handling.
6
+ Shows the submitted form data when resolved.
7
+ Styled with BEM syntax.
8
+ -->
9
+
10
+ <script lang="ts">
11
+ import Icon from '@iconify/svelte';
12
+ import SchemaForm from '../SchemaForm.svelte';
13
+ import type { FormConfig } from '../../types/interrupt.js';
14
+
15
+ /**
16
+ * Component props
17
+ */
18
+ interface Props {
19
+ /** Form configuration from the interrupt */
20
+ config: FormConfig;
21
+ /** Whether this interrupt has been resolved */
22
+ isResolved: boolean;
23
+ /** The resolved form values if resolved */
24
+ resolvedValue?: Record<string, unknown>;
25
+ /** Whether the form is currently submitting */
26
+ isSubmitting: boolean;
27
+ /** Error message if submission failed */
28
+ error?: string;
29
+ /** Callback when user submits form */
30
+ onSubmit: (value: Record<string, unknown>) => void;
31
+ }
32
+
33
+ let { config, isResolved, resolvedValue, isSubmitting, error, onSubmit }: Props = $props();
34
+
35
+ /** Local state for form values */
36
+ let formValues = $state<Record<string, unknown>>(config.defaultValues ?? {});
37
+
38
+ /** Display values - either resolved or current form values */
39
+ const displayValues = $derived(isResolved ? (resolvedValue ?? {}) : formValues);
40
+
41
+ /**
42
+ * Handle form value changes
43
+ */
44
+ function handleChange(values: Record<string, unknown>): void {
45
+ if (isResolved || isSubmitting) return;
46
+ formValues = values;
47
+ }
48
+
49
+ /**
50
+ * Handle form submission
51
+ */
52
+ function handleSave(values: Record<string, unknown>): void {
53
+ if (isResolved || isSubmitting) return;
54
+ onSubmit(values);
55
+ }
56
+
57
+ /**
58
+ * Format resolved value for display
59
+ */
60
+ function formatResolvedValue(value: unknown): string {
61
+ if (value === null || value === undefined) return '—';
62
+ if (typeof value === 'boolean') return value ? 'Yes' : 'No';
63
+ if (typeof value === 'object') return JSON.stringify(value, null, 2);
64
+ return String(value);
65
+ }
66
+ </script>
67
+
68
+ <div
69
+ class="form-prompt"
70
+ class:form-prompt--resolved={isResolved}
71
+ class:form-prompt--submitting={isSubmitting}
72
+ >
73
+ <!-- Message -->
74
+ <p class="form-prompt__message">{config.message}</p>
75
+
76
+ <!-- Error message -->
77
+ {#if error}
78
+ <div class="form-prompt__error">
79
+ <Icon icon="mdi:alert-circle" />
80
+ <span>{error}</span>
81
+ </div>
82
+ {/if}
83
+
84
+ <!-- Form -->
85
+ {#if !isResolved}
86
+ <div class="form-prompt__form-wrapper">
87
+ <SchemaForm
88
+ schema={config.schema}
89
+ values={formValues}
90
+ onChange={handleChange}
91
+ onSave={handleSave}
92
+ showActions={true}
93
+ saveLabel="Submit"
94
+ cancelLabel=""
95
+ loading={isSubmitting}
96
+ disabled={isResolved}
97
+ />
98
+ </div>
99
+ {:else}
100
+ <!-- Resolved state: Show submitted values as read-only -->
101
+ <div class="form-prompt__resolved-values">
102
+ <h4 class="form-prompt__resolved-title">Submitted Values</h4>
103
+ <div class="form-prompt__values-list">
104
+ {#each Object.entries(config.schema.properties ?? {}) as [key, field]}
105
+ {@const value = displayValues[key]}
106
+ {@const fieldTitle = ((field as Record<string, unknown>).title as string) ?? key}
107
+ <div class="form-prompt__value-item">
108
+ <span class="form-prompt__value-label">{fieldTitle}</span>
109
+ <span class="form-prompt__value-content">
110
+ {formatResolvedValue(value)}
111
+ </span>
112
+ </div>
113
+ {/each}
114
+ </div>
115
+ </div>
116
+ {/if}
117
+
118
+ <!-- Resolved indicator -->
119
+ {#if isResolved}
120
+ <div class="form-prompt__resolved-badge">
121
+ <Icon icon="mdi:check-circle" />
122
+ <span>Response submitted</span>
123
+ </div>
124
+ {/if}
125
+ </div>
126
+
127
+ <style>
128
+ /* Uses design tokens from base.css: --flowdrop-interrupt-*, --color-ref-* */
129
+ .form-prompt {
130
+ display: flex;
131
+ flex-direction: column;
132
+ gap: 0.75rem;
133
+ }
134
+
135
+ .form-prompt--resolved {
136
+ opacity: 0.85;
137
+ }
138
+
139
+ .form-prompt--submitting {
140
+ pointer-events: none;
141
+ }
142
+
143
+ .form-prompt__message {
144
+ margin: 0;
145
+ font-size: 0.9375rem;
146
+ line-height: 1.5;
147
+ color: var(--color-ref-gray-800, #1f2937);
148
+ }
149
+
150
+ .form-prompt__error {
151
+ display: flex;
152
+ align-items: center;
153
+ gap: 0.375rem;
154
+ padding: 0.5rem 0.75rem;
155
+ background-color: var(--color-ref-red-50, #fef2f2);
156
+ border-radius: 0.375rem;
157
+ color: var(--color-ref-red-600, #dc2626);
158
+ font-size: 0.8125rem;
159
+ }
160
+
161
+ .form-prompt__form-wrapper {
162
+ background-color: var(--color-ref-gray-50, #f9fafb);
163
+ border: 1px solid var(--color-ref-gray-200, #e5e7eb);
164
+ border-radius: 0.5rem;
165
+ padding: 1rem;
166
+ }
167
+
168
+ /* Resolved values - neutral blue theme */
169
+ .form-prompt__resolved-values {
170
+ background-color: var(--color-ref-blue-50, #eff6ff);
171
+ border: 1px solid var(--flowdrop-interrupt-completed-border);
172
+ border-radius: 0.5rem;
173
+ padding: 1rem;
174
+ }
175
+
176
+ .form-prompt__resolved-title {
177
+ margin: 0 0 0.75rem 0;
178
+ font-size: 0.8125rem;
179
+ font-weight: 600;
180
+ color: var(--flowdrop-interrupt-badge-completed-text);
181
+ text-transform: uppercase;
182
+ letter-spacing: 0.05em;
183
+ }
184
+
185
+ .form-prompt__values-list {
186
+ display: flex;
187
+ flex-direction: column;
188
+ gap: 0.5rem;
189
+ }
190
+
191
+ .form-prompt__value-item {
192
+ display: flex;
193
+ flex-direction: column;
194
+ gap: 0.125rem;
195
+ }
196
+
197
+ .form-prompt__value-label {
198
+ font-size: 0.75rem;
199
+ font-weight: 500;
200
+ color: var(--color-ref-gray-500, #6b7280);
201
+ }
202
+
203
+ .form-prompt__value-content {
204
+ font-size: 0.875rem;
205
+ color: var(--color-ref-gray-800, #1f2937);
206
+ word-break: break-word;
207
+ white-space: pre-wrap;
208
+ }
209
+
210
+ /* Resolved badge - neutral blue theme */
211
+ .form-prompt__resolved-badge {
212
+ display: inline-flex;
213
+ align-items: center;
214
+ gap: 0.375rem;
215
+ padding: 0.375rem 0.75rem;
216
+ background-color: var(--flowdrop-interrupt-badge-completed-bg);
217
+ border-radius: 9999px;
218
+ color: var(--flowdrop-interrupt-badge-completed-text);
219
+ font-size: 0.75rem;
220
+ font-weight: 500;
221
+ align-self: flex-start;
222
+ }
223
+ </style>
@@ -0,0 +1,21 @@
1
+ import type { FormConfig } from '../../types/interrupt.js';
2
+ /**
3
+ * Component props
4
+ */
5
+ interface Props {
6
+ /** Form configuration from the interrupt */
7
+ config: FormConfig;
8
+ /** Whether this interrupt has been resolved */
9
+ isResolved: boolean;
10
+ /** The resolved form values if resolved */
11
+ resolvedValue?: Record<string, unknown>;
12
+ /** Whether the form is currently submitting */
13
+ isSubmitting: boolean;
14
+ /** Error message if submission failed */
15
+ error?: string;
16
+ /** Callback when user submits form */
17
+ onSubmit: (value: Record<string, unknown>) => void;
18
+ }
19
+ declare const FormPrompt: import("svelte").Component<Props, {}, "">;
20
+ type FormPrompt = ReturnType<typeof FormPrompt>;
21
+ export default FormPrompt;