hermes-bsd/tests/tools
Teknium 3800972dd0
feat(vision): vision_analyze returns pixels to vision-capable models, not aux text (#22955)
When the active main model has native vision and the provider supports
multimodal tool results (Anthropic, OpenAI Chat, Codex Responses, Gemini
3, OpenRouter, Nous), vision_analyze loads the image bytes and returns
them to the model as a multimodal tool-result envelope. The model then
sees the pixels directly on its next turn instead of receiving a lossy
text description from an auxiliary LLM.

Falls back to the legacy aux-LLM text path for non-vision models and
unverified providers.

Mirrors the architecture used in OpenCode, Claude Code, Codex CLI, and
Cline. All four converge on the same pattern: tool results carry image
content blocks for vision-capable provider/model combinations.

Changes
- tools/vision_tools.py: _vision_analyze_native fast path + provider
  capability table (_supports_media_in_tool_results). Schema description
  updated to reflect new behaviour.
- agent/codex_responses_adapter.py: function_call_output.output now
  accepts the array form for multimodal tool results (was string-only).
  Preflight validates input_text/input_image parts.
- agent/auxiliary_client.py: _RUNTIME_MAIN_PROVIDER/_MODEL globals so
  tools see the live CLI/gateway override, not the stale config.yaml
  default. set_runtime_main()/clear_runtime_main() helpers.
- run_agent.py: AIAgent.run_conversation calls set_runtime_main at turn
  start so vision_analyze's fast-path check sees the actual runtime.
- tests/conftest.py: clear runtime-main override between tests.

Tests
- tests/tools/test_vision_native_fast_path.py: provider capability
  table, envelope shape, fast-path gating (vision-capable model uses
  fast path; non-vision model falls through to aux).
- tests/run_agent/test_codex_multimodal_tool_result.py: list tool
  content becomes function_call_output.output array; preflight
  preserves arrays and drops unknown part types.

Live verified
- Opus 4.6 + Sonnet 4.6 on OpenRouter: model calls vision_analyze on a
  typed filepath, gets pixels back, reads exact text from images that
  no aux description could capture (font color irony, multi-line
  fruit-count list, etc.).

PR replaces the closed prior efforts (#16506 shipped the inbound user-
attached path; this PR closes the gap for tool-discovered images).
2026-05-09 21:06:19 -07:00
..
__init__.py
test_accretion_caps.py
test_ansi_strip.py
test_approval.py
test_approval_heartbeat.py test: remove 50 stale/broken tests to unblock CI (#22098) 2026-05-08 14:55:40 -07:00
test_approval_plugin_hooks.py test: remove 50 stale/broken tests to unblock CI (#22098) 2026-05-08 14:55:40 -07:00
test_base_environment.py
test_browser_camofox.py
test_browser_camofox_persistence.py
test_browser_camofox_state.py
test_browser_cdp_override.py
test_browser_cdp_tool.py
test_browser_chromium_check.py test: remove 50 stale/broken tests to unblock CI (#22098) 2026-05-08 14:55:40 -07:00
test_browser_cleanup.py
test_browser_cloud_fallback.py
test_browser_cloud_provider_cache.py fix(browser_tool): fall through to autodetect on config read failure 2026-05-09 13:35:39 -07:00
test_browser_console.py
test_browser_content_none_guard.py
test_browser_hardening.py
test_browser_homebrew_paths.py
test_browser_hybrid_routing.py
test_browser_lightpanda.py
test_browser_orphan_reaper.py test: migrate stale os.kill monkeypatches to gateway.status._pid_exists 2026-05-08 14:27:40 -07:00
test_browser_secret_exfil.py
test_browser_ssrf_local.py
test_browser_supervisor.py
test_browser_supervisor_healthcheck.py
test_budget_config.py
test_checkpoint_manager.py fix(checkpoint): guard _touch_project against non-dict project metadata 2026-05-09 17:53:13 -07:00
test_clarify_tool.py
test_clipboard.py
test_code_execution.py fix(windows): enable execute_code — stale AF_UNIX gate was blocking the tool 2026-05-08 14:27:40 -07:00
test_code_execution_modes.py tests: skip POSIX-venv-layout tests on Windows 2026-05-08 14:27:40 -07:00
test_code_execution_windows_env.py execute_code: set PYTHONIOENCODING=utf-8 + PYTHONUTF8=1 in child env 2026-05-08 14:27:40 -07:00
test_command_guards.py test: remove 50 stale/broken tests to unblock CI (#22098) 2026-05-08 14:55:40 -07:00
test_computer_use.py
test_config_null_guard.py
test_credential_files.py
test_credential_pool_env_fallback.py test: remove 50 stale/broken tests to unblock CI (#22098) 2026-05-08 14:55:40 -07:00
test_cron_approval_mode.py
test_cron_prompt_injection.py
test_cronjob_tools.py fix(cron): allow quoted URL in github auth-header allowlist 2026-05-09 11:11:45 -07:00
test_daytona_environment.py test: remove 50 stale/broken tests to unblock CI (#22098) 2026-05-08 14:55:40 -07:00
test_debug_helpers.py
test_delegate.py fix(delegate): add explicit do-not-use guidance to acp_command/acp_args schema (carve-out of #22680) 2026-05-09 13:37:30 -07:00
test_delegate_composite_toolsets.py
test_delegate_subagent_timeout_diagnostic.py
test_delegate_toolset_scope.py
test_discord_tool.py
test_docker_environment.py
test_docker_find.py
test_dockerfile_node_modules_perms.py
test_dockerfile_pid1_reaping.py
test_env_passthrough.py
test_feishu_tools.py
test_file_operations.py
test_file_operations_edge_cases.py
test_file_ops_cwd_tracking.py
test_file_read_guards.py
test_file_staleness.py
test_file_state_registry.py
test_file_sync.py
test_file_sync_back.py fix: move pytest.importorskip below pytest import in skip-guarded tests 2026-05-09 11:12:03 -07:00
test_file_sync_perf.py
test_file_tools.py test(patch-tool): collapse 9 schema-shape tests into 2 invariants 2026-05-08 16:59:24 -07:00
test_file_tools_container_config.py
test_file_tools_live.py
test_file_write_safety.py
test_force_dangerous_override.py
test_fuzzy_match.py
test_hardline_blocklist.py
test_heartbeat_stale_thresholds.py
test_hidden_dir_filter.py
test_homeassistant_tool.py
test_image_generation.py
test_image_generation_env.py
test_image_generation_plugin_dispatch.py
test_init_session_cwd_respect.py
test_interrupt.py
test_kanban_tools.py test(kanban): cover kanban_comment author hardening + cross-task policy 2026-05-09 02:32:16 -07:00
test_llm_content_none_guard.py
test_local_background_child_hang.py
test_local_env_blocklist.py
test_local_env_cwd_recovery.py
test_local_interrupt_cleanup.py
test_local_shell_init.py
test_local_tempdir.py
test_managed_browserbase_and_modal.py
test_managed_media_gateways.py
test_managed_modal_environment.py
test_managed_server_tool_support.py
test_managed_tool_gateway.py
test_mcp_cancelled_error_propagation.py
test_mcp_circuit_breaker.py
test_mcp_dynamic_discovery.py
test_mcp_empty_error_message.py
test_mcp_image_content.py
test_mcp_oauth.py
test_mcp_oauth_bidirectional.py
test_mcp_oauth_cold_load_expiry.py
test_mcp_oauth_integration.py
test_mcp_oauth_manager.py
test_mcp_oauth_metadata.py
test_mcp_probe.py
test_mcp_reconnect_signal.py
test_mcp_sse_transport.py
test_mcp_stability.py test: migrate stale os.kill monkeypatches to gateway.status._pid_exists 2026-05-08 14:27:40 -07:00
test_mcp_structured_content.py
test_mcp_tool.py
test_mcp_tool_401_handling.py
test_mcp_tool_issue_948.py
test_mcp_tool_session_expired.py
test_mcp_utility_capability_gating.py
test_memory_tool.py
test_memory_tool_import_fallback.py
test_memory_tool_schema.py
test_microsoft_graph_auth.py
test_microsoft_graph_client.py
test_mixture_of_agents_tool.py
test_modal_bulk_upload.py
test_modal_sandbox_fixes.py
test_modal_snapshot_isolation.py
test_notify_on_complete.py
test_osv_check.py
test_parse_env_var.py
test_patch_parser.py
test_process_registry.py fix(process_registry): kill orphaned Popen on post-spawn setup failure 2026-05-09 17:53:24 -07:00
test_read_loop_detection.py
test_registry.py
test_resolve_path.py
test_rl_training_tool.py
test_schema_sanitizer.py
test_search_hidden_dirs.py
test_send_message_missing_platforms.py
test_send_message_tool.py feat(plugins): add standalone_sender_fn for out-of-process cron delivery 2026-05-09 02:56:29 -07:00
test_session_search.py fix: make session search initialize session db 2026-05-09 14:36:58 -07:00
test_shared_container_task_id.py
test_signal_media.py
test_singularity_preflight.py
test_skill_env_passthrough.py
test_skill_improvements.py
test_skill_manager_tool.py
test_skill_provenance.py test: remove 50 stale/broken tests to unblock CI (#22098) 2026-05-08 14:55:40 -07:00
test_skill_size_limits.py
test_skill_usage.py
test_skill_view_path_check.py
test_skill_view_traversal.py
test_skills_guard.py
test_skills_hub.py fix(skills-hub): cover remaining SSRF fetch paths after #10029 2026-05-09 17:52:12 -07:00
test_skills_hub_clawhub.py fix(skills-hub): cover remaining SSRF fetch paths after #10029 2026-05-09 17:52:12 -07:00
test_skills_sync.py
test_skills_tool.py
test_slash_confirm.py
test_spotify_client.py
test_ssh_bulk_upload.py
test_ssh_environment.py
test_symlink_prefix_confusion.py
test_sync_back_backends.py
test_terminal_compound_background.py
test_terminal_config_env_sync.py fix(terminal): bridge docker_env config to TERMINAL_DOCKER_ENV 2026-05-09 17:53:35 -07:00
test_terminal_exit_semantics.py
test_terminal_foreground_timeout_cap.py
test_terminal_none_command_guard.py
test_terminal_output_transform_hook.py
test_terminal_requirements.py
test_terminal_task_cwd.py fix(acp): honor task cwd for foreground terminal commands 2026-05-09 14:46:34 -07:00
test_terminal_timeout_output.py
test_terminal_tool.py
test_terminal_tool_pty_fallback.py
test_terminal_tool_requirements.py
test_threaded_process_handle.py
test_tirith_security.py
test_todo_tool.py
test_tool_backend_helpers.py
test_tool_call_parsers.py
test_tool_output_limits.py
test_tool_result_storage.py fix(tool-result-storage): persist via stdin to bypass 128 KB exec-arg cap (#22913) 2026-05-09 18:44:58 -07:00
test_transcription.py
test_transcription_dotenv_fallback.py
test_transcription_tools.py
test_tts_command_providers.py
test_tts_dotenv_fallback.py
test_tts_gemini.py
test_tts_kittentts.py
test_tts_max_text_length.py
test_tts_mistral.py
test_tts_piper.py
test_tts_speed.py
test_url_safety.py
test_vercel_sandbox_environment.py test: remove 50 stale/broken tests to unblock CI (#22098) 2026-05-08 14:55:40 -07:00
test_video_analyze.py
test_vision_native_fast_path.py feat(vision): vision_analyze returns pixels to vision-capable models, not aux text (#22955) 2026-05-09 21:06:19 -07:00
test_vision_tools.py
test_voice_cli_integration.py
test_voice_mode.py
test_watch_patterns.py
test_web_providers.py
test_web_providers_brave_free.py
test_web_providers_ddgs.py
test_web_providers_searxng.py
test_web_tools_config.py
test_web_tools_tavily.py
test_website_policy.py
test_windows_compat.py
test_windows_native_support.py test: migrate stale os.kill monkeypatches to gateway.status._pid_exists 2026-05-08 14:27:40 -07:00
test_write_deny.py
test_yolo_mode.py
test_zombie_process_cleanup.py