tui: detect array-of-enum on items.enum alone (#1752)

* tui: detect array-of-enum on items.enum alone (#1751)

The TUI schemaToForm array-of-enum branch was nested under an outer
`if (property.enum)` guard, so a standard array-of-enums schema —
`{ type: "array", items: { enum: [...] } }` with no top-level `enum` — never
reached it and fell through to a plain string input. The web SchemaForm already
guards on `items?.enum` alone; this aligns the TUI with it.

Restructure the enum handling so the array-of-enums case keys on
`property.type === "array" && property.items?.enum` independently of a top-level
`enum`, falling back to the single-select `property.enum` branch otherwise. The
enumNames labeling from #1691 applies unchanged.

Tests: the array-of-enum cases now use the standard `items.enum`-only shape
(dropping the redundant top-level `enum` the old nesting required), plus a case
asserting a redundant top-level `enum` still works.

Closes #1751

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5

* docs(pr-screenshots): TUI array-of-enum before/after proof shots (#1751)

Before/after of the TUI tool form for an array-of-enums field with no top-level
`enum`: before the fix it renders as a plain text field (raw "m"); with the fix
it renders as a select resolving the enumNames title ("Medium").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cliff Hall 2026-07-23 19:12:45 -04:00 • committed by GitHub
commit c2b866110d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -69,27 +69,24 @@ export function schemaToForm(
let field: FormField;
// Handle enum -> select
if (property.enum) {
if (property.type === "array" && property.items?.enum) {
// For array of enums, we'll use select but handle it differently
// Note: ink-form doesn't have multiselect, so we'll use select
field = {
type: "select",
...baseField,
options: toSelectOptions(
property.items.enum,
property.items.enumNames,
),
} as FormField;
} else {
// Single select
field = {
type: "select",
...baseField,
options: toSelectOptions(property.enum, property.enumNames),
} as FormField;
}
// Handle enum -> select. Detect the array-of-enums case on `items.enum`
// alone (matching the web SchemaForm guard) — a standard array-of-enums
// schema carries no top-level `enum`, so gating on it would drop the field
// to a plain string input.
if (property.type === "array" && property.items?.enum) {
// ink-form has no multiselect, so we render a single select.
field = {
type: "select",
...baseField,
options: toSelectOptions(property.items.enum, property.items.enumNames),
} as FormField;
} else if (property.enum) {
// Single select
field = {
type: "select",
...baseField,
options: toSelectOptions(property.enum, property.enumNames),
} as FormField;
} else {
// Map JSON Schema types to ink-form types
switch (property.type) {