@flowdrop/flowdrop 1.14.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.
@@ -2522,9 +2522,11 @@ components:
2522
2522
  - note
2523
2523
  - simple
2524
2524
  - square
2525
+ - atom
2525
2526
  - tool
2526
2527
  - gateway
2527
2528
  - terminal
2529
+ - idea
2528
2530
  - default
2529
2531
  description: |
2530
2532
  Visual rendering type for the node.
@@ -2533,9 +2535,11 @@ components:
2533
2535
  - `note` - Sticky note with markdown support
2534
2536
  - `simple` - Compact layout with header and description
2535
2537
  - `square` - Minimal square node with centered icon
2538
+ - `atom` - Minimal label-only pill/rectangle for value/transform nodes (uses extensions.ui.atom)
2536
2539
  - `tool` - Specialized node for agent tools
2537
2540
  - `gateway` - Branching control flow with dynamic branches (uses config.branches)
2538
2541
  - `terminal` - Circular node for workflow start/end/exit points
2542
+ - `idea` - Conceptual idea node for BPMN-like flow diagrams
2539
2543
  - `default` - Full-featured workflow node with dynamic port support
2540
2544
 
2541
2545
  ## Dynamic Port Support
@@ -3047,6 +3051,122 @@ components:
3047
3051
  required:
3048
3052
  - type
3049
3053
  - properties
3054
+ TemplateVariablesConfig:
3055
+ type: object
3056
+ description: |
3057
+ Configuration for template variable autocomplete in template fields.
3058
+
3059
+ ## Overview
3060
+
3061
+ When a template field is connected to upstream nodes that have output schemas,
3062
+ FlowDrop automatically derives available variables for autocomplete. This config
3063
+ controls which ports provide variables and how they are presented.
3064
+
3065
+ ## Variable Derivation
3066
+
3067
+ Variables are derived from connected upstream nodes' **output port schemas**.
3068
+ When an output port has a `schema` property with `properties`, those properties
3069
+ become available as template variables.
3070
+
3071
+ ### Default Behavior (includePortName: false)
3072
+
3073
+ Schema properties are **unpacked as top-level variables**:
3074
+
3075
+ ```
3076
+ HTTP Request node (output port "json" with schema):
3077
+ schema.properties: { user: {...}, orders: {...} }
3078
+
3079
+ Template variables: {{ user }}, {{ orders }}
3080
+ ```
3081
+
3082
+ ### With includePortName: true
3083
+
3084
+ Variables are **prefixed with the port name**:
3085
+
3086
+ ```
3087
+ Same schema as above:
3088
+
3089
+ Template variables: {{ data.user }}, {{ data.orders }}
3090
+ ```
3091
+
3092
+ ## Nested Property Access
3093
+
3094
+ The autocomplete supports drilling into nested structures:
3095
+
3096
+ - **Dot notation**: `{{ user.address.city }}`
3097
+ - **Array indices**: `{{ orders[0].product_name }}`
3098
+ - **Combined**: `{{ user.orders[0].items[1].price }}`
3099
+ properties:
3100
+ ports:
3101
+ type: array
3102
+ items:
3103
+ type: string
3104
+ description: |
3105
+ Specifies which input port IDs should provide variables for autocomplete.
3106
+ Only connections to these ports will contribute variables.
3107
+
3108
+ **Behavior:**
3109
+ - If not specified: All input ports with connections are used
3110
+ - If empty array `[]`: No variables derived from ports (use with `schema` for static variables)
3111
+ - If specified: Only the listed ports contribute variables
3112
+
3113
+ **Example:** A node with inputs "data", "context", and "trigger":
3114
+ - `ports: ["data"]` - Only variables from the "data" connection
3115
+ - `ports: ["data", "context"]` - Variables from both connections
3116
+ - Not specified - Variables from all non-trigger connections
3117
+ example:
3118
+ - data
3119
+ - context
3120
+ schema:
3121
+ $ref: '#/components/schemas/VariableSchema'
3122
+ description: |
3123
+ Pre-defined variable schema to provide static variables or override derived ones.
3124
+
3125
+ When both `ports` and `schema` are specified, variables are **merged**:
3126
+ - Variables from connected ports are computed first
3127
+ - Static `schema` variables are added/override existing ones
3128
+
3129
+ **Use cases:**
3130
+ - Provide variables that don't come from connections
3131
+ - Override labels or descriptions for derived variables
3132
+ - Add custom variables for specific use cases
3133
+ includePortName:
3134
+ type: boolean
3135
+ default: false
3136
+ description: |
3137
+ Controls how variables are named when derived from port schemas.
3138
+
3139
+ **When false (default):**
3140
+ Schema properties become top-level variables directly.
3141
+ A port with schema `{ user: {...}, orders: {...} }` produces:
3142
+ - `{{ user }}`
3143
+ - `{{ orders }}`
3144
+
3145
+ **When true:**
3146
+ Variables are prefixed with the input port name.
3147
+ Same schema connected to input port "data" produces:
3148
+ - `{{ data.user }}`
3149
+ - `{{ data.orders }}`
3150
+
3151
+ **When to use true:**
3152
+ - Multiple input ports with potentially overlapping property names
3153
+ - You want to be explicit about data sources in templates
3154
+ - Backward compatibility with existing templates
3155
+ showHints:
3156
+ type: boolean
3157
+ default: true
3158
+ description: |
3159
+ Whether to display clickable variable hints below the editor.
3160
+
3161
+ When enabled, shows a row of buttons for top-level variables that users
3162
+ can click to insert `{{ variableName }}` at the cursor position.
3163
+
3164
+ Disable if the variable list is too long or not useful.
3165
+ example:
3166
+ ports:
3167
+ - data
3168
+ showHints: true
3169
+ includePortName: false
3050
3170
  NodePort:
