Phase 2: Examples use typed flow inputs #6
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Phase 1 (#5) introduces typed flow inputs on Workflow. Currently
Example.input_datais a free-form JSON string — whatever the user typed into the run form as raw JSON. Once inputs are declared with types, examples should be structured fixtures: one value per declared input.Goal
Each Example is a named set of values, one per flow input. Loading an example populates the play-start form field-by-field. Saving an example captures the current form values.
Depends on
Workflow.inputs: [FlowInput]and typed run form)OSchema changes
File:
crates/hero_logic/schemas/logic/logic.oschemaReplace
input_dataonExample:Why
{str: str}with serialized JSON values: OSchema's map-of-Value is more complex than needed; storing each value as a JSON-encoded string keeps it simple and the Python/JS sides parse per-input by looking at the input's declaredtype.Code changes
crates/hero_logic/src/logic/server/rpc.rsexample_create(workflow_sid, name, description, input_values) -> Example: validates that providedinput_valueskeys are a subset of the workflow's declared input names; each value can be parsed according to the input's declaredtype. Unknown keys are dropped with a warning.example_apply(example_sid) -> {input_values: {str: str}}: fetches the example and returns its values — useful for the UI to load them.play_startoptionally acceptsexample_sidinstead ofinput_data; if given, resolves the example'sinput_valuesand composes them into the input_data JSON.Migration
For existing Example records with
input_data:input_values[key](values serialized back to JSON strings).example_migrate_legacy(example_sid)RPC.UI changes
File:
crates/hero_logic_ui/templates/workflow_editor.html+ JSinput_values: {name: JSON.stringify(value)}.example.input_values(parse per input type).prompt="ping hero_proc", num_tests=3).foono longer exists, or required inputbarwas added after).Acceptance criteria
Examplerecord hasinput_values: {str: str}field;input_dataremovedinput_data) still load (auto-migrated on read)Out of scope
workflow_version_sidbut not strictly required for this phase)Backend landed:
671d026Phase 2 schema + RPC changes are in. UI changes (per-input form fields in save/load modals, structured preview) remain.
What's live
OSchema:
Example.input_values: JSON-serialized{input_name: value}mapExample.input_data: kept for legacy (auto-migrated on fetch)Example.workflow_version_sid: optional pinRPC methods:
example_upsert(sid, workflow_sid, workflow_version_sid, name, description, input_values_json)— validates keys againstWorkflow.inputs, rejects unknowns with a clear errorexample_fetch(sid)— auto-migrates legacy examples (copiesinput_data→input_valueswhen the latter is empty)example_to_input_data(example_sid)— new helper that resolvesinput_valuesinto aplay_start-ready input JSON, merging in declared defaults for any unset optional inputsVerified
Remaining for this issue
input_values,workflow_version_sidprompt=..., num_tests=...)Moving on to Phase 3 (#7) next — benchmark flow.
Phase 2 UI landed (commit
c062bbf)Example save/load now uses structured
input_values:FlowInput) when the workflow has declared inputs; falls back to the legacy capture-current-start-node-run_inputs behavior for pre-Phase-2 workflows.example_upsertnow submitsinput_values_json+workflow_version_sid(full Phase 2 signature) so saved Examples bind to declared inputs and pin to the version that was current at save time.loadExampleInputsprefersex.input_valuesover legacyex.input_datawhen applying values into the start-noderun_inputs.collectTypedInputValues(inputs, prefix)JS helper that both the Start-play and Save-as-example modals share — single source of truth for type coercion (string/number/integer/boolean/object/array) and required-field validation.Verified end-to-end:
example_upsert("ping","gpt-4o-mini")against workflow00dz/version00e0→ saved Example00e1withinput_values="{...}"and the legacyinput_dataleft empty.example_to_input_data(00e1)→{"model":"gpt-4o-mini","prompt":"ping"}— ready to feed intoplay_start.example_fetch(00e1)returns bothinput_valuesandworkflow_version_sidso the UI can warn on stale-schema mismatch.Still open for this issue: