Enum forms drop enumNames, so a legacy titled enum renders its raw wire values instead of the human-readable titles. This affects both the web elicitation/schema form and the TUI form builder.
The everything server's elicitation tool sends exactly this shape:
"legacyTitledEnum": {
"type": "string",
"title": "Legacy Titled Single Select Enum",
"description": "Choose your favorite type of pet",
"enum": ["pet-1", "pet-2", "pet-3", "pet-4", "pet-5"],
"enumNames": ["Cats", "Dogs", "Birds", "Fish", "Reptiles"],
"default": "pet-1"
}
The user sees options pet-1 … pet-5 and has no way to know what they are picking; they should see Cats … Reptiles while pet-1 … is still what gets submitted.
Web — SchemaForm
clients/web/src/components/groups/SchemaForm/SchemaForm.tsx:72-84 — the string-enum branch passes data={fieldSchema.enum} straight through, dropping enumNames:
// string with enum
if (fieldSchema.type === "string" && fieldSchema.enum) {
return (
<Select
...
data={fieldSchema.enum}
This is inconsistent with the two sibling branches in the same function, which both already map values to titles:
- array/multi-select (
SchemaForm.tsx:169-178) pairs items.enum with items.enumNames into { value, label }[], guarded on the arrays being the same length.
- string with
oneOf (SchemaForm.tsx:88-92) maps const → title.
The type already supports it — InspectorFormSchema.enumNames?: string[] exists in clients/web/src/utils/jsonUtils.ts:52, annotated "Non-standard legacy support: titles for enum values". Only the scalar branch fails to read it.
Fix: in the string-enum branch, build data the same way the multi-select branch does — pair enum with enumNames into { value, label }[] when enumNames is present and its length matches enum, otherwise fall back to bare enum values. Since the same zip-with-length-guard would then exist in two branches, consider extracting a small local helper.
TUI — schemaToForm
clients/tui/src/utils/schemaToForm.ts has the same gap, and slightly worse: it does not model enumNames at all, and both enum branches hardcode label: String(val):
- the interface (
schemaToForm.ts:8-16) has no enumNames field (nor items.enumNames);
- single select (
schemaToForm.ts:71-74) maps property.enum → { label: String(val), value: String(val) };
- array of enums (
schemaToForm.ts:61-64) does the same on items.enum.
schemaToForm currently backs the tool-test form (ToolTestModal.tsx); the TUI has no dedicated elicitation form component yet, but whenever elicitation is wired to a form it will inherit this builder and the same bug. Fixing it here covers both.
Fix: add enumNames?: string[] (and items.enumNames) to the JsonSchemaProperty interface, then in both enum branches use enumNames[i] as the option label when present and length-matched, falling back to String(val).
Acceptance criteria
Web:
TUI:
Notes
The enumNames length guard matters in both clients: enumNames is non-standard and a server may send a mismatched or absent array, and a wrong-length zip would mislabel options — worse than showing raw values.
Enum forms drop
enumNames, so a legacy titled enum renders its raw wire values instead of the human-readable titles. This affects both the web elicitation/schema form and the TUI form builder.The everything server's elicitation tool sends exactly this shape:
The user sees options
pet-1 … pet-5and has no way to know what they are picking; they should seeCats … Reptileswhilepet-1 …is still what gets submitted.Web —
SchemaFormclients/web/src/components/groups/SchemaForm/SchemaForm.tsx:72-84— the string-enum branch passesdata={fieldSchema.enum}straight through, droppingenumNames:This is inconsistent with the two sibling branches in the same function, which both already map values to titles:
SchemaForm.tsx:169-178) pairsitems.enumwithitems.enumNamesinto{ value, label }[], guarded on the arrays being the same length.oneOf(SchemaForm.tsx:88-92) mapsconst→title.The type already supports it —
InspectorFormSchema.enumNames?: string[]exists inclients/web/src/utils/jsonUtils.ts:52, annotated "Non-standard legacy support: titles for enum values". Only the scalar branch fails to read it.Fix: in the string-enum branch, build
datathe same way the multi-select branch does — pairenumwithenumNamesinto{ value, label }[]whenenumNamesis present and its length matchesenum, otherwise fall back to bareenumvalues. Since the same zip-with-length-guard would then exist in two branches, consider extracting a small local helper.TUI —
schemaToFormclients/tui/src/utils/schemaToForm.tshas the same gap, and slightly worse: it does not modelenumNamesat all, and both enum branches hardcodelabel: String(val):schemaToForm.ts:8-16) has noenumNamesfield (noritems.enumNames);schemaToForm.ts:71-74) mapsproperty.enum→{ label: String(val), value: String(val) };schemaToForm.ts:61-64) does the same onitems.enum.schemaToFormcurrently backs the tool-test form (ToolTestModal.tsx); the TUI has no dedicated elicitation form component yet, but whenever elicitation is wired to a form it will inherit this builder and the same bug. Fixing it here covers both.Fix: add
enumNames?: string[](anditems.enumNames) to theJsonSchemaPropertyinterface, then in both enum branches useenumNames[i]as the optionlabelwhen present and length-matched, falling back toString(val).Acceptance criteria
Web:
enumNamesrenders the titles as option labels while submitting the underlyingenumvalues (showsCats, submitspet-1).enumNamesstill renders the raw values (no regression).enumNamesfalls back to raw values rather than mislabeling.defaultstill preselects correctly (pet-1→Catsshown).SchemaForm.test.tsxcover all four cases; the file already hasenumNamescoverage for the multi-select path to model.TUI:
schemaToFormrendersenumNamestitles as select-option labels (single and array-of-enum branches) while keeping raw values as the optionvalue.enumNamesfalls back toString(val)(no regression).schemaToForm.test.tscover present / absent / mismatched cases for both branches.Notes
The
enumNameslength guard matters in both clients:enumNamesis non-standard and a server may send a mismatched or absent array, and a wrong-length zip would mislabel options — worse than showing raw values.