3051
3171
  type: object
3052
3172
  description: |
@@ -3141,6 +3261,51 @@ components:
3141
3261
  - name
3142
3262
  - type
3143
3263
  - dataType
3264
+ VariableSchema:
3265
+ type: object
3266
+ description: |
3267
+ Schema passed to template editor for autocomplete functionality.
3268
+ Contains all available variables derived from connected upstream nodes.
3269
+
3270
+ This is computed by the frontend based on:
3271
+ 1. Finding all edges that connect to the current node's input ports
3272
+ 2. Getting the output schemas from the source nodes' output ports
3273
+ 3. Building a hierarchical variable structure for autocomplete
3274
+ properties:
3275
+ variables:
3276
+ type: object
3277
+ additionalProperties:
3278
+ $ref: '#/components/schemas/TemplateVariable'
3279
+ description: Map of available variables keyed by variable name
3280
+ required:
3281
+ - variables
3282
+ example:
3283
+ variables:
3284
+ user:
3285
+ name: user
3286
+ type: object
3287
+ label: User Data
3288
+ properties:
3289
+ name:
3290
+ name: name
3291
+ type: string
3292
+ email:
3293
+ name: email
3294
+ type: string
3295
+ items:
3296
+ name: items
3297
+ type: array
3298
+ label: Order Items
3299
+ items:
3300
+ name: item
3301
+ type: object
3302
+ properties:
3303
+ product_name:
3304
+ name: product_name
3305
+ type: string
3306
+ price:
3307
+ name: price
3308
+ type: number
3144
3309
  DynamicPort:
3145
3310
  type: object
3146
3311
  description: |
@@ -3219,6 +3384,59 @@ components:
3219
3384
  description: Route for high priority items
3220
3385
  condition: priority === 'high'
3221
3386
  isDefault: false
