feat(sdk) Variable enhancement - #76
Conversation
…into feat/WB-139-variables
| }); | ||
|
|
||
| return { | ||
| response: { |
There was a problem hiding this comment.
It injects a synthetic response variable into every schemaOutput**
Every node using the new schemaOutput ends up advertising {{nodes.<id>.response}} in the suggestions index, even when its schema declares no such property (e.g. the demo trigger only outputs eventType / timestamp). That reference is a promise the execution side doesn't keep: response is an ai-studio convention (its worker really does store output under that key), not a WB-wide contract. A generic engine won't have it, and resolve-template is intentionally strict, so a user who picks "Response" from the picker gets a run that fails on a variable the editor itself suggested.
Why nothing caught it: the injected entry is typed object, and all stock controls filter objects out (text controls, VariableDynamic, conditions), so it's invisible in the demo UI. And there's currently no place in the repo that both uses schemaOutput and executes (demo isn't executed; ai-studio's ai-agent is back on the deprecated outputSchema, which doesn't inject). It will surface through the newly public getNodeVariablesSuggestions, the planned variables plugin, and any future object-accepting control or schema-based validation.
Question: is there a concrete intent behind this (a "reference the whole output" feature)? If yes, let's make it an explicit, documented opt-in once the runtime actually guarantees the key. If not, my recommendation is to drop the injection: a node that exposes its whole result under response can declare it in its own schema, like ai-studio's ai-agent does today.
Side notes if it stays: the label is hardcoded English (bypasses i18n), and a schema that genuinely declares response wins over the injected one via spread order, so removal is backward-safe for those nodes.
| EDGE_OFFSET, | ||
| SELF_CONNECTING_EDGE_LABEL_OFFSET, | ||
| } from './features/diagram/edges/edge.consts'; | ||
| export { VARIABLE_NODES_KEY } from './features/variables/constants'; |
There was a problem hiding this comment.
VARIABLE_NODES_KEY silently dropped from the public API**
This export existed in 2.3.0 and is listed in the typedoc coverage decision log, so removing it in a minor is a semver break, even if a tiny one. Either re-add it with @deprecated, or keep the removal and call it out explicitly in a changeset. Trimming the rest of the surface (raw store etc.) was the right call since those were never released.
| @@ -0,0 +1,5 @@ | |||
| --- | |||
| '@workflowbuilder/sdk': patch | |||
There was a problem hiding this comment.
Bump says patch, content says feature
Per-handle variables + JSON Schema outputs is a new capability, so this should be minor. No practical effect on the released version (the other changesets already force a minor), but the CHANGELOG entry will land in the wrong section.
There was a problem hiding this comment.
VariableDynamic is missing from the controls reference
The control has a changeset and demo usage, but no section here. Needs the usual table: variableType, placeholder, value contract (plain value vs a single {{...}} reference), and a pointer to the variable picker guide.
| // Variables can’t change while the modal containing them is in use, so we only need to refresh them when they change. | ||
| // .length is critical here for performance. | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| }, [nodeId, edges.length, nodes.length]); |
There was a problem hiding this comment.
The nodes.length / edges.length deps (and the key={totalVariables} remount in VariableDynamic) are a documented perf trade-off, and the sidebar remount masks most cases. Remaining gaps: rewiring an edge to a different source (same counts) and the 100 ms indexing race after addNode. A cheap fix later: subscribe to the suggestions-store state identity (one new object per refresh) instead of counts.
Workflow Builder introduced variable support some time ago, allowing sidebar controls to use variables from previous nodes or global variables.
This PR enhances the feature with the missing logic to make variable usage more robust and flexible.
Main changes
Variables provided by nodes to downstream nodes can now depend on:
Nagranie.z.ekranu.2026-08-14.o.18.32.10.mov
Node variables store:
Previously, variables from previous nodes were calculated when the control was mounted. We traversed the graph and calculated their values at the same time - now we keep nodes variables in the store and only collect them:
New single variable control (previously used in conditions)
Nagranie.z.ekranu.2026-08-14.o.18.28.48.mov
It shows a date picker with
{}when date variables are available.Fixes
totalVariablesIt's worth noting that the majority of the changes are encapsulated in
packages/sdk/src/features/variables/. So while reviewing, we can identify what is used externally as a useful public API and note the core functions that could be valuable to expose.