Skip to content

web+tui: Enum forms ignore enumNames (legacy titled enum renders raw values) #1691

Description

@cliffhall

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 consttitle.

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:

  • A string enum with a valid enumNames renders the titles as option labels while submitting the underlying enum values (shows Cats, submits pet-1).
  • A string enum with no enumNames still renders the raw values (no regression).
  • A mismatched-length enumNames falls back to raw values rather than mislabeling.
  • default still preselects correctly (pet-1Cats shown).
  • Unit tests in SchemaForm.test.tsx cover all four cases; the file already has enumNames coverage for the multi-select path to model.
  • Verified against the everything server's elicitation tool.

TUI:

  • schemaToForm renders enumNames titles as select-option labels (single and array-of-enum branches) while keeping raw values as the option value.
  • Absent / mismatched-length enumNames falls back to String(val) (no regression).
  • Unit tests in schemaToForm.test.ts cover present / absent / mismatched cases for both branches.

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.

Metadata

Metadata

Assignees

Labels

v2Issues and PRs for v2

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions