@flowdrop/flowdrop 1.13.0 → 1.15.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 (51) hide show
  1. package/README.md +5 -0
  2. package/dist/components/ConfigForm.svelte +41 -21
  3. package/dist/components/ConfigPanel.svelte +7 -1
  4. package/dist/components/NodeSwapPicker.svelte +5 -1
  5. package/dist/components/PipelineStatus.svelte +11 -2
  6. package/dist/components/SchemaForm.svelte +28 -16
  7. package/dist/components/SettingsPanel.svelte +5 -1
  8. package/dist/components/WorkflowEditor.svelte +5 -1
  9. package/dist/components/chat/AIChatPanel.svelte +1 -5
  10. package/dist/components/form/FormAutocomplete.svelte +23 -12
  11. package/dist/components/interrupt/ChoicePrompt.svelte +5 -1
  12. package/dist/components/interrupt/InterruptBubble.svelte +4 -5
  13. package/dist/components/nodes/AtomNode.svelte +280 -0
  14. package/dist/components/nodes/AtomNode.svelte.d.ts +26 -0
  15. package/dist/components/playground/ChatBubble.svelte +6 -8
  16. package/dist/components/playground/ChatInput.svelte +11 -5
  17. package/dist/components/playground/ControlPanel.svelte +42 -29
  18. package/dist/components/playground/ExecutionConsole.svelte +5 -1
  19. package/dist/components/playground/ExecutionConsole.svelte.d.ts +2 -0
  20. package/dist/components/playground/ExecutionList.svelte +7 -2
  21. package/dist/components/playground/LogRow.svelte +2 -1
  22. package/dist/components/playground/MessageBubble.svelte +1 -4
  23. package/dist/components/playground/MessageCard.svelte +2 -1
  24. package/dist/components/playground/MessageMarkdown.svelte +15 -5
  25. package/dist/components/playground/MessageNotice.svelte +2 -1
  26. package/dist/components/playground/MessageStream.svelte +138 -17
  27. package/dist/components/playground/MessageStream.svelte.d.ts +5 -0
  28. package/dist/components/playground/MessageTagChip.svelte +24 -6
  29. package/dist/components/playground/PipelineKanbanView.svelte +40 -11
  30. package/dist/components/playground/PipelinePanel.svelte +5 -1
  31. package/dist/components/playground/PipelineTableView.svelte +20 -6
  32. package/dist/components/playground/Playground.svelte +94 -27
  33. package/dist/components/playground/PlaygroundStudio.svelte +21 -7
  34. package/dist/components/playground/pipelineViewUtils.svelte.js +11 -4
  35. package/dist/helpers/proximityConnect.d.ts +4 -1
  36. package/dist/helpers/proximityConnect.js +17 -1
  37. package/dist/openapi/v1/openapi.yaml +6466 -0
  38. package/dist/playground/mount.js +2 -2
  39. package/dist/registry/builtinNodes.d.ts +1 -1
  40. package/dist/registry/builtinNodes.js +13 -0
  41. package/dist/schemas/v1/workflow.schema.json +86 -3
  42. package/dist/services/playgroundService.d.ts +23 -4
  43. package/dist/services/playgroundService.js +22 -9
  44. package/dist/stores/playgroundStore.svelte.d.ts +29 -2
  45. package/dist/stores/playgroundStore.svelte.js +120 -35
  46. package/dist/types/index.d.ts +38 -3
  47. package/dist/types/playground.d.ts +36 -2
  48. package/dist/utils/formMerge.d.ts +36 -0
  49. package/dist/utils/formMerge.js +70 -0
  50. package/dist/utils/nodeTypes.js +1 -0
  51. package/package.json +7 -1
