Repository navigation
Description
Parent
Spec: #22 — Generate text, an LLM action node for workflows.
What to build
The authoring surface. A workflow author opens the builder, finds a Generate text step in a new AI category, writes a prompt, declares what they want out of it, saves, publishes, and a real run fills their variables.
The category. A new AI category registered with the node, gated on a single feature flag. Registration happens by import side effect, so the new category file has to be pulled into the registry's index or it never appears at all and nothing reports the omission.
Panel order, top to bottom: step name, prompt, output fields, model, then the existing accordion for output variables, conditions and error handling. The prompt is the main input and gets the vertical space — it is the thing the author is actually writing.
Output field rows. Each row is a declared workflow variable plus an instruction, laid out on two lines. The variable side reuses the existing select over declared variables, filtered to the ones not already spoken for. Creating a variable stays where it already is, in the variables panel behind the existing link — this panel does not grow a second way to make one.
The coupling that makes it work. Picking a variable writes a derived output-variable mapping pointing at that field's result path. This is the whole reason the node is not a footgun: without the mapping the node runs, spends the customer's credits, and discards the result silently. Field-owned mappings regenerate whenever the fields change; mappings no field owns are left completely alone, because an author may have added their own by hand — including one pointing at the raw generation, which is how a whole generation reaches a variable when fields are not wanted.
Field-owned mappings stay visible and editable in the output variables accordion, tagged so it is clear where they came from and that the field above is the place to change them. Hiding them would make the panel lie about what the step does.
How it renders. A branch on the template id inside the existing function configuration component, following the two literal-id branches already there. No new shared input type — this is one bespoke panel, and the stored shape stays a plain dictionary regardless of how it is rendered.
The model input carries copy stating that each run of the step spends the team's AI credits. Authors should not learn that from a bill.
Acceptance criteria
- The AI category with the Generate text node appears in the builder for a user with the flag on, and does not appear with it off.
- The new category is wired into the registry index, so it actually registers.
- The panel renders in the stated order, with the prompt as the dominant input.
- An output field row pairs a declared variable with an instruction, and the variable select offers only variables not already used by another mapping.
- Picking a variable for a field creates the matching output-variable mapping automatically.
- Changing or removing a field regenerates its mapping, and leaves mappings no field owns untouched — including a hand-added mapping pointing at the raw generation.
- Field-owned mappings are visible in the output variables accordion, tagged to show the field above owns them.
- The model input states that each run spends AI credits.
- The prompt input accepts liquid, so JSON examples, few-shot blocks and conditional blocks need no escaping.
- An author can configure the step, save, publish, and a real run writes the declared variables.
- Covered by the existing logic-level Jest patterns, with mapping regeneration and the preservation of unowned rows tested directly.
Blocked by
- Extract declared output fields with a strict schema #46 — the panel declares fields, so the extraction contract has to exist.
- Generate text node and its polling transport #48 — the template and its input schema.
Activity