Improve CLI UX: enums, validation, help panels, and completions#33
Merged
Conversation
transcribe exposes 40+ options that previously rendered as one flat Options wall in --help. Tag each flag with rich_help_panel so the existing code-comment groupings (model, formatting, speakers, guardrails, analysis, customization, webhooks, translation, advanced, LLM transform) become visible sections. Everyday flags (--sample, --json, -o, --show-code) stay in the default Options panel so the common case stays at the top. Panel headings are centralized in help_panels.py as a single source of truth.
stream has the same 37-flag wall as transcribe. Tag each flag with rich_help_panel, reusing the shared panel vocabulary (Model & Language, Speakers, Guardrails, Webhooks, LLM Transform, Advanced) so the two sibling commands read consistently, plus three stream-specific panels (Audio Capture, Turn Detection, Features) for real-time concerns that file transcription has no equivalent for. Everyday flags (--sample, --json, -o, --show-code) stay in the default Options panel, mirroring transcribe.
Use the assemblyai SDK's own enums as the Typer option types for flags with a fixed value set: --speech-model, --summary-model, --summary-type, --redact-pii-sub (transcribe) and --speech-model, --encoding, --voice-focus (stream). Typer now renders the valid choices in --help (e.g. [best|nano|slam-1|universal]), validates input with a clean listing error, and completes the values on Tab. A new config_builder.enum_value() unwraps each member to its canonical string at the body boundary, so the config/codegen pipelines stay string-based and --show-code output is unchanged. This also fixes a latent bug: the old --voice-focus help advertised near_field/far_field, but the SDK values are hyphenated (near-field/far-field).
Introduce aai_cli/choices.py with TranscriptOutput (text/id/status/ utterances/srt/json) and TextOrJson (text/json) StrEnums, and use them as the -o/--output option type across transcribe, transcripts get, stream, agent, and llm. Typer now lists the modes in --help and rejects a bad value with a clean listing error, replacing the hand-rolled output.validate_output_field and client.TRANSCRIPT_OUTPUT_FIELDS (both removed). StrEnum members are strings, so the existing field == 'text' comparisons and select_transcript_field() calls are unchanged.
Use choices.Scope (user/project/local) for the --scope option on 'aai setup install' and 'aai setup remove', so Typer lists the scopes in --help and rejects a bad value with a clean listing error. Removes the hand-rolled _VALID_SCOPES check in both commands; StrEnum members are strings, so they pass straight through to 'claude mcp add'.
Flip add_completion=True so 'aai --install-completion' / '--show-completion' work; combined with the enum-typed flags from earlier, choices, file paths, and command names now complete on Tab. Add autocompletion callbacks for the two open-set flags whose values aren't enums: llm.complete_model (suggests KNOWN_MODELS without restricting input, wired into transcribe/stream/llm --model) and voices.complete_voice (agent --voice). The existing --list-voices/--list-models flags stay as a no-completion-needed fallback.
- File-path options (transcribe --config-file/--custom-spelling-file, stream --config-file, agent --system-prompt-file) gain exists=True + dir_okay=False, so Typer rejects a missing path up front with a standard message instead of relying on the loaders' deeper handling. Widen config_builder signatures to accept Path. (readable=True was dropped: it can't be exercised in CI, which runs as root.) - Add metavar=KEY=VALUE to --config and metavar=NAME:VALUE to --webhook-auth-header so the expected shape shows in --help. - Add an eager root --version flag alongside the existing 'version' command.
client.transcribe() blocks on the SDK's poll-to-completion with no feedback — on a long file the terminal looks frozen. Wrap the wait in a new output.status() context manager that shows an ephemeral rich spinner on stderr, so stdout pipelines (e.g. -o text > out) stay clean. It's a no-op in JSON or non-interactive mode (piped / agent-run), so machine output is never decorated. Uses rich, already a dependency.
- .mcp.json was accidentally swept into the --scope commit by an 'aai setup install' verification run (added an assemblyai-docs entry and dropped the trailing newline), which failed the pre-commit end-of-file-fixer. Restore it to match origin/main. - test_shell_completion_is_enabled asserted on rendered --help text, which wraps/renders differently in CI's terminal and hid the flag. Introspect the Click command's params instead — stable regardless of width, and still flips when add_completion is disabled.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR enhances the CLI's user experience through better type safety, input validation, organized help text, and shell completions. It introduces a new
choicesmodule for closed-value enums, adds file-path validation via Typer'sexists=True, organizes options into help panels, and implements shell-completion callbacks for dynamic values.Key Changes
New
choicesmodule (aai_cli/choices.py): IntroducesStrEnumtypes for closed value sets (TranscriptOutput,TextOrJson,Scope). These enums automatically render as choices in--help, validate input with clean error messages, and enable shell-tab completion — while remaining backward-compatible with existing string comparisons.Type-safe enums for command options: Replaces string type hints with proper enum types:
transcribe:speech_model→aai.SpeechModel,summary_model→aai.SummarizationModel,summary_type→aai.SummarizationType,redact_pii_sub→aai.PIISubstitutionPolicystream:speech_model→SpeechModel,encoding→Encoding,voice_focus→NoiseSuppressionModelsetup:scope→choices.Scopeagent,llm,transcripts:output→choices.TextOrJsonFile-path validation: Adds
exists=Trueto file-path options (--config-file,--custom-spelling-file,--system-prompt-file) so Typer validates paths before the command runs, providing early, clear error messages. New test filetests/test_path_validation.pypins this behavior.Help panel organization (
aai_cli/help_panels.py): Defines semantic panel names (OPT_MODEL,OPT_FORMATTING,OPT_SPEAKERS,OPT_GUARDRAILS,OPT_ANALYSIS,OPT_CUSTOMIZATION,OPT_CAPTURE,OPT_TURNS,OPT_FEATURES) and assigns options to panels viarich_help_panel=.... This groups related flags under headings in--help, making 40+ options navigable instead of a flat wall.Shell completions:
complete_model()inaai_cli/llm.pyandcomplete_voice()inaai_cli/agent/voices.pyto suggest known values on Tab.add_completion=Trueinaai_cli/main.pyso--install-completionis available.tests/test_completion.pyverifies completion functions.Snapshot updates: Regenerated
tests/__snapshots__/test_cli_output_snapshots.ambrto reflect improved help formatting with panels and enum choices (e.g.,[text|json]instead ofTEXT).Minor improvements:
--versionflag now works as an eager callback (prints version and exits before subcommand is required).config_builder.pytype hints updated to acceptPath | strfor config files..mcp.jsonupdated withassemblyai-docsMCP entry.output.py(now handled by enums).Implementation Details
enum.StrEnumso their members are their string values — existing code likefield == "text"continues to work without changes.[choice1|choice2|...]in help text and validates input, rejecting unknown values with a clean listing error.https://claude.ai/code/session_01WsMwnsXuSkgrX4UzC3aJqP