@@ -202,7 +202,7 @@ export declare function dynamicPortToNodePort(port: DynamicPort, portType: 'inpu
202
202
  * Built-in node types for explicit component rendering.
203
203
  * These are the node types that ship with FlowDrop.
204
204
  */
205
- export type BuiltinNodeType = 'note' | 'simple' | 'square' | 'tool' | 'gateway' | 'terminal' | 'default';
205
+ export type BuiltinNodeType = 'note' | 'simple' | 'square' | 'atom' | 'tool' | 'gateway' | 'terminal' | 'default';
206
206
  /**
207
207
  * Node type for component rendering.
208
208
  * Includes built-in types and allows custom registered types.
@@ -306,8 +306,13 @@ export interface AutocompleteConfig {
306
306
  * If the "account" field currently holds "my-jira", the URL becomes:
307
307
  * /api/jira/issue-types?account=my-jira&q=...
308
308
  *
309
- * When any dependency field changes, the autocomplete clears its
310
- * current value and invalidates the suggestion cache.
309
+ * When a dependency field changes, the component invalidates its cached
310
+ * suggestions and aborts any in-flight fetch. The dependent field's own
311
+ * value is cleared by the parent form (`ConfigForm` / `SchemaForm`) on
312
+ * user-driven edits only — undo/redo, programmatic value replacement, and
313
+ * collaborative edits flow in via props and preserve dependent values.
314
+ * Standalone consumers of `FormAutocomplete` outside a FlowDrop form
315
+ * therefore need to clear dependents themselves.
311
316
  */
312
317
  params?: Record<string, string>;
313
318
  }