3387
+ AtomUIConfig:
3388
+ type: object
3389
+ description: |
3390
+ Display/behaviour settings for minimalist `atom` nodes (e.g. Constant, Cast).
3391
+ Lives under `extensions.ui.atom`. The atom renderer reads these to decide what
3392
+ to show, and `valueTypeKey` drives the bound output port's `dataType` from
3393
+ config so connection validation matches the type the user picked.
3394
+
3395
+ All fields are optional — an empty object renders a label-only pill using the
3396
+ node's `label`.
3397
+ properties:
3398
+ valueKey:
3399
+ type: string
3400
+ description: |
3401
+ Config key whose value becomes the node body text.
3402
+ Falls back to the node `label` when unset or empty.
3403
+ example: value
3404
+ valueTypeKey:
3405
+ type: string
3406
+ description: |
3407
+ Config key holding the selected value's type (a port dataType id).
3408
+ The bound output port adopts this dataType.
3409
+ example: valueType
3410
+ outputPortId:
3411
+ type: string
3412
+ description: |
3413
+ Output port id driven by `valueTypeKey`.
3414
+ Defaults to the first output port when unset.
3415
+ example: value
3416
+ shape:
3417
+ type: string
3418
+ enum:
3419
+ - pill
3420
+ - rectangle
3421
+ default: pill
3422
+ description: |
3423
+ Body shape. `pill` (default) is fully rounded; `rectangle` is lightly rounded.
3424
+ example: rectangle
3425
+ prefix:
3426
+ type: string
3427
+ description: |
3428
+ Dimmed affordance rendered before the body (e.g. `"→ "` to mark a transform).
3429
+ Stays visible while the body value ellipsizes. Hidden in the empty state.
3430
+ example: '→ '
3431
+ placeholder:
3432
+ type: string
3433
+ description: Text shown (dimmed) when the resolved body value is empty/unset.
3434
+ example: empty
3435
+ maxWidth:
3436
+ type: integer
3437
+ description: Max body width in px before the label ellipsizes.
3438
+ example: 200
3439
+ additionalProperties: false
3222
3440
  NodeUIExtensions:
3223
3441
  type: object
3224
3442
  description: |
@@ -3238,6 +3456,8 @@ components:
3238
3456
  When true, only ports with active connections are displayed.
3239
3457
  Useful for nodes with many optional ports.
3240
3458
  example: true
3459
+ atom:
3460
+ $ref: '#/components/schemas/AtomUIConfig'
3241
3461
  style:
3242
3462
  type: object
3243
3463
  additionalProperties: true
@@ -3475,10 +3695,12 @@ components:
3475
3695
  - `default`: Standard workflow node with full details
3476
3696
  - `simple`: Compact layout with minimal chrome
3477
3697
  - `square`: Geometric square layout (icon-only)
3698
+ - `atom`: Minimal label-only pill/rectangle (uses extensions.ui.atom)
3478
3699
  - `tool`: Specialized style for agent tools
3479
3700
  - `gateway`: Branching control flow visualization
3480
3701
  - `terminal`: Start/end/exit node styling
3481
3702
  - `note`: Sticky note style for annotations
3703
+ - `idea`: Conceptual idea node for BPMN-like flow diagrams
3482
3704
 
3483
3705
  The node's `metadata.supportedTypes` defines which types are allowed.
3484
3706
  If invalid or missing, falls back to `metadata.type` or "default".
@@ -3486,10 +3708,12 @@ components:
3486
3708
  - default
3487
3709
  - simple
3488
3710
  - square
3711
+ - atom
3489
3712
  - tool
3490
3713
  - gateway
3491
3714
  - terminal
3492
3715
  - note
3716
+ - idea
3493
3717
  example: simple
3494
3718
  dynamicInputs:
3495
3719
  type: array
@@ -5942,167 +6166,6 @@ components:
5942
6166
  name: country
5943
6167
  type: string
5944
6168
  label: Country
