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

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions