Claude-Session: https://claude.ai/code/session_01XPsuy2ZZ5Gbyfpt8PrK5BV
3.7 KiB
Flow Debugger — method pane takes structured parameters (Gitea #37)
Date: 2026-09-10 · Status: approved (issue-authored spec) · Issue: #37
Problem
The Flow Debugger's Run inbound API method pane rendered one single-line text box per
top-level schema field and coerced the text by declared type. For object / array fields it
tried JsonNode.Parse on the raw text and, on failure, sent the text as a string; an empty
box was silently omitted. A required array-of-object parameter (MesMoveOut WorkOrders,
[{WorkOrderNumber, PartNumber}]) could not be entered from the page at all — the QA run
reached the site with "WorkOrders":[] and the receiver rejected it with a misleading error.
The same payload ran fine through flow-debug run-method --params, so only the UI input
surface was at fault. The Run site script pane on the same page already uses the shared
ParameterValueForm (typed inputs, nested groups, add/remove list editors, $ref:lib:
resolution, inline validation, Monaco escape hatch for unresolved shapes).
Design
- The method pane renders
ParameterValueFormdriven by the method'sParameterDefinitions, keyed on the method id so a change of method remounts the form (the same reason the script pane keys on the script's canonical name). The page holds a_methodParamsvalue tree +_methodParamsValid;BuildParameters()serializes the tree as-is, exactly likeBuildScriptParameters(). The flat_inputs/Coerce()/SetInputpath is deleted — a failed parse can no longer be sent as a string, and there is no type-specific coercion left on the page. - Whole-payload raw-JSON escape hatch. The Inputs card gains a Form | Raw JSON toggle.
Raw mode is a Monaco
jsoneditor given the method's root schema (the form'sToJsonSchemamadeinternal static) so completion and hover work. Every edit parses the text and validates it withInboundApiSchema.Validateagainst the resolved root schema (ParseWithRefs+ISchemaLibraryQueryService, the same resolution the form does); errors render inline under the editor. Switching Form → Raw seeds the editor from the current value tree (indented); Raw → Form loads the last valid tree into the form. The value tree is the single source of truth in both modes. - Run gating.
CanRunfor the method entry ismethod chosen && (no parameters || params valid), mirroring_scriptParamsValid. A required field left empty disables Run (the form reports validity on mount, so this holds before the first keystroke). - Persistence. The per-method
localStorageentry (flowDebugger.inputs.<id>) now stores the value tree as JSON. On restore the tree is converted back (the form'sJsonElementToObjectmadeinternal static) and validated against the schema; an invalid tree is discarded. That also retires the old flatDictionary<string,string>entries without a version flag: legacy strings that still validate (string fields) are kept, anything else is dropped. - Not changed: the runner (
FlowDebugRunMethodCommand), the CLI, prediction, Replay, the script pane. No wire, proto or schema change.
Tests
- bUnit (
FlowDebuggerPageTests): an array-of-object field (theWorkOrdersshape) round-trips from the list item editors to theRunMethodAsyncpayload; invalid raw JSON blocks Run and shows the error; valid raw JSON sends exactly that payload; a required scalar left empty disables Run until filled; switching methods resets the form and its validity. - Playwright
FlowDebuggerTests: the smoke selector moves fromflow-input-Textto the form's#param-Text.
Docs
Component-CentralUI.md (Flow Debugger entry points), CLAUDE.md Flow Debugger bullet, this
design doc.