5945
- VariableSchema:
5946
- type: object
5947
- description: |
5948
- Schema passed to template editor for autocomplete functionality.
5949
- Contains all available variables derived from connected upstream nodes.
5950
-
5951
- This is computed by the frontend based on:
5952
- 1. Finding all edges that connect to the current node's input ports
5953
- 2. Getting the output schemas from the source nodes' output ports
5954
- 3. Building a hierarchical variable structure for autocomplete
5955
- properties:
5956
- variables:
5957
- type: object
5958
- additionalProperties:
5959
- $ref: '#/components/schemas/TemplateVariable'
5960
- description: Map of available variables keyed by variable name
5961
- required:
5962
- - variables
5963
- example:
5964
- variables:
5965
- user:
5966
- name: user
5967
- type: object
5968
- label: User Data
5969
- properties:
5970
- name:
5971
- name: name
5972
- type: string
5973
- email:
5974
- name: email
5975
- type: string
5976
- items:
5977
- name: items
5978
- type: array
5979
- label: Order Items
5980
- items:
5981
- name: item
5982
- type: object
5983
- properties:
5984
- product_name:
5985
- name: product_name
5986
- type: string
5987
- price:
5988
- name: price
5989
- type: number
5990
- TemplateVariablesConfig:
5991
- type: object
5992
- description: |
5993
- Configuration for template variable autocomplete in template fields.
5994
-
5995
- ## Overview
5996
-
5997
- When a template field is connected to upstream nodes that have output schemas,
5998
- FlowDrop automatically derives available variables for autocomplete. This config
5999
- controls which ports provide variables and how they are presented.
6000
-
6001
- ## Variable Derivation
6002
-
6003
- Variables are derived from connected upstream nodes' **output port schemas**.
6004
- When an output port has a `schema` property with `properties`, those properties
6005
- become available as template variables.
6006
-
6007
- ### Default Behavior (includePortName: false)
6008
-
6009
- Schema properties are **unpacked as top-level variables**:
6010
-
6011
- ```
6012
- HTTP Request node (output port "json" with schema):
6013
- schema.properties: { user: {...}, orders: {...} }
6014
-
6015
- Template variables: {{ user }}, {{ orders }}
6016
- ```
6017
-
6018
- ### With includePortName: true
6019
-
6020
- Variables are **prefixed with the port name**:
6021
-
6022
- ```
6023
- Same schema as above:
6024
-
6025
- Template variables: {{ data.user }}, {{ data.orders }}
6026
- ```
6027
-
6028
- ## Nested Property Access
6029
-
6030
- The autocomplete supports drilling into nested structures:
6031
-
6032
- - **Dot notation**: `{{ user.address.city }}`
6033
- - **Array indices**: `{{ orders[0].product_name }}`
6034
- - **Combined**: `{{ user.orders[0].items[1].price }}`
6035
- properties:
6036
- ports:
6037
- type: array
6038
- items:
6039
- type: string
6040
- description: |
6041
- Specifies which input port IDs should provide variables for autocomplete.
6042
- Only connections to these ports will contribute variables.
6043
-
6044
- **Behavior:**
6045
- - If not specified: All input ports with connections are used
6046
- - If empty array `[]`: No variables derived from ports (use with `schema` for static variables)
6047
- - If specified: Only the listed ports contribute variables
6048
-
6049
- **Example:** A node with inputs "data", "context", and "trigger":
6050
- - `ports: ["data"]` - Only variables from the "data" connection
6051
- - `ports: ["data", "context"]` - Variables from both connections
6052
- - Not specified - Variables from all non-trigger connections
6053
- example:
6054
- - data
6055
- - context
6056
- schema:
6057
- $ref: '#/components/schemas/VariableSchema'
6058
- description: |
6059
- Pre-defined variable schema to provide static variables or override derived ones.
6060
-
6061
- When both `ports` and `schema` are specified, variables are **merged**:
6062
- - Variables from connected ports are computed first
6063
- - Static `schema` variables are added/override existing ones
6064
-
6065
- **Use cases:**
6066
- - Provide variables that don't come from connections
6067
- - Override labels or descriptions for derived variables
6068
- - Add custom variables for specific use cases
6069
- includePortName:
6070
- type: boolean
6071
- default: false
6072
- description: |
6073
- Controls how variables are named when derived from port schemas.
6074
-
6075
- **When false (default):**
6076
- Schema properties become top-level variables directly.
6077
- A port with schema `{ user: {...}, orders: {...} }` produces:
6078
- - `{{ user }}`
6079
- - `{{ orders }}`
6080
-
6081
- **When true:**
6082
- Variables are prefixed with the input port name.
6083
- Same schema connected to input port "data" produces:
6084
- - `{{ data.user }}`
6085
- - `{{ data.orders }}`
6086
-
6087
- **When to use true:**
6088
- - Multiple input ports with potentially overlapping property names
6089
- - You want to be explicit about data sources in templates
6090
- - Backward compatibility with existing templates
6091
- showHints:
6092
- type: boolean
6093
- default: true
6094
- description: |
6095
- Whether to display clickable variable hints below the editor.
6096
-
6097
- When enabled, shows a row of buttons for top-level variables that users
6098
- can click to insert `{{ variableName }}` at the cursor position.
6099
-
6100
- Disable if the variable list is too long or not useful.
6101
- example:
6102
- ports:
6103
- - data
6104
- showHints: true
6105
- includePortName: false
6106
6169
  KanbanColumnDef:
6107
6170
  type: object
6108
6171
  properties:
@@ -106,10 +106,10 @@ function buildMountedPlayground(svelteApp, workflowId, config, onSessionStatusCh
106
106
  startPolling: () => {
107
107
  const session = getCurrentSession();
108
108
  if (session) {
109
- playgroundService.startPolling(session.id, (response) => applyServerResponse(response), pollingInterval, config.shouldStopPolling, playgroundService.getLastSequenceNumber());
109
+ playgroundService.startPolling(session.id, (response) => applyServerResponse(response, session.id), pollingInterval, config.shouldStopPolling, playgroundService.getLastSequenceNumber());
110
110
  }
111
111
  },
112
- pushMessages: (response) => applyServerResponse(response),
112
+ pushMessages: (response) => applyServerResponse(response, null),
113
113
  reset: () => {
114
114
  playgroundService.stopPolling();
115
115
  playgroundActions.reset();
@@ -70,7 +70,7 @@ export declare function getBuiltinTypes(): string[];
70
70
  * Type for built-in node types.
71
71
  * Use this when you specifically need a built-in type.
72
72
  */
73
- export type BuiltinNodeType = 'workflowNode' | 'simple' | 'square' | 'tool' | 'gateway' | 'note' | 'terminal' | 'idea';
73
+ export type BuiltinNodeType = 'workflowNode' | 'simple' | 'square' | 'atom' | 'tool' | 'gateway' | 'note' | 'terminal' | 'idea';
74
74
  /**
75
75
  * Array of built-in type strings for runtime validation.
76
76
  */
@@ -9,6 +9,7 @@ import { nodeComponentRegistry } from './nodeComponentRegistry.js';
9
9
  import WorkflowNode from '../components/nodes/WorkflowNode.svelte';
10
10
  import SimpleNode from '../components/nodes/SimpleNode.svelte';
11
11
  import SquareNode from '../components/nodes/SquareNode.svelte';
12
+ import AtomNode from '../components/nodes/AtomNode.svelte';
12
13
  import ToolNode from '../components/nodes/ToolNode.svelte';
13
14
  import GatewayNode from '../components/nodes/GatewayNode.svelte';
14
15
  import NotesNode from '../components/nodes/NotesNode.svelte';
@@ -56,6 +57,17 @@ export const BUILTIN_NODE_COMPONENTS = [
56
57
  statusPosition: 'top-right',
57
58
  statusSize: 'sm'
58
59
  },
60
+ {
61
+ type: 'atom',
62
+ displayName: 'Atom (Minimal Value/Transform)',
63
+ description: 'Low-chrome label-only node for constants and inline transforms',
64
+ component: AtomNode,
65
+ icon: 'mdi:circle-small',
66
+ category: 'visual',
67
+ source: FLOWDROP_SOURCE,
68
+ statusPosition: 'top-right',
69
+ statusSize: 'sm'
70
+ },
59
71
  {
60
72
  type: 'tool',
61
73
  displayName: 'Tool (Agent Tool)',
@@ -197,6 +209,7 @@ export const BUILTIN_NODE_TYPES = [
197
209
  'workflowNode',
198
210
  'simple',
199
211
  'square',
212
+ 'atom',
200
213
  'tool',
201
214
  'gateway',
202
215
  'note',
@@ -51,6 +51,46 @@
51
51
  "metadata"
52
52
  ],
53
53
  "$defs": {
54
+ "AtomUIConfig": {
55
+ "type": "object",
56
+ "description": "Display/behaviour settings for minimalist `atom` nodes (e.g. Constant, Cast).\nLives under `extensions.ui.atom`. The atom renderer reads these to decide what\nto show, and `valueTypeKey` drives the bound output port's `dataType` from\nconfig so connection validation matches the type the user picked.\n\nAll fields are optional — an empty object renders a label-only pill using the\nnode's `label`.\n",
57
+ "properties": {
58
+ "valueKey": {
59
+ "type": "string",
60
+ "description": "Config key whose value becomes the node body text.\nFalls back to the node `label` when unset or empty.\n"
61
+ },
62
+ "valueTypeKey": {
63
+ "type": "string",
64
+ "description": "Config key holding the selected value's type (a port dataType id).\nThe bound output port adopts this dataType.\n"
65
+ },
66
+ "outputPortId": {
67
+ "type": "string",
68
+ "description": "Output port id driven by `valueTypeKey`.\nDefaults to the first output port when unset.\n"
69
+ },
70
+ "shape": {
71
+ "type": "string",
72
+ "enum": [
73
+ "pill",
74
+ "rectangle"
75
+ ],
76
+ "default": "pill",
77
+ "description": "Body shape. `pill` (default) is fully rounded; `rectangle` is lightly rounded.\n"
78
+ },
79
+ "prefix": {
80
+ "type": "string",
81
+ "description": "Dimmed affordance rendered before the body (e.g. `\"→ \"` to mark a transform).\nStays visible while the body value ellipsizes. Hidden in the empty state.\n"
82
+ },
83
+ "placeholder": {
84
+ "type": "string",
85
+ "description": "Text shown (dimmed) when the resolved body value is empty/unset."
86
+ },
87
+ "maxWidth": {
88
+ "type": "integer",
89
+ "description": "Max body width in px before the label ellipsizes."
90
+ }
91
+ },
92
+ "additionalProperties": false
93
+ },
54
94
  "AutocompleteConfig": {
55
95
  "type": "object",
56
96
  "description": "Configuration for autocomplete fields that fetch suggestions from a callback URL.\nUsed when format is \"autocomplete\".\n",
@@ -414,15 +454,17 @@
414
454
  },
415
455
  "nodeType": {
416
456
  "type": "string",
417
- "description": "Changes how the node is visually rendered. This allows a single node definition\nto support multiple visual representations.\n\nAvailable built-in types:\n- `default`: Standard workflow node with full details\n- `simple`: Compact layout with minimal chrome\n- `square`: Geometric square layout (icon-only)\n- `tool`: Specialized style for agent tools\n- `gateway`: Branching control flow visualization\n- `terminal`: Start/end/exit node styling\n- `note`: Sticky note style for annotations\n\nThe node's `metadata.supportedTypes` defines which types are allowed.\nIf invalid or missing, falls back to `metadata.type` or \"default\".\n",
457
+ "description": "Changes how the node is visually rendered. This allows a single node definition\nto support multiple visual representations.\n\nAvailable built-in types:\n- `default`: Standard workflow node with full details\n- `simple`: Compact layout with minimal chrome\n- `square`: Geometric square layout (icon-only)\n- `atom`: Minimal label-only pill/rectangle (uses extensions.ui.atom)\n- `tool`: Specialized style for agent tools\n- `gateway`: Branching control flow visualization\n- `terminal`: Start/end/exit node styling\n- `note`: Sticky note style for annotations\n- `idea`: Conceptual idea node for BPMN-like flow diagrams\n\nThe node's `metadata.supportedTypes` defines which types are allowed.\nIf invalid or missing, falls back to `metadata.type` or \"default\".\n",
418
458
  "enum": [
419
459
  "default",
420
460
  "simple",
421
461
  "square",
462
+ "atom",
422
463
  "tool",
423
464
  "gateway",
424
465
  "terminal",
425
- "note"
466
+ "note",
467
+ "idea"
426
468
  ]
427
469
  },
428
470
  "dynamicInputs": {
@@ -677,12 +719,14 @@
677
719
  "note",
678
720
  "simple",
679
721
  "square",
722
+ "atom",
680
723
  "tool",
681
724
  "gateway",
682
725
  "terminal",
726
+ "idea",
683
727
  "default"
684
728
  ],
685
- "description": "Visual rendering type for the node.\n\nBuilt-in types:\n- `note` - Sticky note with markdown support\n- `simple` - Compact layout with header and description\n- `square` - Minimal square node with centered icon\n- `tool` - Specialized node for agent tools\n- `gateway` - Branching control flow with dynamic branches (uses config.branches)\n- `terminal` - Circular node for workflow start/end/exit points\n- `default` - Full-featured workflow node with dynamic port support\n\n## Dynamic Port Support\n\nThe `default` and `gateway` node types support dynamic ports:\n\n- **default**: Supports `config.dynamicInputs` and `config.dynamicOutputs`\n for user-defined input/output handles\n- **gateway**: Supports `config.branches` for conditional branching paths\n\n## UI Extensions\n\nAll node types support `extensions.ui.hideUnconnectedHandles` to control\nvisibility of unconnected ports.\n"
729
+ "description": "Visual rendering type for the node.\n\nBuilt-in types:\n- `note` - Sticky note with markdown support\n- `simple` - Compact layout with header and description\n- `square` - Minimal square node with centered icon\n- `atom` - Minimal label-only pill/rectangle for value/transform nodes (uses extensions.ui.atom)\n- `tool` - Specialized node for agent tools\n- `gateway` - Branching control flow with dynamic branches (uses config.branches)\n- `terminal` - Circular node for workflow start/end/exit points\n- `idea` - Conceptual idea node for BPMN-like flow diagrams\n- `default` - Full-featured workflow node with dynamic port support\n\n## Dynamic Port Support\n\nThe `default` and `gateway` node types support dynamic ports:\n\n- **default**: Supports `config.dynamicInputs` and `config.dynamicOutputs`\n for user-defined input/output handles\n- **gateway**: Supports `config.branches` for conditional branching paths\n\n## UI Extensions\n\nAll node types support `extensions.ui.hideUnconnectedHandles` to control\nvisibility of unconnected ports.\n"
686
730
  },
687
731
  "NodeUIExtensions": {
688
732
  "type": "object",
@@ -692,6 +736,9 @@
692
736
  "type": "boolean",
693
737
  "description": "Show/hide unconnected handles (ports) to reduce visual noise.\nWhen true, only ports with active connections are displayed.\nUseful for nodes with many optional ports.\n"
694
738
  },
739
+ "atom": {
740
+ "$ref": "#/$defs/AtomUIConfig"
741
+ },
695
742
  "style": {
696
743
  "type": "object",
697
744
  "additionalProperties": true,
@@ -199,8 +199,14 @@ export declare const playgroundActions: {
199
199
  * Apply a server response to the store. All message and status updates from
200
200
  * the server flow through here — polling callback, manual fetches, interrupt
201
201
  * resolution. Nothing updates messages or session status except this function.
202
+ *
203
+ * Pass `sessionId` (the session the response was fetched for) so a response
204
+ * that resolves after the user switched sessions is dropped instead of writing
205
+ * the old session's status/messages onto the new current session. Pass `null`
206
+ * to deliberately opt out of the guard (non-session-scoped callers only) — the
207
+ * argument is required so every new caller has to make that choice explicitly.
202
208
  */
203
- export declare function applyServerResponse(response: PlaygroundMessagesApiResponse): void;
209
+ export declare function applyServerResponse(response: PlaygroundMessagesApiResponse, sessionId: string | null): void;
204
210
  /**
205
211
  * Get the current session ID
206
212
  *
@@ -579,8 +579,16 @@ export const playgroundActions = {
579
579
  * Apply a server response to the store. All message and status updates from
580
580
  * the server flow through here — polling callback, manual fetches, interrupt
581
581
  * resolution. Nothing updates messages or session status except this function.
582
- */
583
- export function applyServerResponse(response) {
582
+ *
583
+ * Pass `sessionId` (the session the response was fetched for) so a response
584
+ * that resolves after the user switched sessions is dropped instead of writing
585
+ * the old session's status/messages onto the new current session. Pass `null`
586
+ * to deliberately opt out of the guard (non-session-scoped callers only) — the
587
+ * argument is required so every new caller has to make that choice explicitly.
588
+ */
589
+ export function applyServerResponse(response, sessionId) {
590
+ if (sessionId !== null && _currentSession?.id !== sessionId)
591
+ return;
584
592
  if (response.data && response.data.length > 0) {
585
593
  playgroundActions.addMessages(response.data);
586
594
  // Refresh the pipeline panel when following latest or pinned to the latest
@@ -696,7 +704,7 @@ export async function refreshSessionMessages(fetchMessages) {
696
704
  return;
697
705
  try {
698
706
  const response = await fetchMessages(session.id);
699
- applyServerResponse(response);
707
+ applyServerResponse(response, session.id);
700
708
  }
701
709
  catch (err) {
702
710
  logger.error('[playgroundStore] Failed to refresh messages:', err);