hermes-agent/tests/hermes_cli
Teknium 01906e99dd
feat(image_gen): multi-model FAL support with picker in hermes tools (#11265)
* feat(image_gen): multi-model FAL support with picker in hermes tools

Adds 8 FAL text-to-image models selectable via `hermes tools` →
Image Generation → (FAL.ai | Nous Subscription) → model picker.

Models supported:
- fal-ai/flux-2/klein/9b (new default, <1s, $0.006/MP)
- fal-ai/flux-2-pro (previous default, kept backward-compat upscaling)
- fal-ai/z-image/turbo (Tongyi-MAI, bilingual EN/CN)
- fal-ai/nano-banana (Gemini 2.5 Flash Image)
- fal-ai/gpt-image-1.5 (with quality tier: low/medium/high)
- fal-ai/ideogram/v3 (best typography)
- fal-ai/recraft-v3 (vector, brand styles)
- fal-ai/qwen-image (LLM-based)

Architecture:
- FAL_MODELS catalog declares per-model size family, defaults, supports
  whitelist, and upscale flag. Three size families handled uniformly:
  image_size_preset (flux family), aspect_ratio (nano-banana), and
  gpt_literal (gpt-image-1.5).
- _build_fal_payload() translates unified inputs (prompt + aspect_ratio)
  into model-specific payloads, merges defaults, applies caller overrides,
  wires GPT quality_setting, then filters to the supports whitelist — so
  models never receive rejected keys.
- IMAGEGEN_BACKENDS registry in tools_config prepares for future imagegen
  providers (Replicate, Stability, etc.); each provider entry tags itself
  with imagegen_backend: 'fal' to select the right catalog.
- Upscaler (Clarity) defaults off for new models (preserves <1s value
  prop), on for flux-2-pro (backward-compat). Per-model via FAL_MODELS.

Config:
  image_gen.model           = fal-ai/flux-2/klein/9b  (new)
  image_gen.quality_setting = medium                  (new, GPT only)
  image_gen.use_gateway     = bool                    (existing)

Agent-facing schema unchanged (prompt + aspect_ratio only) — model
choice is a user-level config decision, not an agent-level arg.

Picker uses curses_radiolist (arrow keys, auto numbered-fallback on
non-TTY). Column-aligned: Model / Speed / Strengths / Price.

Docs: image-generation.md rewritten with the model table and picker
walkthrough. tools-reference, tool-gateway, overview updated to drop
the stale "FLUX 2 Pro" wording.

Tests: 42 new in tests/tools/test_image_generation.py covering catalog
integrity, all 3 size families, supports filter, default merging, GPT
quality wiring, model resolution fallback. 8 new in
tests/hermes_cli/test_tools_config.py for picker wiring (registry,
config writes, GPT quality follow-up prompt, corrupt-config repair).

* feat(image_gen): translate managed-gateway 4xx to actionable error

When the Nous Subscription managed FAL proxy rejects a model with 4xx
(likely portal-side allowlist miss or billing gate), surface a clear
message explaining:
  1. The rejected model ID + HTTP status
  2. Two remediation paths: set FAL_KEY for direct access, or
     pick a different model via `hermes tools`

5xx, connection errors, and direct-FAL errors pass through unchanged
(those have different root causes and reasonable native messages).

Motivation: new FAL models added to this release (flux-2-klein-9b,
z-image-turbo, nano-banana, gpt-image-1.5, ideogram-v3, recraft-v3,
qwen-image) are untested against the Nous Portal proxy. If the portal
allowlists model IDs, users on Nous Subscription will hit cryptic
4xx errors without guidance on how to work around it.

Tests: 8 new cases covering status extraction across httpx/fal error
shapes and 4xx-vs-5xx-vs-ConnectionError translation policy.

Docs: brief note in image-generation.md for Nous subscribers.

Operator action (Nous Portal side): verify that fal-queue-gateway
passes through these 7 new FAL model IDs. If the proxy has an
allowlist, add them; otherwise Nous Subscription users will see the
new translated error and fall back to direct FAL.

* feat(image_gen): pin GPT-Image quality to medium (no user choice)

Previously the tools picker asked a follow-up question for GPT-Image
quality tier (low / medium / high) and persisted the answer to
`image_gen.quality_setting`. This created two problems:

1. Nous Portal billing complexity — the 22x cost spread between tiers
   ($0.009 low / $0.20 high) forces the gateway to meter per-tier per
   user, which the portal team can't easily support at launch.
2. User footgun — anyone picking `high` by mistake burns through
   credit ~6x faster than `medium`.

This commit pins quality at medium by baking it into FAL_MODELS
defaults for gpt-image-1.5 and removes all user-facing override paths:

- Removed `_resolve_gpt_quality()` runtime lookup
- Removed `honors_quality_setting` flag on the model entry
- Removed `_configure_gpt_quality_setting()` picker helper
- Removed `_GPT_QUALITY_CHOICES` constant
- Removed the follow-up prompt call in `_configure_imagegen_model()`
- Even if a user manually edits `image_gen.quality_setting` in
  config.yaml, no code path reads it — always sends medium.

Tests:
- Replaced TestGptQualitySetting (6 tests) with TestGptQualityPinnedToMedium
  (5 tests) — proves medium is baked in, config is ignored, flag is
  removed, helper is removed, non-gpt models never get quality.
- Replaced test_picker_with_gpt_image_also_prompts_quality with
  test_picker_with_gpt_image_does_not_prompt_quality — proves only 1
  picker call fires when gpt-image is selected (no quality follow-up).

Docs updated: image-generation.md replaces the quality-tier table
with a short note explaining the pinning decision.

* docs(image_gen): drop stale 'wires GPT quality tier' line from internals section

Caught in a cleanup sweep after pinning quality to medium. The
"How It Works Internally" walkthrough still described the removed
quality-wiring step.
2026-04-16 20:19:53 -07:00
..
__init__.py test: reorganize test structure and add missing unit tests 2026-02-26 03:20:08 +03:00
test_anthropic_oauth_flow.py refactor(tests): re-architect tests + fix CI failures (#5946) 2026-04-07 17:19:07 -07:00
test_anthropic_provider_persistence.py refactor(tests): re-architect tests + fix CI failures (#5946) 2026-04-07 17:19:07 -07:00
test_api_key_providers.py chore: rename AI Gateway → Vercel AI Gateway, move Xiaomi to #5 (#9326) 2026-04-13 19:51:54 -07:00
test_arcee_provider.py feat(providers): add Arcee AI as direct API provider 2026-04-13 18:40:06 -07:00
test_argparse_flag_propagation.py fix: --yolo and other flags silently dropped when placed before 'chat' subcommand (#5145) 2026-04-04 16:55:13 -07:00
test_atomic_json_write.py refactor(tests): re-architect tests + fix CI failures (#5946) 2026-04-07 17:19:07 -07:00
test_atomic_yaml_write.py refactor(tests): re-architect tests + fix CI failures (#5946) 2026-04-07 17:19:07 -07:00
test_auth_codex_provider.py fix: write refreshed Codex tokens back to ~/.codex/auth.json (#8277) 2026-04-12 02:05:20 -07:00
test_auth_commands.py fix: resolve remaining 4 CI test failures (#9543) 2026-04-14 02:18:38 -07:00
test_auth_nous_provider.py fix: dashboard shows Nous Portal as 'not connected' despite active auth (#9261) 2026-04-13 16:32:11 -07:00
test_auth_provider_gate.py fix: resolve CI test failures — add missing functions, fix stale tests (#9483) 2026-04-14 01:43:45 -07:00
test_auth_qwen_provider.py feat(qwen): add Qwen OAuth provider with portal request support 2026-04-08 13:46:30 -07:00
test_backup.py feat: fix SQLite safety in hermes backup + add --quick snapshots + /snapshot command (#8971) 2026-04-13 04:46:13 -07:00
test_banner.py fix(banner): normalize toolset labels and use skin colors 2026-03-18 03:22:58 -07:00
test_banner_git_state.py fix: CLI/UX batch — ChatConsole errors, curses scroll, skin-aware banner, git state banner (#5974) 2026-04-07 17:59:42 -07:00
test_banner_skills.py fix: disabled skills respected across banner, system prompt, slash commands, and skill_view (#1897) 2026-03-18 03:17:37 -07:00
test_chat_skills_flag.py fix(termux): add local image chat route 2026-04-09 16:24:53 -07:00
test_claw.py fix: unify OpenClaw detection, add isatty guard, fix print_warning import 2026-04-12 16:40:37 -07:00
test_clear_stale_base_url.py fix: warn and clear stale OPENAI_BASE_URL on provider switch (#5161) 2026-04-11 01:52:58 -07:00
test_cmd_update.py fix(update): skip config migration prompts in non-interactive sessions (#3584) 2026-03-28 14:26:32 -07:00
test_coalesce_session_args.py fix(cli): handle unquoted multi-word session names in -c/--continue and -r/--resume 2026-03-09 21:36:29 -07:00
test_codex_cli_model_picker.py fix: openai-codex and anthropic not appearing in /model picker for external credentials (#8224) 2026-04-12 00:33:42 -07:00
test_codex_models.py fix(model): normalize native provider-prefixed model ids 2026-04-10 05:52:45 -07:00
test_commands.py fix: remove 'q' alias from /quit so /queue's 'q' alias works (#10467) (#10538) 2026-04-15 15:04:01 -07:00
test_completion.py fix: preserve profile name completion in dynamic shell completion 2026-04-14 10:45:42 -07:00
test_config.py feat(discord): add channel_prompts config 2026-04-15 16:31:28 -07:00
test_config_env_expansion.py refactor(tests): re-architect tests + fix CI failures (#5946) 2026-04-07 17:19:07 -07:00
test_config_validation.py feat: config structure validation — detect malformed YAML at startup (#5426) 2026-04-05 23:31:20 -07:00
test_container_aware_cli.py fix(gateway): harden Docker/container gateway pathway 2026-04-12 16:36:11 -07:00
test_copilot_auth.py fix: remove 115 verified dead code symbols across 46 production files 2026-04-10 03:44:43 -07:00
test_cron.py feat: add multi-skill cron editing and docs 2026-03-14 19:18:10 -07:00
test_custom_provider_model_switch.py fix: three provider-related bugs (#8161, #8181, #8147) (#8243) 2026-04-12 01:44:18 -07:00
test_debug.py fix: /debug privacy — auto-delete pastes after 1 hour, add privacy notices (#10510) 2026-04-15 13:40:27 -07:00
test_deprecated_cwd_warning.py fix: enforce config.yaml as sole CWD source + deprecate .env CWD vars + add hermes memory reset (#11029) 2026-04-16 06:48:33 -07:00
test_doctor.py fix(doctor): skip health check for OpenCode Go (no shared /models endpoint) 2026-04-15 15:05:32 -07:00
test_doctor_command_install.py feat(doctor): add Command Installation check for hermes bin symlink 2026-04-14 23:13:11 -07:00
test_env_loader.py fix(config): reload .env over stale shell overrides 2026-03-15 06:46:28 -07:00
test_env_sanitize_on_load.py fix: follow-up for salvaged PR #8939 2026-04-13 04:35:37 -07:00
test_gateway.py fix: add all_profiles param + narrow exception handling 2026-04-11 14:44:29 -07:00
test_gateway_linger.py fix(termux): disable gateway service flows on android 2026-04-09 16:24:53 -07:00
test_gateway_runtime_health.py fix(gateway): harden Telegram polling conflict handling 2026-03-14 12:11:23 -07:00
test_gateway_service.py fix(tests): resolve CI test failures — pool auto-seeding, stale assertions, mock isolation 2026-04-15 22:05:21 -07:00
test_gateway_wsl.py feat(gateway): WSL-aware gateway with smart systemd detection (#7510) 2026-04-10 21:15:47 -07:00
test_gemini_provider.py refactor(tests): re-architect tests + fix CI failures (#5946) 2026-04-07 17:19:07 -07:00
test_launcher.py fix: use argparse entrypoint in top-level launcher (#3874) 2026-03-29 21:54:36 -07:00
test_logs.py feat: component-separated logging with session context and filtering (#7991) 2026-04-11 17:23:36 -07:00
test_managed_installs.py chore: prepare Hermes for Homebrew packaging (#4099) 2026-03-30 17:34:43 -07:00
test_mcp_config.py feat: add --env and --preset support to hermes mcp add 2026-04-11 15:34:57 -07:00
test_mcp_tools_config.py feat: interactive MCP tool configuration in hermes tools (#1694) 2026-03-17 03:48:44 -07:00
test_memory_reset.py fix: enforce config.yaml as sole CWD source + deprecate .env CWD vars + add hermes memory reset (#11029) 2026-04-16 06:48:33 -07:00
test_model_normalize.py fix: preserve dots in model names for OpenCode Zen and ZAI providers (#8794) 2026-04-12 21:22:59 -07:00
test_model_provider_persistence.py fix(setup): validate base URL input in hermes model flow (#8264) 2026-04-12 01:51:57 -07:00
test_model_switch_copilot_api_mode.py fix: recompute Copilot api_mode after model switch 2026-04-16 01:16:14 -07:00
test_model_switch_custom_providers.py test: add regression tests for custom_providers multi-model dedup and grouping 2026-04-13 16:41:30 -07:00
test_model_switch_opencode_anthropic.py fix(opencode): strip /v1 from base_url on mid-session /model switch to Anthropic-routed models (#11286) 2026-04-16 19:41:41 -07:00
test_model_switch_variant_tags.py fix(models): preserve OpenRouter variant tags (:free, :extended, :fast) during model switch (#6383) 2026-04-08 19:58:16 -07:00
test_model_validation.py fix(models): add glm-5.1 to opencode-go catalogs 2026-04-16 16:49:22 -07:00
test_models.py refactor: remove dead code — 1,784 lines across 77 files (#9180) 2026-04-13 16:32:04 -07:00
test_non_ascii_credential.py fix: detect and strip non-ASCII characters from API keys (#6843) 2026-04-14 20:20:31 -07:00
test_nous_hermes_non_agentic.py fix(cli): narrow Nous Hermes non-agentic warning to actual hermes-3/-4 models 2026-04-13 04:33:52 -07:00
test_nous_subscription.py feat: ungate Tool Gateway — subscription-based access with per-tool opt-in 2026-04-16 12:36:49 -07:00
test_ollama_cloud_auth.py refactor(tests): re-architect tests + fix CI failures (#5946) 2026-04-07 17:19:07 -07:00
test_ollama_cloud_provider.py fix: wire up Ollama Cloud dynamic model discovery in /model TUI picker 2026-04-16 07:17:45 -07:00
test_opencode_go_in_model_list.py fix(models): add glm-5.1 to opencode-go catalogs 2026-04-16 16:49:22 -07:00
test_overlay_slug_resolution.py fix: resolve overlay provider slug mismatch in /model picker (#7373) 2026-04-10 14:46:57 -07:00
test_path_completion.py feat(cli): add file path autocomplete in the input prompt (#1545) 2026-03-16 06:07:45 -07:00
test_placeholder_usage.py fix: cover remaining config placeholder help text 2026-03-14 10:35:14 -07:00
test_plugin_cli_registration.py refactor: remove dead code — 1,784 lines across 77 files (#9180) 2026-04-13 16:32:04 -07:00
test_plugins.py feat(plugins): add dispatch_tool() to PluginContext (#10763) 2026-04-15 22:23:01 -07:00
test_plugins_cmd.py fix: no auto-activation + unified hermes plugins UI with provider categories 2026-04-10 19:15:50 -07:00
test_profile_export_credentials.py fix: also exclude .env from default profile exports 2026-04-01 11:20:33 -07:00
test_profiles.py fix: improve profile creation UX — seed SOUL.md + credential warning (#8553) 2026-04-12 12:22:34 -07:00
test_reasoning_effort_menu.py fix: normalize reasoning effort ordering in UI 2026-04-09 14:20:16 -07:00
test_runtime_provider_resolution.py fix(config): restore custom providers after v11→v12 migration 2026-04-13 10:50:52 -07:00
test_session_browse.py feat: interactive session browser with search filtering (#718) 2026-03-08 17:42:50 -07:00
test_sessions_delete.py fix(cli): handle EOFError in sessions delete/prune confirmation prompts (#3101) 2026-03-25 18:06:04 -07:00
test_set_config_value.py fix(cli): allow empty strings and falsy values in config set 2026-03-31 11:41:12 -07:00
test_setup.py feat: ungate Tool Gateway — subscription-based access with per-tool opt-in 2026-04-16 12:36:49 -07:00
test_setup_hermes_script.py fix(termux): make setup-hermes use android path 2026-04-09 16:24:53 -07:00
test_setup_matrix_e2ee.py docs(matrix): update all references from matrix-nio to mautrix 2026-04-10 21:15:59 -07:00
test_setup_model_provider.py fix: remove 115 verified dead code symbols across 46 production files 2026-04-10 03:44:43 -07:00
test_setup_noninteractive.py Harden setup provider flows 2026-04-10 02:57:39 -07:00
test_setup_openclaw_migration.py fix: OpenClaw migration now shows dry-run preview before executing (#6769) 2026-04-09 12:15:06 -07:00
test_setup_prompt_menus.py fix(cli): prefer curses over simple_term_menu in setup.py (#1487) 2026-03-15 21:16:21 -07:00
test_skills_config.py fix: respect per-platform disabled skills in Telegram menu and gateway dispatch (#4799) 2026-04-03 10:10:53 -07:00
test_skills_hub.py fix(cli): add ChatConsole.status for /skills search 2026-04-11 15:38:43 -07:00
test_skills_install_flags.py fix: add --yes flag to bypass confirmation in /skills install and uninstall (#1647) 2026-03-17 01:59:07 -07:00
test_skills_skip_confirm.py fix(skills): cache-aware /skills install and uninstall in TUI (#3586) 2026-03-28 14:32:23 -07:00
test_skills_subparser.py fix(cli): resolve duplicate 'skills' subparser crash on Python 3.11+ 2026-03-11 00:50:39 -07:00
test_skin_engine.py fix(cli): handle null/non-dict display config in skin initialization 2026-04-16 06:35:31 -07:00
test_status.py fix(termux): improve status and install UX 2026-04-09 16:24:53 -07:00
test_status_model_provider.py feat: ungate Tool Gateway — subscription-based access with per-tool opt-in 2026-04-16 12:36:49 -07:00
test_subparser_routing_fallback.py fix(cli): defensive subparser routing for argparse bpo-9338 (#10113) 2026-04-14 23:13:02 -07:00
test_subprocess_timeouts.py fix(cli): add missing subprocess.run() timeouts in doctor and status (#4009) 2026-03-30 11:17:15 -07:00
test_terminal_menu_fallbacks.py Harden setup provider flows 2026-04-10 02:57:39 -07:00
test_tips.py refactor: remove dead code — 1,784 lines across 77 files (#9180) 2026-04-13 16:32:04 -07:00
test_tool_token_estimation.py fix(tests): resolve 10 CI failures across hooks, tiktoken, plugins (#3848) 2026-03-29 20:05:59 -07:00
test_tools_config.py feat(image_gen): multi-model FAL support with picker in hermes tools (#11265) 2026-04-16 20:19:53 -07:00
test_tools_disable_enable.py fix: MCP toolset resolution for runtime and config (#3252) 2026-03-26 13:39:41 -07:00
test_update_autostash.py fix(update): always reset on stash conflict — never leave conflict markers (#7010) 2026-04-10 00:32:20 -07:00
test_update_check.py fix: profile paths broken in Docker — profiles go to /root/.hermes instead of mounted volume (#7170) 2026-04-10 05:53:10 -07:00
test_update_gateway_restart.py fix: write update exit code before gateway restart (cgroup kill race) (#8288) 2026-04-12 02:33:21 -07:00
test_user_providers_model_switch.py fix(model): Support providers: dict for custom endpoints in /model 2026-04-13 05:16:21 -07:00
test_web_server.py dashboard: show GATEWAY_HEALTH_URL instead of PID for remote gateways 2026-04-16 16:48:14 -07:00
test_webhook_cli.py feat(webhook): hermes webhook CLI + skill for event-driven subscriptions (#3578) 2026-03-28 14:33:35 -07:00
test_xiaomi_provider.py docs: add Xiaomi MiMo to all provider docs + fix MiMo-V2-Flash ctx len 2026-04-11 11:17:52 -07:00