@@ -495,9 +500,39 @@ export interface ConfigEditOptions {
495
500
  * UI-related extension settings for nodes
496
501
  * Used to control visual behavior in the workflow editor
497
502
  */
503
+ /**
504
+ * Display/behavior config for minimalist "atom" nodes (Constant, Cast, …).
505
+ * Lives under `extensions.ui.atom`. The atom renderer reads it to decide what to
506
+ * show, and `getAllPorts` reads `valueTypeKey` to drive the bound output port's
507
+ * dataType from config so connection validation stays correct.
508
+ */
509
+ export interface AtomUIConfig {
510
+ /** Config key whose value becomes the node body. Falls back to `data.label`. */
511
+ valueKey?: string;
512
+ /**
513
+ * Config key holding the selected value's type (a port dataType id).
514
+ * The bound output port adopts this dataType.
515
+ */
516
+ valueTypeKey?: string;
517
+ /** Output port id driven by `valueTypeKey`. Defaults to the first output port. */
518
+ outputPortId?: string;
519
+ /** Body shape. `'pill'` (default) is fully rounded; `'rectangle'` is lightly rounded. */
520
+ shape?: 'pill' | 'rectangle';
521
+ /**
522
+ * Dimmed affordance rendered before the body (e.g. `'→ '` to mark a transform).
523
+ * Stays visible while the body value ellipsizes. Hidden in the empty state.
524
+ */
525
+ prefix?: string;
526
+ /** Text shown (dimmed) when the resolved body value is empty/unset. */
527
+ placeholder?: string;
528
+ /** Max body width in px before the label ellipsizes. */
529
+ maxWidth?: number;
530
+ }
498
531
  export interface NodeUIExtensions {
499
532
  /** Show/hide unconnected handles (ports) to reduce visual noise */
500
533
  hideUnconnectedHandles?: boolean;
534
+ /** Display/behavior config for minimalist atom nodes (Constant, Cast, …) */
535
+ atom?: AtomUIConfig;
501
536
  /**
502
537
  * Visual-only port display order (no effect on execution).
503
538
  * Arrays of port IDs in the desired render order.
@@ -62,6 +62,14 @@ export interface PlaygroundExecution {
62
62
  id: string;
63
63
  startedAt: string;
64
64
  status: 'running' | 'completed' | 'failed';
65
+ /**
66
+ * Client-derived flag: true when this run is a nested sub-flow rather than a
67
+ * main pipeline run. Inferred from its messages' `parentPipelineId` (with a
68
+ * `hierarchy` depth ≥ 2 fallback for legacy runs predating that field). Used
69
+ * to keep the sidebar on the main pipeline and hide sub-flows from the
70
+ * run-switcher. Not part of the wire contract — the server never sets this.
71
+ */
72
+ isSubflow?: boolean;
65
73
  }
66
74
  /**
67
75
  * Playground session representing a test conversation
@@ -94,7 +102,12 @@ export interface PlaygroundSession {
94
102
  createdAt: string;
95
103
  /** Last activity timestamp (ISO 8601) */
96
104
  updatedAt: string;
97
- /** Pipeline executions triggered within this session, ordered oldest-first */
105
+ /**
106
+ * Main pipeline runs triggered within this session, ordered oldest-first.
107
+ * Sub-flow (nested) runs are excluded — they're surfaced only on individual
108
+ * messages via `parentPipelineId`. The run-switcher relies on this being
109
+ * main-runs-only; runs added from messages are classified client-side.
110
+ */
98
111
  executions?: PlaygroundExecution[];
99
112
  /** Custom session metadata */
100
113
  metadata?: Record<string, unknown>;
@@ -216,6 +229,19 @@ export interface PlaygroundMessage {
216
229
  parentMessageId?: string;
217
230
  /** Pipeline/execution ID that generated this message */
218
231
  executionId?: string | null;
232
+ /**
233
+ * Execution ID of the parent pipeline when this message came from a nested
234
+ * sub-flow; `null`/absent for top-level (main pipeline) messages. Authoritative
235
+ * nesting signal (unlike the display-only `hierarchy`) — used to keep the main
236
+ * pipeline in focus and hide sub-flow runs from the run-switcher.
237
+ */
238
+ parentPipelineId?: string | null;
239
+ /**
240
+ * Execution ID of the top-level pipeline this message ultimately belongs to.
241
+ * Equals `executionId` for main-pipeline messages; for sub-flow messages it
242
+ * points to the main run that triggered the sub-flow.
243
+ */
244
+ rootPipelineId?: string | null;
219
245
  /** Associated node ID (for log/assistant messages) */
220
246
  nodeId?: string | null;
221
247
  /**
@@ -301,6 +327,12 @@ export interface PlaygroundConfig {
301
327
  pollingInterval?: number;
302
328
  /** Maximum number of messages to display (default: 500) */
303
329
  maxMessages?: number;
330
+ /**
331
+ * Number of messages to fetch per page (default: 50).
332
+ * The initial load fetches the most recent page; scrolling up loads
333
+ * older pages of this size on demand.
334
+ */
335
+ messagePageSize?: number;
304
336
  /** Auto-scroll to bottom on new messages (default: true) */
305
337
  autoScroll?: boolean;
306
338
  /** Show timestamps on messages (default: true) */
@@ -433,8 +465,10 @@ export type PlaygroundMessageResponse = PlaygroundApiResponse<PlaygroundMessage>
433
465
  * Type alias for messages list response with polling metadata
434
466
  */
435
467
  export interface PlaygroundMessagesApiResponse extends PlaygroundApiResponse<PlaygroundMessage[]> {
436
- /** Whether there are more messages to fetch */
468
+ /** Whether more recent messages remain after this page (forward pagination via `since`) */
437
469
  hasMore?: boolean;
470
+ /** Whether older messages exist before the first message in this page (backward pagination via `latest`/`before`) */
471
+ hasOlder?: boolean;
438
472
  /** Current session status */
439
473
  sessionStatus?: PlaygroundSessionStatus;
440
474
  }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Form value merge — shared by `SchemaForm` and `ConfigForm`.
3
+ *
4
+ * Produces the view of form values that children read via context. Precedence
5
+ * per key:
6
+ *
7
+ * 1. `key in edits` → use the user's local edit
8
+ * 2. `source[key] !== undefined` → use the prop value (including null/0/false/'')
9
+ * 3. otherwise → use the schema field's `default`
10
+ *
11
+ * Keeping this separate from the host components means the test pins the same
12
+ * function the components run, not a parallel implementation.
13
+ */
14
+ export declare function mergeWithDefaults(schema: {
15
+ properties?: Record<string, unknown>;
16
+ } | undefined, source: Record<string, unknown>, edits: Record<string, unknown>): Record<string, unknown>;
17
+ /**
18
+ * Compute the cascade-clear set when a single field changes — shared by
19
+ * `SchemaForm` and `ConfigForm`.
20
+ *
21
+ * When `changedKey` changes, any property whose `autocomplete.params` references
22
+ * `changedKey` (directly or transitively) should have its value cleared: the
23
+ * old dependent value was computed against the old parent value and is now
24
+ * stale.
25
+ *
26
+ * Returns a map of `{ dependentKey -> clearValue }` to apply on top of the
27
+ * caller's edits buffer. Single-value autocompletes clear to `''`; ones with
28
+ * `multiple: true` clear to `[]`.
29
+ *
30
+ * This logic lives in the parent form (not in `FormAutocomplete`) so it only
31
+ * runs on user-driven changes via `handleFieldChange`, not on undo/redo,
32
+ * programmatic resets, or collaborative edits (#33).
33
+ */
34
+ export declare function cascadeClearAutocompleteDependents(schema: {
35
+ properties?: Record<string, unknown>;
36
+ } | undefined, changedKey: string): Record<string, unknown>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Form value merge — shared by `SchemaForm` and `ConfigForm`.
3
+ *
4
+ * Produces the view of form values that children read via context. Precedence
5
+ * per key:
6
+ *
7
+ * 1. `key in edits` → use the user's local edit
8
+ * 2. `source[key] !== undefined` → use the prop value (including null/0/false/'')
9
+ * 3. otherwise → use the schema field's `default`
10
+ *
11
+ * Keeping this separate from the host components means the test pins the same
12
+ * function the components run, not a parallel implementation.
13
+ */
14
+ export function mergeWithDefaults(schema, source, edits) {
15
+ if (!schema?.properties)
16
+ return {};
17
+ const merged = {};
18
+ for (const [key, field] of Object.entries(schema.properties)) {
19
+ if (key in edits) {
20
+ merged[key] = edits[key];
21
+ }
22
+ else {
23
+ const fieldConfig = field;
24
+ merged[key] = source[key] !== undefined ? source[key] : fieldConfig.default;
25
+ }
26
+ }
27
+ return merged;
28
+ }
29
+ /**
30
+ * Compute the cascade-clear set when a single field changes — shared by
31
+ * `SchemaForm` and `ConfigForm`.
32
+ *
33
+ * When `changedKey` changes, any property whose `autocomplete.params` references
34
+ * `changedKey` (directly or transitively) should have its value cleared: the
35
+ * old dependent value was computed against the old parent value and is now
36
+ * stale.
37
+ *
38
+ * Returns a map of `{ dependentKey -> clearValue }` to apply on top of the
39
+ * caller's edits buffer. Single-value autocompletes clear to `''`; ones with
40
+ * `multiple: true` clear to `[]`.
41
+ *
42
+ * This logic lives in the parent form (not in `FormAutocomplete`) so it only
43
+ * runs on user-driven changes via `handleFieldChange`, not on undo/redo,
44
+ * programmatic resets, or collaborative edits (#33).
45
+ */
46
+ export function cascadeClearAutocompleteDependents(schema, changedKey) {
47
+ if (!schema?.properties)
48
+ return {};
49
+ const cleared = new Set([changedKey]);
50
+ const result = {};
51
+ let added = true;
52
+ while (added) {
53
+ added = false;
54
+ for (const [depKey, depField] of Object.entries(schema.properties)) {
55
+ if (cleared.has(depKey))
56
+ continue;
57
+ const field = depField;
58
+ const params = field.autocomplete?.params;
59
+ if (!params)
60
+ continue;
61
+ const dependsOnCleared = Object.values(params).some((fieldName) => cleared.has(fieldName));
62
+ if (dependsOnCleared) {
63
+ result[depKey] = field.autocomplete?.multiple ? [] : '';
64
+ cleared.add(depKey);
65
+ added = true;
66
+ }
67
+ }
68
+ }
69
+ return result;
70
+ }
@@ -18,6 +18,7 @@ const TYPE_DISPLAY_NAMES = {
18
18
  note: 'Note (sticky note style)',
19
19
  simple: 'Simple (compact layout)',
20
20
  square: 'Square (geometric layout)',
21
+ atom: 'Atom (minimal value/transform)',
21
22
  tool: 'Tool (specialized for agent tools)',
22
23
  gateway: 'Gateway (branching control flow)',
23
24
  terminal: 'Terminal (start/end/exit)',
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A drop-in visual workflow editor for any web application. You own the backend. You own the data. You own the orchestration.",
4
4
  "license": "MIT",
5
5
  "private": false,
6
- "version": "1.13.0",
6
+ "version": "1.15.0",
7
7
  "author": "Shibin Das (D34dMan)",
8
8
  "bugs": {
9
9
  "url": "https://github.com/flowdrop-io/flowdrop/issues"
@@ -125,6 +125,12 @@
125
125
  },
126
126
  "./schema/v1": {
127
127
  "default": "./dist/schemas/v1/workflow.schema.json"
128
+ },
129
+ "./openapi": {
130
+ "default": "./dist/openapi/v1/openapi.yaml"
131
+ },
132
+ "./openapi/v1": {
133
+ "default": "./dist/openapi/v1/openapi.yaml"
128
134
  }
129
135
  },
130
136
  "peerDependencies": {