@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.
- package/dist/api/enhanced-client.d.ts +29 -16
- package/dist/api/enhanced-client.js +0 -14
- package/dist/components/Navbar.svelte +1 -10
- package/dist/components/Navbar.svelte.d.ts +1 -9
- package/dist/components/PipelineStatus.svelte +9 -12
- package/dist/components/WorkflowEditor.svelte +3 -0
- package/dist/components/interrupt/ChoicePrompt.svelte +24 -5
- package/dist/components/interrupt/ConfirmationPrompt.svelte +5 -0
- package/dist/components/interrupt/InterruptBubble.svelte +12 -0
- package/dist/components/interrupt/ReviewPrompt.svelte +20 -0
- package/dist/components/interrupt/TextInputPrompt.svelte +5 -0
- package/dist/components/nodes/GatewayNode.svelte +2 -6
- package/dist/components/nodes/WorkflowNode.svelte +2 -6
- package/dist/components/playground/ChatInput.svelte +359 -0
- package/dist/components/playground/ChatInput.svelte.d.ts +14 -0
- package/dist/components/playground/ChatPanel.svelte +100 -724
- package/dist/components/playground/ChatPanel.svelte.d.ts +9 -26
- package/dist/components/playground/ControlPanel.svelte +496 -0
- package/dist/components/playground/ControlPanel.svelte.d.ts +20 -0
- package/dist/components/playground/ExecutionConsole.svelte +163 -0
- package/dist/components/playground/ExecutionConsole.svelte.d.ts +14 -0
- package/dist/components/playground/MessageStream.svelte +283 -0
- package/dist/components/playground/MessageStream.svelte.d.ts +27 -0
- package/dist/components/playground/PipelineKanbanView.svelte +284 -0
- package/dist/components/playground/PipelineKanbanView.svelte.d.ts +11 -0
- package/dist/components/playground/PipelinePanel.svelte +204 -65
- package/dist/components/playground/PipelinePanel.svelte.d.ts +3 -1
- package/dist/components/playground/PipelineTableView.svelte +376 -0
- package/dist/components/playground/PipelineTableView.svelte.d.ts +11 -0
- package/dist/components/playground/Playground.svelte +262 -1200
- package/dist/components/playground/Playground.svelte.d.ts +0 -13
- package/dist/components/playground/PlaygroundApp.svelte +110 -0
- package/dist/components/playground/PlaygroundApp.svelte.d.ts +28 -0
- package/dist/components/playground/PlaygroundStudio.svelte +35 -61
- package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -1
- package/dist/components/playground/pipelineViewUtils.svelte.d.ts +22 -0
- package/dist/components/playground/pipelineViewUtils.svelte.js +77 -0
- package/dist/messages/defaults.d.ts +24 -0
- package/dist/messages/defaults.js +24 -0
- package/dist/playground/index.d.ts +8 -2
- package/dist/playground/index.js +8 -1
- package/dist/playground/mount.d.ts +59 -4
- package/dist/playground/mount.js +102 -9
- package/dist/stores/playgroundStore.svelte.d.ts +6 -0
- package/dist/stores/playgroundStore.svelte.js +21 -1
- package/dist/svelte-app.d.ts +2 -10
- package/dist/types/index.d.ts +28 -2
- package/dist/types/navbar.d.ts +14 -0
- package/dist/types/navbar.js +1 -0
- package/dist/types/playground.d.ts +5 -2
- package/dist/types/playground.js +5 -7
- package/dist/utils/nodeStatus.js +15 -5
- package/package.json +1 -1
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
ChatInput Component
|
|
3
|
+
|
|
4
|
+
The textarea + Run/Send/Stop button. Reusable input primitive shared by
|
|
5
|
+
ChatPanel (conversational) and ControlPanel (orchestration controls).
|
|
6
|
+
|
|
7
|
+
Reads execution state from playgroundStore. Owns its own input string and
|
|
8
|
+
textarea ref; emits sent content via onSendMessage.
|
|
9
|
+
-->
|
|
10
|
+
|
|
11
|
+
<script lang="ts">
|
|
12
|
+
import Icon from '@iconify/svelte';
|
|
13
|
+
import { tick, untrack } from 'svelte';
|
|
14
|
+
import { hasEnableRunFlag } from '../../types/playground.js';
|
|
15
|
+
import {
|
|
16
|
+
getMessages,
|
|
17
|
+
getIsExecuting,
|
|
18
|
+
getCanSendMessage,
|
|
19
|
+
getCurrentSession
|
|
20
|
+
} from '../../stores/playgroundStore.svelte.js';
|
|
21
|
+
import { m } from '../../messages/index.js';
|
|
22
|
+
|
|
23
|
+
interface Props {
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
/** Show the textarea (default: true). When false, only the Run button is shown. */
|
|
26
|
+
showTextarea?: boolean;
|
|
27
|
+
/** Show the Run button when textarea is hidden (default: true) */
|
|
28
|
+
showRunButton?: boolean;
|
|
29
|
+
/** Message sent when Run is clicked with textarea hidden */
|
|
30
|
+
predefinedMessage?: string;
|
|
31
|
+
onSendMessage?: (content: string) => void;
|
|
32
|
+
onStopExecution?: () => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let {
|
|
36
|
+
placeholder,
|
|
37
|
+
showTextarea = true,
|
|
38
|
+
showRunButton = true,
|
|
39
|
+
predefinedMessage,
|
|
40
|
+
onSendMessage,
|
|
41
|
+
onStopExecution
|
|
42
|
+
}: Props = $props();
|
|
43
|
+
|
|
44
|
+
const actions = $derived(m().playground.actions);
|
|
45
|
+
const chat = $derived(m().playground.chat);
|
|
46
|
+
const states = $derived(m().playground.states);
|
|
47
|
+
|
|
48
|
+
const resolvedPlaceholder = $derived(placeholder ?? chat.placeholder);
|
|
49
|
+
const resolvedPredefinedMessage = $derived(predefinedMessage ?? chat.predefinedRun);
|
|
50
|
+
|
|
51
|
+
const noInputsAvailable = $derived(!showTextarea && !showRunButton);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Tracks whether the Run button is enabled. Starts as true; becomes false
|
|
55
|
+
* after Run is clicked; re-enabled when the backend sends a message with
|
|
56
|
+
* enableRun: true metadata.
|
|
57
|
+
*/
|
|
58
|
+
let runEnabled = $state(true);
|
|
59
|
+
|
|
60
|
+
let inputValue = $state('');
|
|
61
|
+
let inputField: HTMLTextAreaElement | undefined;
|
|
62
|
+
|
|
63
|
+
// Count of enableRun messages seen so far — plain let, not $state.
|
|
64
|
+
// Written with untrack to make the bookkeeping intent explicit.
|
|
65
|
+
let seenEnableRunCount = 0;
|
|
66
|
+
|
|
67
|
+
$effect(() => {
|
|
68
|
+
const count = getMessages().filter(m => hasEnableRunFlag(m.metadata)).length;
|
|
69
|
+
if (count > seenEnableRunCount) {
|
|
70
|
+
untrack(() => { seenEnableRunCount = count; });
|
|
71
|
+
runEnabled = true;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
$effect(() => {
|
|
76
|
+
if (getCurrentSession()?.id) {
|
|
77
|
+
untrack(() => { seenEnableRunCount = 0; });
|
|
78
|
+
runEnabled = true;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
let wasExecuting = false;
|
|
83
|
+
|
|
84
|
+
/** Auto-focus input when execution completes */
|
|
85
|
+
$effect(() => {
|
|
86
|
+
const nowExecuting = getIsExecuting();
|
|
87
|
+
if (wasExecuting && !nowExecuting && inputField) {
|
|
88
|
+
tick().then(() => inputField?.focus({ preventScroll: true }));
|
|
89
|
+
}
|
|
90
|
+
untrack(() => { wasExecuting = nowExecuting; });
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
function handleSend(): void {
|
|
94
|
+
const trimmedValue = inputValue.trim();
|
|
95
|
+
if (!trimmedValue || !getCanSendMessage()) return;
|
|
96
|
+
|
|
97
|
+
onSendMessage?.(trimmedValue);
|
|
98
|
+
inputValue = '';
|
|
99
|
+
|
|
100
|
+
if (inputField) {
|
|
101
|
+
inputField.style.height = 'auto';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
tick().then(() => {
|
|
105
|
+
inputField?.focus({ preventScroll: true });
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function handleKeydown(event: KeyboardEvent): void {
|
|
110
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
|
111
|
+
event.preventDefault();
|
|
112
|
+
handleSend();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function handleStop(): void {
|
|
117
|
+
onStopExecution?.();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function handleRun(): void {
|
|
121
|
+
if (getIsExecuting() || !runEnabled) return;
|
|
122
|
+
runEnabled = false;
|
|
123
|
+
onSendMessage?.(resolvedPredefinedMessage);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function handleInput(): void {
|
|
127
|
+
if (inputField) {
|
|
128
|
+
inputField.style.height = 'auto';
|
|
129
|
+
inputField.style.height = `${Math.min(inputField.scrollHeight, 120)}px`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
</script>
|
|
133
|
+
|
|
134
|
+
<div class="chat-input">
|
|
135
|
+
{#if noInputsAvailable}
|
|
136
|
+
<div class="chat-input__no-inputs">
|
|
137
|
+
<Icon icon="mdi:information-outline" />
|
|
138
|
+
<span>{states.viewOnlyHelp}</span>
|
|
139
|
+
</div>
|
|
140
|
+
{:else}
|
|
141
|
+
<div class="chat-input__container" class:chat-input__container--run-only={!showTextarea}>
|
|
142
|
+
{#if showTextarea}
|
|
143
|
+
<div class="chat-input__wrapper">
|
|
144
|
+
<textarea
|
|
145
|
+
bind:this={inputField}
|
|
146
|
+
bind:value={inputValue}
|
|
147
|
+
class="chat-input__textarea"
|
|
148
|
+
placeholder={resolvedPlaceholder}
|
|
149
|
+
rows="1"
|
|
150
|
+
disabled={getIsExecuting() || !getCurrentSession()}
|
|
151
|
+
onkeydown={handleKeydown}
|
|
152
|
+
oninput={handleInput}
|
|
153
|
+
></textarea>
|
|
154
|
+
</div>
|
|
155
|
+
{/if}
|
|
156
|
+
|
|
157
|
+
{#if getIsExecuting()}
|
|
158
|
+
<button
|
|
159
|
+
type="button"
|
|
160
|
+
class="chat-input__stop-btn"
|
|
161
|
+
onclick={handleStop}
|
|
162
|
+
title={actions.stopTitle}
|
|
163
|
+
aria-label={actions.stopTitle}
|
|
164
|
+
>
|
|
165
|
+
<Icon icon="mdi:stop" />
|
|
166
|
+
{actions.stop}
|
|
167
|
+
</button>
|
|
168
|
+
{:else if showTextarea}
|
|
169
|
+
<button
|
|
170
|
+
type="button"
|
|
171
|
+
class="chat-input__send-btn"
|
|
172
|
+
onclick={handleSend}
|
|
173
|
+
disabled={!inputValue.trim() || !getCanSendMessage()}
|
|
174
|
+
title={actions.sendTitle}
|
|
175
|
+
aria-label={actions.sendTitle}
|
|
176
|
+
>
|
|
177
|
+
{actions.send}
|
|
178
|
+
</button>
|
|
179
|
+
{:else if showRunButton}
|
|
180
|
+
{@const runLabel = runEnabled ? actions.runTitle : actions.runWaitingTitle}
|
|
181
|
+
<button
|
|
182
|
+
type="button"
|
|
183
|
+
class="chat-input__run-btn"
|
|
184
|
+
onclick={handleRun}
|
|
185
|
+
disabled={!runEnabled}
|
|
186
|
+
title={runLabel}
|
|
187
|
+
aria-label={runLabel}
|
|
188
|
+
>
|
|
189
|
+
<Icon icon="mdi:play" />
|
|
190
|
+
{actions.run}
|
|
191
|
+
</button>
|
|
192
|
+
{/if}
|
|
193
|
+
</div>
|
|
194
|
+
{/if}
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<style>
|
|
198
|
+
.chat-input {
|
|
199
|
+
flex-shrink: 0;
|
|
200
|
+
padding: var(--fd-space-xl) var(--fd-space-3xl) var(--fd-space-3xl);
|
|
201
|
+
background-color: var(--fd-background);
|
|
202
|
+
border-top: 1px solid var(--fd-border-muted);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.chat-input__container {
|
|
206
|
+
display: flex;
|
|
207
|
+
align-items: flex-end;
|
|
208
|
+
gap: var(--fd-space-md);
|
|
209
|
+
max-width: 760px;
|
|
210
|
+
margin: 0 auto;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.chat-input__container--run-only {
|
|
214
|
+
justify-content: flex-end;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.chat-input__wrapper {
|
|
218
|
+
flex: 1;
|
|
219
|
+
display: flex;
|
|
220
|
+
align-items: flex-end;
|
|
221
|
+
background-color: var(--fd-background);
|
|
222
|
+
border: 1px solid var(--fd-border);
|
|
223
|
+
border-radius: var(--fd-radius-xl);
|
|
224
|
+
padding: var(--fd-space-sm) var(--fd-space-md);
|
|
225
|
+
transition:
|
|
226
|
+
border-color var(--fd-transition-fast),
|
|
227
|
+
box-shadow var(--fd-transition-fast);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.chat-input__wrapper:focus-within {
|
|
231
|
+
border-color: var(--fd-primary);
|
|
232
|
+
box-shadow: 0 0 0 3px var(--fd-primary-muted);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.chat-input__textarea {
|
|
236
|
+
flex: 1;
|
|
237
|
+
border: none;
|
|
238
|
+
outline: none;
|
|
239
|
+
resize: none;
|
|
240
|
+
font-family: inherit;
|
|
241
|
+
font-size: var(--fd-text-base);
|
|
242
|
+
line-height: var(--fd-leading-normal);
|
|
243
|
+
max-height: 120px;
|
|
244
|
+
background: transparent;
|
|
245
|
+
color: var(--fd-foreground);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.chat-input__textarea::placeholder {
|
|
249
|
+
color: var(--fd-muted-foreground);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.chat-input__textarea:disabled {
|
|
253
|
+
cursor: not-allowed;
|
|
254
|
+
opacity: 0.6;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.chat-input__send-btn {
|
|
258
|
+
display: flex;
|
|
259
|
+
align-items: center;
|
|
260
|
+
justify-content: center;
|
|
261
|
+
padding: var(--fd-space-sm) var(--fd-space-2xl);
|
|
262
|
+
border: none;
|
|
263
|
+
border-radius: var(--fd-radius-lg);
|
|
264
|
+
background-color: var(--fd-foreground);
|
|
265
|
+
color: var(--fd-background);
|
|
266
|
+
font-size: var(--fd-text-sm);
|
|
267
|
+
font-weight: 500;
|
|
268
|
+
cursor: pointer;
|
|
269
|
+
transition: all var(--fd-transition-fast);
|
|
270
|
+
flex-shrink: 0;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.chat-input__send-btn:hover:not(:disabled) {
|
|
274
|
+
opacity: 0.85;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.chat-input__send-btn:disabled {
|
|
278
|
+
background-color: var(--fd-foreground);
|
|
279
|
+
color: var(--fd-background);
|
|
280
|
+
opacity: 0.3;
|
|
281
|
+
cursor: not-allowed;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.chat-input__stop-btn {
|
|
285
|
+
display: flex;
|
|
286
|
+
align-items: center;
|
|
287
|
+
gap: var(--fd-space-3xs);
|
|
288
|
+
padding: var(--fd-space-sm) var(--fd-space-xl);
|
|
289
|
+
border: none;
|
|
290
|
+
border-radius: var(--fd-radius-lg);
|
|
291
|
+
background-color: var(--fd-error);
|
|
292
|
+
color: var(--fd-error-foreground);
|
|
293
|
+
font-size: var(--fd-text-sm);
|
|
294
|
+
font-weight: 500;
|
|
295
|
+
cursor: pointer;
|
|
296
|
+
transition: background-color var(--fd-transition-fast);
|
|
297
|
+
flex-shrink: 0;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.chat-input__stop-btn:hover {
|
|
301
|
+
background-color: var(--fd-error-hover);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.chat-input__run-btn {
|
|
305
|
+
display: flex;
|
|
306
|
+
align-items: center;
|
|
307
|
+
gap: var(--fd-space-3xs);
|
|
308
|
+
padding: var(--fd-space-sm) var(--fd-space-2xl);
|
|
309
|
+
border: none;
|
|
310
|
+
border-radius: var(--fd-radius-lg);
|
|
311
|
+
background-color: var(--fd-success);
|
|
312
|
+
color: var(--fd-success-foreground);
|
|
313
|
+
font-size: var(--fd-text-sm);
|
|
314
|
+
font-weight: 500;
|
|
315
|
+
cursor: pointer;
|
|
316
|
+
transition: all var(--fd-transition-fast);
|
|
317
|
+
flex-shrink: 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.chat-input__run-btn:hover:not(:disabled) {
|
|
321
|
+
background-color: var(--fd-success-hover);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.chat-input__run-btn:disabled {
|
|
325
|
+
background-color: var(--fd-border);
|
|
326
|
+
color: var(--fd-muted-foreground);
|
|
327
|
+
cursor: not-allowed;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.chat-input__no-inputs {
|
|
331
|
+
display: flex;
|
|
332
|
+
align-items: center;
|
|
333
|
+
justify-content: center;
|
|
334
|
+
gap: var(--fd-space-xs);
|
|
335
|
+
padding: var(--fd-space-md) var(--fd-space-xl);
|
|
336
|
+
background-color: var(--fd-muted);
|
|
337
|
+
border-radius: var(--fd-radius-lg);
|
|
338
|
+
color: var(--fd-muted-foreground);
|
|
339
|
+
font-size: var(--fd-text-sm);
|
|
340
|
+
max-width: 760px;
|
|
341
|
+
margin: 0 auto;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
@media (max-width: 640px) {
|
|
345
|
+
.chat-input {
|
|
346
|
+
padding: var(--fd-space-md) var(--fd-space-xl) var(--fd-space-xl);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.chat-input__container {
|
|
350
|
+
gap: var(--fd-space-xs);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.chat-input__send-btn,
|
|
354
|
+
.chat-input__stop-btn,
|
|
355
|
+
.chat-input__run-btn {
|
|
356
|
+
padding: var(--fd-space-xs) var(--fd-space-xl);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
placeholder?: string;
|
|
3
|
+
/** Show the textarea (default: true). When false, only the Run button is shown. */
|
|
4
|
+
showTextarea?: boolean;
|
|
5
|
+
/** Show the Run button when textarea is hidden (default: true) */
|
|
6
|
+
showRunButton?: boolean;
|
|
7
|
+
/** Message sent when Run is clicked with textarea hidden */
|
|
8
|
+
predefinedMessage?: string;
|
|
9
|
+
onSendMessage?: (content: string) => void;
|
|
10
|
+
onStopExecution?: () => void;
|
|
11
|
+
}
|
|
12
|
+
declare const ChatInput: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
type ChatInput = ReturnType<typeof ChatInput>;
|
|
14
|
+
export default ChatInput;
|