SYMBOL INDEX (11130 symbols across 497 files) FILE: acp_adapter/auth.py function detect_provider (line 8) | def detect_provider() -> Optional[str]: function has_provider (line 22) | def has_provider() -> bool: FILE: acp_adapter/entry.py function _setup_logging (line 23) | def _setup_logging() -> None: function _load_env (line 43) | def _load_env() -> None: function main (line 58) | def main() -> None: FILE: acp_adapter/events.py function _send_update (line 27) | def _send_update( function make_tool_progress_cb (line 47) | def make_tool_progress_cb( function make_thinking_cb (line 93) | def make_thinking_cb( function make_step_cb (line 113) | def make_step_cb( function make_message_cb (line 158) | def make_message_cb( FILE: acp_adapter/permissions.py function make_approval_callback (line 29) | def make_approval_callback( FILE: acp_adapter/server.py function _extract_text (line 58) | def _extract_text( class HermesACPAgent (line 78) | class HermesACPAgent(acp.Agent): method __init__ (line 81) | def __init__(self, session_manager: SessionManager | None = None): method on_connect (line 88) | def on_connect(self, conn: acp.Client) -> None: method initialize (line 95) | async def initialize( method authenticate (line 128) | async def authenticate(self, method_id: str, **kwargs: Any) -> Authent... method new_session (line 135) | async def new_session( method load_session (line 145) | async def load_session( method resume_session (line 159) | async def resume_session( method cancel (line 173) | async def cancel(self, session_id: str, **kwargs: Any) -> None: method fork_session (line 184) | async def fork_session( method list_sessions (line 196) | async def list_sessions( method prompt (line 211) | async def prompt( method _handle_slash_command (line 341) | def _handle_slash_command(self, text: str, state: SessionState) -> str... method _cmd_help (line 370) | def _cmd_help(self, args: str, state: SessionState) -> str: method _cmd_model (line 378) | def _cmd_model(self, args: str, state: SessionState) -> str: method _cmd_tools (line 410) | def _cmd_tools(self, args: str, state: SessionState) -> str: method _cmd_context (line 429) | def _cmd_context(self, args: str, state: SessionState) -> str: method _cmd_reset (line 448) | def _cmd_reset(self, args: str, state: SessionState) -> str: method _cmd_compact (line 453) | def _cmd_compact(self, args: str, state: SessionState) -> str: method _cmd_version (line 466) | def _cmd_version(self, args: str, state: SessionState) -> str: method set_session_model (line 471) | async def set_session_model( FILE: acp_adapter/session.py function _register_task_cwd (line 22) | def _register_task_cwd(task_id: str, cwd: str) -> None: function _clear_task_cwd (line 33) | def _clear_task_cwd(task_id: str) -> None: class SessionState (line 45) | class SessionState: class SessionManager (line 56) | class SessionManager: method __init__ (line 64) | def __init__(self, agent_factory=None, db=None): method create_session (line 80) | def create_session(self, cwd: str = ".") -> SessionState: method get_session (line 100) | def get_session(self, session_id: str) -> Optional[SessionState]: method remove_session (line 113) | def remove_session(self, session_id: str) -> bool: method fork_session (line 122) | def fork_session(self, session_id: str, cwd: str = ".") -> Optional[Se... method list_sessions (line 151) | def list_sessions(self) -> List[Dict[str, Any]]: method update_cwd (line 194) | def update_cwd(self, session_id: str, cwd: str) -> Optional[SessionSta... method cleanup (line 204) | def cleanup(self) -> None: method save_session (line 224) | def save_session(self, session_id: str) -> None: method _get_db (line 237) | def _get_db(self): method _persist (line 261) | def _persist(self, state: SessionState) -> None: method _restore (line 311) | def _restore(self, session_id: str) -> Optional[SessionState]: method _delete_persisted (line 370) | def _delete_persisted(self, session_id: str) -> bool: method _make_agent (line 383) | def _make_agent( FILE: acp_adapter/tools.py function get_tool_kind (line 54) | def get_tool_kind(tool_name: str) -> ToolKind: function make_tool_call_id (line 59) | def make_tool_call_id() -> str: function build_tool_title (line 64) | def build_tool_title(tool_name: str, args: Dict[str, Any]) -> str: function build_tool_start (line 105) | def build_tool_start( function build_tool_complete (line 178) | def build_tool_complete( function extract_locations (line 206) | def extract_locations( FILE: agent/anthropic_adapter.py function _supports_adaptive_thinking (line 37) | def _supports_adaptive_thinking(model: str) -> bool: function _detect_claude_code_version (line 62) | def _detect_claude_code_version() -> str: function _is_oauth_token (line 92) | def _is_oauth_token(key: str) -> bool: function build_anthropic_client (line 107) | def build_anthropic_client(api_key: str, base_url: str = None): function read_claude_code_credentials (line 145) | def read_claude_code_credentials() -> Optional[Dict[str, Any]]: function read_claude_managed_key (line 175) | def read_claude_managed_key() -> Optional[str]: function is_claude_code_token_valid (line 189) | def is_claude_code_token_valid(creds: Dict[str, Any]) -> bool: function _refresh_oauth_token (line 204) | def _refresh_oauth_token(creds: Dict[str, Any]) -> Optional[str]: function _write_claude_code_credentials (line 260) | def _write_claude_code_credentials(access_token: str, refresh_token: str... function _resolve_claude_code_token_from_credentials (line 283) | def _resolve_claude_code_token_from_credentials(creds: Optional[Dict[str... function _prefer_refreshable_claude_code_token (line 298) | def _prefer_refreshable_claude_code_token(env_token: str, creds: Optiona... function get_anthropic_token_source (line 320) | def get_anthropic_token_source(token: Optional[str] = None) -> str: function resolve_anthropic_token (line 349) | def resolve_anthropic_token() -> Optional[str]: function run_oauth_setup_token (line 405) | def run_oauth_setup_token() -> Optional[str]: function _generate_pkce (line 456) | def _generate_pkce() -> tuple: function run_hermes_oauth_login (line 469) | def run_hermes_oauth_login() -> Optional[str]: function _save_hermes_oauth_credentials (line 578) | def _save_hermes_oauth_credentials(access_token: str, refresh_token: str... function read_hermes_oauth_credentials (line 593) | def read_hermes_oauth_credentials() -> Optional[Dict[str, Any]]: function refresh_hermes_oauth_token (line 605) | def refresh_hermes_oauth_token() -> Optional[str]: function normalize_model_name (line 659) | def normalize_model_name(model: str) -> str: function _sanitize_tool_id (line 675) | def _sanitize_tool_id(tool_id: str) -> str: function _convert_openai_image_part_to_anthropic (line 688) | def _convert_openai_image_part_to_anthropic(part: Dict[str, Any]) -> Opt... function _convert_user_content_part_to_anthropic (line 721) | def _convert_user_content_part_to_anthropic(part: Any) -> Optional[Dict[... function convert_tools_to_anthropic (line 750) | def convert_tools_to_anthropic(tools: List[Dict]) -> List[Dict]: function _image_source_from_openai_url (line 765) | def _image_source_from_openai_url(url: str) -> Dict[str, str]: function _convert_content_part_to_anthropic (line 787) | def _convert_content_part_to_anthropic(part: Any) -> Optional[Dict[str, ... function _convert_content_to_anthropic (line 812) | def _convert_content_to_anthropic(content: Any) -> Any: function convert_messages_to_anthropic (line 825) | def convert_messages_to_anthropic( function build_anthropic_kwargs (line 1001) | def build_anthropic_kwargs( function normalize_anthropic_response (line 1106) | def normalize_anthropic_response( FILE: agent/auxiliary_client.py function _convert_content_for_responses (line 104) | def _convert_content_for_responses(content: Any) -> Any: class _CodexCompletionsAdapter (line 152) | class _CodexCompletionsAdapter: method __init__ (line 156) | def __init__(self, real_client: OpenAI, model: str): method create (line 160) | def create(self, **kwargs) -> Any: class _CodexChatShim (line 269) | class _CodexChatShim: method __init__ (line 272) | def __init__(self, adapter: _CodexCompletionsAdapter): class CodexAuxiliaryClient (line 276) | class CodexAuxiliaryClient: method __init__ (line 283) | def __init__(self, real_client: OpenAI, model: str): method close (line 290) | def close(self): class _AsyncCodexCompletionsAdapter (line 294) | class _AsyncCodexCompletionsAdapter: method __init__ (line 301) | def __init__(self, sync_adapter: _CodexCompletionsAdapter): method create (line 304) | async def create(self, **kwargs) -> Any: class _AsyncCodexChatShim (line 309) | class _AsyncCodexChatShim: method __init__ (line 310) | def __init__(self, adapter: _AsyncCodexCompletionsAdapter): class AsyncCodexAuxiliaryClient (line 314) | class AsyncCodexAuxiliaryClient: method __init__ (line 317) | def __init__(self, sync_wrapper: "CodexAuxiliaryClient"): class _AnthropicCompletionsAdapter (line 325) | class _AnthropicCompletionsAdapter: method __init__ (line 328) | def __init__(self, real_client: Any, model: str): method create (line 332) | def create(self, **kwargs) -> Any: class _AnthropicChatShim (line 389) | class _AnthropicChatShim: method __init__ (line 390) | def __init__(self, adapter: _AnthropicCompletionsAdapter): class AnthropicAuxiliaryClient (line 394) | class AnthropicAuxiliaryClient: method __init__ (line 397) | def __init__(self, real_client: Any, model: str, api_key: str, base_ur... method close (line 404) | def close(self): class _AsyncAnthropicCompletionsAdapter (line 410) | class _AsyncAnthropicCompletionsAdapter: method __init__ (line 411) | def __init__(self, sync_adapter: _AnthropicCompletionsAdapter): method create (line 414) | async def create(self, **kwargs) -> Any: class _AsyncAnthropicChatShim (line 419) | class _AsyncAnthropicChatShim: method __init__ (line 420) | def __init__(self, adapter: _AsyncAnthropicCompletionsAdapter): class AsyncAnthropicAuxiliaryClient (line 424) | class AsyncAnthropicAuxiliaryClient: method __init__ (line 425) | def __init__(self, sync_wrapper: "AnthropicAuxiliaryClient"): function _read_nous_auth (line 433) | def _read_nous_auth() -> Optional[dict]: function _nous_api_key (line 455) | def _nous_api_key(provider: dict) -> str: function _nous_base_url (line 460) | def _nous_base_url() -> str: function _read_codex_access_token (line 465) | def _read_codex_access_token() -> Optional[str]: function _resolve_api_key_provider (line 480) | def _resolve_api_key_provider() -> Tuple[Optional[OpenAI], Optional[str]]: function _get_auxiliary_provider (line 520) | def _get_auxiliary_provider(task: str = "") -> str: function _get_auxiliary_env_override (line 535) | def _get_auxiliary_env_override(task: str, suffix: str) -> Optional[str]: function _try_openrouter (line 546) | def _try_openrouter() -> Tuple[Optional[OpenAI], Optional[str]]: function _try_nous (line 555) | def _try_nous() -> Tuple[Optional[OpenAI], Optional[str]]: function _read_main_model (line 568) | def _read_main_model() -> str: function _resolve_custom_runtime (line 593) | def _resolve_custom_runtime() -> Tuple[Optional[str], Optional[str]]: function _current_custom_base_url (line 624) | def _current_custom_base_url() -> str: function _try_custom_endpoint (line 629) | def _try_custom_endpoint() -> Tuple[Optional[OpenAI], Optional[str]]: function _try_codex (line 638) | def _try_codex() -> Tuple[Optional[Any], Optional[str]]: function _try_anthropic (line 647) | def _try_anthropic() -> Tuple[Optional[Any], Optional[str]]: function _resolve_forced_provider (line 676) | def _resolve_forced_provider(forced: str) -> Tuple[Optional[OpenAI], Opt... function _resolve_auto (line 710) | def _resolve_auto() -> Tuple[Optional[OpenAI], Optional[str]]: function _to_async_client (line 734) | def _to_async_client(sync_client, model: str): function resolve_provider_client (line 759) | def resolve_provider_client( function get_text_auxiliary_client (line 963) | def get_text_auxiliary_client(task: str = "") -> Tuple[Optional[OpenAI],... function get_async_text_auxiliary_client (line 982) | def get_async_text_auxiliary_client(task: str = ""): function _normalize_vision_provider (line 1008) | def _normalize_vision_provider(provider: Optional[str]) -> str: function _resolve_strict_vision_backend (line 1017) | def _resolve_strict_vision_backend(provider: str) -> Tuple[Optional[Any]... function _strict_vision_backend_available (line 1032) | def _strict_vision_backend_available(provider: str) -> bool: function _preferred_main_vision_provider (line 1036) | def _preferred_main_vision_provider() -> Optional[str]: function get_available_vision_backends (line 1052) | def get_available_vision_backends() -> List[str]: function resolve_vision_provider_client (line 1068) | def resolve_vision_provider_client( function get_vision_auxiliary_client (line 1127) | def get_vision_auxiliary_client() -> Tuple[Optional[OpenAI], Optional[st... function get_async_vision_auxiliary_client (line 1133) | def get_async_vision_auxiliary_client(): function get_auxiliary_extra_body (line 1139) | def get_auxiliary_extra_body() -> dict: function auxiliary_max_tokens_param (line 1148) | def auxiliary_max_tokens_param(value: int) -> dict: function _get_cached_client (line 1183) | def _get_cached_client( function _resolve_task_provider_model (line 1232) | def _resolve_task_provider_model( function _build_call_kwargs (line 1311) | def _build_call_kwargs( function call_llm (line 1357) | def call_llm( function async_call_llm (line 1459) | async def async_call_llm( FILE: agent/context_compressor.py class ContextCompressor (line 31) | class ContextCompressor: method __init__ (line 38) | def __init__( method update_from_response (line 77) | def update_from_response(self, usage: Dict[str, Any]): method should_compress (line 83) | def should_compress(self, prompt_tokens: int = None) -> bool: method should_compress_preflight (line 88) | def should_compress_preflight(self, messages: List[Dict[str, Any]]) ->... method get_status (line 93) | def get_status(self) -> Dict[str, Any]: method _generate_summary (line 103) | def _generate_summary(self, turns_to_summarize: List[Dict[str, Any]]) ... method _with_summary_prefix (line 169) | def _with_summary_prefix(summary: str) -> str: method _get_tool_call_id (line 183) | def _get_tool_call_id(tc) -> str: method _sanitize_tool_pairs (line 189) | def _sanitize_tool_pairs(self, messages: List[Dict[str, Any]]) -> List... method _align_boundary_forward (line 249) | def _align_boundary_forward(self, messages: List[Dict[str, Any]], idx:... method _align_boundary_backward (line 259) | def _align_boundary_backward(self, messages: List[Dict[str, Any]], idx... method compress (line 283) | def compress(self, messages: List[Dict[str, Any]], current_tokens: int... FILE: agent/copilot_acp_client.py function _resolve_command (line 27) | def _resolve_command() -> str: function _resolve_args (line 35) | def _resolve_args() -> list[str]: function _jsonrpc_error (line 42) | def _jsonrpc_error(message_id: Any, code: int, message: str) -> dict[str... function _format_messages_as_prompt (line 53) | def _format_messages_as_prompt(messages: list[dict[str, Any]], model: st... function _render_message_content (line 93) | def _render_message_content(content: Any) -> str: function _ensure_path_within_cwd (line 117) | def _ensure_path_within_cwd(path_text: str, cwd: str) -> Path: class _ACPChatCompletions (line 130) | class _ACPChatCompletions: method __init__ (line 131) | def __init__(self, client: "CopilotACPClient"): method create (line 134) | def create(self, **kwargs: Any) -> Any: class _ACPChatNamespace (line 138) | class _ACPChatNamespace: method __init__ (line 139) | def __init__(self, client: "CopilotACPClient"): class CopilotACPClient (line 143) | class CopilotACPClient: method __init__ (line 146) | def __init__( method close (line 170) | def close(self) -> None: method _create_chat_completion (line 187) | def _create_chat_completion( method _run_prompt (line 221) | def _run_prompt(self, prompt_text: str, *, timeout_seconds: float) -> ... method _handle_server_message (line 363) | def _handle_server_message( FILE: agent/display.py function _get_skin (line 25) | def _get_skin(): function get_skin_faces (line 34) | def get_skin_faces(key: str, default: list) -> list: function get_skin_verbs (line 44) | def get_skin_verbs() -> list: function get_skin_tool_prefix (line 54) | def get_skin_tool_prefix() -> str: function get_tool_emoji (line 62) | def get_tool_emoji(tool_name: str, default: str = "⚡") -> str: function _oneline (line 92) | def _oneline(text: str) -> str: function build_tool_preview (line 97) | def build_tool_preview(tool_name: str, args: dict, max_len: int = 40) ->... class KawaiiSpinner (line 202) | class KawaiiSpinner: method __init__ (line 234) | def __init__(self, message: str = "", spinner_type: str = 'dots'): method _write (line 247) | def _write(self, text: str, end: str = '\n', flush: bool = False): method _animate (line 256) | def _animate(self): method start (line 298) | def start(self): method update_text (line 306) | def update_text(self, new_message: str): method print_above (line 309) | def print_above(self, text: str): method stop (line 327) | def stop(self, final_message: str = None): method __enter__ (line 345) | def __enter__(self): method __exit__ (line 349) | def __exit__(self, exc_type, exc_val, exc_tb): function _detect_tool_failure (line 398) | def _detect_tool_failure(tool_name: str, result: str | None) -> tuple[bo... function get_cute_tool_message (line 435) | def get_cute_tool_message( function honcho_session_url (line 599) | def honcho_session_url(workspace: str, session_name: str) -> str: function _osc8_link (line 610) | def _osc8_link(url: str, text: str) -> str: function honcho_session_line (line 615) | def honcho_session_line(workspace: str, session_name: str) -> str: function write_tty (line 622) | def write_tty(text: str) -> None: function format_context_pressure (line 649) | def format_context_pressure( function format_context_pressure_gateway (line 696) | def format_context_pressure_gateway( FILE: agent/insights.py function _has_known_pricing (line 37) | def _has_known_pricing(model_name: str, provider: str = None, base_url: ... function _get_pricing (line 42) | def _get_pricing(model_name: str) -> Dict[str, float]: function _estimate_cost (line 51) | def _estimate_cost( function _format_duration (line 90) | def _format_duration(seconds: float) -> str: function _bar_chart (line 95) | def _bar_chart(values: List[int], max_width: int = 20) -> List[str]: class InsightsEngine (line 103) | class InsightsEngine: method __init__ (line 111) | def __init__(self, db): method generate (line 121) | def generate(self, days: int = 30, source: str = None) -> Dict[str, Any]: method _get_sessions (line 197) | def _get_sessions(self, cutoff: float, source: str = None) -> List[Dict]: method _get_tool_usage (line 205) | def _get_tool_usage(self, cutoff: float, source: str = None) -> List[D... method _get_message_stats (line 297) | def _get_message_stats(self, cutoff: float, source: str = None) -> Dict: method _compute_overview (line 333) | def _compute_overview(self, sessions: List[Dict], message_stats: Dict)... method _compute_model_breakdown (line 407) | def _compute_model_breakdown(self, sessions: List[Dict]) -> List[Dict]: method _compute_platform_breakdown (line 444) | def _compute_platform_breakdown(self, sessions: List[Dict]) -> List[Di... method _compute_tool_breakdown (line 475) | def _compute_tool_breakdown(self, tool_usage: List[Dict]) -> List[Dict]: method _compute_activity_patterns (line 488) | def _compute_activity_patterns(self, sessions: List[Dict]) -> Dict: method _compute_top_sessions (line 546) | def _compute_top_sessions(self, sessions: List[Dict]) -> List[Dict]: method format_terminal (line 608) | def format_terminal(self, report: Dict) -> str: method format_gateway (line 735) | def format_gateway(self, report: Dict) -> str: FILE: agent/model_metadata.py function _strip_provider_prefix (line 43) | def _strip_provider_prefix(model: str) -> str: function _normalize_base_url (line 141) | def _normalize_base_url(base_url: str) -> str: function _is_openrouter_base_url (line 145) | def _is_openrouter_base_url(base_url: str) -> bool: function _is_custom_endpoint (line 149) | def _is_custom_endpoint(base_url: str) -> bool: function _infer_provider_from_url (line 170) | def _infer_provider_from_url(base_url: str) -> Optional[str]: function _is_known_provider_base_url (line 188) | def _is_known_provider_base_url(base_url: str) -> bool: function is_local_endpoint (line 192) | def is_local_endpoint(base_url: str) -> bool: function detect_local_server_type (line 228) | def detect_local_server_type(base_url: str) -> Optional[str]: function _iter_nested_dicts (line 285) | def _iter_nested_dicts(value: Any): function _coerce_reasonable_int (line 295) | def _coerce_reasonable_int(value: Any, minimum: int = 1024, maximum: int... function _extract_first_int (line 309) | def _extract_first_int(payload: Dict[str, Any], keys: tuple[str, ...]) -... function _extract_context_length (line 321) | def _extract_context_length(payload: Dict[str, Any]) -> Optional[int]: function _extract_max_completion_tokens (line 325) | def _extract_max_completion_tokens(payload: Dict[str, Any]) -> Optional[... function _extract_pricing (line 329) | def _extract_pricing(payload: Dict[str, Any]) -> Dict[str, Any]: function _add_model_aliases (line 352) | def _add_model_aliases(cache: Dict[str, Dict[str, Any]], model_id: str, ... function fetch_model_metadata (line 359) | def fetch_model_metadata(force_refresh: bool = False) -> Dict[str, Dict[... function fetch_endpoint_model_metadata (line 395) | def fetch_endpoint_model_metadata( function _get_context_cache_path (line 483) | def _get_context_cache_path() -> Path: function _load_context_cache (line 489) | def _load_context_cache() -> Dict[str, int]: function save_context_length (line 503) | def save_context_length(model: str, base_url: str, length: int) -> None: function get_cached_context_length (line 524) | def get_cached_context_length(model: str, base_url: str) -> Optional[int]: function get_next_probe_tier (line 531) | def get_next_probe_tier(current_length: int) -> Optional[int]: function parse_context_limit_from_error (line 539) | def parse_context_limit_from_error(error_msg: str) -> Optional[int]: function _model_id_matches (line 567) | def _model_id_matches(candidate_id: str, lookup_model: str) -> bool: function _query_local_context_length (line 586) | def _query_local_context_length(model: str, base_url: str) -> Optional[i... function _normalize_model_version (line 676) | def _normalize_model_version(model: str) -> str: function _query_anthropic_context_length (line 686) | def _query_anthropic_context_length(model: str, base_url: str, api_key: ... function _resolve_nous_context_length (line 717) | def _resolve_nous_context_length(model: str) -> Optional[int]: function get_model_context_length (line 750) | def get_model_context_length( function estimate_tokens_rough (line 875) | def estimate_tokens_rough(text: str) -> int: function estimate_messages_tokens_rough (line 882) | def estimate_messages_tokens_rough(messages: List[Dict[str, Any]]) -> int: FILE: agent/models_dev.py function _get_cache_path (line 47) | def _get_cache_path() -> Path: function _load_disk_cache (line 54) | def _load_disk_cache() -> Dict[str, Any]: function _save_disk_cache (line 66) | def _save_disk_cache(data: Dict[str, Any]) -> None: function fetch_models_dev (line 77) | def fetch_models_dev(force_refresh: bool = False) -> Dict[str, Any]: function lookup_models_dev_context (line 121) | def lookup_models_dev_context(provider: str, model: str) -> Optional[int]: function _extract_context (line 158) | def _extract_context(entry: Dict[str, Any]) -> Optional[int]: FILE: agent/prompt_builder.py function _scan_context_content (line 39) | def _scan_context_content(content: str, filename: str) -> str: function _find_git_root (line 60) | def _find_git_root(start: Path) -> Optional[Path]: function _find_hermes_md (line 76) | def _find_hermes_md(cwd: Path) -> Optional[Path]: function _strip_yaml_frontmatter (line 97) | def _strip_yaml_frontmatter(content: str) -> str: function _parse_skill_file (line 235) | def _parse_skill_file(skill_file: Path) -> tuple[bool, dict, str]: function _read_skill_conditions (line 263) | def _read_skill_conditions(skill_file: Path) -> dict: function _skill_should_show (line 281) | def _skill_should_show( function build_skills_system_prompt (line 312) | def build_skills_system_prompt( function _truncate_content (line 420) | def _truncate_content(content: str, filename: str, max_chars: int = CONT... function load_soul_md (line 432) | def load_soul_md() -> Optional[str]: function build_context_files_prompt (line 460) | def build_context_files_prompt(cwd: Optional[str] = None, skip_soul: boo... FILE: agent/prompt_caching.py function _apply_cache_marker (line 15) | def _apply_cache_marker(msg: dict, cache_marker: dict) -> None: function apply_anthropic_cache_control (line 40) | def apply_anthropic_cache_control( FILE: agent/redact.py function _mask_token (line 90) | def _mask_token(token: str) -> str: function redact_sensitive_text (line 97) | def redact_sensitive_text(text: str) -> str: class RedactingFormatter (line 153) | class RedactingFormatter(logging.Formatter): method __init__ (line 156) | def __init__(self, fmt=None, datefmt=None, style='%', **kwargs): method format (line 159) | def format(self, record: logging.LogRecord) -> str: FILE: agent/skill_commands.py function build_plan_path (line 21) | def build_plan_path( function _load_skill_payload (line 42) | def _load_skill_payload(skill_identifier: str, task_id: str | None = Non... function _build_skill_message (line 79) | def _build_skill_message( function scan_skill_commands (line 151) | def scan_skill_commands() -> Dict[str, Dict[str, Any]]: function get_skill_commands (line 198) | def get_skill_commands() -> Dict[str, Dict[str, Any]]: function build_skill_invocation_message (line 205) | def build_skill_invocation_message( function build_preloaded_skills_prompt (line 243) | def build_preloaded_skills_prompt( FILE: agent/smart_model_routing.py function _coerce_bool (line 49) | def _coerce_bool(value: Any, default: bool = False) -> bool: function _coerce_int (line 59) | def _coerce_int(value: Any, default: int) -> int: function choose_cheap_model_route (line 66) | def choose_cheap_model_route(user_message: str, routing_config: Optional... function resolve_turn_route (line 114) | def resolve_turn_route(user_message: str, routing_config: Optional[Dict[... FILE: agent/title_generator.py function generate_title (line 22) | def generate_title(user_message: str, assistant_response: str, timeout: ... function auto_title_session (line 59) | def auto_title_session( function maybe_auto_title (line 95) | def maybe_auto_title( FILE: agent/trajectory.py function convert_scratchpad_to_think (line 16) | def convert_scratchpad_to_think(content: str) -> str: function has_incomplete_scratchpad (line 23) | def has_incomplete_scratchpad(content: str) -> bool: function save_trajectory (line 30) | def save_trajectory(trajectory: List[Dict[str, Any]], model: str, FILE: agent/usage_pricing.py class CanonicalUsage (line 28) | class CanonicalUsage: method prompt_tokens (line 38) | def prompt_tokens(self) -> int: method total_tokens (line 42) | def total_tokens(self) -> int: class BillingRoute (line 47) | class BillingRoute: class PricingEntry (line 55) | class PricingEntry: class CostResult (line 68) | class CostResult: function _to_decimal (line 290) | def _to_decimal(value: Any) -> Optional[Decimal]: function _to_int (line 299) | def _to_int(value: Any) -> int: function resolve_billing_route (line 306) | def resolve_billing_route( function _lookup_official_docs_pricing (line 333) | def _lookup_official_docs_pricing(route: BillingRoute) -> Optional[Prici... function _openrouter_pricing_entry (line 337) | def _openrouter_pricing_entry(route: BillingRoute) -> Optional[PricingEn... function _pricing_entry_from_metadata (line 346) | def _pricing_entry_from_metadata( function get_pricing_entry (line 390) | def get_pricing_entry( function normalize_usage (line 420) | def normalize_usage( function estimate_usage_cost (line 481) | def estimate_usage_cost( function has_known_pricing (line 560) | def has_known_pricing( function get_pricing (line 578) | def get_pricing( function estimate_cost_usd (line 598) | def estimate_cost_usd( function format_duration_compact (line 622) | def format_duration_compact(seconds: float) -> str: function format_token_count_compact (line 636) | def format_token_count_compact(value: int) -> str: FILE: batch_runner.py function _normalize_tool_stats (line 58) | def _normalize_tool_stats(tool_stats: Dict[str, Dict[str, int]]) -> Dict... function _normalize_tool_error_counts (line 88) | def _normalize_tool_error_counts(tool_error_counts: Dict[str, int]) -> D... function _extract_tool_stats (line 112) | def _extract_tool_stats(messages: List[Dict[str, Any]]) -> Dict[str, Dic... function _extract_reasoning_stats (line 194) | def _extract_reasoning_stats(messages: List[Dict[str, Any]]) -> Dict[str... function _process_single_prompt (line 230) | def _process_single_prompt( function _process_batch_worker (line 385) | def _process_batch_worker(args: Tuple) -> Dict[str, Any]: class BatchRunner (line 511) | class BatchRunner: method __init__ (line 516) | def __init__( method _load_dataset (line 621) | def _load_dataset(self) -> List[Dict[str, Any]]: method _create_batches (line 653) | def _create_batches(self) -> List[List[Tuple[int, Dict[str, Any]]]]: method _load_checkpoint (line 667) | def _load_checkpoint(self) -> Dict[str, Any]: method _save_checkpoint (line 694) | def _save_checkpoint(self, checkpoint_data: Dict[str, Any], lock: Opti... method _scan_completed_prompts_by_content (line 711) | def _scan_completed_prompts_by_content(self) -> set: method _filter_dataset_by_completed (line 755) | def _filter_dataset_by_completed(self, completed_prompts: set) -> Tupl... method run (line 789) | def run(self, resume: bool = False): function main (line 1110) | def main( FILE: cli.py function _load_prefill_messages (line 88) | def _load_prefill_messages(file_path: str) -> List[Dict[str, Any]]: function _parse_reasoning_config (line 117) | def _parse_reasoning_config(effort: str) -> dict | None: function load_cli_config (line 135) | def load_cli_config() -> Dict[str, Any]: function _run_cleanup (line 483) | def _run_cleanup(): function _git_repo_root (line 512) | def _git_repo_root() -> Optional[str]: function _path_is_within_root (line 527) | def _path_is_within_root(path: Path, root: Path) -> bool: function _setup_worktree (line 536) | def _setup_worktree(repo_root: str = None) -> Optional[Dict[str, str]]: function _cleanup_worktree (line 635) | def _cleanup_worktree(info: Dict[str, str] = None) -> None: function _prune_stale_worktrees (line 692) | def _prune_stale_worktrees(repo_root: str, max_age_hours: int = 24) -> N... function _accent_hex (line 768) | def _accent_hex() -> str: function _rich_text_from_ansi (line 777) | def _rich_text_from_ansi(text: str) -> _RichText: function _cprint (line 786) | def _cprint(text: str): class ChatConsole (line 796) | class ChatConsole: method __init__ (line 805) | def __init__(self): method print (line 815) | def print(self, *args, **kwargs): function _build_compact_banner (line 860) | def _build_compact_banner() -> str: function _parse_skills_argument (line 896) | def _parse_skills_argument(skills: str | list[str] | tuple[str, ...] | N... function save_config_value (line 920) | def save_config_value(key_path: str, value: any) -> bool: class HermesCLI (line 982) | class HermesCLI: method __init__ (line 990) | def __init__( method _invalidate (line 1237) | def _invalidate(self, min_interval: float = 0.25) -> None: method _status_bar_context_style (line 1245) | def _status_bar_context_style(self, percent_used: Optional[int]) -> str: method _build_context_bar (line 1256) | def _build_context_bar(self, percent_used: Optional[int], width: int =... method _get_status_bar_snapshot (line 1261) | def _get_status_bar_snapshot(self) -> Dict[str, Any]: method _build_status_bar_text (line 1313) | def _build_status_bar_text(self, width: Optional[int] = None) -> str: method _get_status_bar_fragments (line 1341) | def _get_status_bar_fragments(self): method _normalize_model_for_provider (line 1401) | def _normalize_model_for_provider(self, resolved_provider: str) -> bool: method _on_thinking (line 1463) | def _on_thinking(self, text: str) -> None: method _stream_reasoning_delta (line 1470) | def _stream_reasoning_delta(self, text: str) -> None: method _close_reasoning_box (line 1495) | def _close_reasoning_box(self) -> None: method _stream_delta (line 1507) | def _stream_delta(self, text) -> None: method _emit_stream_text (line 1604) | def _emit_stream_text(self, text: str) -> None: method _flush_stream (line 1648) | def _flush_stream(self) -> None: method _reset_stream_state (line 1663) | def _reset_stream_state(self) -> None: method _slow_command_status (line 1674) | def _slow_command_status(self, command: str) -> str: method _command_spinner_frame (line 1693) | def _command_spinner_frame(self) -> str: method _busy_command (line 1701) | def _busy_command(self, status: str): method _ensure_runtime_credentials (line 1714) | def _ensure_runtime_credentials(self) -> bool: method _resolve_turn_agent_config (line 1777) | def _resolve_turn_agent_config(self, user_message: str) -> dict: method _init_agent (line 1795) | def _init_agent(self, *, model_override: str = None, runtime_override:... method show_banner (line 1925) | def show_banner(self): method _preload_resumed_session (line 1972) | def _preload_resumed_session(self) -> bool: method _display_resumed_history (line 2030) | def _display_resumed_history(self): method _try_attach_clipboard_image (line 2181) | def _try_attach_clipboard_image(self) -> bool: method _handle_rollback_command (line 2200) | def _handle_rollback_command(self, command: str): method _resolve_checkpoint_ref (line 2294) | def _resolve_checkpoint_ref(self, ref: str, checkpoints: list) -> str ... method _handle_stop_command (line 2307) | def _handle_stop_command(self): method _handle_paste_command (line 2327) | def _handle_paste_command(self): method _preprocess_images_with_vision (line 2344) | def _preprocess_images_with_vision(self, text: str, images: list) -> str: method _show_tool_availability_warnings (line 2407) | def _show_tool_availability_warnings(self): method _show_status (line 2429) | def _show_status(self): method show_help (line 2461) | def show_help(self): method show_tools (line 2494) | def show_tools(self): method _handle_tools_command (line 2536) | def _handle_tools_command(self, cmd: str): method show_toolsets (line 2598) | def show_toolsets(self): method show_config (line 2629) | def show_config(self): method show_history (line 2679) | def show_history(self): method new_session (line 2745) | def new_session(self, silent=False): method reset_conversation (line 2800) | def reset_conversation(self): method save_conversation (line 2804) | def save_conversation(self): method retry_last (line 2824) | def retry_last(self): method undo_last (line 2853) | def undo_last(self): method _show_model_and_providers (line 2885) | def _show_model_and_providers(self): method _handle_prompt_command (line 2959) | def _handle_prompt_command(self, cmd: str): method _resolve_personality_prompt (line 3015) | def _resolve_personality_prompt(value) -> str: method _handle_personality_command (line 3026) | def _handle_personality_command(self, cmd: str): method _handle_cron_command (line 3071) | def _handle_cron_command(self, cmd: str): method _handle_skills_command (line 3316) | def _handle_skills_command(self, cmd: str): method _show_gateway_status (line 3321) | def _show_gateway_status(self): method process_command (line 3378) | def process_command(self, command: str) -> bool: method _handle_plan_command (line 3812) | def _handle_plan_command(self, cmd: str): method _handle_background_command (line 3838) | def _handle_background_command(self, cmd: str): method _try_launch_chrome_debug (line 3953) | def _try_launch_chrome_debug(port: int, system: str) -> bool: method _handle_browser_command (line 3995) | def _handle_browser_command(self, cmd: str): method _handle_skin_command (line 4156) | def _handle_skin_command(self, cmd: str): method _toggle_verbose (line 4195) | def _toggle_verbose(self): method _handle_reasoning_command (line 4222) | def _handle_reasoning_command(self, cmd: str): method _on_reasoning (line 4283) | def _on_reasoning(self, reasoning_text: str): method _manual_compress (line 4297) | def _manual_compress(self): method _show_usage (line 4338) | def _show_usage(self): method _show_insights (line 4416) | def _show_insights(self, command: str = "/insights"): method _check_config_mcp_changes (line 4449) | def _check_config_mcp_changes(self) -> None: method _reload_mcp (line 4499) | def _reload_mcp(self): method _on_tool_progress (line 4589) | def _on_tool_progress(self, function_name: str, preview: str, function... method _voice_start_recording (line 4623) | def _voice_start_recording(self): method _voice_stop_and_transcribe (line 4702) | def _voice_stop_and_transcribe(self): method _voice_speak_response (line 4798) | def _voice_speak_response(self, text: str): method _handle_voice_command (line 4852) | def _handle_voice_command(self, command: str): method _enable_voice_mode (line 4875) | def _enable_voice_mode(self): method _disable_voice_mode (line 4931) | def _disable_voice_mode(self): method _toggle_voice_tts (line 4963) | def _toggle_voice_tts(self): method _show_voice_status (line 4980) | def _show_voice_status(self): method _clarify_callback (line 4998) | def _clarify_callback(self, question, choices): method _sudo_password_callback (line 5065) | def _sudo_password_callback(self) -> str: method _approval_callback (line 5108) | def _approval_callback(self, command: str, description: str, method _approval_choices (line 5163) | def _approval_choices(self, command: str, *, allow_permanent: bool = T... method _handle_approval_selection (line 5170) | def _handle_approval_selection(self) -> None: method _get_approval_display_fragments (line 5194) | def _get_approval_display_fragments(self): method _secret_capture_callback (line 5273) | def _secret_capture_callback(self, var_name: str, prompt: str, metadat... method _submit_secret_response (line 5276) | def _submit_secret_response(self, value: str) -> None: method _cancel_secret_capture (line 5284) | def _cancel_secret_capture(self) -> None: method _clear_secret_input_buffer (line 5287) | def _clear_secret_input_buffer(self) -> None: method _clear_current_input (line 5294) | def _clear_current_input(self) -> None: method chat (line 5302) | def chat(self, message, images: list = None) -> Optional[str]: method _print_exit_summary (line 5658) | def _print_exit_summary(self): method _get_tui_prompt_symbols (line 5689) | def _get_tui_prompt_symbols(self) -> tuple[str, str]: method _audio_level_bar (line 5716) | def _audio_level_bar(self) -> str: method _get_tui_prompt_fragments (line 5728) | def _get_tui_prompt_fragments(self): method _get_tui_prompt_text (line 5754) | def _get_tui_prompt_text(self) -> str: method _build_tui_style_dict (line 5758) | def _build_tui_style_dict(self) -> dict[str, str]: method _apply_tui_skin_style (line 5768) | def _apply_tui_skin_style(self) -> bool: method run (line 5776) | def run(self): function main (line 6997) | def main( FILE: cron/jobs.py function _normalize_skill_list (line 40) | def _normalize_skill_list(skill: Optional[str] = None, skills: Optional[... function _apply_skill_fields (line 57) | def _apply_skill_fields(job: Dict[str, Any]) -> Dict[str, Any]: function _secure_dir (line 66) | def _secure_dir(path: Path): function _secure_file (line 74) | def _secure_file(path: Path): function ensure_dirs (line 83) | def ensure_dirs(): function parse_duration (line 95) | def parse_duration(s: str) -> int: function parse_schedule (line 116) | def parse_schedule(schedule: str) -> Dict[str, Any]: function _ensure_aware (line 205) | def _ensure_aware(dt: datetime) -> datetime: function _recoverable_oneshot_run_at (line 224) | def _recoverable_oneshot_run_at( function compute_next_run (line 251) | def compute_next_run(schedule: Dict[str, Any], last_run_at: Optional[str... function load_jobs (line 287) | def load_jobs() -> List[Dict[str, Any]]: function save_jobs (line 301) | def save_jobs(jobs: List[Dict[str, Any]]): function create_job (line 320) | def create_job( function get_job (line 410) | def get_job(job_id: str) -> Optional[Dict[str, Any]]: function list_jobs (line 419) | def list_jobs(include_disabled: bool = False) -> List[Dict[str, Any]]: function update_job (line 427) | def update_job(job_id: str, updates: Dict[str, Any]) -> Optional[Dict[st... function pause_job (line 460) | def pause_job(job_id: str, reason: Optional[str] = None) -> Optional[Dic... function resume_job (line 473) | def resume_job(job_id: str) -> Optional[Dict[str, Any]]: function trigger_job (line 492) | def trigger_job(job_id: str) -> Optional[Dict[str, Any]]: function remove_job (line 509) | def remove_job(job_id: str) -> bool: function mark_job_run (line 520) | def mark_job_run(job_id: str, success: bool, error: Optional[str] = None): function get_due_jobs (line 564) | def get_due_jobs() -> List[Dict[str, Any]]: function save_job_output (line 641) | def save_job_output(job_id: str, output: str): FILE: cron/scheduler.py function _resolve_origin (line 53) | def _resolve_origin(job: dict) -> Optional[dict]: function _resolve_delivery_target (line 65) | def _resolve_delivery_target(job: dict) -> Optional[dict]: function _deliver_result (line 109) | def _deliver_result(job: dict, content: str) -> None: function _build_job_prompt (line 188) | def _build_job_prompt(job: dict) -> str: function run_job (line 248) | def run_job(job: dict) -> tuple[bool, str, str, Optional[str]]: function tick (line 471) | def tick(verbose: bool = True) -> int: FILE: environments/agent_loop.py function resize_tool_pool (line 34) | def resize_tool_pool(max_workers: int): class ToolError (line 51) | class ToolError: class AgentResult (line 62) | class AgentResult: function _extract_reasoning_from_message (line 79) | def _extract_reasoning_from_message(message) -> Optional[str]: class HermesAgentLoop (line 117) | class HermesAgentLoop: method __init__ (line 131) | def __init__( method run (line 167) | async def run(self, messages: List[Dict[str, Any]]) -> AgentResult: method _get_managed_state (line 491) | def _get_managed_state(self) -> Optional[Dict[str, Any]]: FILE: environments/agentic_opd_env.py function _build_hint_judge_messages (line 248) | def _build_hint_judge_messages( function _parse_hint_result (line 263) | def _parse_hint_result(text: str) -> tuple[int | None, str]: function _select_best_hint (line 274) | def _select_best_hint(votes: list[dict]) -> dict | None: function _append_hint_to_messages (line 288) | def _append_hint_to_messages(messages: list[dict], hint: str) -> list[di... class AgenticOPDConfig (line 318) | class AgenticOPDConfig(HermesAgentEnvConfig): class AgenticOPDEnv (line 379) | class AgenticOPDEnv(HermesAgentBaseEnv): method config_init (line 398) | def config_init(cls) -> Tuple[AgenticOPDConfig, List[APIServerConfig]]: method __init__ (line 437) | def __init__(self, *args, **kwargs): method setup (line 455) | async def setup(self) -> None: method get_next_item (line 515) | async def get_next_item(self) -> dict: method format_prompt (line 527) | def format_prompt(self, item: dict) -> str: method compute_reward (line 551) | async def compute_reward( method collect_trajectories (line 643) | async def collect_trajectories( method _apply_opd_pipeline (line 671) | async def _apply_opd_pipeline(self, group: ScoredDataGroup) -> None: method _opd_for_sequence (line 727) | async def _opd_for_sequence( method _extract_turn_pairs (line 862) | def _extract_turn_pairs( method _extract_hint (line 929) | async def _extract_hint( method _find_token_span (line 981) | def _find_token_span( method evaluate (line 1008) | async def evaluate(self, *args, **kwargs) -> None: method wandb_log (line 1158) | async def wandb_log(self, wandb_metrics: Optional[Dict] = None) -> None: FILE: environments/benchmarks/tblite/tblite_env.py class TBLiteEvalConfig (line 44) | class TBLiteEvalConfig(TerminalBench2EvalConfig): class TBLiteEvalEnv (line 63) | class TBLiteEvalEnv(TerminalBench2EvalEnv): method config_init (line 75) | def config_init(cls) -> Tuple[TBLiteEvalConfig, List[APIServerConfig]]: FILE: environments/benchmarks/terminalbench_2/terminalbench2_env.py class TerminalBench2EvalConfig (line 76) | class TerminalBench2EvalConfig(HermesAgentEnvConfig): function _extract_base64_tar (line 151) | def _extract_base64_tar(b64_data: str, target_dir: Path): class TerminalBench2EvalEnv (line 165) | class TerminalBench2EvalEnv(HermesAgentBaseEnv): method config_init (line 192) | def config_init(cls) -> Tuple[TerminalBench2EvalConfig, List[APIServer... method setup (line 259) | async def setup(self): method _save_result (line 320) | def _save_result(self, result: Dict[str, Any]): method get_next_item (line 335) | async def get_next_item(self): method format_prompt (line 341) | def format_prompt(self, item: Dict[str, Any]) -> str: method compute_reward (line 345) | async def compute_reward(self, item, result, ctx) -> float: method collect_trajectories (line 349) | async def collect_trajectories(self, item): method score (line 353) | async def score(self, rollout_group_data): method _resolve_task_image (line 361) | def _resolve_task_image( method rollout_and_score_eval (line 411) | async def rollout_and_score_eval(self, eval_item: Dict[str, Any]) -> D... FILE: environments/benchmarks/yc_bench/yc_bench_env.py class YCBenchEvalConfig (line 179) | class YCBenchEvalConfig(HermesAgentEnvConfig): function _read_final_score (line 232) | def _read_final_score(db_path: str) -> Dict[str, Any]: function _compute_composite_score (line 294) | def _compute_composite_score( class YCBenchEvalEnv (line 329) | class YCBenchEvalEnv(HermesAgentBaseEnv): method config_init (line 348) | def config_init(cls) -> Tuple[YCBenchEvalConfig, List[APIServerConfig]]: method setup (line 391) | async def setup(self): method _save_result (line 433) | def _save_result(self, result: Dict[str, Any]): method get_next_item (line 447) | async def get_next_item(self): method format_prompt (line 452) | def format_prompt(self, item: Dict[str, Any]) -> str: method compute_reward (line 469) | async def compute_reward(self, item, result, ctx) -> float: method collect_trajectories (line 472) | async def collect_trajectories(self, item): method score (line 475) | async def score(self, rollout_group_data): method rollout_and_score_eval (line 482) | async def rollout_and_score_eval(self, eval_item: Dict[str, Any]) -> D... method _run_with_timeout (line 625) | async def _run_with_timeout(self, item: Dict[str, Any]) -> Dict: method evaluate (line 654) | async def evaluate(self, *args, **kwargs) -> None: method wandb_log (line 836) | async def wandb_log(self, wandb_metrics: Optional[Dict] = None): FILE: environments/hermes_base_env.py class HermesAgentEnvConfig (line 73) | class HermesAgentEnvConfig(BaseEnvConfig): class HermesAgentBaseEnv (line 180) | class HermesAgentBaseEnv(BaseEnv): method __init__ (line 205) | def __init__( method _resolve_tools_for_group (line 248) | def _resolve_tools_for_group(self) -> Tuple[List[Dict[str, Any]], Set[... method _use_managed_server (line 287) | def _use_managed_server(self) -> bool: method collect_trajectories (line 309) | async def collect_trajectories( method _format_trajectory_for_display (line 335) | def _format_trajectory_for_display(messages: List[Dict[str, Any]]) -> ... method add_rollouts_for_wandb (line 386) | async def add_rollouts_for_wandb( method wandb_log (line 421) | async def wandb_log(self, wandb_metrics: Optional[Dict] = None): method collect_trajectory (line 448) | async def collect_trajectory( method setup (line 607) | async def setup(self): method get_next_item (line 618) | async def get_next_item(self) -> Item: method format_prompt (line 628) | def format_prompt(self, item: Item) -> str: method compute_reward (line 641) | async def compute_reward( method evaluate (line 663) | async def evaluate(self, *args, **kwargs): FILE: environments/hermes_swe_env/hermes_swe_env.py class HermesSweEnvConfig (line 56) | class HermesSweEnvConfig(HermesAgentEnvConfig): class HermesSweEnv (line 62) | class HermesSweEnv(HermesAgentBaseEnv): method config_init (line 77) | def config_init(cls) -> Tuple[HermesSweEnvConfig, List[APIServerConfig]]: method setup (line 124) | async def setup(self): method get_next_item (line 136) | async def get_next_item(self) -> Dict[str, Any]: method format_prompt (line 144) | def format_prompt(self, item: Dict[str, Any]) -> str: method compute_reward (line 160) | async def compute_reward( method evaluate (line 195) | async def evaluate(self, *args, **kwargs): method wandb_log (line 211) | async def wandb_log(self, wandb_metrics: Optional[Dict] = None): FILE: environments/patches.py class _AsyncWorker (line 38) | class _AsyncWorker: method __init__ (line 47) | def __init__(self): method start (line 52) | def start(self): method _run_loop (line 58) | def _run_loop(self): method run_coroutine (line 65) | def run_coroutine(self, coro, timeout=600): method stop (line 77) | def stop(self): function _patch_swerex_modal (line 85) | def _patch_swerex_modal(): function apply_patches (line 190) | def apply_patches(): FILE: environments/terminal_test_env/terminal_test_env.py class TerminalTestEnvConfig (line 85) | class TerminalTestEnvConfig(HermesAgentEnvConfig): class TerminalTestEnv (line 91) | class TerminalTestEnv(HermesAgentBaseEnv): method config_init (line 110) | def config_init(cls) -> Tuple[TerminalTestEnvConfig, List[APIServerCon... method setup (line 159) | async def setup(self): method get_next_item (line 167) | async def get_next_item(self) -> Dict[str, str]: method format_prompt (line 173) | def format_prompt(self, item: Dict[str, str]) -> str: method compute_reward (line 177) | async def compute_reward( method evaluate (line 212) | async def evaluate(self, *args, **kwargs): method wandb_log (line 272) | async def wandb_log(self, wandb_metrics: Optional[Dict] = None): FILE: environments/tool_call_parsers/__init__.py class ToolCallParser (line 35) | class ToolCallParser(ABC): method parse (line 44) | def parse(self, text: str) -> ParseResult: function register_parser (line 65) | def register_parser(name: str): function get_parser (line 82) | def get_parser(name: str) -> ToolCallParser: function list_parsers (line 103) | def list_parsers() -> List[str]: FILE: environments/tool_call_parsers/deepseek_v3_1_parser.py class DeepSeekV31ToolCallParser (line 26) | class DeepSeekV31ToolCallParser(ToolCallParser): method parse (line 42) | def parse(self, text: str) -> ParseResult: FILE: environments/tool_call_parsers/deepseek_v3_parser.py class DeepSeekV3ToolCallParser (line 31) | class DeepSeekV3ToolCallParser(ToolCallParser): method parse (line 49) | def parse(self, text: str) -> ParseResult: FILE: environments/tool_call_parsers/glm45_parser.py function _deserialize_value (line 29) | def _deserialize_value(value: str) -> Any: class Glm45ToolCallParser (line 48) | class Glm45ToolCallParser(ToolCallParser): method parse (line 64) | def parse(self, text: str) -> ParseResult: FILE: environments/tool_call_parsers/glm47_parser.py class Glm47ToolCallParser (line 18) | class Glm47ToolCallParser(Glm45ToolCallParser): method __init__ (line 24) | def __init__(self): FILE: environments/tool_call_parsers/hermes_parser.py class HermesToolCallParser (line 22) | class HermesToolCallParser(ToolCallParser): method parse (line 35) | def parse(self, text: str) -> ParseResult: FILE: environments/tool_call_parsers/kimi_k2_parser.py class KimiK2ToolCallParser (line 27) | class KimiK2ToolCallParser(ToolCallParser): method parse (line 50) | def parse(self, text: str) -> ParseResult: FILE: environments/tool_call_parsers/llama_parser.py class LlamaToolCallParser (line 26) | class LlamaToolCallParser(ToolCallParser): method parse (line 40) | def parse(self, text: str) -> ParseResult: FILE: environments/tool_call_parsers/longcat_parser.py class LongcatToolCallParser (line 22) | class LongcatToolCallParser(ToolCallParser): method parse (line 33) | def parse(self, text: str) -> ParseResult: FILE: environments/tool_call_parsers/mistral_parser.py function _generate_mistral_id (line 25) | def _generate_mistral_id() -> str: class MistralToolCallParser (line 34) | class MistralToolCallParser(ToolCallParser): method parse (line 48) | def parse(self, text: str) -> ParseResult: FILE: environments/tool_call_parsers/qwen3_coder_parser.py function _try_convert_value (line 32) | def _try_convert_value(value: str) -> Any: class Qwen3CoderToolCallParser (line 60) | class Qwen3CoderToolCallParser(ToolCallParser): method _parse_function_call (line 86) | def _parse_function_call(self, function_str: str) -> Optional[ChatComp... method parse (line 122) | def parse(self, text: str) -> ParseResult: FILE: environments/tool_call_parsers/qwen_parser.py class QwenToolCallParser (line 13) | class QwenToolCallParser(HermesToolCallParser): FILE: environments/tool_context.py function _run_tool_in_thread (line 44) | def _run_tool_in_thread(tool_name: str, arguments: Dict[str, Any], task_... class ToolContext (line 67) | class ToolContext: method __init__ (line 76) | def __init__(self, task_id: str): method terminal (line 83) | def terminal(self, command: str, timeout: int = 180) -> Dict[str, Any]: method read_file (line 113) | def read_file(self, path: str) -> Dict[str, Any]: method write_file (line 131) | def write_file(self, path: str, content: str) -> Dict[str, Any]: method upload_file (line 153) | def upload_file(self, local_path: str, remote_path: str) -> Dict[str, ... method upload_dir (line 207) | def upload_dir(self, local_dir: str, remote_dir: str) -> List[Dict[str... method download_file (line 234) | def download_file(self, remote_path: str, local_path: str) -> Dict[str... method download_dir (line 280) | def download_dir(self, remote_dir: str, local_dir: str) -> List[Dict[s... method search (line 324) | def search(self, query: str, path: str = ".") -> Dict[str, Any]: method web_search (line 347) | def web_search(self, query: str) -> Dict[str, Any]: method web_extract (line 363) | def web_extract(self, urls: List[str]) -> Dict[str, Any]: method browser_navigate (line 383) | def browser_navigate(self, url: str) -> Dict[str, Any]: method browser_snapshot (line 401) | def browser_snapshot(self) -> Dict[str, Any]: method call_tool (line 420) | def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> str: method cleanup (line 440) | def cleanup(self): FILE: environments/web_research_env.py class WebResearchEnvConfig (line 149) | class WebResearchEnvConfig(HermesAgentEnvConfig): class WebResearchEnv (line 201) | class WebResearchEnv(HermesAgentBaseEnv): method config_init (line 223) | def config_init(cls) -> Tuple[WebResearchEnvConfig, List[APIServerConf... method __init__ (line 253) | def __init__(self, *args, **kwargs): method setup (line 270) | async def setup(self) -> None: method get_next_item (line 315) | async def get_next_item(self) -> dict: method format_prompt (line 327) | def format_prompt(self, item: dict) -> str: method compute_reward (line 345) | async def compute_reward( method evaluate (line 427) | async def evaluate(self, *args, **kwargs) -> None: method wandb_log (line 574) | async def wandb_log(self, wandb_metrics: Optional[Dict] = None) -> None: method _llm_judge (line 609) | async def _llm_judge( method _parse_judge_json (line 655) | def _parse_judge_json(text: str) -> Optional[float]: method _heuristic_score (line 672) | def _heuristic_score(expected: str, model_answer: str) -> float: method _extract_domains (line 698) | def _extract_domains(text: str) -> set: FILE: gateway/channel_directory.py function _session_entry_id (line 22) | def _session_entry_id(origin: Dict[str, Any]) -> Optional[str]: function _session_entry_name (line 32) | def _session_entry_name(origin: Dict[str, Any]) -> str: function build_channel_directory (line 46) | def build_channel_directory(adapters: Dict[Any, Any]) -> Dict[str, Any]: function _build_discord (line 85) | def _build_discord(adapter) -> List[Dict[str, str]]: function _build_slack (line 113) | def _build_slack(adapter) -> List[Dict[str, str]]: function _build_from_sessions (line 132) | def _build_from_sessions(platform_name: str) -> List[Dict[str, str]]: function load_directory (line 168) | def load_directory() -> Dict[str, Any]: function resolve_channel_name (line 179) | def resolve_channel_name(platform_name: str, name: str) -> Optional[str]: function format_directory_for_display (line 216) | def format_directory_for_display() -> str: FILE: gateway/config.py function _coerce_bool (line 24) | def _coerce_bool(value: Any, default: bool = True) -> bool: function _normalize_unauthorized_dm_behavior (line 35) | def _normalize_unauthorized_dm_behavior(value: Any, default: str = "pair... class Platform (line 44) | class Platform(Enum): class HomeChannel (line 63) | class HomeChannel: method to_dict (line 74) | def to_dict(self) -> Dict[str, Any]: method from_dict (line 82) | def from_dict(cls, data: Dict[str, Any]) -> "HomeChannel": class SessionResetPolicy (line 91) | class SessionResetPolicy: method to_dict (line 105) | def to_dict(self) -> Dict[str, Any]: method from_dict (line 113) | def from_dict(cls, data: Dict[str, Any]) -> "SessionResetPolicy": class PlatformConfig (line 126) | class PlatformConfig: method to_dict (line 136) | def to_dict(self) -> Dict[str, Any]: method from_dict (line 150) | def from_dict(cls, data: Dict[str, Any]) -> "PlatformConfig": class StreamingConfig (line 165) | class StreamingConfig: method to_dict (line 173) | def to_dict(self) -> Dict[str, Any]: method from_dict (line 183) | def from_dict(cls, data: Dict[str, Any]) -> "StreamingConfig": class GatewayConfig (line 196) | class GatewayConfig: method get_connected_platforms (line 234) | def get_connected_platforms(self) -> List[Platform]: method get_home_channel (line 263) | def get_home_channel(self, platform: Platform) -> Optional[HomeChannel]: method get_reset_policy (line 270) | def get_reset_policy( method to_dict (line 290) | def to_dict(self) -> Dict[str, Any]: method from_dict (line 313) | def from_dict(cls, data: Dict[str, Any]) -> "GatewayConfig": method get_unauthorized_dm_behavior (line 371) | def get_unauthorized_dm_behavior(self, platform: Optional[Platform] = ... function load_gateway_config (line 383) | def load_gateway_config() -> GatewayConfig: function _apply_env_overrides (line 549) | def _apply_env_overrides(config: GatewayConfig) -> None: FILE: gateway/delivery.py class DeliveryTarget (line 30) | class DeliveryTarget: method parse (line 47) | def parse(cls, target: str, origin: Optional[SessionSource] = None) ->... method to_string (line 92) | def to_string(self) -> str: class DeliveryRouter (line 103) | class DeliveryRouter: method __init__ (line 111) | def __init__(self, config: GatewayConfig, adapters: Dict[Platform, Any... method resolve_targets (line 123) | def resolve_targets( method deliver (line 170) | async def deliver( method _deliver_local (line 212) | def _deliver_local( method _save_full_output (line 258) | def _save_full_output(self, content: str, job_id: str) -> Path: method _deliver_to_platform (line 267) | async def _deliver_to_platform( function parse_deliver_spec (line 298) | def parse_deliver_spec( function build_delivery_context_for_tool (line 313) | def build_delivery_context_for_tool( FILE: gateway/hooks.py class HookRegistry (line 36) | class HookRegistry: method __init__ (line 46) | def __init__(self): method loaded_hooks (line 52) | def loaded_hooks(self) -> List[dict]: method discover_and_load (line 56) | def discover_and_load(self) -> None: method emit (line 121) | async def emit(self, event_type: str, context: Optional[Dict[str, Any]... FILE: gateway/mirror.py function mirror_to_session (line 26) | def mirror_to_session( function _find_session_id (line 67) | def _find_session_id(platform: str, chat_id: str, thread_id: Optional[st... function _append_to_jsonl (line 108) | def _append_to_jsonl(session_id: str, message: dict) -> None: function _append_to_sqlite (line 118) | def _append_to_sqlite(session_id: str, message: dict) -> None: FILE: gateway/pairing.py function _secure_write (line 47) | def _secure_write(path: Path, data: str) -> None: class PairingStore (line 57) | class PairingStore: method __init__ (line 67) | def __init__(self): method _pending_path (line 70) | def _pending_path(self, platform: str) -> Path: method _approved_path (line 73) | def _approved_path(self, platform: str) -> Path: method _rate_limit_path (line 76) | def _rate_limit_path(self) -> Path: method _load_json (line 79) | def _load_json(self, path: Path) -> dict: method _save_json (line 87) | def _save_json(self, path: Path, data: dict) -> None: method is_approved (line 92) | def is_approved(self, platform: str, user_id: str) -> bool: method list_approved (line 97) | def list_approved(self, platform: str = None) -> list: method _approve_user (line 107) | def _approve_user(self, platform: str, user_id: str, user_name: str = ... method revoke (line 116) | def revoke(self, platform: str, user_id: str) -> bool: method generate_code (line 128) | def generate_code( method approve_code (line 170) | def approve_code(self, platform: str, code: str) -> Optional[dict]: method list_pending (line 195) | def list_pending(self, platform: str = None) -> list: method clear_pending (line 213) | def clear_pending(self, platform: str = None) -> int: method _is_rate_limited (line 225) | def _is_rate_limited(self, platform: str, user_id: str) -> bool: method _record_rate_limit (line 232) | def _record_rate_limit(self, platform: str, user_id: str) -> None: method _is_locked_out (line 239) | def _is_locked_out(self, platform: str) -> bool: method _record_failed_attempt (line 246) | def _record_failed_attempt(self, platform: str) -> None: method _cleanup_expired (line 262) | def _cleanup_expired(self, platform: str) -> None: method _all_platforms (line 276) | def _all_platforms(self, suffix: str) -> list: FILE: gateway/platforms/api_server.py function check_api_server_requirements (line 50) | def check_api_server_requirements() -> bool: class ResponseStore (line 55) | class ResponseStore: method __init__ (line 64) | def __init__(self, max_size: int = MAX_STORED_RESPONSES): method get (line 68) | def get(self, response_id: str) -> Optional[Dict[str, Any]]: method put (line 75) | def put(self, response_id: str, data: Dict[str, Any]) -> None: method delete (line 83) | def delete(self, response_id: str) -> bool: method __len__ (line 90) | def __len__(self) -> int: function cors_middleware (line 107) | async def cors_middleware(request, handler): class APIServerAdapter (line 118) | class APIServerAdapter(BasePlatformAdapter): method __init__ (line 126) | def __init__(self, config: PlatformConfig): method _check_auth (line 143) | def _check_auth(self, request: "web.Request") -> Optional["web.Respons... method _create_agent (line 168) | def _create_agent( method _handle_health (line 205) | async def _handle_health(self, request: "web.Request") -> "web.Response": method _handle_models (line 209) | async def _handle_models(self, request: "web.Request") -> "web.Response": method _handle_chat_completions (line 230) | async def _handle_chat_completions(self, request: "web.Request") -> "w... method _write_sse_chat_completion (line 351) | async def _write_sse_chat_completion( method _handle_responses (line 430) | async def _handle_responses(self, request: "web.Request") -> "web.Resp... method _handle_get_response (line 597) | async def _handle_get_response(self, request: "web.Request") -> "web.R... method _handle_delete_response (line 613) | async def _handle_delete_response(self, request: "web.Request") -> "we... method _extract_output_items (line 638) | def _extract_output_items(result: Dict[str, Any]) -> List[Dict[str, An... method _run_agent (line 689) | async def _run_agent( method connect (line 728) | async def connect(self) -> bool: method disconnect (line 759) | async def disconnect(self) -> None: method send (line 771) | async def send( method get_chat_info (line 783) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: FILE: gateway/platforms/base.py function get_image_cache_dir (line 50) | def get_image_cache_dir() -> Path: function cache_image_from_bytes (line 56) | def cache_image_from_bytes(data: bytes, ext: str = ".jpg") -> str: function cache_image_from_url (line 74) | async def cache_image_from_url(url: str, ext: str = ".jpg") -> str: function cleanup_image_cache (line 101) | def cleanup_image_cache(max_age_hours: int = 24) -> int: function get_audio_cache_dir (line 132) | def get_audio_cache_dir() -> Path: function cache_audio_from_bytes (line 138) | def cache_audio_from_bytes(data: bytes, ext: str = ".ogg") -> str: function cache_audio_from_url (line 156) | async def cache_audio_from_url(url: str, ext: str = ".ogg") -> str: function get_document_cache_dir (line 200) | def get_document_cache_dir() -> Path: function cache_document_from_bytes (line 206) | def cache_document_from_bytes(data: bytes, filename: str) -> str: function cleanup_document_cache (line 238) | def cleanup_document_cache(max_age_hours: int = 24) -> int: class MessageType (line 259) | class MessageType(Enum): class MessageEvent (line 273) | class MessageEvent: method is_command (line 302) | def is_command(self) -> bool: method get_command (line 306) | def get_command(self) -> Optional[str]: method get_command_args (line 314) | def get_command_args(self) -> str: class SendResult (line 323) | class SendResult: class BasePlatformAdapter (line 335) | class BasePlatformAdapter(ABC): method __init__ (line 346) | def __init__(self, config: PlatformConfig, platform: Platform): method has_fatal_error (line 368) | def has_fatal_error(self) -> bool: method fatal_error_message (line 372) | def fatal_error_message(self) -> Optional[str]: method fatal_error_code (line 376) | def fatal_error_code(self) -> Optional[str]: method fatal_error_retryable (line 380) | def fatal_error_retryable(self) -> bool: method set_fatal_error_handler (line 383) | def set_fatal_error_handler(self, handler: Callable[["BasePlatformAdap... method _mark_connected (line 386) | def _mark_connected(self) -> None: method _mark_disconnected (line 397) | def _mark_disconnected(self) -> None: method _set_fatal_error (line 407) | def _set_fatal_error(self, code: str, message: str, *, retryable: bool... method _notify_fatal_error (line 423) | async def _notify_fatal_error(self) -> None: method name (line 432) | def name(self) -> str: method is_connected (line 437) | def is_connected(self) -> bool: method set_message_handler (line 441) | def set_message_handler(self, handler: MessageHandler) -> None: method connect (line 451) | async def connect(self) -> bool: method disconnect (line 460) | async def disconnect(self) -> None: method send (line 465) | async def send( method edit_message (line 486) | async def edit_message( method send_typing (line 499) | async def send_typing(self, chat_id: str, metadata=None) -> None: method send_image (line 508) | async def send_image( method send_animation (line 527) | async def send_animation( method _is_animation_url (line 545) | def _is_animation_url(url: str) -> bool: method extract_images (line 551) | def extract_images(content: str) -> Tuple[List[Tuple[str, str]], str]: method send_voice (line 598) | async def send_voice( method play_tts (line 618) | async def play_tts( method send_video (line 632) | async def send_video( method send_document (line 651) | async def send_document( method send_image_file (line 671) | async def send_image_file( method extract_media (line 692) | def extract_media(content: str) -> Tuple[List[Tuple[str, bool]], str]: method extract_local_files (line 734) | def extract_local_files(content: str) -> Tuple[List[str], str]: method _keep_typing (line 801) | async def _keep_typing(self, chat_id: str, interval: float = 2.0, meta... method handle_message (line 815) | async def handle_message(self, event: MessageEvent) -> None: method _get_human_delay (line 870) | def _get_human_delay() -> float: method _process_message_background (line 890) | async def _process_message_background(self, event: MessageEvent, sessi... method cancel_background_tasks (line 1129) | async def cancel_background_tasks(self) -> None: method has_pending_interrupt (line 1144) | def has_pending_interrupt(self, session_key: str) -> bool: method get_pending_message (line 1148) | def get_pending_message(self, session_key: str) -> Optional[MessageEve... method build_source (line 1152) | def build_source( method get_chat_info (line 1182) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: method format_message (line 1192) | def format_message(self, content: str) -> str: method truncate_message (line 1204) | def truncate_message(content: str, max_length: int = 4096) -> List[str]: FILE: gateway/platforms/dingtalk.py function check_dingtalk_requirements (line 59) | def check_dingtalk_requirements() -> bool: class DingTalkAdapter (line 68) | class DingTalkAdapter(BasePlatformAdapter): method __init__ (line 78) | def __init__(self, config: PlatformConfig): method connect (line 96) | async def connect(self) -> bool: method _run_stream (line 129) | async def _run_stream(self) -> None: method disconnect (line 151) | async def disconnect(self) -> None: method _on_message (line 175) | async def _on_message(self, message: "ChatbotMessage") -> None: method _extract_text (line 233) | def _extract_text(message: "ChatbotMessage") -> str: method _is_duplicate (line 252) | def _is_duplicate(self, msg_id: str) -> bool: method send (line 266) | async def send( method send_typing (line 302) | async def send_typing(self, chat_id: str, metadata=None) -> None: method get_chat_info (line 306) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: class _IncomingHandler (line 315) | class _IncomingHandler(ChatbotHandler if DINGTALK_STREAM_AVAILABLE else ... method __init__ (line 318) | def __init__(self, adapter: DingTalkAdapter, loop: asyncio.AbstractEve... method process (line 324) | def process(self, message: "ChatbotMessage"): FILE: gateway/platforms/discord.py function _clean_discord_id (line 56) | def _clean_discord_id(entry: str) -> str: function check_discord_requirements (line 73) | def check_discord_requirements() -> bool: class VoiceReceiver (line 78) | class VoiceReceiver: method __init__ (line 92) | def __init__(self, voice_client, allowed_user_ids: set = None): method start (line 123) | def start(self): method stop (line 135) | def stop(self): method pause (line 149) | def pause(self): method resume (line 152) | def resume(self): method map_ssrc (line 159) | def map_ssrc(self, ssrc: int, user_id: int): method _install_speaking_hook (line 163) | def _install_speaking_hook(self, conn): method _on_packet (line 200) | def _on_packet(self, data: bytes): method _infer_user_for_ssrc (line 312) | def _infer_user_for_ssrc(self, ssrc: int) -> int: method check_silence (line 338) | def check_silence(self) -> list: method pcm_to_wav (line 376) | def pcm_to_wav(pcm_data: bytes, output_path: str, class DiscordAdapter (line 404) | class DiscordAdapter(BasePlatformAdapter): method __init__ (line 424) | def __init__(self, config: PlatformConfig): method connect (line 445) | async def connect(self) -> bool: method disconnect (line 594) | async def disconnect(self) -> None: method send (line 614) | async def send( method edit_message (line 685) | async def edit_message( method _send_file_attachment (line 708) | async def _send_file_attachment( method play_tts (line 731) | async def play_tts( method send_voice (line 749) | async def send_voice( method join_voice_channel (line 828) | async def join_voice_channel(self, channel) -> bool: method leave_voice_channel (line 861) | async def leave_voice_channel(self, guild_id: int) -> None: method play_in_voice_channel (line 882) | async def play_in_voice_channel(self, guild_id: int, audio_path: str) ... method get_user_voice_channel (line 925) | async def get_user_voice_channel(self, guild_id: int, user_id: str): method _reset_voice_timeout (line 937) | def _reset_voice_timeout(self, guild_id: int) -> None: method _voice_timeout_handler (line 946) | async def _voice_timeout_handler(self, guild_id: int) -> None: method is_in_voice_channel (line 968) | def is_in_voice_channel(self, guild_id: int) -> bool: method get_voice_channel_info (line 973) | def get_voice_channel_info(self, guild_id: int) -> Optional[Dict[str, ... method get_voice_channel_context (line 1025) | def get_voice_channel_context(self, guild_id: int) -> str: method _voice_listen_loop (line 1050) | async def _voice_listen_loop(self, guild_id: int): method _process_voice_input (line 1082) | async def _process_voice_input(self, guild_id: int, user_id: int, pcm_... method _is_allowed_user (line 1118) | def _is_allowed_user(self, user_id: str) -> bool: method send_image_file (line 1124) | async def send_image_file( method send_image (line 1141) | async def send_image( method send_video (line 1206) | async def send_video( method send_document (line 1223) | async def send_document( method send_typing (line 1241) | async def send_typing(self, chat_id: str, metadata=None) -> None: method get_chat_info (line 1251) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: method _resolve_allowed_usernames (line 1290) | async def _resolve_allowed_usernames(self) -> None: method format_message (line 1354) | def format_message(self, content: str) -> str: method _run_simple_slash (line 1363) | async def _run_simple_slash( method _register_slash_commands (line 1379) | def _register_slash_commands(self) -> None: method _build_slash_event (line 1500) | def _build_slash_event(self, interaction: discord.Interaction, text: s... method _handle_thread_create_slash (line 1534) | async def _handle_thread_create_slash( method _dispatch_thread_session (line 1570) | async def _dispatch_thread_session( method _thread_parent_channel (line 1601) | def _thread_parent_channel(self, channel: Any) -> Any: method _resolve_interaction_channel (line 1605) | async def _resolve_interaction_channel(self, interaction: discord.Inte... method _create_thread (line 1623) | async def _create_thread( method _auto_create_thread (line 1698) | async def _auto_create_thread(self, message: 'DiscordMessage') -> Opti... method send_exec_approval (line 1716) | async def send_exec_approval( method _get_parent_channel_id (line 1753) | def _get_parent_channel_id(self, channel: Any) -> Optional[str]: method _is_forum_parent (line 1763) | def _is_forum_parent(self, channel: Any) -> bool: method _format_thread_chat_name (line 1777) | def _format_thread_chat_name(self, thread: Any) -> str: method _thread_state_path (line 1798) | def _thread_state_path() -> Path: method _load_participated_threads (line 1804) | def _load_participated_threads(cls) -> set: method _save_participated_threads (line 1816) | def _save_participated_threads(self) -> None: method _track_thread (line 1830) | def _track_thread(self, thread_id: str) -> None: method _handle_message (line 1836) | async def _handle_message(self, message: DiscordMessage) -> None: class ExecApprovalView (line 2003) | class ExecApprovalView(discord.ui.View): method __init__ (line 2011) | def __init__(self, approval_id: str, allowed_user_ids: set): method _check_auth (line 2017) | def _check_auth(self, interaction: discord.Interaction) -> bool: method _resolve (line 2023) | async def _resolve( method allow_once (line 2064) | async def allow_once( method allow_always (line 2070) | async def allow_always( method deny (line 2076) | async def deny( method on_timeout (line 2081) | async def on_timeout(self): FILE: gateway/platforms/email.py function check_email_requirements (line 55) | def check_email_requirements() -> bool: function _decode_header_value (line 66) | def _decode_header_value(raw: str) -> str: function _extract_text_body (line 78) | def _extract_text_body(msg: email_lib.message.Message) -> str: function _strip_html (line 116) | def _strip_html(html: str) -> str: function _extract_email_address (line 130) | def _extract_email_address(raw: str) -> str: function _extract_attachments (line 138) | def _extract_attachments( class EmailAdapter (line 194) | class EmailAdapter(BasePlatformAdapter): method __init__ (line 197) | def __init__(self, config: PlatformConfig): method connect (line 224) | async def connect(self) -> bool: method disconnect (line 258) | async def disconnect(self) -> None: method _poll_loop (line 270) | async def _poll_loop(self) -> None: method _check_inbox (line 281) | async def _check_inbox(self) -> None: method _fetch_new_messages (line 289) | def _fetch_new_messages(self) -> List[Dict[str, Any]]: method _dispatch_message (line 344) | async def _dispatch_message(self, msg_data: Dict[str, Any]) -> None: method send (line 399) | async def send( method _send_email (line 417) | def _send_email( method send_typing (line 455) | async def send_typing(self, chat_id: str, metadata: Optional[Dict[str,... method send_image (line 459) | async def send_image( method send_document (line 471) | async def send_document( method _send_email_with_attachment (line 495) | def _send_email_with_attachment( method get_chat_info (line 542) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: FILE: gateway/platforms/homeassistant.py function check_ha_requirements (line 42) | def check_ha_requirements() -> bool: class HomeAssistantAdapter (line 51) | class HomeAssistantAdapter(BasePlatformAdapter): method __init__ (line 65) | def __init__(self, config: PlatformConfig): method _next_id (line 92) | def _next_id(self) -> int: method connect (line 101) | async def connect(self) -> bool: method _ws_connect (line 138) | async def _ws_connect(self) -> bool: method _cleanup_ws (line 183) | async def _cleanup_ws(self) -> None: method disconnect (line 192) | async def disconnect(self) -> None: method _listen_loop (line 213) | async def _listen_loop(self) -> None: method _read_events (line 243) | async def _read_events(self) -> None: method _handle_ha_event (line 258) | async def _handle_ha_event(self, event: Dict[str, Any]) -> None: method _format_state_change (line 317) | def _format_state_change( method send (line 382) | async def send( method send_typing (line 436) | async def send_typing(self, chat_id: str, metadata=None) -> None: method get_chat_info (line 440) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: FILE: gateway/platforms/matrix.py function check_matrix_requirements (line 50) | def check_matrix_requirements() -> bool: class MatrixAdapter (line 73) | class MatrixAdapter(BasePlatformAdapter): method __init__ (line 76) | def __init__(self, config: PlatformConfig): method connect (line 111) | async def connect(self) -> bool: method disconnect (line 226) | async def disconnect(self) -> None: method send (line 243) | async def send( method get_chat_info (line 303) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: method send_typing (line 324) | async def send_typing( method edit_message (line 334) | async def edit_message( method send_image (line 366) | async def send_image( method send_image_file (line 399) | async def send_image_file( method send_document (line 410) | async def send_document( method send_voice (line 422) | async def send_voice( method send_video (line 433) | async def send_video( method format_message (line 444) | def format_message(self, content: str) -> str: method _upload_and_send (line 454) | async def _upload_and_send( method _send_local_file (line 510) | async def _send_local_file( method _sync_loop (line 537) | async def _sync_loop(self) -> None: method _on_room_message (line 554) | async def _on_room_message(self, room: Any, event: Any) -> None: method _on_room_message_media (line 643) | async def _on_room_message_media(self, room: Any, event: Any) -> None: method _on_invite (line 716) | async def _on_invite(self, room: Any, event: Any) -> None: method _refresh_dm_cache (line 753) | async def _refresh_dm_cache(self) -> None: method _get_display_name (line 801) | def _get_display_name(self, room: Any, user_id: str) -> str: method _mxc_to_http (line 812) | def _mxc_to_http(self, mxc_url: str) -> str: method _markdown_to_html (line 823) | def _markdown_to_html(self, text: str) -> str: FILE: gateway/platforms/mattermost.py function check_mattermost_requirements (line 53) | def check_mattermost_requirements() -> bool: class MattermostAdapter (line 71) | class MattermostAdapter(BasePlatformAdapter): method __init__ (line 74) | def __init__(self, config: PlatformConfig): method _headers (line 108) | def _headers(self) -> Dict[str, str]: method _api_get (line 114) | async def _api_get(self, path: str) -> Dict[str, Any]: method _api_post (line 129) | async def _api_post( method _api_put (line 148) | async def _api_put( method _upload_file (line 167) | async def _upload_file( method connect (line 196) | async def connect(self) -> bool: method disconnect (line 228) | async def disconnect(self) -> None: method send (line 251) | async def send( method get_chat_info (line 282) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: method send_typing (line 296) | async def send_typing( method edit_message (line 305) | async def edit_message( method send_image (line 318) | async def send_image( method send_image_file (line 331) | async def send_image_file( method send_document (line 344) | async def send_document( method send_voice (line 358) | async def send_voice( method send_video (line 371) | async def send_video( method format_message (line 384) | def format_message(self, content: str) -> str: method _send_url_as_file (line 398) | async def _send_url_as_file( method _send_local_file (line 438) | async def _send_local_file( method _ws_loop (line 480) | async def _ws_loop(self) -> None: method _ws_connect_and_listen (line 504) | async def _ws_connect_and_listen(self) -> None: method _handle_ws_event (line 543) | async def _handle_ws_event(self, event: Dict[str, Any]) -> None: method _prune_seen (line 655) | def _prune_seen(self) -> None: FILE: gateway/platforms/signal.py function _redact_phone (line 62) | def _redact_phone(phone: str) -> str: function _parse_comma_list (line 71) | def _parse_comma_list(value: str) -> List[str]: function _guess_extension (line 76) | def _guess_extension(data: bytes) -> str: function _is_image_ext (line 99) | def _is_image_ext(ext: str) -> bool: function _is_audio_ext (line 103) | def _is_audio_ext(ext: str) -> bool: function _ext_to_mime (line 116) | def _ext_to_mime(ext: str) -> str: function _render_mentions (line 121) | def _render_mentions(text: str, mentions: list) -> str: function check_signal_requirements (line 142) | def check_signal_requirements() -> bool: class SignalAdapter (line 151) | class SignalAdapter(BasePlatformAdapter): method __init__ (line 156) | def __init__(self, config: PlatformConfig): method connect (line 195) | async def connect(self) -> bool: method disconnect (line 221) | async def disconnect(self) -> None: method _sse_listener (line 254) | async def _sse_listener(self) -> None: method _health_monitor (line 317) | async def _health_monitor(self) -> None: method _force_reconnect (line 343) | def _force_reconnect(self) -> None: method _handle_envelope (line 356) | async def _handle_envelope(self, envelope: dict) -> None: method _fetch_attachment (line 512) | async def _fetch_attachment(self, attachment_id: str) -> tuple: method _rpc (line 539) | async def _rpc(self, method: str, params: dict, rpc_id: str = None) ->... method send (line 578) | async def send( method _track_sent_timestamp (line 605) | def _track_sent_timestamp(self, rpc_result) -> None: method send_typing (line 613) | async def send_typing(self, chat_id: str, metadata=None) -> None: method send_image (line 626) | async def send_image( method send_document (line 672) | async def send_document( method _start_typing_indicator (line 707) | async def _start_typing_indicator(self, chat_id: str) -> None: method _stop_typing_indicator (line 722) | async def _stop_typing_indicator(self, chat_id: str) -> None: method get_chat_info (line 736) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: FILE: gateway/platforms/slack.py function check_slack_requirements (line 48) | def check_slack_requirements() -> bool: class SlackAdapter (line 53) | class SlackAdapter(BasePlatformAdapter): method __init__ (line 71) | def __init__(self, config: PlatformConfig): method connect (line 78) | async def connect(self) -> bool: method disconnect (line 134) | async def disconnect(self) -> None: method send (line 144) | async def send( method edit_message (line 192) | async def edit_message( method send_typing (line 218) | async def send_typing(self, chat_id: str, metadata=None) -> None: method _resolve_thread_ts (line 246) | def _resolve_thread_ts( method _upload_file (line 263) | async def _upload_file( method format_message (line 289) | def format_message(self, content: str) -> str: method _add_reaction (line 373) | async def _add_reaction( method _remove_reaction (line 389) | async def _remove_reaction( method _resolve_user_name (line 406) | async def _resolve_user_name(self, user_id: str) -> str: method send_image_file (line 435) | async def send_image_file( method send_image (line 461) | async def send_image( method send_voice (line 502) | async def send_voice( method send_video (line 525) | async def send_video( method send_document (line 563) | async def send_document( method get_chat_info (line 604) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: method _handle_slack_message (line 628) | async def _handle_slack_message(self, event: dict) -> None: method _handle_slash_command (line 786) | async def _handle_slash_command(self, command: dict) -> None: method _download_slack_file (line 822) | async def _download_slack_file(self, url: str, ext: str, audio: bool =... method _download_slack_file_bytes (line 841) | async def _download_slack_file_bytes(self, url: str) -> bytes: FILE: gateway/platforms/sms.py function _redact_phone (line 45) | def _redact_phone(phone: str) -> str: function check_sms_requirements (line 54) | def check_sms_requirements() -> bool: class SmsAdapter (line 63) | class SmsAdapter(BasePlatformAdapter): method __init__ (line 73) | def __init__(self, config: PlatformConfig): method _basic_auth_header (line 84) | def _basic_auth_header(self) -> str: method connect (line 94) | async def connect(self) -> bool: method disconnect (line 120) | async def disconnect(self) -> None: method send (line 130) | async def send( method get_chat_info (line 183) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: method format_message (line 190) | def format_message(self, content: str) -> str: method _handle_webhook (line 207) | async def _handle_webhook(self, request) -> "aiohttp.web.Response": FILE: gateway/platforms/telegram.py class _MockContextTypes (line 43) | class _MockContextTypes: function check_telegram_requirements (line 64) | def check_telegram_requirements() -> bool: function _escape_mdv2 (line 74) | def _escape_mdv2(text: str) -> str: function _strip_mdv2 (line 79) | def _strip_mdv2(text: str) -> str: class TelegramAdapter (line 99) | class TelegramAdapter(BasePlatformAdapter): method __init__ (line 114) | def __init__(self, config: PlatformConfig): method _looks_like_polling_conflict (line 134) | def _looks_like_polling_conflict(error: Exception) -> bool: method _handle_polling_conflict (line 142) | async def _handle_polling_conflict(self, error: Exception) -> None: method connect (line 159) | async def connect(self) -> bool: method disconnect (line 284) | async def disconnect(self) -> None: method send (line 323) | async def send( method edit_message (line 403) | async def edit_message( method send_voice (line 482) | async def send_voice( method send_image_file (line 531) | async def send_image_file( method send_document (line 565) | async def send_document( method send_video (line 597) | async def send_video( method send_image (line 625) | async def send_image( method send_animation (line 684) | async def send_animation( method send_typing (line 716) | async def send_typing(self, chat_id: str, metadata: Optional[Dict[str,... method get_chat_info (line 735) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: method format_message (line 769) | def format_message(self, content: str) -> str: method _handle_text_message (line 887) | async def _handle_text_message(self, update: Update, context: ContextT... method _handle_command (line 900) | async def _handle_command(self, update: Update, context: ContextTypes.... method _handle_location_message (line 908) | async def _handle_location_message(self, update: Update, context: Cont... method _text_batch_key (line 947) | def _text_batch_key(self, event: MessageEvent) -> str: method _enqueue_text_event (line 955) | def _enqueue_text_event(self, event: MessageEvent) -> None: method _flush_text_batch (line 984) | async def _flush_text_batch(self, key: str) -> None: method _photo_batch_key (line 1005) | def _photo_batch_key(self, event: MessageEvent, msg: Message) -> str: method _flush_photo_batch (line 1017) | async def _flush_photo_batch(self, batch_key: str) -> None: method _enqueue_photo_event (line 1031) | def _enqueue_photo_event(self, batch_key: str, event: MessageEvent) ->... method _handle_media_message (line 1051) | async def _handle_media_message(self, update: Update, context: Context... method _queue_media_group_event (line 1216) | async def _queue_media_group_event(self, media_group_id: str, event: M... method _flush_media_group_event (line 1245) | async def _flush_media_group_event(self, media_group_id: str) -> None: method _handle_sticker (line 1256) | async def _handle_sticker(self, msg: Message, event: "MessageEvent") -... method _build_message_event (line 1323) | def _build_message_event(self, message: Message, msg_type: MessageType... FILE: gateway/platforms/webhook.py function check_webhook_requirements (line 58) | def check_webhook_requirements() -> bool: class WebhookAdapter (line 63) | class WebhookAdapter(BasePlatformAdapter): method __init__ (line 66) | def __init__(self, config: PlatformConfig): method connect (line 98) | async def connect(self) -> bool: method disconnect (line 128) | async def disconnect(self) -> None: method send (line 135) | async def send( method get_chat_info (line 174) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: method _handle_health (line 181) | async def _handle_health(self, request: "web.Request") -> "web.Response": method _handle_webhook (line 185) | async def _handle_webhook(self, request: "web.Request") -> "web.Respon... method _validate_signature (line 382) | def _validate_signature( method _render_prompt (line 417) | def _render_prompt( method _render_delivery_extra (line 450) | def _render_delivery_extra( method _deliver_github_comment (line 466) | async def _deliver_github_comment( method _deliver_cross_platform (line 520) | async def _deliver_cross_platform( FILE: gateway/platforms/whatsapp.py function _kill_port_process (line 34) | def _kill_port_process(port: int) -> None: function check_whatsapp_requirements (line 82) | def check_whatsapp_requirements() -> bool: class WhatsAppAdapter (line 101) | class WhatsAppAdapter(BasePlatformAdapter): method __init__ (line 127) | def __init__(self, config: PlatformConfig): method connect (line 144) | async def connect(self) -> bool: method _close_bridge_log (line 318) | def _close_bridge_log(self) -> None: method disconnect (line 327) | async def disconnect(self) -> None: method send (line 360) | async def send( method edit_message (line 406) | async def edit_message( method _send_media_to_bridge (line 435) | async def _send_media_to_bridge( method send_image (line 482) | async def send_image( method send_image_file (line 496) | async def send_image_file( method send_video (line 506) | async def send_video( method send_document (line 516) | async def send_document( method send_typing (line 530) | async def send_typing(self, chat_id: str, metadata=None) -> None: method get_chat_info (line 547) | async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: method _poll_messages (line 572) | async def _poll_messages(self) -> None: method _build_message_event (line 601) | async def _build_message_event(self, data: Dict[str, Any]) -> Optional... FILE: gateway/run.py function _ensure_ssl_certs (line 36) | def _ensure_ssl_certs() -> None: function _resolve_runtime_agent_kwargs (line 232) | def _resolve_runtime_agent_kwargs() -> dict: function _resolve_gateway_model (line 256) | def _resolve_gateway_model() -> str: function _resolve_hermes_bin (line 280) | def _resolve_hermes_bin() -> Optional[list[str]]: class GatewayRunner (line 307) | class GatewayRunner: method __init__ (line 315) | def __init__(self, config: Optional[GatewayConfig] = None): method _get_or_create_gateway_honcho (line 388) | def _get_or_create_gateway_honcho(self, session_key: str): method _shutdown_gateway_honcho (line 419) | def _shutdown_gateway_honcho(self, session_key: str) -> None: method _shutdown_all_gateway_honcho (line 435) | def _shutdown_all_gateway_honcho(self) -> None: method _has_setup_skill (line 445) | def _has_setup_skill(self) -> bool: method _load_voice_modes (line 457) | def _load_voice_modes(self) -> Dict[str, str]: method _save_voice_modes (line 473) | def _save_voice_modes(self) -> None: method _set_adapter_auto_tts_disabled (line 482) | def _set_adapter_auto_tts_disabled(self, adapter, chat_id: str, disabl... method _sync_voice_mode_state_to_adapter (line 492) | def _sync_voice_mode_state_to_adapter(self, adapter) -> None: method _flush_memories_for_session (line 504) | def _flush_memories_for_session( method _async_flush_memories (line 576) | async def _async_flush_memories( method should_exit_cleanly (line 591) | def should_exit_cleanly(self) -> bool: method exit_reason (line 595) | def exit_reason(self) -> Optional[str]: method _session_key_for_source (line 598) | def _session_key_for_source(self, source: SessionSource) -> str: method _resolve_turn_agent_config (line 613) | def _resolve_turn_agent_config(self, user_message: str, model: str, ru... method _handle_adapter_fatal_error (line 627) | async def _handle_adapter_fatal_error(self, adapter: BasePlatformAdapt... method _request_clean_exit (line 649) | def _request_clean_exit(self, reason: str) -> None: method _load_prefill_messages (line 655) | def _load_prefill_messages() -> List[Dict[str, Any]]: method _load_ephemeral_system_prompt (line 694) | def _load_ephemeral_system_prompt() -> str: method _load_reasoning_config (line 715) | def _load_reasoning_config() -> dict | None: method _load_show_reasoning (line 747) | def _load_show_reasoning() -> bool: method _load_background_notifications_mode (line 761) | def _load_background_notifications_mode() -> str: method _load_provider_routing (line 796) | def _load_provider_routing() -> dict: method _load_fallback_model (line 810) | def _load_fallback_model() -> dict | None: method _load_smart_model_routing (line 830) | def _load_smart_model_routing() -> dict: method start (line 843) | async def start(self) -> bool: method _session_expiry_watcher (line 1015) | async def _session_expiry_watcher(self, interval: int = 300): method stop (line 1053) | async def stop(self) -> None: method wait_for_shutdown (line 1094) | async def wait_for_shutdown(self) -> None: method _create_adapter (line 1098) | def _create_adapter( method _is_user_authorized (line 1205) | def _is_user_authorized(self, source: SessionSource) -> bool: method _get_unauthorized_dm_behavior (line 1284) | def _get_unauthorized_dm_behavior(self, platform: Optional[Platform]) ... method _handle_message (line 1291) | async def _handle_message(self, event: MessageEvent) -> Optional[str]: method _handle_message_with_agent (line 1622) | async def _handle_message_with_agent(self, event, source, _quick_key: ... method _handle_reset_command (line 2313) | async def _handle_reset_command(self, event: MessageEvent) -> str: method _handle_status_command (line 2357) | async def _handle_status_command(self, event: MessageEvent) -> str: method _handle_stop_command (line 2382) | async def _handle_stop_command(self, event: MessageEvent) -> str: method _handle_help_command (line 2397) | async def _handle_help_command(self, event: MessageEvent) -> str: method _handle_model_command (line 2415) | async def _handle_model_command(self, event: MessageEvent) -> str: method _handle_provider_command (line 2610) | async def _handle_provider_command(self, event: MessageEvent) -> str: method _handle_personality_command (line 2664) | async def _handle_personality_command(self, event: MessageEvent) -> str: method _handle_retry_command (line 2740) | async def _handle_retry_command(self, event: MessageEvent) -> str: method _handle_undo_command (line 2775) | async def _handle_undo_command(self, event: MessageEvent) -> str: method _handle_set_home_command (line 2800) | async def _handle_set_home_command(self, event: MessageEvent) -> str: method _get_guild_id (line 2831) | def _get_guild_id(event: MessageEvent) -> Optional[int]: method _handle_voice_command (line 2844) | async def _handle_voice_command(self, event: MessageEvent) -> str: method _handle_voice_channel_join (line 2919) | async def _handle_voice_channel_join(self, event: MessageEvent) -> str: method _handle_voice_channel_leave (line 2969) | async def _handle_voice_channel_leave(self, event: MessageEvent) -> str: method _handle_voice_timeout_cleanup (line 2992) | def _handle_voice_timeout_cleanup(self, chat_id: str) -> None: method _handle_voice_channel_input (line 3002) | async def _handle_voice_channel_input( method _should_send_voice_reply (line 3052) | def _should_send_voice_reply( method _send_voice_reply (line 3101) | async def _send_voice_reply(self, event: MessageEvent, text: str) -> N... method _handle_rollback_command (line 3159) | async def _handle_rollback_command(self, event: MessageEvent) -> str: method _handle_background_command (line 3218) | async def _handle_background_command(self, event: MessageEvent) -> str: method _run_background_task (line 3245) | async def _run_background_task( method _handle_reasoning_command (line 3414) | async def _handle_reasoning_command(self, event: MessageEvent) -> str: method _handle_compress_command (line 3498) | async def _handle_compress_command(self, event: MessageEvent) -> str: method _handle_title_command (line 3557) | async def _handle_title_command(self, event: MessageEvent) -> str: method _handle_resume_command (line 3591) | async def _handle_resume_command(self, event: MessageEvent) -> str: method _handle_usage_command (line 3668) | async def _handle_usage_command(self, event: MessageEvent) -> str: method _handle_insights_command (line 3705) | async def _handle_insights_command(self, event: MessageEvent) -> str: method _handle_reload_mcp_command (line 3752) | async def _handle_reload_mcp_command(self, event: MessageEvent) -> str: method _handle_approve_command (line 3828) | async def _handle_approve_command(self, event: MessageEvent) -> str: method _handle_deny_command (line 3882) | async def _handle_deny_command(self, event: MessageEvent) -> str: method _handle_update_command (line 3894) | async def _handle_update_command(self, event: MessageEvent) -> str: method _schedule_update_notification_watch (line 3968) | def _schedule_update_notification_watch(self) -> None: method _watch_for_update_completion (line 3981) | async def _watch_for_update_completion( method _send_update_notification (line 4004) | async def _send_update_notification(self) -> bool: method _set_session_env (line 4089) | def _set_session_env(self, context: SessionContext) -> None: method _clear_session_env (line 4098) | def _clear_session_env(self) -> None: method _enrich_message_with_vision (line 4104) | async def _enrich_message_with_vision( method _enrich_message_with_transcription (line 4172) | async def _enrich_message_with_transcription( method _run_process_watcher (line 4255) | async def _run_process_watcher(self, watcher: dict) -> None: method _run_agent (line 4352) | async def _run_agent( function _start_cron_ticker (line 5069) | def _start_cron_ticker(stop_event: threading.Event, adapters=None, inter... function start_gateway (line 5120) | async def start_gateway(config: Optional[GatewayConfig] = None, replace:... function main (line 5278) | def main(): FILE: gateway/session.py function _hash_id (line 32) | def _hash_id(value: str) -> str: function _hash_sender_id (line 37) | def _hash_sender_id(value: str) -> str: function _hash_chat_id (line 42) | def _hash_chat_id(value: str) -> str: function _looks_like_phone (line 55) | def _looks_like_phone(value: str) -> bool: class SessionSource (line 68) | class SessionSource: method description (line 89) | def description(self) -> str: method to_dict (line 109) | def to_dict(self) -> Dict[str, Any]: method from_dict (line 127) | def from_dict(cls, data: Dict[str, Any]) -> "SessionSource": method local_cli (line 142) | def local_cli(cls) -> "SessionSource": class SessionContext (line 153) | class SessionContext: method to_dict (line 172) | def to_dict(self) -> Dict[str, Any]: function build_session_context_prompt (line 196) | def build_session_context_prompt( class SessionEntry (line 324) | class SessionEntry: method to_dict (line 359) | def to_dict(self) -> Dict[str, Any]: method from_dict (line 382) | def from_dict(cls, data: Dict[str, Any]) -> "SessionEntry": function build_session_key (line 414) | def build_session_key(source: SessionSource, group_sessions_per_user: bo... class SessionStore (line 457) | class SessionStore: method __init__ (line 465) | def __init__(self, sessions_dir: Path, config: GatewayConfig, method _ensure_loaded (line 485) | def _ensure_loaded(self) -> None: method _save (line 508) | def _save(self) -> None: method _generate_session_key (line 531) | def _generate_session_key(self, source: SessionSource) -> str: method _is_session_expired (line 538) | def _is_session_expired(self, entry: SessionEntry) -> bool: method _should_reset (line 576) | def _should_reset(self, entry: SessionEntry, source: SessionSource) ->... method has_any_sessions (line 617) | def has_any_sessions(self) -> bool: method get_or_create_session (line 638) | def get_or_create_session( method update_session (line 706) | def update_session( method reset_session (line 763) | def reset_session(self, session_key: str) -> Optional[SessionEntry]: method switch_session (line 809) | def switch_session(self, session_key: str, target_session_id: str) -> ... method list_sessions (line 851) | def list_sessions(self, active_minutes: Optional[int] = None) -> List[... method get_transcript_path (line 865) | def get_transcript_path(self, session_id: str) -> Path: method append_to_transcript (line 869) | def append_to_transcript(self, session_id: str, message: Dict[str, Any... method rewrite_transcript (line 897) | def rewrite_transcript(self, session_id: str, messages: List[Dict[str,... method load_transcript (line 925) | def load_transcript(self, session_id: str) -> List[Dict[str, Any]]: function build_session_context (line 958) | def build_session_context( FILE: gateway/status.py function _get_pid_path (line 27) | def _get_pid_path() -> Path: function _get_runtime_status_path (line 33) | def _get_runtime_status_path() -> Path: function _get_lock_dir (line 38) | def _get_lock_dir() -> Path: function _utc_now_iso (line 47) | def _utc_now_iso() -> str: function _scope_hash (line 51) | def _scope_hash(identity: str) -> str: function _get_scope_lock_path (line 55) | def _get_scope_lock_path(scope: str, identity: str) -> Path: function _get_process_start_time (line 59) | def _get_process_start_time(pid: int) -> Optional[int]: function _read_process_cmdline (line 69) | def _read_process_cmdline(pid: int) -> Optional[str]: function _looks_like_gateway_process (line 82) | def _looks_like_gateway_process(pid: int) -> bool: function _record_looks_like_gateway (line 97) | def _record_looks_like_gateway(record: dict[str, Any]) -> bool: function _build_pid_record (line 116) | def _build_pid_record() -> dict: function _build_runtime_status_record (line 125) | def _build_runtime_status_record() -> dict[str, Any]: function _read_json_file (line 136) | def _read_json_file(path: Path) -> Optional[dict[str, Any]]: function _write_json_file (line 152) | def _write_json_file(path: Path, payload: dict[str, Any]) -> None: function _read_pid_record (line 157) | def _read_pid_record() -> Optional[dict]: function write_pid_file (line 181) | def write_pid_file() -> None: function write_runtime_status (line 186) | def write_runtime_status( function read_runtime_status (line 223) | def read_runtime_status() -> Optional[dict[str, Any]]: function remove_pid_file (line 228) | def remove_pid_file() -> None: function acquire_scoped_lock (line 236) | def acquire_scoped_lock(scope: str, identity: str, metadata: Optional[di... function release_scoped_lock (line 301) | def release_scoped_lock(scope: str, identity: str) -> None: function get_running_pid (line 317) | def get_running_pid() -> Optional[int]: function is_gateway_running (line 354) | def is_gateway_running() -> bool: FILE: gateway/sticker_cache.py function _load_cache (line 29) | def _load_cache() -> dict: function _save_cache (line 39) | def _save_cache(cache: dict) -> None: function get_cached_description (line 48) | def get_cached_description(file_unique_id: str) -> Optional[dict]: function cache_sticker_description (line 59) | def cache_sticker_description( function build_sticker_injection (line 84) | def build_sticker_injection( function build_animated_sticker_injection (line 104) | def build_animated_sticker_injection(emoji: str = "") -> str: FILE: gateway/stream_consumer.py class StreamConsumerConfig (line 32) | class StreamConsumerConfig: class GatewayStreamConsumer (line 39) | class GatewayStreamConsumer: method __init__ (line 54) | def __init__( method already_sent (line 74) | def already_sent(self) -> bool: method on_delta (line 79) | def on_delta(self, text: str) -> None: method finish (line 84) | def finish(self) -> None: method run (line 88) | async def run(self) -> None: method _send_or_edit (line 159) | async def _send_or_edit(self, text: str) -> None: FILE: hermes_cli/auth.py class ProviderConfig (line 82) | class ProviderConfig: function _resolve_kimi_base_url (line 229) | def _resolve_kimi_base_url(api_key: str, default_url: str, env_override:... function _gh_cli_candidates (line 242) | def _gh_cli_candidates() -> list[str]: function _try_gh_cli_token (line 263) | def _try_gh_cli_token() -> Optional[str]: function _resolve_api_key_provider_secret (line 281) | def _resolve_api_key_provider_secret( function detect_zai_endpoint (line 323) | def detect_zai_endpoint(api_key: str, timeout: float = 8.0) -> Optional[... class AuthError (line 363) | class AuthError(RuntimeError): method __init__ (line 366) | def __init__( function format_auth_error (line 380) | def format_auth_error(error: Exception) -> str: function _token_fingerprint (line 406) | def _token_fingerprint(token: Any) -> Optional[str]: function _oauth_trace_enabled (line 416) | def _oauth_trace_enabled() -> bool: function _oauth_trace (line 421) | def _oauth_trace(event: str, *, sequence_id: Optional[str] = None, **fie... function _auth_file_path (line 435) | def _auth_file_path() -> Path: function _auth_lock_path (line 439) | def _auth_lock_path() -> Path: function _auth_store_lock (line 446) | def _auth_store_lock(timeout_seconds: float = AUTH_LOCK_TIMEOUT_SECONDS): function _load_auth_store (line 503) | def _load_auth_store(auth_file: Optional[Path] = None) -> Dict[str, Any]: function _save_auth_store (line 528) | def _save_auth_store(auth_store: Dict[str, Any]) -> Path: function _load_provider_state (line 564) | def _load_provider_state(auth_store: Dict[str, Any], provider_id: str) -... function _save_provider_state (line 572) | def _save_provider_state(auth_store: Dict[str, Any], provider_id: str, s... function get_provider_auth_state (line 581) | def get_provider_auth_state(provider_id: str) -> Optional[Dict[str, Any]]: function get_active_provider (line 587) | def get_active_provider() -> Optional[str]: function clear_provider_auth (line 593) | def clear_provider_auth(provider_id: Optional[str] = None) -> bool: function deactivate_provider (line 616) | def deactivate_provider() -> None: function resolve_provider (line 632) | def resolve_provider( function _parse_iso_timestamp (line 714) | def _parse_iso_timestamp(value: Any) -> Optional[float]: function _is_expiring (line 731) | def _is_expiring(expires_at_iso: Any, skew_seconds: int) -> bool: function _coerce_ttl_seconds (line 738) | def _coerce_ttl_seconds(expires_in: Any) -> int: function _optional_base_url (line 746) | def _optional_base_url(value: Any) -> Optional[str]: function _decode_jwt_claims (line 753) | def _decode_jwt_claims(token: Any) -> Dict[str, Any]: function _codex_access_token_is_expiring (line 766) | def _codex_access_token_is_expiring(access_token: Any, skew_seconds: int... function _is_remote_session (line 778) | def _is_remote_session() -> bool: function _read_codex_tokens (line 791) | def _read_codex_tokens(*, _lock: bool = True) -> Dict[str, Any]: function _save_codex_tokens (line 840) | def _save_codex_tokens(tokens: Dict[str, str], last_refresh: str = None)... function _refresh_codex_auth_tokens (line 854) | def _refresh_codex_auth_tokens( function _import_codex_cli_tokens (line 936) | def _import_codex_cli_tokens() -> Optional[Dict[str, str]]: function resolve_codex_runtime_credentials (line 959) | def resolve_codex_runtime_credentials( function _resolve_verify (line 1026) | def _resolve_verify( function _request_device_code (line 1057) | def _request_device_code( function _poll_for_token (line 1084) | def _poll_for_token( function _refresh_access_token (line 1137) | def _refresh_access_token( function _mint_agent_key (line 1172) | def _mint_agent_key( function fetch_nous_models (line 1205) | def fetch_nous_models( function _agent_key_is_usable (line 1262) | def _agent_key_is_usable(state: Dict[str, Any], min_ttl_seconds: int) ->... function resolve_nous_runtime_credentials (line 1269) | def resolve_nous_runtime_credentials( function get_nous_auth_status (line 1522) | def get_nous_auth_status() -> Dict[str, Any]: function get_codex_auth_status (line 1544) | def get_codex_auth_status() -> Dict[str, Any]: function get_api_key_provider_status (line 1563) | def get_api_key_provider_status(provider_id: str) -> Dict[str, Any]: function get_external_process_provider_status (line 1594) | def get_external_process_provider_status(provider_id: str) -> Dict[str, ... function get_auth_status (line 1624) | def get_auth_status(provider_id: Optional[str] = None) -> Dict[str, Any]: function resolve_api_key_provider_credentials (line 1640) | def resolve_api_key_provider_credentials(provider_id: str) -> Dict[str, ... function resolve_external_process_provider_credentials (line 1676) | def resolve_external_process_provider_credentials(provider_id: str) -> D... function detect_external_credentials (line 1720) | def detect_external_credentials() -> List[Dict[str, Any]]: function _update_config_for_provider (line 1747) | def _update_config_for_provider( function _reset_config_provider (line 1809) | def _reset_config_provider() -> Path: function _prompt_model_selection (line 1832) | def _prompt_model_selection(model_ids: List[str], current_model: str = "... function _save_model_choice (line 1909) | def _save_model_choice(model_id: str) -> None: function login_command (line 1926) | def login_command(args) -> None: function _login_openai_codex (line 1934) | def _login_openai_codex(args, pconfig: ProviderConfig) -> None: function _codex_device_code_login (line 1990) | def _codex_device_code_login() -> Dict[str, Any]: function _login_nous (line 2135) | def _login_nous(args, pconfig: ProviderConfig) -> None: function logout_command (line 2293) | def logout_command(args) -> None: FILE: hermes_cli/banner.py function cprint (line 36) | def cprint(text: str): function _skin_color (line 45) | def _skin_color(key: str, fallback: str) -> str: function _skin_branding (line 54) | def _skin_branding(key: str, fallback: str) -> str: function get_available_skills (line 104) | def get_available_skills() -> Dict[str, List[str]]: function check_for_updates (line 132) | def check_for_updates() -> Optional[int]: function prefetch_update_check (line 200) | def prefetch_update_check(): function get_update_result (line 210) | def get_update_result(timeout: float = 0.5) -> Optional[int]: function _format_context_length (line 220) | def _format_context_length(tokens: int) -> str: function _display_toolset_name (line 231) | def _display_toolset_name(toolset_name: str) -> str: function build_welcome_banner (line 242) | def build_welcome_banner(console: Console, model: str, cwd: str, FILE: hermes_cli/callbacks.py function clarify_callback (line 17) | def clarify_callback(cli, question, choices): function sudo_password_callback (line 65) | def sudo_password_callback(cli) -> str: function prompt_for_secret (line 106) | def prompt_for_secret(cli, var_name: str, prompt: str, metadata=None) ->... function approval_callback (line 224) | def approval_callback(cli, command: str, description: str) -> str: FILE: hermes_cli/checklist.py function curses_checklist (line 13) | def curses_checklist( FILE: hermes_cli/claw.py function _find_migration_script (line 51) | def _find_migration_script() -> Path | None: function _load_migration_module (line 59) | def _load_migration_module(script_path: Path): function claw_command (line 76) | def claw_command(args): function _cmd_migrate (line 91) | def _cmd_migrate(args): function _print_migration_report (line 204) | def _print_migration_report(report: dict, dry_run: bool): FILE: hermes_cli/clipboard.py function save_clipboard_image (line 27) | def save_clipboard_image(dest: Path) -> bool: function has_clipboard_image (line 38) | def has_clipboard_image() -> bool: function _macos_save (line 54) | def _macos_save(dest: Path) -> bool: function _macos_has_image (line 59) | def _macos_has_image() -> bool: function _macos_pngpaste (line 71) | def _macos_pngpaste(dest: Path) -> bool: function _macos_osascript (line 87) | def _macos_osascript(dest: Path) -> bool: function _is_wsl (line 117) | def _is_wsl() -> bool: function _linux_save (line 130) | def _linux_save(dest: Path) -> bool: function _wsl_has_image (line 164) | def _wsl_has_image() -> bool: function _wsl_save (line 180) | def _wsl_save(dest: Path) -> bool: function _wayland_has_image (line 209) | def _wayland_has_image() -> bool: function _wayland_save (line 226) | def _wayland_save(dest: Path) -> bool: function _convert_to_png (line 275) | def _convert_to_png(path: Path) -> bool: function _xclip_has_image (line 317) | def _xclip_has_image() -> bool: function _xclip_save (line 332) | def _xclip_save(dest: Path) -> bool: FILE: hermes_cli/codex_models.py function _add_forward_compat_models (line 28) | def _add_forward_compat_models(model_ids: List[str]) -> List[str]: function _fetch_models_from_api (line 52) | def _fetch_models_from_api(access_token: str) -> List[str]: function _read_default_model (line 90) | def _read_default_model(codex_home: Path) -> Optional[str]: function _read_cache_models (line 108) | def _read_cache_models(codex_home: Path) -> List[str]: function get_codex_model_ids (line 144) | def get_codex_model_ids(access_token: Optional[str] = None) -> List[str]: FILE: hermes_cli/colors.py class Colors (line 6) | class Colors: function color (line 18) | def color(text: str, *codes) -> str: FILE: hermes_cli/commands.py class CommandDef (line 29) | class CommandDef: function _build_command_lookup (line 143) | def _build_command_lookup() -> dict[str, CommandDef]: function resolve_command (line 156) | def resolve_command(name: str) -> CommandDef | None: function _build_description (line 164) | def _build_description(cmd: CommandDef) -> str: function gateway_help_lines (line 222) | def gateway_help_lines() -> list[str]: function telegram_bot_commands (line 240) | def telegram_bot_commands() -> list[tuple[str, str]]: function slack_subcommand_map (line 256) | def slack_subcommand_map() -> dict[str, str]: class SlashCommandCompleter (line 276) | class SlashCommandCompleter(Completer): method __init__ (line 279) | def __init__( method _get_model_info (line 291) | def _get_model_info(self) -> dict[str, Any]: method _iter_skill_commands (line 306) | def _iter_skill_commands(self) -> Mapping[str, dict[str, Any]]: method _completion_text (line 315) | def _completion_text(cmd_name: str, word: str) -> str: method _extract_path_word (line 326) | def _extract_path_word(text: str) -> str | None: method _path_completions (line 350) | def _path_completions(word: str, limit: int = 30): method get_completions (line 400) | def get_completions(self, document, complete_event): class SlashCommandAutoSuggest (line 502) | class SlashCommandAutoSuggest(AutoSuggest): method __init__ (line 509) | def __init__( method get_suggestion (line 517) | def get_suggestion(self, buffer, document): function _file_size_label (line 582) | def _file_size_label(path: str) -> str: FILE: hermes_cli/config.py function get_hermes_home (line 53) | def get_hermes_home() -> Path: function get_config_path (line 57) | def get_config_path() -> Path: function get_env_path (line 61) | def get_env_path() -> Path: function get_project_root (line 65) | def get_project_root() -> Path: function _secure_dir (line 69) | def _secure_dir(path): function _secure_file (line 77) | def _secure_file(path): function _ensure_default_soul_md (line 86) | def _ensure_default_soul_md(home: Path) -> None: function ensure_hermes_home (line 95) | def ensure_hermes_home(): function get_missing_env_vars (line 893) | def get_missing_env_vars(required_only: bool = False) -> List[Dict[str, ... function _set_nested (line 915) | def _set_nested(config: dict, dotted_key: str, value): function get_missing_config_fields (line 930) | def get_missing_config_fields() -> List[Dict[str, Any]]: function check_config_version (line 958) | def check_config_version() -> Tuple[int, int]: function migrate_config (line 970) | def migrate_config(interactive: bool = True, quiet: bool = False) -> Dic... function _deep_merge (line 1154) | def _deep_merge(base: dict, override: dict) -> dict: function _normalize_max_turns_config (line 1174) | def _normalize_max_turns_config(config: Dict[str, Any]) -> Dict[str, Any]: function load_config (line 1191) | def load_config() -> Dict[str, Any]: function save_config (line 1313) | def save_config(config: Dict[str, Any]): function load_env (line 1339) | def load_env() -> Dict[str, str]: function _sanitize_env_lines (line 1358) | def _sanitize_env_lines(lines: list) -> list: function sanitize_env_file (line 1409) | def sanitize_env_file() -> int: function save_env_value (line 1454) | def save_env_value(key: str, value: str): function save_anthropic_oauth_token (line 1513) | def save_anthropic_oauth_token(value: str, save_fn=None): function use_anthropic_claude_code_credentials (line 1520) | def use_anthropic_claude_code_credentials(save_fn=None): function save_anthropic_api_key (line 1527) | def save_anthropic_api_key(value: str, save_fn=None): function save_env_value_secure (line 1534) | def save_env_value_secure(key: str, value: str) -> Dict[str, Any]: function get_env_value (line 1544) | def get_env_value(key: str) -> Optional[str]: function redact_key (line 1559) | def redact_key(key: str) -> str: function show_config (line 1568) | def show_config(): function edit_config (line 1707) | def edit_config(): function set_config_value (line 1736) | def set_config_value(key: str, value: str): function config_command (line 1817) | def config_command(args): FILE: hermes_cli/copilot_auth.py function is_classic_pat (line 54) | def is_classic_pat(token: str) -> bool: function validate_copilot_token (line 59) | def validate_copilot_token(token: str) -> tuple[bool, str]: function resolve_copilot_token (line 80) | def resolve_copilot_token() -> tuple[str, str]: function _gh_cli_candidates (line 111) | def _gh_cli_candidates() -> list[str]: function _try_gh_cli_token (line 132) | def _try_gh_cli_token() -> Optional[str]: function copilot_device_code_login (line 152) | def copilot_device_code_login( function copilot_request_headers (line 277) | def copilot_request_headers( FILE: hermes_cli/cron.py function _normalize_skills (line 19) | def _normalize_skills(single_skill=None, skills: Optional[Iterable[str]]... function _cron_api (line 35) | def _cron_api(**kwargs): function cron_list (line 41) | def cron_list(show_all: bool = False): function cron_tick (line 103) | def cron_tick(): function cron_status (line 109) | def cron_status(): function cron_create (line 142) | def cron_create(args): function cron_edit (line 165) | def cron_edit(args): function _job_action (line 214) | def _job_action(action: str, job_id: str, success_verb: str) -> int: function cron_command (line 228) | def cron_command(args): FILE: hermes_cli/curses_ui.py function curses_checklist (line 12) | def curses_checklist( function _numbered_fallback (line 113) | def _numbered_fallback( FILE: hermes_cli/doctor.py function _has_provider_env_config (line 53) | def _has_provider_env_config(content: str) -> bool: function _honcho_is_configured_for_doctor (line 58) | def _honcho_is_configured_for_doctor() -> bool: function _apply_doctor_tool_availability_overrides (line 69) | def _apply_doctor_tool_availability_overrides(available: list[str], unav... function check_ok (line 85) | def check_ok(text: str, detail: str = ""): function check_warn (line 88) | def check_warn(text: str, detail: str = ""): function check_fail (line 91) | def check_fail(text: str, detail: str = ""): function check_info (line 94) | def check_info(text: str): function _check_gateway_service_linger (line 98) | def _check_gateway_service_linger(issues: list[str]) -> None: function run_doctor (line 131) | def run_doctor(args): FILE: hermes_cli/env_loader.py function _load_dotenv_with_fallback (line 12) | def _load_dotenv_with_fallback(path: Path, *, override: bool) -> None: function load_hermes_dotenv (line 19) | def load_hermes_dotenv( FILE: hermes_cli/gateway.py function find_gateway_pids (line 29) | def find_gateway_pids() -> list: function kill_gateway_processes (line 89) | def kill_gateway_processes(force: bool = False) -> int: function is_linux (line 110) | def is_linux() -> bool: function is_macos (line 113) | def is_macos() -> bool: function is_windows (line 116) | def is_windows() -> bool: function get_service_name (line 128) | def get_service_name() -> str: function get_systemd_unit_path (line 148) | def get_systemd_unit_path(system: bool = False) -> Path: function _ensure_user_systemd_env (line 155) | def _ensure_user_systemd_env() -> None: function _systemctl_cmd (line 177) | def _systemctl_cmd(system: bool = False) -> list[str]: function _journalctl_cmd (line 183) | def _journalctl_cmd(system: bool = False) -> list[str]: function _service_scope_label (line 187) | def _service_scope_label(system: bool = False) -> str: function get_installed_systemd_scopes (line 191) | def get_installed_systemd_scopes() -> list[str]: function has_conflicting_systemd_units (line 204) | def has_conflicting_systemd_units() -> bool: function print_systemd_scope_conflict_warning (line 208) | def print_systemd_scope_conflict_warning() -> None: function _require_root_for_system_service (line 222) | def _require_root_for_system_service(action: str) -> None: function _system_service_identity (line 228) | def _system_service_identity(run_as_user: str | None = None) -> tuple[st... function _read_systemd_user_from_unit (line 248) | def _read_systemd_user_from_unit(unit_path: Path) -> str | None: function _default_system_service_user (line 259) | def _default_system_service_user() -> str | None: function prompt_linux_gateway_install_scope (line 266) | def prompt_linux_gateway_install_scope() -> str | None: function install_linux_gateway_from_setup (line 279) | def install_linux_gateway_from_setup(force: bool = False) -> tuple[str |... function get_systemd_linger_status (line 310) | def get_systemd_linger_status() -> tuple[bool | None, str]: function print_systemd_linger_guidance (line 358) | def print_systemd_linger_guidance() -> None: function get_launchd_plist_path (line 371) | def get_launchd_plist_path() -> Path: function get_python_path (line 374) | def get_python_path() -> str: function get_hermes_cli_path (line 383) | def get_hermes_cli_path() -> str: function generate_systemd_unit (line 399) | def generate_systemd_unit(system: bool = False, run_as_user: str | None ... function _normalize_service_definition (line 471) | def _normalize_service_definition(text: str) -> str: function systemd_unit_is_current (line 475) | def systemd_unit_is_current(system: bool = False) -> bool: function refresh_systemd_unit_if_needed (line 487) | def refresh_systemd_unit_if_needed(system: bool = False) -> bool: function _print_linger_enable_warning (line 501) | def _print_linger_enable_warning(username: str, detail: str | None = Non... function _ensure_linger_enabled (line 516) | def _ensure_linger_enabled() -> None: function _select_systemd_scope (line 559) | def _select_systemd_scope(system: bool = False) -> bool: function systemd_install (line 565) | def systemd_install(force: bool = False, system: bool = False, run_as_us... function systemd_uninstall (line 609) | def systemd_uninstall(system: bool = False): function systemd_start (line 626) | def systemd_start(system: bool = False): function systemd_stop (line 636) | def systemd_stop(system: bool = False): function systemd_restart (line 645) | def systemd_restart(system: bool = False): function systemd_status (line 655) | def systemd_status(deep: bool = False, system: bool = False): function generate_launchd_plist (line 726) | def generate_launchd_plist() -> str: function launchd_plist_is_current (line 770) | def launchd_plist_is_current() -> bool: function refresh_launchd_plist_if_needed (line 781) | def refresh_launchd_plist_if_needed() -> bool: function launchd_install (line 800) | def launchd_install(force: bool = False): function launchd_uninstall (line 826) | def launchd_uninstall(): function launchd_start (line 836) | def launchd_start(): function launchd_stop (line 849) | def launchd_stop(): function _wait_for_gateway_exit (line 853) | def _wait_for_gateway_exit(timeout: float = 10.0, force_after: float = 5... function launchd_restart (line 893) | def launchd_restart(): function launchd_status (line 903) | def launchd_status(deep: bool = False): function run_gateway (line 938) | def run_gateway(verbose: bool = False, replace: bool = False): function _platform_status (line 1197) | def _platform_status(platform: dict) -> str: function _runtime_health_lines (line 1243) | def _runtime_health_lines() -> list[str]: function _setup_standard_platform (line 1272) | def _setup_standard_platform(platform: dict): function _setup_whatsapp (line 1370) | def _setup_whatsapp(): function _is_service_installed (line 1377) | def _is_service_installed() -> bool: function _is_service_running (line 1386) | def _is_service_running() -> bool: function _setup_signal (line 1419) | def _setup_signal(): function gateway_setup (line 1534) | def gateway_setup(): function gateway_command (line 1673) | def gateway_command(args): FILE: hermes_cli/main.py function _relative_time (line 77) | def _relative_time(ts) -> str: function _has_any_provider_configured (line 95) | def _has_any_provider_configured() -> bool: function _session_browse_picker (line 168) | def _session_browse_picker(sessions: list) -> Optional[str]: function _resolve_last_cli_session (line 402) | def _resolve_last_cli_session() -> Optional[str]: function _resolve_session_by_name_or_id (line 416) | def _resolve_session_by_name_or_id(name_or_id: str) -> Optional[str]: function cmd_chat (line 442) | def cmd_chat(args): function cmd_gateway (line 546) | def cmd_gateway(args): function cmd_whatsapp (line 552) | def cmd_whatsapp(args): function cmd_setup (line 739) | def cmd_setup(args): function cmd_model (line 745) | def cmd_model(args): function _prompt_provider_choice (line 903) | def _prompt_provider_choice(choices): function _model_flow_openrouter (line 942) | def _model_flow_openrouter(config, current_model=""): function _model_flow_nous (line 991) | def _model_flow_nous(config, current_model=""): function _model_flow_openai_codex (line 1068) | def _model_flow_openai_codex(config, current_model=""): function _model_flow_custom (line 1117) | def _model_flow_custom(config): function _save_custom_provider (line 1220) | def _save_custom_provider(base_url, api_key="", model="", context_length... function _remove_custom_provider (line 1282) | def _remove_custom_provider(config): function _model_flow_named_custom (line 1337) | def _model_flow_named_custom(config, provider_info): function _current_reasoning_effort (line 1511) | def _current_reasoning_effort(config) -> str: function _set_reasoning_effort (line 1518) | def _set_reasoning_effort(config, effort: str) -> None: function _prompt_reasoning_effort_selection (line 1526) | def _prompt_reasoning_effort_selection(efforts, current_effort=""): function _model_flow_copilot (line 1604) | def _model_flow_copilot(config, current_model=""): function _model_flow_copilot_acp (line 1780) | def _model_flow_copilot_acp(config, current_model=""): function _model_flow_kimi (line 1881) | def _model_flow_kimi(config, current_model=""): function _model_flow_api_key_provider (line 1985) | def _model_flow_api_key_provider(config, provider_id, current_model=""): function _run_anthropic_oauth_flow (line 2084) | def _run_anthropic_oauth_flow(save_env_value): function _model_flow_anthropic (line 2168) | def _model_flow_anthropic(config, current_model=""): function cmd_login (line 2301) | def cmd_login(args): function cmd_logout (line 2307) | def cmd_logout(args): function cmd_status (line 2313) | def cmd_status(args): function cmd_cron (line 2319) | def cmd_cron(args): function cmd_doctor (line 2325) | def cmd_doctor(args): function cmd_config (line 2331) | def cmd_config(args): function cmd_version (line 2337) | def cmd_version(args): function cmd_uninstall (line 2365) | def cmd_uninstall(args): function _update_via_zip (line 2371) | def _update_via_zip(args): function _stash_local_changes_if_needed (line 2479) | def _stash_local_changes_if_needed(git_cmd: list[str], cwd: Path) -> Opt... function _resolve_stash_selector (line 2510) | def _resolve_stash_selector(git_cmd: list[str], cwd: Path, stash_ref: st... function _print_stash_cleanup_guidance (line 2526) | def _print_stash_cleanup_guidance(stash_ref: str, stash_selector: Option... function _restore_stashed_changes (line 2536) | def _restore_stashed_changes( function _invalidate_update_cache (line 2597) | def _invalidate_update_cache(): function cmd_update (line 2609) | def cmd_update(args): function _coalesce_session_name_args (line 2930) | def _coalesce_session_name_args(argv: list) -> list: function main (line 2968) | def main(): FILE: hermes_cli/models.py function model_ids (line 257) | def model_ids() -> list[str]: function menu_labels (line 262) | def menu_labels() -> list[str]: function list_available_providers (line 278) | def list_available_providers() -> list[dict[str, str]]: function parse_model_input (line 320) | def parse_model_input(raw: str, current_provider: str) -> tuple[str, str]: function _get_custom_base_url (line 347) | def _get_custom_base_url() -> str: function curated_models_for_provider (line 360) | def curated_models_for_provider(provider: Optional[str]) -> list[tuple[s... function detect_provider_for_model (line 381) | def detect_provider_for_model( function _find_openrouter_slug (line 475) | def _find_openrouter_slug(model_name: str) -> Optional[str]: function normalize_provider (line 502) | def normalize_provider(provider: Optional[str]) -> str: function provider_label (line 513) | def provider_label(provider: Optional[str]) -> str: function _resolve_copilot_catalog_api_key (line 523) | def _resolve_copilot_catalog_api_key() -> str: function provider_model_ids (line 534) | def provider_model_ids(provider: Optional[str]) -> list[str]: function _fetch_anthropic_models (line 590) | def _fetch_anthropic_models(timeout: float = 5.0) -> Optional[list[str]]: function _payload_items (line 634) | def _payload_items(payload: Any) -> list[dict[str, Any]]: function _extract_model_ids (line 644) | def _extract_model_ids(payload: Any) -> list[str]: function copilot_default_headers (line 648) | def copilot_default_headers() -> dict[str, str]: function _copilot_catalog_item_is_text_model (line 666) | def _copilot_catalog_item_is_text_model(item: dict[str, Any]) -> bool: function fetch_github_model_catalog (line 695) | def fetch_github_model_catalog( function _is_github_models_base_url (line 730) | def _is_github_models_base_url(base_url: Optional[str]) -> bool: function _fetch_github_models (line 738) | def _fetch_github_models(api_key: Optional[str] = None, timeout: float =... function _copilot_catalog_ids (line 768) | def _copilot_catalog_ids( function normalize_copilot_model_id (line 783) | def normalize_copilot_model_id( function _github_reasoning_efforts_for_model_id (line 824) | def _github_reasoning_efforts_for_model_id(model_id: str) -> list[str]: function _should_use_copilot_responses_api (line 834) | def _should_use_copilot_responses_api(model_id: str) -> bool: function copilot_model_api_mode (line 851) | def copilot_model_api_mode( function github_model_reasoning_efforts (line 890) | def github_model_reasoning_efforts( function probe_api_models (line 934) | def probe_api_models( function _fetch_ai_gateway_models (line 1002) | def _fetch_ai_gateway_models(timeout: float = 5.0) -> Optional[list[str]]: function fetch_api_models (line 1029) | def fetch_api_models( function validate_requested_model (line 1042) | def validate_requested_model( FILE: hermes_cli/pairing.py function pairing_command (line 11) | def pairing_command(args): function _cmd_list (line 31) | def _cmd_list(store): function _cmd_approve (line 64) | def _cmd_approve(store, platform: str, code: str): function _cmd_revoke (line 81) | def _cmd_revoke(store, platform: str, user_id: str): function _cmd_clear_pending (line 91) | def _cmd_clear_pending(store): FILE: hermes_cli/plugins.py class PluginManifest (line 70) | class PluginManifest: class LoadedPlugin (line 85) | class LoadedPlugin: class PluginContext (line 100) | class PluginContext: method __init__ (line 103) | def __init__(self, manifest: PluginManifest, manager: "PluginManager"): method register_tool (line 109) | def register_tool( method register_hook (line 140) | def register_hook(self, hook_name: str, callback: Callable) -> None: class PluginManager (line 162) | class PluginManager: method __init__ (line 165) | def __init__(self) -> None: method discover_and_load (line 175) | def discover_and_load(self) -> None: method _scan_directory (line 210) | def _scan_directory(self, path: Path, source: str) -> List[PluginManif... method _scan_entry_points (line 252) | def _scan_entry_points(self) -> List[PluginManifest]: method _load_plugin (line 281) | def _load_plugin(self, manifest: PluginManifest) -> None: method _load_directory_module (line 329) | def _load_directory_module(self, manifest: PluginManifest) -> types.Mo... method _load_entrypoint_module (line 359) | def _load_entrypoint_module(self, manifest: PluginManifest) -> types.M... method invoke_hook (line 381) | def invoke_hook(self, hook_name: str, **kwargs: Any) -> None: method list_plugins (line 403) | def list_plugins(self) -> List[Dict[str, Any]]: function get_plugin_manager (line 429) | def get_plugin_manager() -> PluginManager: function discover_plugins (line 437) | def discover_plugins() -> None: function invoke_hook (line 442) | def invoke_hook(hook_name: str, **kwargs: Any) -> None: function get_plugin_tool_names (line 447) | def get_plugin_tool_names() -> Set[str]: FILE: hermes_cli/runtime_provider.py function _normalize_custom_provider_name (line 23) | def _normalize_custom_provider_name(value: str) -> str: function _detect_api_mode_for_url (line 27) | def _detect_api_mode_for_url(base_url: str) -> Optional[str]: function _auto_detect_local_model (line 39) | def _auto_detect_local_model(base_url: str) -> str: function _get_model_config (line 60) | def _get_model_config() -> Dict[str, Any]: function _copilot_runtime_api_mode (line 79) | def _copilot_runtime_api_mode(model_cfg: Dict[str, Any], api_key: str) -... function _parse_api_mode (line 99) | def _parse_api_mode(raw: Any) -> Optional[str]: function resolve_requested_provider (line 108) | def resolve_requested_provider(requested: Optional[str] = None) -> str: function _get_named_custom_provider (line 127) | def _get_named_custom_provider(requested_provider: str) -> Optional[Dict... function _resolve_named_custom_runtime (line 174) | def _resolve_named_custom_runtime( function _resolve_openrouter_runtime (line 209) | def _resolve_openrouter_runtime( function resolve_runtime_provider (line 289) | def resolve_runtime_provider( function format_runtime_provider_error (line 430) | def format_runtime_provider_error(error: Exception) -> str: FILE: hermes_cli/setup.py function _model_config_dict (line 26) | def _model_config_dict(config: Dict[str, Any]) -> Dict[str, Any]: function _set_model_provider (line 35) | def _set_model_provider( function _set_default_model (line 47) | def _set_default_model(config: Dict[str, Any], model_name: str) -> None: function _current_reasoning_effort (line 86) | def _current_reasoning_effort(config: Dict[str, Any]) -> str: function _set_reasoning_effort (line 93) | def _set_reasoning_effort(config: Dict[str, Any], effort: str) -> None: function _setup_copilot_reasoning_selection (line 101) | def _setup_copilot_reasoning_selection( function _setup_provider_model_selection (line 139) | def _setup_provider_model_selection(config, provider_id, current_model, ... function _sync_model_from_disk (line 266) | def _sync_model_from_disk(config: Dict[str, Any]) -> None: function print_header (line 292) | def print_header(title: str): function print_info (line 298) | def print_info(text: str): function print_success (line 303) | def print_success(text: str): function print_warning (line 308) | def print_warning(text: str): function print_error (line 313) | def print_error(text: str): function is_interactive_stdin (line 318) | def is_interactive_stdin() -> bool: function print_noninteractive_setup_guidance (line 329) | def print_noninteractive_setup_guidance(reason: str | None = None) -> None: function prompt (line 348) | def prompt(question: str, default: str = None, password: bool = False) -... function _curses_prompt_choice (line 369) | def _curses_prompt_choice(question: str, choices: list, default: int = 0... function prompt_choice (line 433) | def prompt_choice(question: str, choices: list, default: int = 0) -> int: function prompt_yes_no (line 476) | def prompt_yes_no(question: str, default: bool = True) -> bool: function prompt_checklist (line 500) | def prompt_checklist(title: str, items: list, pre_selected: list = None)... function _prompt_api_key (line 529) | def _prompt_api_key(var: dict): function _print_setup_summary (line 557) | def _print_setup_summary(config: dict, hermes_home): function _prompt_container_resources (line 746) | def _prompt_container_resources(config: dict): function setup_model_provider (line 797) | def setup_model_provider(config: dict): function _check_espeak_ng (line 1792) | def _check_espeak_ng() -> bool: function _install_neutts_deps (line 1798) | def _install_neutts_deps() -> bool: function _setup_tts_provider (line 1848) | def _setup_tts_provider(config: dict): function setup_tts (line 1937) | def setup_tts(config: dict): function setup_terminal_backend (line 1947) | def setup_terminal_backend(config: dict): function setup_agent_settings (line 2253) | def setup_agent_settings(config: dict): function setup_gateway (line 2421) | def setup_gateway(config: dict): function setup_tools (line 2961) | def setup_tools(config: dict, first_install: bool = False): function _offer_openclaw_migration (line 2991) | def _offer_openclaw_migration(hermes_home: Path) -> bool: function run_setup_wizard (line 3098) | def run_setup_wizard(args): function _run_quick_setup (line 3296) | def _run_quick_setup(config: dict, hermes_home): FILE: hermes_cli/skills_config.py function get_disabled_skills (line 31) | def get_disabled_skills(config: dict, platform: Optional[str] = None) ->... function save_disabled_skills (line 43) | def save_disabled_skills(config: dict, disabled: Set[str], platform: Opt... function _list_all_skills (line 56) | def _list_all_skills() -> List[dict]: function _get_categories (line 65) | def _get_categories(skills: List[dict]) -> List[str]: function _select_platform (line 72) | def _select_platform() -> Optional[str]: function _toggle_by_category (line 98) | def _toggle_by_category(skills: List[dict], disabled: Set[str]) -> Set[s... function skills_command (line 129) | def skills_command(args=None): FILE: hermes_cli/skills_hub.py function _resolve_short_name (line 32) | def _resolve_short_name(name: str, sources, console: Console) -> str: function _format_extra_metadata_lines (line 79) | def _format_extra_metadata_lines(extra: Dict[str, Any]) -> list[str]: function _resolve_source_meta_and_bundle (line 107) | def _resolve_source_meta_and_bundle(identifier: str, sources): function _derive_category_from_install_path (line 137) | def _derive_category_from_install_path(install_path: str) -> str: function do_search (line 143) | def do_search(query: str, source: str = "all", limit: int = 10, function do_browse (line 182) | def do_browse(page: int = 1, page_size: int = 20, source: str = "all", function do_install (line 306) | def do_install(identifier: str, category: str = "", force: bool = False, function do_inspect (line 420) | def do_inspect(identifier: str, console: Optional[Console] = None) -> None: function do_list (line 468) | def do_list(source_filter: str = "all", console: Optional[Console] = Non... function do_check (line 526) | def do_check(name: Optional[str] = None, console: Optional[Console] = No... function do_update (line 549) | def do_update(name: Optional[str] = None, console: Optional[Console] = N... function do_audit (line 569) | def do_audit(name: Optional[str] = None, console: Optional[Console] = No... function do_uninstall (line 602) | def do_uninstall(name: str, console: Optional[Console] = None, function do_tap (line 627) | def do_tap(action: str, repo: str = "", console: Optional[Console] = Non... function do_publish (line 669) | def do_publish(skill_path: str, target: str = "github", repo: str = "", function _github_publish (line 738) | def _github_publish(skill_path: Path, skill_name: str, target_repo: str, function do_snapshot_export (line 835) | def do_snapshot_export(output_path: str, console: Optional[Console] = No... function do_snapshot_import (line 870) | def do_snapshot_import(input_path: str, force: bool = False, function skills_command (line 921) | def skills_command(args) -> None: function handle_skills_slash (line 974) | def handle_skills_slash(cmd: str, console: Optional[Console] = None) -> ... function _print_skills_help (line 1148) | def _print_skills_help(console: Console) -> None: FILE: hermes_cli/skin_engine.py class SkinConfig (line 112) | class SkinConfig: method get_color (line 124) | def get_color(self, key: str, fallback: str = "") -> str: method get_spinner_list (line 128) | def get_spinner_list(self, key: str) -> List[str]: method get_spinner_wings (line 132) | def get_spinner_wings(self) -> List[Tuple[str, str]]: method get_branding (line 141) | def get_branding(self, key: str, fallback: str = "") -> str: function _skins_dir (line 514) | def _skins_dir() -> Path: function _load_skin_from_yaml (line 520) | def _load_skin_from_yaml(path: Path) -> Optional[Dict[str, Any]]: function _build_skin_config (line 533) | def _build_skin_config(data: Dict[str, Any]) -> SkinConfig: function list_skins (line 557) | def list_skins() -> List[Dict[str, str]]: function load_skin (line 588) | def load_skin(name: str) -> SkinConfig: function get_active_skin (line 607) | def get_active_skin() -> SkinConfig: function set_active_skin (line 615) | def set_active_skin(name: str) -> SkinConfig: function get_active_skin_name (line 623) | def get_active_skin_name() -> str: function init_skin_from_config (line 628) | def init_skin_from_config(config: dict) -> None: function get_active_prompt_symbol (line 646) | def get_active_prompt_symbol(fallback: str = "❯ ") -> str: function get_active_help_header (line 655) | def get_active_help_header(fallback: str = "(^_^)? Available Commands") ... function get_active_goodbye (line 664) | def get_active_goodbye(fallback: str = "Goodbye! ⚕") -> str: function get_prompt_toolkit_style_overrides (line 673) | def get_prompt_toolkit_style_overrides() -> Dict[str, str]: FILE: hermes_cli/status.py function check_mark (line 21) | def check_mark(ok: bool) -> str: function redact_key (line 26) | def redact_key(key: str) -> str: function _format_iso_timestamp (line 35) | def _format_iso_timestamp(value) -> str: function _configured_model_label (line 54) | def _configured_model_label(config: dict) -> str: function _effective_provider_label (line 66) | def _effective_provider_label() -> str: function show_status (line 80) | def show_status(args): FILE: hermes_cli/tools_config.py function _print_info (line 29) | def _print_info(text: str): function _print_success (line 32) | def _print_success(text: str): function _print_warning (line 35) | def _print_warning(text: str): function _print_error (line 38) | def _print_error(text: str): function _prompt (line 41) | def _prompt(question: str, default: str = None, password: bool = False) ... function _prompt_yes_no (line 57) | def _prompt_yes_no(question: str, default: bool = True) -> bool: function _run_post_setup (line 278) | def _run_post_setup(post_setup_key: str): function _get_enabled_platforms (line 329) | def _get_enabled_platforms() -> List[str]: function _platform_toolset_summary (line 343) | def _platform_toolset_summary(config: dict, platforms: Optional[List[str... function _get_platform_tools (line 359) | def _get_platform_tools(config: dict, platform: str) -> Set[str]: function _save_platform_tools (line 397) | def _save_platform_tools(config: dict, platform: str, enabled_toolset_ke... function _toolset_has_keys (line 438) | def _toolset_has_keys(ts_key: str) -> bool: function _prompt_choice (line 467) | def _prompt_choice(question: str, choices: list, default: int = 0) -> int: function _prompt_toolset_checklist (line 548) | def _prompt_toolset_checklist(platform_label: str, enabled: Set[str]) ->... function _configure_toolset (line 575) | def _configure_toolset(ts_key: str, config: dict): function _configure_tool_category (line 590) | def _configure_tool_category(ts_key: str, cat: dict, config: dict): function _is_provider_active (line 657) | def _is_provider_active(provider: dict, config: dict) -> bool: function _detect_active_provider_index (line 670) | def _detect_active_provider_index(providers: list, config: dict) -> int: function _configure_provider (line 682) | def _configure_provider(provider: dict, config: dict): function _configure_simple_requirements (line 742) | def _configure_simple_requirements(ts_key: str): function _reconfigure_tool (line 800) | def _reconfigure_tool(config: dict): function _configure_tool_category_for_reconfig (line 834) | def _configure_tool_category_for_reconfig(ts_key: str, cat: dict, config... function _reconfigure_provider (line 870) | def _reconfigure_provider(provider: dict, config: dict): function _reconfigure_simple_requirements (line 912) | def _reconfigure_simple_requirements(ts_key: str): function tools_command (line 938) | def tools_command(args=None, first_install: bool = False, config: dict =... function _configure_mcp_tools_interactive (line 1166) | def _configure_mcp_tools_interactive(config: dict): function _apply_toolset_change (line 1297) | def _apply_toolset_change(config: dict, platform: str, toolset_names: Li... function _apply_mcp_change (line 1307) | def _apply_mcp_change(config: dict, targets: List[str], action: str) -> ... function _print_tools_list (line 1332) | def _print_tools_list(enabled_toolsets: set, mcp_servers: dict, platform... function tools_disable_enable_command (line 1355) | def tools_disable_enable_command(args): FILE: hermes_cli/uninstall.py function log_info (line 18) | def log_info(msg: str): function log_success (line 21) | def log_success(msg: str): function log_warn (line 24) | def log_warn(msg: str): function log_error (line 27) | def log_error(msg: str): function get_project_root (line 31) | def get_project_root() -> Path: function get_hermes_home (line 36) | def get_hermes_home() -> Path: function find_shell_configs (line 41) | def find_shell_configs() -> list: function remove_path_from_shell_configs (line 61) | def remove_path_from_shell_configs(): function remove_wrapper_script (line 107) | def remove_wrapper_script(): function uninstall_gateway_service (line 129) | def uninstall_gateway_service(): function run_uninstall (line 179) | def run_uninstall(args): FILE: hermes_state.py class SessionDB (line 107) | class SessionDB: method __init__ (line 115) | def __init__(self, db_path: Path = None): method _init_schema (line 131) | def _init_schema(self): method close (line 211) | def close(self): method create_session (line 222) | def create_session( method end_session (line 252) | def end_session(self, session_id: str, end_reason: str) -> None: method update_system_prompt (line 261) | def update_system_prompt(self, session_id: str, system_prompt: str) ->... method update_token_counts (line 270) | def update_token_counts( method get_session (line 331) | def get_session(self, session_id: str) -> Optional[Dict[str, Any]]: method resolve_session_id (line 340) | def resolve_session_id(self, session_id_or_prefix: str) -> Optional[str]: method sanitize_title (line 371) | def sanitize_title(title: Optional[str]) -> Optional[str]: method set_session_title (line 414) | def set_session_title(self, session_id: str, title: str) -> bool: method get_session_title (line 443) | def get_session_title(self, session_id: str) -> Optional[str]: method get_session_by_title (line 452) | def get_session_by_title(self, title: str) -> Optional[Dict[str, Any]]: method resolve_session_by_title (line 461) | def resolve_session_by_title(self, title: str) -> Optional[str]: method get_next_title_in_lineage (line 490) | def get_next_title_in_lineage(self, base_title: str) -> str: method list_sessions_rich (line 525) | def list_sessions_rich( method append_message (line 580) | def append_message( method get_messages (line 637) | def get_messages(self, session_id: str) -> List[Dict[str, Any]]: method get_messages_as_conversation (line 656) | def get_messages_as_conversation(self, session_id: str) -> List[Dict[s... method _sanitize_fts5_query (line 688) | def _sanitize_fts5_query(query: str) -> str: method search_messages (line 737) | def search_messages( method search_sessions (line 832) | def search_sessions( method session_count (line 856) | def session_count(self, source: str = None) -> int: method message_count (line 866) | def message_count(self, session_id: str = None) -> int: method export_session (line 880) | def export_session(self, session_id: str) -> Optional[Dict[str, Any]]: method export_all (line 888) | def export_all(self, source: str = None) -> List[Dict[str, Any]]: method clear_messages (line 900) | def clear_messages(self, session_id: str) -> None: method delete_session (line 912) | def delete_session(self, session_id: str) -> bool: method prune_sessions (line 925) | def prune_sessions(self, older_than_days: int = 90, source: str = None... FILE: hermes_time.py function _resolve_timezone_name (line 37) | def _resolve_timezone_name() -> str: function _get_zoneinfo (line 65) | def _get_zoneinfo(name: str) -> Optional[ZoneInfo]: function get_timezone (line 79) | def get_timezone() -> Optional[ZoneInfo]: function get_timezone_name (line 92) | def get_timezone_name() -> str: function now (line 100) | def now() -> datetime: function reset_cache (line 114) | def reset_cache() -> None: FILE: honcho_integration/cli.py function _read_config (line 17) | def _read_config() -> dict: function _write_config (line 26) | def _write_config(cfg: dict) -> None: function _resolve_api_key (line 34) | def _resolve_api_key(cfg: dict) -> str: function _prompt (line 40) | def _prompt(label: str, default: str | None = None, secret: bool = False... function _ensure_sdk_installed (line 56) | def _ensure_sdk_installed() -> bool: function cmd_setup (line 86) | def cmd_setup(args) -> None: function cmd_status (line 216) | def cmd_status(args) -> None: function cmd_sessions (line 270) | def cmd_sessions(args) -> None: function cmd_map (line 289) | def cmd_map(args) -> None: function cmd_peer (line 314) | def cmd_peer(args) -> None: function cmd_mode (line 367) | def cmd_mode(args) -> None: function cmd_tokens (line 398) | def cmd_tokens(args) -> None: function cmd_identity (line 440) | def cmd_identity(args) -> None: function cmd_migrate (line 514) | def cmd_migrate(args) -> None: function honcho_command (line 742) | def honcho_command(args) -> None: FILE: honcho_integration/client.py function _normalize_recall_mode (line 34) | def _normalize_recall_mode(val: str) -> str: function _resolve_memory_mode (line 40) | def _resolve_memory_mode( class HonchoClientConfig (line 65) | class HonchoClientConfig: method peer_memory_mode (line 87) | def peer_memory_mode(self, peer_name: str) -> str: method from_env (line 117) | def from_env(cls, workspace_id: str = "hermes") -> HonchoClientConfig: method from_global_config (line 130) | def from_global_config( method _git_repo_name (line 259) | def _git_repo_name(cwd: str) -> str | None: method resolve_session_name (line 274) | def resolve_session_name( method get_linked_workspaces (line 331) | def get_linked_workspaces(self) -> list[str]: function get_honcho_client (line 346) | def get_honcho_client(config: HonchoClientConfig | None = None) -> Honcho: function reset_honcho_client (line 408) | def reset_honcho_client() -> None: FILE: honcho_integration/session.py class HonchoSession (line 25) | class HonchoSession: method add_message (line 42) | def add_message(self, role: str, content: str, **kwargs: Any) -> None: method get_history (line 53) | def get_history(self, max_messages: int = 50) -> list[dict[str, Any]]: method clear (line 62) | def clear(self) -> None: class HonchoSessionManager (line 68) | class HonchoSessionManager: method __init__ (line 76) | def __init__( method honcho (line 127) | def honcho(self) -> Honcho: method _get_or_create_peer (line 133) | def _get_or_create_peer(self, peer_id: str) -> Any: method _get_or_create_honcho_session (line 147) | def _get_or_create_honcho_session( method _sanitize_id (line 206) | def _sanitize_id(self, id_str: str) -> str: method get_or_create (line 210) | def get_or_create(self, key: str) -> HonchoSession: method _flush_session (line 273) | def _flush_session(self, session: HonchoSession) -> bool: method _async_writer_loop (line 310) | def _async_writer_loop(self) -> None: method save (line 349) | def save(self, session: HonchoSession) -> None: method flush_all (line 373) | def flush_all(self) -> None: method shutdown (line 395) | def shutdown(self) -> None: method delete (line 402) | def delete(self, key: str) -> bool: method new_session (line 409) | def new_session(self, key: str) -> HonchoSession: method _dynamic_reasoning_level (line 438) | def _dynamic_reasoning_level(self, query: str) -> str: method dialectic_query (line 464) | def dialectic_query( method prefetch_dialectic (line 504) | def prefetch_dialectic(self, session_key: str, query: str) -> None: method set_dialectic_result (line 524) | def set_dialectic_result(self, session_key: str, result: str) -> None: method pop_dialectic_result (line 531) | def pop_dialectic_result(self, session_key: str) -> str: method prefetch_context (line 540) | def prefetch_context(self, session_key: str, user_message: str | None ... method set_context_result (line 555) | def set_context_result(self, session_key: str, result: dict[str, str])... method pop_context_result (line 562) | def pop_context_result(self, session_key: str) -> dict[str, str]: method get_prefetch_context (line 571) | def get_prefetch_context(self, session_key: str, user_message: str | N... method migrate_local_history (line 626) | def migrate_local_history(self, session_key: str, messages: list[dict[... method _format_migration_transcript (line 668) | def _format_migration_transcript(session_key: str, messages: list[dict... method migrate_memory_files (line 698) | def migrate_memory_files(self, session_key: str, memory_dir: str) -> b... method get_peer_card (line 797) | def get_peer_card(self, session_key: str) -> list[str]: method search_context (line 826) | def search_context(self, session_key: str, query: str, max_tokens: int... method create_conclusion (line 870) | def create_conclusion(self, session_key: str, content: str) -> bool: method seed_ai_identity (line 905) | def seed_ai_identity(self, session_key: str, content: str, source: str... method get_ai_representation (line 950) | def get_ai_representation(self, session_key: str) -> dict[str, str]: method list_sessions (line 981) | def list_sessions(self) -> list[dict[str, Any]]: FILE: landingpage/script.js constant PLATFORMS (line 6) | const PLATFORMS = { function detectPlatform (line 17) | function detectPlatform() { function switchPlatform (line 21) | function switchPlatform(platform) { function switchStepPlatform (line 43) | function switchStepPlatform(platform) { function toggleMobileNav (line 61) | function toggleMobileNav() { function toggleSpecs (line 66) | function toggleSpecs() { function copyInstall (line 98) | function copyInstall() { function copyText (line 112) | function copyText(btn) { function initScrollAnimations (line 126) | function initScrollAnimations() { constant CURSOR (line 161) | const CURSOR = ''; class TerminalDemo (line 314) | class TerminalDemo { method constructor (line 315) | constructor(container) { method start (line 321) | async start() { method stop (line 335) | stop() { method execute (line 339) | async execute(step) { method append (line 367) | append(html) { method render (line 372) | render() { method clear (line 377) | clear() { method sleep (line 382) | sleep(ms) { function initNoiseOverlay (line 388) | function initNoiseOverlay() { FILE: mini_swe_runner.py function create_environment (line 105) | def create_environment( class MiniSWERunner (line 145) | class MiniSWERunner: method __init__ (line 151) | def __init__( method _create_env (line 231) | def _create_env(self): method _cleanup_env (line 242) | def _cleanup_env(self): method _execute_command (line 251) | def _execute_command(self, command: str, timeout: int = None) -> Dict[... method _format_tools_for_system_message (line 279) | def _format_tools_for_system_message(self) -> str: method _convert_to_hermes_format (line 292) | def _convert_to_hermes_format( method run_task (line 401) | def run_task(self, task: str) -> Dict[str, Any]: method run_batch (line 560) | def run_batch( function main (line 617) | def main( FILE: minisweagent_path.py function _read_gitdir (line 20) | def _read_gitdir(repo_root: Path) -> Optional[Path]: function discover_minisweagent_src (line 44) | def discover_minisweagent_src(repo_root: Optional[Path] = None) -> Optio... function ensure_minisweagent_on_path (line 76) | def ensure_minisweagent_on_path(repo_root: Optional[Path] = None) -> Opt... FILE: model_tools.py function _get_tool_loop (line 45) | def _get_tool_loop(): function _get_worker_loop (line 60) | def _get_worker_loop(): function _run_async (line 82) | def _run_async(coro): function _discover_tools (line 133) | def _discover_tools(): function get_tool_definitions (line 235) | def get_tool_definitions( function handle_function_call (line 373) | def handle_function_call( function get_all_tool_names (line 455) | def get_all_tool_names() -> List[str]: function get_toolset_for_tool (line 460) | def get_toolset_for_tool(tool_name: str) -> Optional[str]: function get_available_toolsets (line 465) | def get_available_toolsets() -> Dict[str, dict]: function check_toolset_requirements (line 470) | def check_toolset_requirements() -> Dict[str, bool]: function check_tool_availability (line 475) | def check_tool_availability(quiet: bool = False) -> Tuple[List[str], Lis... FILE: optional-skills/blockchain/base/scripts/base_client.py function _http_get_json (line 80) | def _http_get_json(url: str, timeout: int = 10, retries: int = 2) -> Any: function _rpc_call (line 99) | def _rpc_call(method: str, params: list = None, retries: int = 2) -> Any: function _rpc_batch_chunk (line 140) | def _rpc_batch_chunk(items: list) -> list: function rpc_batch (line 166) | def rpc_batch(calls: list) -> list: function wei_to_eth (line 184) | def wei_to_eth(wei: int) -> float: function wei_to_gwei (line 188) | def wei_to_gwei(wei: int) -> float: function hex_to_int (line 192) | def hex_to_int(hex_str: Optional[str]) -> int: function print_json (line 199) | def print_json(obj: Any) -> None: function _short_addr (line 203) | def _short_addr(addr: str) -> str: function _encode_address (line 214) | def _encode_address(addr: str) -> str: function _decode_uint (line 220) | def _decode_uint(hex_data: Optional[str]) -> int: function _decode_string (line 227) | def _decode_string(hex_data: Optional[str]) -> str: function _eth_call (line 242) | def _eth_call(to: str, selector: str, args: str = "", block: str = "late... function fetch_prices (line 268) | def fetch_prices(addresses: List[str], max_lookups: int = 20) -> Dict[st... function fetch_eth_price (line 293) | def fetch_eth_price() -> Optional[float]: function resolve_token_name (line 303) | def resolve_token_name(addr: str) -> Optional[Dict[str, str]]: function _token_label (line 322) | def _token_label(addr: str) -> str: function cmd_stats (line 334) | def cmd_stats(_args): function cmd_wallet (line 382) | def cmd_wallet(args): function cmd_tx (line 498) | def cmd_tx(args): function cmd_token (line 603) | def cmd_token(args): function cmd_gas (line 663) | def cmd_gas(_args): function cmd_contract (line 757) | def cmd_contract(args): function cmd_whales (line 872) | def cmd_whales(args): function cmd_price (line 915) | def cmd_price(args): function main (line 956) | def main(): FILE: optional-skills/blockchain/solana/scripts/solana_client.py function _http_get_json (line 74) | def _http_get_json(url: str, timeout: int = 10, retries: int = 2) -> Any: function _rpc_call (line 93) | def _rpc_call(method: str, params: list = None, retries: int = 2) -> Any: function rpc_batch (line 131) | def rpc_batch(calls: list) -> list: function lamports_to_sol (line 156) | def lamports_to_sol(lamports: int) -> float: function print_json (line 160) | def print_json(obj: Any) -> None: function _short_mint (line 164) | def _short_mint(mint: str) -> str: function fetch_prices (line 175) | def fetch_prices(mints: List[str], max_lookups: int = 20) -> Dict[str, f... function fetch_sol_price (line 200) | def fetch_sol_price() -> Optional[float]: function resolve_token_name (line 210) | def resolve_token_name(mint: str) -> Optional[Dict[str, str]]: function _token_label (line 225) | def _token_label(mint: str) -> str: function cmd_stats (line 236) | def cmd_stats(_args): function cmd_wallet (line 284) | def cmd_wallet(args): function cmd_tx (line 396) | def cmd_tx(args): function cmd_token (line 451) | def cmd_token(args): function cmd_activity (line 499) | def cmd_activity(args): function cmd_nft (line 521) | def cmd_nft(args): function cmd_whales (line 548) | def cmd_whales(args): function cmd_price (line 614) | def cmd_price(args): function main (line 643) | def main(): FILE: optional-skills/mcp/fastmcp/scripts/scaffold_fastmcp.py function list_templates (line 16) | def list_templates() -> list[str]: function render_template (line 20) | def render_template(template_name: str, server_name: str) -> str: function main (line 28) | def main() -> int: FILE: optional-skills/mcp/fastmcp/templates/api_wrapper.py function _headers (line 17) | def _headers() -> dict[str, str]: function _request (line 24) | def _request(method: str, path: str, *, params: dict[str, Any] | None = ... function health_check (line 33) | def health_check() -> dict[str, Any]: function get_resource (line 40) | def get_resource(resource_id: str) -> dict[str, Any]: function search_resources (line 47) | def search_resources(query: str, limit: int = 10) -> dict[str, Any]: FILE: optional-skills/mcp/fastmcp/templates/database_server.py function _connect (line 18) | def _connect() -> sqlite3.Connection: function _reject_mutation (line 22) | def _reject_mutation(sql: str) -> None: function _validate_table_name (line 28) | def _validate_table_name(table_name: str) -> str: function list_tables (line 35) | def list_tables() -> list[str]: function describe_table (line 45) | def describe_table(table_name: str) -> list[dict[str, Any]]: function query (line 64) | def query(sql: str, limit: int = 50) -> dict[str, Any]: FILE: optional-skills/mcp/fastmcp/templates/file_processor.py function _read_text (line 12) | def _read_text(path: str) -> str: function summarize_text_file (line 23) | def summarize_text_file(path: str, preview_chars: int = 1200) -> dict[st... function search_text_file (line 36) | def search_text_file(path: str, needle: str, max_matches: int = 20) -> d... function read_file_resource (line 49) | def read_file_resource(path: str) -> str: FILE: optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py class ItemResult (line 148) | class ItemResult: function parse_selection_values (line 157) | def parse_selection_values(values: Optional[Sequence[str]]) -> List[str]: function resolve_selected_options (line 167) | def resolve_selected_options( function sha256_file (line 207) | def sha256_file(path: Path) -> str: function read_text (line 215) | def read_text(path: Path) -> str: function normalize_text (line 219) | def normalize_text(text: str) -> str: function ensure_parent (line 223) | def ensure_parent(path: Path) -> None: function load_yaml_file (line 227) | def load_yaml_file(path: Path) -> Dict[str, Any]: function dump_yaml_file (line 234) | def dump_yaml_file(path: Path, data: Dict[str, Any]) -> None: function parse_env_file (line 244) | def parse_env_file(path: Path) -> Dict[str, str]: function save_env_file (line 257) | def save_env_file(path: Path, data: Dict[str, str]) -> None: function backup_existing (line 263) | def backup_existing(path: Path, backup_root: Path) -> Optional[Path]: function parse_existing_memory_entries (line 276) | def parse_existing_memory_entries(path: Path) -> List[str]: function extract_markdown_entries (line 287) | def extract_markdown_entries(text: str) -> List[str]: function merge_entries (line 363) | def merge_entries( function relative_label (line 397) | def relative_label(path: Path, root: Path) -> str: function write_report (line 404) | def write_report(output_dir: Path, report: Dict[str, Any]) -> None: class Migrator (line 444) | class Migrator: method __init__ (line 445) | def __init__( method is_selected (line 489) | def is_selected(self, option_id: str) -> bool: method record (line 492) | def record( method source_candidate (line 512) | def source_candidate(self, *relative_paths: str) -> Optional[Path]: method resolve_skill_destination (line 519) | def resolve_skill_destination(self, destination: Path) -> Path: method migrate (line 531) | def migrate(self) -> Dict[str, Any]: method run_if_selected (line 583) | def run_if_selected(self, option_id: str, func) -> None: method build_report (line 590) | def build_report(self) -> Dict[str, Any]: method maybe_backup (line 633) | def maybe_backup(self, path: Path) -> Optional[Path]: method write_overflow_entries (line 638) | def write_overflow_entries(self, kind: str, entries: Sequence[str]) ->... method copy_file (line 647) | def copy_file(self, source: Path, destination: Path, kind: str) -> None: method migrate_soul (line 667) | def migrate_soul(self) -> None: method migrate_workspace_agents (line 674) | def migrate_workspace_agents(self) -> None: method migrate_memory (line 688) | def migrate_memory(self, source: Optional[Path], destination: Path, li... method migrate_command_allowlist (line 731) | def migrate_command_allowlist(self) -> None: method load_openclaw_config (line 790) | def load_openclaw_config(self) -> Dict[str, Any]: method merge_env_values (line 800) | def merge_env_values(self, additions: Dict[str, str], kind: str, sourc... method migrate_messaging_settings (line 846) | def migrate_messaging_settings(self, config: Optional[Dict[str, Any]] ... method handle_secret_settings (line 876) | def handle_secret_settings(self, config: Optional[Dict[str, Any]] = No... method migrate_secret_settings (line 902) | def migrate_secret_settings(self, config: Dict[str, Any]) -> None: method migrate_discord_settings (line 925) | def migrate_discord_settings(self, config: Optional[Dict[str, Any]] = ... method migrate_slack_settings (line 943) | def migrate_slack_settings(self, config: Optional[Dict[str, Any]] = No... method migrate_whatsapp_settings (line 964) | def migrate_whatsapp_settings(self, config: Optional[Dict[str, Any]] =... method migrate_signal_settings (line 979) | def migrate_signal_settings(self, config: Optional[Dict[str, Any]] = N... method handle_provider_keys (line 1000) | def handle_provider_keys(self, config: Optional[Dict[str, Any]] = None... method migrate_provider_keys (line 1015) | def migrate_provider_keys(self, config: Dict[str, Any]) -> None: method migrate_model_config (line 1083) | def migrate_model_config(self, config: Optional[Dict[str, Any]] = None... method migrate_tts_config (line 1125) | def migrate_tts_config(self, config: Optional[Dict[str, Any]] = None) ... method migrate_shared_skills (line 1198) | def migrate_shared_skills(self) -> None: method migrate_daily_memory (line 1252) | def migrate_daily_memory(self) -> None: method migrate_skills (line 1307) | def migrate_skills(self) -> None: method copy_tree_non_destructive (line 1361) | def copy_tree_non_destructive( method archive_docs (line 1414) | def archive_docs(self) -> None: method archive_path (line 1450) | def archive_path(self, source: Path, reason: str) -> None: function parse_args (line 1463) | def parse_args() -> argparse.Namespace: function main (line 1507) | def main() -> int: FILE: optional-skills/productivity/telephony/scripts/telephony.py class TelephonyError (line 59) | class TelephonyError(RuntimeError): class OwnedTwilioNumber (line 64) | class OwnedTwilioNumber: function _hermes_home (line 71) | def _hermes_home() -> Path: function _env_path (line 75) | def _env_path() -> Path: function _config_path (line 79) | def _config_path() -> Path: function _state_path (line 83) | def _state_path() -> Path: function _load_root_config (line 87) | def _load_root_config() -> dict[str, Any]: function _config_lookup (line 103) | def _config_lookup(*paths: tuple[str, ...], default: str = "") -> str: function _load_dotenv_values (line 117) | def _load_dotenv_values(path: Path | None = None) -> dict[str, str]: function _env_or_config (line 135) | def _env_or_config(env_key: str, *config_paths: tuple[str, ...], default... function _load_state (line 145) | def _load_state(path: Path | None = None) -> dict[str, Any]: function _save_state (line 159) | def _save_state(state: dict[str, Any], path: Path | None = None) -> Path: function _quote_env_value (line 166) | def _quote_env_value(value: str) -> str: function _upsert_env_file (line 173) | def _upsert_env_file(updates: dict[str, str], env_path: Path | None = No... function _normalize_phone (line 206) | def _normalize_phone(number: str) -> str: function _mask_phone (line 220) | def _mask_phone(number: str) -> str: function _parse_twilio_date (line 227) | def _parse_twilio_date(value: str | None) -> datetime | None: function _json_request (line 237) | def _json_request( function _twilio_creds (line 275) | def _twilio_creds() -> tuple[str, str]: function _twilio_basic_headers (line 294) | def _twilio_basic_headers() -> dict[str, str]: function _twilio_request (line 300) | def _twilio_request(method: str, path: str, *, params=None, form=None) -... function _twilio_owned_numbers (line 311) | def _twilio_owned_numbers(limit: int = 50) -> list[OwnedTwilioNumber]: function _remember_twilio_number (line 330) | def _remember_twilio_number( function _remember_vapi_number (line 359) | def _remember_vapi_number( function _resolve_twilio_number (line 382) | def _resolve_twilio_number(identifier: str | None = None) -> OwnedTwilio... function _vapi_api_key (line 427) | def _vapi_api_key() -> str: function _vapi_phone_number_id (line 435) | def _vapi_phone_number_id() -> str: function _bland_api_key (line 446) | def _bland_api_key() -> str: function _ai_provider (line 454) | def _ai_provider(default: str = DEFAULT_AI_PROVIDER) -> str: function _twilio_search_numbers (line 463) | def _twilio_search_numbers( function _twilio_buy_number (line 512) | def _twilio_buy_number( function _twilio_list_owned (line 542) | def _twilio_list_owned() -> dict[str, Any]: function _twilio_set_default (line 560) | def _twilio_set_default(identifier: str, *, save_env: bool = False) -> d... function _twiml_say (line 579) | def _twiml_say(message: str, voice: str) -> str: function _twiml_play (line 583) | def _twiml_play(audio_url: str) -> str: function _twilio_call (line 587) | def _twilio_call( function _twilio_call_status (line 627) | def _twilio_call_status(call_sid: str) -> dict[str, Any]: function _twilio_send_sms (line 644) | def _twilio_send_sms( function _checkpoint_for_messages (line 675) | def _checkpoint_for_messages(messages: list[dict[str, Any]]) -> tuple[st... function _messages_after_checkpoint (line 682) | def _messages_after_checkpoint(messages: list[dict[str, Any]], last_sid:... function _twilio_inbox (line 693) | def _twilio_inbox( function _vapi_import_twilio_number (line 749) | def _vapi_import_twilio_number( function _bland_call (line 795) | def _bland_call( function _bland_status (line 845) | def _bland_status(call_id: str, analyze: str | None = None) -> dict[str,... function _vapi_call (line 873) | def _vapi_call( function _vapi_status (line 948) | def _vapi_status(call_id: str) -> dict[str, Any]: function _provider_decision_tree (line 971) | def _provider_decision_tree() -> list[dict[str, str]]: function diagnose (line 996) | def diagnose() -> dict[str, Any]: function save_twilio (line 1079) | def save_twilio(account_sid: str, auth_token: str, phone_number: str = "... function save_bland (line 1101) | def save_bland(api_key: str, voice: str = BLAND_DEFAULT_VOICE) -> dict[s... function save_vapi (line 1118) | def save_vapi( function _build_parser (line 1148) | def _build_parser() -> argparse.ArgumentParser: function _dispatch (line 1233) | def _dispatch(args: argparse.Namespace) -> dict[str, Any]: function main (line 1330) | def main(argv: list[str] | None = None) -> int: FILE: optional-skills/security/oss-forensics/scripts/evidence-store.py function _now_iso (line 51) | def _now_iso(): function _sha256 (line 55) | def _sha256(content: str) -> str: class EvidenceStore (line 59) | class EvidenceStore: method __init__ (line 60) | def __init__(self, filepath: str): method _save (line 82) | def _save(self): method _next_id (line 87) | def _next_id(self) -> str: method add (line 90) | def add( method list_evidence (line 127) | def list_evidence(self, filter_type: str = None, filter_actor: str = N... method verify_integrity (line 135) | def verify_integrity(self): method query (line 149) | def query(self, keyword: str): method export_markdown (line 160) | def export_markdown(self) -> str: method summary (line 191) | def summary(self) -> dict: function main (line 210) | def main(): FILE: rl_cli.py function load_hermes_config (line 70) | def load_hermes_config() -> dict: function check_requirements (line 181) | def check_requirements(): function check_tinker_atropos (line 203) | def check_tinker_atropos(): function list_environments_sync (line 220) | def list_environments_sync(): function main (line 236) | def main( FILE: run_agent.py class _SafeWriter (line 110) | class _SafeWriter: method __init__ (line 126) | def __init__(self, inner): method write (line 129) | def write(self, data): method flush (line 135) | def flush(self): method fileno (line 141) | def fileno(self): method isatty (line 144) | def isatty(self): method __getattr__ (line 150) | def __getattr__(self, name): function _install_safe_stdio (line 154) | def _install_safe_stdio() -> None: class IterationBudget (line 162) | class IterationBudget: method __init__ (line 173) | def __init__(self, max_total: int): method consume (line 178) | def consume(self) -> bool: method refund (line 186) | def refund(self) -> None: method used (line 193) | def used(self) -> int: method remaining (line 197) | def remaining(self) -> int: function _is_destructive_command (line 247) | def _is_destructive_command(cmd: str) -> bool: function _should_parallelize_tool_batch (line 258) | def _should_parallelize_tool_batch(tool_calls) -> bool: function _extract_parallel_scope_path (line 302) | def _extract_parallel_scope_path(tool_name: str, function_args: dict) ->... function _paths_overlap (line 315) | def _paths_overlap(left: Path, right: Path) -> bool: function _inject_honcho_turn_context (line 326) | def _inject_honcho_turn_context(content, turn_context: str): class AIAgent (line 352) | class AIAgent: method base_url (line 361) | def base_url(self) -> str: method base_url (line 365) | def base_url(self, value: str) -> None: method __init__ (line 369) | def __init__( method reset_session_state (line 1060) | def reset_session_state(self): method _safe_print (line 1101) | def _safe_print(*args, **kwargs): method _vprint (line 1113) | def _vprint(self, *args, force: bool = False, **kwargs): method _is_direct_openai_url (line 1127) | def _is_direct_openai_url(self, base_url: str = None) -> bool: method _max_tokens_param (line 1132) | def _max_tokens_param(self, value: int) -> dict: method _has_content_after_think_block (line 1143) | def _has_content_after_think_block(self, content: str) -> bool: method _strip_think_blocks (line 1166) | def _strip_think_blocks(self, content: str) -> str: method _looks_like_codex_intermediate_ack (line 1178) | def _looks_like_codex_intermediate_ack( method _extract_reasoning (line 1250) | def _extract_reasoning(self, assistant_message) -> Optional[str]: method _cleanup_task_resources (line 1293) | def _cleanup_task_resources(self, task_id: str) -> None: method _spawn_background_review (line 1345) | def _spawn_background_review( method _apply_persist_user_message_override (line 1398) | def _apply_persist_user_message_override(self, messages: List[Dict]) -... method _persist_session (line 1416) | def _persist_session(self, messages: List[Dict], conversation_history:... method _flush_messages_to_session_db (line 1426) | def _flush_messages_to_session_db(self, messages: List[Dict], conversa... method _get_messages_up_to_last_assistant (line 1463) | def _get_messages_up_to_last_assistant(self, messages: List[Dict]) -> ... method _format_tools_for_system_message (line 1494) | def _format_tools_for_system_message(self) -> str: method _convert_to_trajectory_format (line 1518) | def _convert_to_trajectory_format(self, messages: List[Dict[str, Any]]... method _save_trajectory (line 1682) | def _save_trajectory(self, messages: List[Dict[str, Any]], user_query:... method _mask_api_key_for_logs (line 1697) | def _mask_api_key_for_logs(self, key: Optional[str]) -> Optional[str]: method _dump_api_request_debug (line 1704) | def _dump_api_request_debug( method _clean_session_content (line 1787) | def _clean_session_content(content: str) -> str: method _save_session_log (line 1796) | def _save_session_log(self, messages: List[Dict[str, Any]] = None): method interrupt (line 1845) | def interrupt(self, message: str = None) -> None: method clear_interrupt (line 1884) | def clear_interrupt(self) -> None: method _hydrate_todo_store (line 1890) | def _hydrate_todo_store(self, history: List[Dict[str, Any]]) -> None: method is_interrupted (line 1923) | def is_interrupted(self) -> bool: method _honcho_should_activate (line 1929) | def _honcho_should_activate(self, hcfg) -> bool: method _strip_honcho_tools_from_surface (line 1935) | def _strip_honcho_tools_from_surface(self) -> None: method _activate_honcho (line 1949) | def _activate_honcho( method _register_honcho_exit_hook (line 2034) | def _register_honcho_exit_hook(self) -> None: method _queue_honcho_prefetch (line 2053) | def _queue_honcho_prefetch(self, user_message: str) -> None: method _honcho_prefetch (line 2068) | def _honcho_prefetch(self, user_message: str) -> str: method _honcho_save_user_observation (line 2107) | def _honcho_save_user_observation(self, content: str) -> str: method _honcho_sync (line 2128) | def _honcho_sync(self, user_content: str, assistant_content: str) -> N... method _build_system_prompt (line 2144) | def _build_system_prompt(self, system_message: str = None) -> str: method _get_tool_call_id_static (line 2306) | def _get_tool_call_id_static(tc) -> str: method _sanitize_api_messages (line 2313) | def _sanitize_api_messages(messages: List[Dict[str, Any]]) -> List[Dic... method _cap_delegate_task_calls (line 2371) | def _cap_delegate_task_calls(tool_calls: list) -> list: method _deduplicate_tool_calls (line 2401) | def _deduplicate_tool_calls(tool_calls: list) -> list: method _repair_tool_call (line 2418) | def _repair_tool_call(self, tool_name: str) -> str | None: method _invalidate_system_prompt (line 2446) | def _invalidate_system_prompt(self): method _responses_tools (line 2457) | def _responses_tools(self, tools: Optional[List[Dict[str, Any]]] = Non... method _split_responses_tool_id (line 2479) | def _split_responses_tool_id(raw_id: Any) -> tuple[Optional[str], Opti... method _derive_responses_function_call_id (line 2495) | def _derive_responses_function_call_id( method _chat_messages_to_responses_input (line 2524) | def _chat_messages_to_responses_input(self, messages: List[Dict[str, A... method _preflight_codex_input_items (line 2621) | def _preflight_codex_input_items(self, raw_items: Any) -> List[Dict[st... method _preflight_codex_api_kwargs (line 2707) | def _preflight_codex_api_kwargs( method _extract_responses_message_text (line 2831) | def _extract_responses_message_text(self, item: Any) -> str: method _extract_responses_reasoning_text (line 2847) | def _extract_responses_reasoning_text(self, item: Any) -> str: method _normalize_codex_response (line 2863) | def _normalize_codex_response(self, response: Any) -> tuple[Any, str]: method _thread_identity (line 3012) | def _thread_identity(self) -> str: method _client_log_context (line 3016) | def _client_log_context(self) -> str: method _openai_client_lock (line 3025) | def _openai_client_lock(self) -> threading.RLock: method _is_openai_client_closed (line 3033) | def _is_openai_client_closed(client: Any) -> bool: method _create_openai_client (line 3043) | def _create_openai_client(self, client_kwargs: dict, *, reason: str, s... method _close_openai_client (line 3064) | def _close_openai_client(self, client: Any, *, reason: str, shared: bo... method _replace_primary_openai_client (line 3084) | def _replace_primary_openai_client(self, *, reason: str) -> bool: method _ensure_primary_openai_client (line 3101) | def _ensure_primary_openai_client(self, *, reason: str) -> Any: method _create_request_openai_client (line 3117) | def _create_request_openai_client(self, *, reason: str) -> Any: method _close_request_openai_client (line 3127) | def _close_request_openai_client(self, client: Any, *, reason: str) ->... method _run_codex_stream (line 3130) | def _run_codex_stream(self, api_kwargs: dict, client: Any = None, on_f... method _run_codex_create_stream_fallback (line 3183) | def _run_codex_create_stream_fallback(self, api_kwargs: dict, client: ... method _try_refresh_codex_client_credentials (line 3223) | def _try_refresh_codex_client_credentials(self, *, force: bool = True)... method _try_refresh_nous_client_credentials (line 3252) | def _try_refresh_nous_client_credentials(self, *, force: bool = True) ... method _try_refresh_anthropic_client_credentials (line 3287) | def _try_refresh_anthropic_client_credentials(self) -> bool: method _anthropic_messages_create (line 3322) | def _anthropic_messages_create(self, api_kwargs: dict): method _interruptible_api_call (line 3327) | def _interruptible_api_call(self, api_kwargs: dict): method _fire_stream_delta (line 3390) | def _fire_stream_delta(self, text: str) -> None: method _fire_reasoning_delta (line 3399) | def _fire_reasoning_delta(self, text: str) -> None: method _has_stream_consumers (line 3408) | def _has_stream_consumers(self) -> bool: method _interruptible_streaming_api_call (line 3415) | def _interruptible_streaming_api_call( method _try_activate_fallback (line 3660) | def _try_activate_fallback(self) -> bool: method _content_has_image_parts (line 3752) | def _content_has_image_parts(content: Any) -> bool: method _materialize_data_url_for_vision (line 3761) | def _materialize_data_url_for_vision(image_url: str) -> tuple[str, Opt... method _describe_image_for_anthropic_fallback (line 3781) | def _describe_image_for_anthropic_fallback(self, image_url: str, role:... method _preprocess_anthropic_content (line 3832) | def _preprocess_anthropic_content(self, content: Any, role: str) -> Any: method _prepare_anthropic_messages_for_api (line 3876) | def _prepare_anthropic_messages_for_api(self, api_messages: list) -> l... method _build_api_kwargs (line 3893) | def _build_api_kwargs(self, api_messages: list) -> dict: method _supports_reasoning_extra_body (line 4067) | def _supports_reasoning_extra_body(self) -> bool: method _github_models_reasoning_extra_body (line 4101) | def _github_models_reasoning_extra_body(self) -> dict | None: method _build_assistant_message (line 4133) | def _build_assistant_message(self, assistant_message, finish_reason: s... method _sanitize_tool_calls_for_strict_api (line 4239) | def _sanitize_tool_calls_for_strict_api(api_msg: dict) -> dict: method flush_memories (line 4263) | def flush_memories(self, messages: list = None, min_turns: int = None): method _compress_context (line 4425) | def _compress_context(self, messages: list, system_message: str, *, ap... method _execute_tool_calls (line 4476) | def _execute_tool_calls(self, assistant_message, messages: list, effec... method _invoke_tool (line 4499) | def _invoke_tool(self, function_name: str, function_args: dict, effect... method _execute_tool_calls_concurrent (line 4563) | def _execute_tool_calls_concurrent(self, assistant_message, messages: ... method _execute_tool_calls_sequential (line 4752) | def _execute_tool_calls_sequential(self, assistant_message, messages: ... method _get_budget_warning (line 5030) | def _get_budget_warning(self, api_call_count: int) -> Optional[str]: method _emit_context_pressure (line 5054) | def _emit_context_pressure(self, compaction_progress: float, compresso... method _handle_max_iterations (line 5093) | def _handle_max_iterations(self, messages: list, api_call_count: int) ... method run_conversation (line 5242) | def run_conversation( method chat (line 7010) | def chat(self, message: str, stream_callback: Optional[callable] = Non... function main (line 7025) | def main( FILE: scripts/discord-voice-doctor.py function mask (line 33) | def mask(value): function check (line 40) | def check(label, ok, detail=""): function warn (line 49) | def warn(label, detail=""): function section (line 56) | def section(title): function check_packages (line 60) | def check_packages(): function check_system_tools (line 121) | def check_system_tools(): function check_env_vars (line 173) | def check_env_vars(): function check_config (line 234) | def check_config(groq_key, eleven_key): function check_bot_permissions (line 274) | def check_bot_permissions(token): function main (line 363) | def main(): FILE: scripts/release.py function git (line 118) | def git(*args, cwd=None): function get_last_tag (line 131) | def get_last_tag(): function get_current_version (line 139) | def get_current_version(): function bump_version (line 146) | def bump_version(current: str, part: str) -> str: function update_version_files (line 168) | def update_version_files(semver: str, calver_date: str): function resolve_author (line 195) | def resolve_author(name: str, email: str) -> str: function categorize_commit (line 216) | def categorize_commit(subject: str) -> str: function clean_subject (line 250) | def clean_subject(subject: str) -> str: function get_commits (line 262) | def get_commits(since_tag=None): function get_pr_number (line 300) | def get_pr_number(subject: str) -> str: function generate_changelog (line 308) | def generate_changelog(commits, tag_name, semver, repo_url="https://gith... function main (line 406) | def main(): FILE: scripts/sample_and_compress.py function load_dataset_from_hf (line 40) | def load_dataset_from_hf(dataset_name: str) -> List[Dict[str, Any]]: function _init_tokenizer_worker (line 82) | def _init_tokenizer_worker(tokenizer_name: str): function _count_tokens_for_entry (line 89) | def _count_tokens_for_entry(entry: Dict) -> Tuple[Dict, int]: function sample_from_datasets (line 118) | def sample_from_datasets( function save_samples_for_compression (line 226) | def save_samples_for_compression( function run_compression (line 260) | def run_compression(input_dir: Path, output_dir: Path, config_path: str): function merge_output_to_single_jsonl (line 289) | def merge_output_to_single_jsonl(input_dir: Path, output_file: Path): function main (line 318) | def main( FILE: scripts/whatsapp-bridge/bridge.js function getArg (line 32) | function getArg(name, defaultVal) { constant WHATSAPP_DEBUG (line 37) | const WHATSAPP_DEBUG = constant PORT (line 43) | const PORT = parseInt(getArg('port', '3000'), 10); constant SESSION_DIR (line 44) | const SESSION_DIR = getArg('session', path.join(process.env.HOME || '~',... constant IMAGE_CACHE_DIR (line 45) | const IMAGE_CACHE_DIR = path.join(process.env.HOME || '~', '.hermes', 'i... constant PAIR_ONLY (line 46) | const PAIR_ONLY = args.includes('--pair-only'); constant WHATSAPP_MODE (line 47) | const WHATSAPP_MODE = getArg('mode', process.env.WHATSAPP_MODE || 'self-... constant ALLOWED_USERS (line 48) | const ALLOWED_USERS = (process.env.WHATSAPP_ALLOWED_USERS || '').split('... constant DEFAULT_REPLY_PREFIX (line 49) | const DEFAULT_REPLY_PREFIX = '⚕ *Hermes Agent*\n────────────\n'; constant REPLY_PREFIX (line 50) | const REPLY_PREFIX = process.env.WHATSAPP_REPLY_PREFIX === undefined function formatOutgoingMessage (line 54) | function formatOutgoingMessage(message) { function buildLidMap (line 61) | function buildLidMap() { constant MAX_QUEUE_SIZE (line 80) | const MAX_QUEUE_SIZE = 100; constant MAX_RECENT_IDS (line 84) | const MAX_RECENT_IDS = 50; function startSocket (line 89) | async function startSocket() { constant MIME_MAP (line 342) | const MIME_MAP = { function inferMediaType (line 353) | function inferMediaType(ext) { FILE: skills/creative/excalidraw/scripts/upload.py function concat_buffers (line 39) | def concat_buffers(*buffers: bytes) -> bytes: function upload (line 53) | def upload(excalidraw_json: str) -> str: function main (line 104) | def main(): FILE: skills/leisure/find-nearby/scripts/find_nearby.py function _http_get (line 36) | def _http_get(url: str) -> Any: function _http_post (line 42) | def _http_post(url: str, data: str) -> Any: function haversine (line 50) | def haversine(lat1: float, lon1: float, lat2: float, lon2: float) -> float: function geocode (line 60) | def geocode(query: str) -> tuple[float, float]: function find_nearby (line 70) | def find_nearby(lat: float, lon: float, types: list[str], radius: int = ... function main (line 138) | def main(): FILE: skills/media/youtube-content/scripts/fetch_transcript.py function extract_video_id (line 26) | def extract_video_id(url_or_id: str) -> str: function format_timestamp (line 40) | def format_timestamp(seconds: float) -> str: function fetch_transcript (line 50) | def fetch_transcript(video_id: str, languages: list = None): function main (line 64) | def main(): FILE: skills/mlops/training/grpo-rl-training/templates/basic_grpo_training.py function get_dataset (line 39) | def get_dataset(split="train"): function extract_xml_tag (line 66) | def extract_xml_tag(text: str, tag: str) -> str: function extract_answer (line 72) | def extract_answer(text: str) -> str: function correctness_reward_func (line 78) | def correctness_reward_func(prompts, completions, answer, **kwargs): function format_reward_func (line 87) | def format_reward_func(completions, **kwargs): function incremental_format_reward_func (line 96) | def incremental_format_reward_func(completions, **kwargs): function setup_model_and_tokenizer (line 126) | def setup_model_and_tokenizer(): function get_peft_config (line 140) | def get_peft_config(): function main (line 155) | def main(): FILE: skills/productivity/google-workspace/scripts/google_api.py function get_credentials (line 46) | def get_credentials(): function build_service (line 66) | def build_service(api, version): function gmail_search (line 75) | def gmail_search(args): function gmail_get (line 105) | def gmail_get(args): function gmail_send (line 142) | def gmail_send(args): function gmail_reply (line 160) | def gmail_reply(args): function gmail_labels (line 187) | def gmail_labels(args): function gmail_modify (line 194) | def gmail_modify(args): function calendar_list (line 209) | def calendar_list(args): function calendar_create (line 240) | def calendar_create(args): function calendar_delete (line 263) | def calendar_delete(args): function drive_search (line 273) | def drive_search(args): function contacts_list (line 287) | def contacts_list(args): function sheets_get (line 311) | def sheets_get(args): function sheets_update (line 319) | def sheets_update(args): function sheets_append (line 330) | def sheets_append(args): function docs_get (line 345) | def docs_get(args): function main (line 368) | def main(): FILE: skills/productivity/google-workspace/scripts/setup.py function install_deps (line 55) | def install_deps(): function _ensure_deps (line 79) | def _ensure_deps(): function check_auth (line 89) | def check_auth(): function store_client_secret (line 123) | def store_client_secret(path: str): function _save_pending_auth (line 145) | def _save_pending_auth(*, state: str, code_verifier: str): function _load_pending_auth (line 159) | def _load_pending_auth() -> dict: function _extract_code_and_state (line 180) | def _extract_code_and_state(code_or_url: str) -> tuple[str, str | None]: function get_auth_url (line 197) | def get_auth_url(): function exchange_auth_code (line 221) | def exchange_auth_code(code: str): function revoke (line 257) | def revoke(): function main (line 289) | def main(): FILE: skills/productivity/ocr-and-documents/scripts/extract_marker.py function convert (line 19) | def convert(path, output_dir=None, output_format="markdown", use_llm=Fal... function check_requirements (line 53) | def check_requirements(): FILE: skills/productivity/ocr-and-documents/scripts/extract_pymupdf.py function extract_text (line 15) | def extract_text(path, pages=None): function extract_markdown (line 24) | def extract_markdown(path, pages=None): function extract_tables (line 29) | def extract_tables(path): function extract_images (line 39) | def extract_images(path, output_dir): function show_metadata (line 56) | def show_metadata(path): FILE: skills/productivity/powerpoint/scripts/add_slide.py function get_next_slide_number (line 27) | def get_next_slide_number(slides_dir: Path) -> int: function create_slide_from_layout (line 33) | def create_slide_from_layout(unpacked_dir: Path, layout_file: str) -> None: function duplicate_slide (line 90) | def duplicate_slide(unpacked_dir: Path, source: str) -> None: function _add_to_content_types (line 130) | def _add_to_content_types(unpacked_dir: Path, dest: str) -> None: function _add_to_presentation_rels (line 141) | def _add_to_presentation_rels(unpacked_dir: Path, dest: str) -> str: function _get_next_slide_id (line 158) | def _get_next_slide_id(unpacked_dir: Path) -> int: function parse_source (line 165) | def parse_source(source: str) -> tuple[str, str | None]: FILE: skills/productivity/powerpoint/scripts/clean.py function get_slides_in_sldidlst (line 27) | def get_slides_in_sldidlst(unpacked_dir: Path) -> set[str]: function remove_orphaned_slides (line 49) | def remove_orphaned_slides(unpacked_dir: Path) -> list[str]: function remove_trash_directory (line 91) | def remove_trash_directory(unpacked_dir: Path) -> list[str]: function get_slide_referenced_files (line 106) | def get_slide_referenced_files(unpacked_dir: Path) -> set: function remove_orphaned_rels_files (line 128) | def remove_orphaned_rels_files(unpacked_dir: Path) -> list[str]: function get_referenced_files (line 153) | def get_referenced_files(unpacked_dir: Path) -> set: function remove_orphaned_files (line 171) | def remove_orphaned_files(unpacked_dir: Path, referenced: set) -> list[s... function update_content_types (line 221) | def update_content_types(unpacked_dir: Path, removed_files: list[str]) -... function clean_unused_files (line 241) | def clean_unused_files(unpacked_dir: Path) -> list[str]: FILE: skills/productivity/powerpoint/scripts/office/helpers/merge_runs.py function merge_runs (line 16) | def merge_runs(input_dir: str) -> tuple[int, str]: function _find_elements (line 44) | def _find_elements(root, tag: str) -> list: function _get_child (line 59) | def _get_child(parent, tag: str): function _get_children (line 68) | def _get_children(parent, tag: str) -> list: function _is_adjacent (line 78) | def _is_adjacent(elem1, elem2) -> bool: function _remove_elements (line 93) | def _remove_elements(root, tag: str): function _strip_run_rsid_attrs (line 99) | def _strip_run_rsid_attrs(root): function _merge_runs_in (line 108) | def _merge_runs_in(container) -> int: function _first_child_run (line 128) | def _first_child_run(container): function _next_element_sibling (line 135) | def _next_element_sibling(node): function _next_sibling_run (line 144) | def _next_sibling_run(node): function _is_run (line 154) | def _is_run(node) -> bool: function _can_merge (line 159) | def _can_merge(run1, run2) -> bool: function _merge_run_content (line 170) | def _merge_run_content(target, source): function _consolidate_text (line 178) | def _consolidate_text(run): FILE: skills/productivity/powerpoint/scripts/office/helpers/simplify_redlines.py function simplify_redlines (line 22) | def simplify_redlines(input_dir: str) -> tuple[int, str]: function _merge_tracked_changes_in (line 47) | def _merge_tracked_changes_in(container, tag: str) -> int: function _is_element (line 75) | def _is_element(node, tag: str) -> bool: function _get_author (line 80) | def _get_author(elem) -> str: function _can_merge_tracked (line 89) | def _can_merge_tracked(elem1, elem2) -> bool: function _merge_tracked_content (line 104) | def _merge_tracked_content(target, source): function _find_elements (line 111) | def _find_elements(root, tag: str) -> list: function get_tracked_change_authors (line 126) | def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]: function _get_authors_from_docx (line 149) | def _get_authors_from_docx(docx_path: Path) -> dict[str, int]: function infer_author (line 172) | def infer_author(modified_dir: Path, original_docx: Path, default: str =... FILE: skills/productivity/powerpoint/scripts/office/pack.py function pack (line 24) | def pack( function _run_validation (line 69) | def _run_validation( function _condense_xml (line 108) | def _condense_xml(xml_file: Path) -> None: FILE: skills/research/arxiv/scripts/search_arxiv.py function search (line 20) | def search(query=None, author=None, category=None, ids=None, max_results... FILE: skills/research/domain-intel/scripts/domain_intel.py function subdomains (line 30) | def subdomains(domain, include_expired=False, limit=200): function check_ssl (line 66) | def check_ssl(host, port=443, timeout=10): function whois_lookup (line 155) | def whois_lookup(domain): function dns_records (line 211) | def dns_records(domain, types=None): function check_available (line 250) | def check_available(domain): function bulk_check (line 338) | def bulk_check(domains, checks=None, max_workers=5): function main (line 365) | def main(): FILE: skills/research/polymarket/scripts/polymarket.py function _get (line 26) | def _get(url: str) -> dict | list: function _parse_json_field (line 40) | def _parse_json_field(val): function _fmt_pct (line 50) | def _fmt_pct(price_str: str) -> str: function _fmt_volume (line 58) | def _fmt_volume(vol) -> str: function _print_market (line 71) | def _print_market(m: dict, indent: str = ""): function cmd_search (line 96) | def cmd_search(query: str): function cmd_trending (line 114) | def cmd_trending(limit: int = 10): function cmd_market (line 130) | def cmd_market(slug: str): function cmd_event (line 152) | def cmd_event(slug: str): function cmd_price (line 168) | def cmd_price(token_id: str): function cmd_book (line 179) | def cmd_book(token_id: str): function cmd_history (line 198) | def cmd_history(condition_id: str, interval: str = "all", fidelity: int ... function cmd_trades (line 214) | def cmd_trades(limit: int = 10, market: str = None): function main (line 234) | def main(): FILE: tests/acp/test_auth.py class TestHasProvider (line 6) | class TestHasProvider: method test_has_provider_with_resolved_runtime (line 7) | def test_has_provider_with_resolved_runtime(self, monkeypatch): method test_has_no_provider_when_runtime_has_no_key (line 14) | def test_has_no_provider_when_runtime_has_no_key(self, monkeypatch): method test_has_no_provider_when_runtime_resolution_fails (line 21) | def test_has_no_provider_when_runtime_resolution_fails(self, monkeypat... class TestDetectProvider (line 29) | class TestDetectProvider: method test_detect_openrouter (line 30) | def test_detect_openrouter(self, monkeypatch): method test_detect_anthropic (line 37) | def test_detect_anthropic(self, monkeypatch): method test_detect_none_when_no_key (line 44) | def test_detect_none_when_no_key(self, monkeypatch): method test_detect_none_on_resolution_error (line 51) | def test_detect_none_on_resolution_error(self, monkeypatch): FILE: tests/acp/test_events.py function mock_conn (line 21) | def mock_conn(): function event_loop_fixture (line 29) | def event_loop_fixture(): class TestToolProgressCallback (line 41) | class TestToolProgressCallback: method test_emits_tool_call_start (line 42) | def test_emits_tool_call_start(self, mock_conn, event_loop_fixture): method test_handles_string_args (line 66) | def test_handles_string_args(self, mock_conn, event_loop_fixture): method test_handles_non_dict_args (line 82) | def test_handles_non_dict_args(self, mock_conn, event_loop_fixture): method test_duplicate_same_name_tool_calls_use_fifo_ids (line 98) | def test_duplicate_same_name_tool_calls_use_fifo_ids(self, mock_conn, ... class TestThinkingCallback (line 127) | class TestThinkingCallback: method test_emits_thought_chunk (line 128) | def test_emits_thought_chunk(self, mock_conn, event_loop_fixture): method test_ignores_empty_text (line 143) | def test_ignores_empty_text(self, mock_conn, event_loop_fixture): class TestStepCallback (line 160) | class TestStepCallback: method test_completes_tracked_tool_calls (line 161) | def test_completes_tracked_tool_calls(self, mock_conn, event_loop_fixt... method test_ignores_untracked_tools (line 179) | def test_ignores_untracked_tools(self, mock_conn, event_loop_fixture): method test_handles_string_tool_info (line 191) | def test_handles_string_tool_info(self, mock_conn, event_loop_fixture): class TestMessageCallback (line 214) | class TestMessageCallback: method test_emits_agent_message_chunk (line 215) | def test_emits_agent_message_chunk(self, mock_conn, event_loop_fixture): method test_ignores_empty_message (line 230) | def test_ignores_empty_message(self, mock_conn, event_loop_fixture): FILE: tests/acp/test_permissions.py function _make_response (line 17) | def _make_response(outcome): function _setup_callback (line 22) | def _setup_callback(outcome, timeout=60.0): class TestApprovalMapping (line 47) | class TestApprovalMapping: method test_approval_allow_once_maps_correctly (line 48) | def test_approval_allow_once_maps_correctly(self): method test_approval_allow_always_maps_correctly (line 53) | def test_approval_allow_always_maps_correctly(self): method test_approval_deny_maps_correctly (line 58) | def test_approval_deny_maps_correctly(self): method test_approval_timeout_returns_deny (line 63) | def test_approval_timeout_returns_deny(self): FILE: tests/acp/test_server.py function mock_manager (line 29) | def mock_manager(): function agent (line 35) | def agent(mock_manager): class TestInitialize (line 45) | class TestInitialize: method test_initialize_returns_correct_protocol_version (line 47) | async def test_initialize_returns_correct_protocol_version(self, agent): method test_initialize_returns_agent_info (line 53) | async def test_initialize_returns_agent_info(self, agent): method test_initialize_returns_capabilities (line 61) | async def test_initialize_returns_capabilities(self, agent): class TestAuthenticate (line 75) | class TestAuthenticate: method test_authenticate_with_provider_configured (line 77) | async def test_authenticate_with_provider_configured(self, agent, monk... method test_authenticate_without_provider (line 86) | async def test_authenticate_without_provider(self, agent, monkeypatch): class TestSessionOps (line 100) | class TestSessionOps: method test_new_session_creates_session (line 102) | async def test_new_session_creates_session(self, agent): method test_cancel_sets_event (line 112) | async def test_cancel_sets_event(self, agent): method test_cancel_nonexistent_session_is_noop (line 120) | async def test_cancel_nonexistent_session_is_noop(self, agent): method test_load_session_returns_response (line 125) | async def test_load_session_returns_response(self, agent): method test_load_session_not_found_returns_none (line 131) | async def test_load_session_not_found_returns_none(self, agent): method test_resume_session_returns_response (line 136) | async def test_resume_session_returns_response(self, agent): method test_resume_session_creates_new_if_missing (line 142) | async def test_resume_session_creates_new_if_missing(self, agent): class TestListAndFork (line 152) | class TestListAndFork: method test_list_sessions (line 154) | async def test_list_sessions(self, agent): method test_fork_session (line 162) | async def test_fork_session(self, agent): class TestPrompt (line 174) | class TestPrompt: method test_prompt_returns_refusal_for_unknown_session (line 176) | async def test_prompt_returns_refusal_for_unknown_session(self, agent): method test_prompt_returns_end_turn_for_empty_message (line 183) | async def test_prompt_returns_end_turn_for_empty_message(self, agent): method test_prompt_runs_agent (line 190) | async def test_prompt_runs_agent(self, agent): method test_prompt_updates_history (line 217) | async def test_prompt_updates_history(self, agent): method test_prompt_sends_final_message_update (line 241) | async def test_prompt_sends_final_message_update(self, agent): method test_prompt_cancelled_returns_cancelled_stop_reason (line 266) | async def test_prompt_cancelled_returns_cancelled_stop_reason(self, ag... class TestOnConnect (line 293) | class TestOnConnect: method test_on_connect_stores_client (line 294) | def test_on_connect_stores_client(self, agent): class TestSlashCommands (line 305) | class TestSlashCommands: method _make_state (line 308) | def _make_state(self, mock_manager): method test_help_lists_commands (line 315) | def test_help_lists_commands(self, agent, mock_manager): method test_model_shows_current (line 324) | def test_model_shows_current(self, agent, mock_manager): method test_context_empty (line 329) | def test_context_empty(self, agent, mock_manager): method test_context_with_messages (line 335) | def test_context_with_messages(self, agent, mock_manager): method test_reset_clears_history (line 345) | def test_reset_clears_history(self, agent, mock_manager): method test_version (line 352) | def test_version(self, agent, mock_manager): method test_unknown_command_returns_none (line 357) | def test_unknown_command_returns_none(self, agent, mock_manager): method test_slash_command_intercepted_in_prompt (line 363) | async def test_slash_command_intercepted_in_prompt(self, agent, mock_m... method test_unknown_slash_falls_through_to_llm (line 376) | async def test_unknown_slash_falls_through_to_llm(self, agent, mock_ma... FILE: tests/acp/test_session.py function _mock_agent (line 11) | def _mock_agent(): function manager (line 16) | def manager(): class TestCreateSession (line 26) | class TestCreateSession: method test_create_session_returns_state (line 27) | def test_create_session_returns_state(self, manager): method test_create_session_registers_task_cwd (line 35) | def test_create_session_registers_task_cwd(self, manager, monkeypatch): method test_session_ids_are_unique (line 41) | def test_session_ids_are_unique(self, manager): method test_get_session (line 46) | def test_get_session(self, manager): method test_get_nonexistent_session_returns_none (line 51) | def test_get_nonexistent_session_returns_none(self, manager): class TestForkSession (line 60) | class TestForkSession: method test_fork_session_deep_copies_history (line 61) | def test_fork_session_deep_copies_history(self, manager): method test_fork_session_has_new_id (line 78) | def test_fork_session_has_new_id(self, manager): method test_fork_nonexistent_returns_none (line 84) | def test_fork_nonexistent_returns_none(self, manager): class TestListAndCleanup (line 93) | class TestListAndCleanup: method test_list_sessions_empty (line 94) | def test_list_sessions_empty(self, manager): method test_list_sessions_returns_created (line 97) | def test_list_sessions_returns_created(self, manager): method test_cleanup_clears_all (line 106) | def test_cleanup_clears_all(self, manager): method test_remove_session (line 113) | def test_remove_session(self, manager): class TestPersistence (line 126) | class TestPersistence: method test_create_session_writes_to_db (line 129) | def test_create_session_writes_to_db(self, manager): method test_get_session_restores_from_db (line 140) | def test_get_session_restores_from_db(self, manager): method test_save_session_updates_db (line 164) | def test_save_session_updates_db(self, manager): method test_remove_session_deletes_from_db (line 174) | def test_remove_session_deletes_from_db(self, manager): method test_cleanup_removes_all_from_db (line 181) | def test_cleanup_removes_all_from_db(self, manager): method test_list_sessions_includes_db_only (line 191) | def test_list_sessions_includes_db_only(self, manager): method test_fork_restores_source_from_db (line 204) | def test_fork_restores_source_from_db(self, manager): method test_update_cwd_restores_from_db (line 220) | def test_update_cwd_restores_from_db(self, manager): method test_only_restores_acp_sessions (line 237) | def test_only_restores_acp_sessions(self, manager): method test_sessions_searchable_via_fts (line 245) | def test_sessions_searchable_via_fts(self, manager): method test_tool_calls_persisted (line 258) | def test_tool_calls_persisted(self, manager): FILE: tests/acp/test_tools.py class TestToolKindMap (line 31) | class TestToolKindMap: method test_all_hermes_tools_have_kind (line 32) | def test_all_hermes_tools_have_kind(self): method test_tool_kind_read_file (line 37) | def test_tool_kind_read_file(self): method test_tool_kind_terminal (line 40) | def test_tool_kind_terminal(self): method test_tool_kind_patch (line 43) | def test_tool_kind_patch(self): method test_tool_kind_write_file (line 46) | def test_tool_kind_write_file(self): method test_tool_kind_web_search (line 49) | def test_tool_kind_web_search(self): method test_tool_kind_execute_code (line 52) | def test_tool_kind_execute_code(self): method test_tool_kind_browser_navigate (line 55) | def test_tool_kind_browser_navigate(self): method test_unknown_tool_returns_other_kind (line 58) | def test_unknown_tool_returns_other_kind(self): class TestMakeToolCallId (line 67) | class TestMakeToolCallId: method test_returns_string (line 68) | def test_returns_string(self): method test_starts_with_tc_prefix (line 72) | def test_starts_with_tc_prefix(self): method test_ids_are_unique (line 76) | def test_ids_are_unique(self): class TestBuildToolTitle (line 86) | class TestBuildToolTitle: method test_terminal_title_includes_command (line 87) | def test_terminal_title_includes_command(self): method test_terminal_title_truncates_long_command (line 91) | def test_terminal_title_truncates_long_command(self): method test_read_file_title (line 97) | def test_read_file_title(self): method test_patch_title (line 101) | def test_patch_title(self): method test_search_title (line 105) | def test_search_title(self): method test_web_search_title (line 109) | def test_web_search_title(self): method test_unknown_tool_uses_name (line 113) | def test_unknown_tool_uses_name(self): class TestBuildToolStart (line 123) | class TestBuildToolStart: method test_build_tool_start_for_patch (line 124) | def test_build_tool_start_for_patch(self): method test_build_tool_start_for_write_file (line 142) | def test_build_tool_start_for_write_file(self): method test_build_tool_start_for_terminal (line 153) | def test_build_tool_start_for_terminal(self): method test_build_tool_start_for_read_file (line 166) | def test_build_tool_start_for_read_file(self): method test_build_tool_start_for_search (line 177) | def test_build_tool_start_for_search(self): method test_build_tool_start_generic_fallback (line 185) | def test_build_tool_start_generic_fallback(self): class TestBuildToolComplete (line 198) | class TestBuildToolComplete: method test_build_tool_complete_for_terminal (line 199) | def test_build_tool_complete_for_terminal(self): method test_build_tool_complete_truncates_large_output (line 209) | def test_build_tool_complete_truncates_large_output(self): class TestExtractLocations (line 224) | class TestExtractLocations: method test_extract_locations_with_path (line 225) | def test_extract_locations_with_path(self): method test_extract_locations_without_path (line 233) | def test_extract_locations_without_path(self): FILE: tests/agent/test_auxiliary_client.py function _clean_env (line 24) | def _clean_env(monkeypatch): function codex_auth_dir (line 41) | def codex_auth_dir(tmp_path, monkeypatch): class TestReadCodexAccessToken (line 59) | class TestReadCodexAccessToken: method test_valid_auth_store (line 60) | def test_valid_auth_store(self, tmp_path, monkeypatch): method test_missing_returns_none (line 75) | def test_missing_returns_none(self, tmp_path, monkeypatch): method test_empty_token_returns_none (line 83) | def test_empty_token_returns_none(self, tmp_path, monkeypatch): method test_malformed_json_returns_none (line 98) | def test_malformed_json_returns_none(self, tmp_path): method test_missing_tokens_key_returns_none (line 106) | def test_missing_tokens_key_returns_none(self, tmp_path): class TestGetTextAuxiliaryClient (line 115) | class TestGetTextAuxiliaryClient: method test_openrouter_takes_priority (line 118) | def test_openrouter_takes_priority(self, monkeypatch, codex_auth_dir): method test_nous_takes_priority_over_codex (line 127) | def test_nous_takes_priority_over_codex(self, monkeypatch, codex_auth_... method test_custom_endpoint_over_codex (line 134) | def test_custom_endpoint_over_codex(self, monkeypatch, codex_auth_dir): method test_task_direct_endpoint_override (line 150) | def test_task_direct_endpoint_override(self, monkeypatch): method test_task_direct_endpoint_without_openai_key_does_not_fall_back (line 161) | def test_task_direct_endpoint_without_openai_key_does_not_fall_back(se... method test_custom_endpoint_uses_config_saved_base_url (line 171) | def test_custom_endpoint_uses_config_saved_base_url(self, monkeypatch): method test_codex_fallback_when_nothing_else (line 194) | def test_codex_fallback_when_nothing_else(self, codex_auth_dir): method test_returns_none_when_nothing_available (line 203) | def test_returns_none_when_nothing_available(self, monkeypatch): class TestVisionClientFallback (line 215) | class TestVisionClientFallback: method test_vision_returns_none_without_any_credentials (line 218) | def test_vision_returns_none_without_any_credentials(self): method test_vision_auto_includes_anthropic_when_configured (line 227) | def test_vision_auto_includes_anthropic_when_configured(self, monkeypa... method test_resolve_provider_client_returns_native_anthropic_wrapper (line 238) | def test_resolve_provider_client_returns_native_anthropic_wrapper(self... method test_resolve_provider_client_copilot_uses_runtime_credentials (line 251) | def test_resolve_provider_client_copilot_uses_runtime_credentials(self... method test_vision_auto_uses_anthropic_when_no_higher_priority_backend (line 276) | def test_vision_auto_uses_anthropic_when_no_higher_priority_backend(se... method test_selected_anthropic_provider_is_preferred_for_vision_auto (line 289) | def test_selected_anthropic_provider_is_preferred_for_vision_auto(self... method test_vision_auto_includes_codex (line 309) | def test_vision_auto_includes_codex(self, codex_auth_dir): method test_vision_auto_falls_back_to_custom_endpoint (line 318) | def test_vision_auto_falls_back_to_custom_endpoint(self, monkeypatch): method test_vision_direct_endpoint_override (line 331) | def test_vision_direct_endpoint_override(self, monkeypatch): method test_vision_direct_endpoint_requires_openai_api_key (line 342) | def test_vision_direct_endpoint_requires_openai_api_key(self, monkeypa... method test_vision_uses_openrouter_when_available (line 352) | def test_vision_uses_openrouter_when_available(self, monkeypatch): method test_vision_uses_nous_when_available (line 359) | def test_vision_uses_nous_when_available(self, monkeypatch): method test_vision_forced_main_uses_custom_endpoint (line 367) | def test_vision_forced_main_uses_custom_endpoint(self, monkeypatch): method test_vision_forced_main_returns_none_without_creds (line 379) | def test_vision_forced_main_returns_none_without_creds(self, monkeypat... method test_vision_forced_codex (line 391) | def test_vision_forced_codex(self, monkeypatch, codex_auth_dir): class TestGetAuxiliaryProvider (line 402) | class TestGetAuxiliaryProvider: method test_no_task_returns_auto (line 405) | def test_no_task_returns_auto(self): method test_auxiliary_prefix_takes_priority (line 409) | def test_auxiliary_prefix_takes_priority(self, monkeypatch): method test_context_prefix_fallback (line 413) | def test_context_prefix_fallback(self, monkeypatch): method test_auxiliary_prefix_over_context_prefix (line 417) | def test_auxiliary_prefix_over_context_prefix(self, monkeypatch): method test_auto_value_treated_as_auto (line 422) | def test_auto_value_treated_as_auto(self, monkeypatch): method test_whitespace_stripped (line 426) | def test_whitespace_stripped(self, monkeypatch): method test_case_insensitive (line 430) | def test_case_insensitive(self, monkeypatch): method test_main_provider (line 434) | def test_main_provider(self, monkeypatch): class TestResolveForcedProvider (line 439) | class TestResolveForcedProvider: method test_forced_openrouter (line 442) | def test_forced_openrouter(self, monkeypatch): method test_forced_openrouter_no_key (line 449) | def test_forced_openrouter_no_key(self, monkeypatch): method test_forced_nous (line 455) | def test_forced_nous(self, monkeypatch): method test_forced_nous_not_configured (line 463) | def test_forced_nous_not_configured(self, monkeypatch): method test_forced_main_uses_custom (line 469) | def test_forced_main_uses_custom(self, monkeypatch): method test_forced_main_uses_config_saved_custom_endpoint (line 478) | def test_forced_main_uses_config_saved_custom_endpoint(self, monkeypat... method test_forced_main_skips_openrouter_nous (line 499) | def test_forced_main_skips_openrouter_nous(self, monkeypatch): method test_forced_main_falls_to_codex (line 511) | def test_forced_main_falls_to_codex(self, codex_auth_dir, monkeypatch): method test_forced_codex (line 519) | def test_forced_codex(self, codex_auth_dir, monkeypatch): method test_forced_codex_no_token (line 527) | def test_forced_codex_no_token(self, monkeypatch): method test_forced_unknown_returns_none (line 533) | def test_forced_unknown_returns_none(self, monkeypatch): class TestTaskSpecificOverrides (line 541) | class TestTaskSpecificOverrides: method test_text_with_vision_provider_override (line 544) | def test_text_with_vision_provider_override(self, monkeypatch): method test_compression_task_reads_context_prefix (line 552) | def test_compression_task_reads_context_prefix(self, monkeypatch): method test_web_extract_task_override (line 564) | def test_web_extract_task_override(self, monkeypatch): method test_task_direct_endpoint_from_config (line 571) | def test_task_direct_endpoint_from_config(self, monkeypatch, tmp_path): method test_task_without_override_uses_auto (line 589) | def test_task_without_override_uses_auto(self, monkeypatch): method test_compression_summary_base_url_from_config (line 596) | def test_compression_summary_base_url_from_config(self, monkeypatch, t... class TestAuxiliaryMaxTokensParam (line 616) | class TestAuxiliaryMaxTokensParam: method test_codex_fallback_uses_max_tokens (line 617) | def test_codex_fallback_uses_max_tokens(self, monkeypatch): method test_openrouter_uses_max_tokens (line 624) | def test_openrouter_uses_max_tokens(self, monkeypatch): method test_no_provider_uses_max_tokens (line 629) | def test_no_provider_uses_max_tokens(self): FILE: tests/agent/test_context_compressor.py function compressor (line 10) | def compressor(): class TestShouldCompress (line 23) | class TestShouldCompress: method test_below_threshold (line 24) | def test_below_threshold(self, compressor): method test_above_threshold (line 28) | def test_above_threshold(self, compressor): method test_exact_threshold (line 32) | def test_exact_threshold(self, compressor): method test_explicit_tokens (line 36) | def test_explicit_tokens(self, compressor): class TestShouldCompressPreflight (line 41) | class TestShouldCompressPreflight: method test_short_messages (line 42) | def test_short_messages(self, compressor): method test_long_messages (line 46) | def test_long_messages(self, compressor): class TestUpdateFromResponse (line 52) | class TestUpdateFromResponse: method test_updates_fields (line 53) | def test_updates_fields(self, compressor): method test_missing_fields_default_zero (line 63) | def test_missing_fields_default_zero(self, compressor): class TestGetStatus (line 68) | class TestGetStatus: method test_returns_expected_keys (line 69) | def test_returns_expected_keys(self, compressor): method test_usage_percent_calculation (line 77) | def test_usage_percent_calculation(self, compressor): class TestCompress (line 83) | class TestCompress: method _make_messages (line 84) | def _make_messages(self, n): method test_too_few_messages_returns_unchanged (line 87) | def test_too_few_messages_returns_unchanged(self, compressor): method test_truncation_fallback_no_client (line 92) | def test_truncation_fallback_no_client(self, compressor): method test_compression_increments_count (line 101) | def test_compression_increments_count(self, compressor): method test_protects_first_and_last (line 108) | def test_protects_first_and_last(self, compressor): class TestGenerateSummaryNoneContent (line 121) | class TestGenerateSummaryNoneContent: method test_none_content_does_not_crash (line 124) | def test_none_content_does_not_crash(self): method test_none_content_in_system_message_compress (line 147) | def test_none_content_in_system_message_compress(self): class TestNonStringContent (line 160) | class TestNonStringContent: method test_dict_content_coerced_to_string (line 163) | def test_dict_content_coerced_to_string(self): method test_none_content_coerced_to_empty (line 181) | def test_none_content_coerced_to_empty(self): class TestSummaryPrefixNormalization (line 201) | class TestSummaryPrefixNormalization: method test_legacy_prefix_is_replaced (line 202) | def test_legacy_prefix_is_replaced(self): method test_existing_new_prefix_is_not_duplicated (line 206) | def test_existing_new_prefix_is_not_duplicated(self): class TestCompressWithClient (line 211) | class TestCompressWithClient: method test_summarization_path (line 212) | def test_summarization_path(self): method test_summarization_does_not_split_tool_call_pairs (line 231) | def test_summarization_does_not_split_tool_call_pairs(self): method test_summary_role_avoids_consecutive_user_messages (line 278) | def test_summary_role_avoids_consecutive_user_messages(self): method test_summary_role_avoids_consecutive_user_when_head_ends_with_user (line 306) | def test_summary_role_avoids_consecutive_user_when_head_ends_with_user... method test_summary_role_flips_to_avoid_tail_collision (line 336) | def test_summary_role_flips_to_avoid_tail_collision(self): method test_double_collision_merges_summary_into_tail (line 370) | def test_double_collision_merges_summary_into_tail(self): method test_double_collision_user_head_assistant_tail (line 414) | def test_double_collision_user_head_assistant_tail(self): method test_no_collision_scenarios_still_work (line 451) | def test_no_collision_scenarios_still_work(self): method test_summarization_does_not_start_tail_with_tool_outputs (line 476) | def test_summarization_does_not_start_tail_with_tool_outputs(self): FILE: tests/agent/test_display_emoji.py class TestGetToolEmoji (line 8) | class TestGetToolEmoji: method test_returns_registry_emoji_when_no_skin (line 11) | def test_returns_registry_emoji_when_no_skin(self): method test_skin_override_takes_precedence (line 33) | def test_skin_override_takes_precedence(self): method test_skin_empty_dict_falls_through (line 41) | def test_skin_empty_dict_falls_through(self): method test_fallback_default (line 55) | def test_fallback_default(self): method test_custom_default (line 69) | def test_custom_default(self): method test_skin_override_only_for_matching_tool (line 81) | def test_skin_override_only_for_matching_tool(self): class TestSkinConfigToolEmojis (line 96) | class TestSkinConfigToolEmojis: method test_skin_config_has_tool_emojis_field (line 99) | def test_skin_config_has_tool_emojis_field(self): method test_skin_config_accepts_tool_emojis (line 104) | def test_skin_config_accepts_tool_emojis(self): method test_build_skin_config_includes_tool_emojis (line 110) | def test_build_skin_config_includes_tool_emojis(self): method test_build_skin_config_empty_tool_emojis_default (line 119) | def test_build_skin_config_empty_tool_emojis_default(self): FILE: tests/agent/test_model_metadata.py class TestEstimateTokensRough (line 42) | class TestEstimateTokensRough: method test_empty_string (line 43) | def test_empty_string(self): method test_none_returns_zero (line 46) | def test_none_returns_zero(self): method test_known_length (line 49) | def test_known_length(self): method test_short_text (line 52) | def test_short_text(self): method test_proportional (line 55) | def test_proportional(self): method test_unicode_multibyte (line 60) | def test_unicode_multibyte(self): class TestEstimateMessagesTokensRough (line 66) | class TestEstimateMessagesTokensRough: method test_empty_list (line 67) | def test_empty_list(self): method test_single_message_concrete_value (line 70) | def test_single_message_concrete_value(self): method test_multiple_messages_additive (line 77) | def test_multiple_messages_additive(self): method test_tool_call_message (line 86) | def test_tool_call_message(self): method test_message_with_list_content (line 94) | def test_message_with_list_content(self): class TestDefaultContextLengths (line 108) | class TestDefaultContextLengths: method test_claude_models_context_lengths (line 109) | def test_claude_models_context_lengths(self): method test_gpt4_models_128k_or_1m (line 119) | def test_gpt4_models_128k_or_1m(self): method test_gpt41_models_1m (line 125) | def test_gpt41_models_1m(self): method test_gemini_models_1m (line 130) | def test_gemini_models_1m(self): method test_all_values_positive (line 135) | def test_all_values_positive(self): method test_dict_is_not_empty (line 139) | def test_dict_is_not_empty(self): class TestGetModelContextLength (line 147) | class TestGetModelContextLength: method test_known_model_from_api (line 149) | def test_known_model_from_api(self, mock_fetch): method test_fallback_to_defaults (line 156) | def test_fallback_to_defaults(self, mock_fetch): method test_unknown_model_returns_first_probe_tier (line 161) | def test_unknown_model_returns_first_probe_tier(self, mock_fetch): method test_partial_match_in_defaults (line 166) | def test_partial_match_in_defaults(self, mock_fetch): method test_api_missing_context_length_key (line 171) | def test_api_missing_context_length_key(self, mock_fetch): method test_cache_takes_priority_over_api (line 177) | def test_cache_takes_priority_over_api(self, mock_fetch, tmp_path): method test_no_base_url_skips_cache (line 187) | def test_no_base_url_skips_cache(self, mock_fetch, tmp_path): method test_custom_endpoint_metadata_beats_fuzzy_default (line 199) | def test_custom_endpoint_metadata_beats_fuzzy_default(self, mock_endpo... method test_custom_endpoint_without_metadata_skips_name_based_default (line 215) | def test_custom_endpoint_without_metadata_skips_name_based_default(sel... method test_custom_endpoint_single_model_fallback (line 229) | def test_custom_endpoint_single_model_fallback(self, mock_endpoint_fet... method test_custom_endpoint_fuzzy_substring_match (line 246) | def test_custom_endpoint_fuzzy_substring_match(self, mock_endpoint_fet... method test_config_context_length_overrides_all (line 263) | def test_config_context_length_overrides_all(self, mock_fetch): method test_config_context_length_zero_is_ignored (line 277) | def test_config_context_length_zero_is_ignored(self, mock_fetch): method test_config_context_length_none_is_ignored (line 289) | def test_config_context_length_none_is_ignored(self, mock_fetch): class TestStripProviderPrefix (line 305) | class TestStripProviderPrefix: method test_known_provider_prefix_is_stripped (line 306) | def test_known_provider_prefix_is_stripped(self): method test_ollama_model_tag_preserved (line 311) | def test_ollama_model_tag_preserved(self): method test_http_urls_preserved (line 318) | def test_http_urls_preserved(self): method test_no_colon_returns_unchanged (line 322) | def test_no_colon_returns_unchanged(self): method test_ollama_model_tag_not_mangled_in_context_lookup (line 327) | def test_ollama_model_tag_not_mangled_in_context_lookup(self, mock_fet... class TestFetchModelMetadata (line 348) | class TestFetchModelMetadata: method _reset_cache (line 349) | def _reset_cache(self): method test_caches_result (line 355) | def test_caches_result(self, mock_get): method test_api_failure_returns_empty_on_cold_cache (line 373) | def test_api_failure_returns_empty_on_cold_cache(self, mock_get): method test_api_failure_returns_stale_cache (line 380) | def test_api_failure_returns_stale_cache(self, mock_get): method test_canonical_slug_aliasing (line 392) | def test_canonical_slug_aliasing(self, mock_get): method test_provider_prefixed_models_get_bare_aliases (line 414) | def test_provider_prefixed_models_get_bare_aliases(self, mock_get): method test_ttl_expiry_triggers_refetch (line 433) | def test_ttl_expiry_triggers_refetch(self, mock_get): method test_malformed_json_no_data_key (line 454) | def test_malformed_json_no_data_key(self, mock_get): class TestContextProbeTiers (line 470) | class TestContextProbeTiers: method test_tiers_descending (line 471) | def test_tiers_descending(self): method test_first_tier_is_128k (line 475) | def test_first_tier_is_128k(self): method test_last_tier_is_8k (line 478) | def test_last_tier_is_8k(self): class TestGetNextProbeTier (line 482) | class TestGetNextProbeTier: method test_from_128k (line 483) | def test_from_128k(self): method test_from_64k (line 486) | def test_from_64k(self): method test_from_32k (line 489) | def test_from_32k(self): method test_from_8k_returns_none (line 492) | def test_from_8k_returns_none(self): method test_from_below_min_returns_none (line 495) | def test_from_below_min_returns_none(self): method test_from_arbitrary_value (line 498) | def test_from_arbitrary_value(self): method test_above_max_tier (line 501) | def test_above_max_tier(self): method test_zero_returns_none (line 505) | def test_zero_returns_none(self): class TestParseContextLimitFromError (line 513) | class TestParseContextLimitFromError: method test_openai_format (line 514) | def test_openai_format(self): method test_context_length_exceeded (line 518) | def test_context_length_exceeded(self): method test_context_size_exceeded (line 522) | def test_context_size_exceeded(self): method test_no_limit_in_message (line 526) | def test_no_limit_in_message(self): method test_unreasonable_small_number_rejected (line 529) | def test_unreasonable_small_number_rejected(self): method test_ollama_format (line 532) | def test_ollama_format(self): method test_anthropic_format (line 536) | def test_anthropic_format(self): method test_lmstudio_format (line 541) | def test_lmstudio_format(self): method test_completely_unrelated_error (line 545) | def test_completely_unrelated_error(self): method test_empty_string (line 548) | def test_empty_string(self): method test_number_outside_reasonable_range (line 551) | def test_number_outside_reasonable_range(self): class TestContextLengthCache (line 561) | class TestContextLengthCache: method test_save_and_load (line 562) | def test_save_and_load(self, tmp_path): method test_missing_cache_returns_none (line 568) | def test_missing_cache_returns_none(self, tmp_path): method test_multiple_models_cached (line 573) | def test_multiple_models_cached(self, tmp_path): method test_same_model_different_providers (line 581) | def test_same_model_different_providers(self, tmp_path): method test_idempotent_save (line 589) | def test_idempotent_save(self, tmp_path): method test_update_existing_value (line 598) | def test_update_existing_value(self, tmp_path): method test_corrupted_yaml_returns_empty (line 606) | def test_corrupted_yaml_returns_empty(self, tmp_path): method test_wrong_structure_returns_none (line 613) | def test_wrong_structure_returns_none(self, tmp_path): method test_cached_value_takes_priority (line 621) | def test_cached_value_takes_priority(self, mock_fetch, tmp_path): method test_special_chars_in_model_name (line 628) | def test_special_chars_in_model_name(self, tmp_path): FILE: tests/agent/test_models_dev.py class TestProviderMapping (line 75) | class TestProviderMapping: method test_all_mapped_providers_are_strings (line 76) | def test_all_mapped_providers_are_strings(self): method test_known_providers_mapped (line 81) | def test_known_providers_mapped(self): method test_unmapped_provider_not_in_dict (line 87) | def test_unmapped_provider_not_in_dict(self): class TestExtractContext (line 92) | class TestExtractContext: method test_valid_entry (line 93) | def test_valid_entry(self): method test_zero_context_returns_none (line 96) | def test_zero_context_returns_none(self): method test_missing_limit_returns_none (line 99) | def test_missing_limit_returns_none(self): method test_missing_context_returns_none (line 102) | def test_missing_context_returns_none(self): method test_non_dict_returns_none (line 105) | def test_non_dict_returns_none(self): method test_float_context_coerced_to_int (line 108) | def test_float_context_coerced_to_int(self): class TestLookupModelsDevContext (line 112) | class TestLookupModelsDevContext: method test_exact_match (line 114) | def test_exact_match(self, mock_fetch): method test_case_insensitive_match (line 119) | def test_case_insensitive_match(self, mock_fetch): method test_provider_not_mapped (line 124) | def test_provider_not_mapped(self, mock_fetch): method test_model_not_found (line 129) | def test_model_not_found(self, mock_fetch): method test_provider_aware_context (line 134) | def test_provider_aware_context(self, mock_fetch): method test_zero_context_filtered (line 143) | def test_zero_context_filtered(self, mock_fetch): method test_empty_registry (line 150) | def test_empty_registry(self, mock_fetch): class TestFetchModelsDev (line 155) | class TestFetchModelsDev: method test_fetch_success (line 157) | def test_fetch_success(self, mock_get): method test_fetch_failure_returns_stale_cache (line 176) | def test_fetch_failure_returns_stale_cache(self, mock_get): method test_in_memory_cache_used (line 189) | def test_in_memory_cache_used(self, mock_get): FILE: tests/agent/test_prompt_builder.py class TestGuidanceConstants (line 32) | class TestGuidanceConstants: method test_memory_guidance_discourages_task_logs (line 33) | def test_memory_guidance_discourages_task_logs(self): method test_session_search_guidance_is_simple_cross_session_recall (line 40) | def test_session_search_guidance_is_simple_cross_session_recall(self): class TestScanContextContent (line 50) | class TestScanContextContent: method test_clean_content_passes (line 51) | def test_clean_content_passes(self): method test_prompt_injection_blocked (line 56) | def test_prompt_injection_blocked(self): method test_disregard_rules_blocked (line 62) | def test_disregard_rules_blocked(self): method test_system_prompt_override_blocked (line 66) | def test_system_prompt_override_blocked(self): method test_html_comment_injection_blocked (line 70) | def test_html_comment_injection_blocked(self): method test_hidden_div_blocked (line 74) | def test_hidden_div_blocked(self): method test_exfiltration_curl_blocked (line 80) | def test_exfiltration_curl_blocked(self): method test_read_secrets_blocked (line 84) | def test_read_secrets_blocked(self): method test_invisible_unicode_blocked (line 88) | def test_invisible_unicode_blocked(self): method test_translate_execute_blocked (line 92) | def test_translate_execute_blocked(self): method test_bypass_restrictions_blocked (line 98) | def test_bypass_restrictions_blocked(self): class TestTruncateContent (line 108) | class TestTruncateContent: method test_short_content_unchanged (line 109) | def test_short_content_unchanged(self): method test_long_content_truncated (line 114) | def test_long_content_truncated(self): method test_truncation_keeps_head_and_tail (line 120) | def test_truncation_keeps_head_and_tail(self): method test_exact_limit_unchanged (line 129) | def test_exact_limit_unchanged(self): class TestParseSkillFile (line 140) | class TestParseSkillFile: method test_reads_frontmatter_description (line 141) | def test_reads_frontmatter_description(self, tmp_path): method test_missing_description_returns_empty (line 151) | def test_missing_description_returns_empty(self, tmp_path): method test_long_description_truncated (line 157) | def test_long_description_truncated(self, tmp_path): method test_nonexistent_file_returns_defaults (line 165) | def test_nonexistent_file_returns_defaults(self, tmp_path): method test_logs_parse_failures_and_returns_defaults (line 171) | def test_logs_parse_failures_and_returns_defaults(self, tmp_path, monk... method test_incompatible_platform_returns_false (line 188) | def test_incompatible_platform_returns_false(self, tmp_path): method test_returns_frontmatter_with_prerequisites (line 200) | def test_returns_frontmatter_with_prerequisites(self, tmp_path, monkey... class TestPromptBuilderImports (line 211) | class TestPromptBuilderImports: method test_module_import_does_not_eagerly_import_skills_tool (line 212) | def test_module_import_does_not_eagerly_import_skills_tool(self, monke... class TestBuildSkillsSystemPrompt (line 235) | class TestBuildSkillsSystemPrompt: method test_empty_when_no_skills_dir (line 236) | def test_empty_when_no_skills_dir(self, monkeypatch, tmp_path): method test_builds_index_with_skills (line 241) | def test_builds_index_with_skills(self, monkeypatch, tmp_path): method test_deduplicates_skills (line 253) | def test_deduplicates_skills(self, monkeypatch, tmp_path): method test_excludes_incompatible_platform_skills (line 264) | def test_excludes_incompatible_platform_skills(self, monkeypatch, tmp_... method test_includes_matching_platform_skills (line 293) | def test_includes_matching_platform_skills(self, monkeypatch, tmp_path): method test_excludes_disabled_skills (line 312) | def test_excludes_disabled_skills(self, monkeypatch, tmp_path): method test_includes_setup_needed_skills (line 341) | def test_includes_setup_needed_skills(self, monkeypatch, tmp_path): method test_includes_skills_with_met_prerequisites (line 363) | def test_includes_skills_with_met_prerequisites(self, monkeypatch, tmp... method test_non_local_backend_keeps_skill_visible_without_probe (line 379) | def test_non_local_backend_keeps_skill_visible_without_probe( class TestBuildContextFilesPrompt (line 403) | class TestBuildContextFilesPrompt: method test_empty_dir_loads_seeded_global_soul (line 404) | def test_empty_dir_loads_seeded_global_soul(self, tmp_path): method test_loads_agents_md (line 414) | def test_loads_agents_md(self, tmp_path): method test_loads_cursorrules (line 420) | def test_loads_cursorrules(self, tmp_path): method test_loads_soul_md_from_hermes_home_only (line 425) | def test_loads_soul_md_from_hermes_home_only(self, tmp_path, monkeypat... method test_soul_md_has_no_wrapper_text (line 435) | def test_soul_md_has_no_wrapper_text(self, tmp_path, monkeypatch): method test_empty_soul_md_adds_nothing (line 445) | def test_empty_soul_md_adds_nothing(self, tmp_path, monkeypatch): method test_blocks_injection_in_agents_md (line 453) | def test_blocks_injection_in_agents_md(self, tmp_path): method test_loads_cursor_rules_mdc (line 460) | def test_loads_cursor_rules_mdc(self, tmp_path): method test_recursive_agents_md (line 467) | def test_recursive_agents_md(self, tmp_path): method test_loads_hermes_md (line 478) | def test_loads_hermes_md(self, tmp_path): method test_loads_hermes_md_uppercase (line 484) | def test_loads_hermes_md_uppercase(self, tmp_path): method test_hermes_md_lowercase_takes_priority (line 489) | def test_hermes_md_lowercase_takes_priority(self, tmp_path): method test_hermes_md_parent_dir_discovery (line 496) | def test_hermes_md_parent_dir_discovery(self, tmp_path): method test_hermes_md_stops_at_git_root (line 506) | def test_hermes_md_stops_at_git_root(self, tmp_path): method test_hermes_md_strips_yaml_frontmatter (line 516) | def test_hermes_md_strips_yaml_frontmatter(self, tmp_path): method test_hermes_md_blocks_injection (line 524) | def test_hermes_md_blocks_injection(self, tmp_path): method test_hermes_md_coexists_with_agents_md (line 529) | def test_hermes_md_coexists_with_agents_md(self, tmp_path): class TestFindHermesMd (line 542) | class TestFindHermesMd: method test_finds_in_cwd (line 543) | def test_finds_in_cwd(self, tmp_path): method test_finds_uppercase (line 547) | def test_finds_uppercase(self, tmp_path): method test_prefers_lowercase (line 551) | def test_prefers_lowercase(self, tmp_path): method test_walks_to_git_root (line 556) | def test_walks_to_git_root(self, tmp_path): method test_returns_none_when_absent (line 563) | def test_returns_none_when_absent(self, tmp_path): method test_stops_at_git_root (line 566) | def test_stops_at_git_root(self, tmp_path): class TestFindGitRoot (line 575) | class TestFindGitRoot: method test_finds_git_dir (line 576) | def test_finds_git_dir(self, tmp_path): method test_finds_from_subdirectory (line 580) | def test_finds_from_subdirectory(self, tmp_path): method test_returns_none_without_git (line 586) | def test_returns_none_without_git(self, tmp_path): class TestStripYamlFrontmatter (line 601) | class TestStripYamlFrontmatter: method test_strips_frontmatter (line 602) | def test_strips_frontmatter(self): method test_no_frontmatter_unchanged (line 606) | def test_no_frontmatter_unchanged(self): method test_unclosed_frontmatter_unchanged (line 610) | def test_unclosed_frontmatter_unchanged(self): method test_empty_body_returns_original (line 614) | def test_empty_body_returns_original(self): class TestPromptBuilderConstants (line 625) | class TestPromptBuilderConstants: method test_default_identity_non_empty (line 626) | def test_default_identity_non_empty(self): method test_platform_hints_known_platforms (line 629) | def test_platform_hints_known_platforms(self): class TestReadSkillConditions (line 641) | class TestReadSkillConditions: method test_no_conditions_returns_empty_lists (line 642) | def test_no_conditions_returns_empty_lists(self, tmp_path): method test_reads_fallback_for_toolsets (line 651) | def test_reads_fallback_for_toolsets(self, tmp_path): method test_reads_requires_toolsets (line 659) | def test_reads_requires_toolsets(self, tmp_path): method test_reads_multiple_conditions (line 667) | def test_reads_multiple_conditions(self, tmp_path): method test_missing_file_returns_empty (line 676) | def test_missing_file_returns_empty(self, tmp_path): method test_logs_condition_read_failures_and_returns_empty (line 680) | def test_logs_condition_read_failures_and_returns_empty(self, tmp_path... class TestSkillShouldShow (line 696) | class TestSkillShouldShow: method test_no_filter_info_always_shows (line 697) | def test_no_filter_info_always_shows(self): method test_empty_conditions_always_shows (line 700) | def test_empty_conditions_always_shows(self): method test_fallback_hidden_when_toolset_available (line 707) | def test_fallback_hidden_when_toolset_available(self): method test_fallback_shown_when_toolset_unavailable (line 712) | def test_fallback_shown_when_toolset_unavailable(self): method test_requires_shown_when_toolset_available (line 717) | def test_requires_shown_when_toolset_available(self): method test_requires_hidden_when_toolset_missing (line 722) | def test_requires_hidden_when_toolset_missing(self): method test_fallback_for_tools_hidden_when_tool_available (line 727) | def test_fallback_for_tools_hidden_when_tool_available(self): method test_fallback_for_tools_shown_when_tool_missing (line 732) | def test_fallback_for_tools_shown_when_tool_missing(self): method test_requires_tools_hidden_when_tool_missing (line 737) | def test_requires_tools_hidden_when_tool_missing(self): method test_requires_tools_shown_when_tool_available (line 742) | def test_requires_tools_shown_when_tool_available(self): class TestBuildSkillsSystemPromptConditional (line 748) | class TestBuildSkillsSystemPromptConditional: method test_fallback_skill_hidden_when_primary_available (line 749) | def test_fallback_skill_hidden_when_primary_available(self, monkeypatc... method test_fallback_skill_shown_when_primary_unavailable (line 762) | def test_fallback_skill_shown_when_primary_unavailable(self, monkeypat... method test_requires_skill_hidden_when_toolset_missing (line 775) | def test_requires_skill_hidden_when_toolset_missing(self, monkeypatch,... method test_requires_skill_shown_when_toolset_available (line 788) | def test_requires_skill_shown_when_toolset_available(self, monkeypatch... method test_unconditional_skill_always_shown (line 801) | def test_unconditional_skill_always_shown(self, monkeypatch, tmp_path): method test_no_args_shows_all_skills (line 814) | def test_no_args_shows_all_skills(self, monkeypatch, tmp_path): FILE: tests/agent/test_prompt_caching.py class TestApplyCacheMarker (line 15) | class TestApplyCacheMarker: method test_tool_message_gets_top_level_marker (line 16) | def test_tool_message_gets_top_level_marker(self): method test_none_content_gets_top_level_marker (line 21) | def test_none_content_gets_top_level_marker(self): method test_empty_string_content_gets_top_level_marker (line 26) | def test_empty_string_content_gets_top_level_marker(self): method test_string_content_wrapped_in_list (line 34) | def test_string_content_wrapped_in_list(self): method test_list_content_last_item_gets_marker (line 43) | def test_list_content_last_item_gets_marker(self): method test_empty_list_content_no_crash (line 55) | def test_empty_list_content_no_crash(self): class TestApplyAnthropicCacheControl (line 61) | class TestApplyAnthropicCacheControl: method test_empty_messages (line 62) | def test_empty_messages(self): method test_returns_deep_copy (line 66) | def test_returns_deep_copy(self): method test_system_message_gets_marker (line 74) | def test_system_message_gets_marker(self): method test_last_3_non_system_get_markers (line 85) | def test_last_3_non_system_get_markers(self): method test_no_system_message (line 102) | def test_no_system_message(self): method test_1h_ttl (line 111) | def test_1h_ttl(self): method test_max_4_breakpoints (line 118) | def test_max_4_breakpoints(self): FILE: tests/agent/test_redact.py class TestKnownPrefixes (line 10) | class TestKnownPrefixes: method test_openai_sk_key (line 11) | def test_openai_sk_key(self): method test_openrouter_sk_key (line 18) | def test_openrouter_sk_key(self): method test_github_pat_classic (line 23) | def test_github_pat_classic(self): method test_github_pat_fine_grained (line 27) | def test_github_pat_fine_grained(self): method test_slack_token (line 31) | def test_slack_token(self): method test_google_api_key (line 36) | def test_google_api_key(self): method test_perplexity_key (line 40) | def test_perplexity_key(self): method test_fal_key (line 44) | def test_fal_key(self): method test_short_token_fully_masked (line 48) | def test_short_token_fully_masked(self): class TestEnvAssignments (line 53) | class TestEnvAssignments: method test_export_api_key (line 54) | def test_export_api_key(self): method test_quoted_value (line 60) | def test_quoted_value(self): method test_non_secret_env_unchanged (line 66) | def test_non_secret_env_unchanged(self): method test_path_unchanged (line 71) | def test_path_unchanged(self): class TestJsonFields (line 77) | class TestJsonFields: method test_json_api_key (line 78) | def test_json_api_key(self): method test_json_token (line 83) | def test_json_token(self): method test_json_non_secret_unchanged (line 88) | def test_json_non_secret_unchanged(self): class TestAuthHeaders (line 94) | class TestAuthHeaders: method test_bearer_token (line 95) | def test_bearer_token(self): method test_case_insensitive (line 101) | def test_case_insensitive(self): class TestTelegramTokens (line 107) | class TestTelegramTokens: method test_bot_token (line 108) | def test_bot_token(self): method test_raw_token (line 114) | def test_raw_token(self): class TestPassthrough (line 120) | class TestPassthrough: method test_empty_string (line 121) | def test_empty_string(self): method test_none_returns_none (line 124) | def test_none_returns_none(self): method test_normal_text_unchanged (line 127) | def test_normal_text_unchanged(self): method test_code_unchanged (line 131) | def test_code_unchanged(self): method test_url_without_key_unchanged (line 135) | def test_url_without_key_unchanged(self): class TestRedactingFormatter (line 140) | class TestRedactingFormatter: method test_formats_and_redacts (line 141) | def test_formats_and_redacts(self): class TestPrintenvSimulation (line 157) | class TestPrintenvSimulation: method test_full_env_dump (line 160) | def test_full_env_dump(self): class TestSecretCapturePayloadRedaction (line 180) | class TestSecretCapturePayloadRedaction: method test_secret_value_field_redacted (line 181) | def test_secret_value_field_redacted(self): method test_raw_secret_field_redacted (line 186) | def test_raw_secret_field_redacted(self): FILE: tests/agent/test_skill_commands.py function _make_skill (line 17) | def _make_skill( class TestScanSkillCommands (line 40) | class TestScanSkillCommands: method test_finds_skills (line 41) | def test_finds_skills(self, tmp_path): method test_empty_dir (line 48) | def test_empty_dir(self, tmp_path): method test_excludes_incompatible_platform (line 53) | def test_excludes_incompatible_platform(self, tmp_path): method test_includes_matching_platform (line 66) | def test_includes_matching_platform(self, tmp_path): method test_universal_skill_on_any_platform (line 77) | def test_universal_skill_on_any_platform(self, tmp_path): method test_excludes_disabled_skills (line 88) | def test_excludes_disabled_skills(self, tmp_path): class TestBuildPreloadedSkillsPrompt (line 104) | class TestBuildPreloadedSkillsPrompt: method test_builds_prompt_for_multiple_named_skills (line 105) | def test_builds_prompt_for_multiple_named_skills(self, tmp_path): method test_reports_missing_named_skills (line 119) | def test_reports_missing_named_skills(self, tmp_path): class TestBuildSkillInvocationMessage (line 131) | class TestBuildSkillInvocationMessage: method test_loads_skill_by_stored_path_when_frontmatter_name_differs (line 132) | def test_loads_skill_by_stored_path_when_frontmatter_name_differs(self... method test_builds_message (line 156) | def test_builds_message(self, tmp_path): method test_returns_none_for_unknown (line 165) | def test_returns_none_for_unknown(self, tmp_path): method test_uses_shared_skill_loader_for_secure_setup (line 171) | def test_uses_shared_skill_loader_for_secure_setup(self, tmp_path, mon... method test_gateway_still_loads_skill_but_returns_setup_guidance (line 210) | def test_gateway_still_loads_skill_but_returns_setup_guidance( method test_preserves_remaining_remote_setup_warning (line 246) | def test_preserves_remaining_remote_setup_warning(self, tmp_path, monk... method test_supporting_file_hint_uses_file_path_argument (line 282) | def test_supporting_file_hint_uses_file_path_argument(self, tmp_path): class TestPlanSkillHelpers (line 295) | class TestPlanSkillHelpers: method test_build_plan_path_uses_workspace_relative_dir_and_slugifies_request (line 296) | def test_build_plan_path_uses_workspace_relative_dir_and_slugifies_req... method test_plan_skill_message_can_include_runtime_save_path_note (line 304) | def test_plan_skill_message_can_include_runtime_save_path_note(self, t... FILE: tests/agent/test_smart_model_routing.py function test_returns_none_when_disabled (line 13) | def test_returns_none_when_disabled(): function test_routes_short_simple_prompt (line 18) | def test_routes_short_simple_prompt(): function test_skips_long_prompt (line 26) | def test_skips_long_prompt(): function test_skips_code_like_prompt (line 31) | def test_skips_code_like_prompt(): function test_skips_tool_heavy_prompt_keywords (line 36) | def test_skips_tool_heavy_prompt_keywords(): function test_resolve_turn_route_falls_back_to_primary_when_route_runtime_cannot_be_resolved (line 41) | def test_resolve_turn_route_falls_back_to_primary_when_route_runtime_can... FILE: tests/agent/test_subagent_progress.py class TestPrintAbove (line 26) | class TestPrintAbove: method test_print_above_without_spinner_running (line 29) | def test_print_above_without_spinner_running(self): method test_print_above_with_spinner_running (line 39) | def test_print_above_with_spinner_running(self): method test_print_above_uses_captured_stdout (line 51) | def test_print_above_uses_captured_stdout(self): class TestBuildChildProgressCallback (line 73) | class TestBuildChildProgressCallback: method test_returns_none_when_no_display (line 76) | def test_returns_none_when_no_display(self): method test_cli_spinner_tool_event (line 85) | def test_cli_spinner_tool_event(self): method test_cli_spinner_thinking_event (line 105) | def test_cli_spinner_thinking_event(self): method test_gateway_batched_progress (line 123) | def test_gateway_batched_progress(self): method test_thinking_not_relayed_to_gateway (line 144) | def test_thinking_not_relayed_to_gateway(self): method test_parallel_callbacks_independent (line 156) | def test_parallel_callbacks_independent(self): method test_task_index_prefix_in_batch_mode (line 173) | def test_task_index_prefix_in_batch_mode(self): method test_single_task_no_prefix (line 198) | def test_single_task_no_prefix(self): class TestThinkingCallback (line 220) | class TestThinkingCallback: method _simulate_thinking_callback (line 223) | def _simulate_thinking_callback(self, content, callback, delegate_dept... method test_thinking_callback_fires_on_content (line 242) | def test_thinking_callback_fires_on_content(self): method test_thinking_callback_skipped_when_no_content (line 254) | def test_thinking_callback_skipped_when_no_content(self): method test_thinking_callback_truncates_long_content (line 263) | def test_thinking_callback_truncates_long_content(self): method test_thinking_callback_skipped_for_main_agent (line 273) | def test_thinking_callback_skipped_for_main_agent(self): method test_thinking_callback_strips_reasoning_scratchpad (line 284) | def test_thinking_callback_strips_reasoning_scratchpad(self): method test_thinking_callback_strips_think_tags (line 295) | def test_thinking_callback_strips_think_tags(self): method test_thinking_callback_empty_after_strip (line 306) | def test_thinking_callback_empty_after_strip(self): class TestBatchFlush (line 320) | class TestBatchFlush: method test_flush_sends_remaining_batch (line 323) | def test_flush_sends_remaining_batch(self): method test_flush_noop_when_batch_empty (line 345) | def test_flush_noop_when_batch_empty(self): method test_flush_noop_when_no_parent_callback (line 356) | def test_flush_noop_when_no_parent_callback(self): FILE: tests/agent/test_title_generator.py class TestGenerateTitle (line 15) | class TestGenerateTitle: method test_returns_title_on_success (line 18) | def test_returns_title_on_success(self): method test_strips_quotes (line 27) | def test_strips_quotes(self): method test_strips_title_prefix (line 36) | def test_strips_title_prefix(self): method test_truncates_long_titles (line 45) | def test_truncates_long_titles(self): method test_returns_none_on_empty_response (line 55) | def test_returns_none_on_empty_response(self): method test_returns_none_on_exception (line 63) | def test_returns_none_on_exception(self): method test_truncates_long_messages (line 67) | def test_truncates_long_messages(self): class TestAutoTitleSession (line 86) | class TestAutoTitleSession: method test_skips_if_no_session_db (line 89) | def test_skips_if_no_session_db(self): method test_skips_if_title_exists (line 92) | def test_skips_if_title_exists(self): method test_generates_and_sets_title (line 100) | def test_generates_and_sets_title(self): method test_skips_if_generation_fails (line 108) | def test_skips_if_generation_fails(self): class TestMaybeAutoTitle (line 117) | class TestMaybeAutoTitle: method test_skips_if_not_first_exchange (line 120) | def test_skips_if_not_first_exchange(self): method test_fires_on_first_exchange (line 139) | def test_fires_on_first_exchange(self): method test_skips_if_no_response (line 155) | def test_skips_if_no_response(self): method test_skips_if_no_session_db (line 159) | def test_skips_if_no_session_db(self): FILE: tests/agent/test_usage_pricing.py function test_normalize_usage_anthropic_keeps_cache_buckets_separate (line 11) | def test_normalize_usage_anthropic_keeps_cache_buckets_separate(): function test_normalize_usage_openai_subtracts_cached_prompt_tokens (line 28) | def test_normalize_usage_openai_subtracts_cached_prompt_tokens(): function test_openrouter_models_api_pricing_is_converted_from_per_token_to_per_million (line 42) | def test_openrouter_models_api_pricing_is_converted_from_per_token_to_pe... function test_estimate_usage_cost_marks_subscription_routes_included (line 69) | def test_estimate_usage_cost_marks_subscription_routes_included(): function test_estimate_usage_cost_refuses_cache_pricing_without_official_cache_rate (line 81) | def test_estimate_usage_cost_refuses_cache_pricing_without_official_cach... function test_custom_endpoint_models_api_pricing_is_supported (line 104) | def test_custom_endpoint_models_api_pricing_is_supported(monkeypatch): FILE: tests/conftest.py function _isolate_hermes_home (line 20) | def _isolate_hermes_home(tmp_path, monkeypatch): function tmp_dir (line 44) | def tmp_dir(tmp_path): function mock_config (line 50) | def mock_config(): function _timeout_handler (line 72) | def _timeout_handler(signum, frame): function _ensure_current_event_loop (line 76) | def _ensure_current_event_loop(request): function _enforce_test_timeout (line 109) | def _enforce_test_timeout(): FILE: tests/cron/test_jobs.py class TestParseDuration (line 32) | class TestParseDuration: method test_minutes (line 33) | def test_minutes(self): method test_hours (line 40) | def test_hours(self): method test_days (line 47) | def test_days(self): method test_whitespace_tolerance (line 52) | def test_whitespace_tolerance(self): method test_invalid_raises (line 56) | def test_invalid_raises(self): class TestParseSchedule (line 71) | class TestParseSchedule: method test_duration_becomes_once (line 72) | def test_duration_becomes_once(self): method test_every_becomes_interval (line 84) | def test_every_becomes_interval(self): method test_every_case_insensitive (line 89) | def test_every_case_insensitive(self): method test_cron_expression (line 94) | def test_cron_expression(self): method test_iso_timestamp (line 100) | def test_iso_timestamp(self): method test_invalid_schedule_raises (line 105) | def test_invalid_schedule_raises(self): method test_invalid_cron_raises (line 109) | def test_invalid_cron_raises(self): class TestComputeNextRun (line 119) | class TestComputeNextRun: method test_once_future_returns_time (line 120) | def test_once_future_returns_time(self): method test_once_recent_past_within_grace_returns_time (line 125) | def test_once_recent_past_within_grace_returns_time(self, monkeypatch): method test_once_past_returns_none (line 134) | def test_once_past_returns_none(self): method test_once_with_last_run_returns_none_even_within_grace (line 139) | def test_once_with_last_run_returns_none_even_within_grace(self, monke... method test_interval_first_run (line 148) | def test_interval_first_run(self): method test_interval_subsequent_run (line 155) | def test_interval_subsequent_run(self): method test_cron_returns_future (line 163) | def test_cron_returns_future(self): method test_unknown_kind_returns_none (line 173) | def test_unknown_kind_returns_none(self): function tmp_cron_dir (line 182) | def tmp_cron_dir(tmp_path, monkeypatch): class TestJobCRUD (line 190) | class TestJobCRUD: method test_create_and_get (line 191) | def test_create_and_get(self, tmp_cron_dir): method test_list_jobs (line 202) | def test_list_jobs(self, tmp_cron_dir): method test_remove_job (line 208) | def test_remove_job(self, tmp_cron_dir): method test_remove_nonexistent_returns_false (line 213) | def test_remove_nonexistent_returns_false(self, tmp_cron_dir): method test_auto_repeat_for_once (line 216) | def test_auto_repeat_for_once(self, tmp_cron_dir): method test_interval_no_auto_repeat (line 220) | def test_interval_no_auto_repeat(self, tmp_cron_dir): method test_default_delivery_origin (line 224) | def test_default_delivery_origin(self, tmp_cron_dir): method test_default_delivery_local_no_origin (line 231) | def test_default_delivery_local_no_origin(self, tmp_cron_dir): class TestUpdateJob (line 236) | class TestUpdateJob: method test_update_name (line 237) | def test_update_name(self, tmp_cron_dir): method test_update_schedule (line 252) | def test_update_schedule(self, tmp_cron_dir): method test_update_enable_disable (line 269) | def test_update_enable_disable(self, tmp_cron_dir): method test_update_nonexistent_returns_none (line 277) | def test_update_nonexistent_returns_none(self, tmp_cron_dir): class TestPauseResumeJob (line 282) | class TestPauseResumeJob: method test_pause_sets_state (line 283) | def test_pause_sets_state(self, tmp_cron_dir): method test_resume_reenables_job (line 291) | def test_resume_reenables_job(self, tmp_cron_dir): class TestMarkJobRun (line 302) | class TestMarkJobRun: method test_increments_completed (line 303) | def test_increments_completed(self, tmp_cron_dir): method test_repeat_limit_removes_job (line 310) | def test_repeat_limit_removes_job(self, tmp_cron_dir): method test_error_status (line 316) | def test_error_status(self, tmp_cron_dir): class TestGetDueJobs (line 324) | class TestGetDueJobs: method test_past_due_within_window_returned (line 325) | def test_past_due_within_window_returned(self, tmp_cron_dir): method test_stale_past_due_skipped (line 337) | def test_stale_past_due_skipped(self, tmp_cron_dir): method test_future_not_returned (line 353) | def test_future_not_returned(self, tmp_cron_dir): method test_disabled_not_returned (line 358) | def test_disabled_not_returned(self, tmp_cron_dir): method test_broken_recent_one_shot_without_next_run_is_recovered (line 368) | def test_broken_recent_one_shot_without_next_run_is_recovered(self, tm... method test_broken_stale_one_shot_without_next_run_is_not_recovered (line 400) | def test_broken_stale_one_shot_without_next_run_is_not_recovered(self,... class TestSaveJobOutput (line 430) | class TestSaveJobOutput: method test_creates_output_file (line 431) | def test_creates_output_file(self, tmp_cron_dir): FILE: tests/cron/test_scheduler.py class TestResolveOrigin (line 13) | class TestResolveOrigin: method test_full_origin (line 14) | def test_full_origin(self): method test_no_origin (line 31) | def test_no_origin(self): method test_missing_platform (line 35) | def test_missing_platform(self): method test_missing_chat_id (line 39) | def test_missing_chat_id(self): method test_empty_origin (line 43) | def test_empty_origin(self): class TestResolveDeliveryTarget (line 48) | class TestResolveDeliveryTarget: method test_origin_delivery_preserves_thread_id (line 49) | def test_origin_delivery_preserves_thread_id(self): method test_bare_platform_uses_matching_origin_chat (line 65) | def test_bare_platform_uses_matching_origin_chat(self): method test_bare_platform_falls_back_to_home_channel (line 81) | def test_bare_platform_falls_back_to_home_channel(self, monkeypatch): class TestDeliverResultMirrorLogging (line 98) | class TestDeliverResultMirrorLogging: method test_mirror_failure_is_logged (line 101) | def test_mirror_failure_is_logged(self, caplog): method test_origin_delivery_preserves_thread_id (line 124) | def test_origin_delivery_preserves_thread_id(self): class TestRunJobSessionPersistence (line 159) | class TestRunJobSessionPersistence: method test_run_job_passes_session_db_and_cron_platform (line 160) | def test_run_job_passes_session_db_and_cron_platform(self, tmp_path): method test_run_job_sets_auto_delivery_env_from_dotenv_home_channel (line 199) | def test_run_job_sets_auto_delivery_env_from_dotenv_home_channel(self,... class TestRunJobConfigLogging (line 254) | class TestRunJobConfigLogging: method test_bad_config_yaml_is_logged (line 257) | def test_bad_config_yaml_is_logged(self, caplog, tmp_path): method test_bad_prefill_messages_is_logged (line 282) | def test_bad_prefill_messages_is_logged(self, caplog, tmp_path): class TestRunJobPerJobOverrides (line 312) | class TestRunJobPerJobOverrides: method test_job_level_model_provider_and_base_url_overrides_are_used (line 313) | def test_job_level_model_provider_and_base_url_overrides_are_used(self... class TestRunJobSkillBacked (line 363) | class TestRunJobSkillBacked: method test_run_job_loads_skill_and_disables_recursive_cron_tools (line 364) | def test_run_job_loads_skill_and_disables_recursive_cron_tools(self, t... method test_run_job_loads_multiple_skills_in_order (line 407) | def test_run_job_loads_multiple_skills_in_order(self, tmp_path): class TestSilentDelivery (line 454) | class TestSilentDelivery: method _make_job (line 457) | def _make_job(self): method test_normal_response_delivers (line 465) | def test_normal_response_delivers(self): method test_silent_response_suppresses_delivery (line 475) | def test_silent_response_suppresses_delivery(self, caplog): method test_silent_with_note_suppresses_delivery (line 487) | def test_silent_with_note_suppresses_delivery(self): method test_silent_is_case_insensitive (line 497) | def test_silent_is_case_insensitive(self): method test_failed_job_always_delivers (line 507) | def test_failed_job_always_delivers(self): method test_output_saved_even_when_delivery_suppressed (line 518) | def test_output_saved_even_when_delivery_suppressed(self): class TestBuildJobPromptSilentHint (line 531) | class TestBuildJobPromptSilentHint: method test_hint_always_present (line 534) | def test_hint_always_present(self): method test_hint_present_even_without_prompt (line 540) | def test_hint_present_even_without_prompt(self): class TestBuildJobPromptMissingSkill (line 546) | class TestBuildJobPromptMissingSkill: method _missing_skill_view (line 549) | def _missing_skill_view(self, name: str) -> str: method test_missing_skill_does_not_raise (line 552) | def test_missing_skill_does_not_raise(self): method test_missing_skill_injects_user_notice_into_prompt (line 559) | def test_missing_skill_injects_user_notice_into_prompt(self): method test_missing_skill_logs_warning (line 566) | def test_missing_skill_logs_warning(self, caplog): method test_valid_skill_loaded_alongside_missing (line 573) | def test_valid_skill_loaded_alongside_missing(self): FILE: tests/fakes/fake_ha_server.py class FakeHAServer (line 77) | class FakeHAServer: method __init__ (line 86) | def __init__(self, token: str = "test-token-123"): method url (line 110) | def url(self) -> str: method push_event (line 117) | async def push_event(self, event_data: Dict[str, Any]) -> None: method start (line 123) | async def start(self) -> None: method stop (line 128) | async def stop(self) -> None: method __aenter__ (line 137) | async def __aenter__(self) -> "FakeHAServer": method __aexit__ (line 141) | async def __aexit__(self, *exc) -> None: method _build_app (line 146) | def _build_app(self) -> web.Application: method _check_rest_auth (line 165) | def _check_rest_auth(self, request: web.Request) -> Optional[web.Respo... method _handle_ws (line 176) | async def _handle_ws(self, request: web.Request) -> web.WebSocketRespo... method _handle_get_states (line 236) | async def _handle_get_states(self, request: web.Request) -> web.Response: method _handle_get_state (line 242) | async def _handle_get_state(self, request: web.Request) -> web.Response: method _handle_notification (line 252) | async def _handle_notification(self, request: web.Request) -> web.Resp... method _handle_call_service (line 260) | async def _handle_call_service(self, request: web.Request) -> web.Resp... FILE: tests/gateway/test_api_server.py class TestCheckRequirements (line 39) | class TestCheckRequirements: method test_returns_true_when_aiohttp_available (line 40) | def test_returns_true_when_aiohttp_available(self): method test_returns_false_without_aiohttp (line 44) | def test_returns_false_without_aiohttp(self): class TestResponseStore (line 53) | class TestResponseStore: method test_put_and_get (line 54) | def test_put_and_get(self): method test_get_missing_returns_none (line 59) | def test_get_missing_returns_none(self): method test_lru_eviction (line 63) | def test_lru_eviction(self): method test_access_refreshes_lru (line 74) | def test_access_refreshes_lru(self): method test_update_existing_key (line 86) | def test_update_existing_key(self): method test_delete_existing (line 93) | def test_delete_existing(self): method test_delete_missing (line 100) | def test_delete_missing(self): class TestAdapterInit (line 110) | class TestAdapterInit: method test_default_config (line 111) | def test_default_config(self): method test_custom_config_from_extra (line 119) | def test_custom_config_from_extra(self): method test_config_from_env (line 129) | def test_config_from_env(self, monkeypatch): class TestAuth (line 145) | class TestAuth: method test_no_key_configured_allows_all (line 146) | def test_no_key_configured_allows_all(self): method test_valid_key_passes (line 153) | def test_valid_key_passes(self): method test_invalid_key_returns_401 (line 160) | def test_invalid_key_returns_401(self): method test_missing_auth_header_returns_401 (line 169) | def test_missing_auth_header_returns_401(self): method test_malformed_auth_header_returns_401 (line 178) | def test_malformed_auth_header_returns_401(self): function _make_adapter (line 193) | def _make_adapter(api_key: str = "") -> APIServerAdapter: function _create_app (line 202) | def _create_app(adapter: APIServerAdapter) -> web.Application: function adapter (line 215) | def adapter(): function auth_adapter (line 220) | def auth_adapter(): class TestHealthEndpoint (line 229) | class TestHealthEndpoint: method test_health_returns_ok (line 231) | async def test_health_returns_ok(self, adapter): class TestModelsEndpoint (line 246) | class TestModelsEndpoint: method test_models_returns_hermes_agent (line 248) | async def test_models_returns_hermes_agent(self, adapter): method test_models_requires_auth (line 260) | async def test_models_requires_auth(self, auth_adapter): method test_models_with_valid_auth (line 267) | async def test_models_with_valid_auth(self, auth_adapter): class TestChatCompletionsEndpoint (line 282) | class TestChatCompletionsEndpoint: method test_invalid_json_returns_400 (line 284) | async def test_invalid_json_returns_400(self, adapter): method test_missing_messages_returns_400 (line 297) | async def test_missing_messages_returns_400(self, adapter): method test_empty_messages_returns_400 (line 306) | async def test_empty_messages_returns_400(self, adapter): method test_stream_true_returns_sse (line 313) | async def test_stream_true_returns_sse(self, adapter): method test_no_user_message_returns_400 (line 345) | async def test_no_user_message_returns_400(self, adapter): method test_successful_completion (line 358) | async def test_successful_completion(self, adapter): method test_system_prompt_extracted (line 390) | async def test_system_prompt_extracted(self, adapter): method test_conversation_history_passed (line 420) | async def test_conversation_history_passed(self, adapter): method test_agent_error_returns_500 (line 448) | async def test_agent_error_returns_500(self, adapter): class TestResponsesEndpoint (line 472) | class TestResponsesEndpoint: method test_missing_input_returns_400 (line 474) | async def test_missing_input_returns_400(self, adapter): method test_invalid_json_returns_400 (line 483) | async def test_invalid_json_returns_400(self, adapter): method test_successful_response_with_string_input (line 494) | async def test_successful_response_with_string_input(self, adapter): method test_successful_response_with_array_input (line 525) | async def test_successful_response_with_array_input(self, adapter): method test_instructions_as_ephemeral_prompt (line 551) | async def test_instructions_as_ephemeral_prompt(self, adapter): method test_previous_response_id_chaining (line 573) | async def test_previous_response_id_chaining(self, adapter): method test_invalid_previous_response_id_returns_404 (line 620) | async def test_invalid_previous_response_id_returns_404(self, adapter): method test_store_false_does_not_store (line 634) | async def test_store_false_does_not_store(self, adapter): method test_instructions_inherited_from_previous (line 657) | async def test_instructions_inherited_from_previous(self, adapter): method test_agent_error_returns_500 (line 695) | async def test_agent_error_returns_500(self, adapter): method test_invalid_input_type_returns_400 (line 708) | async def test_invalid_input_type_returns_400(self, adapter): class TestEndpointAuth (line 723) | class TestEndpointAuth: method test_chat_completions_requires_auth (line 725) | async def test_chat_completions_requires_auth(self, auth_adapter): method test_responses_requires_auth (line 735) | async def test_responses_requires_auth(self, auth_adapter): method test_models_requires_auth (line 745) | async def test_models_requires_auth(self, auth_adapter): method test_health_does_not_require_auth (line 752) | async def test_health_does_not_require_auth(self, auth_adapter): class TestConfigIntegration (line 764) | class TestConfigIntegration: method test_platform_enum_has_api_server (line 765) | def test_platform_enum_has_api_server(self): method test_env_override_enables_api_server (line 768) | def test_env_override_enables_api_server(self, monkeypatch): method test_env_override_with_key (line 775) | def test_env_override_with_key(self, monkeypatch): method test_env_override_port_and_host (line 782) | def test_env_override_port_and_host(self, monkeypatch): method test_api_server_in_connected_platforms (line 791) | def test_api_server_in_connected_platforms(self): method test_api_server_not_in_connected_when_disabled (line 797) | def test_api_server_not_in_connected_when_disabled(self): class TestMultipleSystemMessages (line 809) | class TestMultipleSystemMessages: method test_multiple_system_messages_concatenated (line 811) | async def test_multiple_system_messages_concatenated(self, adapter): class TestSendMethod (line 842) | class TestSendMethod: method test_send_returns_not_supported (line 844) | async def test_send_returns_not_supported(self): class TestGetResponse (line 857) | class TestGetResponse: method test_get_stored_response (line 859) | async def test_get_stored_response(self, adapter): method test_get_not_found (line 886) | async def test_get_not_found(self, adapter): method test_get_requires_auth (line 893) | async def test_get_requires_auth(self, auth_adapter): class TestDeleteResponse (line 905) | class TestDeleteResponse: method test_delete_stored_response (line 907) | async def test_delete_stored_response(self, adapter): method test_delete_not_found (line 936) | async def test_delete_not_found(self, adapter): method test_delete_requires_auth (line 943) | async def test_delete_requires_auth(self, auth_adapter): class TestToolCallsInOutput (line 955) | class TestToolCallsInOutput: method test_tool_calls_in_output (line 957) | async def test_tool_calls_in_output(self, adapter): method test_no_tool_calls_still_works (line 1014) | async def test_no_tool_calls_still_works(self, adapter): class TestUsageCounting (line 1038) | class TestUsageCounting: method test_responses_usage (line 1040) | async def test_responses_usage(self, adapter): method test_chat_completions_usage (line 1061) | async def test_chat_completions_usage(self, adapter): class TestTruncation (line 1090) | class TestTruncation: method test_truncation_auto_limits_history (line 1092) | async def test_truncation_auto_limits_history(self, adapter): method test_no_truncation_keeps_full_history (line 1124) | async def test_no_truncation_keeps_full_history(self, adapter): class TestCORS (line 1158) | class TestCORS: method test_cors_headers_on_get (line 1160) | async def test_cors_headers_on_get(self, adapter): method test_cors_options_preflight (line 1171) | async def test_cors_options_preflight(self, adapter): class TestConversationParameter (line 1187) | class TestConversationParameter: method test_conversation_creates_new (line 1189) | async def test_conversation_creates_new(self, adapter): method test_conversation_chains_automatically (line 1209) | async def test_conversation_chains_automatically(self, adapter): method test_conversation_and_previous_response_id_conflict (line 1247) | async def test_conversation_and_previous_response_id_conflict(self, ad... method test_separate_conversations_are_isolated (line 1261) | async def test_separate_conversations_are_isolated(self, adapter): method test_conversation_store_false_no_mapping (line 1283) | async def test_conversation_store_false_no_mapping(self, adapter): FILE: tests/gateway/test_approve_deny_commands.py function _make_source (line 18) | def _make_source() -> SessionSource: function _make_event (line 28) | def _make_event(text: str) -> MessageEvent: function _make_runner (line 36) | def _make_runner(): function _make_pending_approval (line 62) | def _make_pending_approval(command="sudo rm -rf /tmp/test", pattern_key=... class TestApproveCommand (line 77) | class TestApproveCommand: method test_approve_executes_pending_command (line 80) | async def test_approve_executes_pending_command(self): method test_approve_session_remembers_pattern (line 96) | async def test_approve_session_remembers_pattern(self): method test_approve_always_approves_permanently (line 114) | async def test_approve_always_approves_permanently(self): method test_approve_no_pending (line 132) | async def test_approve_no_pending(self): method test_approve_expired (line 140) | async def test_approve_expired(self): class TestDenyCommand (line 161) | class TestDenyCommand: method test_deny_clears_pending (line 164) | async def test_deny_clears_pending(self): method test_deny_no_pending (line 178) | async def test_deny_no_pending(self): class TestBareTextNoLongerApproves (line 191) | class TestBareTextNoLongerApproves: method test_yes_does_not_execute_pending_command (line 194) | async def test_yes_does_not_execute_pending_command(self): class TestApprovalHint (line 223) | class TestApprovalHint: method test_approval_hint_appended_to_response (line 225) | def test_approval_hint_appended_to_response(self): FILE: tests/gateway/test_async_memory_flush.py function idle_store (line 20) | def idle_store(tmp_path): function no_reset_store (line 33) | def no_reset_store(tmp_path): class TestIsSessionExpired (line 45) | class TestIsSessionExpired: method test_idle_session_expired (line 48) | def test_idle_session_expired(self, idle_store): method test_active_session_not_expired (line 59) | def test_active_session_not_expired(self, idle_store): method test_none_mode_never_expires (line 70) | def test_none_mode_never_expires(self, no_reset_store): method test_active_processes_prevent_expiry (line 81) | def test_active_processes_prevent_expiry(self, idle_store): method test_daily_mode_expired (line 94) | def test_daily_mode_expired(self, tmp_path): class TestGetOrCreateSessionNoCallback (line 115) | class TestGetOrCreateSessionNoCallback: method test_auto_reset_cleans_pre_flushed_marker (line 118) | def test_auto_reset_cleans_pre_flushed_marker(self, idle_store): method test_no_sync_callback_invoked (line 144) | def test_no_sync_callback_invoked(self, idle_store): class TestPreFlushedSessionsTracking (line 163) | class TestPreFlushedSessionsTracking: method test_starts_empty (line 166) | def test_starts_empty(self, idle_store): method test_add_and_check (line 169) | def test_add_and_check(self, idle_store): method test_discard_on_reset (line 174) | def test_discard_on_reset(self, idle_store): FILE: tests/gateway/test_background_command.py function _make_event (line 18) | def _make_event(text="/background", platform=Platform.TELEGRAM, function _make_runner (line 30) | def _make_runner(): class TestHandleBackgroundCommand (line 56) | class TestHandleBackgroundCommand: method test_no_prompt_shows_usage (line 60) | async def test_no_prompt_shows_usage(self): method test_bg_alias_no_prompt_shows_usage (line 69) | async def test_bg_alias_no_prompt_shows_usage(self): method test_empty_prompt_shows_usage (line 77) | async def test_empty_prompt_shows_usage(self): method test_valid_prompt_starts_task (line 85) | async def test_valid_prompt_starts_task(self): method test_prompt_truncated_in_preview (line 111) | async def test_prompt_truncated_in_preview(self): method test_task_id_is_unique (line 125) | async def test_task_id_is_unique(self): method test_works_across_platforms (line 143) | async def test_works_across_platforms(self): class TestRunBackgroundTask (line 161) | class TestRunBackgroundTask: method test_no_adapter_returns_silently (line 165) | async def test_no_adapter_returns_silently(self): method test_no_credentials_sends_error (line 178) | async def test_no_credentials_sends_error(self): method test_successful_task_sends_result (line 201) | async def test_successful_task_sends_result(self): method test_exception_sends_error_message (line 235) | async def test_exception_sends_error_message(self): class TestBackgroundInHelp (line 263) | class TestBackgroundInHelp: method test_background_in_help_output (line 267) | async def test_background_in_help_output(self): method test_background_is_known_command (line 274) | def test_background_is_known_command(self): method test_bg_alias_is_known_command (line 279) | def test_bg_alias_is_known_command(self): class TestBackgroundInCLICommands (line 290) | class TestBackgroundInCLICommands: method test_background_in_commands_dict (line 293) | def test_background_in_commands_dict(self): method test_bg_alias_in_commands_dict (line 298) | def test_bg_alias_in_commands_dict(self): method test_background_in_session_category (line 303) | def test_background_in_session_category(self): method test_background_autocompletes (line 308) | def test_background_autocompletes(self): FILE: tests/gateway/test_background_process_notifications.py class _FakeRegistry (line 24) | class _FakeRegistry: method __init__ (line 27) | def __init__(self, sessions): method get (line 30) | def get(self, session_id): function _build_runner (line 36) | def _build_runner(monkeypatch, tmp_path, mode: str) -> GatewayRunner: function _watcher_dict (line 53) | def _watcher_dict(session_id="proc_test", thread_id=""): class TestLoadBackgroundNotificationsMode (line 69) | class TestLoadBackgroundNotificationsMode: method test_defaults_to_all (line 71) | def test_defaults_to_all(self, monkeypatch, tmp_path): method test_reads_config_yaml (line 77) | def test_reads_config_yaml(self, monkeypatch, tmp_path): method test_env_var_overrides_config (line 86) | def test_env_var_overrides_config(self, monkeypatch, tmp_path): method test_false_value_maps_to_off (line 95) | def test_false_value_maps_to_off(self, monkeypatch, tmp_path): method test_invalid_value_defaults_to_all (line 104) | def test_invalid_value_defaults_to_all(self, monkeypatch, tmp_path): function test_run_process_watcher_respects_notification_mode (line 179) | async def test_run_process_watcher_respects_notification_mode( function test_thread_id_passed_to_send (line 205) | async def test_thread_id_passed_to_send(monkeypatch, tmp_path): function test_no_thread_id_sends_no_metadata (line 227) | async def test_no_thread_id_sends_no_metadata(monkeypatch, tmp_path): FILE: tests/gateway/test_base_topic_sessions.py class DummyTelegramAdapter (line 13) | class DummyTelegramAdapter(BasePlatformAdapter): method __init__ (line 14) | def __init__(self): method connect (line 19) | async def connect(self) -> bool: method disconnect (line 22) | async def disconnect(self) -> None: method send (line 25) | async def send(self, chat_id, content, reply_to=None, metadata=None) -... method send_typing (line 36) | async def send_typing(self, chat_id: str, metadata=None) -> None: method get_chat_info (line 40) | async def get_chat_info(self, chat_id: str): function _make_event (line 44) | def _make_event(chat_id: str, thread_id: str, message_id: str = "1") -> ... class TestBasePlatformTopicSessions (line 57) | class TestBasePlatformTopicSessions: method test_handle_message_does_not_interrupt_different_topic (line 59) | async def test_handle_message_does_not_interrupt_different_topic(self,... method test_handle_message_interrupts_same_topic (line 81) | async def test_handle_message_interrupts_same_topic(self, monkeypatch): method test_process_message_background_replies_in_same_topic (line 104) | async def test_process_message_background_replies_in_same_topic(self): FILE: tests/gateway/test_channel_directory.py function _write_directory (line 17) | def _write_directory(tmp_path, platforms): class TestLoadDirectory (line 25) | class TestLoadDirectory: method test_missing_file (line 26) | def test_missing_file(self, tmp_path): method test_valid_file (line 32) | def test_valid_file(self, tmp_path): method test_corrupt_file (line 40) | def test_corrupt_file(self, tmp_path): class TestResolveChannelName (line 48) | class TestResolveChannelName: method _setup (line 49) | def _setup(self, tmp_path, platforms): method test_exact_match (line 53) | def test_exact_match(self, tmp_path): method test_case_insensitive (line 64) | def test_case_insensitive(self, tmp_path): method test_guild_qualified_match (line 72) | def test_guild_qualified_match(self, tmp_path): method test_prefix_match_unambiguous (line 83) | def test_prefix_match_unambiguous(self, tmp_path): method test_prefix_match_ambiguous_returns_none (line 94) | def test_prefix_match_ambiguous_returns_none(self, tmp_path): method test_no_channels_returns_none (line 104) | def test_no_channels_returns_none(self, tmp_path): method test_no_match_returns_none (line 108) | def test_no_match_returns_none(self, tmp_path): method test_topic_name_resolves_to_composite_id (line 115) | def test_topic_name_resolves_to_composite_id(self, tmp_path): class TestBuildFromSessions (line 123) | class TestBuildFromSessions: method _write_sessions (line 124) | def _write_sessions(self, tmp_path, sessions_data): method test_builds_from_sessions_json (line 130) | def test_builds_from_sessions_json(self, tmp_path): method test_missing_sessions_file (line 164) | def test_missing_sessions_file(self, tmp_path): method test_deduplication_by_chat_id (line 169) | def test_deduplication_by_chat_id(self, tmp_path): method test_keeps_distinct_topics_with_same_chat_id (line 180) | def test_keeps_distinct_topics_with_same_chat_id(self, tmp_path): class TestFormatDirectoryForDisplay (line 217) | class TestFormatDirectoryForDisplay: method test_empty_directory (line 218) | def test_empty_directory(self, tmp_path): method test_telegram_display (line 223) | def test_telegram_display(self, tmp_path): method test_discord_grouped_by_guild (line 239) | def test_discord_grouped_by_guild(self, tmp_path): FILE: tests/gateway/test_config.py class TestHomeChannelRoundtrip (line 13) | class TestHomeChannelRoundtrip: method test_to_dict_from_dict (line 14) | def test_to_dict_from_dict(self): class TestPlatformConfigRoundtrip (line 24) | class TestPlatformConfigRoundtrip: method test_to_dict_from_dict (line 25) | def test_to_dict_from_dict(self): method test_disabled_no_token (line 44) | def test_disabled_no_token(self): class TestGetConnectedPlatforms (line 52) | class TestGetConnectedPlatforms: method test_returns_enabled_with_token (line 53) | def test_returns_enabled_with_token(self): method test_empty_platforms (line 66) | def test_empty_platforms(self): class TestSessionResetPolicy (line 71) | class TestSessionResetPolicy: method test_roundtrip (line 72) | def test_roundtrip(self): method test_defaults (line 80) | def test_defaults(self): method test_from_dict_treats_null_values_as_defaults (line 86) | def test_from_dict_treats_null_values_as_defaults(self): class TestGatewayConfigRoundtrip (line 95) | class TestGatewayConfigRoundtrip: method test_full_roundtrip (line 96) | def test_full_roundtrip(self): method test_roundtrip_preserves_unauthorized_dm_behavior (line 118) | def test_roundtrip_preserves_unauthorized_dm_behavior(self): class TestLoadGatewayConfig (line 135) | class TestLoadGatewayConfig: method test_bridges_quick_commands_from_config_yaml (line 136) | def test_bridges_quick_commands_from_config_yaml(self, tmp_path, monke... method test_bridges_group_sessions_per_user_from_config_yaml (line 154) | def test_bridges_group_sessions_per_user_from_config_yaml(self, tmp_pa... method test_invalid_quick_commands_in_config_yaml_are_ignored (line 166) | def test_invalid_quick_commands_in_config_yaml_are_ignored(self, tmp_p... method test_bridges_unauthorized_dm_behavior_from_config_yaml (line 178) | def test_bridges_unauthorized_dm_behavior_from_config_yaml(self, tmp_p... FILE: tests/gateway/test_config_cwd_bridge.py function _simulate_config_bridge (line 17) | def _simulate_config_bridge(cfg: dict, initial_env: dict | None = None): class TestTopLevelCwdAlias (line 65) | class TestTopLevelCwdAlias: method test_top_level_cwd_sets_terminal_cwd (line 68) | def test_top_level_cwd_sets_terminal_cwd(self): method test_top_level_backend_sets_terminal_env (line 73) | def test_top_level_backend_sets_terminal_env(self): method test_top_level_cwd_and_backend (line 78) | def test_top_level_cwd_and_backend(self): method test_nested_terminal_takes_precedence_over_top_level (line 84) | def test_nested_terminal_takes_precedence_over_top_level(self): method test_nested_terminal_backend_takes_precedence (line 93) | def test_nested_terminal_backend_takes_precedence(self): method test_no_cwd_falls_back_to_messaging_cwd (line 101) | def test_no_cwd_falls_back_to_messaging_cwd(self): method test_no_cwd_no_messaging_cwd_falls_back_to_home (line 106) | def test_no_cwd_no_messaging_cwd_falls_back_to_home(self): method test_dot_cwd_triggers_messaging_fallback (line 111) | def test_dot_cwd_triggers_messaging_fallback(self): method test_auto_cwd_triggers_messaging_fallback (line 123) | def test_auto_cwd_triggers_messaging_fallback(self): method test_empty_cwd_ignored (line 128) | def test_empty_cwd_ignored(self): method test_whitespace_only_cwd_ignored (line 133) | def test_whitespace_only_cwd_ignored(self): method test_messaging_cwd_env_var_works (line 138) | def test_messaging_cwd_env_var_works(self): method test_top_level_cwd_beats_messaging_cwd (line 144) | def test_top_level_cwd_beats_messaging_cwd(self): FILE: tests/gateway/test_delivery.py class TestParseTargetPlatformChat (line 8) | class TestParseTargetPlatformChat: method test_explicit_telegram_chat (line 9) | def test_explicit_telegram_chat(self): method test_platform_only_no_chat_id (line 15) | def test_platform_only_no_chat_id(self): method test_local_target (line 21) | def test_local_target(self): method test_origin_with_source (line 26) | def test_origin_with_source(self): method test_origin_without_source (line 34) | def test_origin_without_source(self): method test_unknown_platform (line 39) | def test_unknown_platform(self): class TestParseDeliverSpec (line 44) | class TestParseDeliverSpec: method test_none_returns_default (line 45) | def test_none_returns_default(self): method test_empty_string_returns_default (line 49) | def test_empty_string_returns_default(self): method test_custom_default (line 53) | def test_custom_default(self): method test_passthrough_string (line 57) | def test_passthrough_string(self): method test_passthrough_list (line 61) | def test_passthrough_list(self): class TestTargetToStringRoundtrip (line 66) | class TestTargetToStringRoundtrip: method test_origin_roundtrip (line 67) | def test_origin_roundtrip(self): method test_local_roundtrip (line 72) | def test_local_roundtrip(self): method test_platform_only_roundtrip (line 76) | def test_platform_only_roundtrip(self): method test_explicit_chat_roundtrip (line 80) | def test_explicit_chat_roundtrip(self): class TestDeliveryRouter (line 90) | class TestDeliveryRouter: method test_resolve_targets_does_not_duplicate_local_when_explicit (line 91) | def test_resolve_targets_does_not_duplicate_local_when_explicit(self): FILE: tests/gateway/test_dingtalk.py class TestDingTalkRequirements (line 17) | class TestDingTalkRequirements: method test_returns_false_when_sdk_missing (line 19) | def test_returns_false_when_sdk_missing(self, monkeypatch): method test_returns_false_when_env_vars_missing (line 27) | def test_returns_false_when_env_vars_missing(self, monkeypatch): method test_returns_true_when_all_available (line 37) | def test_returns_true_when_all_available(self, monkeypatch): class TestDingTalkAdapterInit (line 53) | class TestDingTalkAdapterInit: method test_reads_config_from_extra (line 55) | def test_reads_config_from_extra(self): method test_falls_back_to_env_vars (line 66) | def test_falls_back_to_env_vars(self, monkeypatch): class TestExtractText (line 81) | class TestExtractText: method test_extracts_dict_text (line 83) | def test_extracts_dict_text(self): method test_extracts_string_text (line 90) | def test_extracts_string_text(self): method test_falls_back_to_rich_text (line 97) | def test_falls_back_to_rich_text(self): method test_returns_empty_for_no_content (line 104) | def test_returns_empty_for_no_content(self): class TestDeduplication (line 117) | class TestDeduplication: method test_first_message_not_duplicate (line 119) | def test_first_message_not_duplicate(self): method test_second_same_message_is_duplicate (line 124) | def test_second_same_message_is_duplicate(self): method test_different_messages_not_duplicate (line 130) | def test_different_messages_not_duplicate(self): method test_cache_cleanup_on_overflow (line 136) | def test_cache_cleanup_on_overflow(self): class TestSend (line 151) | class TestSend: method test_send_posts_to_webhook (line 154) | async def test_send_posts_to_webhook(self): method test_send_fails_without_webhook (line 180) | async def test_send_fails_without_webhook(self): method test_send_uses_cached_webhook (line 190) | async def test_send_uses_cached_webhook(self): method test_send_handles_http_error (line 206) | async def test_send_handles_http_error(self): class TestConnect (line 230) | class TestConnect: method test_connect_fails_without_sdk (line 233) | async def test_connect_fails_without_sdk(self, monkeypatch): method test_connect_fails_without_credentials (line 243) | async def test_connect_fails_without_credentials(self): method test_disconnect_cleans_up (line 252) | async def test_disconnect_cleans_up(self): class TestPlatformEnum (line 271) | class TestPlatformEnum: method test_dingtalk_in_platform_enum (line 273) | def test_dingtalk_in_platform_enum(self): FILE: tests/gateway/test_discord_bot_filter.py function _make_author (line 9) | def _make_author(*, bot: bool = False, is_self: bool = False): function _make_message (line 19) | def _make_message(*, author=None, content="hello", mentions=None, is_dm=... class TestDiscordBotFilter (line 41) | class TestDiscordBotFilter(unittest.TestCase): method _run_filter (line 44) | def _run_filter(self, message, allow_bots="none", client_user=None): method test_own_messages_always_ignored (line 61) | def test_own_messages_always_ignored(self): method test_human_messages_always_accepted (line 67) | def test_human_messages_always_accepted(self): method test_allow_bots_none_rejects_bots (line 75) | def test_allow_bots_none_rejects_bots(self): method test_allow_bots_all_accepts_bots (line 81) | def test_allow_bots_all_accepts_bots(self): method test_allow_bots_mentions_rejects_without_mention (line 87) | def test_allow_bots_mentions_rejects_without_mention(self): method test_allow_bots_mentions_accepts_with_mention (line 94) | def test_allow_bots_mentions_accepts_with_mention(self): method test_default_is_none (line 101) | def test_default_is_none(self): method test_case_insensitive (line 106) | def test_case_insensitive(self): FILE: tests/gateway/test_discord_free_response.py function _ensure_discord_mock (line 13) | def _ensure_discord_mock(): class FakeDMChannel (line 52) | class FakeDMChannel: method __init__ (line 53) | def __init__(self, channel_id: int = 1, name: str = "dm"): class FakeTextChannel (line 58) | class FakeTextChannel: method __init__ (line 59) | def __init__(self, channel_id: int = 1, name: str = "general", guild_n... class FakeForumChannel (line 66) | class FakeForumChannel: method __init__ (line 67) | def __init__(self, channel_id: int = 1, name: str = "support-forum", g... class FakeThread (line 75) | class FakeThread: method __init__ (line 76) | def __init__(self, channel_id: int = 1, name: str = "thread", parent=N... function adapter (line 86) | def adapter(monkeypatch): function make_message (line 98) | def make_message(*, channel, content: str, mentions=None): function test_discord_defaults_to_require_mention (line 113) | async def test_discord_defaults_to_require_mention(adapter, monkeypatch): function test_discord_free_response_in_server_channels (line 127) | async def test_discord_free_response_in_server_channels(adapter, monkeyp... function test_discord_free_response_in_threads (line 143) | async def test_discord_free_response_in_threads(adapter, monkeypatch): function test_discord_forum_threads_are_handled_as_threads (line 161) | async def test_discord_forum_threads_are_handled_as_threads(adapter, mon... function test_discord_can_still_require_mentions_when_enabled (line 181) | async def test_discord_can_still_require_mentions_when_enabled(adapter, ... function test_discord_free_response_channel_overrides_mention_requirement (line 193) | async def test_discord_free_response_channel_overrides_mention_requireme... function test_discord_forum_parent_in_free_response_list_allows_forum_thread (line 207) | async def test_discord_forum_parent_in_free_response_list_allows_forum_t... function test_discord_accepts_and_strips_bot_mentions_when_required (line 224) | async def test_discord_accepts_and_strips_bot_mentions_when_required(ada... function test_discord_dms_ignore_mention_requirement (line 243) | async def test_discord_dms_ignore_mention_requirement(adapter, monkeypat... function test_discord_auto_thread_enabled_by_default (line 258) | async def test_discord_auto_thread_enabled_by_default(adapter, monkeypat... function test_discord_auto_thread_can_be_disabled (line 279) | async def test_discord_auto_thread_can_be_disabled(adapter, monkeypatch): function test_discord_bot_thread_skips_mention_requirement (line 297) | async def test_discord_bot_thread_skips_mention_requirement(adapter, mon... function test_discord_unknown_thread_still_requires_mention (line 318) | async def test_discord_unknown_thread_still_requires_mention(adapter, mo... function test_discord_auto_thread_tracks_participation (line 334) | async def test_discord_auto_thread_tracks_participation(adapter, monkeyp... function test_discord_thread_participation_tracked_on_dispatch (line 350) | async def test_discord_thread_participation_tracked_on_dispatch(adapter,... FILE: tests/gateway/test_discord_imports.py class TestDiscordImportSafety (line 8) | class TestDiscordImportSafety: method test_module_imports_even_when_discord_dependency_is_missing (line 9) | def test_module_imports_even_when_discord_dependency_is_missing(self, ... FILE: tests/gateway/test_discord_media_metadata.py function test_discord_media_methods_accept_metadata_kwarg (line 6) | def test_discord_media_methods_accept_metadata_kwarg(): FILE: tests/gateway/test_discord_opus.py class TestOpusFindLibrary (line 6) | class TestOpusFindLibrary: method test_uses_find_library_first (line 9) | def test_uses_find_library_first(self): method test_homebrew_fallback_is_conditional (line 16) | def test_homebrew_fallback_is_conditional(self): method test_opus_decode_error_logged (line 32) | def test_opus_decode_error_logged(self): FILE: tests/gateway/test_discord_send.py function _ensure_discord_mock (line 10) | def _ensure_discord_mock(): function test_send_retries_without_reference_when_reply_target_is_system_message (line 48) | async def test_send_retries_without_reference_when_reply_target_is_syste... FILE: tests/gateway/test_discord_slash_commands.py function _ensure_discord_mock (line 12) | def _ensure_discord_mock(): class FakeTree (line 43) | class FakeTree: method __init__ (line 44) | def __init__(self): method command (line 47) | def command(self, *, name, description): function adapter (line 56) | def adapter(): function test_registers_native_thread_slash_command (line 74) | async def test_registers_native_thread_slash_command(adapter): function test_handle_thread_create_slash_reports_success (line 95) | async def test_handle_thread_create_slash_reports_success(adapter): function test_handle_thread_create_slash_dispatches_session_when_message_provided (line 123) | async def test_handle_thread_create_slash_dispatches_session_when_messag... function test_handle_thread_create_slash_no_dispatch_without_message (line 145) | async def test_handle_thread_create_slash_no_dispatch_without_message(ad... function test_handle_thread_create_slash_falls_back_to_seed_message (line 165) | async def test_handle_thread_create_slash_falls_back_to_seed_message(ada... function test_handle_thread_create_slash_reports_failure (line 192) | async def test_handle_thread_create_slash_reports_failure(adapter): function test_dispatch_thread_session_builds_thread_event (line 219) | async def test_dispatch_thread_session_builds_thread_event(adapter): function test_auto_create_thread_uses_message_content_as_name (line 250) | async def test_auto_create_thread_uses_message_content_as_name(adapter): function test_auto_create_thread_truncates_long_names (line 267) | async def test_auto_create_thread_truncates_long_names(adapter): function test_auto_create_thread_returns_none_on_failure (line 284) | async def test_auto_create_thread_returns_none_on_failure(adapter): class _FakeTextChannel (line 302) | class _FakeTextChannel: method __init__ (line 305) | def __init__(self, channel_id=100, name="general", guild_name="TestGui... class _FakeThreadChannel (line 312) | class _FakeThreadChannel(_discord_mod.Thread): method __init__ (line 315) | def __init__(self, channel_id=200, name="existing-thread", guild_name=... function _fake_message (line 324) | def _fake_message(channel, *, content="Hello", author_id=42, display_nam... function test_auto_thread_creates_thread_and_redirects (line 338) | async def test_auto_thread_creates_thread_and_redirects(adapter, monkeyp... function test_auto_thread_enabled_by_default_slash_commands (line 366) | async def test_auto_thread_enabled_by_default_slash_commands(adapter, mo... function test_auto_thread_can_be_disabled (line 392) | async def test_auto_thread_can_be_disabled(adapter, monkeypatch): function test_auto_thread_skips_threads_and_dms (line 416) | async def test_auto_thread_skips_threads_and_dms(adapter, monkeypatch): function test_discord_auto_thread_config_bridge (line 442) | def test_discord_auto_thread_config_bridge(monkeypatch, tmp_path): FILE: tests/gateway/test_discord_thread_persistence.py class TestDiscordThreadPersistence (line 14) | class TestDiscordThreadPersistence: method _make_adapter (line 17) | def _make_adapter(self, tmp_path): method test_starts_empty_when_no_state_file (line 26) | def test_starts_empty_when_no_state_file(self, tmp_path): method test_track_thread_persists_to_disk (line 30) | def test_track_thread_persists_to_disk(self, tmp_path): method test_threads_survive_restart (line 41) | def test_threads_survive_restart(self, tmp_path): method test_duplicate_track_does_not_double_save (line 52) | def test_duplicate_track_does_not_double_save(self, tmp_path): method test_caps_at_max_tracked_threads (line 61) | def test_caps_at_max_tracked_threads(self, tmp_path): method test_corrupted_state_file_falls_back_to_empty (line 70) | def test_corrupted_state_file_falls_back_to_empty(self, tmp_path): method test_missing_hermes_home_does_not_crash (line 76) | def test_missing_hermes_home_does_not_crash(self, tmp_path): FILE: tests/gateway/test_document_cache.py function _redirect_cache (line 26) | def _redirect_cache(tmp_path, monkeypatch): class TestGetDocumentCacheDir (line 37) | class TestGetDocumentCacheDir: method test_creates_directory (line 38) | def test_creates_directory(self, tmp_path): method test_returns_existing_directory (line 43) | def test_returns_existing_directory(self): class TestCacheDocumentFromBytes (line 54) | class TestCacheDocumentFromBytes: method test_basic_caching (line 55) | def test_basic_caching(self): method test_filename_preserved_in_path (line 61) | def test_filename_preserved_in_path(self): method test_empty_filename_uses_fallback (line 65) | def test_empty_filename_uses_fallback(self): method test_unique_filenames (line 69) | def test_unique_filenames(self): method test_path_traversal_blocked (line 74) | def test_path_traversal_blocked(self): method test_null_bytes_stripped (line 85) | def test_null_bytes_stripped(self): method test_dot_dot_filename_handled (line 91) | def test_dot_dot_filename_handled(self): method test_none_filename_uses_fallback (line 97) | def test_none_filename_uses_fallback(self): class TestCleanupDocumentCache (line 106) | class TestCleanupDocumentCache: method test_removes_old_files (line 107) | def test_removes_old_files(self, tmp_path): method test_keeps_recent_files (line 119) | def test_keeps_recent_files(self): method test_returns_removed_count (line 128) | def test_returns_removed_count(self): method test_empty_cache_dir (line 138) | def test_empty_cache_dir(self): class TestSupportedDocumentTypes (line 146) | class TestSupportedDocumentTypes: method test_all_extensions_have_mime_types (line 147) | def test_all_extensions_have_mime_types(self): method test_expected_extensions_present (line 156) | def test_expected_extensions_present(self, ext): FILE: tests/gateway/test_email.py class TestPlatformEnum (line 28) | class TestPlatformEnum(unittest.TestCase): method test_email_in_platform_enum (line 31) | def test_email_in_platform_enum(self): class TestConfigEnvOverrides (line 36) | class TestConfigEnvOverrides(unittest.TestCase): method test_email_config_loaded_from_env (line 45) | def test_email_config_loaded_from_env(self): method test_email_home_channel_loaded (line 60) | def test_email_home_channel_loaded(self): method test_email_not_loaded_without_env (line 69) | def test_email_not_loaded_without_env(self): method test_email_in_connected_platforms (line 81) | def test_email_in_connected_platforms(self): class TestCheckRequirements (line 89) | class TestCheckRequirements(unittest.TestCase): method test_requirements_met (line 98) | def test_requirements_met(self): method test_requirements_not_met (line 105) | def test_requirements_not_met(self): method test_requirements_empty_env (line 110) | def test_requirements_empty_env(self): class TestHelperFunctions (line 115) | class TestHelperFunctions(unittest.TestCase): method test_decode_header_plain (line 118) | def test_decode_header_plain(self): method test_decode_header_encoded (line 122) | def test_decode_header_encoded(self): method test_extract_email_address_with_name (line 129) | def test_extract_email_address_with_name(self): method test_extract_email_address_bare (line 136) | def test_extract_email_address_bare(self): method test_extract_email_address_uppercase (line 143) | def test_extract_email_address_uppercase(self): method test_strip_html_basic (line 150) | def test_strip_html_basic(self): method test_strip_html_br_tags (line 159) | def test_strip_html_br_tags(self): method test_strip_html_entities (line 166) | def test_strip_html_entities(self): class TestExtractTextBody (line 173) | class TestExtractTextBody(unittest.TestCase): method test_plain_text_body (line 176) | def test_plain_text_body(self): method test_html_body_fallback (line 182) | def test_html_body_fallback(self): method test_multipart_prefers_plain (line 189) | def test_multipart_prefers_plain(self): method test_multipart_html_only (line 197) | def test_multipart_html_only(self): method test_empty_body (line 204) | def test_empty_body(self): class TestExtractAttachments (line 211) | class TestExtractAttachments(unittest.TestCase): method test_no_attachments (line 214) | def test_no_attachments(self): method test_document_attachment (line 221) | def test_document_attachment(self, mock_cache): method test_image_attachment (line 241) | def test_image_attachment(self, mock_cache): class TestAuthorizationMaps (line 260) | class TestAuthorizationMaps(unittest.TestCase): method test_email_in_adapter_factory (line 263) | def test_email_in_adapter_factory(self): method test_email_in_allowed_users_map (line 270) | def test_email_in_allowed_users_map(self): method test_email_in_allow_all_map (line 277) | def test_email_in_allow_all_map(self): class TestSendMessageToolRouting (line 285) | class TestSendMessageToolRouting(unittest.TestCase): method test_email_in_platform_map (line 288) | def test_email_in_platform_map(self): method test_send_to_platform_has_email_branch (line 294) | def test_send_to_platform_has_email_branch(self): class TestCronDelivery (line 301) | class TestCronDelivery(unittest.TestCase): method test_email_in_cron_platform_map (line 304) | def test_email_in_cron_platform_map(self): class TestToolset (line 311) | class TestToolset(unittest.TestCase): method test_email_toolset_exists (line 314) | def test_email_toolset_exists(self): method test_email_in_gateway_toolset (line 318) | def test_email_in_gateway_toolset(self): class TestPlatformHints (line 324) | class TestPlatformHints(unittest.TestCase): method test_email_in_platform_hints (line 327) | def test_email_in_platform_hints(self): class TestChannelDirectory (line 333) | class TestChannelDirectory(unittest.TestCase): method test_email_in_session_discovery (line 336) | def test_email_in_session_discovery(self): class TestGatewaySetup (line 343) | class TestGatewaySetup(unittest.TestCase): method test_email_in_platforms_list (line 346) | def test_email_in_platforms_list(self): method test_email_has_setup_vars (line 351) | def test_email_has_setup_vars(self): class TestEnvExample (line 361) | class TestEnvExample(unittest.TestCase): method test_env_example_has_email_vars (line 364) | def test_env_example_has_email_vars(self): class TestDispatchMessage (line 373) | class TestDispatchMessage(unittest.TestCase): method _make_adapter (line 376) | def _make_adapter(self): method test_self_message_filtered (line 392) | def test_self_message_filtered(self): method test_subject_included_in_text (line 413) | def test_subject_included_in_text(self): method test_reply_subject_not_duplicated (line 449) | def test_reply_subject_not_duplicated(self): method test_empty_body_handled (line 477) | def test_empty_body_handled(self): method test_image_attachment_sets_photo_type (line 504) | def test_image_attachment_sets_photo_type(self): method test_source_built_correctly (line 533) | def test_source_built_correctly(self): class TestThreadContext (line 564) | class TestThreadContext(unittest.TestCase): method _make_adapter (line 567) | def _make_adapter(self): method test_thread_context_stored_after_dispatch (line 579) | def test_thread_context_stored_after_dispatch(self): method test_reply_uses_re_prefix (line 607) | def test_reply_uses_re_prefix(self): method test_reply_does_not_double_re (line 627) | def test_reply_does_not_double_re(self): method test_no_thread_context_uses_default_subject (line 645) | def test_no_thread_context_uses_default_subject(self): class TestSendMethods (line 659) | class TestSendMethods(unittest.TestCase): method _make_adapter (line 662) | def _make_adapter(self): method test_send_calls_smtp (line 674) | def test_send_calls_smtp(self): method test_send_failure_returns_error (line 693) | def test_send_failure_returns_error(self): method test_send_image_includes_url (line 708) | def test_send_image_includes_url(self): method test_send_document_with_attachment (line 725) | def test_send_document_with_attachment(self): method test_send_typing_is_noop (line 757) | def test_send_typing_is_noop(self): method test_get_chat_info (line 764) | def test_get_chat_info(self): class TestConnectDisconnect (line 779) | class TestConnectDisconnect(unittest.TestCase): method _make_adapter (line 782) | def _make_adapter(self): method test_connect_success (line 794) | def test_connect_success(self): method test_connect_imap_failure (line 818) | def test_connect_imap_failure(self): method test_connect_smtp_failure (line 828) | def test_connect_smtp_failure(self): method test_disconnect_cancels_poll (line 841) | def test_disconnect_cancels_poll(self): class TestFetchNewMessages (line 857) | class TestFetchNewMessages(unittest.TestCase): method _make_adapter (line 860) | def _make_adapter(self): method test_fetch_skips_seen_uids (line 872) | def test_fetch_skips_seen_uids(self): method test_fetch_no_unseen_messages (line 901) | def test_fetch_no_unseen_messages(self): method test_fetch_handles_imap_error (line 913) | def test_fetch_handles_imap_error(self): method test_fetch_extracts_sender_name (line 922) | def test_fetch_extracts_sender_name(self): class TestPollLoop (line 950) | class TestPollLoop(unittest.TestCase): method _make_adapter (line 953) | def _make_adapter(self): method test_check_inbox_dispatches_messages (line 966) | def test_check_inbox_dispatches_messages(self): class TestSendEmailStandalone (line 1000) | class TestSendEmailStandalone(unittest.TestCase): method test_send_email_tool_success (line 1009) | def test_send_email_tool_success(self): method test_send_email_tool_failure (line 1033) | def test_send_email_tool_failure(self): method test_send_email_tool_not_configured (line 1047) | def test_send_email_tool_not_configured(self): FILE: tests/gateway/test_extract_local_files.py function _extract (line 23) | def _extract(content: str, existing_files: set[str] | None = None): class TestBasicDetection (line 50) | class TestBasicDetection: method test_absolute_path_image (line 52) | def test_absolute_path_image(self): method test_tilde_path_image (line 58) | def test_tilde_path_image(self): method test_video_extensions (line 63) | def test_video_extensions(self): method test_image_extensions (line 70) | def test_image_extensions(self): method test_case_insensitive_extension (line 77) | def test_case_insensitive_extension(self): method test_multiple_paths (line 81) | def test_multiple_paths(self): method test_path_at_line_start (line 91) | def test_path_at_line_start(self): method test_path_at_end_of_line (line 95) | def test_path_at_end_of_line(self): method test_path_with_dots_in_directory (line 99) | def test_path_with_dots_in_directory(self): method test_path_with_hyphens (line 103) | def test_path_with_hyphens(self): class TestIsfileGuard (line 112) | class TestIsfileGuard: method test_nonexistent_path_skipped (line 114) | def test_nonexistent_path_skipped(self): method test_only_existing_paths_extracted (line 123) | def test_only_existing_paths_extracted(self): class TestURLRejection (line 138) | class TestURLRejection: method test_https_url_not_matched (line 140) | def test_https_url_not_matched(self): method test_http_url_not_matched (line 149) | def test_http_url_not_matched(self): method test_file_url_not_matched (line 153) | def test_file_url_not_matched(self): class TestCodeBlockExclusion (line 163) | class TestCodeBlockExclusion: method test_fenced_code_block_skipped (line 165) | def test_fenced_code_block_skipped(self): method test_inline_code_skipped (line 171) | def test_inline_code_skipped(self): method test_path_outside_code_block_still_matched (line 177) | def test_path_outside_code_block_still_matched(self): method test_mixed_inline_code_and_bare_path (line 185) | def test_mixed_inline_code_and_bare_path(self): method test_multiline_fenced_block (line 192) | def test_multiline_fenced_block(self): class TestDeduplication (line 208) | class TestDeduplication: method test_duplicate_paths_deduplicated (line 210) | def test_duplicate_paths_deduplicated(self): method test_tilde_and_expanded_same_file (line 215) | def test_tilde_and_expanded_same_file(self): class TestTextCleanup (line 227) | class TestTextCleanup: method test_path_removed_from_text (line 229) | def test_path_removed_from_text(self): method test_excessive_blank_lines_collapsed (line 235) | def test_excessive_blank_lines_collapsed(self): method test_no_paths_text_unchanged (line 240) | def test_no_paths_text_unchanged(self): method test_tilde_form_cleaned_from_text (line 246) | def test_tilde_form_cleaned_from_text(self): method test_only_path_in_text (line 253) | def test_only_path_in_text(self): class TestEdgeCases (line 264) | class TestEdgeCases: method test_empty_string (line 266) | def test_empty_string(self): method test_no_media_extensions (line 271) | def test_no_media_extensions(self): method test_path_with_spaces_not_matched (line 276) | def test_path_with_spaces_not_matched(self): method test_windows_path_not_matched (line 281) | def test_windows_path_not_matched(self): method test_relative_path_not_matched (line 286) | def test_relative_path_not_matched(self): method test_bare_filename_not_matched (line 291) | def test_bare_filename_not_matched(self): method test_path_followed_by_punctuation (line 296) | def test_path_followed_by_punctuation(self): method test_path_in_parentheses (line 303) | def test_path_in_parentheses(self): method test_path_in_quotes (line 307) | def test_path_in_quotes(self): method test_deep_nested_path (line 311) | def test_deep_nested_path(self): FILE: tests/gateway/test_gateway_shutdown.py class StubAdapter (line 12) | class StubAdapter(BasePlatformAdapter): method __init__ (line 13) | def __init__(self): method connect (line 16) | async def connect(self): method disconnect (line 19) | async def disconnect(self): method send (line 22) | async def send(self, chat_id, content, reply_to=None, metadata=None): method send_typing (line 25) | async def send_typing(self, chat_id, metadata=None): method get_chat_info (line 28) | async def get_chat_info(self, chat_id): function _source (line 32) | def _source(chat_id="123456", chat_type="dm"): function test_cancel_background_tasks_cancels_inflight_message_processing (line 41) | async def test_cancel_background_tasks_cancels_inflight_message_processi... function test_gateway_stop_interrupts_running_agents_and_cancels_adapter_tasks (line 67) | async def test_gateway_stop_interrupts_running_agents_and_cancels_adapte... FILE: tests/gateway/test_homeassistant.py class TestCheckRequirements (line 28) | class TestCheckRequirements: method test_returns_false_without_token (line 29) | def test_returns_false_without_token(self, monkeypatch): method test_returns_true_with_token (line 33) | def test_returns_true_with_token(self, monkeypatch): method test_returns_false_without_aiohttp (line 38) | def test_returns_false_without_aiohttp(self, monkeypatch): class TestFormatStateChange (line 48) | class TestFormatStateChange: method fmt (line 50) | def fmt(entity_id, old_state, new_state): method test_climate_includes_temperatures (line 53) | def test_climate_includes_temperatures(self): method test_sensor_includes_unit (line 67) | def test_sensor_includes_unit(self): method test_sensor_without_unit (line 79) | def test_sensor_without_unit(self): method test_binary_sensor_on (line 87) | def test_binary_sensor_on(self): method test_binary_sensor_off (line 96) | def test_binary_sensor_off(self): method test_light_turned_on (line 104) | def test_light_turned_on(self): method test_switch_turned_off (line 112) | def test_switch_turned_off(self): method test_fan_domain_uses_light_switch_branch (line 120) | def test_fan_domain_uses_light_switch_branch(self): method test_alarm_panel (line 128) | def test_alarm_panel(self): method test_generic_domain_includes_entity_id (line 137) | def test_generic_domain_includes_entity_id(self): method test_same_state_returns_none (line 146) | def test_same_state_returns_none(self): method test_empty_new_state_returns_none (line 153) | def test_empty_new_state_returns_none(self): method test_no_old_state_uses_unknown (line 156) | def test_no_old_state_uses_unknown(self): method test_uses_entity_id_when_no_friendly_name (line 165) | def test_uses_entity_id_when_no_friendly_name(self): class TestAdapterInit (line 179) | class TestAdapterInit: method test_url_and_token_from_config_extra (line 180) | def test_url_and_token_from_config_extra(self, monkeypatch): method test_url_fallback_to_env (line 193) | def test_url_fallback_to_env(self, monkeypatch): method test_trailing_slash_stripped (line 201) | def test_trailing_slash_stripped(self): method test_watch_filters_parsed (line 209) | def test_watch_filters_parsed(self): method test_watch_all_parsed (line 226) | def test_watch_all_parsed(self): method test_defaults_when_no_extra (line 234) | def test_defaults_when_no_extra(self, monkeypatch): function _make_adapter (line 253) | def _make_adapter(**extra) -> HomeAssistantAdapter: function _make_event (line 260) | def _make_event(entity_id, old_state, new_state, old_attrs=None, new_att... class TestEventFilteringPipeline (line 270) | class TestEventFilteringPipeline: method test_ignored_entity_not_forwarded (line 272) | async def test_ignored_entity_not_forwarded(self): method test_unwatched_domain_not_forwarded (line 278) | async def test_unwatched_domain_not_forwarded(self): method test_watched_domain_forwarded (line 284) | async def test_watched_domain_forwarded(self): method test_watched_entity_forwarded (line 300) | async def test_watched_entity_forwarded(self): method test_no_filters_blocks_everything (line 311) | async def test_no_filters_blocks_everything(self): method test_watch_all_passes_everything (line 318) | async def test_watch_all_passes_everything(self): method test_same_state_not_forwarded (line 325) | async def test_same_state_not_forwarded(self): method test_empty_entity_id_skipped (line 331) | async def test_empty_entity_id_skipped(self): method test_message_event_has_correct_source (line 337) | async def test_message_event_has_correct_source(self): class TestCooldown (line 354) | class TestCooldown: method test_cooldown_blocks_rapid_events (line 356) | async def test_cooldown_blocks_rapid_events(self): method test_cooldown_expires (line 371) | async def test_cooldown_expires(self): method test_different_entities_independent_cooldowns (line 388) | async def test_different_entities_independent_cooldowns(self): method test_zero_cooldown_passes_all (line 407) | async def test_zero_cooldown_passes_all(self): class TestConfigIntegration (line 423) | class TestConfigIntegration: method test_env_override_creates_ha_platform (line 424) | def test_env_override_creates_ha_platform(self, monkeypatch): method test_no_env_no_platform (line 440) | def test_no_env_no_platform(self, monkeypatch): method test_config_roundtrip_preserves_extra (line 449) | def test_config_roundtrip_preserves_extra(self): method test_connected_platforms_includes_ha (line 472) | def test_connected_platforms_includes_ha(self): class TestSendViaRestApi (line 489) | class TestSendViaRestApi: method _mock_aiohttp_session (line 493) | def _mock_aiohttp_session(response_status=200, response_text="OK"): method test_send_success (line 515) | async def test_send_success(self): method test_send_http_error (line 534) | async def test_send_http_error(self): method test_send_truncates_long_message (line 548) | async def test_send_truncates_long_message(self): method test_send_does_not_use_websocket (line 563) | async def test_send_does_not_use_websocket(self): class TestToolsetIntegration (line 585) | class TestToolsetIntegration: method test_homeassistant_toolset_resolves (line 586) | def test_homeassistant_toolset_resolves(self): method test_gateway_toolset_includes_ha_tools (line 592) | def test_gateway_toolset_includes_ha_tools(self): method test_hermes_core_tools_includes_ha (line 599) | def test_hermes_core_tools_includes_ha(self): class TestWsUrlConstruction (line 611) | class TestWsUrlConstruction: method test_http_to_ws (line 612) | def test_http_to_ws(self): method test_https_to_wss (line 618) | def test_https_to_wss(self): FILE: tests/gateway/test_honcho_lifecycle.py function _make_runner (line 13) | def _make_runner(): function _make_event (line 28) | def _make_event(text="/reset"): class TestGatewayHonchoLifecycle (line 40) | class TestGatewayHonchoLifecycle: method test_gateway_reuses_honcho_manager_for_session_key (line 41) | def test_gateway_reuses_honcho_manager_for_session_key(self): method test_gateway_skips_honcho_manager_when_disabled (line 67) | def test_gateway_skips_honcho_manager_when_disabled(self): method test_reset_shuts_down_gateway_honcho_manager (line 89) | async def test_reset_shuts_down_gateway_honcho_manager(self): method test_flush_memories_reuses_gateway_session_key_and_skips_honcho_sync (line 107) | def test_flush_memories_reuses_gateway_session_key_and_skips_honcho_sy... FILE: tests/gateway/test_hooks.py function _create_hook (line 12) | def _create_hook(hooks_dir, hook_name, events, handler_code): class TestHookRegistryInit (line 25) | class TestHookRegistryInit: method test_empty_registry (line 26) | def test_empty_registry(self): class TestDiscoverAndLoad (line 32) | class TestDiscoverAndLoad: method test_loads_valid_hook (line 33) | def test_loads_valid_hook(self, tmp_path): method test_skips_missing_hook_yaml (line 45) | def test_skips_missing_hook_yaml(self, tmp_path): method test_skips_missing_handler_py (line 56) | def test_skips_missing_handler_py(self, tmp_path): method test_skips_no_events (line 67) | def test_skips_no_events(self, tmp_path): method test_skips_no_handle_function (line 79) | def test_skips_no_handle_function(self, tmp_path): method test_nonexistent_hooks_dir (line 91) | def test_nonexistent_hooks_dir(self, tmp_path): method test_multiple_hooks (line 98) | def test_multiple_hooks(self, tmp_path): class TestEmit (line 111) | class TestEmit: method test_emit_calls_sync_handler (line 113) | async def test_emit_calls_sync_handler(self, tmp_path): method test_emit_calls_async_handler (line 133) | async def test_emit_calls_async_handler(self, tmp_path): method test_wildcard_matching (line 159) | async def test_wildcard_matching(self, tmp_path): method test_no_handlers_for_event (line 178) | async def test_no_handlers_for_event(self, tmp_path): method test_handler_error_does_not_propagate (line 186) | async def test_handler_error_does_not_propagate(self, tmp_path): method test_emit_default_context (line 201) | async def test_emit_default_context(self, tmp_path): FILE: tests/gateway/test_interrupt_key_match.py class StubAdapter (line 18) | class StubAdapter(BasePlatformAdapter): method __init__ (line 21) | def __init__(self): method connect (line 24) | async def connect(self): method disconnect (line 27) | async def disconnect(self): method send (line 30) | async def send(self, chat_id, content, reply_to=None, metadata=None): method send_typing (line 33) | async def send_typing(self, chat_id, metadata=None): method get_chat_info (line 36) | async def get_chat_info(self, chat_id): function _source (line 40) | def _source(chat_id="123456", chat_type="dm", thread_id=None): class TestInterruptKeyConsistency (line 49) | class TestInterruptKeyConsistency: method test_session_key_differs_from_chat_id_for_dm (line 52) | def test_session_key_differs_from_chat_id_for_dm(self): method test_session_key_differs_from_chat_id_for_group (line 59) | def test_session_key_differs_from_chat_id_for_group(self): method test_has_pending_interrupt_requires_session_key (line 68) | async def test_has_pending_interrupt_requires_session_key(self): method test_get_pending_message_requires_session_key (line 86) | async def test_get_pending_message_requires_session_key(self): method test_handle_message_stores_under_session_key (line 103) | async def test_handle_message_stores_under_session_key(self): method test_photo_followup_is_queued_without_interrupt (line 127) | async def test_photo_followup_is_queued_without_interrupt(self): FILE: tests/gateway/test_matrix.py class TestMatrixPlatformEnum (line 14) | class TestMatrixPlatformEnum: method test_matrix_enum_exists (line 15) | def test_matrix_enum_exists(self): method test_matrix_in_platform_list (line 18) | def test_matrix_in_platform_list(self): class TestMatrixConfigLoading (line 23) | class TestMatrixConfigLoading: method test_apply_env_overrides_with_access_token (line 24) | def test_apply_env_overrides_with_access_token(self, monkeypatch): method test_apply_env_overrides_with_password (line 38) | def test_apply_env_overrides_with_password(self, monkeypatch): method test_matrix_not_loaded_without_creds (line 54) | def test_matrix_not_loaded_without_creds(self, monkeypatch): method test_matrix_encryption_flag (line 65) | def test_matrix_encryption_flag(self, monkeypatch): method test_matrix_encryption_default_off (line 77) | def test_matrix_encryption_default_off(self, monkeypatch): method test_matrix_home_room (line 89) | def test_matrix_home_room(self, monkeypatch): method test_matrix_user_id_stored_in_extra (line 104) | def test_matrix_user_id_stored_in_extra(self, monkeypatch): function _make_adapter (line 121) | def _make_adapter(): class TestMatrixMxcToHttp (line 140) | class TestMatrixMxcToHttp: method setup_method (line 141) | def setup_method(self): method test_basic_mxc_conversion (line 144) | def test_basic_mxc_conversion(self): method test_mxc_with_different_server (line 150) | def test_mxc_with_different_server(self): method test_non_mxc_url_passthrough (line 157) | def test_non_mxc_url_passthrough(self): method test_mxc_uses_client_v1_endpoint (line 162) | def test_mxc_uses_client_v1_endpoint(self): class TestMatrixDmDetection (line 174) | class TestMatrixDmDetection: method setup_method (line 175) | def setup_method(self): method test_room_in_m_direct_is_dm (line 178) | def test_room_in_m_direct_is_dm(self): method test_unknown_room_not_in_cache (line 189) | def test_unknown_room_not_in_cache(self): method test_refresh_dm_cache_with_m_direct (line 195) | async def test_refresh_dm_cache_with_m_direct(self): class TestMatrixReplyFallbackStripping (line 219) | class TestMatrixReplyFallbackStripping: method setup_method (line 222) | def setup_method(self): method _strip_fallback (line 229) | def _strip_fallback(self, body: str, has_reply: bool = True) -> str: method test_simple_reply_fallback (line 248) | def test_simple_reply_fallback(self): method test_multiline_reply_fallback (line 253) | def test_multiline_reply_fallback(self): method test_no_reply_fallback_preserved (line 258) | def test_no_reply_fallback_preserved(self): method test_quote_without_reply_preserved (line 263) | def test_quote_without_reply_preserved(self): method test_empty_fallback_separator (line 269) | def test_empty_fallback_separator(self): method test_multiline_response_after_fallback (line 275) | def test_multiline_response_after_fallback(self): class TestMatrixThreadDetection (line 285) | class TestMatrixThreadDetection: method test_thread_id_from_m_relates_to (line 286) | def test_thread_id_from_m_relates_to(self): method test_no_thread_for_reply (line 300) | def test_no_thread_for_reply(self): method test_no_thread_for_edit (line 310) | def test_no_thread_for_edit(self): method test_empty_relates_to (line 321) | def test_empty_relates_to(self): class TestMatrixFormatMessage (line 334) | class TestMatrixFormatMessage: method setup_method (line 335) | def setup_method(self): method test_image_markdown_stripped (line 338) | def test_image_markdown_stripped(self): method test_regular_markdown_preserved (line 343) | def test_regular_markdown_preserved(self): method test_plain_text_unchanged (line 348) | def test_plain_text_unchanged(self): method test_multiple_images_stripped (line 352) | def test_multiple_images_stripped(self): class TestMatrixMarkdownToHtml (line 364) | class TestMatrixMarkdownToHtml: method setup_method (line 365) | def setup_method(self): method test_bold_conversion (line 368) | def test_bold_conversion(self): method test_italic_conversion (line 374) | def test_italic_conversion(self): method test_inline_code (line 379) | def test_inline_code(self): method test_plain_text_returns_html (line 384) | def test_plain_text_returns_html(self): class TestMatrixDisplayName (line 394) | class TestMatrixDisplayName: method setup_method (line 395) | def setup_method(self): method test_get_display_name_from_room_users (line 398) | def test_get_display_name_from_room_users(self): method test_get_display_name_fallback_to_localpart (line 408) | def test_get_display_name_fallback_to_localpart(self): method test_get_display_name_no_room (line 416) | def test_get_display_name_no_room(self): class TestMatrixRequirements (line 426) | class TestMatrixRequirements: method test_check_requirements_with_token (line 427) | def test_check_requirements_with_token(self, monkeypatch): method test_check_requirements_without_creds (line 437) | def test_check_requirements_without_creds(self, monkeypatch): method test_check_requirements_without_homeserver (line 444) | def test_check_requirements_without_homeserver(self, monkeypatch): FILE: tests/gateway/test_mattermost.py class TestMattermostPlatformEnum (line 14) | class TestMattermostPlatformEnum: method test_mattermost_enum_exists (line 15) | def test_mattermost_enum_exists(self): method test_mattermost_in_platform_list (line 18) | def test_mattermost_in_platform_list(self): class TestMattermostConfigLoading (line 23) | class TestMattermostConfigLoading: method test_apply_env_overrides_mattermost (line 24) | def test_apply_env_overrides_mattermost(self, monkeypatch): method test_mattermost_not_loaded_without_token (line 38) | def test_mattermost_not_loaded_without_token(self, monkeypatch): method test_connected_platforms_includes_mattermost (line 48) | def test_connected_platforms_includes_mattermost(self, monkeypatch): method test_mattermost_home_channel (line 59) | def test_mattermost_home_channel(self, monkeypatch): method test_mattermost_url_warning_without_url (line 74) | def test_mattermost_url_warning_without_url(self, monkeypatch): function _make_adapter (line 91) | def _make_adapter(): class TestMattermostFormatMessage (line 103) | class TestMattermostFormatMessage: method setup_method (line 104) | def setup_method(self): method test_image_markdown_to_url (line 107) | def test_image_markdown_to_url(self): method test_image_markdown_strips_alt_text (line 112) | def test_image_markdown_strips_alt_text(self): method test_regular_markdown_preserved (line 117) | def test_regular_markdown_preserved(self): method test_regular_links_preserved (line 122) | def test_regular_links_preserved(self): method test_plain_text_unchanged (line 127) | def test_plain_text_unchanged(self): method test_multiple_images (line 131) | def test_multiple_images(self): class TestMattermostTruncateMessage (line 139) | class TestMattermostTruncateMessage: method setup_method (line 140) | def setup_method(self): method test_short_message_single_chunk (line 143) | def test_short_message_single_chunk(self): method test_long_message_splits (line 149) | def test_long_message_splits(self): method test_custom_max_length (line 156) | def test_custom_max_length(self): method test_exactly_at_limit (line 161) | def test_exactly_at_limit(self): class TestMattermostSend (line 171) | class TestMattermostSend: method setup_method (line 172) | def setup_method(self): method test_send_calls_api_post (line 177) | async def test_send_calls_api_post(self): method test_send_empty_content_succeeds (line 202) | async def test_send_empty_content_succeeds(self): method test_send_with_thread_reply (line 208) | async def test_send_with_thread_reply(self): method test_send_without_thread_no_root_id (line 228) | async def test_send_without_thread_no_root_id(self): method test_send_api_failure (line 248) | async def test_send_api_failure(self): class TestMattermostWebSocketParsing (line 268) | class TestMattermostWebSocketParsing: method setup_method (line 269) | def setup_method(self): method test_parse_posted_event (line 276) | async def test_parse_posted_event(self): method test_ignore_own_messages (line 300) | async def test_ignore_own_messages(self): method test_ignore_non_posted_events (line 320) | async def test_ignore_non_posted_events(self): method test_ignore_system_posts (line 331) | async def test_ignore_system_posts(self): method test_channel_type_mapping (line 352) | async def test_channel_type_mapping(self): method test_thread_id_from_root_id (line 375) | async def test_thread_id_from_root_id(self): method test_invalid_post_json_ignored (line 399) | async def test_invalid_post_json_ignored(self): class TestMattermostFileUpload (line 417) | class TestMattermostFileUpload: method setup_method (line 418) | def setup_method(self): method test_send_image_downloads_and_uploads (line 423) | async def test_send_image_downloads_and_uploads(self): class TestMattermostDedup (line 476) | class TestMattermostDedup: method setup_method (line 477) | def setup_method(self): method test_duplicate_post_ignored (line 484) | async def test_duplicate_post_ignored(self): method test_different_post_ids_both_processed (line 510) | async def test_different_post_ids_both_processed(self): method test_prune_seen_clears_expired (line 531) | def test_prune_seen_clears_expired(self): method test_seen_cache_tracks_post_ids (line 547) | def test_seen_cache_tracks_post_ids(self): class TestMattermostRequirements (line 557) | class TestMattermostRequirements: method test_check_requirements_with_token_and_url (line 558) | def test_check_requirements_with_token_and_url(self, monkeypatch): method test_check_requirements_without_token (line 564) | def test_check_requirements_without_token(self, monkeypatch): method test_check_requirements_without_url (line 570) | def test_check_requirements_without_url(self, monkeypatch): FILE: tests/gateway/test_media_extraction.py function extract_media_tags_fixed (line 14) | def extract_media_tags_fixed(result_messages, history_len): function extract_media_tags_broken (line 46) | def extract_media_tags_broken(result_messages): class TestMediaExtraction (line 68) | class TestMediaExtraction: method test_media_tags_not_extracted_from_history (line 71) | def test_media_tags_not_extracted_from_history(self): method test_media_tags_extracted_from_current_turn (line 100) | def test_media_tags_extracted_from_current_turn(self): method test_multiple_tts_calls_in_history_not_accumulated (line 125) | def test_multiple_tts_calls_in_history_not_accumulated(self): method test_deduplication_within_current_turn (line 157) | def test_deduplication_within_current_turn(self): FILE: tests/gateway/test_mirror.py function _setup_sessions (line 15) | def _setup_sessions(tmp_path, sessions_data): class TestFindSessionId (line 24) | class TestFindSessionId: method test_finds_matching_session (line 25) | def test_finds_matching_session(self, tmp_path): method test_returns_most_recent (line 40) | def test_returns_most_recent(self, tmp_path): method test_thread_id_disambiguates_same_chat (line 60) | def test_thread_id_disambiguates_same_chat(self, tmp_path): method test_no_match_returns_none (line 80) | def test_no_match_returns_none(self, tmp_path): method test_missing_sessions_file (line 94) | def test_missing_sessions_file(self, tmp_path): method test_platform_case_insensitive (line 100) | def test_platform_case_insensitive(self, tmp_path): class TestAppendToJsonl (line 115) | class TestAppendToJsonl: method test_appends_message (line 116) | def test_appends_message(self, tmp_path): method test_appends_multiple_messages (line 130) | def test_appends_multiple_messages(self, tmp_path): class TestMirrorToSession (line 143) | class TestMirrorToSession: method test_successful_mirror (line 144) | def test_successful_mirror(self, tmp_path): method test_successful_mirror_uses_thread_id (line 169) | def test_successful_mirror_uses_thread_id(self, tmp_path): method test_no_matching_session (line 192) | def test_no_matching_session(self, tmp_path): method test_error_returns_false (line 201) | def test_error_returns_false(self, tmp_path): class TestAppendToSqlite (line 208) | class TestAppendToSqlite: method test_connection_is_closed_after_use (line 209) | def test_connection_is_closed_after_use(self, tmp_path): method test_connection_closed_even_on_error (line 220) | def test_connection_closed_even_on_error(self, tmp_path): FILE: tests/gateway/test_pairing.py function _make_store (line 22) | def _make_store(tmp_path): class TestSecureWrite (line 33) | class TestSecureWrite: method test_creates_parent_dirs (line 34) | def test_creates_parent_dirs(self, tmp_path): method test_sets_file_permissions (line 40) | def test_sets_file_permissions(self, tmp_path): class TestCodeGeneration (line 52) | class TestCodeGeneration: method test_code_format (line 53) | def test_code_format(self, tmp_path): method test_code_uniqueness (line 61) | def test_code_uniqueness(self, tmp_path): method test_stores_pending_entry (line 72) | def test_stores_pending_entry(self, tmp_path): class TestRateLimiting (line 88) | class TestRateLimiting: method test_same_user_rate_limited (line 89) | def test_same_user_rate_limited(self, tmp_path): method test_different_users_not_rate_limited (line 97) | def test_different_users_not_rate_limited(self, tmp_path): method test_rate_limit_expires (line 105) | def test_rate_limit_expires(self, tmp_path): class TestMaxPending (line 126) | class TestMaxPending: method test_max_pending_per_platform (line 127) | def test_max_pending_per_platform(self, tmp_path): method test_different_platforms_independent (line 140) | def test_different_platforms_independent(self, tmp_path): class TestApprovalFlow (line 155) | class TestApprovalFlow: method test_approve_valid_code (line 156) | def test_approve_valid_code(self, tmp_path): method test_approved_user_is_approved (line 168) | def test_approved_user_is_approved(self, tmp_path): method test_unapproved_user_not_approved (line 175) | def test_unapproved_user_not_approved(self, tmp_path): method test_approve_removes_from_pending (line 180) | def test_approve_removes_from_pending(self, tmp_path): method test_approve_case_insensitive (line 188) | def test_approve_case_insensitive(self, tmp_path): method test_approve_strips_whitespace (line 197) | def test_approve_strips_whitespace(self, tmp_path): method test_invalid_code_returns_none (line 206) | def test_invalid_code_returns_none(self, tmp_path): class TestLockout (line 218) | class TestLockout: method test_lockout_after_max_failures (line 219) | def test_lockout_after_max_failures(self, tmp_path): method test_lockout_blocks_code_generation (line 232) | def test_lockout_blocks_code_generation(self, tmp_path): method test_lockout_expires (line 241) | def test_lockout_expires(self, tmp_path): class TestCodeExpiry (line 261) | class TestCodeExpiry: method test_expired_codes_cleaned_up (line 262) | def test_expired_codes_cleaned_up(self, tmp_path): method test_expired_code_cannot_be_approved (line 276) | def test_expired_code_cannot_be_approved(self, tmp_path): class TestRevoke (line 295) | class TestRevoke: method test_revoke_approved_user (line 296) | def test_revoke_approved_user(self, tmp_path): method test_revoke_nonexistent_returns_false (line 308) | def test_revoke_nonexistent_returns_false(self, tmp_path): class TestListAndClear (line 319) | class TestListAndClear: method test_list_approved (line 320) | def test_list_approved(self, tmp_path): method test_list_approved_all_platforms (line 330) | def test_list_approved_all_platforms(self, tmp_path): method test_clear_pending (line 340) | def test_clear_pending(self, tmp_path): method test_clear_pending_all_platforms (line 350) | def test_clear_pending_all_platforms(self, tmp_path): FILE: tests/gateway/test_pii_redaction.py class TestHashHelpers (line 19) | class TestHashHelpers: method test_hash_id_deterministic (line 20) | def test_hash_id_deterministic(self): method test_hash_id_12_hex_chars (line 23) | def test_hash_id_12_hex_chars(self): method test_hash_sender_id_prefix (line 28) | def test_hash_sender_id_prefix(self): method test_hash_chat_id_preserves_prefix (line 32) | def test_hash_chat_id_preserves_prefix(self): method test_hash_chat_id_no_prefix (line 37) | def test_hash_chat_id_no_prefix(self): method test_looks_like_phone (line 42) | def test_looks_like_phone(self): function _make_context (line 55) | def _make_context( class TestBuildSessionContextPromptRedaction (line 76) | class TestBuildSessionContextPromptRedaction: method test_no_redaction_by_default (line 77) | def test_no_redaction_by_default(self): method test_user_id_hashed_when_redact_pii (line 82) | def test_user_id_hashed_when_redact_pii(self): method test_user_name_not_redacted (line 88) | def test_user_name_not_redacted(self): method test_home_channel_id_hashed (line 95) | def test_home_channel_id_hashed(self): method test_home_channel_id_preserved_without_redaction (line 109) | def test_home_channel_id_preserved_without_redaction(self): method test_redaction_is_deterministic (line 121) | def test_redaction_is_deterministic(self): method test_different_ids_produce_different_hashes (line 127) | def test_different_ids_produce_different_hashes(self): method test_discord_ids_not_redacted_even_with_flag (line 134) | def test_discord_ids_not_redacted_even_with_flag(self): method test_whatsapp_ids_redacted (line 140) | def test_whatsapp_ids_redacted(self): method test_signal_ids_redacted (line 146) | def test_signal_ids_redacted(self): method test_slack_ids_not_redacted (line 152) | def test_slack_ids_not_redacted(self): FILE: tests/gateway/test_plan_command.py function _make_runner (line 15) | def _make_runner(): function _make_event (line 60) | def _make_event(text="/plan"): function _make_plan_skill (line 74) | def _make_plan_skill(skills_dir): class TestGatewayPlanCommand (line 91) | class TestGatewayPlanCommand: method test_plan_command_loads_skill_and_runs_agent (line 93) | async def test_plan_command_loads_skill_and_runs_agent(self, monkeypat... method test_plan_command_appears_in_help_output_via_skill_listing (line 120) | async def test_plan_command_appears_in_help_output_via_skill_listing(s... FILE: tests/gateway/test_platform_base.py class TestSecretCaptureGuidance (line 14) | class TestSecretCaptureGuidance: method test_gateway_secret_capture_message_points_to_local_setup (line 15) | def test_gateway_secret_capture_message_points_to_local_setup(self): class TestMessageEventIsCommand (line 26) | class TestMessageEventIsCommand: method test_slash_command (line 27) | def test_slash_command(self): method test_regular_text (line 31) | def test_regular_text(self): method test_empty_text (line 35) | def test_empty_text(self): method test_slash_only (line 39) | def test_slash_only(self): class TestMessageEventGetCommand (line 44) | class TestMessageEventGetCommand: method test_simple_command (line 45) | def test_simple_command(self): method test_command_with_args (line 49) | def test_command_with_args(self): method test_not_a_command (line 53) | def test_not_a_command(self): method test_command_is_lowercased (line 57) | def test_command_is_lowercased(self): method test_slash_only_returns_empty (line 61) | def test_slash_only_returns_empty(self): class TestMessageEventGetCommandArgs (line 66) | class TestMessageEventGetCommandArgs: method test_command_with_args (line 67) | def test_command_with_args(self): method test_command_without_args (line 71) | def test_command_without_args(self): method test_not_a_command_returns_full_text (line 75) | def test_not_a_command_returns_full_text(self): class TestExtractImages (line 85) | class TestExtractImages: method test_no_images (line 86) | def test_no_images(self): method test_markdown_image_with_image_ext (line 91) | def test_markdown_image_with_image_ext(self): method test_markdown_image_jpg (line 99) | def test_markdown_image_jpg(self): method test_markdown_image_jpeg (line 106) | def test_markdown_image_jpeg(self): method test_markdown_image_gif (line 113) | def test_markdown_image_gif(self): method test_markdown_image_webp (line 120) | def test_markdown_image_webp(self): method test_fal_media_cdn (line 127) | def test_fal_media_cdn(self): method test_fal_cdn_url (line 134) | def test_fal_cdn_url(self): method test_replicate_delivery (line 141) | def test_replicate_delivery(self): method test_non_image_ext_not_extracted (line 148) | def test_non_image_ext_not_extracted(self): method test_html_img_tag (line 155) | def test_html_img_tag(self): method test_html_img_self_closing (line 163) | def test_html_img_self_closing(self): method test_html_img_with_closing_tag (line 170) | def test_html_img_with_closing_tag(self): method test_multiple_images (line 177) | def test_multiple_images(self): method test_mixed_markdown_and_html (line 184) | def test_mixed_markdown_and_html(self): method test_cleaned_content_trims_excess_newlines (line 189) | def test_cleaned_content_trims_excess_newlines(self): method test_non_http_url_not_matched (line 194) | def test_non_http_url_not_matched(self): method test_non_image_link_preserved_when_mixed_with_images (line 199) | def test_non_image_link_preserved_when_mixed_with_images(self): class TestExtractMedia (line 218) | class TestExtractMedia: method test_no_media (line 219) | def test_no_media(self): method test_single_media_tag (line 224) | def test_single_media_tag(self): method test_media_with_voice_directive (line 231) | def test_media_with_voice_directive(self): method test_multiple_media_tags (line 238) | def test_multiple_media_tags(self): method test_voice_directive_removed_from_content (line 243) | def test_voice_directive_removed_from_content(self): method test_media_with_text_before (line 250) | def test_media_with_text_before(self): method test_cleaned_content_trims_excess_newlines (line 256) | def test_cleaned_content_trims_excess_newlines(self): method test_media_tag_allows_optional_whitespace_after_colon (line 261) | def test_media_tag_allows_optional_whitespace_after_colon(self): method test_media_tag_strips_wrapping_quotes_and_backticks (line 267) | def test_media_tag_strips_wrapping_quotes_and_backticks(self): method test_media_tag_supports_quoted_paths_with_spaces (line 277) | def test_media_tag_supports_quoted_paths_with_spaces(self): class TestTruncateMessage (line 290) | class TestTruncateMessage: method _adapter (line 291) | def _adapter(self): method test_short_message_single_chunk (line 312) | def test_short_message_single_chunk(self): method test_exact_length_single_chunk (line 317) | def test_exact_length_single_chunk(self): method test_long_message_splits (line 323) | def test_long_message_splits(self): method test_chunks_have_indicators (line 334) | def test_chunks_have_indicators(self): method test_code_block_first_chunk_closed (line 341) | def test_code_block_first_chunk_closed(self): method test_code_block_language_tag_carried (line 350) | def test_code_block_language_tag_carried(self): method test_continuation_chunks_have_balanced_fences (line 361) | def test_continuation_chunks_have_balanced_fences(self): method test_each_chunk_under_max_length (line 373) | def test_each_chunk_under_max_length(self): class TestGetHumanDelay (line 389) | class TestGetHumanDelay: method test_off_mode (line 390) | def test_off_mode(self): method test_default_is_off (line 394) | def test_default_is_off(self): method test_natural_mode_range (line 399) | def test_natural_mode_range(self): method test_custom_mode_uses_env_vars (line 404) | def test_custom_mode_uses_env_vars(self): FILE: tests/gateway/test_reasoning_command.py function _make_event (line 18) | def _make_event(text="/reasoning", platform=Platform.TELEGRAM, user_id="... function _make_runner (line 29) | def _make_runner(): class _CapturingAgent (line 48) | class _CapturingAgent: method __init__ (line 53) | def __init__(self, *args, **kwargs): method run_conversation (line 57) | def run_conversation(self, user_message: str, conversation_history=Non... class TestReasoningCommand (line 65) | class TestReasoningCommand: method test_reasoning_in_help_output (line 67) | async def test_reasoning_in_help_output(self): method test_reasoning_is_known_command (line 75) | def test_reasoning_is_known_command(self): method test_reasoning_command_reloads_current_state_from_config (line 80) | async def test_reasoning_command_reloads_current_state_from_config(sel... method test_handle_reasoning_command_updates_config_and_cache (line 104) | async def test_handle_reasoning_command_updates_config_and_cache(self,... method test_run_agent_reloads_reasoning_config_per_message (line 123) | def test_run_agent_reloads_reasoning_config_per_message(self, tmp_path... method test_run_agent_prefers_config_over_stale_reasoning_env (line 173) | def test_run_agent_prefers_config_over_stale_reasoning_env(self, tmp_p... FILE: tests/gateway/test_resume_command.py function _make_event (line 16) | def _make_event(text="/resume", platform=Platform.TELEGRAM, function _session_key_for_event (line 28) | def _session_key_for_event(event): function _make_runner (line 33) | def _make_runner(session_db=None, current_session_id="current_session_001", class TestHandleResumeCommand (line 67) | class TestHandleResumeCommand: method test_no_session_db (line 71) | async def test_no_session_db(self): method test_list_named_sessions_when_no_arg (line 79) | async def test_list_named_sessions_when_no_arg(self, tmp_path): method test_list_shows_usage_when_no_titled (line 97) | async def test_list_shows_usage_when_no_titled(self, tmp_path): method test_resume_by_name (line 111) | async def test_resume_by_name(self, tmp_path): method test_resume_nonexistent_name (line 133) | async def test_resume_nonexistent_name(self, tmp_path): method test_resume_already_on_session (line 146) | async def test_resume_already_on_session(self, tmp_path): method test_resume_auto_lineage (line 161) | async def test_resume_auto_lineage(self, tmp_path): method test_resume_clears_running_agent (line 183) | async def test_resume_clears_running_agent(self, tmp_path): method test_resume_flushes_memories_with_gateway_session_key (line 204) | async def test_resume_flushes_memories_with_gateway_session_key(self, ... FILE: tests/gateway/test_retry_replacement.py function test_gateway_retry_replaces_last_user_turn_in_transcript (line 14) | async def test_gateway_retry_replaces_last_user_turn_in_transcript(tmp_p... function test_gateway_retry_replays_original_text_not_retry_command (line 68) | async def test_gateway_retry_replays_original_text_not_retry_command(tmp... FILE: tests/gateway/test_retry_response.py function gateway (line 14) | def gateway(tmp_path): function test_retry_returns_response_not_none (line 25) | async def test_retry_returns_response_not_none(gateway): function test_retry_no_previous_message (line 48) | async def test_retry_no_previous_message(gateway): FILE: tests/gateway/test_run_progress_topics.py class ProgressCaptureAdapter (line 16) | class ProgressCaptureAdapter(BasePlatformAdapter): method __init__ (line 17) | def __init__(self): method connect (line 23) | async def connect(self) -> bool: method disconnect (line 26) | async def disconnect(self) -> None: method send (line 29) | async def send(self, chat_id, content, reply_to=None, metadata=None) -... method edit_message (line 40) | async def edit_message(self, chat_id, message_id, content) -> SendResult: method send_typing (line 50) | async def send_typing(self, chat_id, metadata=None) -> None: method get_chat_info (line 53) | async def get_chat_info(self, chat_id: str): class FakeAgent (line 57) | class FakeAgent: method __init__ (line 58) | def __init__(self, **kwargs): method run_conversation (line 62) | def run_conversation(self, message, conversation_history=None, task_id... function _make_runner (line 74) | def _make_runner(adapter): function test_run_agent_progress_stays_in_originating_topic (line 93) | async def test_run_agent_progress_stays_in_originating_topic(monkeypatch... FILE: tests/gateway/test_runner_fatal_adapter.py class _FatalAdapter (line 8) | class _FatalAdapter(BasePlatformAdapter): method __init__ (line 9) | def __init__(self): method connect (line 12) | async def connect(self) -> bool: method disconnect (line 20) | async def disconnect(self) -> None: method send (line 23) | async def send(self, chat_id, content, reply_to=None, metadata=None): method get_chat_info (line 26) | async def get_chat_info(self, chat_id): function test_runner_requests_clean_exit_for_nonretryable_startup_conflict (line 31) | async def test_runner_requests_clean_exit_for_nonretryable_startup_confl... FILE: tests/gateway/test_runner_startup_failures.py class _RetryableFailureAdapter (line 9) | class _RetryableFailureAdapter(BasePlatformAdapter): method __init__ (line 10) | def __init__(self): method connect (line 13) | async def connect(self) -> bool: method disconnect (line 21) | async def disconnect(self) -> None: method send (line 24) | async def send(self, chat_id, content, reply_to=None, metadata=None): method get_chat_info (line 27) | async def get_chat_info(self, chat_id): class _DisabledAdapter (line 31) | class _DisabledAdapter(BasePlatformAdapter): method __init__ (line 32) | def __init__(self): method connect (line 35) | async def connect(self) -> bool: method disconnect (line 38) | async def disconnect(self) -> None: method send (line 41) | async def send(self, chat_id, content, reply_to=None, metadata=None): method get_chat_info (line 44) | async def get_chat_info(self, chat_id): function test_runner_returns_failure_for_retryable_startup_errors (line 49) | async def test_runner_returns_failure_for_retryable_startup_errors(monke... function test_runner_allows_cron_only_mode_when_no_platforms_are_enabled (line 73) | async def test_runner_allows_cron_only_mode_when_no_platforms_are_enable... FILE: tests/gateway/test_send_image_file.py function _run (line 20) | def _run(coro): class TestExtractMediaImages (line 30) | class TestExtractMediaImages: method test_png_image_extracted (line 33) | def test_png_image_extracted(self): method test_jpg_image_extracted (line 41) | def test_jpg_image_extracted(self): method test_webp_image_extracted (line 47) | def test_webp_image_extracted(self): method test_mixed_audio_and_image (line 52) | def test_mixed_audio_and_image(self): function _ensure_telegram_mock (line 66) | def _ensure_telegram_mock(): class TestTelegramSendImageFile (line 88) | class TestTelegramSendImageFile: method adapter (line 90) | def adapter(self): method test_sends_local_image_as_photo (line 96) | def test_sends_local_image_as_photo(self, adapter, tmp_path): method test_returns_error_when_file_missing (line 116) | def test_returns_error_when_file_missing(self, adapter): method test_returns_error_when_not_connected (line 124) | def test_returns_error_when_not_connected(self, adapter): method test_caption_truncated_to_1024 (line 133) | def test_caption_truncated_to_1024(self, adapter, tmp_path): function _ensure_discord_mock (line 156) | def _ensure_discord_mock(): class TestDiscordSendImageFile (line 176) | class TestDiscordSendImageFile: method adapter (line 178) | def adapter(self): method test_sends_local_image_as_attachment (line 184) | def test_sends_local_image_as_attachment(self, adapter, tmp_path): method test_send_document_uploads_file_attachment (line 202) | def test_send_document_uploads_file_attachment(self, adapter, tmp_path): method test_send_video_uploads_file_attachment (line 228) | def test_send_video_uploads_file_attachment(self, adapter, tmp_path): method test_returns_error_when_file_missing (line 253) | def test_returns_error_when_file_missing(self, adapter): method test_returns_error_when_not_connected (line 260) | def test_returns_error_when_not_connected(self, adapter): method test_handles_missing_channel (line 268) | def test_handles_missing_channel(self, adapter): function _ensure_slack_mock (line 284) | def _ensure_slack_mock(): class TestSlackSendImageFile (line 299) | class TestSlackSendImageFile: method adapter (line 301) | def adapter(self): method test_sends_local_image_via_upload (line 307) | def test_sends_local_image_via_upload(self, adapter, tmp_path): method test_returns_error_when_file_missing (line 326) | def test_returns_error_when_file_missing(self, adapter): method test_returns_error_when_not_connected (line 333) | def test_returns_error_when_not_connected(self, adapter): class TestScreenshotCleanup (line 347) | class TestScreenshotCleanup: method test_cleanup_removes_old_screenshots (line 348) | def test_cleanup_removes_old_screenshots(self, tmp_path): method test_cleanup_is_throttled_per_directory (line 370) | def test_cleanup_is_throttled_per_directory(self, tmp_path): method test_cleanup_ignores_non_screenshot_files (line 390) | def test_cleanup_ignores_non_screenshot_files(self, tmp_path): method test_cleanup_handles_empty_dir (line 406) | def test_cleanup_handles_empty_dir(self, tmp_path): method test_cleanup_handles_nonexistent_dir (line 412) | def test_cleanup_handles_nonexistent_dir(self): FILE: tests/gateway/test_session.py class TestSessionSourceRoundtrip (line 17) | class TestSessionSourceRoundtrip: method test_full_roundtrip (line 18) | def test_full_roundtrip(self): method test_full_roundtrip_with_chat_topic (line 39) | def test_full_roundtrip_with_chat_topic(self): method test_minimal_roundtrip (line 57) | def test_minimal_roundtrip(self): method test_chat_id_coerced_to_string (line 65) | def test_chat_id_coerced_to_string(self): method test_missing_optional_fields (line 74) | def test_missing_optional_fields(self): method test_invalid_platform_raises (line 86) | def test_invalid_platform_raises(self): class TestSessionSourceDescription (line 91) | class TestSessionSourceDescription: method test_local_cli (line 92) | def test_local_cli(self): method test_dm_with_username (line 96) | def test_dm_with_username(self): method test_dm_without_username_falls_back_to_user_id (line 104) | def test_dm_without_username_falls_back_to_user_id(self): method test_group_shows_chat_name (line 111) | def test_group_shows_chat_name(self): method test_channel_type (line 119) | def test_channel_type(self): method test_thread_id_appended (line 127) | def test_thread_id_appended(self): method test_unknown_chat_type_uses_name (line 136) | def test_unknown_chat_type_uses_name(self): class TestLocalCliFactory (line 144) | class TestLocalCliFactory: method test_local_cli_defaults (line 145) | def test_local_cli_defaults(self): class TestBuildSessionContextPrompt (line 153) | class TestBuildSessionContextPrompt: method test_telegram_prompt_contains_platform_and_chat (line 154) | def test_telegram_prompt_contains_platform_and_chat(self): method test_discord_prompt (line 180) | def test_discord_prompt(self): method test_slack_prompt_includes_platform_notes (line 202) | def test_slack_prompt_includes_platform_notes(self): method test_discord_prompt_with_channel_topic (line 222) | def test_discord_prompt_with_channel_topic(self): method test_prompt_omits_channel_topic_when_none (line 246) | def test_prompt_omits_channel_topic_when_none(self): method test_local_prompt_mentions_machine (line 268) | def test_local_prompt_mentions_machine(self): method test_whatsapp_prompt (line 277) | def test_whatsapp_prompt(self): class TestSessionStoreRewriteTranscript (line 295) | class TestSessionStoreRewriteTranscript: method store (line 299) | def store(self, tmp_path): method test_rewrite_replaces_jsonl (line 307) | def test_rewrite_replaces_jsonl(self, store, tmp_path): method test_rewrite_with_empty_list (line 329) | def test_rewrite_with_empty_list(self, store): class TestLoadTranscriptCorruptLines (line 339) | class TestLoadTranscriptCorruptLines: method store (line 344) | def store(self, tmp_path): method test_corrupt_line_skipped (line 352) | def test_corrupt_line_skipped(self, store, tmp_path): method test_all_lines_corrupt_returns_empty (line 367) | def test_all_lines_corrupt_returns_empty(self, store, tmp_path): method test_valid_transcript_unaffected (line 378) | def test_valid_transcript_unaffected(self, store, tmp_path): class TestWhatsAppDMSessionKeyConsistency (line 389) | class TestWhatsAppDMSessionKeyConsistency: method store (line 394) | def store(self, tmp_path): method test_whatsapp_dm_includes_chat_id (line 402) | def test_whatsapp_dm_includes_chat_id(self): method test_store_delegates_to_build_session_key (line 412) | def test_store_delegates_to_build_session_key(self, store): method test_store_creates_distinct_group_sessions_per_user (line 422) | def test_store_creates_distinct_group_sessions_per_user(self, store): method test_store_shares_group_sessions_when_disabled_in_config (line 445) | def test_store_shares_group_sessions_when_disabled_in_config(self, sto... method test_telegram_dm_includes_chat_id (line 470) | def test_telegram_dm_includes_chat_id(self): method test_distinct_dm_chat_ids_get_distinct_session_keys (line 480) | def test_distinct_dm_chat_ids_get_distinct_session_keys(self): method test_discord_group_includes_chat_id (line 489) | def test_discord_group_includes_chat_id(self): method test_group_sessions_are_isolated_per_user_when_user_id_present (line 499) | def test_group_sessions_are_isolated_per_user_when_user_id_present(self): method test_group_sessions_can_be_shared_when_isolation_disabled (line 517) | def test_group_sessions_can_be_shared_when_isolation_disabled(self): method test_group_thread_includes_thread_id (line 534) | def test_group_thread_includes_thread_id(self): method test_group_thread_sessions_are_isolated_per_user (line 545) | def test_group_thread_sessions_are_isolated_per_user(self): class TestSessionStoreEntriesAttribute (line 557) | class TestSessionStoreEntriesAttribute: method test_entries_attribute_exists (line 560) | def test_entries_attribute_exists(self): class TestHasAnySessions (line 569) | class TestHasAnySessions: method store_with_mock_db (line 573) | def store_with_mock_db(self, tmp_path): method test_uses_database_count_when_available (line 583) | def test_uses_database_count_when_available(self, store_with_mock_db): method test_first_session_ever_returns_false (line 594) | def test_first_session_ever_returns_false(self, store_with_mock_db): method test_fallback_without_database (line 603) | def test_fallback_without_database(self, tmp_path): class TestLastPromptTokens (line 619) | class TestLastPromptTokens: method test_session_entry_default (line 622) | def test_session_entry_default(self): method test_session_entry_roundtrip (line 634) | def test_session_entry_roundtrip(self): method test_session_entry_from_old_data (line 650) | def test_session_entry_from_old_data(self): method test_update_session_sets_last_prompt_tokens (line 666) | def test_update_session_sets_last_prompt_tokens(self, tmp_path): method test_update_session_none_does_not_change (line 688) | def test_update_session_none_does_not_change(self, tmp_path): method test_update_session_zero_resets (line 711) | def test_update_session_zero_resets(self, tmp_path): method test_update_session_passes_model_to_db (line 734) | def test_update_session_passes_model_to_db(self, tmp_path): FILE: tests/gateway/test_session_env.py function test_set_session_env_includes_thread_id (line 8) | def test_set_session_env_includes_thread_id(monkeypatch): function test_clear_session_env_removes_thread_id (line 32) | def test_clear_session_env_removes_thread_id(monkeypatch): FILE: tests/gateway/test_session_hygiene.py function _make_history (line 30) | def _make_history(n_messages: int, content_size: int = 100) -> list: function _make_large_history_tokens (line 40) | def _make_large_history_tokens(target_tokens: int) -> list: class HygieneCaptureAdapter (line 54) | class HygieneCaptureAdapter(BasePlatformAdapter): method __init__ (line 55) | def __init__(self): method connect (line 59) | async def connect(self) -> bool: method disconnect (line 62) | async def disconnect(self) -> None: method send (line 65) | async def send(self, chat_id, content, reply_to=None, metadata=None) -... method get_chat_info (line 76) | async def get_chat_info(self, chat_id: str): class TestSessionHygieneThresholds (line 84) | class TestSessionHygieneThresholds: method test_small_session_below_thresholds (line 91) | def test_small_session_below_thresholds(self): method test_large_token_count_triggers (line 104) | def test_large_token_count_triggers(self): method test_under_threshold_no_trigger (line 117) | def test_under_threshold_no_trigger(self): method test_message_count_alone_does_not_trigger (line 134) | def test_message_count_alone_does_not_trigger(self): method test_threshold_scales_with_model (line 153) | def test_threshold_scales_with_model(self): method test_custom_threshold_percentage (line 173) | def test_custom_threshold_percentage(self): method test_minimum_message_guard (line 189) | def test_minimum_message_guard(self): class TestSessionHygieneWarnThreshold (line 197) | class TestSessionHygieneWarnThreshold: method test_warn_when_still_large (line 200) | def test_warn_when_still_large(self): method test_no_warn_when_under (line 207) | def test_no_warn_when_under(self): class TestTokenEstimation (line 215) | class TestTokenEstimation: method test_empty_history (line 218) | def test_empty_history(self): method test_proportional_to_content (line 221) | def test_proportional_to_content(self): method test_proportional_to_count (line 226) | def test_proportional_to_count(self): method test_pathological_session_detected (line 231) | def test_pathological_session_detected(self): function test_session_hygiene_messages_stay_in_originating_topic (line 244) | async def test_session_hygiene_messages_stay_in_originating_topic(monkey... FILE: tests/gateway/test_session_race_guard.py class _FakeAdapter (line 22) | class _FakeAdapter: method __init__ (line 25) | def __init__(self): method send (line 28) | async def send(self, chat_id, text, **kwargs): function _make_runner (line 32) | def _make_runner(): function _make_event (line 46) | def _make_event(text="hello", chat_id="12345"): function test_sentinel_placed_before_agent_setup (line 57) | async def test_sentinel_placed_before_agent_setup(): function test_sentinel_cleaned_up_after_handler_returns (line 85) | async def test_sentinel_cleaned_up_after_handler_returns(): function test_sentinel_cleaned_up_on_exception (line 107) | async def test_sentinel_cleaned_up_on_exception(): function test_second_message_during_sentinel_queued_not_duplicate (line 130) | async def test_second_message_during_sentinel_queued_not_duplicate(): function test_command_messages_do_not_leave_sentinel (line 175) | async def test_command_messages_do_not_leave_sentinel(): function test_stop_during_sentinel_returns_message (line 204) | async def test_stop_during_sentinel_returns_message(): function test_shutdown_skips_sentinel (line 242) | async def test_shutdown_skips_sentinel(): FILE: tests/gateway/test_signal.py class TestSignalPlatformEnum (line 13) | class TestSignalPlatformEnum: method test_signal_enum_exists (line 14) | def test_signal_enum_exists(self): method test_signal_in_platform_list (line 17) | def test_signal_in_platform_list(self): class TestSignalConfigLoading (line 22) | class TestSignalConfigLoading: method test_apply_env_overrides_signal (line 23) | def test_apply_env_overrides_signal(self, monkeypatch): method test_signal_not_loaded_without_both_vars (line 37) | def test_signal_not_loaded_without_both_vars(self, monkeypatch): method test_connected_platforms_includes_signal (line 47) | def test_connected_platforms_includes_signal(self, monkeypatch): class TestSignalAdapterInit (line 63) | class TestSignalAdapterInit: method _make_config (line 64) | def _make_config(self, **extra): method test_init_parses_config (line 74) | def test_init_parses_config(self, monkeypatch): method test_init_empty_allowlist (line 84) | def test_init_empty_allowlist(self, monkeypatch): method test_init_strips_trailing_slash (line 92) | def test_init_strips_trailing_slash(self, monkeypatch): method test_self_message_filtering (line 100) | def test_self_message_filtering(self, monkeypatch): class TestSignalHelpers (line 109) | class TestSignalHelpers: method test_redact_phone_long (line 110) | def test_redact_phone_long(self): method test_redact_phone_short (line 114) | def test_redact_phone_short(self): method test_redact_phone_empty (line 118) | def test_redact_phone_empty(self): method test_parse_comma_list (line 122) | def test_parse_comma_list(self): method test_guess_extension_png (line 128) | def test_guess_extension_png(self): method test_guess_extension_jpeg (line 132) | def test_guess_extension_jpeg(self): method test_guess_extension_pdf (line 136) | def test_guess_extension_pdf(self): method test_guess_extension_zip (line 140) | def test_guess_extension_zip(self): method test_guess_extension_mp4 (line 144) | def test_guess_extension_mp4(self): method test_guess_extension_unknown (line 148) | def test_guess_extension_unknown(self): method test_is_image_ext (line 152) | def test_is_image_ext(self): method test_is_audio_ext (line 159) | def test_is_audio_ext(self): method test_check_requirements (line 165) | def test_check_requirements(self, monkeypatch): method test_render_mentions (line 171) | def test_render_mentions(self): method test_render_mentions_no_mentions (line 179) | def test_render_mentions_no_mentions(self): method test_check_requirements_missing (line 185) | def test_check_requirements_missing(self, monkeypatch): class TestSignalSessionSource (line 196) | class TestSignalSessionSource: method test_session_source_alt_fields (line 197) | def test_session_source_alt_fields(self): method test_session_source_roundtrip (line 210) | def test_session_source_roundtrip(self): class TestSignalPhoneRedaction (line 231) | class TestSignalPhoneRedaction: method test_us_number (line 232) | def test_us_number(self): method test_uk_number (line 239) | def test_uk_number(self): method test_multiple_numbers (line 245) | def test_multiple_numbers(self): method test_short_number_not_matched (line 252) | def test_short_number_not_matched(self): class TestSignalAuthorization (line 263) | class TestSignalAuthorization: method test_signal_in_allowlist_maps (line 264) | def test_signal_in_allowlist_maps(self): class TestSignalSendMessage (line 288) | class TestSignalSendMessage: method test_signal_in_platform_map (line 289) | def test_signal_in_platform_map(self): FILE: tests/gateway/test_slack.py function _ensure_slack_mock (line 31) | def _ensure_slack_mock(): function adapter (line 70) | def adapter(): function _redirect_cache (line 84) | def _redirect_cache(tmp_path, monkeypatch): class TestAppMentionHandler (line 95) | class TestAppMentionHandler: method test_app_mention_registered_on_connect (line 98) | def test_app_mention_registered_on_connect(self): class TestSendDocument (line 144) | class TestSendDocument: method test_send_document_success (line 146) | async def test_send_document_success(self, adapter, tmp_path): method test_send_document_custom_name (line 167) | async def test_send_document_custom_name(self, adapter, tmp_path): method test_send_document_missing_file (line 184) | async def test_send_document_missing_file(self, adapter): method test_send_document_not_connected (line 194) | async def test_send_document_not_connected(self, adapter): method test_send_document_api_error_falls_back (line 205) | async def test_send_document_api_error_falls_back(self, adapter, tmp_p... method test_send_document_with_thread (line 223) | async def test_send_document_with_thread(self, adapter, tmp_path): class TestSendVideo (line 244) | class TestSendVideo: method test_send_video_success (line 246) | async def test_send_video_success(self, adapter, tmp_path): method test_send_video_missing_file (line 264) | async def test_send_video_missing_file(self, adapter): method test_send_video_not_connected (line 274) | async def test_send_video_not_connected(self, adapter): method test_send_video_api_error_falls_back (line 285) | async def test_send_video_api_error_falls_back(self, adapter, tmp_path): class TestIncomingDocumentHandling (line 306) | class TestIncomingDocumentHandling: method _make_event (line 307) | def _make_event(self, files=None, text="hello", channel_type="im"): method test_pdf_document_cached (line 319) | async def test_pdf_document_cached(self, adapter): method test_txt_document_injects_content (line 340) | async def test_txt_document_injects_content(self, adapter): method test_md_document_injects_content (line 363) | async def test_md_document_injects_content(self, adapter): method test_large_txt_not_injected (line 381) | async def test_large_txt_not_injected(self, adapter): method test_unsupported_file_type_skipped (line 400) | async def test_unsupported_file_type_skipped(self, adapter): method test_oversized_document_skipped (line 415) | async def test_oversized_document_skipped(self, adapter): method test_document_download_error_handled (line 429) | async def test_document_download_error_handled(self, adapter): method test_image_still_handled (line 445) | async def test_image_still_handled(self, adapter): class TestMessageRouting (line 465) | class TestMessageRouting: method test_dm_processed_without_mention (line 467) | async def test_dm_processed_without_mention(self, adapter): method test_channel_message_requires_mention (line 480) | async def test_channel_message_requires_mention(self, adapter): method test_channel_mention_strips_bot_id (line 493) | async def test_channel_mention_strips_bot_id(self, adapter): method test_bot_messages_ignored (line 508) | async def test_bot_messages_ignored(self, adapter): method test_message_edits_ignored (line 521) | async def test_message_edits_ignored(self, adapter): class TestSendTyping (line 540) | class TestSendTyping: method test_sets_status_in_thread (line 544) | async def test_sets_status_in_thread(self, adapter): method test_noop_without_thread (line 554) | async def test_noop_without_thread(self, adapter): method test_handles_missing_scope_gracefully (line 560) | async def test_handles_missing_scope_gracefully(self, adapter): method test_uses_thread_ts_fallback (line 568) | async def test_uses_thread_ts_fallback(self, adapter): class TestFormatMessage (line 583) | class TestFormatMessage: method test_bold_conversion (line 586) | def test_bold_conversion(self, adapter): method test_italic_asterisk_conversion (line 589) | def test_italic_asterisk_conversion(self, adapter): method test_italic_underscore_preserved (line 592) | def test_italic_underscore_preserved(self, adapter): method test_header_to_bold (line 595) | def test_header_to_bold(self, adapter): method test_header_with_bold_content (line 598) | def test_header_with_bold_content(self, adapter): method test_link_conversion (line 602) | def test_link_conversion(self, adapter): method test_strikethrough (line 606) | def test_strikethrough(self, adapter): method test_code_block_preserved (line 609) | def test_code_block_preserved(self, adapter): method test_inline_code_preserved (line 613) | def test_inline_code_preserved(self, adapter): method test_mixed_content (line 617) | def test_mixed_content(self, adapter): method test_empty_string (line 624) | def test_empty_string(self, adapter): method test_none_passthrough (line 627) | def test_none_passthrough(self, adapter): class TestReactions (line 636) | class TestReactions: method test_add_reaction_calls_api (line 640) | async def test_add_reaction_calls_api(self, adapter): method test_add_reaction_handles_error (line 649) | async def test_add_reaction_handles_error(self, adapter): method test_remove_reaction_calls_api (line 655) | async def test_remove_reaction_calls_api(self, adapter): method test_reactions_in_message_flow (line 661) | async def test_reactions_in_message_flow(self, adapter): class TestUserNameResolution (line 693) | class TestUserNameResolution: method test_resolves_display_name (line 697) | async def test_resolves_display_name(self, adapter): method test_falls_back_to_real_name (line 705) | async def test_falls_back_to_real_name(self, adapter): method test_caches_result (line 713) | async def test_caches_result(self, adapter): method test_handles_api_error (line 723) | async def test_handles_api_error(self, adapter): method test_user_name_in_message_source (line 729) | async def test_user_name_in_message_source(self, adapter): class TestSlashCommands (line 756) | class TestSlashCommands: method test_compact_maps_to_compress (line 760) | async def test_compact_maps_to_compress(self, adapter): method test_resume_command (line 767) | async def test_resume_command(self, adapter): method test_background_command (line 774) | async def test_background_command(self, adapter): method test_usage_command (line 781) | async def test_usage_command(self, adapter): method test_reasoning_command (line 788) | async def test_reasoning_command(self, adapter): class TestMessageSplitting (line 800) | class TestMessageSplitting: method test_long_message_split_into_chunks (line 804) | async def test_long_message_split_into_chunks(self, adapter): method test_short_message_single_send (line 815) | async def test_short_message_single_send(self, adapter): class TestReplyBroadcast (line 829) | class TestReplyBroadcast: method test_broadcast_disabled_by_default (line 833) | async def test_broadcast_disabled_by_default(self, adapter): method test_broadcast_enabled_via_config (line 842) | async def test_broadcast_enabled_via_config(self, adapter): class TestFallbackPreservesThreadContext (line 856) | class TestFallbackPreservesThreadContext: method test_send_image_file_fallback_preserves_thread (line 862) | async def test_send_image_file_fallback_preserves_thread(self, adapter... method test_send_video_fallback_preserves_thread (line 885) | async def test_send_video_fallback_preserves_thread(self, adapter, tmp... method test_send_document_fallback_preserves_thread (line 907) | async def test_send_document_fallback_preserves_thread(self, adapter, ... method test_send_image_file_fallback_includes_caption (line 930) | async def test_send_image_file_fallback_includes_caption(self, adapter... FILE: tests/gateway/test_sms.py class TestSmsConfigLoading (line 17) | class TestSmsConfigLoading: method test_sms_platform_enum_exists (line 20) | def test_sms_platform_enum_exists(self): method test_env_overrides_create_sms_config (line 23) | def test_env_overrides_create_sms_config(self): method test_env_overrides_set_home_channel (line 38) | def test_env_overrides_set_home_channel(self): method test_sms_in_connected_platforms (line 56) | def test_sms_in_connected_platforms(self): class TestSmsFormatAndTruncate (line 71) | class TestSmsFormatAndTruncate: method _make_adapter (line 74) | def _make_adapter(self): method test_strips_bold (line 92) | def test_strips_bold(self): method test_strips_italic (line 96) | def test_strips_italic(self): method test_strips_code_blocks (line 100) | def test_strips_code_blocks(self): method test_strips_inline_code (line 106) | def test_strips_inline_code(self): method test_strips_headers (line 110) | def test_strips_headers(self): method test_strips_links (line 114) | def test_strips_links(self): method test_collapses_newlines (line 118) | def test_collapses_newlines(self): class TestSmsEchoPrevention (line 126) | class TestSmsEchoPrevention: method test_own_number_detection (line 129) | def test_own_number_detection(self): class TestSmsRequirements (line 146) | class TestSmsRequirements: method test_check_sms_requirements_missing_sid (line 147) | def test_check_sms_requirements_missing_sid(self): method test_check_sms_requirements_missing_token (line 154) | def test_check_sms_requirements_missing_token(self): method test_check_sms_requirements_both_set (line 161) | def test_check_sms_requirements_both_set(self): class TestSmsToolset (line 180) | class TestSmsToolset: method test_hermes_sms_toolset_exists (line 181) | def test_hermes_sms_toolset_exists(self): method test_hermes_sms_in_gateway_includes (line 188) | def test_hermes_sms_in_gateway_includes(self): method test_sms_platform_hint_exists (line 195) | def test_sms_platform_hint_exists(self): method test_sms_in_scheduler_platform_map (line 201) | def test_sms_in_scheduler_platform_map(self): method test_sms_in_send_message_platform_map (line 206) | def test_sms_in_send_message_platform_map(self): method test_sms_in_cronjob_deliver_description (line 211) | def test_sms_in_cronjob_deliver_description(self): FILE: tests/gateway/test_ssl_certs.py function _load_ensure_ssl (line 8) | def _load_ensure_ssl(): class TestEnsureSslCerts (line 47) | class TestEnsureSslCerts: method test_respects_existing_env_var (line 48) | def test_respects_existing_env_var(self): method test_sets_from_ssl_default_paths (line 54) | def test_sets_from_ssl_default_paths(self, tmp_path): method test_no_op_when_nothing_found (line 69) | def test_no_op_when_nothing_found(self): FILE: tests/gateway/test_status.py class TestGatewayPidState (line 9) | class TestGatewayPidState: method test_write_pid_file_records_gateway_metadata (line 10) | def test_write_pid_file_records_gateway_metadata(self, tmp_path, monke... method test_get_running_pid_rejects_live_non_gateway_pid (line 21) | def test_get_running_pid_rejects_live_non_gateway_pid(self, tmp_path, ... method test_get_running_pid_accepts_gateway_metadata_when_cmdline_unavailable (line 29) | def test_get_running_pid_accepts_gateway_metadata_when_cmdline_unavail... method test_get_running_pid_accepts_script_style_gateway_cmdline (line 45) | def test_get_running_pid_accepts_script_style_gateway_cmdline(self, tm... class TestGatewayRuntimeStatus (line 66) | class TestGatewayRuntimeStatus: method test_write_runtime_status_overwrites_stale_pid_on_restart (line 67) | def test_write_runtime_status_overwrites_stale_pid_on_restart(self, tm... method test_write_runtime_status_records_platform_failure (line 87) | def test_write_runtime_status_records_platform_failure(self, tmp_path,... class TestScopedLocks (line 107) | class TestScopedLocks: method test_acquire_scoped_lock_rejects_live_other_process (line 108) | def test_acquire_scoped_lock_rejects_live_other_process(self, tmp_path... method test_acquire_scoped_lock_replaces_stale_record (line 126) | def test_acquire_scoped_lock_replaces_stale_record(self, tmp_path, mon... method test_release_scoped_lock_only_removes_current_owner (line 148) | def test_release_scoped_lock_only_removes_current_owner(self, tmp_path... FILE: tests/gateway/test_status_command.py function _make_source (line 14) | def _make_source() -> SessionSource: function _make_event (line 24) | def _make_event(text: str) -> MessageEvent: function _make_runner (line 32) | def _make_runner(session_entry: SessionEntry): function test_status_command_reports_running_agent_without_interrupt (line 69) | async def test_status_command_reports_running_agent_without_interrupt(mo... function test_handle_message_persists_agent_token_counts (line 92) | async def test_handle_message_persists_agent_token_counts(monkeypatch): FILE: tests/gateway/test_sticker_cache.py class TestLoadSaveCache (line 18) | class TestLoadSaveCache: method test_load_missing_file (line 19) | def test_load_missing_file(self, tmp_path): method test_load_corrupt_file (line 23) | def test_load_corrupt_file(self, tmp_path): method test_save_and_load_roundtrip (line 29) | def test_save_and_load_roundtrip(self, tmp_path): method test_save_creates_parent_dirs (line 37) | def test_save_creates_parent_dirs(self, tmp_path): class TestCacheSticker (line 44) | class TestCacheSticker: method test_cache_and_retrieve (line 45) | def test_cache_and_retrieve(self, tmp_path): method test_missing_sticker_returns_none (line 57) | def test_missing_sticker_returns_none(self, tmp_path): method test_overwrite_existing (line 63) | def test_overwrite_existing(self, tmp_path): method test_multiple_stickers (line 72) | def test_multiple_stickers(self, tmp_path): class TestBuildStickerInjection (line 84) | class TestBuildStickerInjection: method test_exact_format_no_context (line 85) | def test_exact_format_no_context(self): method test_exact_format_emoji_only (line 89) | def test_exact_format_emoji_only(self): method test_exact_format_emoji_and_set_name (line 93) | def test_exact_format_emoji_and_set_name(self): method test_set_name_without_emoji_ignored (line 97) | def test_set_name_without_emoji_ignored(self): method test_description_with_quotes (line 103) | def test_description_with_quotes(self): method test_empty_description (line 108) | def test_empty_description(self): class TestBuildAnimatedStickerInjection (line 113) | class TestBuildAnimatedStickerInjection: method test_exact_format_with_emoji (line 114) | def test_exact_format_with_emoji(self): method test_exact_format_without_emoji (line 121) | def test_exact_format_without_emoji(self): method test_empty_emoji_same_as_no_emoji (line 125) | def test_empty_emoji_same_as_no_emoji(self): FILE: tests/gateway/test_stt_config.py function test_gateway_config_stt_disabled_from_dict_nested (line 12) | def test_gateway_config_stt_disabled_from_dict_nested(): function test_load_gateway_config_bridges_stt_enabled_from_config_yaml (line 17) | def test_load_gateway_config_bridges_stt_enabled_from_config_yaml(tmp_pa... function test_enrich_message_with_transcription_skips_when_stt_disabled (line 34) | async def test_enrich_message_with_transcription_skips_when_stt_disabled(): function test_enrich_message_with_transcription_avoids_bogus_no_provider_message_for_backend_key_errors (line 57) | async def test_enrich_message_with_transcription_avoids_bogus_no_provide... FILE: tests/gateway/test_telegram_conflict.py function _ensure_telegram_mock (line 11) | def _ensure_telegram_mock(): function test_connect_rejects_same_host_token_lock (line 33) | async def test_connect_rejects_same_host_token_lock(monkeypatch): function test_polling_conflict_stops_polling_and_notifies_handler (line 50) | async def test_polling_conflict_stops_polling_and_notifies_handler(monke... function test_connect_marks_retryable_fatal_error_for_startup_network_failure (line 104) | async def test_connect_marks_retryable_fatal_error_for_startup_network_f... function test_disconnect_skips_inactive_updater_and_app (line 137) | async def test_disconnect_skips_inactive_updater_and_app(monkeypatch): FILE: tests/gateway/test_telegram_documents.py function _ensure_telegram_mock (line 33) | def _ensure_telegram_mock(): function _make_file_obj (line 62) | def _make_file_obj(data: bytes = b"hello"): function _make_document (line 70) | def _make_document( function _make_message (line 85) | def _make_message(document=None, caption=None, media_group_id=None, phot... function _make_update (line 113) | def _make_update(msg): function adapter (line 125) | def adapter(): function _redirect_cache (line 134) | def _redirect_cache(tmp_path, monkeypatch): class TestDocumentTypeDetection (line 145) | class TestDocumentTypeDetection: method test_document_detected_explicitly (line 147) | async def test_document_detected_explicitly(self, adapter): method test_fallback_is_document (line 156) | async def test_fallback_is_document(self, adapter): function _make_photo (line 170) | def _make_photo(file_obj=None): class TestDocumentDownloadBlock (line 176) | class TestDocumentDownloadBlock: method test_supported_pdf_is_cached (line 178) | async def test_supported_pdf_is_cached(self, adapter): method test_supported_txt_injects_content (line 192) | async def test_supported_txt_injects_content(self, adapter): method test_supported_md_injects_content (line 208) | async def test_supported_md_injects_content(self, adapter): method test_caption_preserved_with_injection (line 223) | async def test_caption_preserved_with_injection(self, adapter): method test_unsupported_type_rejected (line 239) | async def test_unsupported_type_rejected(self, adapter): method test_oversized_file_rejected (line 250) | async def test_oversized_file_rejected(self, adapter): method test_none_file_size_rejected (line 260) | async def test_none_file_size_rejected(self, adapter): method test_missing_filename_uses_mime_lookup (line 271) | async def test_missing_filename_uses_mime_lookup(self, adapter): method test_missing_filename_and_mime_rejected (line 288) | async def test_missing_filename_and_mime_rejected(self, adapter): method test_unicode_decode_error_handled (line 298) | async def test_unicode_decode_error_handled(self, adapter): method test_text_injection_capped (line 318) | async def test_text_injection_capped(self, adapter): method test_download_exception_handled (line 337) | async def test_download_exception_handled(self, adapter): class TestMediaGroups (line 354) | class TestMediaGroups: method test_non_album_photo_burst_is_buffered_and_combined (line 356) | async def test_non_album_photo_burst_is_buffered_and_combined(self, ad... method test_photo_album_is_buffered_and_combined (line 376) | async def test_photo_album_is_buffered_and_combined(self, adapter): method test_disconnect_cancels_pending_media_group_flush (line 396) | async def test_disconnect_cancels_pending_media_group_flush(self, adap... class TestSendDocument (line 418) | class TestSendDocument: method connected_adapter (line 422) | def connected_adapter(self, adapter): method test_send_document_success (line 429) | async def test_send_document_success(self, connected_adapter, tmp_path): method test_send_document_custom_filename (line 454) | async def test_send_document_custom_filename(self, connected_adapter, ... method test_send_document_file_not_found (line 474) | async def test_send_document_file_not_found(self, connected_adapter): method test_send_document_not_connected (line 486) | async def test_send_document_not_connected(self, adapter): method test_send_document_caption_truncated (line 497) | async def test_send_document_caption_truncated(self, connected_adapter... method test_send_document_api_error_falls_back (line 517) | async def test_send_document_api_error_falls_back(self, connected_adap... method test_send_document_reply_to (line 542) | async def test_send_document_reply_to(self, connected_adapter, tmp_path): class TestTelegramPhotoBatching (line 561) | class TestTelegramPhotoBatching: method test_flush_photo_batch_does_not_drop_newer_scheduled_task (line 563) | async def test_flush_photo_batch_does_not_drop_newer_scheduled_task(se... method test_disconnect_cancels_pending_photo_batch_tasks (line 585) | async def test_disconnect_cancels_pending_photo_batch_tasks(self, adap... class TestSendVideo (line 610) | class TestSendVideo: method connected_adapter (line 614) | def connected_adapter(self, adapter): method test_send_video_success (line 620) | async def test_send_video_success(self, connected_adapter, tmp_path): method test_send_video_file_not_found (line 639) | async def test_send_video_file_not_found(self, connected_adapter): method test_send_video_not_connected (line 649) | async def test_send_video_not_connected(self, adapter): FILE: tests/gateway/test_telegram_format.py function _ensure_telegram_mock (line 21) | def _ensure_telegram_mock(): function adapter (line 45) | def adapter(): class TestEscapeMdv2 (line 55) | class TestEscapeMdv2: method test_escapes_all_special_characters (line 56) | def test_escapes_all_special_characters(self): method test_empty_string (line 65) | def test_empty_string(self): method test_no_special_characters (line 68) | def test_no_special_characters(self): method test_backslash_escaped (line 71) | def test_backslash_escaped(self): method test_dot_escaped (line 74) | def test_dot_escaped(self): method test_exclamation_escaped (line 77) | def test_exclamation_escaped(self): method test_mixed_text_and_specials (line 80) | def test_mixed_text_and_specials(self): class TestFormatMessageBasic (line 90) | class TestFormatMessageBasic: method test_empty_string (line 91) | def test_empty_string(self, adapter): method test_none_input (line 94) | def test_none_input(self, adapter): method test_plain_text_specials_escaped (line 98) | def test_plain_text_specials_escaped(self, adapter): method test_plain_text_no_markdown (line 103) | def test_plain_text_no_markdown(self, adapter): class TestFormatMessageCodeBlocks (line 113) | class TestFormatMessageCodeBlocks: method test_fenced_code_block_preserved (line 114) | def test_fenced_code_block_preserved(self, adapter): method test_inline_code_preserved (line 122) | def test_inline_code_preserved(self, adapter): method test_code_block_special_chars_not_escaped (line 130) | def test_code_block_special_chars_not_escaped(self, adapter): method test_inline_code_special_chars_not_escaped (line 136) | def test_inline_code_special_chars_not_escaped(self, adapter): method test_multiple_code_blocks (line 141) | def test_multiple_code_blocks(self, adapter): method test_inline_code_backslashes_escaped (line 149) | def test_inline_code_backslashes_escaped(self, adapter): method test_fenced_code_block_backslashes_escaped (line 155) | def test_fenced_code_block_backslashes_escaped(self, adapter): method test_fenced_code_block_backticks_escaped (line 161) | def test_fenced_code_block_backticks_escaped(self, adapter): method test_inline_code_no_double_escape (line 167) | def test_inline_code_no_double_escape(self, adapter): class TestFormatMessageBoldItalic (line 180) | class TestFormatMessageBoldItalic: method test_bold_converted (line 181) | def test_bold_converted(self, adapter): method test_italic_converted (line 188) | def test_italic_converted(self, adapter): method test_bold_with_special_chars (line 193) | def test_bold_with_special_chars(self, adapter): method test_italic_with_special_chars (line 198) | def test_italic_with_special_chars(self, adapter): method test_bold_and_italic_in_same_line (line 202) | def test_bold_and_italic_in_same_line(self, adapter): class TestFormatMessageHeaders (line 213) | class TestFormatMessageHeaders: method test_h1_converted_to_bold (line 214) | def test_h1_converted_to_bold(self, adapter): method test_h2_converted (line 221) | def test_h2_converted(self, adapter): method test_header_with_inner_bold_stripped (line 225) | def test_header_with_inner_bold_stripped(self, adapter): method test_header_with_special_chars (line 234) | def test_header_with_special_chars(self, adapter): method test_multiline_headers (line 240) | def test_multiline_headers(self, adapter): class TestFormatMessageLinks (line 253) | class TestFormatMessageLinks: method test_markdown_link_converted (line 254) | def test_markdown_link_converted(self, adapter): method test_link_display_text_escaped (line 258) | def test_link_display_text_escaped(self, adapter): method test_link_url_parentheses_escaped (line 263) | def test_link_url_parentheses_escaped(self, adapter): method test_link_with_surrounding_text (line 268) | def test_link_with_surrounding_text(self, adapter): class TestItalicNewlineBug (line 279) | class TestItalicNewlineBug: method test_bullet_list_not_corrupted (line 286) | def test_bullet_list_not_corrupted(self, adapter): method test_asterisk_list_items_preserved (line 297) | def test_asterisk_list_items_preserved(self, adapter): method test_italic_does_not_span_lines (line 308) | def test_italic_does_not_span_lines(self, adapter): method test_single_line_italic_still_works (line 316) | def test_single_line_italic_still_works(self, adapter): class TestFormatMessageStrikethrough (line 328) | class TestFormatMessageStrikethrough: method test_strikethrough_converted (line 329) | def test_strikethrough_converted(self, adapter): method test_strikethrough_with_special_chars (line 334) | def test_strikethrough_with_special_chars(self, adapter): method test_strikethrough_in_code_not_converted (line 338) | def test_strikethrough_in_code_not_converted(self, adapter): method test_strikethrough_with_bold (line 342) | def test_strikethrough_with_bold(self, adapter): class TestFormatMessageSpoiler (line 353) | class TestFormatMessageSpoiler: method test_spoiler_converted (line 354) | def test_spoiler_converted(self, adapter): method test_spoiler_with_special_chars (line 358) | def test_spoiler_with_special_chars(self, adapter): method test_spoiler_in_code_not_converted (line 362) | def test_spoiler_in_code_not_converted(self, adapter): method test_spoiler_pipes_not_escaped (line 366) | def test_spoiler_pipes_not_escaped(self, adapter): class TestFormatMessageBlockquote (line 378) | class TestFormatMessageBlockquote: method test_blockquote_converted (line 379) | def test_blockquote_converted(self, adapter): method test_blockquote_with_special_chars (line 385) | def test_blockquote_with_special_chars(self, adapter): method test_blockquote_multiline (line 390) | def test_blockquote_multiline(self, adapter): method test_blockquote_in_code_not_converted (line 397) | def test_blockquote_in_code_not_converted(self, adapter): method test_nested_blockquote (line 401) | def test_nested_blockquote(self, adapter): method test_gt_in_middle_of_line_still_escaped (line 406) | def test_gt_in_middle_of_line_still_escaped(self, adapter): class TestFormatMessageComplex (line 417) | class TestFormatMessageComplex: method test_code_block_with_bold_outside (line 418) | def test_code_block_with_bold_outside(self, adapter): method test_bold_inside_code_not_converted (line 424) | def test_bold_inside_code_not_converted(self, adapter): method test_link_inside_code_not_converted (line 430) | def test_link_inside_code_not_converted(self, adapter): method test_header_after_code_block (line 435) | def test_header_after_code_block(self, adapter): method test_multiple_bold_segments (line 441) | def test_multiple_bold_segments(self, adapter): method test_special_chars_in_plain_text (line 445) | def test_special_chars_in_plain_text(self, adapter): method test_empty_bold (line 452) | def test_empty_bold(self, adapter): method test_empty_code_block (line 457) | def test_empty_code_block(self, adapter): method test_placeholder_collision (line 461) | def test_placeholder_collision(self, adapter): class TestStripMdv2 (line 484) | class TestStripMdv2: method test_removes_escape_backslashes (line 485) | def test_removes_escape_backslashes(self): method test_removes_bold_markers (line 488) | def test_removes_bold_markers(self): method test_removes_italic_markers (line 491) | def test_removes_italic_markers(self): method test_removes_both_bold_and_italic (line 494) | def test_removes_both_bold_and_italic(self): method test_preserves_snake_case (line 498) | def test_preserves_snake_case(self): method test_preserves_multi_underscore_identifier (line 501) | def test_preserves_multi_underscore_identifier(self): method test_plain_text_unchanged (line 504) | def test_plain_text_unchanged(self): method test_empty_string (line 507) | def test_empty_string(self): method test_removes_strikethrough_markers (line 510) | def test_removes_strikethrough_markers(self): method test_removes_spoiler_markers (line 513) | def test_removes_spoiler_markers(self): function test_send_escapes_chunk_indicator_for_markdownv2 (line 518) | async def test_send_escapes_chunk_indicator_for_markdownv2(adapter): FILE: tests/gateway/test_telegram_photo_interrupts.py class _PendingAdapter (line 12) | class _PendingAdapter: method __init__ (line 13) | def __init__(self): function _make_runner (line 17) | def _make_runner(): function test_handle_message_does_not_priority_interrupt_photo_followup (line 30) | async def test_handle_message_does_not_priority_interrupt_photo_followup(): FILE: tests/gateway/test_telegram_text_batching.py function _make_adapter (line 17) | def _make_adapter(): function _make_event (line 35) | def _make_event(text: str, chat_id: str = "12345") -> MessageEvent: class TestTextBatching (line 43) | class TestTextBatching: method test_single_message_dispatched_after_delay (line 45) | async def test_single_message_dispatched_after_delay(self): method test_split_messages_aggregated (line 62) | async def test_split_messages_aggregated(self): method test_three_way_split_aggregated (line 82) | async def test_three_way_split_aggregated(self): method test_different_chats_not_merged (line 101) | async def test_different_chats_not_merged(self): method test_batch_cleans_up_after_flush (line 113) | async def test_batch_cleans_up_after_flush(self): FILE: tests/gateway/test_title_command.py function _make_event (line 17) | def _make_event(text="/title", platform=Platform.TELEGRAM, function _make_runner (line 29) | def _make_runner(session_db=None): class TestHandleTitleCommand (line 53) | class TestHandleTitleCommand: method test_set_title (line 57) | async def test_set_title(self, tmp_path): method test_show_title_when_set (line 74) | async def test_show_title_when_set(self, tmp_path): method test_show_title_when_not_set (line 89) | async def test_show_title_when_not_set(self, tmp_path): method test_title_conflict (line 103) | async def test_title_conflict(self, tmp_path): method test_no_session_db (line 119) | async def test_no_session_db(self): method test_title_too_long (line 127) | async def test_title_too_long(self, tmp_path): method test_title_control_chars_sanitized (line 142) | async def test_title_control_chars_sanitized(self, tmp_path): method test_title_only_control_chars (line 156) | async def test_title_only_control_chars(self, tmp_path): method test_works_across_platforms (line 169) | async def test_works_across_platforms(self, tmp_path): class TestTitleInHelp (line 189) | class TestTitleInHelp: method test_title_in_help_output (line 193) | async def test_title_in_help_output(self): method test_title_is_known_command (line 203) | def test_title_is_known_command(self): FILE: tests/gateway/test_transcript_offset.py function _filter_history (line 22) | def _filter_history(history: list) -> list: class TestTranscriptHistoryOffset (line 55) | class TestTranscriptHistoryOffset: method test_session_meta_causes_offset_mismatch (line 58) | def test_session_meta_causes_offset_mismatch(self): method test_no_session_meta_same_result (line 101) | def test_no_session_meta_same_result(self): method test_multiple_session_meta_larger_drift (line 122) | def test_multiple_session_meta_larger_drift(self): method test_system_messages_also_filtered (line 167) | def test_system_messages_also_filtered(self): method test_else_branch_returns_empty_list (line 200) | def test_else_branch_returns_empty_list(self): method test_tool_call_messages_preserved_in_filter (line 227) | def test_tool_call_messages_preserved_in_filter(self): FILE: tests/gateway/test_unauthorized_dm_behavior.py function _clear_auth_env (line 11) | def _clear_auth_env(monkeypatch) -> None: function _make_event (line 39) | def _make_event(platform: Platform, user_id: str, chat_id: str) -> Messa... function _make_runner (line 53) | def _make_runner(platform: Platform, config: GatewayConfig): function test_unauthorized_dm_pairs_by_default (line 66) | async def test_unauthorized_dm_pairs_by_default(monkeypatch): function test_unauthorized_whatsapp_dm_can_be_ignored (line 93) | async def test_unauthorized_whatsapp_dm_can_be_ignored(monkeypatch): function test_global_ignore_suppresses_pairing_reply (line 119) | async def test_global_ignore_suppresses_pairing_reply(monkeypatch): FILE: tests/gateway/test_update_command.py function _make_event (line 19) | def _make_event(text="/update", platform=Platform.TELEGRAM, function _make_runner (line 31) | def _make_runner(): class TestHandleUpdateCommand (line 45) | class TestHandleUpdateCommand: method test_no_git_directory (line 49) | async def test_no_git_directory(self, tmp_path): method test_no_hermes_binary (line 90) | async def test_no_hermes_binary(self, tmp_path): method test_fallback_to_sys_executable (line 113) | async def test_fallback_to_sys_executable(self, tmp_path): method test_resolve_hermes_bin_prefers_which (line 144) | async def test_resolve_hermes_bin_prefers_which(self, tmp_path): method test_resolve_hermes_bin_fallback (line 154) | async def test_resolve_hermes_bin_fallback(self): method test_resolve_hermes_bin_returns_none_when_both_fail (line 167) | async def test_resolve_hermes_bin_returns_none_when_both_fail(self): method test_writes_pending_marker (line 178) | async def test_writes_pending_marker(self, tmp_path): method test_spawns_systemd_run (line 207) | async def test_spawns_systemd_run(self, tmp_path): method test_fallback_nohup_when_no_systemd_run (line 236) | async def test_fallback_nohup_when_no_systemd_run(self, tmp_path): method test_popen_failure_cleans_up (line 273) | async def test_popen_failure_cleans_up(self, tmp_path): method test_returns_user_friendly_message (line 299) | async def test_returns_user_friendly_message(self, tmp_path): class TestSendUpdateNotification (line 327) | class TestSendUpdateNotification: method test_no_pending_file_is_noop (line 331) | async def test_no_pending_file_is_noop(self, tmp_path): method test_defers_notification_while_update_still_running (line 342) | async def test_defers_notification_while_update_still_running(self, tm... method test_recovers_from_claimed_pending_file (line 365) | async def test_recovers_from_claimed_pending_file(self, tmp_path): method test_sends_notification_with_output (line 389) | async def test_sends_notification_with_output(self, tmp_path): method test_strips_ansi_codes (line 422) | async def test_strips_ansi_codes(self, tmp_path): method test_truncates_long_output (line 446) | async def test_truncates_long_output(self, tmp_path): method test_sends_failure_message_when_update_fails (line 470) | async def test_sends_failure_message_when_update_fails(self, tmp_path): method test_sends_generic_message_when_no_output (line 493) | async def test_sends_generic_message_when_no_output(self, tmp_path): method test_cleans_up_files_after_notification (line 514) | async def test_cleans_up_files_after_notification(self, tmp_path): method test_cleans_up_on_error (line 540) | async def test_cleans_up_on_error(self, tmp_path): method test_handles_corrupt_pending_file (line 569) | async def test_handles_corrupt_pending_file(self, tmp_path): method test_no_adapter_for_platform (line 586) | async def test_no_adapter_for_platform(self, tmp_path): class TestUpdateInHelp (line 619) | class TestUpdateInHelp: method test_update_in_help_output (line 623) | async def test_update_in_help_output(self): method test_update_is_known_command (line 630) | def test_update_is_known_command(self): FILE: tests/gateway/test_voice_command.py function _ensure_discord_mock (line 15) | def _ensure_discord_mock(): function _make_event (line 61) | def _make_event(text: str = "", message_type=MessageType.TEXT, chat_id="... function _make_runner (line 74) | def _make_runner(tmp_path): class TestHandleVoiceCommand (line 91) | class TestHandleVoiceCommand: method runner (line 94) | def runner(self, tmp_path): method test_voice_on (line 98) | async def test_voice_on(self, runner): method test_voice_off (line 105) | async def test_voice_off(self, runner): method test_voice_tts (line 113) | async def test_voice_tts(self, runner): method test_voice_status_off (line 120) | async def test_voice_status_off(self, runner): method test_voice_status_on (line 126) | async def test_voice_status_on(self, runner): method test_toggle_off_to_on (line 133) | async def test_toggle_off_to_on(self, runner): method test_toggle_on_to_off (line 140) | async def test_toggle_on_to_off(self, runner): method test_persistence_saved (line 148) | async def test_persistence_saved(self, runner): method test_persistence_loaded (line 156) | async def test_persistence_loaded(self, runner): method test_persistence_saved_for_off (line 162) | async def test_persistence_saved_for_off(self, runner): method test_sync_voice_mode_state_to_adapter_restores_off_chats (line 168) | def test_sync_voice_mode_state_to_adapter_restores_off_chats(self, run... method test_restart_restores_voice_off_state (line 176) | def test_restart_restores_voice_off_state(self, runner, tmp_path): method test_per_chat_isolation (line 189) | async def test_per_chat_isolation(self, runner): class TestAutoVoiceReply (line 202) | class TestAutoVoiceReply: method runner (line 218) | def runner(self, tmp_path): method _call (line 221) | def _call(self, runner, voice_mode, message_type, agent_messages=None, method test_voice_input_voice_only_skipped (line 270) | def test_voice_input_voice_only_skipped(self, runner): method test_voice_input_all_mode_skipped (line 274) | def test_voice_input_all_mode_skipped(self, runner): method test_text_input_all_mode_runner_fires (line 280) | def test_text_input_all_mode_runner_fires(self, runner): method test_text_input_voice_only_no_reply (line 284) | def test_text_input_voice_only_no_reply(self, runner): method test_off_mode_voice (line 290) | def test_off_mode_voice(self, runner): method test_off_mode_text (line 293) | def test_off_mode_text(self, runner): method test_discord_vc_voice_input_base_handles (line 298) | def test_discord_vc_voice_input_base_handles(self, runner): method test_discord_vc_voice_only_base_handles (line 303) | def test_discord_vc_voice_only_base_handles(self, runner): method test_error_response_skipped (line 309) | def test_error_response_skipped(self, runner): method test_empty_response_skipped (line 312) | def test_empty_response_skipped(self, runner): method test_dedup_skips_when_agent_called_tts (line 315) | def test_dedup_skips_when_agent_called_tts(self, runner): method test_no_dedup_for_other_tools (line 326) | def test_no_dedup_for_other_tools(self, runner): class TestSendVoiceReply (line 342) | class TestSendVoiceReply: method runner (line 345) | def runner(self, tmp_path): method test_calls_tts_and_send_voice (line 349) | async def test_calls_tts_and_send_voice(self, runner): method test_empty_text_after_strip_skips (line 369) | async def test_empty_text_after_strip_skips(self, runner): method test_tts_failure_no_crash (line 379) | async def test_tts_failure_no_crash(self, runner): method test_exception_caught (line 394) | async def test_exception_caught(self, runner): class TestDiscordPlayTtsSkip (line 407) | class TestDiscordPlayTtsSkip: method _make_discord_adapter (line 410) | def _make_discord_adapter(self): method test_play_tts_plays_in_vc_when_connected (line 428) | async def test_play_tts_plays_in_vc_when_connected(self): method test_play_tts_not_skipped_when_not_in_vc (line 447) | async def test_play_tts_not_skipped_when_not_in_vc(self): method test_play_tts_not_skipped_for_different_channel (line 455) | async def test_play_tts_not_skipped_for_different_channel(self): class TestVoiceInHelp (line 475) | class TestVoiceInHelp: method test_voice_in_help_output (line 477) | def test_voice_in_help_output(self): method test_voice_is_known_command (line 483) | def test_voice_is_known_command(self): class TestVoiceReceiver (line 493) | class TestVoiceReceiver: method _make_receiver (line 496) | def _make_receiver(self): method test_initial_state (line 508) | def test_initial_state(self): method test_start_sets_running (line 515) | def test_start_sets_running(self): method test_stop_clears_state (line 520) | def test_stop_clears_state(self): method test_map_ssrc (line 532) | def test_map_ssrc(self): method test_map_ssrc_overwrites (line 537) | def test_map_ssrc_overwrites(self): method test_pause_resume (line 543) | def test_pause_resume(self): method test_check_silence_empty (line 551) | def test_check_silence_empty(self): method test_check_silence_returns_completed_utterance (line 555) | def test_check_silence_returns_completed_utterance(self): method test_check_silence_ignores_short_buffer (line 572) | def test_check_silence_ignores_short_buffer(self): method test_check_silence_ignores_recent_audio (line 581) | def test_check_silence_ignores_recent_audio(self): method test_check_silence_unknown_user_discarded (line 589) | def test_check_silence_unknown_user_discarded(self): method test_stale_buffer_discarded (line 597) | def test_stale_buffer_discarded(self): method test_on_packet_skips_when_not_running (line 606) | def test_on_packet_skips_when_not_running(self): method test_on_packet_skips_when_paused (line 612) | def test_on_packet_skips_when_paused(self): method test_on_packet_skips_short_data (line 620) | def test_on_packet_skips_short_data(self): method test_on_packet_skips_non_rtp (line 626) | def test_on_packet_skips_non_rtp(self): class TestVoiceChannelCommands (line 640) | class TestVoiceChannelCommands: method runner (line 645) | def runner(self, tmp_path): method _make_discord_event (line 648) | def _make_discord_event(self, text="/voice channel", chat_id="123", method test_join_unsupported_platform (line 666) | async def test_join_unsupported_platform(self, runner): method test_join_no_guild_id (line 675) | async def test_join_no_guild_id(self, runner): method test_join_user_not_in_vc (line 686) | async def test_join_user_not_in_vc(self, runner): method test_join_success (line 697) | async def test_join_success(self, runner): method test_join_failure (line 714) | async def test_join_failure(self, runner): method test_join_exception (line 727) | async def test_join_exception(self, runner): method test_join_missing_voice_dependencies (line 740) | async def test_join_missing_voice_dependencies(self, runner): method test_leave_not_in_vc (line 760) | async def test_leave_not_in_vc(self, runner): method test_leave_no_guild (line 770) | async def test_leave_no_guild(self, runner): method test_leave_success (line 780) | async def test_leave_success(self, runner): method test_input_no_adapter (line 796) | async def test_input_no_adapter(self, runner): method test_input_no_text_channel (line 803) | async def test_input_no_text_channel(self, runner): method test_input_creates_event_and_dispatches (line 813) | async def test_input_creates_event_and_dispatches(self, runner): method test_input_posts_transcript_in_text_channel (line 832) | async def test_input_posts_transcript_in_text_channel(self, runner): method test_get_guild_id_from_guild (line 850) | def test_get_guild_id_from_guild(self, runner): method test_get_guild_id_from_interaction (line 858) | def test_get_guild_id_from_interaction(self, runner): method test_get_guild_id_none (line 864) | def test_get_guild_id_none(self, runner): method test_get_guild_id_dm (line 870) | def test_get_guild_id_dm(self, runner): class TestDiscordVoiceChannelMethods (line 881) | class TestDiscordVoiceChannelMethods: method _make_adapter (line 884) | def _make_adapter(self): method test_is_in_voice_channel_true (line 903) | def test_is_in_voice_channel_true(self): method test_is_in_voice_channel_false_no_client (line 910) | def test_is_in_voice_channel_false_no_client(self): method test_is_in_voice_channel_false_disconnected (line 914) | def test_is_in_voice_channel_false_disconnected(self): method test_leave_voice_channel_cleans_up (line 922) | async def test_leave_voice_channel_cleans_up(self): method test_leave_voice_channel_no_connection (line 950) | async def test_leave_voice_channel_no_connection(self): method test_get_user_voice_channel_no_client (line 956) | async def test_get_user_voice_channel_no_client(self): method test_get_user_voice_channel_no_guild (line 963) | async def test_get_user_voice_channel_no_guild(self): method test_get_user_voice_channel_user_not_in_vc (line 970) | async def test_get_user_voice_channel_user_not_in_vc(self): method test_get_user_voice_channel_success (line 981) | async def test_get_user_voice_channel_success(self): method test_play_in_voice_channel_not_connected (line 994) | async def test_play_in_voice_channel_not_connected(self): method test_is_allowed_user_empty_list (line 999) | def test_is_allowed_user_empty_list(self): method test_is_allowed_user_in_list (line 1003) | def test_is_allowed_user_in_list(self): method test_is_allowed_user_not_in_list (line 1008) | def test_is_allowed_user_not_in_list(self): method test_process_voice_input_success (line 1014) | async def test_process_voice_input_success(self): method test_process_voice_input_hallucination_filtered (line 1032) | async def test_process_voice_input_hallucination_filtered(self): method test_process_voice_input_stt_failure (line 1047) | async def test_process_voice_input_stt_failure(self): method test_process_voice_input_exception_caught (line 1061) | async def test_process_voice_input_exception_caught(self): class TestVoiceReceiverThreadSafety (line 1080) | class TestVoiceReceiverThreadSafety: method _make_receiver (line 1083) | def _make_receiver(self): method test_check_silence_holds_lock (line 1094) | def test_check_silence_holds_lock(self): method test_on_packet_buffer_write_holds_lock (line 1115) | def test_on_packet_buffer_write_holds_lock(self): method test_concurrent_buffer_access_safe (line 1132) | def test_concurrent_buffer_access_safe(self): class TestCallbackWiringOrder (line 1165) | class TestCallbackWiringOrder: method test_callback_set_before_join (line 1168) | def test_callback_set_before_join(self): method test_join_failure_clears_callback (line 1190) | async def test_join_failure_clears_callback(self, tmp_path): method test_join_returns_false_clears_callback (line 1212) | async def test_join_returns_false_clears_callback(self, tmp_path): class TestLeaveExceptionHandling (line 1236) | class TestLeaveExceptionHandling: method runner (line 1240) | def runner(self, tmp_path): method test_leave_exception_still_cleans_state (line 1244) | async def test_leave_exception_still_cleans_state(self, runner): method test_leave_clears_callback (line 1264) | async def test_leave_clears_callback(self, runner): class TestAutoTtsEmptyTextGuard (line 1284) | class TestAutoTtsEmptyTextGuard: method test_empty_after_strip_skips_tts (line 1287) | def test_empty_after_strip_skips_tts(self): method test_code_block_response_skips_tts (line 1294) | def test_code_block_response_skips_tts(self): method test_base_empty_check_in_source (line 1303) | def test_base_empty_check_in_source(self): class TestStreamTtsToSpeaker (line 1313) | class TestStreamTtsToSpeaker: method test_none_sentinel_flushes_buffer (line 1316) | def test_none_sentinel_flushes_buffer(self): method test_stop_event_aborts_early (line 1334) | def test_stop_event_aborts_early(self): method test_done_event_set_on_exception (line 1350) | def test_done_event_set_on_exception(self): method test_think_blocks_stripped (line 1364) | def test_think_blocks_stripped(self): method test_sentence_splitting (line 1382) | def test_sentence_splitting(self): method test_markdown_stripped_in_speech (line 1399) | def test_markdown_stripped_in_speech(self): method test_duplicate_sentences_deduped (line 1415) | def test_duplicate_sentences_deduped(self): method test_no_api_key_display_only (line 1433) | def test_no_api_key_display_only(self): method test_long_buffer_flushed_on_timeout (line 1450) | def test_long_buffer_flushed_on_timeout(self): class TestStopAcquiresLock (line 1480) | class TestStopAcquiresLock: method _make_receiver (line 1484) | def _make_receiver(): method test_stop_clears_under_lock (line 1492) | def test_stop_clears_under_lock(self): method test_stop_does_not_deadlock_with_on_packet (line 1542) | def test_stop_does_not_deadlock_with_on_packet(self): class TestPacketDebugCounterIsInstanceLevel (line 1582) | class TestPacketDebugCounterIsInstanceLevel: method _make_receiver (line 1586) | def _make_receiver(): method test_counter_is_per_instance (line 1594) | def test_counter_is_per_instance(self): method test_counter_initialized_in_init (line 1603) | def test_counter_initialized_in_init(self): class TestPlayInVoiceChannelUsesRunningLoop (line 1614) | class TestPlayInVoiceChannelUsesRunningLoop: method test_source_uses_get_running_loop (line 1617) | def test_source_uses_get_running_loop(self): class TestSendVoiceReplyFilename (line 1632) | class TestSendVoiceReplyFilename: method test_filename_uses_uuid (line 1635) | def test_filename_uses_uuid(self): method test_filenames_are_unique (line 1645) | def test_filenames_are_unique(self): class TestVoiceTimeoutCleansRunnerState (line 1659) | class TestVoiceTimeoutCleansRunnerState: method _make_discord_adapter (line 1663) | def _make_discord_adapter(): method adapter (line 1684) | def adapter(self): method test_adapter_has_on_voice_disconnect_attr (line 1687) | def test_adapter_has_on_voice_disconnect_attr(self, adapter): method test_timeout_calls_disconnect_callback (line 1693) | async def test_timeout_calls_disconnect_callback(self, adapter): method test_runner_cleanup_method_removes_voice_mode (line 1716) | async def test_runner_cleanup_method_removes_voice_mode(self, tmp_path): method test_timeout_without_callback_does_not_crash (line 1727) | async def test_timeout_without_callback_does_not_crash(self, adapter): class TestPlaybackTimeout (line 1748) | class TestPlaybackTimeout: method _make_discord_adapter (line 1752) | def _make_discord_adapter(): method test_source_has_wait_for_timeout (line 1772) | def test_source_has_wait_for_timeout(self): method test_playback_timeout_constant_exists (line 1782) | def test_playback_timeout_constant_exists(self): method test_playback_timeout_fires (line 1789) | async def test_playback_timeout_fires(self): method test_is_playing_wait_has_timeout (line 1817) | async def test_is_playing_wait_has_timeout(self): class TestSendVoiceReplyCleanup (line 1848) | class TestSendVoiceReplyCleanup: method test_cleanup_in_finally (line 1851) | def test_cleanup_in_finally(self): method test_files_cleaned_on_send_exception (line 1871) | async def test_files_cleaned_on_send_exception(self, tmp_path): class TestAutoTtsTempFileCleanup (line 1907) | class TestAutoTtsTempFileCleanup: method test_source_has_finally_remove (line 1910) | def test_source_has_finally_remove(self): class TestVoiceChannelAwareness (line 1931) | class TestVoiceChannelAwareness: method _make_adapter (line 1934) | def _make_adapter(self): method _make_member (line 1947) | def _make_member(self, user_id, display_name, is_bot=False): method test_returns_none_when_not_connected (line 1952) | def test_returns_none_when_not_connected(self): method test_returns_none_when_vc_disconnected (line 1956) | def test_returns_none_when_vc_disconnected(self): method test_returns_info_with_members (line 1963) | def test_returns_info_with_members(self): method test_speaking_detection (line 1983) | def test_speaking_detection(self): method test_context_string_format (line 2008) | def test_context_string_format(self): method test_context_empty_when_not_connected (line 2022) | def test_context_empty_when_not_connected(self): class TestDisconnectVoiceCleanup (line 2032) | class TestDisconnectVoiceCleanup: method test_disconnect_clears_voice_state (line 2036) | async def test_disconnect_clears_voice_state(self): class TestVoiceReception (line 2071) | class TestVoiceReception: method _make_receiver (line 2075) | def _make_receiver(allowed_ids=None, members=None, dave=False, bot_id=... method _fill_buffer (line 2091) | def _fill_buffer(receiver, ssrc, duration_s=1.0, age_s=3.0): method test_known_ssrc_returns_completed (line 2099) | def test_known_ssrc_returns_completed(self): method test_known_ssrc_short_buffer_ignored (line 2109) | def test_known_ssrc_short_buffer_ignored(self): method test_known_ssrc_recent_audio_waits (line 2117) | def test_known_ssrc_recent_audio_waits(self): method test_unknown_ssrc_no_automap_no_completed (line 2127) | def test_unknown_ssrc_no_automap_no_completed(self): method test_unknown_ssrc_late_speaking_event (line 2136) | def test_unknown_ssrc_late_speaking_event(self): method test_automap_single_allowed_user (line 2153) | def test_automap_single_allowed_user(self): method test_automap_multiple_allowed_users_no_map (line 2166) | def test_automap_multiple_allowed_users_no_map(self): method test_automap_no_allowlist_single_member (line 2178) | def test_automap_no_allowlist_single_member(self): method test_automap_unallowed_user_rejected (line 2191) | def test_automap_unallowed_user_rejected(self): method test_automap_only_bot_in_channel (line 2203) | def test_automap_only_bot_in_channel(self): method test_automap_persists_across_calls (line 2212) | def test_automap_persists_across_calls(self): method test_stale_unknown_buffer_discarded (line 2231) | def test_stale_unknown_buffer_discarded(self): method test_paused_receiver_ignores_packets (line 2242) | def test_paused_receiver_ignores_packets(self): method test_resumed_receiver_accepts_packets (line 2249) | def test_resumed_receiver_accepts_packets(self): method _make_receiver_with_nacl (line 2258) | def _make_receiver_with_nacl(self, dave_session=None, mapped_ssrcs=None): method _build_rtp_packet (line 2280) | def _build_rtp_packet(ssrc=100, seq=1, timestamp=960): method _inject_mock_decoder (line 2293) | def _inject_mock_decoder(self, receiver, ssrc): method test_on_packet_dave_known_user_decrypt_ok (line 2300) | def test_on_packet_dave_known_user_decrypt_ok(self): method test_on_packet_dave_unknown_ssrc_passthrough (line 2317) | def test_on_packet_dave_unknown_ssrc_passthrough(self): method test_on_packet_dave_unencrypted_error_passthrough (line 2331) | def test_on_packet_dave_unencrypted_error_passthrough(self): method test_on_packet_dave_other_error_drops (line 2349) | def test_on_packet_dave_other_error_drops(self): method test_on_packet_no_dave_direct_decode (line 2363) | def test_on_packet_no_dave_direct_decode(self): method test_on_packet_bot_own_ssrc_ignored (line 2375) | def test_on_packet_bot_own_ssrc_ignored(self): method test_on_packet_multiple_ssrcs_separate_buffers (line 2382) | def test_on_packet_multiple_ssrcs_separate_buffers(self): class TestVoiceTTSPlayback (line 2397) | class TestVoiceTTSPlayback: method _make_discord_adapter (line 2401) | def _make_discord_adapter(): method test_play_tts_plays_in_vc (line 2417) | async def test_play_tts_plays_in_vc(self): method test_play_tts_fallback_when_not_in_vc (line 2436) | async def test_play_tts_fallback_when_not_in_vc(self): method test_play_tts_wrong_channel_no_match (line 2446) | async def test_play_tts_wrong_channel_no_match(self): method _make_runner (line 2463) | def _make_runner(): method _call_should_reply (line 2470) | def _call_should_reply(self, runner, voice_mode, msg_type, response="H... method test_voice_input_runner_skips (line 2481) | def test_voice_input_runner_skips(self): method test_text_input_voice_all_runner_fires (line 2487) | def test_text_input_voice_all_runner_fires(self): method test_text_input_voice_off_no_tts (line 2493) | def test_text_input_voice_off_no_tts(self): method test_text_input_voice_only_no_tts (line 2499) | def test_text_input_voice_only_no_tts(self): method test_error_response_no_tts (line 2505) | def test_error_response_no_tts(self): method test_empty_response_no_tts (line 2511) | def test_empty_response_no_tts(self): method test_agent_tts_tool_dedup (line 2517) | def test_agent_tts_tool_dedup(self): class TestUDPKeepalive (line 2527) | class TestUDPKeepalive: method test_keepalive_interval_is_reasonable (line 2530) | def test_keepalive_interval_is_reasonable(self): method test_keepalive_sends_silence_frame (line 2536) | async def test_keepalive_sends_silence_frame(self): FILE: tests/gateway/test_webhook_adapter.py function _make_config (line 41) | def _make_config( function _make_adapter (line 62) | def _make_adapter(routes=None, **kwargs): function _create_app (line 68) | def _create_app(adapter: WebhookAdapter) -> web.Application: function _mock_request (line 76) | def _mock_request(headers=None, body=b"", content_length=None, match_inf... function _github_signature (line 91) | def _github_signature(body: bytes, secret: str) -> str: function _generic_signature (line 98) | def _generic_signature(body: bytes, secret: str) -> str: class TestValidateSignature (line 108) | class TestValidateSignature: method test_validate_github_signature_valid (line 111) | def test_validate_github_signature_valid(self): method test_validate_github_signature_invalid (line 120) | def test_validate_github_signature_invalid(self): method test_validate_gitlab_token (line 128) | def test_validate_gitlab_token(self): method test_validate_gitlab_token_wrong (line 135) | def test_validate_gitlab_token_wrong(self): method test_validate_no_signature_with_secret_rejects (line 141) | def test_validate_no_signature_with_secret_rejects(self): method test_validate_no_secret_allows_all (line 147) | def test_validate_no_secret_allows_all(self): method test_validate_generic_signature_valid (line 164) | def test_validate_generic_signature_valid(self): class TestRenderPrompt (line 179) | class TestRenderPrompt: method test_render_prompt_dot_notation (line 182) | def test_render_prompt_dot_notation(self): method test_render_prompt_missing_key_preserved (line 194) | def test_render_prompt_missing_key_preserved(self): method test_render_prompt_no_template_dumps_json (line 205) | def test_render_prompt_no_template_dumps_json(self): class TestRenderDeliveryExtra (line 220) | class TestRenderDeliveryExtra: method test_render_delivery_extra_templates (line 221) | def test_render_delivery_extra_templates(self): class TestEventFilter (line 237) | class TestEventFilter: method test_event_filter_accepts_matching (line 241) | async def test_event_filter_accepts_matching(self): method test_event_filter_rejects_non_matching (line 264) | async def test_event_filter_rejects_non_matching(self): method test_event_filter_empty_allows_all (line 287) | async def test_event_filter_empty_allows_all(self): class TestHTTPHandling (line 313) | class TestHTTPHandling: method test_unknown_route_returns_404 (line 316) | async def test_unknown_route_returns_404(self): method test_webhook_handler_returns_202 (line 325) | async def test_webhook_handler_returns_202(self): method test_health_endpoint (line 340) | async def test_health_endpoint(self): method test_connect_starts_server (line 352) | async def test_connect_starts_server(self): method test_disconnect_cleans_up (line 375) | async def test_disconnect_cleans_up(self): class TestIdempotency (line 394) | class TestIdempotency: method test_duplicate_delivery_id_returns_200 (line 397) | async def test_duplicate_delivery_id_returns_200(self): method test_expired_delivery_id_allows_reprocess (line 415) | async def test_expired_delivery_id_allows_reprocess(self): class TestRateLimiting (line 441) | class TestRateLimiting: method test_rate_limit_rejects_excess (line 444) | async def test_rate_limit_rejects_excess(self): method test_rate_limit_window_resets (line 470) | async def test_rate_limit_window_resets(self): class TestBodySize (line 501) | class TestBodySize: method test_oversized_payload_rejected (line 504) | async def test_oversized_payload_rejected(self): class TestInsecureNoAuth (line 525) | class TestInsecureNoAuth: method test_insecure_no_auth_skips_validation (line 528) | async def test_insecure_no_auth_skips_validation(self): class TestSessionIsolation (line 546) | class TestSessionIsolation: method test_concurrent_webhooks_get_independent_sessions (line 549) | async def test_concurrent_webhooks_get_independent_sessions(self): class TestDeliveryCleanup (line 590) | class TestDeliveryCleanup: method test_delivery_info_cleaned_after_send (line 593) | async def test_delivery_info_cleaned_after_send(self): class TestCheckRequirements (line 613) | class TestCheckRequirements: method test_returns_true_when_aiohttp_available (line 614) | def test_returns_true_when_aiohttp_available(self): method test_returns_false_without_aiohttp (line 618) | def test_returns_false_without_aiohttp(self): FILE: tests/gateway/test_webhook_integration.py function _make_adapter (line 34) | def _make_adapter(routes, **extra_kw) -> WebhookAdapter: function _create_app (line 42) | def _create_app(adapter: WebhookAdapter) -> web.Application: function _github_signature (line 50) | def _github_signature(body: bytes, secret: str) -> str: class TestGitHubPRWebhook (line 81) | class TestGitHubPRWebhook: method test_github_pr_webhook_triggers_agent (line 84) | async def test_github_pr_webhook_triggers_agent(self): class TestSkillsInjection (line 151) | class TestSkillsInjection: method test_skills_injected_into_prompt (line 154) | async def test_skills_injected_into_prompt(self): class TestCrossPlatformDelivery (line 213) | class TestCrossPlatformDelivery: method test_cross_platform_delivery (line 216) | async def test_cross_platform_delivery(self): class TestGitHubCommentDelivery (line 270) | class TestGitHubCommentDelivery: method test_github_comment_delivery (line 273) | async def test_github_comment_delivery(self): FILE: tests/gateway/test_whatsapp_connect.py class _AsyncCM (line 28) | class _AsyncCM: method __init__ (line 31) | def __init__(self, value): method __aenter__ (line 34) | async def __aenter__(self): method __aexit__ (line 37) | async def __aexit__(self, *exc): function _make_adapter (line 41) | def _make_adapter(): function _mock_aiohttp (line 60) | def _mock_aiohttp(status=200, json_data=None, json_side_effect=None): function _connect_patches (line 75) | def _connect_patches(mock_proc, mock_fh, mock_client_cls=None): class TestCloseBridgeLog (line 100) | class TestCloseBridgeLog: method _bare_adapter (line 104) | def _bare_adapter(): method test_closes_open_handle (line 110) | def test_closes_open_handle(self): method test_noop_when_no_handle (line 120) | def test_noop_when_no_handle(self): method test_suppresses_close_exception (line 127) | def test_suppresses_close_exception(self): class TestDataInitialized (line 142) | class TestDataInitialized: method test_no_name_error_when_json_always_fails (line 146) | async def test_no_name_error_when_json_always_fails(self): class TestFileHandleClosedOnError (line 180) | class TestFileHandleClosedOnError: method test_closed_when_bridge_dies_phase1 (line 184) | async def test_closed_when_bridge_dies_phase1(self): method test_closed_when_http_not_ready (line 204) | async def test_closed_when_http_not_ready(self): method test_closed_when_bridge_dies_phase2 (line 224) | async def test_closed_when_bridge_dies_phase2(self): method test_closed_on_unexpected_exception (line 255) | async def test_closed_on_unexpected_exception(self): class TestKillPortProcess (line 278) | class TestKillPortProcess: method test_uses_netstat_and_taskkill_on_windows (line 281) | def test_uses_netstat_and_taskkill_on_windows(self): method test_does_not_kill_wrong_port_on_windows (line 313) | def test_does_not_kill_wrong_port_on_windows(self): method test_uses_fuser_on_linux (line 331) | def test_uses_fuser_on_linux(self): method test_skips_fuser_kill_when_port_free (line 344) | def test_skips_fuser_kill_when_port_free(self): method test_suppresses_exceptions (line 357) | def test_suppresses_exceptions(self): FILE: tests/gateway/test_whatsapp_reply_prefix.py class TestConfigYamlBridging (line 23) | class TestConfigYamlBridging: method test_reply_prefix_bridged_from_yaml (line 26) | def test_reply_prefix_bridged_from_yaml(self, tmp_path): method test_empty_reply_prefix_bridged (line 41) | def test_empty_reply_prefix_bridged(self, tmp_path): method test_no_whatsapp_section_no_extra (line 55) | def test_no_whatsapp_section_no_extra(self, tmp_path): method test_whatsapp_section_without_reply_prefix (line 69) | def test_whatsapp_section_without_reply_prefix(self, tmp_path): class TestAdapterInit (line 88) | class TestAdapterInit: method test_reply_prefix_from_extra (line 91) | def test_reply_prefix_from_extra(self): method test_reply_prefix_default_none (line 97) | def test_reply_prefix_default_none(self): method test_reply_prefix_empty_string (line 103) | def test_reply_prefix_empty_string(self): class TestConfigVersionCoverage (line 115) | class TestConfigVersionCoverage: method test_default_config_version_covers_env_var_versions (line 118) | def test_default_config_version_covers_env_var_versions(self): FILE: tests/hermes_cli/test_banner.py function test_display_toolset_name_strips_legacy_suffix (line 12) | def test_display_toolset_name_strips_legacy_suffix(): function test_display_toolset_name_preserves_clean_names (line 18) | def test_display_toolset_name_preserves_clean_names(): function test_display_toolset_name_handles_empty (line 24) | def test_display_toolset_name_handles_empty(): function test_build_welcome_banner_uses_normalized_toolset_names (line 29) | def test_build_welcome_banner_uses_normalized_toolset_names(): FILE: tests/hermes_cli/test_banner_skills.py function test_get_available_skills_delegates_to_find_all_skills (line 15) | def test_get_available_skills_delegates_to_find_all_skills(): function test_get_available_skills_excludes_disabled (line 27) | def test_get_available_skills_excludes_disabled(): function test_get_available_skills_empty_when_no_skills (line 42) | def test_get_available_skills_empty_when_no_skills(): function test_get_available_skills_handles_import_failure (line 51) | def test_get_available_skills_handles_import_failure(): function test_get_available_skills_null_category_becomes_general (line 60) | def test_get_available_skills_null_category_becomes_general(): FILE: tests/hermes_cli/test_chat_skills_flag.py function test_top_level_skills_flag_defaults_to_chat (line 4) | def test_top_level_skills_flag_defaults_to_chat(monkeypatch): function test_chat_subcommand_accepts_skills_flag (line 28) | def test_chat_subcommand_accepts_skills_flag(monkeypatch): function test_continue_worktree_and_skills_flags_work_together (line 52) | def test_continue_worktree_and_skills_flags_work_together(monkeypatch): FILE: tests/hermes_cli/test_claw.py class TestFindMigrationScript (line 17) | class TestFindMigrationScript: method test_finds_project_root_script (line 20) | def test_finds_project_root_script(self, tmp_path): method test_finds_installed_script (line 26) | def test_finds_installed_script(self, tmp_path): method test_returns_none_when_missing (line 35) | def test_returns_none_when_missing(self, tmp_path): class TestClawCommand (line 48) | class TestClawCommand: method test_routes_to_migrate (line 51) | def test_routes_to_migrate(self): method test_shows_help_for_no_action (line 59) | def test_shows_help_for_no_action(self, capsys): class TestCmdMigrate (line 71) | class TestCmdMigrate: method test_error_when_source_missing (line 74) | def test_error_when_source_missing(self, tmp_path, capsys): method test_error_when_script_missing (line 85) | def test_error_when_script_missing(self, tmp_path, capsys): method test_dry_run_succeeds (line 102) | def test_dry_run_succeeds(self, tmp_path, capsys): method test_execute_with_confirmation (line 141) | def test_execute_with_confirmation(self, tmp_path, capsys): method test_execute_cancelled_by_user (line 178) | def test_execute_cancelled_by_user(self, tmp_path, capsys): method test_execute_with_yes_skips_confirmation (line 200) | def test_execute_with_yes_skips_confirmation(self, tmp_path, capsys): method test_handles_migration_error (line 232) | def test_handles_migration_error(self, tmp_path, capsys): method test_full_preset_enables_secrets (line 257) | def test_full_preset_enables_secrets(self, tmp_path, capsys): class TestPrintMigrationReport (line 298) | class TestPrintMigrationReport: method test_dry_run_report (line 301) | def test_dry_run_report(self, capsys): method test_execute_report (line 319) | def test_execute_report(self, capsys): method test_empty_report (line 333) | def test_empty_report(self, capsys): FILE: tests/hermes_cli/test_cmd_update.py function _make_run_side_effect (line 12) | def _make_run_side_effect(branch="main", verify_ok=True, commit_count="0"): function mock_args (line 38) | def mock_args(): class TestCmdUpdateBranchFallback (line 42) | class TestCmdUpdateBranchFallback: method test_update_falls_back_to_main_when_branch_not_on_remote (line 47) | def test_update_falls_back_to_main_when_branch_not_on_remote( method test_update_uses_current_branch_when_on_remote (line 71) | def test_update_uses_current_branch_when_on_remote( method test_update_already_up_to_date (line 92) | def test_update_already_up_to_date( FILE: tests/hermes_cli/test_coalesce_session_args.py class TestCoalesceSessionNameArgs (line 7) | class TestCoalesceSessionNameArgs: method test_continue_multiword_unquoted (line 12) | def test_continue_multiword_unquoted(self): method test_continue_long_form_multiword (line 18) | def test_continue_long_form_multiword(self): method test_continue_single_word (line 24) | def test_continue_single_word(self): method test_continue_already_quoted (line 31) | def test_continue_already_quoted(self): method test_continue_bare_flag (line 37) | def test_continue_bare_flag(self): method test_continue_followed_by_flag (line 41) | def test_continue_followed_by_flag(self): method test_continue_multiword_then_flag (line 45) | def test_continue_multiword_then_flag(self): method test_continue_multiword_then_subcommand (line 51) | def test_continue_multiword_then_subcommand(self): method test_resume_multiword (line 59) | def test_resume_multiword(self): method test_resume_long_form_multiword (line 65) | def test_resume_long_form_multiword(self): method test_resume_multiword_then_flag (line 71) | def test_resume_multiword_then_flag(self): method test_worktree_and_continue_multiword (line 79) | def test_worktree_and_continue_multiword(self): method test_continue_multiword_and_worktree (line 85) | def test_continue_multiword_and_worktree(self): method test_no_session_flags_passthrough (line 93) | def test_no_session_flags_passthrough(self): method test_empty_argv (line 98) | def test_empty_argv(self): method test_stops_at_sessions_subcommand (line 103) | def test_stops_at_sessions_subcommand(self): method test_stops_at_setup_subcommand (line 109) | def test_stops_at_setup_subcommand(self): FILE: tests/hermes_cli/test_commands.py function _completions (line 22) | def _completions(completer: SlashCommandCompleter, text: str): class TestCommandRegistry (line 35) | class TestCommandRegistry: method test_registry_is_nonempty (line 36) | def test_registry_is_nonempty(self): method test_every_entry_is_commanddef (line 39) | def test_every_entry_is_commanddef(self): method test_no_duplicate_canonical_names (line 43) | def test_no_duplicate_canonical_names(self): method test_no_alias_collides_with_canonical_name (line 47) | def test_no_alias_collides_with_canonical_name(self): method test_every_entry_has_valid_category (line 59) | def test_every_entry_has_valid_category(self): method test_cli_only_and_gateway_only_are_mutually_exclusive (line 64) | def test_cli_only_and_gateway_only_are_mutually_exclusive(self): class TestResolveCommand (line 74) | class TestResolveCommand: method test_canonical_name_resolves (line 75) | def test_canonical_name_resolves(self): method test_alias_resolves_to_canonical (line 79) | def test_alias_resolves_to_canonical(self): method test_leading_slash_stripped (line 88) | def test_leading_slash_stripped(self): method test_unknown_returns_none (line 92) | def test_unknown_returns_none(self): class TestDerivedDicts (line 101) | class TestDerivedDicts: method test_commands_dict_excludes_gateway_only (line 102) | def test_commands_dict_excludes_gateway_only(self): method test_commands_dict_includes_all_cli_commands (line 109) | def test_commands_dict_includes_all_cli_commands(self): method test_commands_dict_includes_aliases (line 115) | def test_commands_dict_includes_aliases(self): method test_commands_by_category_covers_all_categories (line 123) | def test_commands_by_category_covers_all_categories(self): method test_every_command_has_nonempty_description (line 127) | def test_every_command_has_nonempty_description(self): class TestGatewayKnownCommands (line 136) | class TestGatewayKnownCommands: method test_excludes_cli_only (line 137) | def test_excludes_cli_only(self): method test_includes_gateway_commands (line 143) | def test_includes_gateway_commands(self): method test_bg_alias_in_gateway (line 150) | def test_bg_alias_in_gateway(self): method test_is_frozenset (line 154) | def test_is_frozenset(self): class TestGatewayHelpLines (line 158) | class TestGatewayHelpLines: method test_returns_nonempty_list (line 159) | def test_returns_nonempty_list(self): method test_excludes_cli_only_commands (line 163) | def test_excludes_cli_only_commands(self): method test_includes_alias_note_for_bg (line 171) | def test_includes_alias_note_for_bg(self): class TestTelegramBotCommands (line 178) | class TestTelegramBotCommands: method test_returns_list_of_tuples (line 179) | def test_returns_list_of_tuples(self): method test_no_hyphens_in_command_names (line 186) | def test_no_hyphens_in_command_names(self): method test_excludes_cli_only (line 191) | def test_excludes_cli_only(self): class TestSlackSubcommandMap (line 199) | class TestSlackSubcommandMap: method test_returns_dict (line 200) | def test_returns_dict(self): method test_values_are_slash_prefixed (line 205) | def test_values_are_slash_prefixed(self): method test_includes_aliases (line 209) | def test_includes_aliases(self): method test_excludes_cli_only (line 214) | def test_excludes_cli_only(self): class TestSlashCommandCompleter (line 225) | class TestSlashCommandCompleter: method test_builtin_prefix_completion_uses_shared_registry (line 228) | def test_builtin_prefix_completion_uses_shared_registry(self): method test_builtin_completion_display_meta_shows_description (line 236) | def test_builtin_completion_display_meta_shows_description(self): method test_exact_match_completion_adds_trailing_space (line 243) | def test_exact_match_completion_adds_trailing_space(self): method test_partial_match_does_not_add_trailing_space (line 248) | def test_partial_match_does_not_add_trailing_space(self): method test_no_completions_for_non_slash_input (line 255) | def test_no_completions_for_non_slash_input(self): method test_no_completions_for_empty_input (line 258) | def test_no_completions_for_empty_input(self): method test_skill_commands_are_completed_from_provider (line 263) | def test_skill_commands_are_completed_from_provider(self): method test_skill_exact_match_adds_trailing_space (line 277) | def test_skill_exact_match_adds_trailing_space(self): method test_no_skill_provider_means_no_skill_completions (line 289) | def test_no_skill_provider_means_no_skill_completions(self): method test_skill_provider_exception_is_swallowed (line 296) | def test_skill_provider_exception_is_swallowed(self): method test_skill_description_truncated_at_50_chars (line 306) | def test_skill_description_truncated_at_50_chars(self): method test_skill_missing_description_uses_fallback (line 319) | def test_skill_missing_description_uses_fallback(self): class TestSubcommands (line 333) | class TestSubcommands: method test_explicit_subcommands_extracted (line 334) | def test_explicit_subcommands_extracted(self): method test_reasoning_has_subcommands (line 339) | def test_reasoning_has_subcommands(self): method test_voice_has_subcommands (line 346) | def test_voice_has_subcommands(self): method test_cron_has_subcommands (line 351) | def test_cron_has_subcommands(self): method test_commands_without_subcommands_not_in_dict (line 356) | def test_commands_without_subcommands_not_in_dict(self): class TestSubcommandCompletion (line 366) | class TestSubcommandCompletion: method test_subcommand_completion_after_space (line 367) | def test_subcommand_completion_after_space(self): method test_subcommand_prefix_filters (line 374) | def test_subcommand_prefix_filters(self): method test_subcommand_exact_match_suppressed (line 380) | def test_subcommand_exact_match_suppressed(self): method test_no_subcommands_for_plain_command (line 386) | def test_no_subcommands_for_plain_command(self): function _model_completer (line 395) | def _model_completer() -> SlashCommandCompleter: class TestModelCompletion (line 414) | class TestModelCompletion: method test_stage1_shows_providers (line 415) | def test_stage1_shows_providers(self): method test_stage1_current_provider_last (line 422) | def test_stage1_current_provider_last(self): method test_stage1_current_provider_labeled (line 427) | def test_stage1_current_provider_labeled(self): method test_stage1_prefix_filters (line 436) | def test_stage1_prefix_filters(self): method test_stage2_shows_models (line 441) | def test_stage2_shows_models(self): method test_stage2_prefix_filters_models (line 447) | def test_stage2_prefix_filters_models(self): method test_stage2_no_model_provider_returns_empty (line 453) | def test_stage2_no_model_provider_returns_empty(self): function _suggestion (line 461) | def _suggestion(text: str, completer=None) -> str | None: class TestGhostText (line 473) | class TestGhostText: method test_command_name_suggestion (line 474) | def test_command_name_suggestion(self): method test_command_name_suggestion_reasoning (line 478) | def test_command_name_suggestion_reasoning(self): method test_no_suggestion_for_complete_command (line 482) | def test_no_suggestion_for_complete_command(self): method test_subcommand_suggestion (line 485) | def test_subcommand_suggestion(self): method test_subcommand_suggestion_show (line 489) | def test_subcommand_suggestion_show(self): method test_no_suggestion_for_non_slash (line 493) | def test_no_suggestion_for_non_slash(self): method test_model_stage1_ghost_text (line 496) | def test_model_stage1_ghost_text(self): method test_model_stage2_ghost_text (line 501) | def test_model_stage2_ghost_text(self): FILE: tests/hermes_cli/test_config.py class TestGetHermesHome (line 24) | class TestGetHermesHome: method test_default_path (line 25) | def test_default_path(self): method test_env_override (line 31) | def test_env_override(self): class TestEnsureHermesHome (line 37) | class TestEnsureHermesHome: method test_creates_subdirs (line 38) | def test_creates_subdirs(self, tmp_path): method test_creates_default_soul_md_if_missing (line 46) | def test_creates_default_soul_md_if_missing(self, tmp_path): method test_does_not_overwrite_existing_soul_md (line 53) | def test_does_not_overwrite_existing_soul_md(self, tmp_path): class TestLoadConfigDefaults (line 61) | class TestLoadConfigDefaults: method test_returns_defaults_when_no_file (line 62) | def test_returns_defaults_when_no_file(self, tmp_path): method test_legacy_root_level_max_turns_migrates_to_agent_config (line 71) | def test_legacy_root_level_max_turns_migrates_to_agent_config(self, tm... class TestSaveAndLoadRoundtrip (line 81) | class TestSaveAndLoadRoundtrip: method test_roundtrip (line 82) | def test_roundtrip(self, tmp_path): method test_save_config_normalizes_legacy_root_level_max_turns (line 97) | def test_save_config_normalizes_legacy_root_level_max_turns(self, tmp_... method test_nested_values_preserved (line 105) | def test_nested_values_preserved(self, tmp_path): class TestSaveEnvValueSecure (line 115) | class TestSaveEnvValueSecure: method test_save_env_value_writes_without_stdout (line 116) | def test_save_env_value_writes_without_stdout(self, tmp_path, capsys): method test_secure_save_returns_metadata_only (line 126) | def test_secure_save_returns_metadata_only(self, tmp_path): method test_save_env_value_updates_process_environment (line 136) | def test_save_env_value_updates_process_environment(self, tmp_path): method test_save_env_value_hardens_file_permissions_on_posix (line 142) | def test_save_env_value_hardens_file_permissions_on_posix(self, tmp_pa... class TestSaveConfigAtomicity (line 152) | class TestSaveConfigAtomicity: method test_no_partial_write_on_crash (line 155) | def test_no_partial_write_on_crash(self, tmp_path): method test_no_leftover_temp_files (line 179) | def test_no_leftover_temp_files(self, tmp_path): method test_atomic_write_creates_valid_yaml (line 195) | def test_atomic_write_creates_valid_yaml(self, tmp_path): class TestSanitizeEnvLines (line 211) | class TestSanitizeEnvLines: method test_splits_concatenated_keys (line 214) | def test_splits_concatenated_keys(self): method test_preserves_clean_file (line 223) | def test_preserves_clean_file(self): method test_preserves_comments_and_blanks (line 234) | def test_preserves_comments_and_blanks(self): method test_adds_missing_trailing_newline (line 239) | def test_adds_missing_trailing_newline(self): method test_three_concatenated_keys (line 245) | def test_three_concatenated_keys(self): method test_value_with_equals_sign_not_split (line 255) | def test_value_with_equals_sign_not_split(self): method test_unknown_keys_not_split (line 261) | def test_unknown_keys_not_split(self): method test_value_ending_with_digits_still_splits (line 268) | def test_value_ending_with_digits_still_splits(self): method test_save_env_value_fixes_corruption_on_write (line 276) | def test_save_env_value_fixes_corruption_on_write(self, tmp_path): method test_sanitize_env_file_returns_fix_count (line 294) | def test_sanitize_env_file_returns_fix_count(self, tmp_path): method test_sanitize_env_file_noop_on_clean_file (line 310) | def test_sanitize_env_file_noop_on_clean_file(self, tmp_path): class TestOptionalEnvVarsRegistry (line 319) | class TestOptionalEnvVarsRegistry: method test_tavily_api_key_registered (line 322) | def test_tavily_api_key_registered(self): method test_tavily_api_key_is_tool_category (line 327) | def test_tavily_api_key_is_tool_category(self): method test_tavily_api_key_is_password (line 332) | def test_tavily_api_key_is_password(self): method test_tavily_api_key_has_url (line 337) | def test_tavily_api_key_has_url(self): method test_tavily_in_env_vars_by_version (line 342) | def test_tavily_in_env_vars_by_version(self): class TestAnthropicTokenMigration (line 351) | class TestAnthropicTokenMigration: method _write_config_version (line 354) | def _write_config_version(self, tmp_path, version): method test_clears_token_on_upgrade_to_v9 (line 359) | def test_clears_token_on_upgrade_to_v9(self, tmp_path): method test_skips_on_version_9_or_later (line 370) | def test_skips_on_version_9_or_later(self, tmp_path): FILE: tests/hermes_cli/test_copilot_auth.py class TestTokenValidation (line 8) | class TestTokenValidation: method test_classic_pat_rejected (line 11) | def test_classic_pat_rejected(self): method test_oauth_token_accepted (line 18) | def test_oauth_token_accepted(self): method test_fine_grained_pat_accepted (line 23) | def test_fine_grained_pat_accepted(self): method test_github_app_token_accepted (line 28) | def test_github_app_token_accepted(self): method test_empty_token_rejected (line 33) | def test_empty_token_rejected(self): method test_is_classic_pat (line 38) | def test_is_classic_pat(self): class TestResolveToken (line 46) | class TestResolveToken: method test_copilot_github_token_first_priority (line 49) | def test_copilot_github_token_first_priority(self, monkeypatch): method test_gh_token_second_priority (line 58) | def test_gh_token_second_priority(self, monkeypatch): method test_github_token_third_priority (line 67) | def test_github_token_third_priority(self, monkeypatch): method test_classic_pat_in_env_skipped (line 76) | def test_classic_pat_in_env_skipped(self, monkeypatch): method test_gh_cli_fallback (line 87) | def test_gh_cli_fallback(self, monkeypatch): method test_gh_cli_classic_pat_raises (line 97) | def test_gh_cli_classic_pat_raises(self, monkeypatch): method test_no_token_returns_empty (line 106) | def test_no_token_returns_empty(self, monkeypatch): class TestRequestHeaders (line 117) | class TestRequestHeaders: method test_default_headers_include_openai_intent (line 120) | def test_default_headers_include_openai_intent(self): method test_agent_turn_sets_initiator (line 127) | def test_agent_turn_sets_initiator(self): method test_user_turn_sets_initiator (line 132) | def test_user_turn_sets_initiator(self): method test_vision_header (line 137) | def test_vision_header(self): method test_no_vision_header_by_default (line 142) | def test_no_vision_header_by_default(self): class TestCopilotDefaultHeaders (line 148) | class TestCopilotDefaultHeaders: method test_includes_openai_intent (line 151) | def test_includes_openai_intent(self): method test_includes_x_initiator (line 157) | def test_includes_x_initiator(self): class TestApiModeSelection (line 163) | class TestApiModeSelection: method test_gpt5_uses_responses (line 166) | def test_gpt5_uses_responses(self): method test_gpt5_mini_excluded (line 175) | def test_gpt5_mini_excluded(self): method test_gpt4_uses_chat (line 179) | def test_gpt4_uses_chat(self): method test_non_gpt_uses_chat (line 185) | def test_non_gpt_uses_chat(self): class TestEnvVarOrder (line 193) | class TestEnvVarOrder: method test_copilot_env_vars_include_copilot_github_token (line 196) | def test_copilot_env_vars_include_copilot_github_token(self): method test_copilot_env_vars_order_matches_docs (line 203) | def test_copilot_env_vars_order_matches_docs(self): FILE: tests/hermes_cli/test_cron.py function tmp_cron_dir (line 12) | def tmp_cron_dir(tmp_path, monkeypatch): class TestCronCommandLifecycle (line 19) | class TestCronCommandLifecycle: method test_pause_resume_run (line 20) | def test_pause_resume_run(self, tmp_cron_dir, capsys): method test_edit_can_replace_and_clear_skills (line 40) | def test_edit_can_replace_and_clear_skills(self, tmp_cron_dir, capsys): method test_create_with_multiple_skills (line 88) | def test_create_with_multiple_skills(self, tmp_cron_dir, capsys): FILE: tests/hermes_cli/test_doctor.py class TestProviderEnvDetection (line 17) | class TestProviderEnvDetection: method test_detects_openai_api_key (line 18) | def test_detects_openai_api_key(self): method test_detects_custom_endpoint_without_openrouter_key (line 22) | def test_detects_custom_endpoint_without_openrouter_key(self): method test_returns_false_when_no_provider_settings (line 26) | def test_returns_false_when_no_provider_settings(self): class TestDoctorToolAvailabilityOverrides (line 31) | class TestDoctorToolAvailabilityOverrides: method test_marks_honcho_available_when_configured (line 32) | def test_marks_honcho_available_when_configured(self, monkeypatch): method test_leaves_honcho_unavailable_when_not_configured (line 43) | def test_leaves_honcho_unavailable_when_not_configured(self, monkeypat... class TestHonchoDoctorConfigDetection (line 56) | class TestHonchoDoctorConfigDetection: method test_reports_configured_when_enabled_with_api_key (line 57) | def test_reports_configured_when_enabled_with_api_key(self, monkeypatch): method test_reports_not_configured_without_api_key (line 67) | def test_reports_not_configured_without_api_key(self, monkeypatch): function test_run_doctor_sets_interactive_env_for_tool_checks (line 78) | def test_run_doctor_sets_interactive_env_for_tool_checks(monkeypatch, tm... function test_check_gateway_service_linger_warns_when_disabled (line 107) | def test_check_gateway_service_linger_warns_when_disabled(monkeypatch, t... function test_check_gateway_service_linger_skips_when_service_not_installed (line 127) | def test_check_gateway_service_linger_skips_when_service_not_installed(m... FILE: tests/hermes_cli/test_env_loader.py function test_user_env_overrides_stale_shell_values (line 9) | def test_user_env_overrides_stale_shell_values(tmp_path, monkeypatch): function test_project_env_overrides_stale_shell_values_when_user_env_missing (line 23) | def test_project_env_overrides_stale_shell_values_when_user_env_missing(... function test_user_env_takes_precedence_over_project_env (line 36) | def test_user_env_takes_precedence_over_project_env(tmp_path, monkeypatch): function test_main_import_applies_user_env_over_shell_values (line 54) | def test_main_import_applies_user_env_over_shell_values(tmp_path, monkey... FILE: tests/hermes_cli/test_gateway.py class TestSystemdLingerStatus (line 10) | class TestSystemdLingerStatus: method test_reports_enabled (line 11) | def test_reports_enabled(self, monkeypatch): method test_reports_disabled (line 23) | def test_reports_disabled(self, monkeypatch): function test_systemd_status_warns_when_linger_disabled (line 36) | def test_systemd_status_warns_when_linger_disabled(monkeypatch, tmp_path... function test_systemd_install_checks_linger_status (line 60) | def test_systemd_install_checks_linger_status(monkeypatch, tmp_path, cap... function test_systemd_install_system_scope_skips_linger_and_uses_systemctl (line 87) | def test_systemd_install_system_scope_skips_linger_and_uses_systemctl(mo... function test_conflicting_systemd_units_warning (line 122) | def test_conflicting_systemd_units_warning(monkeypatch, tmp_path, capsys): function test_install_linux_gateway_from_setup_system_choice_without_root_prints_followup (line 144) | def test_install_linux_gateway_from_setup_system_choice_without_root_pri... function test_install_linux_gateway_from_setup_system_choice_as_root_installs (line 158) | def test_install_linux_gateway_from_setup_system_choice_as_root_installs... class TestWaitForGatewayExit (line 181) | class TestWaitForGatewayExit: method test_returns_immediately_when_no_pid (line 184) | def test_returns_immediately_when_no_pid(self, monkeypatch): method test_returns_when_process_exits_gracefully (line 190) | def test_returns_when_process_exits_gracefully(self, monkeypatch): method test_force_kills_after_grace_period (line 206) | def test_force_kills_after_grace_period(self, monkeypatch): method test_handles_process_already_gone_on_kill (line 235) | def test_handles_process_already_gone_on_kill(self, monkeypatch): FILE: tests/hermes_cli/test_gateway_linger.py class TestEnsureLingerEnabled (line 8) | class TestEnsureLingerEnabled: method test_linger_already_enabled_via_file (line 9) | def test_linger_already_enabled_via_file(self, monkeypatch, capsys): method test_status_enabled_skips_enable (line 23) | def test_status_enabled_skips_enable(self, monkeypatch, capsys): method test_loginctl_success_enables_linger (line 38) | def test_loginctl_success_enables_linger(self, monkeypatch, capsys): method test_missing_loginctl_shows_manual_guidance (line 60) | def test_missing_loginctl_shows_manual_guidance(self, monkeypatch, cap... method test_loginctl_failure_shows_manual_guidance (line 77) | def test_loginctl_failure_shows_manual_guidance(self, monkeypatch, cap... function test_systemd_install_calls_linger_helper (line 96) | def test_systemd_install_calls_linger_helper(monkeypatch, tmp_path, caps... FILE: tests/hermes_cli/test_gateway_runtime_health.py function test_runtime_health_lines_include_fatal_platform_and_startup_reason (line 4) | def test_runtime_health_lines_include_fatal_platform_and_startup_reason(... FILE: tests/hermes_cli/test_gateway_service.py class TestSystemdServiceRefresh (line 9) | class TestSystemdServiceRefresh: method test_systemd_install_repairs_outdated_unit_without_force (line 10) | def test_systemd_install_repairs_outdated_unit_without_force(self, tmp... method test_systemd_start_refreshes_outdated_unit (line 33) | def test_systemd_start_refreshes_outdated_unit(self, tmp_path, monkeyp... method test_systemd_restart_refreshes_outdated_unit (line 56) | def test_systemd_restart_refreshes_outdated_unit(self, tmp_path, monke... class TestGeneratedSystemdUnits (line 80) | class TestGeneratedSystemdUnits: method test_user_unit_avoids_recursive_execstop_and_uses_extended_stop_timeout (line 81) | def test_user_unit_avoids_recursive_execstop_and_uses_extended_stop_ti... method test_user_unit_includes_resolved_node_directory_in_path (line 88) | def test_user_unit_includes_resolved_node_directory_in_path(self, monk... method test_system_unit_avoids_recursive_execstop_and_uses_extended_stop_timeout (line 95) | def test_system_unit_avoids_recursive_execstop_and_uses_extended_stop_... class TestGatewayStopCleanup (line 104) | class TestGatewayStopCleanup: method test_stop_sweeps_manual_gateway_processes_after_service_stop (line 105) | def test_stop_sweeps_manual_gateway_processes_after_service_stop(self,... class TestLaunchdServiceRecovery (line 129) | class TestLaunchdServiceRecovery: method test_launchd_install_repairs_outdated_plist_without_force (line 130) | def test_launchd_install_repairs_outdated_plist_without_force(self, tm... method test_launchd_start_reloads_unloaded_job_and_retries (line 152) | def test_launchd_start_reloads_unloaded_job_and_retries(self, tmp_path... method test_launchd_status_reports_local_stale_plist_when_unloaded (line 175) | def test_launchd_status_reports_local_stale_plist_when_unloaded(self, ... class TestGatewayServiceDetection (line 194) | class TestGatewayServiceDetection: method test_is_service_running_checks_system_scope_when_user_scope_is_inactive (line 195) | def test_is_service_running_checks_system_scope_when_user_scope_is_ina... class TestGatewaySystemServiceRouting (line 219) | class TestGatewaySystemServiceRouting: method test_gateway_install_passes_system_flags (line 220) | def test_gateway_install_passes_system_flags(self, monkeypatch): method test_gateway_status_prefers_system_service_when_only_system_unit_exists (line 237) | def test_gateway_status_prefers_system_service_when_only_system_unit_e... method test_gateway_restart_does_not_fallback_to_foreground_when_launchd_restart_fails (line 256) | def test_gateway_restart_does_not_fallback_to_foreground_when_launchd_... class TestEnsureUserSystemdEnv (line 285) | class TestEnsureUserSystemdEnv: method test_sets_xdg_runtime_dir_when_missing (line 288) | def test_sets_xdg_runtime_dir_when_missing(self, tmp_path, monkeypatch): method test_sets_dbus_address_when_bus_socket_exists (line 310) | def test_sets_dbus_address_when_bus_socket_exists(self, tmp_path, monk... method test_preserves_existing_env_vars (line 324) | def test_preserves_existing_env_vars(self, monkeypatch): method test_no_dbus_when_bus_socket_missing (line 333) | def test_no_dbus_when_bus_socket_missing(self, tmp_path, monkeypatch): method test_systemctl_cmd_calls_ensure_for_user_mode (line 346) | def test_systemctl_cmd_calls_ensure_for_user_mode(self, monkeypatch): method test_systemctl_cmd_skips_ensure_for_system_mode (line 354) | def test_systemctl_cmd_skips_ensure_for_system_mode(self, monkeypatch): FILE: tests/hermes_cli/test_mcp_tools_config.py function test_no_mcp_servers_prints_info (line 14) | def test_no_mcp_servers_prints_info(capsys): function test_all_servers_disabled_prints_info (line 22) | def test_all_servers_disabled_prints_info(capsys): function test_probe_failure_shows_warning (line 35) | def test_probe_failure_shows_warning(capsys): function test_probe_exception_shows_error (line 44) | def test_probe_exception_shows_error(capsys): function test_no_changes_when_checklist_cancelled (line 53) | def test_no_changes_when_checklist_cancelled(capsys): function test_disabling_tool_writes_exclude_list (line 71) | def test_disabling_tool_writes_exclude_list(capsys): function test_enabling_all_clears_filters (line 96) | def test_enabling_all_clears_filters(capsys): function test_pre_selection_respects_existing_exclude (line 121) | def test_pre_selection_respects_existing_exclude(capsys): function test_pre_selection_respects_existing_include (line 147) | def test_pre_selection_respects_existing_include(capsys): function test_multiple_servers_each_get_checklist (line 173) | def test_multiple_servers_each_get_checklist(capsys): function test_failed_server_shows_warning (line 202) | def test_failed_server_shows_warning(capsys): function test_description_truncation_in_labels (line 222) | def test_description_truncation_in_labels(): function test_switching_from_include_to_exclude (line 247) | def test_switching_from_include_to_exclude(capsys): function test_empty_tools_server_skipped (line 271) | def test_empty_tools_server_skipped(capsys): FILE: tests/hermes_cli/test_model_validation.py function _validate (line 32) | def _validate(model, provider="openrouter", api_models=FAKE_API_MODELS, ... class TestParseModelInput (line 48) | class TestParseModelInput: method test_plain_model_keeps_current_provider (line 49) | def test_plain_model_keeps_current_provider(self): method test_provider_colon_model_switches_provider (line 54) | def test_provider_colon_model_switches_provider(self): method test_provider_alias_resolved (line 59) | def test_provider_alias_resolved(self): method test_no_slash_no_colon_keeps_provider (line 64) | def test_no_slash_no_colon_keeps_provider(self): method test_nous_provider_switch (line 69) | def test_nous_provider_switch(self): method test_empty_model_after_colon_keeps_current (line 74) | def test_empty_model_after_colon_keeps_current(self): method test_colon_at_start_keeps_current (line 79) | def test_colon_at_start_keeps_current(self): method test_unknown_prefix_colon_not_treated_as_provider (line 84) | def test_unknown_prefix_colon_not_treated_as_provider(self): method test_http_url_not_treated_as_provider (line 90) | def test_http_url_not_treated_as_provider(self): class TestCuratedModelsForProvider (line 98) | class TestCuratedModelsForProvider: method test_openrouter_returns_curated_list (line 99) | def test_openrouter_returns_curated_list(self): method test_zai_returns_glm_models (line 104) | def test_zai_returns_glm_models(self): method test_unknown_provider_returns_empty (line 108) | def test_unknown_provider_returns_empty(self): class TestNormalizeProvider (line 114) | class TestNormalizeProvider: method test_defaults_to_openrouter (line 115) | def test_defaults_to_openrouter(self): method test_known_aliases (line 119) | def test_known_aliases(self): method test_case_insensitive (line 125) | def test_case_insensitive(self): class TestProviderLabel (line 129) | class TestProviderLabel: method test_known_labels_and_auto (line 130) | def test_known_labels_and_auto(self): method test_unknown_provider_preserves_original_name (line 137) | def test_unknown_provider_preserves_original_name(self): class TestProviderModelIds (line 143) | class TestProviderModelIds: method test_openrouter_returns_curated_list (line 144) | def test_openrouter_returns_curated_list(self): method test_unknown_provider_returns_empty (line 149) | def test_unknown_provider_returns_empty(self): method test_zai_returns_glm_models (line 152) | def test_zai_returns_glm_models(self): method test_copilot_prefers_live_catalog (line 155) | def test_copilot_prefers_live_catalog(self): method test_copilot_acp_reuses_copilot_catalog (line 160) | def test_copilot_acp_reuses_copilot_catalog(self): method test_copilot_acp_falls_back_to_copilot_defaults (line 165) | def test_copilot_acp_falls_back_to_copilot_defaults(self): class TestFetchApiModels (line 176) | class TestFetchApiModels: method test_returns_none_when_no_base_url (line 177) | def test_returns_none_when_no_base_url(self): method test_returns_none_on_network_error (line 180) | def test_returns_none_on_network_error(self): method test_probe_api_models_tries_v1_fallback (line 184) | def test_probe_api_models_tries_v1_fallback(self): method test_probe_api_models_uses_copilot_catalog (line 211) | def test_probe_api_models_uses_copilot_catalog(self): method test_fetch_github_model_catalog_filters_non_chat_models (line 230) | def test_fetch_github_model_catalog_filters_non_chat_models(self): class TestGithubReasoningEfforts (line 248) | class TestGithubReasoningEfforts: method test_gpt5_supports_minimal_to_high (line 249) | def test_gpt5_supports_minimal_to_high(self): method test_legacy_catalog_reasoning_still_supported (line 261) | def test_legacy_catalog_reasoning_still_supported(self): method test_non_reasoning_model_returns_empty (line 269) | def test_non_reasoning_model_returns_empty(self): class TestCopilotNormalization (line 274) | class TestCopilotNormalization: method test_normalize_old_github_models_slug (line 275) | def test_normalize_old_github_models_slug(self): method test_copilot_api_mode_gpt5_uses_responses (line 279) | def test_copilot_api_mode_gpt5_uses_responses(self): method test_copilot_api_mode_gpt5_mini_uses_chat (line 287) | def test_copilot_api_mode_gpt5_mini_uses_chat(self): method test_copilot_api_mode_non_gpt5_uses_chat (line 291) | def test_copilot_api_mode_non_gpt5_uses_chat(self): method test_copilot_api_mode_with_catalog_both_endpoints (line 300) | def test_copilot_api_mode_with_catalog_both_endpoints(self): method test_copilot_api_mode_with_catalog_only_responses (line 309) | def test_copilot_api_mode_with_catalog_only_responses(self): class TestValidateFormatChecks (line 320) | class TestValidateFormatChecks: method test_empty_model_rejected (line 321) | def test_empty_model_rejected(self): method test_whitespace_only_rejected (line 326) | def test_whitespace_only_rejected(self): method test_model_with_spaces_rejected (line 330) | def test_model_with_spaces_rejected(self): method test_no_slash_model_still_probes_api (line 334) | def test_no_slash_model_still_probes_api(self): method test_no_slash_model_rejected_if_not_in_api (line 339) | def test_no_slash_model_rejected_if_not_in_api(self): class TestValidateApiFound (line 347) | class TestValidateApiFound: method test_model_found_in_api (line 348) | def test_model_found_in_api(self): method test_model_found_for_custom_endpoint (line 354) | def test_model_found_for_custom_endpoint(self): class TestValidateApiNotFound (line 366) | class TestValidateApiNotFound: method test_model_not_in_api_accepted_with_warning (line 367) | def test_model_not_in_api_accepted_with_warning(self): method test_warning_includes_suggestions (line 373) | def test_warning_includes_suggestions(self): class TestValidateApiFallback (line 381) | class TestValidateApiFallback: method test_any_model_accepted_when_api_down (line 382) | def test_any_model_accepted_when_api_down(self): method test_unknown_model_also_accepted_when_api_down (line 387) | def test_unknown_model_also_accepted_when_api_down(self): method test_zai_model_accepted_when_api_down (line 394) | def test_zai_model_accepted_when_api_down(self): method test_unknown_provider_accepted_when_api_down (line 399) | def test_unknown_provider_accepted_when_api_down(self): method test_custom_endpoint_warns_with_probed_url_and_v1_hint (line 404) | def test_custom_endpoint_warns_with_probed_url_and_v1_hint(self): FILE: tests/hermes_cli/test_models.py class TestModelIds (line 6) | class TestModelIds: method test_returns_non_empty_list (line 7) | def test_returns_non_empty_list(self): method test_ids_match_models_list (line 12) | def test_ids_match_models_list(self): method test_all_ids_contain_provider_slash (line 17) | def test_all_ids_contain_provider_slash(self): method test_no_duplicate_ids (line 22) | def test_no_duplicate_ids(self): class TestMenuLabels (line 27) | class TestMenuLabels: method test_same_length_as_model_ids (line 28) | def test_same_length_as_model_ids(self): method test_first_label_marked_recommended (line 31) | def test_first_label_marked_recommended(self): method test_each_label_contains_its_model_id (line 35) | def test_each_label_contains_its_model_id(self): method test_non_recommended_labels_have_no_tag (line 39) | def test_non_recommended_labels_have_no_tag(self): class TestOpenRouterModels (line 46) | class TestOpenRouterModels: method test_structure_is_list_of_tuples (line 47) | def test_structure_is_list_of_tuples(self): method test_at_least_5_models (line 54) | def test_at_least_5_models(self): class TestFindOpenrouterSlug (line 59) | class TestFindOpenrouterSlug: method test_exact_match (line 60) | def test_exact_match(self): method test_bare_name_match (line 64) | def test_bare_name_match(self): method test_case_insensitive (line 69) | def test_case_insensitive(self): method test_unknown_returns_none (line 74) | def test_unknown_returns_none(self): class TestDetectProviderForModel (line 79) | class TestDetectProviderForModel: method test_anthropic_model_detected (line 80) | def test_anthropic_model_detected(self): method test_deepseek_model_detected (line 86) | def test_deepseek_model_detected(self): method test_current_provider_model_returns_none (line 93) | def test_current_provider_model_returns_none(self): method test_openrouter_slug_match (line 97) | def test_openrouter_slug_match(self): method test_bare_name_gets_openrouter_slug (line 104) | def test_bare_name_gets_openrouter_slug(self): method test_unknown_model_returns_none (line 111) | def test_unknown_model_returns_none(self): method test_aggregator_not_suggested (line 115) | def test_aggregator_not_suggested(self): FILE: tests/hermes_cli/test_path_completion.py function _display_names (line 13) | def _display_names(completions): function _display_metas (line 18) | def _display_metas(completions): function completer (line 24) | def completer(): class TestExtractPathWord (line 28) | class TestExtractPathWord: method test_relative_path (line 29) | def test_relative_path(self): method test_home_path (line 32) | def test_home_path(self): method test_absolute_path (line 35) | def test_absolute_path(self): method test_parent_path (line 38) | def test_parent_path(self): method test_path_with_slash_in_middle (line 41) | def test_path_with_slash_in_middle(self): method test_plain_word_not_path (line 44) | def test_plain_word_not_path(self): method test_empty_string (line 47) | def test_empty_string(self): method test_single_word_no_slash (line 50) | def test_single_word_no_slash(self): method test_word_after_space (line 53) | def test_word_after_space(self): method test_just_dot_slash (line 56) | def test_just_dot_slash(self): method test_just_tilde_slash (line 59) | def test_just_tilde_slash(self): class TestPathCompletions (line 63) | class TestPathCompletions: method test_lists_current_directory (line 64) | def test_lists_current_directory(self, tmp_path): method test_filters_by_prefix (line 80) | def test_filters_by_prefix(self, tmp_path): method test_directories_have_trailing_slash (line 91) | def test_directories_have_trailing_slash(self, tmp_path): method test_home_expansion (line 102) | def test_home_expansion(self, tmp_path, monkeypatch): method test_nonexistent_dir_returns_empty (line 110) | def test_nonexistent_dir_returns_empty(self): method test_respects_limit (line 114) | def test_respects_limit(self, tmp_path): method test_case_insensitive_prefix (line 121) | def test_case_insensitive_prefix(self, tmp_path): class TestIntegration (line 129) | class TestIntegration: method test_slash_commands_still_work (line 132) | def test_slash_commands_still_work(self, completer): method test_path_completion_triggers_on_dot_slash (line 139) | def test_path_completion_triggers_on_dot_slash(self, completer, tmp_pa... method test_no_completion_for_plain_words (line 152) | def test_no_completion_for_plain_words(self, completer): method test_absolute_path_triggers_completion (line 158) | def test_absolute_path_triggers_completion(self, completer): class TestFileSizeLabel (line 167) | class TestFileSizeLabel: method test_bytes (line 168) | def test_bytes(self, tmp_path): method test_kilobytes (line 173) | def test_kilobytes(self, tmp_path): method test_megabytes (line 178) | def test_megabytes(self, tmp_path): method test_nonexistent (line 183) | def test_nonexistent(self): FILE: tests/hermes_cli/test_placeholder_usage.py function test_config_set_usage_marks_placeholders (line 13) | def test_config_set_usage_marks_placeholders(capsys): function test_config_unknown_command_help_marks_placeholders (line 24) | def test_config_unknown_command_help_marks_placeholders(capsys): function test_show_config_marks_placeholders (line 35) | def test_show_config_marks_placeholders(tmp_path, capsys): function test_setup_summary_marks_placeholders (line 43) | def test_setup_summary_marks_placeholders(tmp_path, capsys): FILE: tests/hermes_cli/test_session_browse.py function _make_sessions (line 20) | def _make_sessions(n=5): class TestSessionBrowsePicker (line 43) | class TestSessionBrowsePicker: method test_empty_sessions_returns_none (line 46) | def test_empty_sessions_returns_none(self, capsys): method test_returns_none_when_no_sessions (line 51) | def test_returns_none_when_no_sessions(self, capsys): method test_fallback_mode_valid_selection (line 55) | def test_fallback_mode_valid_selection(self): method test_fallback_mode_cancel_q (line 74) | def test_fallback_mode_cancel_q(self): method test_fallback_mode_cancel_empty (line 92) | def test_fallback_mode_cancel_empty(self): method test_fallback_mode_invalid_then_valid (line 110) | def test_fallback_mode_invalid_then_valid(self): method test_fallback_mode_keyboard_interrupt (line 128) | def test_fallback_mode_keyboard_interrupt(self): method test_fallback_displays_all_sessions (line 146) | def test_fallback_displays_all_sessions(self, capsys): method test_fallback_shows_title_over_preview (line 169) | def test_fallback_shows_title_over_preview(self, capsys): method test_fallback_shows_preview_when_no_title (line 194) | def test_fallback_shows_preview_when_no_title(self, capsys): method test_fallback_shows_id_when_no_title_or_preview (line 219) | def test_fallback_shows_id_when_no_title_or_preview(self, capsys): class TestCursesBrowse (line 247) | class TestCursesBrowse: method _run_with_keys (line 250) | def _run_with_keys(self, sessions, key_sequence): method test_enter_selects_first_session (line 273) | def test_enter_selects_first_session(self): method test_down_then_enter_selects_second (line 278) | def test_down_then_enter_selects_second(self): method test_down_down_enter_selects_third (line 284) | def test_down_down_enter_selects_third(self): method test_up_wraps_to_last (line 290) | def test_up_wraps_to_last(self): method test_escape_cancels (line 296) | def test_escape_cancels(self): method test_q_cancels (line 301) | def test_q_cancels(self): method test_type_to_filter_then_enter (line 306) | def test_type_to_filter_then_enter(self): method test_filter_no_match_enter_does_nothing (line 319) | def test_filter_no_match_enter_does_nothing(self): method test_backspace_removes_filter_char (line 326) | def test_backspace_removes_filter_char(self): method test_escape_clears_filter_first (line 338) | def test_escape_clears_filter_first(self): method test_filter_matches_preview (line 347) | def test_filter_matches_preview(self): method test_filter_matches_source (line 357) | def test_filter_matches_source(self): method test_q_quits_when_no_filter_active (line 367) | def test_q_quits_when_no_filter_active(self): method test_q_types_into_filter_when_filter_active (line 373) | def test_q_types_into_filter_when_filter_active(self): class TestSessionBrowseArgparse (line 389) | class TestSessionBrowseArgparse: method test_browse_subcommand_exists (line 392) | def test_browse_subcommand_exists(self): method test_browse_default_limit_is_50 (line 404) | def test_browse_default_limit_is_50(self): class TestCmdSessionsBrowse (line 416) | class TestCmdSessionsBrowse: method test_browse_no_sessions_prints_message (line 419) | def test_browse_no_sessions_prints_message(self, capsys): method test_browse_with_source_filter (line 426) | def test_browse_with_source_filter(self): class TestEdgeCases (line 449) | class TestEdgeCases: method test_sessions_with_missing_fields (line 452) | def test_sessions_with_missing_fields(self): method test_single_session (line 472) | def test_single_session(self): method test_long_title_truncated_in_fallback (line 492) | def test_long_title_truncated_in_fallback(self, capsys): method test_relative_time_formatting (line 518) | def test_relative_time_formatting(self, capsys): FILE: tests/hermes_cli/test_sessions_delete.py function test_sessions_delete_accepts_unique_id_prefix (line 4) | def test_sessions_delete_accepts_unique_id_prefix(monkeypatch, capsys): function test_sessions_delete_reports_not_found_when_prefix_is_unknown (line 40) | def test_sessions_delete_reports_not_found_when_prefix_is_unknown(monkey... FILE: tests/hermes_cli/test_set_config_value.py function _isolated_hermes_home (line 13) | def _isolated_hermes_home(tmp_path): function _read_env (line 21) | def _read_env(tmp_path): function _read_config (line 25) | def _read_config(tmp_path): class TestExplicitAllowlist (line 34) | class TestExplicitAllowlist: method test_explicit_key_routes_to_env (line 54) | def test_explicit_key_routes_to_env(self, key, _isolated_hermes_home): class TestCatchAllPatterns (line 66) | class TestCatchAllPatterns: method test_api_key_suffix_routes_to_env (line 76) | def test_api_key_suffix_routes_to_env(self, key, _isolated_hermes_home): method test_case_insensitive (line 82) | def test_case_insensitive(self, _isolated_hermes_home): method test_terminal_ssh_prefix_routes_to_env (line 88) | def test_terminal_ssh_prefix_routes_to_env(self, _isolated_hermes_home): class TestConfigYamlRouting (line 98) | class TestConfigYamlRouting: method test_simple_key (line 101) | def test_simple_key(self, _isolated_hermes_home): method test_nested_key (line 107) | def test_nested_key(self, _isolated_hermes_home): method test_terminal_image_goes_to_config (line 113) | def test_terminal_image_goes_to_config(self, _isolated_hermes_home): method test_terminal_docker_cwd_mount_flag_goes_to_config_and_env (line 119) | def test_terminal_docker_cwd_mount_flag_goes_to_config_and_env(self, _... FILE: tests/hermes_cli/test_setup.py function _maybe_keep_current_tts (line 8) | def _maybe_keep_current_tts(question, choices): function _clear_provider_env (line 15) | def _clear_provider_env(monkeypatch): function test_nous_oauth_setup_keeps_current_model_when_syncing_disk_provider (line 27) | def test_nous_oauth_setup_keeps_current_model_when_syncing_disk_provider( function test_custom_setup_clears_active_oauth_provider (line 81) | def test_custom_setup_clears_active_oauth_provider(tmp_path, monkeypatch): function test_codex_setup_uses_runtime_access_token_for_live_model_list (line 128) | def test_codex_setup_uses_runtime_access_token_for_live_model_list(tmp_p... FILE: tests/hermes_cli/test_setup_model_provider.py function _maybe_keep_current_tts (line 9) | def _maybe_keep_current_tts(question, choices): function _read_env (line 16) | def _read_env(home): function _clear_provider_env (line 29) | def _clear_provider_env(monkeypatch): function test_setup_keep_current_custom_from_config_does_not_fall_through (line 47) | def test_setup_keep_current_custom_from_config_does_not_fall_through(tmp... function test_setup_custom_endpoint_saves_working_v1_base_url (line 86) | def test_setup_custom_endpoint_saves_working_v1_base_url(tmp_path, monke... function test_setup_keep_current_config_provider_uses_provider_specific_model_menu (line 144) | def test_setup_keep_current_config_provider_uses_provider_specific_model... function test_setup_keep_current_anthropic_can_configure_openai_vision_default (line 192) | def test_setup_keep_current_anthropic_can_configure_openai_vision_defaul... function test_setup_copilot_uses_gh_auth_and_saves_provider (line 239) | def test_setup_copilot_uses_gh_auth_and_saves_provider(tmp_path, monkeyp... function test_setup_copilot_acp_uses_model_picker_and_saves_provider (line 318) | def test_setup_copilot_acp_uses_model_picker_and_saves_provider(tmp_path... function test_setup_switch_custom_to_codex_clears_custom_endpoint_and_updates_config (line 385) | def test_setup_switch_custom_to_codex_clears_custom_endpoint_and_updates... function test_setup_summary_marks_codex_auth_as_vision_available (line 443) | def test_setup_summary_marks_codex_auth_as_vision_available(tmp_path, mo... function test_setup_summary_marks_anthropic_auth_as_vision_available (line 462) | def test_setup_summary_marks_anthropic_auth_as_vision_available(tmp_path... FILE: tests/hermes_cli/test_setup_noninteractive.py function _make_setup_args (line 9) | def _make_setup_args(**overrides): function _make_chat_args (line 17) | def _make_chat_args(**overrides): class TestNonInteractiveSetup (line 34) | class TestNonInteractiveSetup: method test_non_interactive_flag_skips_wizard (line 37) | def test_non_interactive_flag_skips_wizard(self, capsys): method test_no_tty_skips_wizard (line 55) | def test_no_tty_skips_wizard(self, capsys): method test_chat_first_run_headless_skips_setup_prompt (line 75) | def test_chat_first_run_headless_skips_setup_prompt(self, capsys): FILE: tests/hermes_cli/test_setup_openclaw_migration.py class TestOfferOpenclawMigration (line 15) | class TestOfferOpenclawMigration: method test_skips_when_no_openclaw_dir (line 18) | def test_skips_when_no_openclaw_dir(self, tmp_path): method test_skips_when_migration_script_missing (line 23) | def test_skips_when_migration_script_missing(self, tmp_path): method test_skips_when_user_declines (line 33) | def test_skips_when_user_declines(self, tmp_path): method test_runs_migration_when_user_accepts (line 46) | def test_runs_migration_when_user_accepts(self, tmp_path): method test_handles_migration_error_gracefully (line 102) | def test_handles_migration_error_gracefully(self, tmp_path): method test_creates_config_if_missing (line 128) | def test_creates_config_if_missing(self, tmp_path): function _first_time_args (line 163) | def _first_time_args() -> Namespace: class TestSetupWizardOpenclawIntegration (line 171) | class TestSetupWizardOpenclawIntegration: method test_migration_offered_during_first_time_setup (line 174) | def test_migration_offered_during_first_time_setup(self, tmp_path): method test_migration_reloads_config_on_success (line 204) | def test_migration_reloads_config_on_success(self, tmp_path): method test_reloaded_config_flows_into_remaining_setup_sections (line 235) | def test_reloaded_config_flows_into_remaining_setup_sections(self, tmp... method test_migration_not_offered_for_existing_install (line 265) | def test_migration_not_offered_for_existing_install(self, tmp_path): FILE: tests/hermes_cli/test_setup_prompt_menus.py function test_prompt_choice_uses_curses_helper (line 4) | def test_prompt_choice_uses_curses_helper(monkeypatch): function test_prompt_choice_falls_back_to_numbered_input (line 12) | def test_prompt_choice_falls_back_to_numbered_input(monkeypatch): function test_prompt_checklist_uses_shared_curses_checklist (line 21) | def test_prompt_checklist_uses_shared_curses_checklist(monkeypatch): FILE: tests/hermes_cli/test_skills_config.py class TestGetDisabledSkills (line 10) | class TestGetDisabledSkills: method test_empty_config (line 11) | def test_empty_config(self): method test_reads_global_disabled (line 15) | def test_reads_global_disabled(self): method test_reads_platform_disabled (line 20) | def test_reads_platform_disabled(self): method test_platform_falls_back_to_global (line 28) | def test_platform_falls_back_to_global(self): method test_missing_skills_key (line 34) | def test_missing_skills_key(self): method test_empty_disabled_list (line 38) | def test_empty_disabled_list(self): class TestSaveDisabledSkills (line 47) | class TestSaveDisabledSkills: method test_saves_global_sorted (line 49) | def test_saves_global_sorted(self, mock_save): method test_saves_platform_disabled (line 57) | def test_saves_platform_disabled(self, mock_save): method test_saves_empty (line 64) | def test_saves_empty(self, mock_save): method test_creates_skills_key (line 71) | def test_creates_skills_key(self, mock_save): class TestIsSkillDisabled (line 83) | class TestIsSkillDisabled: method test_globally_disabled (line 85) | def test_globally_disabled(self, mock_load): method test_globally_enabled (line 91) | def test_globally_enabled(self, mock_load): method test_platform_disabled (line 97) | def test_platform_disabled(self, mock_load): method test_platform_enabled_overrides_global (line 106) | def test_platform_enabled_overrides_global(self, mock_load): method test_platform_falls_back_to_global (line 116) | def test_platform_falls_back_to_global(self, mock_load): method test_empty_config (line 123) | def test_empty_config(self, mock_load): method test_exception_returns_false (line 129) | def test_exception_returns_false(self, mock_load): method test_env_var_platform (line 136) | def test_env_var_platform(self, mock_load): class TestFindAllSkillsFiltering (line 148) | class TestFindAllSkillsFiltering: method test_disabled_skill_excluded (line 152) | def test_disabled_skill_excluded(self, mock_dir, mock_platform, mock_d... method test_enabled_skill_included (line 166) | def test_enabled_skill_included(self, mock_dir, mock_platform, mock_di... method test_skip_disabled_returns_all (line 180) | def test_skip_disabled_returns_all(self, mock_dir, mock_platform, mock... class TestGetCategories (line 197) | class TestGetCategories: method test_extracts_unique_categories (line 198) | def test_extracts_unique_categories(self): method test_none_becomes_uncategorized (line 208) | def test_none_becomes_uncategorized(self): FILE: tests/hermes_cli/test_skills_hub.py class _DummyLockFile (line 9) | class _DummyLockFile: method __init__ (line 10) | def __init__(self, installed): method list_installed (line 13) | def list_installed(self): function hub_env (line 18) | def hub_env(monkeypatch, tmp_path): function three_source_env (line 50) | def three_source_env(monkeypatch, hub_env): function _capture (line 63) | def _capture(source_filter: str = "all") -> str: function _capture_check (line 71) | def _capture_check(monkeypatch, results, name=None) -> str: function _capture_update (line 81) | def _capture_update(monkeypatch, results) -> tuple[str, list[tuple[str, ... function test_do_list_initializes_hub_dir (line 104) | def test_do_list_initializes_hub_dir(monkeypatch, hub_env): function test_do_list_distinguishes_hub_builtin_and_local (line 122) | def test_do_list_distinguishes_hub_builtin_and_local(three_source_env): function test_do_list_filter_local (line 131) | def test_do_list_filter_local(three_source_env): function test_do_list_filter_hub (line 139) | def test_do_list_filter_hub(three_source_env): function test_do_list_filter_builtin (line 147) | def test_do_list_filter_builtin(three_source_env): function test_do_check_reports_available_updates (line 155) | def test_do_check_reports_available_updates(monkeypatch): function test_do_check_handles_no_installed_updates (line 166) | def test_do_check_handles_no_installed_updates(monkeypatch): function test_do_update_reinstalls_outdated_skills (line 172) | def test_do_update_reinstalls_outdated_skills(monkeypatch): FILE: tests/hermes_cli/test_skills_install_flags.py function test_cli_skills_install_yes_sets_skip_confirm (line 14) | def test_cli_skills_install_yes_sets_skip_confirm(monkeypatch): function test_cli_skills_install_y_alias (line 39) | def test_cli_skills_install_y_alias(monkeypatch): function test_cli_skills_install_force_sets_force (line 62) | def test_cli_skills_install_force_sets_force(monkeypatch): function test_cli_skills_install_force_and_yes_together (line 85) | def test_cli_skills_install_force_and_yes_together(monkeypatch): function test_cli_skills_install_no_flags (line 108) | def test_cli_skills_install_no_flags(monkeypatch): FILE: tests/hermes_cli/test_skills_skip_confirm.py class TestHandleSkillsSlashInstallFlags (line 15) | class TestHandleSkillsSlashInstallFlags: method test_yes_flag_sets_skip_confirm (line 18) | def test_yes_flag_sets_skip_confirm(self): method test_y_flag_sets_skip_confirm (line 27) | def test_y_flag_sets_skip_confirm(self): method test_force_flag_sets_force_not_skip (line 35) | def test_force_flag_sets_force_not_skip(self): method test_no_flags (line 44) | def test_no_flags(self): class TestHandleSkillsSlashUninstallFlags (line 54) | class TestHandleSkillsSlashUninstallFlags: method test_yes_flag_sets_skip_confirm (line 57) | def test_yes_flag_sets_skip_confirm(self): method test_y_flag_sets_skip_confirm (line 65) | def test_y_flag_sets_skip_confirm(self): method test_no_flags (line 73) | def test_no_flags(self): class TestDoInstallSkipConfirm (line 82) | class TestDoInstallSkipConfirm: method test_without_skip_confirm_prompts_user (line 86) | def test_without_skip_confirm_prompts_user(self, mock_input): class TestDoUninstallSkipConfirm (line 103) | class TestDoUninstallSkipConfirm: method test_skip_confirm_bypasses_input (line 106) | def test_skip_confirm_bypasses_input(self): method test_without_skip_confirm_calls_input (line 116) | def test_without_skip_confirm_calls_input(self): method test_without_skip_confirm_cancel (line 125) | def test_without_skip_confirm_cancel(self): FILE: tests/hermes_cli/test_skills_subparser.py function test_no_duplicate_skills_subparser (line 6) | def test_no_duplicate_skills_subparser(): FILE: tests/hermes_cli/test_skin_engine.py function reset_skin_state (line 11) | def reset_skin_state(): class TestSkinConfig (line 21) | class TestSkinConfig: method test_default_skin_has_required_fields (line 22) | def test_default_skin_has_required_fields(self): method test_get_color_with_fallback (line 31) | def test_get_color_with_fallback(self): method test_get_branding_with_fallback (line 37) | def test_get_branding_with_fallback(self): method test_get_spinner_list_empty_for_default (line 43) | def test_get_spinner_list_empty_for_default(self): method test_get_spinner_wings_empty_for_default (line 50) | def test_get_spinner_wings_empty_for_default(self): class TestBuiltinSkins (line 56) | class TestBuiltinSkins: method test_ares_skin_loads (line 57) | def test_ares_skin_loads(self): method test_ares_has_spinner_customization (line 68) | def test_ares_has_spinner_customization(self): method test_mono_skin_loads (line 79) | def test_mono_skin_loads(self): method test_slate_skin_loads (line 85) | def test_slate_skin_loads(self): method test_unknown_skin_falls_back_to_default (line 91) | def test_unknown_skin_falls_back_to_default(self): method test_all_builtin_skins_have_complete_colors (line 96) | def test_all_builtin_skins_have_complete_colors(self): class TestSkinManagement (line 106) | class TestSkinManagement: method test_set_active_skin (line 107) | def test_set_active_skin(self): method test_get_active_skin_defaults (line 114) | def test_get_active_skin_defaults(self): method test_list_skins_includes_builtins (line 119) | def test_list_skins_includes_builtins(self): method test_init_skin_from_config (line 131) | def test_init_skin_from_config(self): method test_init_skin_from_empty_config (line 136) | def test_init_skin_from_empty_config(self): class TestUserSkins (line 142) | class TestUserSkins: method test_load_user_skin_from_yaml (line 143) | def test_load_user_skin_from_yaml(self, tmp_path, monkeypatch): method test_list_skins_includes_user_skins (line 170) | def test_list_skins_includes_user_skins(self, tmp_path, monkeypatch): class TestDisplayIntegration (line 188) | class TestDisplayIntegration: method test_get_skin_tool_prefix_default (line 189) | def test_get_skin_tool_prefix_default(self): method test_get_skin_tool_prefix_custom (line 193) | def test_get_skin_tool_prefix_custom(self): method test_get_skin_faces_default (line 199) | def test_get_skin_faces_default(self): method test_get_skin_faces_ares (line 205) | def test_get_skin_faces_ares(self): method test_get_skin_verbs_default (line 212) | def test_get_skin_verbs_default(self): method test_get_skin_verbs_ares (line 217) | def test_get_skin_verbs_ares(self): method test_tool_message_uses_skin_prefix (line 224) | def test_tool_message_uses_skin_prefix(self): method test_tool_message_default_prefix (line 232) | def test_tool_message_default_prefix(self): class TestCliBrandingHelpers (line 238) | class TestCliBrandingHelpers: method test_active_prompt_symbol_default (line 239) | def test_active_prompt_symbol_default(self): method test_active_prompt_symbol_ares (line 244) | def test_active_prompt_symbol_ares(self): method test_active_help_header_ares (line 250) | def test_active_help_header_ares(self): method test_active_goodbye_ares (line 256) | def test_active_goodbye_ares(self): method test_prompt_toolkit_style_overrides_cover_tui_classes (line 262) | def test_prompt_toolkit_style_overrides_cover_tui_classes(self): method test_prompt_toolkit_style_overrides_use_skin_colors (line 300) | def test_prompt_toolkit_style_overrides_use_skin_colors(self): FILE: tests/hermes_cli/test_status.py function test_show_status_includes_tavily_key (line 6) | def test_show_status_includes_tavily_key(monkeypatch, capsys, tmp_path): FILE: tests/hermes_cli/test_status_model_provider.py function _patch_common_status_deps (line 6) | def _patch_common_status_deps(monkeypatch, status_mod, tmp_path, *, open... function test_show_status_displays_configured_dict_model_and_provider_label (line 27) | def test_show_status_displays_configured_dict_model_and_provider_label(m... function test_show_status_displays_legacy_string_model_and_custom_endpoint (line 48) | def test_show_status_displays_legacy_string_model_and_custom_endpoint(mo... FILE: tests/hermes_cli/test_tools_config.py function test_get_platform_tools_uses_default_when_platform_not_configured (line 13) | def test_get_platform_tools_uses_default_when_platform_not_configured(): function test_get_platform_tools_preserves_explicit_empty_selection (line 21) | def test_get_platform_tools_preserves_explicit_empty_selection(): function test_platform_toolset_summary_uses_explicit_platform_list (line 29) | def test_platform_toolset_summary_uses_explicit_platform_list(): function test_toolset_has_keys_for_vision_accepts_codex_auth (line 38) | def test_toolset_has_keys_for_vision_accepts_codex_auth(tmp_path, monkey... function test_save_platform_tools_preserves_mcp_server_names (line 52) | def test_save_platform_tools_preserves_mcp_server_names(): function test_save_platform_tools_handles_empty_existing_config (line 78) | def test_save_platform_tools_handles_empty_existing_config(): function test_save_platform_tools_handles_invalid_existing_config (line 90) | def test_save_platform_tools_handles_invalid_existing_config(): FILE: tests/hermes_cli/test_tools_disable_enable.py class TestToolsDisableBuiltin (line 11) | class TestToolsDisableBuiltin: method test_disable_removes_toolset_from_platform (line 13) | def test_disable_removes_toolset_from_platform(self): method test_disable_multiple_toolsets (line 22) | def test_disable_multiple_toolsets(self): method test_disable_already_absent_is_idempotent (line 32) | def test_disable_already_absent_is_idempotent(self): class TestToolsEnableBuiltin (line 44) | class TestToolsEnableBuiltin: method test_enable_adds_toolset_to_platform (line 46) | def test_enable_adds_toolset_to_platform(self): method test_enable_already_present_is_idempotent (line 54) | def test_enable_already_present_is_idempotent(self): class TestToolsDisableMcp (line 66) | class TestToolsDisableMcp: method test_disable_adds_to_exclude_list (line 68) | def test_disable_adds_to_exclude_list(self): method test_disable_already_excluded_is_idempotent (line 78) | def test_disable_already_excluded_is_idempotent(self): method test_disable_unknown_server_prints_error (line 88) | def test_disable_unknown_server_prints_error(self, capsys): class TestToolsEnableMcp (line 102) | class TestToolsEnableMcp: method test_enable_removes_from_exclude_list (line 104) | def test_enable_removes_from_exclude_list(self): class TestToolsMixedTargets (line 119) | class TestToolsMixedTargets: method test_disable_builtin_and_mcp_together (line 121) | def test_disable_builtin_and_mcp_together(self): class TestToolsList (line 141) | class TestToolsList: method test_list_shows_enabled_toolsets (line 143) | def test_list_shows_enabled_toolsets(self, capsys): method test_list_shows_mcp_excluded_tools (line 151) | def test_list_shows_mcp_excluded_tools(self, capsys): class TestToolsValidation (line 165) | class TestToolsValidation: method test_unknown_platform_prints_error (line 167) | def test_unknown_platform_prints_error(self, capsys): method test_unknown_toolset_prints_error (line 177) | def test_unknown_toolset_prints_error(self, capsys): method test_unknown_toolset_does_not_corrupt_config (line 187) | def test_unknown_toolset_does_not_corrupt_config(self): method test_mixed_valid_and_invalid_applies_valid_only (line 198) | def test_mixed_valid_and_invalid_applies_valid_only(self): FILE: tests/hermes_cli/test_update_autostash.py function test_stash_local_changes_if_needed_returns_none_when_tree_clean (line 11) | def test_stash_local_changes_if_needed_returns_none_when_tree_clean(monk... function test_stash_local_changes_if_needed_returns_specific_stash_commit (line 28) | def test_stash_local_changes_if_needed_returns_specific_stash_commit(mon... function test_resolve_stash_selector_returns_matching_entry (line 50) | def test_resolve_stash_selector_returns_matching_entry(monkeypatch, tmp_... function test_restore_stashed_changes_prompts_before_applying (line 64) | def test_restore_stashed_changes_prompts_before_applying(monkeypatch, tm... function test_restore_stashed_changes_can_skip_restore_and_keep_stash (line 93) | def test_restore_stashed_changes_can_skip_restore_and_keep_stash(monkeyp... function test_restore_stashed_changes_applies_without_prompt_when_disabled (line 113) | def test_restore_stashed_changes_applies_without_prompt_when_disabled(mo... function test_print_stash_cleanup_guidance_with_selector (line 138) | def test_print_stash_cleanup_guidance_with_selector(capsys): function test_restore_stashed_changes_keeps_going_when_stash_entry_cannot_be_resolved (line 148) | def test_restore_stashed_changes_keeps_going_when_stash_entry_cannot_be_... function test_restore_stashed_changes_keeps_going_when_drop_fails (line 177) | def test_restore_stashed_changes_keeps_going_when_drop_fails(monkeypatch... function test_restore_stashed_changes_exits_cleanly_when_apply_fails (line 204) | def test_restore_stashed_changes_exits_cleanly_when_apply_fails(monkeypa... function test_stash_local_changes_if_needed_raises_when_stash_ref_missing (line 225) | def test_stash_local_changes_if_needed_raises_when_stash_ref_missing(mon... function _setup_update_mocks (line 245) | def _setup_update_mocks(monkeypatch, tmp_path): function test_cmd_update_tries_extras_first_then_falls_back (line 257) | def test_cmd_update_tries_extras_first_then_falls_back(monkeypatch, tmp_... function test_cmd_update_succeeds_with_extras (line 292) | def test_cmd_update_succeeds_with_extras(monkeypatch, tmp_path): FILE: tests/hermes_cli/test_update_check.py function test_version_string_no_v_prefix (line 12) | def test_version_string_no_v_prefix(): function test_check_for_updates_uses_cache (line 18) | def test_check_for_updates_uses_cache(tmp_path): function test_check_for_updates_expired_cache (line 38) | def test_check_for_updates_expired_cache(tmp_path): function test_check_for_updates_no_git_dir (line 60) | def test_check_for_updates_no_git_dir(tmp_path): function test_check_for_updates_fallback_to_project_root (line 81) | def test_check_for_updates_fallback_to_project_root(): function test_prefetch_non_blocking (line 100) | def test_prefetch_non_blocking(): function test_get_update_result_timeout (line 121) | def test_get_update_result_timeout(): FILE: tests/hermes_cli/test_update_gateway_restart.py function _make_run_side_effect (line 23) | def _make_run_side_effect( function mock_args (line 70) | def mock_args(): class TestLaunchdPlistReplace (line 79) | class TestLaunchdPlistReplace: method test_plist_contains_replace_flag (line 83) | def test_plist_contains_replace_flag(self): method test_plist_program_arguments_order (line 87) | def test_plist_program_arguments_order(self): class TestLaunchdPlistRefresh (line 109) | class TestLaunchdPlistRefresh: method test_refresh_rewrites_stale_plist (line 113) | def test_refresh_rewrites_stale_plist(self, tmp_path, monkeypatch): method test_refresh_skips_when_current (line 135) | def test_refresh_skips_when_current(self, tmp_path, monkeypatch): method test_refresh_skips_when_no_plist (line 153) | def test_refresh_skips_when_no_plist(self, tmp_path, monkeypatch): method test_launchd_start_calls_refresh (line 160) | def test_launchd_start_calls_refresh(self, tmp_path, monkeypatch): class TestCmdUpdateLaunchdRestart (line 181) | class TestCmdUpdateLaunchdRestart: method test_update_detects_launchd_and_skips_manual_restart_message (line 186) | def test_update_detects_launchd_and_skips_manual_restart_message( method test_update_without_launchd_shows_manual_restart (line 227) | def test_update_without_launchd_shows_manual_restart( method test_update_with_systemd_still_restarts_via_systemd (line 256) | def test_update_with_systemd_still_restarts_via_systemd( method test_update_no_gateway_running_skips_restart (line 286) | def test_update_no_gateway_running_skips_restart( FILE: tests/honcho_integration/test_async_memory.py function _make_session (line 35) | def _make_session(**kwargs) -> HonchoSession: function _make_manager (line 45) | def _make_manager(write_frequency="turn", memory_mode="hybrid") -> Honch... class TestWriteFrequencyParsing (line 61) | class TestWriteFrequencyParsing: method test_string_async (line 62) | def test_string_async(self, tmp_path): method test_string_turn (line 68) | def test_string_turn(self, tmp_path): method test_string_session (line 74) | def test_string_session(self, tmp_path): method test_integer_frequency (line 80) | def test_integer_frequency(self, tmp_path): method test_integer_string_coerced (line 86) | def test_integer_string_coerced(self, tmp_path): method test_host_block_overrides_root (line 92) | def test_host_block_overrides_root(self, tmp_path): method test_defaults_to_async (line 102) | def test_defaults_to_async(self, tmp_path): class TestMemoryModeParsing (line 113) | class TestMemoryModeParsing: method test_hybrid (line 114) | def test_hybrid(self, tmp_path): method test_honcho_only (line 120) | def test_honcho_only(self, tmp_path): method test_defaults_to_hybrid (line 126) | def test_defaults_to_hybrid(self, tmp_path): method test_host_block_overrides_root (line 132) | def test_host_block_overrides_root(self, tmp_path): method test_object_form_sets_default_and_overrides (line 142) | def test_object_form_sets_default_and_overrides(self, tmp_path): method test_object_form_no_default_falls_back_to_hybrid (line 156) | def test_object_form_no_default_falls_back_to_hybrid(self, tmp_path): method test_global_string_host_object_override (line 167) | def test_global_string_host_object_override(self, tmp_path): class TestResolveSessionNameTitle (line 184) | class TestResolveSessionNameTitle: method test_manual_override_beats_title (line 185) | def test_manual_override_beats_title(self): method test_title_beats_dirname (line 190) | def test_title_beats_dirname(self): method test_title_with_peer_prefix (line 195) | def test_title_with_peer_prefix(self): method test_title_sanitized (line 200) | def test_title_sanitized(self): method test_title_all_invalid_chars_falls_back_to_dirname (line 206) | def test_title_all_invalid_chars_falls_back_to_dirname(self): method test_none_title_falls_back_to_dirname (line 212) | def test_none_title_falls_back_to_dirname(self): method test_empty_title_falls_back_to_dirname (line 217) | def test_empty_title_falls_back_to_dirname(self): method test_per_session_uses_session_id (line 222) | def test_per_session_uses_session_id(self): method test_per_session_with_peer_prefix (line 227) | def test_per_session_with_peer_prefix(self): method test_per_session_no_id_falls_back_to_dirname (line 232) | def test_per_session_no_id_falls_back_to_dirname(self): method test_title_beats_session_id (line 237) | def test_title_beats_session_id(self): method test_manual_beats_session_id (line 242) | def test_manual_beats_session_id(self): method test_global_strategy_returns_workspace (line 247) | def test_global_strategy_returns_workspace(self): class TestSaveRouting (line 257) | class TestSaveRouting: method _make_session_with_message (line 258) | def _make_session_with_message(self, mgr=None): method test_turn_flushes_immediately (line 266) | def test_turn_flushes_immediately(self): method test_session_mode_does_not_flush (line 273) | def test_session_mode_does_not_flush(self): method test_async_mode_enqueues (line 280) | def test_async_mode_enqueues(self): method test_int_frequency_flushes_on_nth_turn (line 289) | def test_int_frequency_flushes_on_nth_turn(self): method test_int_frequency_skips_other_turns (line 299) | def test_int_frequency_skips_other_turns(self): class TestFlushAll (line 314) | class TestFlushAll: method test_flushes_all_cached_sessions (line 315) | def test_flushes_all_cached_sessions(self): method test_flush_all_drains_async_queue (line 327) | def test_flush_all_drains_async_queue(self): method test_flush_all_tolerates_errors (line 338) | def test_flush_all_tolerates_errors(self): class TestAsyncWriterThread (line 351) | class TestAsyncWriterThread: method test_thread_started_on_async_mode (line 352) | def test_thread_started_on_async_mode(self): method test_no_thread_for_turn_mode (line 358) | def test_no_thread_for_turn_mode(self): method test_shutdown_joins_thread (line 363) | def test_shutdown_joins_thread(self): method test_async_writer_calls_flush (line 369) | def test_async_writer_calls_flush(self): method test_shutdown_sentinel_stops_loop (line 391) | def test_shutdown_sentinel_stops_loop(self): class TestAsyncWriterRetry (line 403) | class TestAsyncWriterRetry: method test_retries_once_on_failure (line 404) | def test_retries_once_on_failure(self): method test_drops_after_two_failures (line 428) | def test_drops_after_two_failures(self): method test_retries_when_flush_reports_failure (line 452) | def test_retries_when_flush_reports_failure(self): class TestMemoryFileMigrationTargets (line 475) | class TestMemoryFileMigrationTargets: method test_soul_upload_targets_ai_peer (line 476) | def test_soul_upload_targets_ai_peer(self, tmp_path): class TestNewConfigFieldDefaults (line 517) | class TestNewConfigFieldDefaults: method test_write_frequency_default (line 518) | def test_write_frequency_default(self): method test_memory_mode_default (line 522) | def test_memory_mode_default(self): method test_write_frequency_set (line 526) | def test_write_frequency_set(self): method test_memory_mode_set (line 530) | def test_memory_mode_set(self): method test_peer_memory_mode_falls_back_to_global (line 534) | def test_peer_memory_mode_falls_back_to_global(self): method test_peer_memory_mode_override (line 538) | def test_peer_memory_mode_override(self): class TestPrefetchCacheAccessors (line 544) | class TestPrefetchCacheAccessors: method test_set_and_pop_context_result (line 545) | def test_set_and_pop_context_result(self): method test_set_and_pop_dialectic_result (line 554) | def test_set_and_pop_dialectic_result(self): FILE: tests/honcho_integration/test_cli.py class TestResolveApiKey (line 6) | class TestResolveApiKey: method test_prefers_host_scoped_key (line 7) | def test_prefers_host_scoped_key(self): method test_falls_back_to_root_key (line 18) | def test_falls_back_to_root_key(self): method test_falls_back_to_env_key (line 25) | def test_falls_back_to_env_key(self, monkeypatch): FILE: tests/honcho_integration/test_client.py class TestHonchoClientConfigDefaults (line 19) | class TestHonchoClientConfigDefaults: method test_default_values (line 20) | def test_default_values(self): class TestFromEnv (line 35) | class TestFromEnv: method test_reads_api_key_from_env (line 36) | def test_reads_api_key_from_env(self): method test_reads_environment_from_env (line 42) | def test_reads_environment_from_env(self): method test_defaults_without_env (line 50) | def test_defaults_without_env(self): method test_custom_workspace (line 59) | def test_custom_workspace(self): method test_reads_base_url_from_env (line 63) | def test_reads_base_url_from_env(self): method test_enabled_without_api_key_when_base_url_set (line 69) | def test_enabled_without_api_key_when_base_url_set(self): class TestFromGlobalConfig (line 79) | class TestFromGlobalConfig: method test_missing_config_falls_back_to_env (line 80) | def test_missing_config_falls_back_to_env(self, tmp_path): method test_reads_full_config (line 89) | def test_reads_full_config(self, tmp_path): method test_host_block_overrides_root (line 125) | def test_host_block_overrides_root(self, tmp_path): method test_root_fields_used_when_no_host_block (line 143) | def test_root_fields_used_when_no_host_block(self, tmp_path): method test_session_strategy_default_from_global_config (line 155) | def test_session_strategy_default_from_global_config(self, tmp_path): method test_context_tokens_host_block_wins (line 162) | def test_context_tokens_host_block_wins(self, tmp_path): method test_recall_mode_from_config (line 173) | def test_recall_mode_from_config(self, tmp_path): method test_recall_mode_default (line 184) | def test_recall_mode_default(self, tmp_path): method test_corrupt_config_falls_back_to_env (line 190) | def test_corrupt_config_falls_back_to_env(self, tmp_path): method test_api_key_env_fallback (line 198) | def test_api_key_env_fallback(self, tmp_path): method test_base_url_env_fallback (line 206) | def test_base_url_env_fallback(self, tmp_path): method test_base_url_from_config_root (line 216) | def test_base_url_from_config_root(self, tmp_path): method test_base_url_not_read_from_host_block (line 225) | def test_base_url_not_read_from_host_block(self, tmp_path): class TestResolveSessionName (line 237) | class TestResolveSessionName: method test_manual_override (line 238) | def test_manual_override(self): method test_derive_from_dirname (line 242) | def test_derive_from_dirname(self): method test_peer_prefix (line 247) | def test_peer_prefix(self): method test_no_peer_prefix_when_no_peer_name (line 252) | def test_no_peer_prefix_when_no_peer_name(self): method test_default_cwd (line 257) | def test_default_cwd(self): method test_per_repo_uses_git_root (line 263) | def test_per_repo_uses_git_root(self): method test_per_repo_with_peer_prefix (line 271) | def test_per_repo_with_peer_prefix(self): method test_per_repo_falls_back_to_dirname_outside_git (line 281) | def test_per_repo_falls_back_to_dirname_outside_git(self): method test_per_repo_manual_override_still_wins (line 289) | def test_per_repo_manual_override_still_wins(self): class TestGetLinkedWorkspaces (line 298) | class TestGetLinkedWorkspaces: method test_resolves_linked_hosts (line 299) | def test_resolves_linked_hosts(self): method test_excludes_own_workspace (line 314) | def test_excludes_own_workspace(self): method test_uses_host_key_as_fallback (line 323) | def test_uses_host_key_as_fallback(self): class TestResetHonchoClient (line 333) | class TestResetHonchoClient: method test_reset_clears_singleton (line 334) | def test_reset_clears_singleton(self): FILE: tests/honcho_integration/test_session.py class TestHonchoSession (line 17) | class TestHonchoSession: method _make_session (line 18) | def _make_session(self): method test_initial_state (line 26) | def test_initial_state(self): method test_add_message (line 33) | def test_add_message(self): method test_add_message_with_kwargs (line 41) | def test_add_message_with_kwargs(self): method test_add_message_updates_timestamp (line 46) | def test_add_message_updates_timestamp(self): method test_get_history (line 52) | def test_get_history(self): method test_get_history_strips_extra_fields (line 61) | def test_get_history_strips_extra_fields(self): method test_get_history_max_messages (line 68) | def test_get_history_max_messages(self): method test_get_history_max_messages_larger_than_total (line 77) | def test_get_history_max_messages_larger_than_total(self): method test_clear (line 83) | def test_clear(self): method test_clear_updates_timestamp (line 90) | def test_clear_updates_timestamp(self): class TestSanitizeId (line 103) | class TestSanitizeId: method test_clean_id_unchanged (line 104) | def test_clean_id_unchanged(self): method test_colons_replaced (line 108) | def test_colons_replaced(self): method test_special_chars_replaced (line 112) | def test_special_chars_replaced(self): method test_alphanumeric_preserved (line 119) | def test_alphanumeric_preserved(self): class TestFormatMigrationTranscript (line 129) | class TestFormatMigrationTranscript: method test_basic_transcript (line 130) | def test_basic_transcript(self): method test_empty_messages (line 144) | def test_empty_messages(self): method test_missing_fields_handled (line 150) | def test_missing_fields_handled(self): class TestManagerCacheOps (line 162) | class TestManagerCacheOps: method test_delete_cached_session (line 163) | def test_delete_cached_session(self): method test_delete_nonexistent_returns_false (line 173) | def test_delete_nonexistent_returns_false(self): method test_list_sessions (line 177) | def test_list_sessions(self): FILE: tests/integration/test_batch_runner.py function create_test_dataset (line 17) | def create_test_dataset(): function cleanup_test_run (line 36) | def cleanup_test_run(run_name): function verify_output (line 44) | def verify_output(run_name): function main (line 93) | def main(): FILE: tests/integration/test_checkpoint_resumption.py function create_test_dataset (line 37) | def create_test_dataset(num_prompts: int = 20) -> Path: function monitor_checkpoint_during_run (line 56) | def monitor_checkpoint_during_run(checkpoint_file: Path, duration: int =... function _cleanup_test_artifacts (line 111) | def _cleanup_test_artifacts(*paths): function test_current_implementation (line 121) | def test_current_implementation(): function test_interruption_and_resume (line 216) | def test_interruption_and_resume(): function test_simulated_crash (line 314) | def test_simulated_crash(): function print_test_plan (line 324) | def print_test_plan(): function main (line 390) | def main( FILE: tests/integration/test_daytona_terminal.py function _force_daytona (line 37) | def _force_daytona(monkeypatch): function task_id (line 44) | def task_id(request): function _run (line 51) | def _run(command, task_id, **kwargs): class TestDaytonaBasic (line 56) | class TestDaytonaBasic: method test_echo (line 57) | def test_echo(self, task_id): method test_python_version (line 62) | def test_python_version(self, task_id): method test_nonzero_exit (line 67) | def test_nonzero_exit(self, task_id): method test_os_info (line 71) | def test_os_info(self, task_id): class TestDaytonaFilesystem (line 77) | class TestDaytonaFilesystem: method test_write_and_read_file (line 78) | def test_write_and_read_file(self, task_id): method test_persistence_within_session (line 84) | def test_persistence_within_session(self, task_id): class TestDaytonaPersistence (line 91) | class TestDaytonaPersistence: method test_filesystem_survives_stop_and_resume (line 92) | def test_filesystem_survives_stop_and_resume(self): class TestDaytonaIsolation (line 113) | class TestDaytonaIsolation: method test_different_tasks_isolated (line 114) | def test_different_tasks_isolated(self): FILE: tests/integration/test_ha_integration.py function _adapter_for (line 33) | def _adapter_for(server: FakeHAServer, **extra) -> HomeAssistantAdapter: class TestGatewayWebSocket (line 48) | class TestGatewayWebSocket: method test_connect_auth_subscribe (line 50) | async def test_connect_auth_subscribe(self): method test_connect_auth_rejected (line 62) | async def test_connect_auth_rejected(self): method test_event_received_and_forwarded (line 71) | async def test_event_received_and_forwarded(self): method test_event_filtering_ignores_unwatched (line 106) | async def test_event_filtering_ignores_unwatched(self): method test_disconnect_closes_cleanly (line 132) | async def test_disconnect_closes_cleanly(self): class TestToolRest (line 153) | class TestToolRest: method test_list_entities_returns_all (line 164) | async def test_list_entities_returns_all(self, monkeypatch): method test_list_entities_domain_filter (line 182) | async def test_list_entities_domain_filter(self, monkeypatch): method test_get_state_single_entity (line 199) | async def test_get_state_single_entity(self, monkeypatch): method test_get_state_not_found (line 217) | async def test_get_state_not_found(self, monkeypatch): method test_call_service_turn_on (line 234) | async def test_call_service_turn_on(self, monkeypatch): class TestSendNotification (line 270) | class TestSendNotification: method test_send_notification_delivered (line 272) | async def test_send_notification_delivered(self): method test_send_auth_failure (line 286) | async def test_send_auth_failure(self): class TestAuthAndErrors (line 307) | class TestAuthAndErrors: method test_rest_unauthorized (line 309) | async def test_rest_unauthorized(self, monkeypatch): method test_rest_server_error (line 326) | async def test_rest_server_error(self, monkeypatch): FILE: tests/integration/test_modal_terminal.py function test_modal_requirements (line 60) | def test_modal_requirements(): function test_simple_command (line 89) | def test_simple_command(): function test_python_execution (line 115) | def test_python_execution(): function test_pip_install (line 143) | def test_pip_install(): function test_filesystem_persistence (line 176) | def test_filesystem_persistence(): function test_environment_isolation (line 210) | def test_environment_isolation(): function main (line 242) | def main(): FILE: tests/integration/test_voice_channel_flow.py function _make_secret_key (line 48) | def _make_secret_key(): function _build_encrypted_rtp_packet (line 54) | def _build_encrypted_rtp_packet(secret_key, opus_payload, ssrc=100, seq=... function _make_voice_receiver (line 76) | def _make_voice_receiver(secret_key, dave_session=None, bot_ssrc=9999, class TestRealNaClDecrypt (line 99) | class TestRealNaClDecrypt: method test_valid_encrypted_packet_buffered (line 102) | def test_valid_encrypted_packet_buffered(self): method test_wrong_key_packet_dropped (line 114) | def test_wrong_key_packet_dropped(self): method test_bot_ssrc_ignored (line 126) | def test_bot_ssrc_ignored(self): method test_multiple_packets_accumulate (line 136) | def test_multiple_packets_accumulate(self): method test_different_ssrcs_separate_buffers (line 151) | def test_different_ssrcs_separate_buffers(self): class TestRealNaClWithDAVE (line 165) | class TestRealNaClWithDAVE: method test_dave_unknown_ssrc_passthrough (line 168) | def test_dave_unknown_ssrc_passthrough(self): method test_dave_unencrypted_error_passthrough (line 183) | def test_dave_unencrypted_error_passthrough(self): method test_dave_real_error_drops (line 201) | def test_dave_real_error_drops(self): class TestFullVoiceFlow (line 215) | class TestFullVoiceFlow: method test_single_utterance_flow (line 218) | def test_single_utterance_flow(self): method test_utterance_with_ssrc_automap (line 242) | def test_utterance_with_ssrc_automap(self): method test_pause_blocks_during_playback (line 266) | def test_pause_blocks_during_playback(self): method test_corrupted_packet_ignored (line 283) | def test_corrupted_packet_ignored(self): method test_stop_cleans_everything (line 302) | def test_stop_cleans_everything(self): class TestSPEAKINGHook (line 323) | class TestSPEAKINGHook: method test_speaking_hook_installed (line 326) | def test_speaking_hook_installed(self): method test_map_ssrc_via_speaking (line 334) | def test_map_ssrc_via_speaking(self): method test_map_ssrc_overwrites (line 341) | def test_map_ssrc_overwrites(self): method test_speaking_mapped_audio_processed (line 349) | def test_speaking_mapped_audio_processed(self): class TestAuthFiltering (line 367) | class TestAuthFiltering: method test_allowed_user_audio_processed (line 370) | def test_allowed_user_audio_processed(self): method test_automap_rejects_unallowed_user (line 393) | def test_automap_rejects_unallowed_user(self): method test_empty_allowlist_allows_all (line 416) | def test_empty_allowlist_allows_all(self): class TestRejoinFlow (line 440) | class TestRejoinFlow: method test_stop_then_new_receiver_clean_state (line 443) | def test_stop_then_new_receiver_clean_state(self): method test_rejoin_new_ssrc_works (line 464) | def test_rejoin_new_ssrc_works(self): method test_rejoin_without_speaking_event_automap (line 485) | def test_rejoin_without_speaking_event_automap(self): class TestMultiGuildIsolation (line 518) | class TestMultiGuildIsolation: method test_separate_receivers_independent (line 521) | def test_separate_receivers_independent(self): method test_stop_one_doesnt_affect_other (line 543) | def test_stop_one_doesnt_affect_other(self): class TestEchoPreventionFlow (line 567) | class TestEchoPreventionFlow: method test_audio_during_pause_ignored (line 570) | def test_audio_during_pause_ignored(self): method test_audio_after_resume_processed (line 585) | def test_audio_after_resume_processed(self): FILE: tests/integration/test_web_tools.py class Colors (line 42) | class Colors: function print_header (line 55) | def print_header(text: str): function print_section (line 62) | def print_section(text: str): function print_success (line 68) | def print_success(text: str): function print_error (line 73) | def print_error(text: str): function print_warning (line 78) | def print_warning(text: str): function print_info (line 83) | def print_info(text: str, indent: int = 0): class WebToolsTester (line 89) | class WebToolsTester: method __init__ (line 92) | def __init__(self, verbose: bool = False, test_llm: bool = True): method log_result (line 103) | def log_result(self, test_name: str, status: str, details: str = ""): method test_environment (line 122) | def test_environment(self) -> bool: method test_web_search (line 149) | def test_web_search(self) -> List[str]: method test_web_extract (line 249) | async def test_web_extract(self, urls: List[str] = None): method test_web_extract_with_llm (line 354) | async def test_web_extract_with_llm(self, urls: List[str] = None): method test_web_crawl (line 414) | async def test_web_crawl(self): method run_all_tests (line 521) | async def run_all_tests(self): method save_results (line 567) | def save_results(self): function main (line 600) | async def main(): FILE: tests/run_interrupt_test.py function main (line 19) | def main() -> int: FILE: tests/skills/test_google_oauth_setup.py class FakeCredentials (line 22) | class FakeCredentials: method __init__ (line 23) | def __init__(self, payload=None): method to_json (line 33) | def to_json(self): class FakeFlow (line 37) | class FakeFlow: method __init__ (line 44) | def __init__( method reset (line 70) | def reset(cls): method from_client_secrets_file (line 78) | def from_client_secrets_file(cls, client_secrets_file, scopes, **kwargs): method authorization_url (line 83) | def authorization_url(self, **kwargs): method fetch_token (line 87) | def fetch_token(self, **kwargs): function setup_module (line 94) | def setup_module(monkeypatch, tmp_path): class TestGetAuthUrl (line 126) | class TestGetAuthUrl: method test_persists_state_and_code_verifier_for_later_exchange (line 127) | def test_persists_state_and_code_verifier_for_later_exchange(self, set... class TestExchangeAuthCode (line 142) | class TestExchangeAuthCode: method test_reuses_saved_pkce_material_for_plain_code (line 143) | def test_reuses_saved_pkce_material_for_plain_code(self, setup_module): method test_extracts_code_from_redirect_url_and_checks_state (line 157) | def test_extracts_code_from_redirect_url_and_checks_state(self, setup_... method test_rejects_state_mismatch (line 169) | def test_rejects_state_mismatch(self, setup_module, capsys): method test_requires_pending_auth_session (line 183) | def test_requires_pending_auth_session(self, setup_module, capsys): method test_keeps_pending_auth_session_when_exchange_fails (line 191) | def test_keeps_pending_auth_session_when_exchange_fails(self, setup_mo... FILE: tests/skills/test_openclaw_migration.py function load_module (line 19) | def load_module(): function load_skills_guard (line 28) | def load_skills_guard(): function test_extract_markdown_entries_promotes_heading_context (line 40) | def test_extract_markdown_entries_promotes_heading_context(): function test_merge_entries_respects_limit_and_reports_overflow (line 59) | def test_merge_entries_respects_limit_and_reports_overflow(): function test_resolve_selected_options_supports_include_and_exclude (line 70) | def test_resolve_selected_options_supports_include_and_exclude(): function test_resolve_selected_options_supports_presets (line 76) | def test_resolve_selected_options_supports_presets(): function test_resolve_selected_options_rejects_unknown_values (line 85) | def test_resolve_selected_options_rejects_unknown_values(): function test_resolve_selected_options_rejects_unknown_preset (line 95) | def test_resolve_selected_options_rejects_unknown_preset(): function test_migrator_copies_skill_and_merges_allowlist (line 105) | def test_migrator_copies_skill_and_merges_allowlist(tmp_path: Path): function test_migrator_optionally_imports_supported_secrets_and_messaging_settings (line 150) | def test_migrator_optionally_imports_supported_secrets_and_messaging_set... function test_migrator_can_execute_only_selected_categories (line 188) | def test_migrator_can_execute_only_selected_categories(tmp_path: Path): function test_migrator_records_preset_in_report (line 225) | def test_migrator_records_preset_in_report(tmp_path: Path): function test_migrator_exports_full_overflow_entries (line 251) | def test_migrator_exports_full_overflow_entries(tmp_path: Path): function test_migrator_can_rename_conflicting_imported_skill (line 282) | def test_migrator_can_rename_conflicting_imported_skill(tmp_path: Path): function test_migrator_can_overwrite_conflicting_imported_skill_with_backup (line 321) | def test_migrator_can_overwrite_conflicting_imported_skill_with_backup(t... function test_discord_settings_migrated (line 358) | def test_discord_settings_migrated(tmp_path: Path): function test_slack_settings_migrated (line 389) | def test_slack_settings_migrated(tmp_path: Path): function test_signal_settings_migrated (line 422) | def test_signal_settings_migrated(tmp_path: Path): function test_model_config_migrated (line 455) | def test_model_config_migrated(tmp_path: Path): function test_model_config_object_format (line 482) | def test_model_config_object_format(tmp_path: Path): function test_tts_config_migrated (line 508) | def test_tts_config_migrated(tmp_path: Path): function test_shared_skills_migrated (line 543) | def test_shared_skills_migrated(tmp_path: Path): function test_daily_memory_merged (line 567) | def test_daily_memory_merged(tmp_path: Path): function test_provider_keys_require_migrate_secrets_flag (line 598) | def test_provider_keys_require_migrate_secrets_flag(tmp_path: Path): function test_workspace_agents_records_skip_when_missing (line 642) | def test_workspace_agents_records_skip_when_missing(tmp_path: Path): function test_skill_installs_cleanly_under_skills_guard (line 661) | def test_skill_installs_cleanly_under_skills_guard(): FILE: tests/skills/test_telephony_skill.py function load_module (line 20) | def load_module(): function test_save_twilio_writes_env_and_state (line 29) | def test_save_twilio_writes_env_and_state(tmp_path: Path, monkeypatch): function test_upsert_env_updates_existing_values (line 52) | def test_upsert_env_updates_existing_values(tmp_path: Path): function test_messages_after_checkpoint_returns_only_newer_items (line 71) | def test_messages_after_checkpoint_returns_only_newer_items(): function test_twilio_buy_number_saves_env_and_state (line 84) | def test_twilio_buy_number_saves_env_and_state(tmp_path: Path): function test_twilio_inbox_marks_seen_checkpoint (line 113) | def test_twilio_inbox_marks_seen_checkpoint(tmp_path: Path): function test_vapi_import_twilio_number_saves_phone_number_id (line 169) | def test_vapi_import_twilio_number_saves_phone_number_id(tmp_path: Path): function test_diagnose_includes_decision_tree_and_saved_state (line 200) | def test_diagnose_includes_decision_tree_and_saved_state(tmp_path: Path,... FILE: tests/test_1630_context_overflow_loop.py class TestGeneric400Heuristic (line 21) | class TestGeneric400Heuristic: method _make_agent (line 25) | def _make_agent(self): method test_generic_400_with_small_session_is_client_error (line 46) | def test_generic_400_with_small_session_is_client_error(self): method test_generic_400_with_large_token_count_triggers_heuristic (line 70) | def test_generic_400_with_large_token_count_triggers_heuristic(self): method test_generic_400_with_many_messages_triggers_heuristic (line 91) | def test_generic_400_with_many_messages_triggers_heuristic(self): method test_specific_error_message_bypasses_heuristic (line 105) | def test_specific_error_message_bypasses_heuristic(self): method test_descriptive_context_error_caught_by_phrases (line 116) | def test_descriptive_context_error_caught_by_phrases(self): class TestGatewaySkipsPersistenceOnFailure (line 134) | class TestGatewaySkipsPersistenceOnFailure: method test_agent_failed_early_detected (line 138) | def test_agent_failed_early_detected(self): method test_agent_with_response_not_failed_early (line 153) | def test_agent_with_response_not_failed_early(self): method test_successful_agent_not_failed_early (line 167) | def test_successful_agent_not_failed_early(self): class TestContextOverflowErrorMessages (line 184) | class TestContextOverflowErrorMessages: method test_detects_context_keywords (line 188) | def test_detects_context_keywords(self): method test_detects_generic_400_with_large_history (line 205) | def test_detects_generic_400_with_large_history(self): method test_unrelated_error_not_flagged (line 220) | def test_unrelated_error_not_flagged(self): class TestAgentSkipsPersistenceForLargeFailedSessions (line 239) | class TestAgentSkipsPersistenceForLargeFailedSessions: method test_large_session_400_skips_persistence (line 243) | def test_large_session_400_skips_persistence(self): method test_small_session_400_persists_normally (line 252) | def test_small_session_400_persists_normally(self): method test_non_400_error_persists_normally (line 261) | def test_non_400_error_persists_normally(self): FILE: tests/test_413_compression.py function _make_tool_defs (line 28) | def _make_tool_defs(*names: str) -> list: function _mock_response (line 42) | def _mock_response(content="Hello", finish_reason="stop", tool_calls=Non... function _make_413_error (line 55) | def _make_413_error(*, use_status_code=True, message="Request entity too... function agent (line 64) | def agent(): class TestHTTP413Compression (line 89) | class TestHTTP413Compression: method test_413_triggers_compression (line 92) | def test_413_triggers_compression(self, agent): method test_413_not_treated_as_generic_4xx (line 122) | def test_413_not_treated_as_generic_4xx(self, agent): method test_413_error_message_detection (line 149) | def test_413_error_message_detection(self, agent): method test_400_context_length_triggers_compression (line 175) | def test_400_context_length_triggers_compression(self, agent): method test_400_reduce_length_triggers_compression (line 214) | def test_400_reduce_length_triggers_compression(self, agent): method test_context_length_retry_rebuilds_request_after_compression (line 243) | def test_context_length_retry_rebuilds_request_after_compression(self,... method test_413_cannot_compress_further (line 292) | def test_413_cannot_compress_further(self, agent): class TestPreflightCompression (line 315) | class TestPreflightCompression: method test_preflight_compresses_oversized_history (line 318) | def test_preflight_compresses_oversized_history(self, agent): method test_no_preflight_when_under_threshold (line 356) | def test_no_preflight_when_under_threshold(self, agent): method test_no_preflight_when_compression_disabled (line 382) | def test_no_preflight_when_compression_disabled(self, agent): class TestToolResultPreflightCompression (line 407) | class TestToolResultPreflightCompression: method test_large_tool_results_trigger_compression (line 410) | def test_large_tool_results_trigger_compression(self, agent): method test_anthropic_prompt_too_long_safety_net (line 448) | def test_anthropic_prompt_too_long_safety_net(self, agent): FILE: tests/test_860_dedup.py class TestFlushDeduplication (line 24) | class TestFlushDeduplication: method _make_agent (line 27) | def _make_agent(self, session_db): method test_flush_writes_only_new_messages (line 41) | def test_flush_writes_only_new_messages(self): method test_flush_writes_incrementally (line 71) | def test_flush_writes_incrementally(self): method test_persist_session_multiple_calls_no_duplication (line 100) | def test_persist_session_multiple_calls_no_duplication(self): method test_flush_reset_after_compression (line 127) | def test_flush_reset_after_compression(self): class TestAppendToTranscriptSkipDb (line 170) | class TestAppendToTranscriptSkipDb: method store (line 174) | def store(self, tmp_path): method test_skip_db_writes_jsonl_only (line 184) | def test_skip_db_writes_jsonl_only(self, store, tmp_path): method test_skip_db_prevents_sqlite_write (line 199) | def test_skip_db_prevents_sqlite_write(self, tmp_path): method test_default_writes_both (line 230) | def test_default_writes_both(self, tmp_path): class TestFlushIdxInit (line 266) | class TestFlushIdxInit: method test_init_zero (line 269) | def test_init_zero(self): method test_no_session_db_noop (line 281) | def test_no_session_db_noop(self): FILE: tests/test_agent_guardrails.py function make_tc (line 19) | def make_tc(name: str, arguments: str = "{}") -> types.SimpleNamespace: function tool_result (line 26) | def tool_result(call_id: str, content: str = "ok") -> dict: function assistant_dict_call (line 30) | def assistant_dict_call(call_id: str, name: str = "terminal") -> dict: class TestSanitizeApiMessages (line 39) | class TestSanitizeApiMessages: method test_orphaned_result_removed (line 41) | def test_orphaned_result_removed(self): method test_orphaned_call_gets_stub_result (line 51) | def test_orphaned_call_gets_stub_result(self): method test_clean_messages_pass_through (line 62) | def test_clean_messages_pass_through(self): method test_mixed_orphaned_result_and_orphaned_call (line 72) | def test_mixed_orphaned_result_and_orphaned_call(self): method test_empty_list_is_safe (line 87) | def test_empty_list_is_safe(self): method test_no_tool_messages (line 90) | def test_no_tool_messages(self): method test_sdk_object_tool_calls (line 98) | def test_sdk_object_tool_calls(self): class TestCapDelegateTaskCalls (line 114) | class TestCapDelegateTaskCalls: method test_excess_delegates_truncated (line 116) | def test_excess_delegates_truncated(self): method test_non_delegate_calls_preserved (line 122) | def test_non_delegate_calls_preserved(self): method test_at_limit_passes_through (line 132) | def test_at_limit_passes_through(self): method test_below_limit_passes_through (line 137) | def test_below_limit_passes_through(self): method test_no_delegate_calls_unchanged (line 142) | def test_no_delegate_calls_unchanged(self): method test_empty_list_safe (line 147) | def test_empty_list_safe(self): method test_original_list_not_mutated (line 150) | def test_original_list_not_mutated(self): method test_interleaved_order_preserved (line 156) | def test_interleaved_order_preserved(self): class TestDeduplicateToolCalls (line 173) | class TestDeduplicateToolCalls: method test_duplicate_pair_deduplicated (line 175) | def test_duplicate_pair_deduplicated(self): method test_multiple_duplicates (line 183) | def test_multiple_duplicates(self): method test_same_tool_different_args_kept (line 194) | def test_same_tool_different_args_kept(self): method test_different_tools_same_args_kept (line 202) | def test_different_tools_same_args_kept(self): method test_clean_list_unchanged (line 210) | def test_clean_list_unchanged(self): method test_empty_list_safe (line 218) | def test_empty_list_safe(self): method test_first_occurrence_kept (line 221) | def test_first_occurrence_kept(self): method test_original_list_not_mutated (line 228) | def test_original_list_not_mutated(self): class TestGetToolCallIdStatic (line 242) | class TestGetToolCallIdStatic: method test_dict_with_valid_id (line 244) | def test_dict_with_valid_id(self): method test_dict_with_none_id (line 247) | def test_dict_with_none_id(self): method test_dict_without_id_key (line 250) | def test_dict_without_id_key(self): method test_object_with_valid_id (line 253) | def test_object_with_valid_id(self): method test_object_with_none_id (line 257) | def test_object_with_none_id(self): method test_object_without_id_attr (line 261) | def test_object_without_id_attr(self): FILE: tests/test_agent_loop.py class MockFunction (line 37) | class MockFunction: class MockToolCall (line 43) | class MockToolCall: class MockMessage (line 50) | class MockMessage: class MockChoice (line 60) | class MockChoice: class MockChatCompletion (line 67) | class MockChatCompletion: class MockServer (line 73) | class MockServer: method __init__ (line 79) | def __init__(self, responses: List[MockChatCompletion]): method chat_completion (line 84) | async def chat_completion(self, **kwargs) -> MockChatCompletion: function make_text_response (line 96) | def make_text_response(content: str) -> MockChatCompletion: function make_tool_response (line 103) | def make_tool_response( class TestAgentResult (line 134) | class TestAgentResult: method test_defaults (line 135) | def test_defaults(self): class TestExtractReasoning (line 145) | class TestExtractReasoning: method test_reasoning_content_field (line 146) | def test_reasoning_content_field(self): method test_reasoning_field (line 150) | def test_reasoning_field(self): method test_reasoning_details (line 154) | def test_reasoning_details(self): method test_reasoning_details_dict_format (line 160) | def test_reasoning_details_dict_format(self): method test_no_reasoning (line 167) | def test_no_reasoning(self): method test_reasoning_content_takes_priority (line 171) | def test_reasoning_content_takes_priority(self): class TestHermesAgentLoop (line 180) | class TestHermesAgentLoop: method basic_tools (line 184) | def basic_tools(self): method valid_names (line 221) | def valid_names(self): method test_simple_text_response (line 225) | async def test_simple_text_response(self, basic_tools, valid_names): method test_tool_call_then_text (line 244) | async def test_tool_call_then_text(self, basic_tools, valid_names): method test_max_turns_reached (line 266) | async def test_max_turns_reached(self, basic_tools, valid_names): method test_unknown_tool_name (line 287) | async def test_unknown_tool_name(self, basic_tools, valid_names): method test_empty_response (line 307) | async def test_empty_response(self, basic_tools, valid_names): method test_api_error_handling (line 323) | async def test_api_error_handling(self, basic_tools, valid_names): method test_tools_passed_to_server (line 343) | async def test_tools_passed_to_server(self, basic_tools, valid_names): method test_extra_body_forwarded (line 360) | async def test_extra_body_forwarded(self, basic_tools, valid_names): method test_managed_state_returned (line 377) | async def test_managed_state_returned(self, basic_tools, valid_names): method test_no_managed_state_without_get_state (line 395) | async def test_no_managed_state_without_get_state(self, basic_tools, v... method test_memory_tool_blocked (line 410) | async def test_memory_tool_blocked(self, basic_tools): method test_session_search_blocked (line 434) | async def test_session_search_blocked(self, basic_tools): method test_reasoning_content_preserved (line 456) | async def test_reasoning_content_preserved(self, basic_tools, valid_na... class TestResizeToolPool (line 482) | class TestResizeToolPool: method test_resize_works (line 483) | def test_resize_works(self): method test_resize_shuts_down_previous_executor (line 488) | def test_resize_shuts_down_previous_executor(self, monkeypatch): FILE: tests/test_agent_loop_tool_calling.py function _get_api_key (line 56) | def _get_api_key(): function _make_server (line 63) | def _make_server(model: str = None): function _try_models (line 78) | async def _try_models(test_fn): function _fake_tool_handler (line 171) | def _fake_tool_handler(tool_name: str, args: Dict[str, Any], **kwargs) -... function test_single_tool_call (line 207) | async def test_single_tool_call(): function test_multi_tool_single_turn (line 256) | async def test_multi_tool_single_turn(): function test_multi_turn_conversation (line 298) | async def test_multi_turn_conversation(): function test_unknown_tool_rejected (line 341) | async def test_unknown_tool_rejected(): function test_max_turns_limit (line 374) | async def test_max_turns_limit(): function test_no_tools_direct_response (line 406) | async def test_no_tools_direct_response(): function test_tool_error_handling (line 440) | async def test_tool_error_handling(): function test_agent_result_structure (line 476) | async def test_agent_result_structure(): function test_conversation_history_preserved (line 517) | async def test_conversation_history_preserved(): FILE: tests/test_agent_loop_vllm.py function _vllm_is_running (line 53) | def _vllm_is_running() -> bool: function _make_server_manager (line 78) | def _make_server_manager(): function _get_tokenizer (line 96) | def _get_tokenizer(): function _fake_tool_handler (line 143) | def _fake_tool_handler(tool_name: str, args: Dict[str, Any], **kwargs) -... function test_vllm_single_tool_call (line 168) | async def test_vllm_single_tool_call(): function test_vllm_multi_tool_calls (line 210) | async def test_vllm_multi_tool_calls(): function test_vllm_managed_server_produces_nodes (line 248) | async def test_vllm_managed_server_produces_nodes(): function test_vllm_no_tools_direct_response (line 288) | async def test_vllm_no_tools_direct_response(): function test_vllm_thinking_content_extracted (line 319) | async def test_vllm_thinking_content_extracted(): FILE: tests/test_anthropic_adapter.py class TestIsOAuthToken (line 34) | class TestIsOAuthToken: method test_setup_token (line 35) | def test_setup_token(self): method test_api_key (line 38) | def test_api_key(self): method test_managed_key (line 41) | def test_managed_key(self): method test_jwt_token (line 45) | def test_jwt_token(self): method test_empty (line 49) | def test_empty(self): class TestBuildAnthropicClient (line 53) | class TestBuildAnthropicClient: method test_setup_token_uses_auth_token (line 54) | def test_setup_token_uses_auth_token(self): method test_api_key_uses_api_key (line 66) | def test_api_key_uses_api_key(self): method test_custom_base_url (line 78) | def test_custom_base_url(self): class TestReadClaudeCodeCredentials (line 85) | class TestReadClaudeCodeCredentials: method test_reads_valid_credentials (line 86) | def test_reads_valid_credentials(self, tmp_path, monkeypatch): method test_ignores_primary_api_key_for_native_anthropic_resolution (line 103) | def test_ignores_primary_api_key_for_native_anthropic_resolution(self,... method test_returns_none_for_missing_file (line 111) | def test_returns_none_for_missing_file(self, tmp_path, monkeypatch): method test_returns_none_for_missing_oauth_key (line 115) | def test_returns_none_for_missing_oauth_key(self, tmp_path, monkeypatch): method test_returns_none_for_empty_access_token (line 122) | def test_returns_none_for_empty_access_token(self, tmp_path, monkeypat... class TestIsClaudeCodeTokenValid (line 132) | class TestIsClaudeCodeTokenValid: method test_valid_token (line 133) | def test_valid_token(self): method test_expired_token (line 137) | def test_expired_token(self): method test_no_expiry_but_has_token (line 141) | def test_no_expiry_but_has_token(self): class TestResolveAnthropicToken (line 146) | class TestResolveAnthropicToken: method test_prefers_oauth_token_over_api_key (line 147) | def test_prefers_oauth_token_over_api_key(self, monkeypatch, tmp_path): method test_reports_claude_json_primary_key_source (line 154) | def test_reports_claude_json_primary_key_source(self, monkeypatch, tmp... method test_does_not_resolve_primary_api_key_as_native_anthropic_token (line 163) | def test_does_not_resolve_primary_api_key_as_native_anthropic_token(se... method test_falls_back_to_api_key_when_no_oauth_sources_exist (line 172) | def test_falls_back_to_api_key_when_no_oauth_sources_exist(self, monke... method test_falls_back_to_token (line 179) | def test_falls_back_to_token(self, monkeypatch, tmp_path): method test_returns_none_with_no_creds (line 186) | def test_returns_none_with_no_creds(self, monkeypatch, tmp_path): method test_falls_back_to_claude_code_oauth_token (line 193) | def test_falls_back_to_claude_code_oauth_token(self, monkeypatch, tmp_... method test_falls_back_to_claude_code_credentials (line 200) | def test_falls_back_to_claude_code_credentials(self, monkeypatch, tmp_... method test_prefers_refreshable_claude_code_credentials_over_static_anthropic_token (line 216) | def test_prefers_refreshable_claude_code_credentials_over_static_anthr... method test_keeps_static_anthropic_token_when_only_non_refreshable_claude_key_exists (line 233) | def test_keeps_static_anthropic_token_when_only_non_refreshable_claude... class TestRefreshOauthToken (line 244) | class TestRefreshOauthToken: method test_returns_none_without_refresh_token (line 245) | def test_returns_none_without_refresh_token(self): method test_successful_refresh (line 249) | def test_successful_refresh(self, tmp_path, monkeypatch): method test_failed_refresh_returns_none (line 282) | def test_failed_refresh_returns_none(self): class TestWriteClaudeCodeCredentials (line 293) | class TestWriteClaudeCodeCredentials: method test_writes_new_file (line 294) | def test_writes_new_file(self, tmp_path, monkeypatch): method test_preserves_existing_fields (line 304) | def test_preserves_existing_fields(self, tmp_path, monkeypatch): class TestResolveWithRefresh (line 316) | class TestResolveWithRefresh: method test_auto_refresh_on_expired_creds (line 317) | def test_auto_refresh_on_expired_creds(self, monkeypatch, tmp_path): method test_static_env_oauth_token_does_not_block_refreshable_claude_creds (line 341) | def test_static_env_oauth_token_does_not_block_refreshable_claude_cred... class TestRunOauthSetupToken (line 363) | class TestRunOauthSetupToken: method test_raises_when_claude_not_installed (line 364) | def test_raises_when_claude_not_installed(self, monkeypatch): method test_returns_token_from_credential_files (line 369) | def test_returns_token_from_credential_files(self, monkeypatch, tmp_pa... method test_returns_token_from_env_var (line 394) | def test_returns_token_from_env_var(self, monkeypatch, tmp_path): method test_returns_none_when_no_creds_found (line 407) | def test_returns_none_when_no_creds_found(self, monkeypatch, tmp_path): method test_returns_none_on_keyboard_interrupt (line 420) | def test_returns_none_on_keyboard_interrupt(self, monkeypatch): class TestNormalizeModelName (line 435) | class TestNormalizeModelName: method test_strips_anthropic_prefix (line 436) | def test_strips_anthropic_prefix(self): method test_leaves_bare_name (line 439) | def test_leaves_bare_name(self): method test_converts_dots_to_hyphens (line 442) | def test_converts_dots_to_hyphens(self): method test_already_hyphenated_unchanged (line 448) | def test_already_hyphenated_unchanged(self): class TestConvertTools (line 459) | class TestConvertTools: method test_converts_openai_to_anthropic_format (line 460) | def test_converts_openai_to_anthropic_format(self): method test_empty_tools (line 481) | def test_empty_tools(self): class TestConvertMessages (line 491) | class TestConvertMessages: method test_extracts_system_prompt (line 492) | def test_extracts_system_prompt(self): method test_converts_user_image_url_blocks_to_anthropic_image_blocks (line 502) | def test_converts_user_image_url_blocks_to_anthropic_image_blocks(self): method test_converts_data_url_image_blocks_to_base64_anthropic_image_blocks (line 525) | def test_converts_data_url_image_blocks_to_base64_anthropic_image_bloc... method test_converts_tool_calls (line 555) | def test_converts_tool_calls(self): method test_converts_tool_results (line 579) | def test_converts_tool_results(self): method test_merges_consecutive_tool_results (line 596) | def test_merges_consecutive_tool_results(self): method test_strips_orphaned_tool_use (line 615) | def test_strips_orphaned_tool_use(self): method test_strips_orphaned_tool_result (line 631) | def test_strips_orphaned_tool_result(self): method test_strips_orphaned_tool_result_preserves_valid (line 655) | def test_strips_orphaned_tool_result_preserves_valid(self): method test_system_with_cache_control (line 676) | def test_system_with_cache_control(self): method test_assistant_cache_control_blocks_are_preserved (line 691) | def test_assistant_cache_control_blocks_are_preserved(self): method test_tool_cache_control_is_preserved_on_tool_result_block (line 704) | def test_tool_cache_control_is_preserved_on_tool_result_block(self): method test_converts_data_url_image_to_anthropic_image_block (line 726) | def test_converts_data_url_image_to_anthropic_image_block(self): method test_converts_remote_image_url_to_anthropic_image_block (line 752) | def test_converts_remote_image_url_to_anthropic_image_block(self): method test_empty_cached_assistant_tool_turn_converts_without_empty_text_block (line 776) | def test_empty_cached_assistant_tool_turn_converts_without_empty_text_... class TestBuildAnthropicKwargs (line 804) | class TestBuildAnthropicKwargs: method test_basic_kwargs (line 805) | def test_basic_kwargs(self): method test_strips_anthropic_prefix (line 822) | def test_strips_anthropic_prefix(self): method test_reasoning_config_maps_to_manual_thinking_for_pre_4_6_models (line 832) | def test_reasoning_config_maps_to_manual_thinking_for_pre_4_6_models(s... method test_reasoning_config_maps_to_adaptive_thinking_for_4_6_models (line 846) | def test_reasoning_config_maps_to_adaptive_thinking_for_4_6_models(self): method test_reasoning_config_maps_xhigh_to_max_effort_for_4_6_models (line 860) | def test_reasoning_config_maps_xhigh_to_max_effort_for_4_6_models(self): method test_reasoning_disabled (line 871) | def test_reasoning_disabled(self): method test_default_max_tokens (line 881) | def test_default_max_tokens(self): class TestNormalizeResponse (line 897) | class TestNormalizeResponse: method _make_response (line 898) | def _make_response(self, content_blocks, stop_reason="end_turn"): method test_text_response (line 905) | def test_text_response(self): method test_tool_use_response (line 912) | def test_tool_use_response(self): method test_thinking_response (line 931) | def test_thinking_response(self): method test_stop_reason_mapping (line 940) | def test_stop_reason_mapping(self): method test_no_text_content (line 955) | def test_no_text_content(self): class TestRoleAlternation (line 971) | class TestRoleAlternation: method test_merges_consecutive_user_messages (line 972) | def test_merges_consecutive_user_messages(self): method test_preserves_proper_alternation (line 983) | def test_preserves_proper_alternation(self): class TestToolChoice (line 999) | class TestToolChoice: method test_auto_tool_choice (line 1011) | def test_auto_tool_choice(self): method test_required_tool_choice (line 1022) | def test_required_tool_choice(self): method test_specific_tool_choice (line 1033) | def test_specific_tool_choice(self): FILE: tests/test_anthropic_error_handling.py function _patch_agent_bootstrap (line 35) | def _patch_agent_bootstrap(monkeypatch): function _anthropic_response (line 53) | def _anthropic_response(text: str): class _RateLimitError (line 63) | class _RateLimitError(Exception): method __init__ (line 65) | def __init__(self): class _OverloadedError (line 70) | class _OverloadedError(Exception): method __init__ (line 72) | def __init__(self): class _BadRequestError (line 77) | class _BadRequestError(Exception): method __init__ (line 79) | def __init__(self): class _UnauthorizedError (line 84) | class _UnauthorizedError(Exception): method __init__ (line 86) | def __init__(self): class _ServerError (line 91) | class _ServerError(Exception): method __init__ (line 93) | def __init__(self): class _PromptTooLongError (line 98) | class _PromptTooLongError(Exception): method __init__ (line 100) | def __init__(self): class _FakeAnthropicClient (line 105) | class _FakeAnthropicClient: method close (line 106) | def close(self): function _fake_build_anthropic_client (line 110) | def _fake_build_anthropic_client(key, base_url=None): function _make_agent_cls (line 114) | def _make_agent_cls(error_cls, recover_after=None): function _run_with_agent (line 148) | def _run_with_agent(monkeypatch, agent_cls): function test_429_rate_limit_is_retried_and_recovers (line 205) | def test_429_rate_limit_is_retried_and_recovers(monkeypatch): function test_529_overloaded_is_retried_and_recovers (line 212) | def test_529_overloaded_is_retried_and_recovers(monkeypatch): function test_429_exhausts_all_retries_before_raising (line 219) | def test_429_exhausts_all_retries_before_raising(monkeypatch): function test_400_bad_request_is_non_retryable (line 226) | def test_400_bad_request_is_non_retryable(monkeypatch): function test_500_server_error_is_retried_and_recovers (line 234) | def test_500_server_error_is_retried_and_recovers(monkeypatch): function test_401_credential_refresh_recovers (line 241) | def test_401_credential_refresh_recovers(monkeypatch): function test_401_refresh_fails_is_non_retryable (line 322) | def test_401_refresh_fails_is_non_retryable(monkeypatch): function test_prompt_too_long_triggers_compression (line 396) | def test_prompt_too_long_triggers_compression(monkeypatch): FILE: tests/test_anthropic_oauth_flow.py function test_run_anthropic_oauth_flow_prefers_claude_code_credentials (line 6) | def test_run_anthropic_oauth_flow_prefers_claude_code_credentials(tmp_pa... function test_run_anthropic_oauth_flow_manual_token_still_persists (line 37) | def test_run_anthropic_oauth_flow_manual_token_still_persists(tmp_path, ... FILE: tests/test_anthropic_provider_persistence.py function test_save_anthropic_oauth_token_uses_token_slot_and_clears_api_key (line 6) | def test_save_anthropic_oauth_token_uses_token_slot_and_clears_api_key(t... function test_use_anthropic_claude_code_credentials_clears_env_slots (line 20) | def test_use_anthropic_claude_code_credentials_clears_env_slots(tmp_path... function test_save_anthropic_api_key_uses_api_key_slot_and_clears_token (line 35) | def test_save_anthropic_api_key_uses_api_key_slot_and_clears_token(tmp_p... FILE: tests/test_api_key_providers.py class TestProviderRegistry (line 35) | class TestProviderRegistry: method test_provider_registered (line 48) | def test_provider_registered(self, provider_id, name, auth_type): method test_zai_env_vars (line 55) | def test_zai_env_vars(self): method test_copilot_env_vars (line 60) | def test_copilot_env_vars(self): method test_kimi_env_vars (line 65) | def test_kimi_env_vars(self): method test_minimax_env_vars (line 70) | def test_minimax_env_vars(self): method test_minimax_cn_env_vars (line 75) | def test_minimax_cn_env_vars(self): method test_ai_gateway_env_vars (line 80) | def test_ai_gateway_env_vars(self): method test_kilocode_env_vars (line 85) | def test_kilocode_env_vars(self): method test_base_urls (line 90) | def test_base_urls(self): method test_oauth_providers_unchanged (line 100) | def test_oauth_providers_unchanged(self): function _clear_provider_env (line 127) | def _clear_provider_env(monkeypatch): class TestResolveProvider (line 133) | class TestResolveProvider: method test_explicit_zai (line 136) | def test_explicit_zai(self): method test_explicit_kimi_coding (line 139) | def test_explicit_kimi_coding(self): method test_explicit_minimax (line 142) | def test_explicit_minimax(self): method test_explicit_minimax_cn (line 145) | def test_explicit_minimax_cn(self): method test_explicit_ai_gateway (line 148) | def test_explicit_ai_gateway(self): method test_alias_glm (line 151) | def test_alias_glm(self): method test_alias_z_ai (line 154) | def test_alias_z_ai(self): method test_alias_zhipu (line 157) | def test_alias_zhipu(self): method test_alias_kimi (line 160) | def test_alias_kimi(self): method test_alias_moonshot (line 163) | def test_alias_moonshot(self): method test_alias_minimax_underscore (line 166) | def test_alias_minimax_underscore(self): method test_alias_aigateway (line 169) | def test_alias_aigateway(self): method test_alias_vercel (line 172) | def test_alias_vercel(self): method test_explicit_kilocode (line 175) | def test_explicit_kilocode(self): method test_alias_kilo (line 178) | def test_alias_kilo(self): method test_alias_kilo_code (line 181) | def test_alias_kilo_code(self): method test_alias_kilo_gateway (line 184) | def test_alias_kilo_gateway(self): method test_alias_case_insensitive (line 187) | def test_alias_case_insensitive(self): method test_alias_github_copilot (line 192) | def test_alias_github_copilot(self): method test_alias_github_models (line 195) | def test_alias_github_models(self): method test_alias_github_copilot_acp (line 198) | def test_alias_github_copilot_acp(self): method test_unknown_provider_raises (line 202) | def test_unknown_provider_raises(self): method test_auto_detects_glm_key (line 206) | def test_auto_detects_glm_key(self, monkeypatch): method test_auto_detects_zai_key (line 210) | def test_auto_detects_zai_key(self, monkeypatch): method test_auto_detects_z_ai_key (line 214) | def test_auto_detects_z_ai_key(self, monkeypatch): method test_auto_detects_kimi_key (line 218) | def test_auto_detects_kimi_key(self, monkeypatch): method test_auto_detects_minimax_key (line 222) | def test_auto_detects_minimax_key(self, monkeypatch): method test_auto_detects_minimax_cn_key (line 226) | def test_auto_detects_minimax_cn_key(self, monkeypatch): method test_auto_detects_ai_gateway_key (line 230) | def test_auto_detects_ai_gateway_key(self, monkeypatch): method test_auto_detects_kilocode_key (line 234) | def test_auto_detects_kilocode_key(self, monkeypatch): method test_openrouter_takes_priority_over_glm (line 238) | def test_openrouter_takes_priority_over_glm(self, monkeypatch): method test_auto_does_not_select_copilot_from_github_token (line 244) | def test_auto_does_not_select_copilot_from_github_token(self, monkeypa... class TestApiKeyProviderStatus (line 253) | class TestApiKeyProviderStatus: method test_unconfigured_provider (line 255) | def test_unconfigured_provider(self): method test_configured_provider (line 260) | def test_configured_provider(self, monkeypatch): method test_fallback_env_var (line 268) | def test_fallback_env_var(self, monkeypatch): method test_custom_base_url (line 275) | def test_custom_base_url(self, monkeypatch): method test_copilot_status_uses_gh_cli_token (line 281) | def test_copilot_status_uses_gh_cli_token(self, monkeypatch): method test_get_auth_status_dispatches_to_api_key (line 289) | def test_get_auth_status_dispatches_to_api_key(self, monkeypatch): method test_copilot_acp_status_detects_local_cli (line 295) | def test_copilot_acp_status_detects_local_cli(self, monkeypatch): method test_get_auth_status_dispatches_to_external_process (line 308) | def test_get_auth_status_dispatches_to_external_process(self, monkeypa... method test_non_api_key_provider (line 316) | def test_non_api_key_provider(self): class TestResolveApiKeyProviderCredentials (line 325) | class TestResolveApiKeyProviderCredentials: method test_resolve_zai_with_key (line 327) | def test_resolve_zai_with_key(self, monkeypatch): method test_resolve_copilot_with_github_token (line 335) | def test_resolve_copilot_with_github_token(self, monkeypatch): method test_resolve_copilot_with_gh_cli_fallback (line 343) | def test_resolve_copilot_with_gh_cli_fallback(self, monkeypatch): method test_try_gh_cli_token_uses_homebrew_path_when_not_on_path (line 351) | def test_try_gh_cli_token_uses_homebrew_path_when_not_on_path(self, mo... method test_resolve_copilot_acp_with_local_cli (line 377) | def test_resolve_copilot_acp_with_local_cli(self, monkeypatch): method test_resolve_kimi_with_key (line 390) | def test_resolve_kimi_with_key(self, monkeypatch): method test_resolve_minimax_with_key (line 397) | def test_resolve_minimax_with_key(self, monkeypatch): method test_resolve_minimax_cn_with_key (line 404) | def test_resolve_minimax_cn_with_key(self, monkeypatch): method test_resolve_ai_gateway_with_key (line 411) | def test_resolve_ai_gateway_with_key(self, monkeypatch): method test_resolve_kilocode_with_key (line 418) | def test_resolve_kilocode_with_key(self, monkeypatch): method test_resolve_kilocode_custom_base_url (line 425) | def test_resolve_kilocode_custom_base_url(self, monkeypatch): method test_resolve_with_custom_base_url (line 431) | def test_resolve_with_custom_base_url(self, monkeypatch): method test_resolve_without_key_returns_empty (line 437) | def test_resolve_without_key_returns_empty(self): method test_resolve_invalid_provider_raises (line 442) | def test_resolve_invalid_provider_raises(self): method test_glm_key_priority (line 446) | def test_glm_key_priority(self, monkeypatch): method test_zai_key_fallback (line 454) | def test_zai_key_fallback(self, monkeypatch): class TestRuntimeProviderResolution (line 466) | class TestRuntimeProviderResolution: method test_runtime_zai (line 468) | def test_runtime_zai(self, monkeypatch): method test_runtime_kimi (line 477) | def test_runtime_kimi(self, monkeypatch): method test_runtime_minimax (line 485) | def test_runtime_minimax(self, monkeypatch): method test_runtime_ai_gateway (line 492) | def test_runtime_ai_gateway(self, monkeypatch): method test_runtime_kilocode (line 501) | def test_runtime_kilocode(self, monkeypatch): method test_runtime_auto_detects_api_key_provider (line 510) | def test_runtime_auto_detects_api_key_provider(self, monkeypatch): method test_runtime_copilot_uses_gh_cli_token (line 517) | def test_runtime_copilot_uses_gh_cli_token(self, monkeypatch): method test_runtime_copilot_uses_responses_for_gpt_5_4 (line 526) | def test_runtime_copilot_uses_responses_for_gpt_5_4(self, monkeypatch): method test_runtime_copilot_acp_uses_process_runtime (line 549) | def test_runtime_copilot_acp_uses_process_runtime(self, monkeypatch): class TestHasAnyProviderConfigured (line 569) | class TestHasAnyProviderConfigured: method test_glm_key_counts (line 571) | def test_glm_key_counts(self, monkeypatch, tmp_path): method test_minimax_key_counts (line 581) | def test_minimax_key_counts(self, monkeypatch, tmp_path): method test_gh_cli_token_counts (line 591) | def test_gh_cli_token_counts(self, monkeypatch, tmp_path): class TestResolveKimiBaseUrl (line 609) | class TestResolveKimiBaseUrl: method test_sk_kimi_prefix_routes_to_kimi_code (line 612) | def test_sk_kimi_prefix_routes_to_kimi_code(self): method test_legacy_key_uses_default (line 616) | def test_legacy_key_uses_default(self): method test_empty_key_uses_default (line 620) | def test_empty_key_uses_default(self): method test_env_override_wins_over_sk_kimi (line 624) | def test_env_override_wins_over_sk_kimi(self): method test_env_override_wins_over_legacy (line 630) | def test_env_override_wins_over_legacy(self): class TestKimiCodeStatusAutoDetect (line 636) | class TestKimiCodeStatusAutoDetect: method test_sk_kimi_key_gets_kimi_code_url (line 639) | def test_sk_kimi_key_gets_kimi_code_url(self, monkeypatch): method test_legacy_key_gets_moonshot_url (line 645) | def test_legacy_key_gets_moonshot_url(self, monkeypatch): method test_env_override_wins (line 651) | def test_env_override_wins(self, monkeypatch): class TestKimiCodeCredentialAutoDetect (line 658) | class TestKimiCodeCredentialAutoDetect: method test_sk_kimi_key_gets_kimi_code_url (line 661) | def test_sk_kimi_key_gets_kimi_code_url(self, monkeypatch): method test_legacy_key_gets_moonshot_url (line 667) | def test_legacy_key_gets_moonshot_url(self, monkeypatch): method test_env_override_wins (line 673) | def test_env_override_wins(self, monkeypatch): method test_non_kimi_providers_unaffected (line 679) | def test_non_kimi_providers_unaffected(self, monkeypatch): class TestKimiMoonshotModelListIsolation (line 690) | class TestKimiMoonshotModelListIsolation: method test_moonshot_list_excludes_coding_plan_only_models (line 693) | def test_moonshot_list_excludes_coding_plan_only_models(self): method test_moonshot_list_contains_shared_models (line 700) | def test_moonshot_list_contains_shared_models(self): method test_coding_plan_list_contains_plan_specific_models (line 706) | def test_coding_plan_list_contains_plan_specific_models(self): FILE: tests/test_atomic_json_write.py class TestAtomicJsonWrite (line 13) | class TestAtomicJsonWrite: method test_writes_valid_json (line 16) | def test_writes_valid_json(self, tmp_path): method test_creates_parent_directories (line 24) | def test_creates_parent_directories(self, tmp_path): method test_overwrites_existing_file (line 31) | def test_overwrites_existing_file(self, tmp_path): method test_preserves_original_on_serialization_error (line 39) | def test_preserves_original_on_serialization_error(self, tmp_path): method test_no_leftover_temp_files_on_success (line 52) | def test_no_leftover_temp_files_on_success(self, tmp_path): method test_no_leftover_temp_files_on_failure (line 61) | def test_no_leftover_temp_files_on_failure(self, tmp_path): method test_cleans_up_temp_file_on_baseexception (line 71) | def test_cleans_up_temp_file_on_baseexception(self, tmp_path): method test_accepts_string_path (line 87) | def test_accepts_string_path(self, tmp_path): method test_writes_list_data (line 94) | def test_writes_list_data(self, tmp_path): method test_empty_list (line 102) | def test_empty_list(self, tmp_path): method test_custom_indent (line 109) | def test_custom_indent(self, tmp_path): method test_accepts_json_dump_default_hook (line 116) | def test_accepts_json_dump_default_hook(self, tmp_path): method test_unicode_content (line 127) | def test_unicode_content(self, tmp_path): method test_concurrent_writes_dont_corrupt (line 136) | def test_concurrent_writes_dont_corrupt(self, tmp_path): FILE: tests/test_atomic_yaml_write.py class TestAtomicYamlWrite (line 12) | class TestAtomicYamlWrite: method test_writes_valid_yaml (line 13) | def test_writes_valid_yaml(self, tmp_path): method test_cleans_up_temp_file_on_baseexception (line 21) | def test_cleans_up_temp_file_on_baseexception(self, tmp_path): method test_appends_extra_content (line 37) | def test_appends_extra_content(self, tmp_path): FILE: tests/test_auth_codex_provider.py function _setup_hermes_auth (line 25) | def _setup_hermes_auth(hermes_home: Path, *, access_token: str = "access... function _jwt_with_exp (line 47) | def _jwt_with_exp(exp_epoch: int) -> str: function test_read_codex_tokens_success (line 53) | def test_read_codex_tokens_success(tmp_path, monkeypatch): function test_read_codex_tokens_missing (line 63) | def test_read_codex_tokens_missing(tmp_path, monkeypatch): function test_resolve_codex_runtime_credentials_missing_access_token (line 75) | def test_resolve_codex_runtime_credentials_missing_access_token(tmp_path... function test_resolve_codex_runtime_credentials_refreshes_expiring_token (line 86) | def test_resolve_codex_runtime_credentials_refreshes_expiring_token(tmp_... function test_resolve_codex_runtime_credentials_force_refresh (line 106) | def test_resolve_codex_runtime_credentials_force_refresh(tmp_path, monke... function test_resolve_provider_explicit_codex_does_not_fallback (line 125) | def test_resolve_provider_explicit_codex_does_not_fallback(monkeypatch): function test_save_codex_tokens_roundtrip (line 131) | def test_save_codex_tokens_roundtrip(tmp_path, monkeypatch): function test_import_codex_cli_tokens (line 144) | def test_import_codex_cli_tokens(tmp_path, monkeypatch): function test_import_codex_cli_tokens_missing (line 158) | def test_import_codex_cli_tokens_missing(tmp_path, monkeypatch): function test_codex_tokens_not_written_to_shared_file (line 163) | def test_codex_tokens_not_written_to_shared_file(tmp_path, monkeypatch): function test_resolve_returns_hermes_auth_store_source (line 184) | def test_resolve_returns_hermes_auth_store_source(tmp_path, monkeypatch): FILE: tests/test_auth_nous_provider.py function _setup_nous_auth (line 13) | def _setup_nous_auth( function _mint_payload (line 47) | def _mint_payload(api_key: str = "agent-key") -> dict: function test_refresh_token_persisted_when_mint_returns_insufficient_credits (line 57) | def test_refresh_token_persisted_when_mint_returns_insufficient_credits(... function test_refresh_token_persisted_when_mint_times_out (line 98) | def test_refresh_token_persisted_when_mint_times_out(tmp_path, monkeypat... function test_mint_retry_uses_latest_rotated_refresh_token (line 126) | def test_mint_retry_uses_latest_rotated_refresh_token(tmp_path, monkeypa... FILE: tests/test_auxiliary_config_bridge.py function _run_auxiliary_bridge (line 19) | def _run_auxiliary_bridge(config_dict, monkeypatch): class TestAuxiliaryConfigBridge (line 74) | class TestAuxiliaryConfigBridge: method test_vision_provider_bridged (line 77) | def test_vision_provider_bridged(self, monkeypatch): method test_vision_model_bridged (line 89) | def test_vision_model_bridged(self, monkeypatch): method test_web_extract_bridged (line 100) | def test_web_extract_bridged(self, monkeypatch): method test_direct_endpoint_bridged (line 110) | def test_direct_endpoint_bridged(self, monkeypatch): method test_empty_values_not_bridged (line 125) | def test_empty_values_not_bridged(self, monkeypatch): method test_missing_auxiliary_section_safe (line 135) | def test_missing_auxiliary_section_safe(self, monkeypatch): method test_non_dict_task_config_ignored (line 141) | def test_non_dict_task_config_ignored(self, monkeypatch): method test_mixed_tasks (line 151) | def test_mixed_tasks(self, monkeypatch): method test_all_tasks_with_overrides (line 164) | def test_all_tasks_with_overrides(self, monkeypatch): method test_whitespace_in_values_stripped (line 177) | def test_whitespace_in_values_stripped(self, monkeypatch): method test_empty_auxiliary_dict_safe (line 187) | def test_empty_auxiliary_dict_safe(self, monkeypatch): class TestGatewayBridgeCodeParity (line 197) | class TestGatewayBridgeCodeParity: method test_gateway_has_auxiliary_bridge (line 200) | def test_gateway_has_auxiliary_bridge(self): method test_gateway_no_compression_env_bridge (line 214) | def test_gateway_no_compression_env_bridge(self): class TestVisionModelOverride (line 225) | class TestVisionModelOverride: method test_env_var_overrides_default (line 228) | def test_env_var_overrides_default(self, monkeypatch): method test_default_model_when_no_override (line 238) | def test_default_model_when_no_override(self, monkeypatch): class TestDefaultConfigShape (line 253) | class TestDefaultConfigShape: method test_auxiliary_section_exists (line 256) | def test_auxiliary_section_exists(self): method test_vision_task_structure (line 260) | def test_vision_task_structure(self): method test_web_extract_task_structure (line 268) | def test_web_extract_task_structure(self): method test_compression_provider_default (line 276) | def test_compression_provider_default(self): method test_compression_base_url_default (line 282) | def test_compression_base_url_default(self): class TestCLIDefaultsHaveAuxiliaryKeys (line 292) | class TestCLIDefaultsHaveAuxiliaryKeys: method test_cli_defaults_can_merge_auxiliary (line 296) | def test_cli_defaults_can_merge_auxiliary(self): FILE: tests/test_batch_runner_checkpoint.py function runner (line 19) | def runner(tmp_path): class TestSaveCheckpoint (line 33) | class TestSaveCheckpoint: method test_writes_valid_json (line 36) | def test_writes_valid_json(self, runner): method test_adds_last_updated (line 44) | def test_adds_last_updated(self, runner): method test_overwrites_previous_checkpoint (line 52) | def test_overwrites_previous_checkpoint(self, runner): method test_with_lock (line 59) | def test_with_lock(self, runner): method test_without_lock (line 67) | def test_without_lock(self, runner): method test_creates_parent_dirs (line 74) | def test_creates_parent_dirs(self, tmp_path): method test_no_temp_files_left (line 83) | def test_no_temp_files_left(self, runner): class TestLoadCheckpoint (line 91) | class TestLoadCheckpoint: method test_returns_empty_when_no_file (line 94) | def test_returns_empty_when_no_file(self, runner): method test_loads_existing_checkpoint (line 98) | def test_loads_existing_checkpoint(self, runner): method test_handles_corrupt_json (line 107) | def test_handles_corrupt_json(self, runner): class TestResumePreservesProgress (line 115) | class TestResumePreservesProgress: method test_completed_prompts_loaded_from_checkpoint (line 118) | def test_completed_prompts_loaded_from_checkpoint(self, runner): method test_different_run_name_starts_fresh (line 141) | def test_different_run_name_starts_fresh(self, runner): FILE: tests/test_cli_approval_ui.py function _make_cli_stub (line 10) | def _make_cli_stub(): class TestCliApprovalUi (line 20) | class TestCliApprovalUi: method test_approval_callback_includes_view_for_long_commands (line 21) | def test_approval_callback_includes_view_for_long_commands(self): method test_handle_approval_selection_view_expands_in_place (line 43) | def test_handle_approval_selection_view_expands_in_place(self): method test_approval_display_places_title_inside_box_not_border (line 61) | def test_approval_display_places_title_inside_box_not_border(self): method test_approval_display_shows_full_command_after_view (line 81) | def test_approval_display_shows_full_command_after_view(self): FILE: tests/test_cli_init.py function _make_cli (line 11) | def _make_cli(env_overrides=None, config_overrides=None, **kwargs): class TestMaxTurnsResolution (line 56) | class TestMaxTurnsResolution: method test_default_max_turns_is_integer (line 59) | def test_default_max_turns_is_integer(self): method test_explicit_max_turns_honored (line 64) | def test_explicit_max_turns_honored(self): method test_none_max_turns_gets_default (line 68) | def test_none_max_turns_gets_default(self): method test_env_var_max_turns (line 73) | def test_env_var_max_turns(self): method test_legacy_root_max_turns_is_used_when_agent_key_exists_without_value (line 78) | def test_legacy_root_max_turns_is_used_when_agent_key_exists_without_v... method test_max_turns_never_none_for_agent (line 82) | def test_max_turns_never_none_for_agent(self): class TestVerboseAndToolProgress (line 88) | class TestVerboseAndToolProgress: method test_default_verbose_is_bool (line 89) | def test_default_verbose_is_bool(self): method test_tool_progress_mode_is_string (line 93) | def test_tool_progress_mode_is_string(self): class TestSingleQueryState (line 99) | class TestSingleQueryState: method test_voice_and_interrupt_state_initialized_before_run (line 100) | def test_voice_and_interrupt_state_initialized_before_run(self): class TestHistoryDisplay (line 110) | class TestHistoryDisplay: method test_history_numbers_only_visible_messages_and_summarizes_tools (line 111) | def test_history_numbers_only_visible_messages_and_summarizes_tools(se... class TestProviderResolution (line 142) | class TestProviderResolution: method test_api_key_is_string_or_none (line 143) | def test_api_key_is_string_or_none(self): method test_base_url_is_string (line 147) | def test_base_url_is_string(self): method test_model_is_string (line 152) | def test_model_is_string(self): FILE: tests/test_cli_interrupt_subagent.py class TestCLISubagentInterrupt (line 24) | class TestCLISubagentInterrupt(unittest.TestCase): method setUp (line 27) | def setUp(self): method tearDown (line 30) | def tearDown(self): method test_full_delegate_interrupt_flow (line 33) | def test_full_delegate_interrupt_flow(self): FILE: tests/test_cli_loading_indicator.py class TestCLILoadingIndicator (line 8) | class TestCLILoadingIndicator: method _make_cli (line 9) | def _make_cli(self): method test_skills_command_sets_busy_state_and_prints_status (line 17) | def test_skills_command_sets_busy_state_and_prints_status(self, capsys): method test_reload_mcp_sets_busy_state_and_prints_status (line 43) | def test_reload_mcp_sets_busy_state_and_prints_status(self, capsys): FILE: tests/test_cli_mcp_config_watch.py function _make_cli (line 7) | def _make_cli(tmp_path, mcp_servers=None): class TestMCPConfigWatch (line 29) | class TestMCPConfigWatch: method test_no_change_does_not_reload (line 31) | def test_no_change_does_not_reload(self, tmp_path): method test_mtime_change_with_same_mcp_servers_does_not_reload (line 40) | def test_mtime_change_with_same_mcp_servers_does_not_reload(self, tmp_... method test_new_mcp_server_triggers_reload (line 55) | def test_new_mcp_server_triggers_reload(self, tmp_path): method test_removed_mcp_server_triggers_reload (line 69) | def test_removed_mcp_server_triggers_reload(self, tmp_path): method test_interval_throttle_skips_check (line 83) | def test_interval_throttle_skips_check(self, tmp_path): method test_missing_config_file_does_not_crash (line 95) | def test_missing_config_file_does_not_crash(self, tmp_path): FILE: tests/test_cli_model_command.py class TestModelCommand (line 8) | class TestModelCommand: method _make_cli (line 9) | def _make_cli(self): method test_valid_model_from_api_saved_to_config (line 21) | def test_valid_model_from_api_saved_to_config(self, capsys): method test_unlisted_model_accepted_with_warning (line 34) | def test_unlisted_model_accepted_with_warning(self, capsys): method test_api_unreachable_accepts_and_persists (line 46) | def test_api_unreachable_accepts_and_persists(self, capsys): method test_no_slash_model_accepted_with_warning (line 58) | def test_no_slash_model_accepted_with_warning(self, capsys): method test_validation_crash_falls_back_to_save (line 70) | def test_validation_crash_falls_back_to_save(self, capsys): method test_show_model_when_no_argument (line 83) | def test_show_model_when_no_argument(self, capsys): method test_provider_colon_model_switches_provider (line 95) | def test_provider_colon_model_switches_provider(self, capsys): method test_provider_switch_fails_on_bad_credentials (line 117) | def test_provider_switch_fails_on_bad_credentials(self, capsys): FILE: tests/test_cli_new_session.py class _FakeCompressor (line 15) | class _FakeCompressor: method __init__ (line 18) | def __init__(self): class _FakeAgent (line 26) | class _FakeAgent: method __init__ (line 27) | def __init__(self, session_id: str, session_start): method reset_session_state (line 54) | def reset_session_state(self): function _make_cli (line 76) | def _make_cli(env_overrides=None, config_overrides=None, **kwargs): function _prepare_cli_with_active_session (line 122) | def _prepare_cli_with_active_session(tmp_path): function test_new_command_creates_real_fresh_session_and_resets_agent_state (line 136) | def test_new_command_creates_real_fresh_session_and_resets_agent_state(t... function test_reset_command_is_alias_for_new_session (line 163) | def test_reset_command_is_alias_for_new_session(tmp_path): function test_clear_command_starts_new_session_before_redrawing (line 174) | def test_clear_command_starts_new_session_before_redrawing(tmp_path): function test_new_session_resets_token_counters (line 190) | def test_new_session_resets_token_counters(tmp_path): FILE: tests/test_cli_plan_command.py function _make_cli (line 9) | def _make_cli(): function _make_plan_skill (line 20) | def _make_plan_skill(skills_dir): class TestCLIPlanCommand (line 37) | class TestCLIPlanCommand: method test_plan_command_queues_plan_skill_message (line 38) | def test_plan_command_queues_plan_skill_message(self, tmp_path, monkey... method test_plan_without_args_uses_skill_context_guidance (line 56) | def test_plan_without_args_uses_skill_context_guidance(self, tmp_path,... FILE: tests/test_cli_prefix_matching.py function _make_cli (line 6) | def _make_cli(): class TestSlashCommandPrefixMatching (line 17) | class TestSlashCommandPrefixMatching: method test_unique_prefix_dispatches_command (line 18) | def test_unique_prefix_dispatches_command(self): method test_unique_prefix_with_args_does_not_recurse (line 25) | def test_unique_prefix_with_args_does_not_recurse(self): method test_exact_command_with_args_does_not_recurse (line 49) | def test_exact_command_with_args_does_not_recurse(self): method test_ambiguous_prefix_shows_suggestions (line 72) | def test_ambiguous_prefix_shows_suggestions(self): method test_unknown_command_shows_error (line 80) | def test_unknown_command_shows_error(self): method test_exact_command_still_works (line 88) | def test_exact_command_still_works(self): method test_skill_command_prefix_matches (line 95) | def test_skill_command_prefix_matches(self): method test_ambiguous_between_builtin_and_skill (line 110) | def test_ambiguous_between_builtin_and_skill(self): method test_shortest_match_preferred_over_longer_skill (line 125) | def test_shortest_match_preferred_over_longer_skill(self): method test_tied_shortest_matches_still_ambiguous (line 140) | def test_tied_shortest_matches_still_ambiguous(self): method test_exact_typed_name_dispatches_over_longer_match (line 150) | def test_exact_typed_name_dispatches_over_longer_match(self): FILE: tests/test_cli_preloaded_skills.py function _make_real_cli (line 11) | def _make_real_cli(**kwargs): class _DummyCLI (line 51) | class _DummyCLI: method __init__ (line 52) | def __init__(self, **kwargs): method show_banner (line 58) | def show_banner(self): method show_tools (line 61) | def show_tools(self): method show_toolsets (line 64) | def show_toolsets(self): method run (line 67) | def run(self): function test_main_applies_preloaded_skills_to_system_prompt (line 71) | def test_main_applies_preloaded_skills_to_system_prompt(monkeypatch): function test_main_raises_for_unknown_preloaded_skill (line 95) | def test_main_raises_for_unknown_preloaded_skill(monkeypatch): function test_show_banner_prints_preloaded_skills_once_before_banner (line 109) | def test_show_banner_prints_preloaded_skills_once_before_banner(): FILE: tests/test_cli_provider_resolution.py function _install_prompt_toolkit_stubs (line 11) | def _install_prompt_toolkit_stubs(): function _import_cli (line 80) | def _import_cli(): function test_hermes_cli_init_does_not_eagerly_resolve_runtime_provider (line 88) | def test_hermes_cli_init_does_not_eagerly_resolve_runtime_provider(monke... function test_runtime_resolution_failure_is_not_sticky (line 105) | def test_runtime_resolution_failure_is_not_sticky(monkeypatch): function test_runtime_resolution_rebuilds_agent_on_routing_change (line 137) | def test_runtime_resolution_rebuilds_agent_on_routing_change(monkeypatch): function test_cli_turn_routing_uses_primary_when_disabled (line 165) | def test_cli_turn_routing_uses_primary_when_disabled(monkeypatch): function test_cli_turn_routing_uses_cheap_model_when_simple (line 181) | def test_cli_turn_routing_uses_cheap_model_when_simple(monkeypatch): function test_cli_prefers_config_provider_over_stale_env_override (line 216) | def test_cli_prefers_config_provider_over_stale_env_override(monkeypatch): function test_codex_provider_replaces_incompatible_default_model (line 232) | def test_codex_provider_replaces_incompatible_default_model(monkeypatch): function test_codex_provider_uses_config_model (line 272) | def test_codex_provider_uses_config_model(monkeypatch): function test_codex_config_model_not_replaced_by_normalization (line 315) | def test_codex_config_model_not_replaced_by_normalization(monkeypatch): function test_codex_provider_preserves_explicit_codex_model (line 358) | def test_codex_provider_preserves_explicit_codex_model(monkeypatch): function test_codex_provider_strips_provider_prefix_from_model (line 385) | def test_codex_provider_strips_provider_prefix_from_model(monkeypatch): function test_cmd_model_falls_back_to_auto_on_invalid_provider (line 411) | def test_cmd_model_falls_back_to_auto_on_invalid_provider(monkeypatch, c... function test_model_flow_custom_saves_verified_v1_base_url (line 436) | def test_model_flow_custom_saves_verified_v1_base_url(monkeypatch, capsys): FILE: tests/test_cli_retry.py function test_retry_last_truncates_history_before_requeueing_message (line 6) | def test_retry_last_truncates_history_before_requeueing_message(): function test_process_command_retry_requeues_original_message_not_retry_command (line 32) | def test_process_command_retry_requeues_original_message_not_retry_comma... FILE: tests/test_cli_secret_capture.py class _FakeBuffer (line 13) | class _FakeBuffer: method __init__ (line 14) | def __init__(self): method reset (line 17) | def reset(self): class _FakeApp (line 21) | class _FakeApp: method __init__ (line 22) | def __init__(self): method invalidate (line 26) | def invalidate(self): function _make_cli_stub (line 30) | def _make_cli_stub(with_app=False): function test_secret_capture_callback_can_be_completed_from_cli_state_machine (line 39) | def test_secret_capture_callback_can_be_completed_from_cli_state_machine(): function test_cancel_secret_capture_marks_setup_skipped (line 70) | def test_cancel_secret_capture_marks_setup_skipped(): function test_secret_capture_uses_getpass_without_tui (line 86) | def test_secret_capture_uses_getpass_without_tui(): function test_secret_capture_timeout_clears_hidden_input_buffer (line 104) | def test_secret_capture_timeout_clears_hidden_input_buffer(): function test_cli_chat_registers_secret_capture_callback (line 125) | def test_cli_chat_registers_secret_capture_callback(): FILE: tests/test_cli_skin_integration.py function _make_cli_stub (line 8) | def _make_cli_stub(): class TestCliSkinPromptIntegration (line 32) | class TestCliSkinPromptIntegration: method test_default_prompt_fragments_use_default_symbol (line 33) | def test_default_prompt_fragments_use_default_symbol(self): method test_ares_prompt_fragments_use_skin_symbol (line 39) | def test_ares_prompt_fragments_use_skin_symbol(self): method test_secret_prompt_fragments_preserve_secret_state (line 45) | def test_secret_prompt_fragments_preserve_secret_state(self): method test_icon_only_skin_symbol_still_visible_in_special_states (line 52) | def test_icon_only_skin_symbol_still_visible_in_special_states(self): method test_build_tui_style_dict_uses_skin_overrides (line 59) | def test_build_tui_style_dict_uses_skin_overrides(self): method test_apply_tui_skin_style_updates_running_app (line 71) | def test_apply_tui_skin_style_updates_running_app(self): method test_handle_skin_command_refreshes_live_tui (line 79) | def test_handle_skin_command_refreshes_live_tui(self, capsys): class TestAnsiRichTextHelper (line 91) | class TestAnsiRichTextHelper: method test_preserves_literal_brackets (line 92) | def test_preserves_literal_brackets(self): method test_strips_ansi_but_keeps_plain_text (line 96) | def test_strips_ansi_but_keeps_plain_text(self): FILE: tests/test_cli_status_bar.py function _make_cli (line 7) | def _make_cli(model: str = "anthropic/claude-sonnet-4-20250514"): function _attach_agent (line 16) | def _attach_agent( class TestCLIStatusBar (line 52) | class TestCLIStatusBar: method test_context_style_thresholds (line 53) | def test_context_style_thresholds(self): method test_build_status_bar_text_for_wide_terminal (line 62) | def test_build_status_bar_text_for_wide_terminal(self): method test_build_status_bar_text_no_cost_in_status_bar (line 81) | def test_build_status_bar_text_no_cost_in_status_bar(self): method test_build_status_bar_text_collapses_for_narrow_terminal (line 95) | def test_build_status_bar_text_collapses_for_narrow_terminal(self): method test_build_status_bar_text_handles_missing_agent (line 113) | def test_build_status_bar_text_handles_missing_agent(self): class TestCLIUsageReport (line 122) | class TestCLIUsageReport: method test_show_usage_includes_estimated_cost (line 123) | def test_show_usage_includes_estimated_cost(self, capsys): method test_show_usage_marks_unknown_pricing (line 148) | def test_show_usage_marks_unknown_pricing(self, capsys): method test_zero_priced_provider_models_stay_unknown (line 167) | def test_zero_priced_provider_models_stay_unknown(self, capsys): FILE: tests/test_cli_tools_command.py function _make_cli (line 8) | def _make_cli(enabled_toolsets=None): class TestToolsSlashNoSubcommand (line 20) | class TestToolsSlashNoSubcommand: method test_bare_tools_shows_tool_list (line 22) | def test_bare_tools_shows_tool_list(self): method test_unknown_subcommand_falls_back_to_show_tools (line 28) | def test_unknown_subcommand_falls_back_to_show_tools(self): class TestToolsSlashList (line 38) | class TestToolsSlashList: method test_list_calls_backend (line 40) | def test_list_calls_backend(self, capsys): method test_list_does_not_modify_enabled_toolsets (line 49) | def test_list_does_not_modify_enabled_toolsets(self): class TestToolsSlashDisableWithReset (line 61) | class TestToolsSlashDisableWithReset: method test_disable_confirms_then_resets_session (line 63) | def test_disable_confirms_then_resets_session(self): method test_disable_cancelled_does_not_reset (line 76) | def test_disable_cancelled_does_not_reset(self): method test_disable_eof_cancels (line 85) | def test_disable_eof_cancels(self): method test_disable_missing_name_prints_usage (line 92) | def test_disable_missing_name_prints_usage(self, capsys): class TestToolsSlashEnableWithReset (line 102) | class TestToolsSlashEnableWithReset: method test_enable_confirms_then_resets_session (line 104) | def test_enable_confirms_then_resets_session(self): method test_enable_missing_name_prints_usage (line 117) | def test_enable_missing_name_prints_usage(self, capsys): FILE: tests/test_codex_execution_paths.py function _patch_agent_bootstrap (line 18) | def _patch_agent_bootstrap(monkeypatch): function _codex_message_response (line 36) | def _codex_message_response(text: str): class _UnauthorizedError (line 50) | class _UnauthorizedError(RuntimeError): method __init__ (line 51) | def __init__(self): class _FakeOpenAI (line 56) | class _FakeOpenAI: method __init__ (line 57) | def __init__(self, **kwargs): method close (line 60) | def close(self): class _Codex401ThenSuccessAgent (line 64) | class _Codex401ThenSuccessAgent(run_agent.AIAgent): method __init__ (line 68) | def __init__(self, *args, **kwargs): method _try_refresh_codex_client_credentials (line 79) | def _try_refresh_codex_client_credentials(self, *, force: bool = True)... method run_conversation (line 83) | def run_conversation(self, user_message: str, conversation_history=Non... function test_cron_run_job_codex_path_handles_internal_401_refresh (line 96) | def test_cron_run_job_codex_path_handles_internal_401_refresh(monkeypatch): function test_gateway_run_agent_codex_path_handles_internal_401_refresh (line 127) | def test_gateway_run_agent_codex_path_handles_internal_401_refresh(monke... FILE: tests/test_codex_models.py function test_get_codex_model_ids_prioritizes_default_and_cache (line 11) | def test_get_codex_model_ids_prioritizes_default_and_cache(tmp_path, mon... function test_setup_wizard_codex_import_resolves (line 39) | def test_setup_wizard_codex_import_resolves(): function test_get_codex_model_ids_falls_back_to_curated_defaults (line 47) | def test_get_codex_model_ids_falls_back_to_curated_defaults(tmp_path, mo... function test_get_codex_model_ids_adds_forward_compat_models_from_templates (line 59) | def test_get_codex_model_ids_adds_forward_compat_models_from_templates(m... function test_model_command_uses_runtime_access_token_for_codex_list (line 70) | def test_model_command_uses_runtime_access_token_for_codex_list(monkeypa... function _make_cli (line 112) | def _make_cli(model="anthropic/claude-opus-4.6", **kwargs): class TestNormalizeModelForProvider (line 137) | class TestNormalizeModelForProvider: method test_non_codex_provider_is_noop (line 146) | def test_non_codex_provider_is_noop(self): method test_bare_codex_model_passes_through (line 152) | def test_bare_codex_model_passes_through(self): method test_bare_non_codex_model_passes_through (line 158) | def test_bare_non_codex_model_passes_through(self): method test_any_bare_model_trusted (line 165) | def test_any_bare_model_trusted(self): method test_provider_prefix_stripped (line 173) | def test_provider_prefix_stripped(self): method test_any_provider_prefix_stripped (line 180) | def test_any_provider_prefix_stripped(self): method test_default_model_replaced (line 188) | def test_default_model_replaced(self): method test_default_fallback_when_api_fails (line 220) | def test_default_fallback_when_api_fails(self): FILE: tests/test_compression_boundary.py function _tc (line 17) | def _tc(call_id: str) -> dict: function _tool_result (line 22) | def _tool_result(call_id: str, content: str = "result") -> dict: function _assistant_with_tools (line 27) | def _assistant_with_tools(*call_ids: str) -> dict: function _make_compressor (line 32) | def _make_compressor(**kwargs) -> ContextCompressor: class TestAlignBoundaryBackward (line 49) | class TestAlignBoundaryBackward: method test_boundary_at_clean_position (line 52) | def test_boundary_at_clean_position(self): method test_boundary_after_assistant_with_tools (line 68) | def test_boundary_after_assistant_with_tools(self): method test_boundary_in_middle_of_tool_results (line 83) | def test_boundary_in_middle_of_tool_results(self): method test_boundary_at_last_tool_result (line 104) | def test_boundary_at_last_tool_result(self): method test_boundary_with_consecutive_tool_groups (line 121) | def test_boundary_with_consecutive_tool_groups(self): class TestCompressionToolResultPreservation (line 144) | class TestCompressionToolResultPreservation: method test_parallel_tool_results_not_lost (line 147) | def test_parallel_tool_results_not_lost(self): FILE: tests/test_context_pressure.py class TestFormatContextPressure (line 25) | class TestFormatContextPressure: method test_60_percent_uses_info_icon (line 32) | def test_60_percent_uses_info_icon(self): method test_85_percent_uses_warning_icon (line 37) | def test_85_percent_uses_warning_icon(self): method test_bar_length_scales_with_progress (line 42) | def test_bar_length_scales_with_progress(self): method test_shows_threshold_tokens (line 47) | def test_shows_threshold_tokens(self): method test_small_threshold (line 51) | def test_small_threshold(self): method test_shows_threshold_percent (line 55) | def test_shows_threshold_percent(self): method test_imminent_hint_at_85 (line 59) | def test_imminent_hint_at_85(self): method test_approaching_hint_below_85 (line 63) | def test_approaching_hint_below_85(self): method test_no_compaction_when_disabled (line 67) | def test_no_compaction_when_disabled(self): method test_returns_string (line 71) | def test_returns_string(self): method test_over_100_percent_capped (line 75) | def test_over_100_percent_capped(self): class TestFormatContextPressureGateway (line 82) | class TestFormatContextPressureGateway: method test_60_percent_informational (line 85) | def test_60_percent_informational(self): method test_85_percent_warning (line 90) | def test_85_percent_warning(self): method test_no_compaction_warning (line 95) | def test_no_compaction_warning(self): method test_no_ansi_codes (line 99) | def test_no_ansi_codes(self): method test_has_progress_bar (line 103) | def test_has_progress_bar(self): function _make_tool_defs (line 113) | def _make_tool_defs(*names): function agent (line 128) | def agent(): class TestContextPressureFlags (line 145) | class TestContextPressureFlags: method test_flags_initialized_false (line 148) | def test_flags_initialized_false(self, agent): method test_emit_calls_status_callback (line 152) | def test_emit_calls_status_callback(self, agent): method test_emit_no_callback_no_crash (line 168) | def test_emit_no_callback_no_crash(self, agent): method test_emit_prints_for_cli_platform (line 179) | def test_emit_prints_for_cli_platform(self, agent, capsys): method test_emit_skips_print_for_gateway_platform (line 194) | def test_emit_skips_print_for_gateway_platform(self, agent, capsys): method test_flags_reset_on_compression (line 207) | def test_flags_reset_on_compression(self, agent): method test_emit_callback_error_handled (line 239) | def test_emit_callback_error_handled(self, agent): FILE: tests/test_context_token_tracking.py function _patch_bootstrap (line 20) | def _patch_bootstrap(monkeypatch): class _FakeAnthropicClient (line 28) | class _FakeAnthropicClient: method close (line 29) | def close(self): function _make_agent (line 33) | def _make_agent(monkeypatch, api_mode, provider, response_fn): function _anthropic_resp (line 52) | def _anthropic_resp(input_tok, output_tok, cache_read=0, cache_creation=0): function test_anthropic_cache_read_and_creation_added (line 68) | def test_anthropic_cache_read_and_creation_added(monkeypatch): function test_anthropic_no_cache_fields (line 76) | def test_anthropic_no_cache_fields(monkeypatch): function test_anthropic_cache_read_only (line 83) | def test_anthropic_cache_read_only(monkeypatch): function test_openai_prompt_tokens_unchanged (line 92) | def test_openai_prompt_tokens_unchanged(monkeypatch): function test_codex_no_cache_fields (line 107) | def test_codex_no_cache_fields(monkeypatch): FILE: tests/test_dict_tool_call_args.py function _tool_call (line 5) | def _tool_call(name: str, arguments): function _response_with_tool_call (line 13) | def _response_with_tool_call(arguments): class _FakeChatCompletions (line 23) | class _FakeChatCompletions: method __init__ (line 24) | def __init__(self): method create (line 27) | def create(self, **kwargs): class _FakeClient (line 42) | class _FakeClient: method __init__ (line 43) | def __init__(self): function test_tool_call_validation_accepts_dict_arguments (line 47) | def test_tool_call_validation_accepts_dict_arguments(monkeypatch): FILE: tests/test_display.py class TestBuildToolPreview (line 7) | class TestBuildToolPreview: method test_none_args_returns_none (line 10) | def test_none_args_returns_none(self): method test_empty_dict_returns_none (line 14) | def test_empty_dict_returns_none(self): method test_known_tool_with_primary_arg (line 18) | def test_known_tool_with_primary_arg(self): method test_web_search_preview (line 24) | def test_web_search_preview(self): method test_read_file_preview (line 29) | def test_read_file_preview(self): method test_unknown_tool_with_fallback_key (line 34) | def test_unknown_tool_with_fallback_key(self): method test_unknown_tool_no_matching_key (line 40) | def test_unknown_tool_no_matching_key(self): method test_long_value_truncated (line 45) | def test_long_value_truncated(self): method test_process_tool_with_none_args (line 52) | def test_process_tool_with_none_args(self): method test_process_tool_normal (line 56) | def test_process_tool_normal(self): method test_todo_tool_read (line 61) | def test_todo_tool_read(self): method test_todo_tool_with_todos (line 66) | def test_todo_tool_with_todos(self): method test_memory_tool_add (line 71) | def test_memory_tool_add(self): method test_session_search_preview (line 76) | def test_session_search_preview(self): method test_false_like_args_zero (line 81) | def test_false_like_args_zero(self): FILE: tests/test_evidence_store.py function test_evidence_store_init (line 17) | def test_evidence_store_init(tmp_path): function test_evidence_store_add (line 27) | def test_evidence_store_add(tmp_path): function test_evidence_store_add_persists (line 50) | def test_evidence_store_add_persists(tmp_path): function test_evidence_store_sequential_ids (line 61) | def test_evidence_store_sequential_ids(tmp_path): function test_evidence_store_list (line 74) | def test_evidence_store_list(tmp_path): function test_evidence_store_verify_integrity (line 93) | def test_evidence_store_verify_integrity(tmp_path): function test_evidence_store_query (line 107) | def test_evidence_store_query(tmp_path): function test_evidence_store_query_searches_multiple_fields (line 123) | def test_evidence_store_query_searches_multiple_fields(tmp_path): function test_evidence_store_chain_of_custody (line 138) | def test_evidence_store_chain_of_custody(tmp_path): function test_evidence_store_export_markdown (line 152) | def test_evidence_store_export_markdown(tmp_path): function test_evidence_store_summary (line 165) | def test_evidence_store_summary(tmp_path): function test_evidence_store_corrupted_file (line 181) | def test_evidence_store_corrupted_file(tmp_path): FILE: tests/test_external_credential_detection.py class TestDetectCodexCLI (line 12) | class TestDetectCodexCLI: method test_detects_valid_codex_auth (line 13) | def test_detects_valid_codex_auth(self, tmp_path, monkeypatch): method test_skips_codex_without_access_token (line 26) | def test_skips_codex_without_access_token(self, tmp_path, monkeypatch): method test_skips_missing_codex_dir (line 34) | def test_skips_missing_codex_dir(self, tmp_path, monkeypatch): method test_skips_malformed_codex_auth (line 39) | def test_skips_malformed_codex_auth(self, tmp_path, monkeypatch): method test_returns_empty_when_nothing_found (line 47) | def test_returns_empty_when_nothing_found(self, tmp_path, monkeypatch): FILE: tests/test_fallback_model.py function _make_tool_defs (line 16) | def _make_tool_defs(*names: str) -> list: function _make_agent (line 30) | def _make_agent(fallback_model=None): function _mock_resolve (line 48) | def _mock_resolve(base_url="https://openrouter.ai/api/v1", api_key="test... class TestTryActivateFallback (line 60) | class TestTryActivateFallback: method test_returns_false_when_not_configured (line 61) | def test_returns_false_when_not_configured(self): method test_returns_false_for_empty_config (line 66) | def test_returns_false_for_empty_config(self): method test_returns_false_for_missing_provider (line 70) | def test_returns_false_for_missing_provider(self): method test_returns_false_for_missing_model (line 74) | def test_returns_false_for_missing_model(self): method test_activates_openrouter_fallback (line 78) | def test_activates_openrouter_fallback(self): method test_activates_zai_fallback (line 98) | def test_activates_zai_fallback(self): method test_activates_kimi_fallback (line 116) | def test_activates_kimi_fallback(self): method test_activates_minimax_fallback (line 132) | def test_activates_minimax_fallback(self): method test_only_fires_once (line 149) | def test_only_fires_once(self): method test_returns_false_when_no_api_key (line 165) | def test_returns_false_when_no_api_key(self): method test_custom_base_url (line 177) | def test_custom_base_url(self): method test_prompt_caching_enabled_for_claude_on_openrouter (line 199) | def test_prompt_caching_enabled_for_claude_on_openrouter(self): method test_prompt_caching_disabled_for_non_claude (line 214) | def test_prompt_caching_disabled_for_non_claude(self): method test_prompt_caching_disabled_for_non_openrouter (line 229) | def test_prompt_caching_disabled_for_non_openrouter(self): method test_zai_alt_env_var (line 244) | def test_zai_alt_env_var(self): method test_activates_codex_fallback (line 260) | def test_activates_codex_fallback(self): method test_codex_fallback_fails_gracefully_without_credentials (line 280) | def test_codex_fallback_fails_gracefully_without_credentials(self): method test_activates_nous_fallback (line 292) | def test_activates_nous_fallback(self): method test_nous_fallback_fails_gracefully_without_login (line 312) | def test_nous_fallback_fails_gracefully_without_login(self): class TestFallbackInit (line 329) | class TestFallbackInit: method test_fallback_stored_when_configured (line 330) | def test_fallback_stored_when_configured(self): method test_fallback_none_when_not_configured (line 338) | def test_fallback_none_when_not_configured(self): method test_fallback_none_for_non_dict (line 343) | def test_fallback_none_for_non_dict(self): class TestProviderCredentials (line 352) | class TestProviderCredentials: method test_provider_resolves (line 362) | def test_provider_resolves(self, provider, env_var, base_url_fragment): FILE: tests/test_file_permissions.py class TestCronFilePermissions (line 12) | class TestCronFilePermissions(unittest.TestCase): method setUp (line 15) | def setUp(self): method tearDown (line 20) | def tearDown(self): method test_ensure_dirs_sets_0700 (line 27) | def test_ensure_dirs_sets_0700(self, mock_jobs_file, mock_output, mock... method test_save_jobs_sets_0600 (line 46) | def test_save_jobs_sets_0600(self, mock_jobs_file, mock_output, mock_c... method test_save_job_output_sets_0600 (line 60) | def test_save_job_output_sets_0600(self): class TestConfigFilePermissions (line 78) | class TestConfigFilePermissions(unittest.TestCase): method setUp (line 81) | def setUp(self): method tearDown (line 84) | def tearDown(self): method test_save_config_sets_0600 (line 88) | def test_save_config_sets_0600(self): method test_save_env_value_sets_0600 (line 98) | def test_save_env_value_sets_0600(self): method test_ensure_hermes_home_sets_0700 (line 108) | def test_ensure_hermes_home_sets_0700(self): class TestSecureHelpers (line 122) | class TestSecureHelpers(unittest.TestCase): method test_secure_file_nonexistent_no_error (line 125) | def test_secure_file_nonexistent_no_error(self): method test_secure_dir_nonexistent_no_error (line 129) | def test_secure_dir_nonexistent_no_error(self): FILE: tests/test_flush_memories_codex.py class _FakeOpenAI (line 23) | class _FakeOpenAI: method __init__ (line 24) | def __init__(self, **kwargs): method close (line 29) | def close(self): function _make_agent (line 33) | def _make_agent(monkeypatch, api_mode="chat_completions", provider="open... function _chat_response_with_memory_call (line 72) | def _chat_response_with_memory_call(): class TestFlushMemoriesUsesAuxiliaryClient (line 94) | class TestFlushMemoriesUsesAuxiliaryClient: method test_flush_uses_auxiliary_when_available (line 98) | def test_flush_uses_auxiliary_when_available(self, monkeypatch): method test_flush_uses_main_client_when_no_auxiliary (line 116) | def test_flush_uses_main_client_when_no_auxiliary(self, monkeypatch): method test_flush_executes_memory_tool_calls (line 133) | def test_flush_executes_memory_tool_calls(self, monkeypatch): method test_flush_strips_artifacts_from_messages (line 154) | def test_flush_strips_artifacts_from_messages(self, monkeypatch): class TestFlushMemoriesCodexFallback (line 177) | class TestFlushMemoriesCodexFallback: method test_codex_mode_no_aux_uses_responses_api (line 181) | def test_codex_mode_no_aux_uses_responses_api(self, monkeypatch): FILE: tests/test_hermes_state.py function db (line 11) | def db(tmp_path): class TestSessionLifecycle (line 23) | class TestSessionLifecycle: method test_create_and_get_session (line 24) | def test_create_and_get_session(self, db): method test_get_nonexistent_session (line 38) | def test_get_nonexistent_session(self, db): method test_end_session (line 41) | def test_end_session(self, db): method test_update_system_prompt (line 49) | def test_update_system_prompt(self, db): method test_update_token_counts (line 56) | def test_update_token_counts(self, db): method test_update_token_counts_backfills_model_when_null (line 65) | def test_update_token_counts_backfills_model_when_null(self, db): method test_update_token_counts_preserves_existing_model (line 72) | def test_update_token_counts_preserves_existing_model(self, db): method test_parent_session (line 79) | def test_parent_session(self, db): class TestMessageStorage (line 91) | class TestMessageStorage: method test_append_and_get_messages (line 92) | def test_append_and_get_messages(self, db): method test_message_increments_session_count (line 103) | def test_message_increments_session_count(self, db): method test_tool_response_does_not_increment_tool_count (line 111) | def test_tool_response_does_not_increment_tool_count(self, db): method test_assistant_tool_calls_increment_by_count (line 122) | def test_assistant_tool_calls_increment_by_count(self, db): method test_tool_call_count_matches_actual_calls (line 133) | def test_tool_call_count_matches_actual_calls(self, db): method test_tool_calls_serialization (line 155) | def test_tool_calls_serialization(self, db): method test_get_messages_as_conversation (line 163) | def test_get_messages_as_conversation(self, db): method test_finish_reason_stored (line 173) | def test_finish_reason_stored(self, db): class TestFTS5Search (line 185) | class TestFTS5Search: method test_search_finds_content (line 186) | def test_search_finds_content(self, db): method test_search_empty_query (line 197) | def test_search_empty_query(self, db): method test_search_with_source_filter (line 201) | def test_search_with_source_filter(self, db): method test_search_default_sources_include_acp (line 213) | def test_search_default_sources_include_acp(self, db): method test_search_default_includes_all_platforms (line 221) | def test_search_default_includes_all_platforms(self, db): method test_search_with_role_filter (line 232) | def test_search_with_role_filter(self, db): method test_search_returns_context (line 241) | def test_search_returns_context(self, db): method test_search_special_chars_do_not_crash (line 252) | def test_search_special_chars_do_not_crash(self, db): method test_search_sanitized_query_still_finds_content (line 273) | def test_search_sanitized_query_still_finds_content(self, db): method test_search_hyphenated_term_does_not_crash (line 283) | def test_search_hyphenated_term_does_not_crash(self, db): method test_search_quoted_phrase_preserved (line 294) | def test_search_quoted_phrase_preserved(self, db): method test_sanitize_fts5_query_strips_dangerous_chars (line 307) | def test_sanitize_fts5_query_strips_dangerous_chars(self): method test_sanitize_fts5_preserves_quoted_phrases (line 324) | def test_sanitize_fts5_preserves_quoted_phrases(self): method test_sanitize_fts5_quotes_hyphenated_terms (line 339) | def test_sanitize_fts5_quotes_hyphenated_terms(self): class TestSearchSessions (line 366) | class TestSearchSessions: method test_list_all_sessions (line 367) | def test_list_all_sessions(self, db): method test_filter_by_source (line 374) | def test_filter_by_source(self, db): method test_pagination (line 382) | def test_pagination(self, db): class TestCounts (line 397) | class TestCounts: method test_session_count (line 398) | def test_session_count(self, db): method test_session_count_by_source (line 404) | def test_session_count_by_source(self, db): method test_message_count_total (line 411) | def test_message_count_total(self, db): method test_message_count_per_session (line 418) | def test_message_count_per_session(self, db): class TestDeleteAndExport (line 432) | class TestDeleteAndExport: method test_delete_session (line 433) | def test_delete_session(self, db): method test_delete_nonexistent (line 441) | def test_delete_nonexistent(self, db): method test_resolve_session_id_exact (line 444) | def test_resolve_session_id_exact(self, db): method test_resolve_session_id_unique_prefix (line 448) | def test_resolve_session_id_unique_prefix(self, db): method test_resolve_session_id_ambiguous_prefix_returns_none (line 452) | def test_resolve_session_id_ambiguous_prefix_returns_none(self, db): method test_resolve_session_id_escapes_like_wildcards (line 457) | def test_resolve_session_id_escapes_like_wildcards(self, db): method test_export_session (line 462) | def test_export_session(self, db): method test_export_nonexistent (line 472) | def test_export_nonexistent(self, db): method test_export_all (line 475) | def test_export_all(self, db): method test_export_all_with_source (line 483) | def test_export_all_with_source(self, db): class TestPruneSessions (line 496) | class TestPruneSessions: method test_prune_old_ended_sessions (line 497) | def test_prune_old_ended_sessions(self, db): method test_prune_skips_active_sessions (line 518) | def test_prune_skips_active_sessions(self, db): method test_prune_with_source_filter (line 531) | def test_prune_with_source_filter(self, db): class TestSessionTitle (line 555) | class TestSessionTitle: method test_set_and_get_title (line 556) | def test_set_and_get_title(self, db): method test_set_title_nonexistent_session (line 563) | def test_set_title_nonexistent_session(self, db): method test_title_initially_none (line 566) | def test_title_initially_none(self, db): method test_update_title (line 571) | def test_update_title(self, db): method test_title_in_search_sessions (line 579) | def test_title_in_search_sessions(self, db): method test_title_in_export (line 589) | def test_title_in_export(self, db): method test_title_with_special_characters (line 597) | def test_title_with_special_characters(self, db): method test_title_empty_string_normalized_to_none (line 605) | def test_title_empty_string_normalized_to_none(self, db): method test_multiple_empty_titles_no_conflict (line 615) | def test_multiple_empty_titles_no_conflict(self, db): method test_title_survives_end_session (line 625) | def test_title_survives_end_session(self, db): class TestSanitizeTitle (line 635) | class TestSanitizeTitle: method test_normal_title_unchanged (line 638) | def test_normal_title_unchanged(self): method test_strips_whitespace (line 641) | def test_strips_whitespace(self): method test_collapses_internal_whitespace (line 644) | def test_collapses_internal_whitespace(self): method test_tabs_and_newlines_collapsed (line 647) | def test_tabs_and_newlines_collapsed(self): method test_none_returns_none (line 650) | def test_none_returns_none(self): method test_empty_string_returns_none (line 653) | def test_empty_string_returns_none(self): method test_whitespace_only_returns_none (line 656) | def test_whitespace_only_returns_none(self): method test_control_chars_stripped (line 659) | def test_control_chars_stripped(self): method test_del_char_stripped (line 664) | def test_del_char_stripped(self): method test_zero_width_chars_stripped (line 667) | def test_zero_width_chars_stripped(self): method test_rtl_override_stripped (line 672) | def test_rtl_override_stripped(self): method test_bom_stripped (line 676) | def test_bom_stripped(self): method test_only_control_chars_returns_none (line 680) | def test_only_control_chars_returns_none(self): method test_max_length_allowed (line 683) | def test_max_length_allowed(self): method test_exceeds_max_length_raises (line 687) | def test_exceeds_max_length_raises(self): method test_unicode_emoji_allowed (line 692) | def test_unicode_emoji_allowed(self): method test_cjk_characters_allowed (line 695) | def test_cjk_characters_allowed(self): method test_accented_characters_allowed (line 698) | def test_accented_characters_allowed(self): method test_special_punctuation_allowed (line 701) | def test_special_punctuation_allowed(self): method test_sanitize_applied_in_set_session_title (line 705) | def test_sanitize_applied_in_set_session_title(self, db): method test_too_long_title_rejected_by_set (line 711) | def test_too_long_title_rejected_by_set(self, db): class TestSchemaInit (line 718) | class TestSchemaInit: method test_wal_mode (line 719) | def test_wal_mode(self, db): method test_foreign_keys_enabled (line 724) | def test_foreign_keys_enabled(self, db): method test_tables_exist (line 728) | def test_tables_exist(self, db): method test_schema_version (line 737) | def test_schema_version(self, db): method test_title_column_exists (line 742) | def test_title_column_exists(self, db): method test_migration_from_v2 (line 748) | def test_migration_from_v2(self, tmp_path): class TestTitleUniqueness (line 816) | class TestTitleUniqueness: method test_duplicate_title_raises (line 819) | def test_duplicate_title_raises(self, db): method test_same_session_can_keep_title (line 827) | def test_same_session_can_keep_title(self, db): method test_null_titles_not_unique (line 834) | def test_null_titles_not_unique(self, db): method test_get_session_by_title (line 842) | def test_get_session_by_title(self, db): method test_get_session_by_title_not_found (line 849) | def test_get_session_by_title_not_found(self, db): method test_get_session_title (line 852) | def test_get_session_title(self, db): method test_get_session_title_nonexistent (line 858) | def test_get_session_title_nonexistent(self, db): class TestTitleLineage (line 862) | class TestTitleLineage: method test_resolve_exact_title (line 865) | def test_resolve_exact_title(self, db): method test_resolve_returns_latest_numbered (line 870) | def test_resolve_returns_latest_numbered(self, db): method test_resolve_exact_numbered (line 884) | def test_resolve_exact_numbered(self, db): method test_resolve_nonexistent_title (line 893) | def test_resolve_nonexistent_title(self, db): method test_next_title_no_existing (line 896) | def test_next_title_no_existing(self, db): method test_next_title_first_continuation (line 900) | def test_next_title_first_continuation(self, db): method test_next_title_increments (line 906) | def test_next_title_increments(self, db): method test_next_title_strips_existing_number (line 916) | def test_next_title_strips_existing_number(self, db): class TestTitleSqlWildcards (line 926) | class TestTitleSqlWildcards: method test_resolve_title_with_underscore (line 929) | def test_resolve_title_with_underscore(self, db): method test_resolve_title_with_percent (line 938) | def test_resolve_title_with_percent(self, db): method test_next_lineage_with_underscore (line 947) | def test_next_lineage_with_underscore(self, db): class TestListSessionsRich (line 957) | class TestListSessionsRich: method test_preview_from_first_user_message (line 960) | def test_preview_from_first_user_message(self, db): method test_preview_truncated_at_60 (line 969) | def test_preview_truncated_at_60(self, db): method test_preview_empty_when_no_user_messages (line 977) | def test_preview_empty_when_no_user_messages(self, db): method test_last_active_from_latest_message (line 983) | def test_last_active_from_latest_message(self, db): method test_last_active_fallback_to_started_at (line 993) | def test_last_active_fallback_to_started_at(self, db): method test_rich_list_includes_title (line 999) | def test_rich_list_includes_title(self, db): method test_rich_list_source_filter (line 1005) | def test_rich_list_source_filter(self, db): method test_preview_newlines_collapsed (line 1012) | def test_preview_newlines_collapsed(self, db): class TestResolveSessionByNameOrId (line 1020) | class TestResolveSessionByNameOrId: method test_resolve_by_id (line 1023) | def test_resolve_by_id(self, db): method test_resolve_by_title_falls_back (line 1029) | def test_resolve_by_title_falls_back(self, db): FILE: tests/test_honcho_client_config.py class TestHonchoClientConfigAutoEnable (line 13) | class TestHonchoClientConfigAutoEnable: method test_auto_enables_when_api_key_present_no_explicit_enabled (line 16) | def test_auto_enables_when_api_key_present_no_explicit_enabled(self, t... method test_respects_explicit_enabled_false (line 29) | def test_respects_explicit_enabled_false(self, tmp_path): method test_respects_explicit_enabled_true (line 42) | def test_respects_explicit_enabled_true(self, tmp_path): method test_disabled_when_no_api_key_and_no_explicit_enabled (line 55) | def test_disabled_when_no_api_key_and_no_explicit_enabled(self, tmp_pa... method test_auto_enables_with_env_var_api_key (line 73) | def test_auto_enables_with_env_var_api_key(self, tmp_path, monkeypatch): method test_from_env_always_enabled (line 88) | def test_from_env_always_enabled(self, monkeypatch): method test_falls_back_to_env_when_no_config_file (line 97) | def test_falls_back_to_env_when_no_config_file(self, tmp_path, monkeyp... FILE: tests/test_insights.py function db (line 20) | def db(tmp_path): function populated_db (line 29) | def populated_db(db): class TestPricing (line 125) | class TestPricing: method test_provider_prefix_stripped (line 126) | def test_provider_prefix_stripped(self): method test_unknown_models_do_not_use_heuristics (line 131) | def test_unknown_models_do_not_use_heuristics(self): method test_unknown_model_returns_zero_cost (line 137) | def test_unknown_model_returns_zero_cost(self): method test_custom_endpoint_model_zero_cost (line 144) | def test_custom_endpoint_model_zero_cost(self): method test_none_model (line 151) | def test_none_model(self): method test_empty_model (line 155) | def test_empty_model(self): class TestHasKnownPricing (line 160) | class TestHasKnownPricing: method test_known_commercial_model (line 161) | def test_known_commercial_model(self): method test_unknown_custom_model (line 166) | def test_unknown_custom_model(self): method test_heuristic_matched_models_are_not_considered_known (line 173) | def test_heuristic_matched_models_are_not_considered_known(self): class TestEstimateCost (line 178) | class TestEstimateCost: method test_basic_cost (line 179) | def test_basic_cost(self): method test_zero_tokens (line 189) | def test_zero_tokens(self): method test_cache_aware_usage (line 194) | def test_cache_aware_usage(self): class TestFormatDuration (line 212) | class TestFormatDuration: method test_seconds (line 213) | def test_seconds(self): method test_minutes (line 216) | def test_minutes(self): method test_hours_with_minutes (line 219) | def test_hours_with_minutes(self): method test_exact_hours (line 223) | def test_exact_hours(self): method test_days (line 226) | def test_days(self): class TestBarChart (line 231) | class TestBarChart: method test_basic_bars (line 232) | def test_basic_bars(self): method test_empty_values (line 239) | def test_empty_values(self): method test_all_zeros (line 243) | def test_all_zeros(self): method test_single_value (line 247) | def test_single_value(self): class TestInsightsEmpty (line 257) | class TestInsightsEmpty: method test_empty_db_returns_empty_report (line 258) | def test_empty_db_returns_empty_report(self, db): method test_empty_db_terminal_format (line 264) | def test_empty_db_terminal_format(self, db): method test_empty_db_gateway_format (line 270) | def test_empty_db_gateway_format(self, db): class TestInsightsPopulated (line 281) | class TestInsightsPopulated: method test_generate_returns_all_sections (line 282) | def test_generate_returns_all_sections(self, populated_db): method test_overview_session_count (line 294) | def test_overview_session_count(self, populated_db): method test_overview_token_totals (line 302) | def test_overview_token_totals(self, populated_db): method test_overview_cost_positive (line 313) | def test_overview_cost_positive(self, populated_db): method test_overview_duration_stats (line 318) | def test_overview_duration_stats(self, populated_db): method test_model_breakdown (line 327) | def test_model_breakdown(self, populated_db): method test_platform_breakdown (line 342) | def test_platform_breakdown(self, populated_db): method test_tool_breakdown (line 355) | def test_tool_breakdown(self, populated_db): method test_activity_patterns (line 375) | def test_activity_patterns(self, populated_db): method test_top_sessions (line 386) | def test_top_sessions(self, populated_db): method test_source_filter_cli (line 397) | def test_source_filter_cli(self, populated_db): method test_source_filter_telegram (line 403) | def test_source_filter_telegram(self, populated_db): method test_source_filter_nonexistent (line 409) | def test_source_filter_nonexistent(self, populated_db): method test_days_filter_short (line 415) | def test_days_filter_short(self, populated_db): method test_days_filter_long (line 422) | def test_days_filter_long(self, populated_db): class TestTerminalFormatting (line 434) | class TestTerminalFormatting: method test_terminal_format_has_sections (line 435) | def test_terminal_format_has_sections(self, populated_db): method test_terminal_format_shows_tokens (line 447) | def test_terminal_format_shows_tokens(self, populated_db): method test_terminal_format_shows_platforms (line 457) | def test_terminal_format_shows_platforms(self, populated_db): method test_terminal_format_shows_bar_chart (line 467) | def test_terminal_format_shows_bar_chart(self, populated_db): method test_terminal_format_shows_na_for_custom_models (line 474) | def test_terminal_format_shows_na_for_custom_models(self, db): class TestGatewayFormatting (line 488) | class TestGatewayFormatting: method test_gateway_format_is_shorter (line 489) | def test_gateway_format_is_shorter(self, populated_db): method test_gateway_format_has_bold (line 497) | def test_gateway_format_has_bold(self, populated_db): method test_gateway_format_shows_cost (line 504) | def test_gateway_format_shows_cost(self, populated_db): method test_gateway_format_shows_models (line 512) | def test_gateway_format_shows_models(self, populated_db): class TestEdgeCases (line 525) | class TestEdgeCases: method test_session_with_no_tokens (line 526) | def test_session_with_no_tokens(self, db): method test_session_with_no_end_time (line 537) | def test_session_with_no_end_time(self, db): method test_session_with_no_model (line 551) | def test_session_with_no_model(self, db): method test_custom_model_shows_zero_cost (line 566) | def test_custom_model_shows_zero_cost(self, db): method test_tool_usage_from_tool_calls_json (line 582) | def test_tool_usage_from_tool_calls_json(self, db): method test_overview_pricing_sets_are_lists (line 618) | def test_overview_pricing_sets_are_lists(self, db): method test_mixed_commercial_and_custom_models (line 634) | def test_mixed_commercial_and_custom_models(self, db): method test_single_session_streak (line 665) | def test_single_session_streak(self, db): method test_no_tool_calls (line 674) | def test_no_tool_calls(self, db): method test_only_one_platform (line 685) | def test_only_one_platform(self, db): method test_large_days_value (line 700) | def test_large_days_value(self, db): method test_zero_days (line 709) | def test_zero_days(self, db): FILE: tests/test_interactive_interrupt.py function make_slow_response (line 32) | def make_slow_response(delay=2.0): function main (line 52) | def main() -> int: FILE: tests/test_interrupt_propagation.py class TestInterruptPropagationToChild (line 16) | class TestInterruptPropagationToChild(unittest.TestCase): method setUp (line 19) | def setUp(self): method tearDown (line 22) | def tearDown(self): method test_parent_interrupt_sets_child_flag (line 25) | def test_parent_interrupt_sets_child_flag(self): method test_child_clear_interrupt_at_start_clears_global (line 52) | def test_child_clear_interrupt_at_start_clears_global(self): method test_interrupt_during_child_api_call_detected (line 76) | def test_interrupt_during_child_api_call_detected(self): method test_concurrent_interrupt_propagation (line 118) | def test_concurrent_interrupt_propagation(self): FILE: tests/test_managed_server_tool_support.py class TestManagedServerAPI (line 27) | class TestManagedServerAPI: method test_managed_server_init_signature (line 30) | def test_managed_server_init_signature(self): method test_server_manager_managed_server_signature (line 52) | def test_server_manager_managed_server_signature(self): method test_managed_server_chat_template_kwargs (line 69) | def test_managed_server_chat_template_kwargs(self): method test_no_get_logprobs_method (line 82) | def test_no_get_logprobs_method(self): class TestParserCompatibility (line 95) | class TestParserCompatibility: method test_parser_parse_returns_correct_format (line 98) | def test_parser_parse_returns_correct_format(self): method test_parser_no_tools_returns_none (line 119) | def test_parser_no_tools_returns_none(self): method test_parser_content_is_string_or_none (line 127) | def test_parser_content_is_string_or_none(self): class TestBaseEnvCompatibility (line 143) | class TestBaseEnvCompatibility: method test_hermes_base_env_sets_server_manager_tool_parser (line 146) | def test_hermes_base_env_sets_server_manager_tool_parser(self): method test_hermes_base_env_uses_config_tool_call_parser (line 172) | def test_hermes_base_env_uses_config_tool_call_parser(self): FILE: tests/test_minisweagent_path.py function test_discover_minisweagent_src_in_current_checkout (line 8) | def test_discover_minisweagent_src_in_current_checkout(tmp_path): function test_discover_minisweagent_src_falls_back_from_worktree_to_main_checkout (line 16) | def test_discover_minisweagent_src_falls_back_from_worktree_to_main_chec... function test_discover_minisweagent_src_returns_none_when_missing (line 30) | def test_discover_minisweagent_src_returns_none_when_missing(tmp_path): FILE: tests/test_model_metadata_local_ctx.py class TestQueryLocalContextLengthOllama (line 21) | class TestQueryLocalContextLengthOllama: method _make_resp (line 24) | def _make_resp(self, status_code, body): method test_ollama_model_info_context_length (line 30) | def test_ollama_model_info_context_length(self): method test_ollama_parameters_num_ctx (line 51) | def test_ollama_parameters_num_ctx(self): method test_ollama_show_404_falls_through (line 73) | def test_ollama_show_404_falls_through(self): class TestQueryLocalContextLengthVllm (line 93) | class TestQueryLocalContextLengthVllm: method _make_resp (line 96) | def _make_resp(self, status_code, body): method test_vllm_max_model_len (line 102) | def test_vllm_max_model_len(self): method test_vllm_context_length_key (line 121) | def test_vllm_context_length_key(self): class TestQueryLocalContextLengthModelsList (line 140) | class TestQueryLocalContextLengthModelsList: method _make_resp (line 143) | def _make_resp(self, status_code, body): method test_models_list_max_model_len (line 149) | def test_models_list_max_model_len(self): method test_models_list_model_not_found_returns_none (line 180) | def test_models_list_model_not_found_returns_none(self): class TestQueryLocalContextLengthLmStudio (line 209) | class TestQueryLocalContextLengthLmStudio: method _make_resp (line 212) | def _make_resp(self, status_code, body): method _make_client (line 218) | def _make_client(self, native_resp, detail_resp, list_resp): method test_lmstudio_exact_key_match (line 238) | def test_lmstudio_exact_key_match(self): method test_lmstudio_slug_only_matches_key_with_publisher_prefix (line 262) | def test_lmstudio_slug_only_matches_key_with_publisher_prefix(self): method test_lmstudio_v1_models_list_slug_fuzzy_match (line 293) | def test_lmstudio_v1_models_list_slug_fuzzy_match(self): method test_lmstudio_loaded_instances_context_length (line 321) | def test_lmstudio_loaded_instances_context_length(self): method test_lmstudio_loaded_instance_beats_max_context_length (line 350) | def test_lmstudio_loaded_instance_beats_max_context_length(self): class TestQueryLocalContextLengthNetworkError (line 389) | class TestQueryLocalContextLengthNetworkError: method test_connection_error_returns_none (line 392) | def test_connection_error_returns_none(self): class TestGetModelContextLengthLocalFallback (line 413) | class TestGetModelContextLengthLocalFallback: method test_local_endpoint_unknown_model_queries_server (line 416) | def test_local_endpoint_unknown_model_queries_server(self): method test_local_endpoint_unknown_model_result_is_cached (line 430) | def test_local_endpoint_unknown_model_result_is_cached(self): method test_local_endpoint_server_returns_none_falls_back_to_2m (line 444) | def test_local_endpoint_server_returns_none_falls_back_to_2m(self): method test_non_local_endpoint_does_not_query_local_server (line 457) | def test_non_local_endpoint_does_not_query_local_server(self): method test_cached_result_skips_local_query (line 472) | def test_cached_result_skips_local_query(self): method test_no_base_url_does_not_query_local_server (line 483) | def test_no_base_url_does_not_query_local_server(self): FILE: tests/test_model_provider_persistence.py function config_home (line 16) | def config_home(tmp_path, monkeypatch): class TestSaveModelChoiceAlwaysDict (line 38) | class TestSaveModelChoiceAlwaysDict: method test_string_model_becomes_dict (line 39) | def test_string_model_becomes_dict(self, config_home): method test_dict_model_stays_dict (line 54) | def test_dict_model_stays_dict(self, config_home): class TestProviderPersistsAfterModelSave (line 71) | class TestProviderPersistsAfterModelSave: method test_api_key_provider_saved_when_model_was_string (line 72) | def test_api_key_provider_saved_when_model_was_string(self, config_hom... method test_copilot_provider_saved_when_selected (line 103) | def test_copilot_provider_saved_when_selected(self, config_home): method test_copilot_acp_provider_saved_when_selected (line 152) | def test_copilot_acp_provider_saved_when_selected(self, config_home): FILE: tests/test_model_tools.py class TestHandleFunctionCall (line 20) | class TestHandleFunctionCall: method test_agent_loop_tool_returns_error (line 21) | def test_agent_loop_tool_returns_error(self): method test_unknown_tool_returns_error (line 27) | def test_unknown_tool_returns_error(self): method test_exception_returns_json_error (line 32) | def test_exception_returns_json_error(self): class TestAgentLoopTools (line 46) | class TestAgentLoopTools: method test_expected_tools_in_set (line 47) | def test_expected_tools_in_set(self): method test_no_regular_tools_in_set (line 53) | def test_no_regular_tools_in_set(self): class TestLegacyToolsetMap (line 62) | class TestLegacyToolsetMap: method test_expected_legacy_names (line 63) | def test_expected_legacy_names(self): method test_values_are_lists_of_strings (line 72) | def test_values_are_lists_of_strings(self): class TestBackwardCompat (line 83) | class TestBackwardCompat: method test_get_all_tool_names_returns_list (line 84) | def test_get_all_tool_names_returns_list(self): method test_get_toolset_for_tool (line 92) | def test_get_toolset_for_tool(self): method test_get_toolset_for_unknown_tool (line 97) | def test_get_toolset_for_unknown_tool(self): method test_tool_to_toolset_map (line 101) | def test_tool_to_toolset_map(self): FILE: tests/test_model_tools_async_bridge.py function _get_current_loop (line 26) | async def _get_current_loop(): function _create_and_return_transport (line 31) | async def _create_and_return_transport(): class TestRunAsyncLoopLifecycle (line 47) | class TestRunAsyncLoopLifecycle: method test_loop_not_closed_after_run_async (line 50) | def test_loop_not_closed_after_run_async(self): method test_same_loop_reused_across_calls (line 61) | def test_same_loop_reused_across_calls(self): method test_cached_transport_survives_between_calls (line 73) | def test_cached_transport_survives_between_calls(self): class TestRunAsyncWorkerThread (line 87) | class TestRunAsyncWorkerThread: method test_worker_thread_loop_not_closed (line 90) | def test_worker_thread_loop_not_closed(self): method test_worker_thread_reuses_loop_across_calls (line 109) | def test_worker_thread_reuses_loop_across_calls(self): method test_parallel_workers_get_separate_loops (line 129) | def test_parallel_workers_get_separate_loops(self): method test_worker_loop_separate_from_main_loop (line 162) | def test_worker_loop_separate_from_main_loop(self): class TestRunAsyncWithRunningLoop (line 183) | class TestRunAsyncWithRunningLoop: method test_run_async_from_async_context (line 187) | async def test_run_async_from_async_context(self): function _mock_vision_response (line 205) | def _mock_vision_response(): class TestVisionDispatchLoopSafety (line 212) | class TestVisionDispatchLoopSafety: method test_vision_dispatch_keeps_loop_alive (line 217) | def test_vision_dispatch_keeps_loop_alive(self, tmp_path): method test_two_consecutive_vision_dispatches (line 260) | def test_two_consecutive_vision_dispatches(self, tmp_path): function _write_fake_image (line 303) | def _write_fake_image(dest): FILE: tests/test_openai_client_lifecycle.py class FakeRequestClient (line 17) | class FakeRequestClient: method __init__ (line 18) | def __init__(self, responder): method _create (line 27) | def _create(self, **kwargs): method close (line 30) | def close(self): class FakeSharedClient (line 35) | class FakeSharedClient(FakeRequestClient): class OpenAIFactory (line 39) | class OpenAIFactory: method __init__ (line 40) | def __init__(self, clients): method __call__ (line 44) | def __call__(self, **kwargs): function _build_agent (line 51) | def _build_agent(shared_client=None): function _connection_error (line 70) | def _connection_error(): function test_retry_after_api_connection_error_recreates_request_client (line 77) | def test_retry_after_api_connection_error_recreates_request_client(monke... function test_closed_shared_client_is_recreated_before_request (line 96) | def test_closed_shared_client_is_recreated_before_request(monkeypatch): function test_concurrent_requests_do_not_break_each_other_when_one_client_closes (line 115) | def test_concurrent_requests_do_not_break_each_other_when_one_client_clo... function test_streaming_call_recreates_closed_shared_client_before_request (line 158) | def test_streaming_call_recreates_closed_shared_client_before_request(mo... FILE: tests/test_personality_none.py class TestCLIPersonalityNone (line 9) | class TestCLIPersonalityNone: method _make_cli (line 11) | def _make_cli(self, personalities=None): method test_none_clears_system_prompt (line 23) | def test_none_clears_system_prompt(self): method test_default_clears_system_prompt (line 29) | def test_default_clears_system_prompt(self): method test_neutral_clears_system_prompt (line 35) | def test_neutral_clears_system_prompt(self): method test_none_forces_agent_reinit (line 41) | def test_none_forces_agent_reinit(self): method test_none_saves_to_config (line 47) | def test_none_saves_to_config(self): method test_known_personality_still_works (line 53) | def test_known_personality_still_works(self): method test_unknown_personality_shows_none_in_available (line 59) | def test_unknown_personality_shows_none_in_available(self, capsys): method test_list_shows_none_option (line 65) | def test_list_shows_none_option(self): class TestGatewayPersonalityNone (line 75) | class TestGatewayPersonalityNone: method _make_event (line 77) | def _make_event(self, args=""): method _make_runner (line 83) | def _make_runner(self, personalities=None): method test_none_clears_ephemeral_prompt (line 95) | async def test_none_clears_ephemeral_prompt(self, tmp_path): method test_default_clears_ephemeral_prompt (line 109) | async def test_default_clears_ephemeral_prompt(self, tmp_path): method test_list_includes_none (line 122) | async def test_list_includes_none(self, tmp_path): method test_unknown_shows_none_in_available (line 135) | async def test_unknown_shows_none_in_available(self, tmp_path): class TestPersonalityDictFormat (line 148) | class TestPersonalityDictFormat: method _make_cli (line 151) | def _make_cli(self, personalities): method test_dict_personality_uses_system_prompt (line 160) | def test_dict_personality_uses_system_prompt(self): method test_dict_personality_includes_tone (line 173) | def test_dict_personality_includes_tone(self): method test_dict_personality_includes_style (line 184) | def test_dict_personality_includes_style(self): method test_string_personality_still_works (line 195) | def test_string_personality_still_works(self): method test_resolve_prompt_dict_no_tone_no_style (line 201) | def test_resolve_prompt_dict_no_tone_no_style(self): method test_resolve_prompt_string (line 209) | def test_resolve_prompt_string(self): FILE: tests/test_plugins.py function _make_plugin_dir (line 30) | def _make_plugin_dir(base: Path, name: str, *, register_body: str = "pass", class TestPluginDiscovery (line 50) | class TestPluginDiscovery: method test_discover_user_plugins (line 53) | def test_discover_user_plugins(self, tmp_path, monkeypatch): method test_discover_project_plugins (line 65) | def test_discover_project_plugins(self, tmp_path, monkeypatch): method test_discover_is_idempotent (line 79) | def test_discover_is_idempotent(self, tmp_path, monkeypatch): method test_discover_skips_dir_without_manifest (line 91) | def test_discover_skips_dir_without_manifest(self, tmp_path, monkeypat... method test_entry_points_scanned (line 102) | def test_entry_points_scanned(self, tmp_path, monkeypatch): class TestPluginLoading (line 130) | class TestPluginLoading: method test_load_missing_init (line 133) | def test_load_missing_init(self, tmp_path, monkeypatch): method test_load_missing_register_fn (line 148) | def test_load_missing_register_fn(self, tmp_path, monkeypatch): method test_load_registers_namespace_module (line 164) | def test_load_registers_namespace_module(self, tmp_path, monkeypatch): class TestPluginHooks (line 182) | class TestPluginHooks: method test_register_and_invoke_hook (line 185) | def test_register_and_invoke_hook(self, tmp_path, monkeypatch): method test_hook_exception_does_not_propagate (line 200) | def test_hook_exception_does_not_propagate(self, tmp_path, monkeypatch): method test_invalid_hook_name_warns (line 215) | def test_invalid_hook_name_warns(self, tmp_path, monkeypatch, caplog): class TestPluginContext (line 234) | class TestPluginContext: method test_register_tool_adds_to_registry (line 237) | def test_register_tool_adds_to_registry(self, tmp_path, monkeypatch): class TestPluginToolVisibility (line 266) | class TestPluginToolVisibility: method test_plugin_tools_in_definitions (line 269) | def test_plugin_tools_in_definitions(self, tmp_path, monkeypatch): class TestPluginManagerList (line 301) | class TestPluginManagerList: method test_list_empty (line 304) | def test_list_empty(self): method test_list_returns_sorted (line 309) | def test_list_returns_sorted(self, tmp_path, monkeypatch): method test_list_with_plugins (line 323) | def test_list_with_plugins(self, tmp_path, monkeypatch): FILE: tests/test_provider_parity.py function _tool_defs (line 25) | def _tool_defs(*names): class _FakeOpenAI (line 39) | class _FakeOpenAI: method __init__ (line 40) | def __init__(self, **kw): method close (line 43) | def close(self): function _make_agent (line 47) | def _make_agent(monkeypatch, provider, api_mode="chat_completions", base... class TestBuildApiKwargsOpenRouter (line 65) | class TestBuildApiKwargsOpenRouter: method test_uses_chat_completions_format (line 66) | def test_uses_chat_completions_format(self, monkeypatch): method test_includes_reasoning_in_extra_body (line 74) | def test_includes_reasoning_in_extra_body(self, monkeypatch): method test_includes_tools (line 82) | def test_includes_tools(self, monkeypatch): method test_no_responses_api_fields (line 90) | def test_no_responses_api_fields(self, monkeypatch): method test_strips_codex_only_tool_call_fields_from_chat_messages (line 98) | def test_strips_codex_only_tool_call_fields_from_chat_messages(self, m... class TestBuildApiKwargsAIGateway (line 140) | class TestBuildApiKwargsAIGateway: method test_uses_chat_completions_format (line 141) | def test_uses_chat_completions_format(self, monkeypatch): method test_no_responses_api_fields (line 149) | def test_no_responses_api_fields(self, monkeypatch): method test_includes_reasoning_in_extra_body (line 157) | def test_includes_reasoning_in_extra_body(self, monkeypatch): method test_includes_tools (line 165) | def test_includes_tools(self, monkeypatch): class TestBuildApiKwargsNousPortal (line 174) | class TestBuildApiKwargsNousPortal: method test_includes_nous_product_tags (line 175) | def test_includes_nous_product_tags(self, monkeypatch): method test_uses_chat_completions_format (line 182) | def test_uses_chat_completions_format(self, monkeypatch): class TestBuildApiKwargsCustomEndpoint (line 190) | class TestBuildApiKwargsCustomEndpoint: method test_uses_chat_completions_format (line 191) | def test_uses_chat_completions_format(self, monkeypatch): method test_no_openrouter_extra_body (line 198) | def test_no_openrouter_extra_body(self, monkeypatch): method test_fireworks_tool_call_payload_strips_codex_only_fields (line 205) | def test_fireworks_tool_call_payload_strips_codex_only_fields(self, mo... class TestBuildApiKwargsCodex (line 252) | class TestBuildApiKwargsCodex: method test_uses_responses_api_format (line 253) | def test_uses_responses_api_format(self, monkeypatch): method test_includes_reasoning_config (line 263) | def test_includes_reasoning_config(self, monkeypatch): method test_includes_encrypted_content_in_include (line 271) | def test_includes_encrypted_content_in_include(self, monkeypatch): method test_tools_converted_to_responses_format (line 278) | def test_tools_converted_to_responses_format(self, monkeypatch): class TestChatMessagesToResponsesInput (line 292) | class TestChatMessagesToResponsesInput: method test_user_message_passes_through (line 295) | def test_user_message_passes_through(self, monkeypatch): method test_system_messages_filtered (line 302) | def test_system_messages_filtered(self, monkeypatch): method test_assistant_tool_calls_become_function_call_items (line 313) | def test_assistant_tool_calls_become_function_call_items(self, monkeyp... method test_tool_results_become_function_call_output (line 331) | def test_tool_results_become_function_call_output(self, monkeypatch): method test_encrypted_reasoning_replayed (line 340) | def test_encrypted_reasoning_replayed(self, monkeypatch): method test_no_reasoning_items_for_non_codex_messages (line 360) | def test_no_reasoning_items_for_non_codex_messages(self, monkeypatch): class TestNormalizeCodexResponse (line 375) | class TestNormalizeCodexResponse: method _make_codex_agent (line 378) | def _make_codex_agent(self, monkeypatch): method test_text_response (line 382) | def test_text_response(self, monkeypatch): method test_reasoning_summary_extracted (line 396) | def test_reasoning_summary_extracted(self, monkeypatch): method test_encrypted_content_captured (line 415) | def test_encrypted_content_captured(self, monkeypatch): method test_no_encrypted_content_when_missing (line 435) | def test_no_encrypted_content_when_missing(self, monkeypatch): method test_tool_calls_extracted (line 448) | def test_tool_calls_extracted(self, monkeypatch): class TestBuildAssistantMessage (line 466) | class TestBuildAssistantMessage: method test_openrouter_reasoning_fields (line 469) | def test_openrouter_reasoning_fields(self, monkeypatch): method test_openrouter_reasoning_details_preserved_unmodified (line 483) | def test_openrouter_reasoning_details_preserved_unmodified(self, monke... method test_codex_preserves_encrypted_reasoning (line 509) | def test_codex_preserves_encrypted_reasoning(self, monkeypatch): method test_plain_message_no_codex_items (line 527) | def test_plain_message_no_codex_items(self, monkeypatch): class TestAuxiliaryClientProviderPriority (line 542) | class TestAuxiliaryClientProviderPriority: method test_openrouter_always_wins (line 545) | def test_openrouter_always_wins(self, monkeypatch): method test_nous_when_no_openrouter (line 553) | def test_nous_when_no_openrouter(self, monkeypatch): method test_custom_endpoint_when_no_nous (line 561) | def test_custom_endpoint_when_no_nous(self, monkeypatch): method test_codex_fallback_last_resort (line 571) | def test_codex_fallback_last_resort(self, monkeypatch): class TestProviderRouting (line 586) | class TestProviderRouting: method test_sort_throughput (line 589) | def test_sort_throughput(self, monkeypatch): method test_only_providers (line 595) | def test_only_providers(self, monkeypatch): method test_ignore_providers (line 601) | def test_ignore_providers(self, monkeypatch): method test_order_providers (line 607) | def test_order_providers(self, monkeypatch): method test_require_parameters (line 613) | def test_require_parameters(self, monkeypatch): method test_data_collection_deny (line 619) | def test_data_collection_deny(self, monkeypatch): method test_no_routing_when_unset (line 625) | def test_no_routing_when_unset(self, monkeypatch): method test_combined_routing (line 632) | def test_combined_routing(self, monkeypatch): method test_routing_not_injected_for_codex (line 643) | def test_routing_not_injected_for_codex(self, monkeypatch): class TestCodexReasoningPreflight (line 655) | class TestCodexReasoningPreflight: method test_reasoning_item_passes_through (line 658) | def test_reasoning_item_passes_through(self, monkeypatch): method test_reasoning_item_without_id (line 674) | def test_reasoning_item_without_id(self, monkeypatch): method test_reasoning_item_empty_encrypted_skipped (line 685) | def test_reasoning_item_empty_encrypted_skipped(self, monkeypatch): method test_reasoning_items_replayed_from_history (line 696) | def test_reasoning_items_replayed_from_history(self, monkeypatch): class TestReasoningEffortDefaults (line 719) | class TestReasoningEffortDefaults: method test_openrouter_default_medium (line 722) | def test_openrouter_default_medium(self, monkeypatch): method test_codex_default_medium (line 728) | def test_codex_default_medium(self, monkeypatch): method test_codex_reasoning_disabled (line 734) | def test_codex_reasoning_disabled(self, monkeypatch): method test_codex_reasoning_low (line 742) | def test_codex_reasoning_low(self, monkeypatch): method test_openrouter_reasoning_config_override (line 749) | def test_openrouter_reasoning_config_override(self, monkeypatch): FILE: tests/test_quick_commands.py class TestCLIQuickCommands (line 10) | class TestCLIQuickCommands: method _printed_plain (line 14) | def _printed_plain(call_arg): method _make_cli (line 19) | def _make_cli(self, quick_commands): method test_exec_command_runs_and_prints_output (line 28) | def test_exec_command_runs_and_prints_output(self): method test_exec_command_stderr_shown_on_no_stdout (line 36) | def test_exec_command_stderr_shown_on_no_stdout(self): method test_exec_command_no_output_shows_fallback (line 43) | def test_exec_command_no_output_shows_fallback(self): method test_alias_command_routes_to_target (line 50) | def test_alias_command_routes_to_target(self): method test_alias_command_passes_args (line 58) | def test_alias_command_passes_args(self): method test_alias_no_target_shows_error (line 65) | def test_alias_no_target_shows_error(self): method test_unsupported_type_shows_error (line 72) | def test_unsupported_type_shows_error(self): method test_missing_command_field_shows_error (line 79) | def test_missing_command_field_shows_error(self): method test_quick_command_takes_priority_over_skill_commands (line 86) | def test_quick_command_takes_priority_over_skill_commands(self): method test_unknown_command_still_shows_error (line 95) | def test_unknown_command_still_shows_error(self): method test_timeout_shows_error (line 103) | def test_timeout_shows_error(self): class TestGatewayQuickCommands (line 114) | class TestGatewayQuickCommands: method _make_event (line 117) | def _make_event(self, command, args=""): method test_exec_command_returns_output (line 131) | async def test_exec_command_returns_output(self): method test_unsupported_type_returns_error (line 144) | async def test_unsupported_type_returns_error(self): method test_timeout_returns_error (line 158) | async def test_timeout_returns_error(self): method test_gateway_config_object_supports_quick_commands (line 174) | async def test_gateway_config_object_supports_quick_commands(self): FILE: tests/test_real_interrupt_subagent.py function _make_slow_api_response (line 17) | def _make_slow_api_response(delay=5.0): class TestRealSubagentInterrupt (line 39) | class TestRealSubagentInterrupt(unittest.TestCase): method setUp (line 42) | def setUp(self): method tearDown (line 46) | def tearDown(self): method test_interrupt_child_during_api_call (line 49) | def test_interrupt_child_during_api_call(self): FILE: tests/test_reasoning_command.py class TestParseReasoningConfig (line 20) | class TestParseReasoningConfig(unittest.TestCase): method _parse (line 23) | def _parse(self, effort): method test_none_disables (line 27) | def test_none_disables(self): method test_valid_levels (line 31) | def test_valid_levels(self): method test_empty_returns_none (line 38) | def test_empty_returns_none(self): method test_unknown_returns_none (line 42) | def test_unknown_returns_none(self): method test_case_insensitive (line 46) | def test_case_insensitive(self): class TestHandleReasoningCommand (line 56) | class TestHandleReasoningCommand(unittest.TestCase): method _make_cli (line 59) | def _make_cli(self, reasoning_config=None, show_reasoning=False): method test_show_enables_display (line 68) | def test_show_enables_display(self): method test_hide_disables_display (line 77) | def test_hide_disables_display(self): method test_on_enables_display (line 87) | def test_on_enables_display(self): method test_off_disables_display (line 94) | def test_off_disables_display(self): method test_effort_level_sets_config (line 101) | def test_effort_level_sets_config(self): method test_effort_none_disables_reasoning (line 110) | def test_effort_none_disables_reasoning(self): method test_invalid_argument_rejected (line 117) | def test_invalid_argument_rejected(self): method test_no_args_shows_status (line 123) | def test_no_args_shows_status(self): method test_status_with_disabled_reasoning (line 137) | def test_status_with_disabled_reasoning(self): method test_status_with_explicit_level (line 148) | def test_status_with_explicit_level(self): class TestLastReasoningInResult (line 162) | class TestLastReasoningInResult(unittest.TestCase): method _build_messages (line 165) | def _build_messages(self, reasoning=None): method test_reasoning_present (line 176) | def test_reasoning_present(self): method test_reasoning_none (line 185) | def test_reasoning_none(self): method test_picks_last_assistant (line 194) | def test_picks_last_assistant(self): method test_empty_reasoning_treated_as_none (line 208) | def test_empty_reasoning_treated_as_none(self): class TestReasoningCollapse (line 222) | class TestReasoningCollapse(unittest.TestCase): method test_short_reasoning_not_collapsed (line 225) | def test_short_reasoning_not_collapsed(self): method test_long_reasoning_collapsed (line 230) | def test_long_reasoning_collapsed(self): method test_exactly_10_lines_not_collapsed (line 241) | def test_exactly_10_lines_not_collapsed(self): method test_intermediate_callback_collapses_to_5 (line 247) | def test_intermediate_callback_collapses_to_5(self): class TestReasoningCallback (line 265) | class TestReasoningCallback(unittest.TestCase): method test_callback_invoked_with_reasoning (line 268) | def test_callback_invoked_with_reasoning(self): method test_callback_not_invoked_without_reasoning (line 279) | def test_callback_not_invoked_without_reasoning(self): method test_callback_none_does_not_crash (line 290) | def test_callback_none_does_not_crash(self): class TestExtractReasoningFormats (line 302) | class TestExtractReasoningFormats(unittest.TestCase): method _get_extractor (line 305) | def _get_extractor(self): method test_openrouter_reasoning_details (line 309) | def test_openrouter_reasoning_details(self): method test_deepseek_reasoning_field (line 321) | def test_deepseek_reasoning_field(self): method test_moonshot_reasoning_content (line 330) | def test_moonshot_reasoning_content(self): method test_no_reasoning_returns_none (line 338) | def test_no_reasoning_returns_none(self): class TestInlineThinkBlockExtraction (line 349) | class TestInlineThinkBlockExtraction(unittest.TestCase): method _build_msg (line 353) | def _build_msg(self, content, reasoning=None, reasoning_content=None, ... method _make_agent (line 364) | def _make_agent(self): method test_single_think_block_extracted (line 374) | def test_single_think_block_extracted(self): method test_multiple_think_blocks_extracted (line 380) | def test_multiple_think_blocks_extracted(self): method test_no_think_blocks_no_reasoning (line 387) | def test_no_think_blocks_no_reasoning(self): method test_structured_reasoning_takes_priority (line 394) | def test_structured_reasoning_takes_priority(self): method test_empty_think_block_ignored (line 404) | def test_empty_think_block_ignored(self): method test_multiline_think_block (line 411) | def test_multiline_think_block(self): method test_callback_fires_for_inline_think (line 418) | def test_callback_fires_for_inline_think(self): class TestConfigDefault (line 433) | class TestConfigDefault(unittest.TestCase): method test_default_config_has_show_reasoning (line 436) | def test_default_config_has_show_reasoning(self): class TestCommandRegistered (line 443) | class TestCommandRegistered(unittest.TestCase): method test_reasoning_in_commands (line 446) | def test_reasoning_in_commands(self): class TestEndToEndPipeline (line 455) | class TestEndToEndPipeline(unittest.TestCase): method test_openrouter_claude_pipeline (line 458) | def test_openrouter_claude_pipeline(self): method test_no_reasoning_model_pipeline (line 494) | def test_no_reasoning_model_pipeline(self): FILE: tests/test_redirect_stdout_issue.py class TestRedirectStdoutIsProcessWide (line 17) | class TestRedirectStdoutIsProcessWide(unittest.TestCase): method test_redirect_stdout_affects_other_threads (line 19) | def test_redirect_stdout_affects_other_threads(self): FILE: tests/test_resume_display.py function _make_cli (line 18) | def _make_cli(config_overrides=None, env_overrides=None, **kwargs): function _simple_history (line 54) | def _simple_history(): function _tool_call_history (line 65) | def _tool_call_history(): function _large_history (line 92) | def _large_history(n_exchanges=15): function _multimodal_history (line 101) | def _multimodal_history(): class TestDisplayResumedHistory (line 119) | class TestDisplayResumedHistory: method _capture_display (line 122) | def _capture_display(self, cli_obj): method test_simple_history_shows_user_and_assistant (line 129) | def test_simple_history_shows_user_and_assistant(self): method test_system_messages_hidden (line 140) | def test_system_messages_hidden(self): method test_tool_messages_hidden (line 147) | def test_tool_messages_hidden(self): method test_tool_calls_shown_as_summary (line 156) | def test_tool_calls_shown_as_summary(self): method test_long_user_message_truncated (line 165) | def test_long_user_message_truncated(self): method test_long_assistant_message_truncated (line 182) | def test_long_assistant_message_truncated(self): method test_multiline_assistant_truncated (line 194) | def test_multiline_assistant_truncated(self): method test_large_history_shows_truncation_indicator (line 210) | def test_large_history_shows_truncation_indicator(self): method test_multimodal_content_handled (line 220) | def test_multimodal_content_handled(self): method test_empty_history_no_output (line 228) | def test_empty_history_no_output(self): method test_minimal_config_suppresses_display (line 235) | def test_minimal_config_suppresses_display(self): method test_panel_has_title (line 244) | def test_panel_has_title(self): method test_assistant_with_no_content_no_tools_skipped (line 251) | def test_assistant_with_no_content_no_tools_skipped(self): method test_only_system_messages_no_output (line 265) | def test_only_system_messages_no_output(self): method test_reasoning_scratchpad_stripped (line 274) | def test_reasoning_scratchpad_stripped(self): method test_pure_reasoning_message_skipped (line 293) | def test_pure_reasoning_message_skipped(self): method test_assistant_with_text_and_tool_calls (line 309) | def test_assistant_with_text_and_tool_calls(self): class TestPreloadResumedSession (line 336) | class TestPreloadResumedSession: method test_returns_false_when_not_resumed (line 339) | def test_returns_false_when_not_resumed(self): method test_returns_false_when_no_session_db (line 343) | def test_returns_false_when_no_session_db(self): method test_returns_false_when_session_not_found (line 348) | def test_returns_false_when_session_not_found(self): method test_returns_false_when_session_has_no_messages (line 362) | def test_returns_false_when_session_has_no_messages(self): method test_loads_session_successfully (line 377) | def test_loads_session_successfully(self): method test_reopens_session_in_db (line 397) | def test_reopens_session_in_db(self): method test_singular_user_message_grammar (line 417) | def test_singular_user_message_grammar(self): class TestInitAgentSkipsPreloaded (line 442) | class TestInitAgentSkipsPreloaded: method test_init_agent_skips_db_when_preloaded (line 445) | def test_init_agent_skips_db_when_preloaded(self): class TestResumeDisplayConfig (line 466) | class TestResumeDisplayConfig: method test_default_config_has_resume_display (line 469) | def test_default_config_has_resume_display(self): method test_cli_defaults_have_resume_display (line 476) | def test_cli_defaults_have_resume_display(self): FILE: tests/test_run_agent.py function _make_tool_defs (line 30) | def _make_tool_defs(*names: str) -> list: function agent (line 46) | def agent(): function agent_with_memory_tool (line 66) | def agent_with_memory_tool(): function test_aiagent_reuses_existing_errors_log_handler (line 86) | def test_aiagent_reuses_existing_errors_log_handler(): function _mock_assistant_msg (line 145) | def _mock_assistant_msg( function _mock_tool_call (line 163) | def _mock_tool_call(name="web_search", arguments="{}", call_id=None): function _mock_response (line 172) | def _mock_response( class TestHasContentAfterThinkBlock (line 195) | class TestHasContentAfterThinkBlock: method test_none_returns_false (line 196) | def test_none_returns_false(self, agent): method test_empty_returns_false (line 199) | def test_empty_returns_false(self, agent): method test_only_think_block_returns_false (line 202) | def test_only_think_block_returns_false(self, agent): method test_content_after_think_returns_true (line 205) | def test_content_after_think_returns_true(self, agent): method test_no_think_block_returns_true (line 211) | def test_no_think_block_returns_true(self, agent): class TestStripThinkBlocks (line 215) | class TestStripThinkBlocks: method test_none_returns_empty (line 216) | def test_none_returns_empty(self, agent): method test_no_blocks_unchanged (line 219) | def test_no_blocks_unchanged(self, agent): method test_single_block_removed (line 222) | def test_single_block_removed(self, agent): method test_multiline_block_removed (line 227) | def test_multiline_block_removed(self, agent): class TestExtractReasoning (line 234) | class TestExtractReasoning: method test_reasoning_field (line 235) | def test_reasoning_field(self, agent): method test_reasoning_content_field (line 239) | def test_reasoning_content_field(self, agent): method test_reasoning_details_array (line 243) | def test_reasoning_details_array(self, agent): method test_no_reasoning_returns_none (line 249) | def test_no_reasoning_returns_none(self, agent): method test_combined_reasoning (line 253) | def test_combined_reasoning(self, agent): method test_deduplication (line 262) | def test_deduplication(self, agent): class TestCleanSessionContent (line 271) | class TestCleanSessionContent: method test_none_passthrough (line 272) | def test_none_passthrough(self): method test_scratchpad_converted (line 275) | def test_scratchpad_converted(self): method test_extra_newlines_cleaned (line 281) | def test_extra_newlines_cleaned(self): class TestGetMessagesUpToLastAssistant (line 290) | class TestGetMessagesUpToLastAssistant: method test_empty_list (line 291) | def test_empty_list(self, agent): method test_no_assistant_returns_copy (line 294) | def test_no_assistant_returns_copy(self, agent): method test_single_assistant (line 300) | def test_single_assistant(self, agent): method test_multiple_assistants_returns_up_to_last (line 309) | def test_multiple_assistants_returns_up_to_last(self, agent): method test_assistant_then_tool_messages (line 320) | def test_assistant_then_tool_messages(self, agent): class TestMaskApiKey (line 332) | class TestMaskApiKey: method test_none_returns_none (line 333) | def test_none_returns_none(self, agent): method test_short_key_returns_stars (line 336) | def test_short_key_returns_stars(self, agent): method test_long_key_masked (line 339) | def test_long_key_masked(self, agent): class TestInit (line 352) | class TestInit: method test_anthropic_base_url_accepted (line 353) | def test_anthropic_base_url_accepted(self): method test_prompt_caching_claude_openrouter (line 370) | def test_prompt_caching_claude_openrouter(self): method test_prompt_caching_non_claude (line 386) | def test_prompt_caching_non_claude(self): method test_prompt_caching_non_openrouter (line 402) | def test_prompt_caching_non_openrouter(self): method test_prompt_caching_native_anthropic (line 419) | def test_prompt_caching_native_anthropic(self): method test_valid_tool_names_populated (line 436) | def test_valid_tool_names_populated(self): method test_session_id_auto_generated (line 452) | def test_session_id_auto_generated(self): class TestInterrupt (line 471) | class TestInterrupt: method test_interrupt_sets_flag (line 472) | def test_interrupt_sets_flag(self, agent): method test_interrupt_with_message (line 477) | def test_interrupt_with_message(self, agent): method test_clear_interrupt (line 482) | def test_clear_interrupt(self, agent): method test_is_interrupted_property (line 489) | def test_is_interrupted_property(self, agent): class TestHydrateTodoStore (line 496) | class TestHydrateTodoStore: method test_no_todo_in_history (line 497) | def test_no_todo_in_history(self, agent): method test_recovers_from_history (line 506) | def test_recovers_from_history(self, agent): method test_skips_non_todo_tools (line 521) | def test_skips_non_todo_tools(self, agent): method test_invalid_json_skipped (line 533) | def test_invalid_json_skipped(self, agent): class TestBuildSystemPrompt (line 546) | class TestBuildSystemPrompt: method test_always_has_identity (line 547) | def test_always_has_identity(self, agent): method test_includes_system_message (line 551) | def test_includes_system_message(self, agent): method test_memory_guidance_when_memory_tool_loaded (line 555) | def test_memory_guidance_when_memory_tool_loaded(self, agent_with_memo... method test_no_memory_guidance_without_tool (line 561) | def test_no_memory_guidance_without_tool(self, agent): method test_includes_datetime (line 567) | def test_includes_datetime(self, agent): class TestInvalidateSystemPrompt (line 573) | class TestInvalidateSystemPrompt: method test_clears_cache (line 574) | def test_clears_cache(self, agent): method test_reloads_memory_store (line 579) | def test_reloads_memory_store(self, agent): class TestBuildApiKwargs (line 587) | class TestBuildApiKwargs: method test_basic_kwargs (line 588) | def test_basic_kwargs(self, agent): method test_provider_preferences_injected (line 595) | def test_provider_preferences_injected(self, agent): method test_reasoning_config_default_openrouter (line 601) | def test_reasoning_config_default_openrouter(self, agent): method test_reasoning_config_custom (line 609) | def test_reasoning_config_custom(self, agent): method test_reasoning_not_sent_for_unsupported_openrouter_model (line 615) | def test_reasoning_not_sent_for_unsupported_openrouter_model(self, age... method test_reasoning_sent_for_supported_openrouter_model (line 621) | def test_reasoning_sent_for_supported_openrouter_model(self, agent): method test_reasoning_sent_for_nous_route (line 627) | def test_reasoning_sent_for_nous_route(self, agent): method test_reasoning_sent_for_copilot_gpt5 (line 634) | def test_reasoning_sent_for_copilot_gpt5(self, agent): method test_reasoning_xhigh_normalized_for_copilot (line 641) | def test_reasoning_xhigh_normalized_for_copilot(self, agent): method test_reasoning_omitted_for_non_reasoning_copilot_model (line 649) | def test_reasoning_omitted_for_non_reasoning_copilot_model(self, agent): method test_max_tokens_injected (line 656) | def test_max_tokens_injected(self, agent): class TestBuildAssistantMessage (line 663) | class TestBuildAssistantMessage: method test_basic_message (line 664) | def test_basic_message(self, agent): method test_with_reasoning (line 671) | def test_with_reasoning(self, agent): method test_with_tool_calls (line 676) | def test_with_tool_calls(self, agent): method test_with_reasoning_details (line 683) | def test_with_reasoning_details(self, agent): method test_empty_content (line 690) | def test_empty_content(self, agent): method test_tool_call_extra_content_preserved (line 695) | def test_tool_call_extra_content_preserved(self, agent): method test_tool_call_without_extra_content (line 708) | def test_tool_call_without_extra_content(self, agent): class TestFormatToolsForSystemMessage (line 716) | class TestFormatToolsForSystemMessage: method test_no_tools_returns_empty_array (line 717) | def test_no_tools_returns_empty_array(self, agent): method test_formats_single_tool (line 721) | def test_formats_single_tool(self, agent): method test_formats_multiple_tools (line 728) | def test_formats_multiple_tools(self, agent): class TestExecuteToolCalls (line 742) | class TestExecuteToolCalls: method test_single_tool_executed (line 743) | def test_single_tool_executed(self, agent): method test_interrupt_skips_remaining (line 759) | def test_interrupt_skips_remaining(self, agent): method test_invalid_json_args_defaults_empty (line 776) | def test_invalid_json_args_defaults_empty(self, agent): method test_result_truncation_over_100k (line 792) | def test_result_truncation_over_100k(self, agent): class TestConcurrentToolExecution (line 804) | class TestConcurrentToolExecution: method test_single_tool_uses_sequential_path (line 807) | def test_single_tool_uses_sequential_path(self, agent): method test_clarify_forces_sequential (line 818) | def test_clarify_forces_sequential(self, agent): method test_multiple_tools_uses_concurrent_path (line 830) | def test_multiple_tools_uses_concurrent_path(self, agent): method test_terminal_batch_forces_sequential (line 842) | def test_terminal_batch_forces_sequential(self, agent): method test_write_batch_forces_sequential (line 854) | def test_write_batch_forces_sequential(self, agent): method test_disjoint_write_batch_uses_concurrent_path (line 866) | def test_disjoint_write_batch_uses_concurrent_path(self, agent): method test_overlapping_write_batch_forces_sequential (line 886) | def test_overlapping_write_batch_forces_sequential(self, agent): method test_malformed_json_args_forces_sequential (line 906) | def test_malformed_json_args_forces_sequential(self, agent): method test_non_dict_args_forces_sequential (line 918) | def test_non_dict_args_forces_sequential(self, agent): method test_concurrent_executes_all_tools (line 930) | def test_concurrent_executes_all_tools(self, agent): method test_concurrent_preserves_order_despite_timing (line 959) | def test_concurrent_preserves_order_despite_timing(self, agent): method test_concurrent_handles_tool_error (line 982) | def test_concurrent_handles_tool_error(self, agent): method test_concurrent_interrupt_before_start (line 1005) | def test_concurrent_interrupt_before_start(self, agent): method test_concurrent_truncates_large_results (line 1020) | def test_concurrent_truncates_large_results(self, agent): method test_invoke_tool_dispatches_to_handle_function_call (line 1036) | def test_invoke_tool_dispatches_to_handle_function_call(self, agent): method test_invoke_tool_handles_agent_level_tools (line 1048) | def test_invoke_tool_handles_agent_level_tools(self, agent): class TestPathsOverlap (line 1056) | class TestPathsOverlap: method test_same_path_overlaps (line 1059) | def test_same_path_overlaps(self): method test_siblings_do_not_overlap (line 1063) | def test_siblings_do_not_overlap(self): method test_parent_child_overlap (line 1067) | def test_parent_child_overlap(self): method test_different_roots_do_not_overlap (line 1071) | def test_different_roots_do_not_overlap(self): method test_nested_vs_flat_do_not_overlap (line 1075) | def test_nested_vs_flat_do_not_overlap(self): method test_empty_paths_do_not_overlap (line 1079) | def test_empty_paths_do_not_overlap(self): method test_one_empty_path_does_not_overlap (line 1083) | def test_one_empty_path_does_not_overlap(self): class TestHandleMaxIterations (line 1089) | class TestHandleMaxIterations: method test_returns_summary (line 1090) | def test_returns_summary(self, agent): method test_api_failure_returns_error (line 1100) | def test_api_failure_returns_error(self, agent): method test_summary_skips_reasoning_for_unsupported_openrouter_model (line 1109) | def test_summary_skips_reasoning_for_unsupported_openrouter_model(self... class TestRunConversation (line 1123) | class TestRunConversation: method _setup_agent (line 1130) | def _setup_agent(self, agent): method test_stop_finish_reason_returns_response (line 1138) | def test_stop_finish_reason_returns_response(self, agent): method test_tool_calls_then_stop (line 1151) | def test_tool_calls_then_stop(self, agent): method test_interrupt_breaks_loop (line 1167) | def test_interrupt_breaks_loop(self, agent): method test_invalid_tool_name_retry (line 1186) | def test_invalid_tool_name_retry(self, agent): method test_empty_content_retry_and_fallback (line 1205) | def test_empty_content_retry_and_fallback(self, agent): method test_nous_401_refreshes_after_remint_and_retries (line 1228) | def test_nous_401_refreshes_after_remint_and_retries(self, agent): method test_context_compression_triggered (line 1269) | def test_context_compression_triggered(self, agent): method test_length_finish_reason_requests_continuation (line 1306) | def test_length_finish_reason_requests_continuation( class TestRetryExhaustion (line 1330) | class TestRetryExhaustion: method _setup_agent (line 1338) | def _setup_agent(self, agent): method _make_fast_time_mock (line 1346) | def _make_fast_time_mock(): method test_invalid_response_returns_error_not_crash (line 1360) | def test_invalid_response_returns_error_not_crash(self, agent): method test_api_error_raises_after_retries (line 1384) | def test_api_error_raises_after_retries(self, agent): class TestFlushSentinelNotLeaked (line 1403) | class TestFlushSentinelNotLeaked: method test_flush_sentinel_stripped_from_api_messages (line 1406) | def test_flush_sentinel_stripped_from_api_messages(self, agent_with_me... class TestConversationHistoryNotMutated (line 1445) | class TestConversationHistoryNotMutated: method test_caller_list_unchanged_after_run (line 1448) | def test_caller_list_unchanged_after_run(self, agent): class TestNousCredentialRefresh (line 1481) | class TestNousCredentialRefresh: method test_try_refresh_nous_client_credentials_rebuilds_client (line 1484) | def test_try_refresh_nous_client_credentials_rebuilds_client( class TestMaxTokensParam (line 1531) | class TestMaxTokensParam: method test_returns_max_completion_tokens_for_direct_openai (line 1534) | def test_returns_max_completion_tokens_for_direct_openai(self, agent): method test_returns_max_tokens_for_openrouter (line 1539) | def test_returns_max_tokens_for_openrouter(self, agent): method test_returns_max_tokens_for_local (line 1544) | def test_returns_max_tokens_for_local(self, agent): method test_not_tricked_by_openai_in_openrouter_url (line 1549) | def test_not_tricked_by_openai_in_openrouter_url(self, agent): class TestSystemPromptStability (line 1559) | class TestSystemPromptStability: method test_stored_prompt_reused_for_continuing_session (line 1562) | def test_stored_prompt_reused_for_continuing_session(self, agent): method test_fresh_build_when_no_history (line 1601) | def test_fresh_build_when_no_history(self, agent): method test_fresh_build_when_db_has_no_prompt (line 1627) | def test_fresh_build_when_db_has_no_prompt(self, agent): method test_honcho_context_baked_into_prompt_on_first_turn (line 1654) | def test_honcho_context_baked_into_prompt_on_first_turn(self, agent): method test_honcho_prefetch_runs_on_continuing_session (line 1669) | def test_honcho_prefetch_runs_on_continuing_session(self): method test_inject_honcho_turn_context_appends_system_note (line 1679) | def test_inject_honcho_turn_context_appends_system_note(self): method test_honcho_continuing_session_keeps_turn_context_out_of_system_prompt (line 1685) | def test_honcho_continuing_session_keeps_turn_context_out_of_system_pr... method test_honcho_prefetch_runs_on_first_turn (line 1726) | def test_honcho_prefetch_runs_on_first_turn(self): method test_run_conversation_can_skip_honcho_sync_for_synthetic_turns (line 1732) | def test_run_conversation_can_skip_honcho_sync_for_synthetic_turns(sel... class TestHonchoActivation (line 1765) | class TestHonchoActivation: method test_disabled_config_skips_honcho_init (line 1766) | def test_disabled_config_skips_honcho_init(self): method test_injected_honcho_manager_skips_fresh_client_init (line 1792) | def test_injected_honcho_manager_skips_fresh_client_init(self): method test_recall_mode_context_suppresses_honcho_tools (line 1832) | def test_recall_mode_context_suppresses_honcho_tools(self): method test_inactive_honcho_strips_stale_honcho_tools (line 1880) | def test_inactive_honcho_strips_stale_honcho_tools(self): class TestHonchoPrefetchScheduling (line 1908) | class TestHonchoPrefetchScheduling: method test_honcho_prefetch_includes_cached_dialectic (line 1909) | def test_honcho_prefetch_includes_cached_dialectic(self, agent): method test_queue_honcho_prefetch_skips_tools_mode (line 1920) | def test_queue_honcho_prefetch_skips_tools_mode(self, agent): method test_queue_honcho_prefetch_runs_when_context_enabled (line 1934) | def test_queue_honcho_prefetch_runs_when_context_enabled(self, agent): class TestBudgetPressure (line 1953) | class TestBudgetPressure: method test_no_warning_below_caution (line 1956) | def test_no_warning_below_caution(self, agent): method test_caution_at_70_percent (line 1960) | def test_caution_at_70_percent(self, agent): method test_warning_at_90_percent (line 1967) | def test_warning_at_90_percent(self, agent): method test_last_iteration (line 1973) | def test_last_iteration(self, agent): method test_disabled (line 1978) | def test_disabled(self, agent): method test_zero_max_iterations (line 1983) | def test_zero_max_iterations(self, agent): method test_injects_into_json_tool_result (line 1987) | def test_injects_into_json_tool_result(self, agent): method test_appends_to_non_json_tool_result (line 2006) | def test_appends_to_non_json_tool_result(self, agent): class TestSafeWriter (line 2024) | class TestSafeWriter: method test_write_delegates_normally (line 2027) | def test_write_delegates_normally(self): method test_write_catches_oserror (line 2036) | def test_write_catches_oserror(self): method test_flush_catches_oserror (line 2046) | def test_flush_catches_oserror(self): method test_print_survives_broken_stdout (line 2055) | def test_print_survives_broken_stdout(self, monkeypatch): method test_installed_in_run_conversation (line 2069) | def test_installed_in_run_conversation(self, agent): method test_installed_before_init_time_honcho_error_prints (line 2090) | def test_installed_before_init_time_honcho_error_prints(self): method test_double_wrap_prevented (line 2123) | def test_double_wrap_prevented(self): class TestSaveSessionLogAtomicWrite (line 2140) | class TestSaveSessionLogAtomicWrite: method test_uses_shared_atomic_json_helper (line 2141) | def test_uses_shared_atomic_json_helper(self, agent, tmp_path): class TestBuildApiKwargsAnthropicMaxTokens (line 2163) | class TestBuildApiKwargsAnthropicMaxTokens: method test_max_tokens_passed_to_anthropic (line 2166) | def test_max_tokens_passed_to_anthropic(self, agent): method test_max_tokens_none_when_unset (line 2182) | def test_max_tokens_none_when_unset(self, agent): class TestAnthropicImageFallback (line 2198) | class TestAnthropicImageFallback: method test_build_api_kwargs_converts_multimodal_user_image_to_text (line 2199) | def test_build_api_kwargs_converts_multimodal_user_image_to_text(self,... method test_build_api_kwargs_reuses_cached_image_analysis_for_duplicate_images (line 2228) | def test_build_api_kwargs_reuses_cached_image_analysis_for_duplicate_i... class TestFallbackAnthropicProvider (line 2261) | class TestFallbackAnthropicProvider: method test_fallback_to_anthropic_sets_api_mode (line 2264) | def test_fallback_to_anthropic_sets_api_mode(self, agent): method test_fallback_to_anthropic_enables_prompt_caching (line 2285) | def test_fallback_to_anthropic_enables_prompt_caching(self, agent): method test_fallback_to_openrouter_uses_openai_client (line 2302) | def test_fallback_to_openrouter_uses_openai_client(self, agent): function test_aiagent_uses_copilot_acp_client (line 2318) | def test_aiagent_uses_copilot_acp_client(): function test_is_openai_client_closed_honors_custom_client_flag (line 2348) | def test_is_openai_client_closed_honors_custom_client_flag(): class TestAnthropicBaseUrlPassthrough (line 2353) | class TestAnthropicBaseUrlPassthrough: method test_custom_proxy_base_url_passed_through (line 2356) | def test_custom_proxy_base_url_passed_through(self): method test_none_base_url_passed_as_none (line 2375) | def test_none_base_url_passed_as_none(self): class TestAnthropicCredentialRefresh (line 2395) | class TestAnthropicCredentialRefresh: method test_try_refresh_anthropic_client_credentials_rebuilds_client (line 2396) | def test_try_refresh_anthropic_client_credentials_rebuilds_client(self): method test_try_refresh_anthropic_client_credentials_returns_false_when_token_unchanged (line 2428) | def test_try_refresh_anthropic_client_credentials_returns_false_when_t... method test_anthropic_messages_create_preflights_refresh (line 2455) | def test_anthropic_messages_create_preflights_refresh(self): function _make_chunk (line 2485) | def _make_chunk(content=None, tool_calls=None, finish_reason=None, model... function _make_tc_delta (line 2492) | def _make_tc_delta(index=0, tc_id=None, name=None, arguments=None): class TestStreamingApiCall (line 2498) | class TestStreamingApiCall: method test_content_assembly (line 2501) | def test_content_assembly(self, agent): method test_tool_call_accumulation (line 2521) | def test_tool_call_accumulation(self, agent): method test_multiple_tool_calls (line 2537) | def test_multiple_tool_calls(self, agent): method test_content_and_tool_calls_together (line 2552) | def test_content_and_tool_calls_together(self, agent): method test_empty_content_returns_none (line 2565) | def test_empty_content_returns_none(self, agent): method test_callback_exception_swallowed (line 2574) | def test_callback_exception_swallowed(self, agent): method test_model_name_captured (line 2587) | def test_model_name_captured(self, agent): method test_stream_kwarg_injected (line 2598) | def test_stream_kwarg_injected(self, agent): method test_api_exception_falls_back_to_non_streaming (line 2607) | def test_api_exception_falls_back_to_non_streaming(self, agent): method test_response_has_uuid_id (line 2614) | def test_response_has_uuid_id(self, agent): method test_empty_choices_chunk_skipped (line 2623) | def test_empty_choices_chunk_skipped(self, agent): class TestInterruptVprintForceTrue (line 2643) | class TestInterruptVprintForceTrue: method test_all_interrupt_vprint_have_force_true (line 2646) | def test_all_interrupt_vprint_have_force_true(self): class TestAnthropicInterruptHandler (line 2668) | class TestAnthropicInterruptHandler: method test_interruptible_has_anthropic_branch (line 2671) | def test_interruptible_has_anthropic_branch(self): method test_interruptible_rebuilds_anthropic_client (line 2678) | def test_interruptible_rebuilds_anthropic_client(self): method test_streaming_has_anthropic_branch (line 2685) | def test_streaming_has_anthropic_branch(self): class TestStreamCallbackNonStreamingProvider (line 2698) | class TestStreamCallbackNonStreamingProvider: method test_callback_receives_chat_completions_response (line 2702) | def test_callback_receives_chat_completions_response(self, agent): method test_callback_receives_anthropic_content (line 2750) | def test_callback_receives_anthropic_content(self, agent): class TestPersistUserMessageOverride (line 2786) | class TestPersistUserMessageOverride: method test_persist_session_rewrites_current_turn_user_message (line 2789) | def test_persist_session_rewrites_current_turn_user_message(self, agent): class TestVprintForceOnErrors (line 2821) | class TestVprintForceOnErrors: method test_forced_message_shown_during_tts (line 2824) | def test_forced_message_shown_during_tts(self, agent): method test_non_forced_suppressed_during_tts (line 2831) | def test_non_forced_suppressed_during_tts(self, agent): method test_all_shown_without_tts (line 2838) | def test_all_shown_without_tts(self, agent): class TestNormalizeCodexDictArguments (line 2847) | class TestNormalizeCodexDictArguments: method _make_codex_response (line 2851) | def _make_codex_response(self, item_type, arguments, item_status="comp... method test_function_call_dict_arguments_produce_valid_json (line 2872) | def test_function_call_dict_arguments_produce_valid_json(self, agent): method test_custom_tool_call_dict_arguments_produce_valid_json (line 2882) | def test_custom_tool_call_dict_arguments_produce_valid_json(self, agent): method test_string_arguments_unchanged (line 2891) | def test_string_arguments_unchanged(self, agent): class TestOAuthFlagAfterCredentialRefresh (line 2905) | class TestOAuthFlagAfterCredentialRefresh: method test_oauth_flag_updates_api_key_to_oauth (line 2908) | def test_oauth_flag_updates_api_key_to_oauth(self, agent): method test_oauth_flag_updates_oauth_to_api_key (line 2926) | def test_oauth_flag_updates_oauth_to_api_key(self, agent): class TestFallbackSetsOAuthFlag (line 2945) | class TestFallbackSetsOAuthFlag: method test_fallback_to_anthropic_oauth_sets_flag (line 2948) | def test_fallback_to_anthropic_oauth_sets_flag(self, agent): method test_fallback_to_anthropic_api_key_clears_flag (line 2969) | def test_fallback_to_anthropic_api_key_clears_flag(self, agent): class TestMemoryNudgeCounterPersistence (line 2991) | class TestMemoryNudgeCounterPersistence: method test_counters_initialized_in_init (line 2994) | def test_counters_initialized_in_init(self): method test_counters_not_reset_in_preamble (line 3006) | def test_counters_not_reset_in_preamble(self): class TestDeadRetryCode (line 3019) | class TestDeadRetryCode: method test_no_unreachable_max_retries_after_backoff (line 3022) | def test_no_unreachable_max_retries_after_backoff(self): FILE: tests/test_run_agent_codex_responses.py function _patch_agent_bootstrap (line 15) | def _patch_agent_bootstrap(monkeypatch): function _build_agent (line 33) | def _build_agent(monkeypatch): function _build_copilot_agent (line 52) | def _build_copilot_agent(monkeypatch, *, model="gpt-5.4"): function _codex_message_response (line 73) | def _codex_message_response(text: str): function _codex_tool_call_response (line 87) | def _codex_tool_call_response(): function _codex_incomplete_message_response (line 104) | def _codex_incomplete_message_response(text: str): function _codex_commentary_message_response (line 119) | def _codex_commentary_message_response(text: str): function _codex_ack_message_response (line 135) | def _codex_ack_message_response(text: str): class _FakeResponsesStream (line 150) | class _FakeResponsesStream: method __init__ (line 151) | def __init__(self, *, final_response=None, final_error=None): method __enter__ (line 155) | def __enter__(self): method __exit__ (line 158) | def __exit__(self, exc_type, exc, tb): method __iter__ (line 161) | def __iter__(self): method get_final_response (line 164) | def get_final_response(self): class _FakeCreateStream (line 170) | class _FakeCreateStream: method __init__ (line 171) | def __init__(self, events): method __iter__ (line 175) | def __iter__(self): method close (line 178) | def close(self): function _codex_request_kwargs (line 182) | def _codex_request_kwargs(): function test_api_mode_uses_explicit_provider_when_codex (line 192) | def test_api_mode_uses_explicit_provider_when_codex(monkeypatch): function test_api_mode_normalizes_provider_case (line 208) | def test_api_mode_normalizes_provider_case(monkeypatch): function test_api_mode_respects_explicit_openrouter_provider_over_codex_url (line 224) | def test_api_mode_respects_explicit_openrouter_provider_over_codex_url(m... function test_build_api_kwargs_codex (line 240) | def test_build_api_kwargs_codex(monkeypatch): function test_build_api_kwargs_copilot_responses_omits_openai_only_fields (line 268) | def test_build_api_kwargs_copilot_responses_omits_openai_only_fields(mon... function test_build_api_kwargs_copilot_responses_omits_reasoning_for_non_reasoning_model (line 281) | def test_build_api_kwargs_copilot_responses_omits_reasoning_for_non_reas... function test_run_codex_stream_retries_when_completed_event_missing (line 290) | def test_run_codex_stream_retries_when_completed_event_missing(monkeypat... function test_run_codex_stream_falls_back_to_create_after_stream_completion_error (line 314) | def test_run_codex_stream_falls_back_to_create_after_stream_completion_e... function test_run_codex_stream_fallback_parses_create_stream_events (line 341) | def test_run_codex_stream_fallback_parses_create_stream_events(monkeypat... function test_run_conversation_codex_plain_text (line 377) | def test_run_conversation_codex_plain_text(monkeypatch): function test_run_conversation_codex_refreshes_after_401_and_retries (line 389) | def test_run_conversation_codex_refreshes_after_401_and_retries(monkeypa... function test_try_refresh_codex_client_credentials_rebuilds_client (line 420) | def test_try_refresh_codex_client_credentials_rebuilds_client(monkeypatch): function test_run_conversation_codex_tool_round_trip (line 455) | def test_run_conversation_codex_tool_round_trip(monkeypatch): function test_chat_messages_to_responses_input_uses_call_id_for_function_call (line 480) | def test_chat_messages_to_responses_input_uses_call_id_for_function_call... function test_chat_messages_to_responses_input_accepts_call_pipe_fc_ids (line 508) | def test_chat_messages_to_responses_input_accepts_call_pipe_fc_ids(monke... function test_preflight_codex_api_kwargs_strips_optional_function_call_id (line 536) | def test_preflight_codex_api_kwargs_strips_optional_function_call_id(mon... function test_preflight_codex_api_kwargs_rejects_function_call_output_without_call_id (line 562) | def test_preflight_codex_api_kwargs_rejects_function_call_output_without... function test_preflight_codex_api_kwargs_rejects_unsupported_request_fields (line 577) | def test_preflight_codex_api_kwargs_rejects_unsupported_request_fields(m... function test_preflight_codex_api_kwargs_allows_reasoning_and_temperature (line 586) | def test_preflight_codex_api_kwargs_allows_reasoning_and_temperature(mon... function test_run_conversation_codex_replay_payload_keeps_call_id (line 601) | def test_run_conversation_codex_replay_payload_keeps_call_id(monkeypatch): function test_run_conversation_codex_continues_after_incomplete_interim_message (line 638) | def test_run_conversation_codex_continues_after_incomplete_interim_messa... function test_normalize_codex_response_marks_commentary_only_message_as_incomplete (line 672) | def test_normalize_codex_response_marks_commentary_only_message_as_incom... function test_run_conversation_codex_continues_after_commentary_phase_message (line 682) | def test_run_conversation_codex_continues_after_commentary_phase_message... function test_run_conversation_codex_continues_after_ack_stop_message (line 716) | def test_run_conversation_codex_continues_after_ack_stop_message(monkeyp... function test_run_conversation_codex_continues_after_ack_for_directory_listing_prompt (line 757) | def test_run_conversation_codex_continues_after_ack_for_directory_listin... function test_dump_api_request_debug_uses_responses_url (line 798) | def test_dump_api_request_debug_uses_responses_url(monkeypatch, tmp_path): function test_dump_api_request_debug_uses_chat_completions_url (line 811) | def test_dump_api_request_debug_uses_chat_completions_url(monkeypatch, t... function _codex_reasoning_only_response (line 838) | def _codex_reasoning_only_response(*, encrypted_content="enc_abc123", su... function test_normalize_codex_response_marks_reasoning_only_as_incomplete (line 856) | def test_normalize_codex_response_marks_reasoning_only_as_incomplete(mon... function test_normalize_codex_response_reasoning_with_content_is_stop (line 874) | def test_normalize_codex_response_reasoning_with_content_is_stop(monkeyp... function test_run_conversation_codex_continues_after_reasoning_only_response (line 902) | def test_run_conversation_codex_continues_after_reasoning_only_response(... function test_run_conversation_codex_preserves_encrypted_reasoning_in_interim (line 924) | def test_run_conversation_codex_preserves_encrypted_reasoning_in_interim... function test_chat_messages_to_responses_input_reasoning_only_has_following_item (line 964) | def test_chat_messages_to_responses_input_reasoning_only_has_following_i... function test_duplicate_detection_distinguishes_different_codex_reasoning (line 994) | def test_duplicate_detection_distinguishes_different_codex_reasoning(mon... FILE: tests/test_runtime_provider_resolution.py function test_resolve_runtime_provider_codex (line 4) | def test_resolve_runtime_provider_codex(monkeypatch): function test_resolve_runtime_provider_ai_gateway (line 29) | def test_resolve_runtime_provider_ai_gateway(monkeypatch): function test_resolve_runtime_provider_openrouter_explicit (line 43) | def test_resolve_runtime_provider_openrouter_explicit(monkeypatch): function test_resolve_runtime_provider_openrouter_ignores_codex_config_base_url (line 64) | def test_resolve_runtime_provider_openrouter_ignores_codex_config_base_u... function test_resolve_runtime_provider_auto_uses_custom_config_base_url (line 85) | def test_resolve_runtime_provider_auto_uses_custom_config_base_url(monke... function test_openrouter_key_takes_priority_over_openai_key (line 106) | def test_openrouter_key_takes_priority_over_openai_key(monkeypatch): function test_openai_key_used_when_no_openrouter_key (line 124) | def test_openai_key_used_when_no_openrouter_key(monkeypatch): function test_custom_endpoint_prefers_openai_key (line 138) | def test_custom_endpoint_prefers_openai_key(monkeypatch): function test_custom_endpoint_uses_saved_config_base_url_when_env_missing (line 157) | def test_custom_endpoint_uses_saved_config_base_url_when_env_missing(mon... function test_custom_endpoint_uses_config_api_key_over_env (line 180) | def test_custom_endpoint_uses_config_api_key_over_env(monkeypatch): function test_custom_endpoint_uses_config_api_field_when_no_api_key (line 202) | def test_custom_endpoint_uses_config_api_field_when_no_api_key(monkeypat... function test_custom_endpoint_auto_provider_prefers_openai_key (line 224) | def test_custom_endpoint_auto_provider_prefers_openai_key(monkeypatch): function test_named_custom_provider_uses_saved_credentials (line 242) | def test_named_custom_provider_uses_saved_credentials(monkeypatch): function test_named_custom_provider_falls_back_to_openai_api_key (line 278) | def test_named_custom_provider_falls_back_to_openai_api_key(monkeypatch): function test_named_custom_provider_does_not_shadow_builtin_provider (line 310) | def test_named_custom_provider_does_not_shadow_builtin_provider(monkeypa... function test_explicit_openrouter_skips_openai_base_url (line 343) | def test_explicit_openrouter_skips_openai_base_url(monkeypatch): function test_resolve_requested_provider_precedence (line 362) | def test_resolve_requested_provider_precedence(monkeypatch): function test_model_config_api_mode (line 378) | def test_model_config_api_mode(monkeypatch): function test_invalid_api_mode_ignored (line 400) | def test_invalid_api_mode_ignored(monkeypatch): function test_named_custom_provider_api_mode (line 414) | def test_named_custom_provider_api_mode(monkeypatch): function test_named_custom_provider_without_api_mode_defaults (line 433) | def test_named_custom_provider_without_api_mode_defaults(monkeypatch): function test_anthropic_messages_in_valid_api_modes (line 450) | def test_anthropic_messages_in_valid_api_modes(): function test_api_key_provider_anthropic_url_auto_detection (line 455) | def test_api_key_provider_anthropic_url_auto_detection(monkeypatch): function test_api_key_provider_explicit_api_mode_config (line 469) | def test_api_key_provider_explicit_api_mode_config(monkeypatch): function test_minimax_default_url_uses_anthropic_messages (line 482) | def test_minimax_default_url_uses_anthropic_messages(monkeypatch): function test_minimax_stale_v1_url_auto_corrected (line 496) | def test_minimax_stale_v1_url_auto_corrected(monkeypatch): function test_minimax_cn_stale_v1_url_auto_corrected (line 510) | def test_minimax_cn_stale_v1_url_auto_corrected(monkeypatch): function test_minimax_explicit_api_mode_respected (line 524) | def test_minimax_explicit_api_mode_respected(monkeypatch): function test_named_custom_provider_anthropic_api_mode (line 537) | def test_named_custom_provider_anthropic_api_mode(monkeypatch): FILE: tests/test_setup_model_selection.py function mock_provider_registry (line 11) | def mock_provider_registry(): class TestSetupProviderModelSelection (line 28) | class TestSetupProviderModelSelection: method test_falls_back_to_default_models_without_crashing (line 40) | def test_falls_back_to_default_models_without_crashing( method test_live_models_used_when_available (line 71) | def test_live_models_used_when_available( method test_custom_model_selection (line 101) | def test_custom_model_selection( FILE: tests/test_sql_injection.py function test_session_cols_no_injection_chars (line 8) | def test_session_cols_no_injection_chars(): function test_get_sessions_all_query_is_parameterized (line 17) | def test_get_sessions_all_query_is_parameterized(): function test_get_sessions_with_source_query_is_parameterized (line 26) | def test_get_sessions_with_source_query_is_parameterized(): function test_session_col_names_are_safe_identifiers (line 35) | def test_session_col_names_are_safe_identifiers(): FILE: tests/test_streaming.py function _make_stream_chunk (line 18) | def _make_stream_chunk( function _make_tool_call_delta (line 42) | def _make_tool_call_delta(index=0, tc_id=None, name=None, arguments=None): function _make_empty_chunk (line 48) | def _make_empty_chunk(model=None, usage=None): class TestStreamingAccumulator (line 56) | class TestStreamingAccumulator: method test_text_only_response (line 62) | def test_text_only_response(self, mock_close, mock_create): method test_tool_call_response (line 96) | def test_tool_call_response(self, mock_close, mock_create): method test_mixed_content_and_tool_calls (line 137) | def test_mixed_content_and_tool_calls(self, mock_close, mock_create): class TestStreamingCallbacks (line 174) | class TestStreamingCallbacks: method test_deltas_fire_in_order (line 179) | def test_deltas_fire_in_order(self, mock_close, mock_create): method test_on_first_delta_fires_once (line 212) | def test_on_first_delta_fires_once(self, mock_close, mock_create): method test_tool_only_does_not_fire_callback (line 245) | def test_tool_only_does_not_fire_callback(self, mock_close, mock_create): method test_text_suppressed_when_tool_calls_present (line 281) | def test_text_suppressed_when_tool_calls_present(self, mock_close, moc... class TestStreamingFallback (line 323) | class TestStreamingFallback: method test_stream_error_falls_back (line 329) | def test_stream_error_falls_back(self, mock_close, mock_create, mock_n... method test_any_stream_error_falls_back (line 373) | def test_any_stream_error_falls_back(self, mock_close, mock_create, mo... method test_fallback_error_propagates (line 417) | def test_fallback_error_propagates(self, mock_close, mock_create, mock... class TestReasoningStreaming (line 443) | class TestReasoningStreaming: method test_reasoning_callback_fires (line 448) | def test_reasoning_callback_fires(self, mock_close, mock_create): class TestHasStreamConsumers (line 488) | class TestHasStreamConsumers: method test_no_consumers (line 491) | def test_no_consumers(self): method test_delta_callback_set (line 501) | def test_delta_callback_set(self): method test_stream_callback_set (line 512) | def test_stream_callback_set(self): class TestCodexStreamCallbacks (line 527) | class TestCodexStreamCallbacks: method test_codex_text_delta_fires_callback (line 530) | def test_codex_text_delta_fires_callback(self): FILE: tests/test_timezone.py class TestHermesTimeNow (line 27) | class TestHermesTimeNow: method setup_method (line 30) | def setup_method(self): method teardown_method (line 33) | def teardown_method(self): method test_valid_timezone_applies (line 37) | def test_valid_timezone_applies(self): method test_utc_timezone (line 46) | def test_utc_timezone(self): method test_us_eastern (line 52) | def test_us_eastern(self): method test_invalid_timezone_falls_back (line 61) | def test_invalid_timezone_falls_back(self, caplog): method test_empty_timezone_uses_local (line 70) | def test_empty_timezone_uses_local(self): method test_format_unchanged (line 76) | def test_format_unchanged(self): method test_cache_invalidation (line 86) | def test_cache_invalidation(self): class TestGetTimezone (line 99) | class TestGetTimezone: method setup_method (line 102) | def setup_method(self): method teardown_method (line 105) | def teardown_method(self): method test_returns_zoneinfo_for_valid (line 109) | def test_returns_zoneinfo_for_valid(self): method test_returns_none_for_empty (line 115) | def test_returns_none_for_empty(self): method test_returns_none_for_invalid (line 120) | def test_returns_none_for_invalid(self): method test_get_timezone_name (line 125) | def test_get_timezone_name(self): class TestCodeExecutionTZ (line 135) | class TestCodeExecutionTZ: method _import_execute_code (line 139) | def _import_execute_code(self): method teardown_method (line 147) | def teardown_method(self): method _mock_handle (line 150) | def _mock_handle(self, function_name, function_args, task_id=None, use... method test_tz_injected_when_configured (line 154) | def test_tz_injected_when_configured(self): method test_tz_not_injected_when_empty (line 168) | def test_tz_not_injected_when_empty(self): method test_hermes_timezone_not_leaked_to_child (line 182) | def test_hermes_timezone_not_leaked_to_child(self): class TestCronTimezone (line 201) | class TestCronTimezone: method setup_method (line 204) | def setup_method(self): method teardown_method (line 207) | def teardown_method(self): method test_parse_schedule_duration_uses_tz_aware_now (line 211) | def test_parse_schedule_duration_uses_tz_aware_now(self): method test_compute_next_run_tz_aware (line 220) | def test_compute_next_run_tz_aware(self): method test_get_due_jobs_handles_naive_timestamps (line 229) | def test_get_due_jobs_handles_naive_timestamps(self, tmp_path, monkeyp... method test_ensure_aware_naive_preserves_absolute_time (line 252) | def test_ensure_aware_naive_preserves_absolute_time(self): method test_ensure_aware_normalizes_aware_to_hermes_tz (line 281) | def test_ensure_aware_normalizes_aware_to_hermes_tz(self): method test_ensure_aware_due_job_not_skipped_when_system_ahead (line 298) | def test_ensure_aware_due_job_not_skipped_when_system_ahead(self, tmp_... method test_get_due_jobs_naive_cross_timezone (line 331) | def test_get_due_jobs_naive_cross_timezone(self, tmp_path, monkeypatch): method test_create_job_stores_tz_aware_timestamps (line 359) | def test_create_job_stores_tz_aware_timestamps(self, tmp_path, monkeyp... FILE: tests/test_tool_call_parsers.py class TestParserRegistry (line 30) | class TestParserRegistry: method test_list_parsers_returns_nonempty (line 31) | def test_list_parsers_returns_nonempty(self): method test_hermes_parser_registered (line 35) | def test_hermes_parser_registered(self): method test_get_parser_returns_instance (line 39) | def test_get_parser_returns_instance(self): method test_get_parser_unknown_raises (line 43) | def test_get_parser_unknown_raises(self): method test_all_registered_parsers_instantiate (line 47) | def test_all_registered_parsers_instantiate(self): class TestHermesParser (line 57) | class TestHermesParser: method parser (line 59) | def parser(self): method test_no_tool_call (line 62) | def test_no_tool_call(self, parser): method test_single_tool_call (line 68) | def test_single_tool_call(self, parser): method test_tool_call_with_surrounding_text (line 77) | def test_tool_call_with_surrounding_text(self, parser): method test_multiple_tool_calls (line 87) | def test_multiple_tool_calls(self, parser): method test_tool_call_ids_are_unique (line 99) | def test_tool_call_ids_are_unique(self, parser): method test_empty_string (line 109) | def test_empty_string(self, parser): method test_malformed_json_in_tool_call (line 113) | def test_malformed_json_in_tool_call(self, parser): method test_truncated_tool_call (line 119) | def test_truncated_tool_call(self, parser): class TestParseResultContract (line 129) | class TestParseResultContract: method parser (line 133) | def parser(self, request): method test_returns_tuple_of_two (line 136) | def test_returns_tuple_of_two(self, parser): method test_no_tools_returns_none_tool_calls (line 141) | def test_no_tools_returns_none_tool_calls(self, parser): method test_tool_calls_are_proper_objects (line 146) | def test_tool_calls_are_proper_objects(self, parser): class TestDeepSeekV3Parser (line 164) | class TestDeepSeekV3Parser: method parser (line 166) | def parser(self): method test_no_tool_call (line 169) | def test_no_tool_call(self, parser): method test_single_tool_call (line 175) | def test_single_tool_call(self, parser): method test_multiple_tool_calls (line 187) | def test_multiple_tool_calls(self, parser): method test_tool_call_with_preceding_text (line 203) | def test_tool_call_with_preceding_text(self, parser): FILE: tests/test_toolset_distributions.py class TestGetDistribution (line 15) | class TestGetDistribution: method test_known_distribution (line 16) | def test_known_distribution(self): method test_unknown_returns_none (line 22) | def test_unknown_returns_none(self): method test_all_named_distributions_exist (line 25) | def test_all_named_distributions_exist(self): class TestListDistributions (line 36) | class TestListDistributions: method test_returns_copy (line 37) | def test_returns_copy(self): method test_contains_all (line 43) | def test_contains_all(self): class TestValidateDistribution (line 48) | class TestValidateDistribution: method test_valid (line 49) | def test_valid(self): method test_invalid (line 53) | def test_invalid(self): class TestSampleToolsetsFromDistribution (line 58) | class TestSampleToolsetsFromDistribution: method test_unknown_raises (line 59) | def test_unknown_raises(self): method test_default_returns_all_toolsets (line 63) | def test_default_returns_all_toolsets(self): method test_minimal_returns_web_only (line 72) | def test_minimal_returns_web_only(self): method test_returns_list_of_strings (line 76) | def test_returns_list_of_strings(self): method test_fallback_guarantees_at_least_one (line 82) | def test_fallback_guarantees_at_least_one(self): class TestDistributionStructure (line 89) | class TestDistributionStructure: method test_all_have_required_keys (line 90) | def test_all_have_required_keys(self): method test_probabilities_are_valid_range (line 96) | def test_probabilities_are_valid_range(self): method test_descriptions_non_empty (line 101) | def test_descriptions_non_empty(self): FILE: tests/test_toolsets.py class TestGetToolset (line 18) | class TestGetToolset: method test_known_toolset (line 19) | def test_known_toolset(self): method test_unknown_returns_none (line 24) | def test_unknown_returns_none(self): class TestResolveToolset (line 28) | class TestResolveToolset: method test_leaf_toolset (line 29) | def test_leaf_toolset(self): method test_composite_toolset (line 33) | def test_composite_toolset(self): method test_cycle_detection (line 39) | def test_cycle_detection(self): method test_unknown_toolset_returns_empty (line 52) | def test_unknown_toolset_returns_empty(self): method test_all_alias (line 55) | def test_all_alias(self): method test_star_alias (line 59) | def test_star_alias(self): class TestResolveMultipleToolsets (line 64) | class TestResolveMultipleToolsets: method test_combines_and_deduplicates (line 65) | def test_combines_and_deduplicates(self): method test_empty_list (line 73) | def test_empty_list(self): class TestValidateToolset (line 77) | class TestValidateToolset: method test_valid (line 78) | def test_valid(self): method test_all_alias_valid (line 82) | def test_all_alias_valid(self): method test_invalid (line 86) | def test_invalid(self): class TestGetToolsetInfo (line 90) | class TestGetToolsetInfo: method test_leaf (line 91) | def test_leaf(self): method test_composite (line 97) | def test_composite(self): method test_unknown_returns_none (line 102) | def test_unknown_returns_none(self): class TestCreateCustomToolset (line 106) | class TestCreateCustomToolset: method test_runtime_creation (line 107) | def test_runtime_creation(self): class TestToolsetConsistency (line 123) | class TestToolsetConsistency: method test_all_toolsets_have_required_keys (line 126) | def test_all_toolsets_have_required_keys(self): method test_all_includes_reference_existing_toolsets (line 132) | def test_all_includes_reference_existing_toolsets(self): method test_hermes_platforms_share_core_tools (line 137) | def test_hermes_platforms_share_core_tools(self): FILE: tests/test_trajectory_compressor.py class TestCompressionConfig (line 22) | class TestCompressionConfig: method test_defaults (line 23) | def test_defaults(self): method test_from_yaml (line 30) | def test_from_yaml(self, tmp_path): method test_from_yaml_partial (line 80) | def test_from_yaml_partial(self, tmp_path): method test_from_yaml_empty (line 90) | def test_from_yaml_empty(self, tmp_path): class TestTrajectoryMetrics (line 102) | class TestTrajectoryMetrics: method test_to_dict (line 103) | def test_to_dict(self): method test_default_values (line 120) | def test_default_values(self): class TestAggregateMetrics (line 133) | class TestAggregateMetrics: method test_empty_to_dict (line 134) | def test_empty_to_dict(self): method test_add_compressed_trajectory (line 141) | def test_add_compressed_trajectory(self): method test_add_skipped_trajectory (line 158) | def test_add_skipped_trajectory(self): method test_add_over_limit_trajectory (line 168) | def test_add_over_limit_trajectory(self): method test_multiple_trajectories_aggregation (line 179) | def test_multiple_trajectories_aggregation(self): method test_to_dict_no_division_by_zero (line 196) | def test_to_dict_no_division_by_zero(self): function _make_compressor (line 209) | def _make_compressor(config=None): class TestFindProtectedIndices (line 222) | class TestFindProtectedIndices: method test_basic_trajectory (line 223) | def test_basic_trajectory(self): method test_short_trajectory_all_protected (line 252) | def test_short_trajectory_all_protected(self): method test_protect_last_n_zero (line 264) | def test_protect_last_n_zero(self): method test_no_system_turn (line 286) | def test_no_system_turn(self): method test_disable_protect_first_system (line 298) | def test_disable_protect_first_system(self): class TestExtractTurnContent (line 321) | class TestExtractTurnContent: method test_basic_extraction (line 322) | def test_basic_extraction(self): method test_long_content_truncated (line 337) | def test_long_content_truncated(self): method test_empty_range (line 346) | def test_empty_range(self): class TestTokenCounting (line 358) | class TestTokenCounting: method test_count_tokens_empty (line 359) | def test_count_tokens_empty(self): method test_count_tokens_basic (line 363) | def test_count_tokens_basic(self): method test_count_trajectory_tokens (line 368) | def test_count_trajectory_tokens(self): method test_count_turn_tokens (line 376) | def test_count_turn_tokens(self): method test_count_tokens_fallback_on_error (line 385) | def test_count_tokens_fallback_on_error(self): class TestGenerateSummary (line 392) | class TestGenerateSummary: method test_generate_summary_handles_none_content (line 393) | def test_generate_summary_handles_none_content(self): method test_generate_summary_async_handles_none_content (line 406) | async def test_generate_summary_async_handles_none_content(self): FILE: tests/test_worktree.py function git_repo (line 16) | def git_repo(tmp_path): function _git_repo_root (line 43) | def _git_repo_root(cwd=None): function _setup_worktree (line 58) | def _setup_worktree(repo_root): function _cleanup_worktree (line 83) | def _cleanup_worktree(info): class TestGitRepoDetection (line 117) | class TestGitRepoDetection: method test_detects_git_repo (line 120) | def test_detects_git_repo(self, git_repo): method test_detects_subdirectory (line 125) | def test_detects_subdirectory(self, git_repo): method test_returns_none_outside_repo (line 132) | def test_returns_none_outside_repo(self, tmp_path): class TestWorktreeCreation (line 140) | class TestWorktreeCreation: method test_creates_worktree (line 143) | def test_creates_worktree(self, git_repo): method test_worktree_has_own_branch (line 157) | def test_worktree_has_own_branch(self, git_repo): method test_worktree_is_independent (line 168) | def test_worktree_is_independent(self, git_repo): method test_worktrees_dir_created (line 183) | def test_worktrees_dir_created(self, git_repo): method test_worktree_has_repo_files (line 188) | def test_worktree_has_repo_files(self, git_repo): class TestWorktreeCleanup (line 195) | class TestWorktreeCleanup: method test_clean_worktree_removed (line 198) | def test_clean_worktree_removed(self, git_repo): method test_dirty_worktree_kept (line 207) | def test_dirty_worktree_kept(self, git_repo): method test_branch_deleted_on_cleanup (line 222) | def test_branch_deleted_on_cleanup(self, git_repo): method test_cleanup_nonexistent_worktree (line 235) | def test_cleanup_nonexistent_worktree(self, git_repo): class TestWorktreeInclude (line 246) | class TestWorktreeInclude: method test_copies_included_files (line 249) | def test_copies_included_files(self, git_repo): method test_ignores_comments_and_blanks (line 288) | def test_ignores_comments_and_blanks(self, git_repo): class TestGitignoreManagement (line 300) | class TestGitignoreManagement: method test_adds_to_gitignore (line 303) | def test_adds_to_gitignore(self, git_repo): method test_does_not_duplicate_gitignore_entry (line 325) | def test_does_not_duplicate_gitignore_entry(self, git_repo): class TestMultipleWorktrees (line 335) | class TestMultipleWorktrees: method test_ten_concurrent_worktrees (line 338) | def test_ten_concurrent_worktrees(self, git_repo): class TestWorktreeDirectorySymlink (line 384) | class TestWorktreeDirectorySymlink: method test_symlinks_directory (line 387) | def test_symlinks_directory(self, git_repo): class TestStaleWorktreePruning (line 419) | class TestStaleWorktreePruning: method test_prunes_old_clean_worktree (line 422) | def test_prunes_old_clean_worktree(self, git_repo): method test_keeps_recent_worktree (line 472) | def test_keeps_recent_worktree(self, git_repo): method test_keeps_dirty_old_worktree (line 495) | def test_keeps_dirty_old_worktree(self, git_repo): class TestEdgeCases (line 523) | class TestEdgeCases: method test_no_commits_repo (line 526) | def test_no_commits_repo(self, tmp_path): method test_not_a_git_repo (line 535) | def test_not_a_git_repo(self, tmp_path): method test_worktrees_dir_already_exists (line 542) | def test_worktrees_dir_already_exists(self, git_repo): class TestCLIFlagLogic (line 550) | class TestCLIFlagLogic: method test_worktree_flag_triggers (line 553) | def test_worktree_flag_triggers(self): method test_w_flag_triggers (line 561) | def test_w_flag_triggers(self): method test_config_triggers (line 569) | def test_config_triggers(self): method test_none_set_no_trigger (line 577) | def test_none_set_no_trigger(self): class TestTerminalCWDIntegration (line 586) | class TestTerminalCWDIntegration: method test_terminal_cwd_set (line 589) | def test_terminal_cwd_set(self, git_repo): method test_terminal_cwd_is_valid_git_repo (line 602) | def test_terminal_cwd_is_valid_git_repo(self, git_repo): class TestSystemPromptInjection (line 614) | class TestSystemPromptInjection: method test_prompt_note_format (line 617) | def test_prompt_note_format(self, git_repo): FILE: tests/test_worktree_security.py function git_repo (line 10) | def git_repo(tmp_path): function _force_remove_worktree (line 23) | def _force_remove_worktree(info: dict | None) -> None: class TestWorktreeIncludeSecurity (line 40) | class TestWorktreeIncludeSecurity: method test_rejects_parent_directory_file_traversal (line 41) | def test_rejects_parent_directory_file_traversal(self, git_repo): method test_rejects_parent_directory_directory_traversal (line 59) | def test_rejects_parent_directory_directory_traversal(self, git_repo): method test_rejects_symlink_that_resolves_outside_repo (line 79) | def test_rejects_symlink_that_resolves_outside_repo(self, git_repo): method test_allows_valid_file_include (line 96) | def test_allows_valid_file_include(self, git_repo): method test_allows_valid_directory_include (line 113) | def test_allows_valid_directory_include(self, git_repo): FILE: tests/tools/test_approval.py class TestDetectDangerousRm (line 19) | class TestDetectDangerousRm: method test_rm_rf_detected (line 20) | def test_rm_rf_detected(self): method test_rm_recursive_long_flag (line 26) | def test_rm_recursive_long_flag(self): class TestDetectDangerousSudo (line 33) | class TestDetectDangerousSudo: method test_shell_via_c_flag (line 34) | def test_shell_via_c_flag(self): method test_curl_pipe_sh (line 40) | def test_curl_pipe_sh(self): method test_shell_via_lc_flag (line 46) | def test_shell_via_lc_flag(self): method test_shell_via_lc_with_newline (line 52) | def test_shell_via_lc_with_newline(self): method test_ksh_via_c_flag (line 59) | def test_ksh_via_c_flag(self): class TestDetectSqlPatterns (line 66) | class TestDetectSqlPatterns: method test_drop_table (line 67) | def test_drop_table(self): method test_delete_without_where (line 72) | def test_delete_without_where(self): method test_delete_with_where_safe (line 77) | def test_delete_with_where_safe(self): class TestSafeCommand (line 84) | class TestSafeCommand: method test_echo_is_safe (line 85) | def test_echo_is_safe(self): method test_ls_is_safe (line 90) | def test_ls_is_safe(self): method test_git_is_safe (line 96) | def test_git_is_safe(self): class TestSubmitAndPopPending (line 103) | class TestSubmitAndPopPending: method test_submit_and_pop (line 104) | def test_submit_and_pop(self): method test_pop_empty_returns_none (line 115) | def test_pop_empty_returns_none(self): class TestApproveAndCheckSession (line 122) | class TestApproveAndCheckSession: method test_session_approval (line 123) | def test_session_approval(self): method test_clear_session_removes_approvals (line 131) | def test_clear_session_removes_approvals(self): class TestRmFalsePositiveFix (line 140) | class TestRmFalsePositiveFix: method test_rm_readme_not_flagged (line 143) | def test_rm_readme_not_flagged(self): method test_rm_requirements_not_flagged (line 148) | def test_rm_requirements_not_flagged(self): method test_rm_report_not_flagged (line 153) | def test_rm_report_not_flagged(self): method test_rm_results_not_flagged (line 158) | def test_rm_results_not_flagged(self): method test_rm_robots_not_flagged (line 163) | def test_rm_robots_not_flagged(self): method test_rm_run_not_flagged (line 168) | def test_rm_run_not_flagged(self): method test_rm_force_readme_not_flagged (line 173) | def test_rm_force_readme_not_flagged(self): method test_rm_verbose_readme_not_flagged (line 178) | def test_rm_verbose_readme_not_flagged(self): class TestRmRecursiveFlagVariants (line 184) | class TestRmRecursiveFlagVariants: method test_rm_r (line 187) | def test_rm_r(self): method test_rm_rf (line 193) | def test_rm_rf(self): method test_rm_rfv (line 198) | def test_rm_rfv(self): method test_rm_fr (line 203) | def test_rm_fr(self): method test_rm_irf (line 208) | def test_rm_irf(self): method test_rm_recursive_long (line 213) | def test_rm_recursive_long(self): method test_sudo_rm_rf (line 218) | def test_sudo_rm_rf(self): class TestMultilineBypass (line 224) | class TestMultilineBypass: method test_curl_pipe_sh_with_newline (line 227) | def test_curl_pipe_sh_with_newline(self): method test_wget_pipe_bash_with_newline (line 233) | def test_wget_pipe_bash_with_newline(self): method test_dd_with_newline (line 239) | def test_dd_with_newline(self): method test_chmod_recursive_with_newline (line 245) | def test_chmod_recursive_with_newline(self): method test_find_exec_rm_with_newline (line 251) | def test_find_exec_rm_with_newline(self): method test_find_delete_with_newline (line 257) | def test_find_delete_with_newline(self): class TestProcessSubstitutionPattern (line 264) | class TestProcessSubstitutionPattern: method test_bash_curl_process_sub (line 267) | def test_bash_curl_process_sub(self): method test_sh_wget_process_sub (line 272) | def test_sh_wget_process_sub(self): method test_zsh_curl_process_sub (line 277) | def test_zsh_curl_process_sub(self): method test_ksh_curl_process_sub (line 282) | def test_ksh_curl_process_sub(self): method test_bash_redirect_from_process_sub (line 287) | def test_bash_redirect_from_process_sub(self): method test_plain_curl_not_flagged (line 292) | def test_plain_curl_not_flagged(self): method test_bash_script_not_flagged (line 297) | def test_bash_script_not_flagged(self): class TestTeePattern (line 303) | class TestTeePattern: method test_tee_etc_passwd (line 306) | def test_tee_etc_passwd(self): method test_tee_etc_sudoers (line 311) | def test_tee_etc_sudoers(self): method test_tee_ssh_authorized_keys (line 316) | def test_tee_ssh_authorized_keys(self): method test_tee_block_device (line 321) | def test_tee_block_device(self): method test_tee_hermes_env (line 326) | def test_tee_hermes_env(self): method test_tee_tmp_safe (line 331) | def test_tee_tmp_safe(self): method test_tee_local_file_safe (line 336) | def test_tee_local_file_safe(self): class TestFindExecFullPathRm (line 342) | class TestFindExecFullPathRm: method test_find_exec_bin_rm (line 345) | def test_find_exec_bin_rm(self): method test_find_exec_usr_bin_rm (line 350) | def test_find_exec_usr_bin_rm(self): method test_find_exec_bare_rm_still_works (line 355) | def test_find_exec_bare_rm_still_works(self): method test_find_print_safe (line 360) | def test_find_print_safe(self): class TestPatternKeyUniqueness (line 366) | class TestPatternKeyUniqueness: method test_find_exec_rm_and_find_delete_have_different_keys (line 371) | def test_find_exec_rm_and_find_delete_have_different_keys(self): method test_approving_find_exec_does_not_approve_find_delete (line 379) | def test_approving_find_exec_does_not_approve_find_delete(self): method test_legacy_find_key_still_approves_find_exec (line 392) | def test_legacy_find_key_still_approves_find_exec(self): method test_legacy_find_key_still_approves_find_delete (line 399) | def test_legacy_find_key_still_approves_find_delete(self): class TestFullCommandAlwaysShown (line 407) | class TestFullCommandAlwaysShown: method test_once_with_long_command (line 415) | def test_once_with_long_command(self): method test_session_with_long_command (line 422) | def test_session_with_long_command(self): method test_always_with_long_command (line 429) | def test_always_with_long_command(self): method test_deny_with_long_command (line 436) | def test_deny_with_long_command(self): method test_invalid_input_denies (line 443) | def test_invalid_input_denies(self): class TestForkBombDetection (line 451) | class TestForkBombDetection: method test_classic_fork_bomb (line 454) | def test_classic_fork_bomb(self): method test_fork_bomb_with_spaces (line 459) | def test_fork_bomb_with_spaces(self): method test_colon_in_safe_command_not_flagged (line 463) | def test_colon_in_safe_command_not_flagged(self): FILE: tests/tools/test_browser_cdp_override.py class TestResolveCdpOverride (line 11) | class TestResolveCdpOverride: method test_keeps_full_devtools_websocket_url (line 12) | def test_keeps_full_devtools_websocket_url(self): method test_resolves_http_discovery_endpoint_to_websocket (line 17) | def test_resolves_http_discovery_endpoint_to_websocket(self): method test_resolves_bare_ws_hostport_to_discovery_websocket (line 30) | def test_resolves_bare_ws_hostport_to_discovery_websocket(self): method test_falls_back_to_raw_url_when_discovery_fails (line 43) | def test_falls_back_to_raw_url_when_discovery_fails(self): FILE: tests/tools/test_browser_cleanup.py class TestScreenshotPathRecovery (line 6) | class TestScreenshotPathRecovery: method test_extracts_standard_absolute_path (line 7) | def test_extracts_standard_absolute_path(self): method test_extracts_quoted_absolute_path (line 15) | def test_extracts_quoted_absolute_path(self): class TestBrowserCleanup (line 26) | class TestBrowserCleanup: method setup_method (line 27) | def setup_method(self): method teardown_method (line 36) | def teardown_method(self): method test_cleanup_browser_clears_tracking_state (line 45) | def test_cleanup_browser_clears_tracking_state(self): method test_browser_close_delegates_to_cleanup_browser (line 68) | def test_browser_close_delegates_to_cleanup_browser(self): method test_emergency_cleanup_clears_all_tracking_state (line 80) | def test_emergency_cleanup_clears_all_tracking_state(self): FILE: tests/tools/test_browser_console.py class TestBrowserConsole (line 16) | class TestBrowserConsole: method test_returns_console_messages_and_errors (line 19) | def test_returns_console_messages_and_errors(self): method test_passes_clear_flag (line 51) | def test_passes_clear_flag(self): method test_no_clear_by_default (line 63) | def test_no_clear_by_default(self): method test_empty_console_and_errors (line 74) | def test_empty_console_and_errors(self): method test_handles_failed_commands (line 86) | def test_handles_failed_commands(self): class TestBrowserConsoleSchema (line 102) | class TestBrowserConsoleSchema: method test_schema_in_browser_schemas (line 105) | def test_schema_in_browser_schemas(self): method test_schema_has_clear_param (line 111) | def test_schema_has_clear_param(self): class TestBrowserConsoleToolsetWiring (line 120) | class TestBrowserConsoleToolsetWiring: method test_in_browser_toolset (line 123) | def test_in_browser_toolset(self): method test_in_hermes_core_tools (line 127) | def test_in_hermes_core_tools(self): method test_in_legacy_toolset_map (line 131) | def test_in_legacy_toolset_map(self): method test_in_registry (line 135) | def test_in_registry(self): class TestBrowserVisionAnnotate (line 144) | class TestBrowserVisionAnnotate: method test_schema_has_annotate_param (line 147) | def test_schema_has_annotate_param(self): method test_annotate_false_no_flag (line 155) | def test_annotate_false_no_flag(self): method test_annotate_true_adds_flag (line 176) | def test_annotate_true_adds_flag(self): class TestRecordSessionsConfig (line 200) | class TestRecordSessionsConfig: method test_default_config_has_record_sessions (line 203) | def test_default_config_has_record_sessions(self): method test_maybe_start_recording_disabled (line 210) | def test_maybe_start_recording_disabled(self): method test_maybe_stop_recording_noop_when_not_recording (line 223) | def test_maybe_stop_recording_noop_when_not_recording(self): class TestDogfoodSkill (line 237) | class TestDogfoodSkill: method _skill_dir (line 241) | def _skill_dir(self): method test_skill_md_exists (line 247) | def test_skill_md_exists(self): method test_taxonomy_exists (line 250) | def test_taxonomy_exists(self): method test_report_template_exists (line 255) | def test_report_template_exists(self): method test_skill_md_has_frontmatter (line 260) | def test_skill_md_has_frontmatter(self): method test_skill_references_browser_console (line 267) | def test_skill_references_browser_console(self): method test_skill_references_annotate (line 272) | def test_skill_references_annotate(self): method test_taxonomy_has_severity_levels (line 277) | def test_taxonomy_has_severity_levels(self): method test_taxonomy_has_categories (line 287) | def test_taxonomy_has_categories(self): FILE: tests/tools/test_checkpoint_manager.py function work_dir (line 30) | def work_dir(tmp_path): function checkpoint_base (line 40) | def checkpoint_base(tmp_path): function mgr (line 46) | def mgr(work_dir, checkpoint_base, monkeypatch): function disabled_mgr (line 53) | def disabled_mgr(checkpoint_base, monkeypatch): class TestShadowRepoPath (line 63) | class TestShadowRepoPath: method test_deterministic (line 64) | def test_deterministic(self, work_dir, checkpoint_base, monkeypatch): method test_different_dirs_different_paths (line 70) | def test_different_dirs_different_paths(self, tmp_path, checkpoint_bas... method test_under_checkpoint_base (line 76) | def test_under_checkpoint_base(self, work_dir, checkpoint_base, monkey... class TestShadowRepoInit (line 86) | class TestShadowRepoInit: method test_creates_git_repo (line 87) | def test_creates_git_repo(self, work_dir, checkpoint_base, monkeypatch): method test_no_git_in_project_dir (line 94) | def test_no_git_in_project_dir(self, work_dir, checkpoint_base, monkey... method test_has_exclude_file (line 100) | def test_has_exclude_file(self, work_dir, checkpoint_base, monkeypatch): method test_has_workdir_file (line 110) | def test_has_workdir_file(self, work_dir, checkpoint_base, monkeypatch): method test_idempotent (line 118) | def test_idempotent(self, work_dir, checkpoint_base, monkeypatch): class TestDisabledManager (line 131) | class TestDisabledManager: method test_ensure_checkpoint_returns_false (line 132) | def test_ensure_checkpoint_returns_false(self, disabled_mgr, work_dir): method test_new_turn_works (line 135) | def test_new_turn_works(self, disabled_mgr): class TestTakeCheckpoint (line 143) | class TestTakeCheckpoint: method test_first_checkpoint (line 144) | def test_first_checkpoint(self, mgr, work_dir): method test_successful_checkpoint_does_not_log_expected_diff_exit (line 148) | def test_successful_checkpoint_does_not_log_expected_diff_exit(self, m... method test_dedup_same_turn (line 154) | def test_dedup_same_turn(self, mgr, work_dir): method test_new_turn_resets_dedup (line 160) | def test_new_turn_resets_dedup(self, mgr, work_dir): method test_no_changes_skips_commit (line 171) | def test_no_changes_skips_commit(self, mgr, work_dir): method test_skip_root_dir (line 180) | def test_skip_root_dir(self, mgr): method test_skip_home_dir (line 184) | def test_skip_home_dir(self, mgr): class TestListCheckpoints (line 193) | class TestListCheckpoints: method test_empty_when_no_checkpoints (line 194) | def test_empty_when_no_checkpoints(self, mgr, work_dir): method test_list_after_take (line 198) | def test_list_after_take(self, mgr, work_dir): method test_multiple_checkpoints_ordered (line 207) | def test_multiple_checkpoints_ordered(self, mgr, work_dir): class TestRestore (line 229) | class TestRestore: method test_restore_to_previous (line 230) | def test_restore_to_previous(self, mgr, work_dir): method test_restore_invalid_hash (line 250) | def test_restore_invalid_hash(self, mgr, work_dir): method test_restore_no_checkpoints (line 255) | def test_restore_no_checkpoints(self, mgr, work_dir): method test_restore_creates_pre_rollback_snapshot (line 259) | def test_restore_creates_pre_rollback_snapshot(self, mgr, work_dir): class TestWorkingDirResolution (line 279) | class TestWorkingDirResolution: method test_resolves_git_project_root (line 280) | def test_resolves_git_project_root(self, tmp_path): method test_resolves_pyproject_root (line 293) | def test_resolves_pyproject_root(self, tmp_path): method test_falls_back_to_parent (line 304) | def test_falls_back_to_parent(self, tmp_path): class TestGitEnvIsolation (line 318) | class TestGitEnvIsolation: method test_sets_git_dir (line 319) | def test_sets_git_dir(self, tmp_path): method test_sets_work_tree (line 324) | def test_sets_work_tree(self, tmp_path): method test_clears_index_file (line 330) | def test_clears_index_file(self, tmp_path, monkeypatch): class TestFormatCheckpointList (line 341) | class TestFormatCheckpointList: method test_empty_list (line 342) | def test_empty_list(self): method test_formats_entries (line 346) | def test_formats_entries(self): class TestDirFileCount (line 362) | class TestDirFileCount: method test_counts_files (line 363) | def test_counts_files(self, work_dir): method test_nonexistent_dir (line 367) | def test_nonexistent_dir(self, tmp_path): class TestErrorResilience (line 376) | class TestErrorResilience: method test_no_git_installed (line 377) | def test_no_git_installed(self, work_dir, checkpoint_base, monkeypatch): method test_run_git_allows_expected_nonzero_without_error_log (line 386) | def test_run_git_allows_expected_nonzero_without_error_log(self, tmp_p... method test_checkpoint_failure_does_not_raise (line 406) | def test_checkpoint_failure_does_not_raise(self, mgr, work_dir, monkey... FILE: tests/tools/test_clarify_tool.py class TestClarifyToolBasics (line 16) | class TestClarifyToolBasics: method test_simple_question_with_callback (line 19) | def test_simple_question_with_callback(self): method test_question_with_choices (line 31) | def test_question_with_choices(self): method test_empty_question_returns_error (line 47) | def test_empty_question_returns_error(self): method test_whitespace_only_question_returns_error (line 53) | def test_whitespace_only_question_returns_error(self): method test_no_callback_returns_error (line 58) | def test_no_callback_returns_error(self): class TestClarifyToolChoicesValidation (line 65) | class TestClarifyToolChoicesValidation: method test_choices_trimmed_to_max (line 68) | def test_choices_trimmed_to_max(self): method test_empty_choices_become_none (line 81) | def test_empty_choices_become_none(self): method test_choices_with_only_whitespace_stripped (line 94) | def test_choices_with_only_whitespace_stripped(self): method test_invalid_choices_type_returns_error (line 105) | def test_invalid_choices_type_returns_error(self): method test_choices_converted_to_strings (line 115) | def test_choices_converted_to_strings(self): class TestClarifyToolCallbackHandling (line 127) | class TestClarifyToolCallbackHandling: method test_callback_exception_returns_error (line 130) | def test_callback_exception_returns_error(self): method test_callback_receives_stripped_question (line 140) | def test_callback_receives_stripped_question(self): method test_user_response_stripped (line 151) | def test_user_response_stripped(self): class TestCheckClarifyRequirements (line 160) | class TestCheckClarifyRequirements: method test_always_returns_true (line 163) | def test_always_returns_true(self): class TestClarifySchema (line 168) | class TestClarifySchema: method test_schema_name (line 171) | def test_schema_name(self): method test_schema_has_description (line 175) | def test_schema_has_description(self): method test_schema_question_required (line 180) | def test_schema_question_required(self): method test_schema_choices_optional (line 184) | def test_schema_choices_optional(self): method test_schema_choices_max_items (line 188) | def test_schema_choices_max_items(self): method test_max_choices_is_four (line 193) | def test_max_choices_is_four(self): FILE: tests/tools/test_clipboard.py class TestSaveClipboardImage (line 45) | class TestSaveClipboardImage: method test_dispatches_to_macos_on_darwin (line 46) | def test_dispatches_to_macos_on_darwin(self, tmp_path): method test_dispatches_to_linux_on_linux (line 54) | def test_dispatches_to_linux_on_linux(self, tmp_path): method test_creates_parent_dirs (line 62) | def test_creates_parent_dirs(self, tmp_path): class TestMacosPngpaste (line 73) | class TestMacosPngpaste: method test_success_writes_file (line 74) | def test_success_writes_file(self, tmp_path): method test_not_installed (line 83) | def test_not_installed(self, tmp_path): method test_no_image_in_clipboard (line 87) | def test_no_image_in_clipboard(self, tmp_path): method test_empty_file_rejected (line 94) | def test_empty_file_rejected(self, tmp_path): method test_timeout_returns_false (line 102) | def test_timeout_returns_false(self, tmp_path): class TestMacosHasImage (line 109) | class TestMacosHasImage: method test_png_detected (line 110) | def test_png_detected(self): method test_tiff_detected (line 117) | def test_tiff_detected(self): method test_text_only (line 124) | def test_text_only(self): class TestMacosOsascript (line 132) | class TestMacosOsascript: method test_no_image_type_in_clipboard (line 133) | def test_no_image_type_in_clipboard(self, tmp_path): method test_clipboard_info_fails (line 140) | def test_clipboard_info_fails(self, tmp_path): method test_success_with_png (line 144) | def test_success_with_png(self, tmp_path): method test_success_with_tiff (line 157) | def test_success_with_tiff(self, tmp_path): method test_extraction_returns_fail (line 169) | def test_extraction_returns_fail(self, tmp_path): method test_extraction_writes_empty_file (line 180) | def test_extraction_writes_empty_file(self, tmp_path): class TestIsWsl (line 195) | class TestIsWsl: method setup_method (line 196) | def setup_method(self): method test_wsl2_detected (line 201) | def test_wsl2_detected(self): method test_wsl1_detected (line 206) | def test_wsl1_detected(self): method test_regular_linux (line 211) | def test_regular_linux(self): method test_proc_version_missing (line 216) | def test_proc_version_missing(self): method test_result_is_cached (line 220) | def test_result_is_cached(self): class TestWslHasImage (line 230) | class TestWslHasImage: method test_clipboard_has_image (line 231) | def test_clipboard_has_image(self): method test_clipboard_no_image (line 236) | def test_clipboard_no_image(self): method test_powershell_not_found (line 241) | def test_powershell_not_found(self): method test_powershell_error (line 245) | def test_powershell_error(self): class TestWslSave (line 251) | class TestWslSave: method test_successful_extraction (line 252) | def test_successful_extraction(self, tmp_path): method test_no_image_returns_false (line 260) | def test_no_image_returns_false(self, tmp_path): method test_empty_output (line 267) | def test_empty_output(self, tmp_path): method test_powershell_not_found (line 273) | def test_powershell_not_found(self, tmp_path): method test_invalid_base64 (line 278) | def test_invalid_base64(self, tmp_path): method test_timeout (line 284) | def test_timeout(self, tmp_path): class TestWaylandHasImage (line 293) | class TestWaylandHasImage: method test_has_png (line 294) | def test_has_png(self): method test_has_bmp_only (line 301) | def test_has_bmp_only(self): method test_text_only (line 308) | def test_text_only(self): method test_wl_paste_not_installed (line 315) | def test_wl_paste_not_installed(self): class TestWaylandSave (line 320) | class TestWaylandSave: method test_png_extraction (line 321) | def test_png_extraction(self, tmp_path): method test_bmp_extraction_with_pillow_convert (line 336) | def test_bmp_extraction_with_pillow_convert(self, tmp_path): method test_no_image_types (line 350) | def test_no_image_types(self, tmp_path): method test_wl_paste_not_installed (line 358) | def test_wl_paste_not_installed(self, tmp_path): method test_list_types_fails (line 363) | def test_list_types_fails(self, tmp_path): method test_prefers_png_over_bmp (line 369) | def test_prefers_png_over_bmp(self, tmp_path): class TestXclipHasImage (line 391) | class TestXclipHasImage: method test_has_image (line 392) | def test_has_image(self): method test_no_image (line 399) | def test_no_image(self): method test_xclip_not_installed (line 406) | def test_xclip_not_installed(self): class TestXclipSave (line 411) | class TestXclipSave: method test_no_xclip_installed (line 412) | def test_no_xclip_installed(self, tmp_path): method test_no_image_in_clipboard (line 416) | def test_no_image_in_clipboard(self, tmp_path): method test_image_extraction_success (line 421) | def test_image_extraction_success(self, tmp_path): method test_extraction_fails_cleans_up (line 433) | def test_extraction_fails_cleans_up(self, tmp_path): method test_targets_check_timeout (line 443) | def test_targets_check_timeout(self, tmp_path): class TestLinuxSave (line 451) | class TestLinuxSave: method setup_method (line 454) | def setup_method(self): method test_wsl_tried_first (line 458) | def test_wsl_tried_first(self, tmp_path): method test_wsl_fails_falls_through_to_xclip (line 465) | def test_wsl_fails_falls_through_to_xclip(self, tmp_path): method test_wayland_tried_when_display_set (line 474) | def test_wayland_tried_when_display_set(self, tmp_path): method test_wayland_fails_falls_through_to_xclip (line 482) | def test_wayland_fails_falls_through_to_xclip(self, tmp_path): method test_xclip_used_on_plain_x11 (line 491) | def test_xclip_used_on_plain_x11(self, tmp_path): class TestConvertToPng (line 502) | class TestConvertToPng: method test_pillow_conversion (line 503) | def test_pillow_conversion(self, tmp_path): method test_pillow_not_available_tries_imagemagick (line 516) | def test_pillow_not_available_tries_imagemagick(self, tmp_path): method test_file_still_usable_when_no_converter (line 549) | def test_file_still_usable_when_no_converter(self, tmp_path): method test_imagemagick_failure_preserves_original (line 561) | def test_imagemagick_failure_preserves_original(self, tmp_path): method test_imagemagick_not_installed_preserves_original (line 579) | def test_imagemagick_not_installed_preserves_original(self, tmp_path): method test_imagemagick_timeout_preserves_original (line 592) | def test_imagemagick_timeout_preserves_original(self, tmp_path): class TestHasClipboardImage (line 609) | class TestHasClipboardImage: method setup_method (line 610) | def setup_method(self): method test_macos_dispatch (line 614) | def test_macos_dispatch(self): method test_linux_wsl_dispatch (line 621) | def test_linux_wsl_dispatch(self): method test_linux_wayland_dispatch (line 629) | def test_linux_wayland_dispatch(self): method test_linux_x11_dispatch (line 638) | def test_linux_x11_dispatch(self): class TestPreprocessImagesWithVision (line 652) | class TestPreprocessImagesWithVision: method cli (line 656) | def cli(self): method _make_image (line 679) | def _make_image(self, tmp_path, name="test.png", content=FAKE_PNG): method _mock_vision_success (line 684) | def _mock_vision_success(self, description="A test image with colored ... method _mock_vision_failure (line 691) | def _mock_vision_failure(self): method test_single_image_with_text (line 698) | def test_single_image_with_text(self, cli, tmp_path): method test_multiple_images (line 709) | def test_multiple_images(self, cli, tmp_path): method test_empty_text_gets_default_question (line 720) | def test_empty_text_gets_default_question(self, cli, tmp_path): method test_missing_image_skipped (line 727) | def test_missing_image_skipped(self, cli, tmp_path): method test_mix_of_existing_and_missing (line 734) | def test_mix_of_existing_and_missing(self, cli, tmp_path): method test_vision_failure_includes_path (line 743) | def test_vision_failure_includes_path(self, cli, tmp_path): method test_vision_exception_includes_path (line 751) | def test_vision_exception_includes_path(self, cli, tmp_path): class TestTryAttachClipboardImage (line 765) | class TestTryAttachClipboardImage: method cli (line 769) | def cli(self): method test_image_found_attaches (line 776) | def test_image_found_attaches(self, cli): method test_no_image_doesnt_attach (line 783) | def test_no_image_doesnt_attach(self, cli): method test_multiple_attaches_increment_counter (line 790) | def test_multiple_attaches_increment_counter(self, cli): method test_mixed_success_and_failure (line 798) | def test_mixed_success_and_failure(self, cli): method test_image_path_follows_naming_convention (line 807) | def test_image_path_follows_naming_convention(self, cli): class TestQueueRouting (line 820) | class TestQueueRouting: method test_plain_string_stays_string (line 823) | def test_plain_string_stays_string(self): method test_tuple_unpacks_text_and_images (line 832) | def test_tuple_unpacks_text_and_images(self, tmp_path): method test_empty_text_with_images (line 845) | def test_empty_text_with_images(self, tmp_path): method test_command_with_images_not_treated_as_command (line 857) | def test_command_with_images_not_treated_as_command(self): method test_images_only_not_treated_as_command (line 866) | def test_images_only_not_treated_as_command(self, tmp_path): FILE: tests/tools/test_code_execution.py function _mock_handle_function_call (line 38) | def _mock_handle_function_call(function_name, function_args, task_id=Non... class TestSandboxRequirements (line 58) | class TestSandboxRequirements(unittest.TestCase): method test_available_on_posix (line 59) | def test_available_on_posix(self): method test_schema_is_valid (line 63) | def test_schema_is_valid(self): class TestHermesToolsGeneration (line 69) | class TestHermesToolsGeneration(unittest.TestCase): method test_generates_all_allowed_tools (line 70) | def test_generates_all_allowed_tools(self): method test_generates_subset (line 75) | def test_generates_subset(self): method test_empty_list_generates_nothing (line 81) | def test_empty_list_generates_nothing(self): method test_non_allowed_tools_ignored (line 86) | def test_non_allowed_tools_ignored(self): method test_rpc_infrastructure_present (line 91) | def test_rpc_infrastructure_present(self): method test_convenience_helpers_present (line 98) | def test_convenience_helpers_present(self): class TestExecuteCode (line 108) | class TestExecuteCode(unittest.TestCase): method _run (line 111) | def _run(self, code, enabled_tools=None): method test_basic_print (line 125) | def test_basic_print(self): method test_repo_root_modules_are_importable (line 132) | def test_repo_root_modules_are_importable(self): method test_single_tool_call (line 138) | def test_single_tool_call(self): method test_multi_tool_chain (line 150) | def test_multi_tool_chain(self): method test_syntax_error (line 163) | def test_syntax_error(self): method test_runtime_exception (line 169) | def test_runtime_exception(self): method test_excluded_tool_returns_error (line 174) | def test_excluded_tool_returns_error(self): method test_empty_code (line 186) | def test_empty_code(self): method test_output_captured (line 191) | def test_output_captured(self): method test_stderr_on_error (line 202) | def test_stderr_on_error(self): method test_timeout_enforcement (line 214) | def test_timeout_enforcement(self): method test_web_search_tool (line 228) | def test_web_search_tool(self): method test_json_parse_helper (line 239) | def test_json_parse_helper(self): method test_shell_quote_helper (line 252) | def test_shell_quote_helper(self): method test_retry_helper_success (line 267) | def test_retry_helper_success(self): method test_retry_helper_eventual_success (line 282) | def test_retry_helper_eventual_success(self): method test_retry_helper_all_fail (line 299) | def test_retry_helper_all_fail(self): class TestStubSchemaDrift (line 316) | class TestStubSchemaDrift(unittest.TestCase): method test_stubs_cover_all_schema_params (line 330) | def test_stubs_cover_all_schema_params(self): method test_stubs_pass_all_params_to_rpc (line 365) | def test_stubs_pass_all_params_to_rpc(self): method test_search_files_target_uses_current_values (line 382) | def test_search_files_target_uses_current_values(self): method test_generated_module_accepts_all_params (line 393) | def test_generated_module_accepts_all_params(self): class TestBuildExecuteCodeSchema (line 415) | class TestBuildExecuteCodeSchema(unittest.TestCase): method test_default_includes_all_tools (line 418) | def test_default_includes_all_tools(self): method test_schema_structure (line 424) | def test_schema_structure(self): method test_subset_only_lists_enabled_tools (line 431) | def test_subset_only_lists_enabled_tools(self): method test_single_tool (line 441) | def test_single_tool(self): method test_import_examples_prefer_web_search_and_terminal (line 447) | def test_import_examples_prefer_web_search_and_terminal(self): method test_import_examples_fallback_when_no_preferred (line 454) | def test_import_examples_fallback_when_no_preferred(self): method test_empty_set_produces_valid_description (line 464) | def test_empty_set_produces_valid_description(self): method test_real_scenario_all_sandbox_tools_disabled (line 472) | def test_real_scenario_all_sandbox_tools_disabled(self): method test_real_scenario_only_vision_enabled (line 499) | def test_real_scenario_only_vision_enabled(self): method test_description_mentions_limits (line 514) | def test_description_mentions_limits(self): method test_description_mentions_helpers (line 521) | def test_description_mentions_helpers(self): method test_none_defaults_to_all_tools (line 528) | def test_none_defaults_to_all_tools(self): class TestEnvVarFiltering (line 539) | class TestEnvVarFiltering(unittest.TestCase): method _get_child_env (line 546) | def _get_child_env(self, extra_env=None): method test_api_keys_excluded (line 569) | def test_api_keys_excluded(self): method test_tokens_excluded (line 579) | def test_tokens_excluded(self): method test_password_vars_excluded (line 589) | def test_password_vars_excluded(self): method test_path_included (line 599) | def test_path_included(self): method test_home_included (line 603) | def test_home_included(self): method test_hermes_rpc_socket_injected (line 607) | def test_hermes_rpc_socket_injected(self): method test_pythondontwritebytecode_set (line 611) | def test_pythondontwritebytecode_set(self): method test_timezone_injected_when_set (line 615) | def test_timezone_injected_when_set(self): method test_timezone_not_set_when_empty (line 625) | def test_timezone_not_set_when_empty(self): class TestExecuteCodeEdgeCases (line 641) | class TestExecuteCodeEdgeCases(unittest.TestCase): method test_windows_returns_error (line 643) | def test_windows_returns_error(self): method test_whitespace_only_code (line 650) | def test_whitespace_only_code(self): method test_none_enabled_tools_uses_all (line 656) | def test_none_enabled_tools_uses_all(self): method test_empty_enabled_tools_uses_all (line 670) | def test_empty_enabled_tools_uses_all(self): method test_nonoverlapping_tools_fallback (line 684) | def test_nonoverlapping_tools_fallback(self): class TestLoadConfig (line 705) | class TestLoadConfig(unittest.TestCase): method test_returns_empty_dict_when_cli_config_unavailable (line 706) | def test_returns_empty_dict_when_cli_config_unavailable(self): method test_returns_code_execution_section (line 712) | def test_returns_code_execution_section(self): class TestInterruptHandling (line 726) | class TestInterruptHandling(unittest.TestCase): method test_interrupt_event_stops_execution (line 727) | def test_interrupt_event_stops_execution(self): class TestHeadTailTruncation (line 757) | class TestHeadTailTruncation(unittest.TestCase): method _run (line 760) | def _run(self, code): method test_short_output_not_truncated (line 769) | def test_short_output_not_truncated(self): method test_large_output_preserves_head_and_tail (line 776) | def test_large_output_preserves_head_and_tail(self): method test_truncation_notice_format (line 795) | def test_truncation_notice_format(self): FILE: tests/tools/test_command_guards.py function _tirith_result (line 24) | def _tirith_result(action="allow", findings=None, summary=""): function _clean_state (line 35) | def _clean_state(): class TestContainerSkip (line 57) | class TestContainerSkip: method test_docker_skips_both (line 58) | def test_docker_skips_both(self): method test_singularity_skips_both (line 62) | def test_singularity_skips_both(self): method test_modal_skips_both (line 66) | def test_modal_skips_both(self): method test_daytona_skips_both (line 70) | def test_daytona_skips_both(self): class TestTirithAllowSafeCommand (line 79) | class TestTirithAllowSafeCommand: method test_both_allow (line 81) | def test_both_allow(self, mock_tirith): method test_noninteractive_skips_external_scan (line 87) | def test_noninteractive_skips_external_scan(self, mock_tirith): class TestTirithBlock (line 97) | class TestTirithBlock: method test_tirith_block_safe_command (line 100) | def test_tirith_block_safe_command(self, mock_tirith): method test_tirith_block_plus_dangerous (line 109) | def test_tirith_block_plus_dangerous(self, mock_tirith): class TestTirithAllowDangerous (line 121) | class TestTirithAllowDangerous: method test_dangerous_only_gateway (line 123) | def test_dangerous_only_gateway(self, mock_tirith): method test_dangerous_only_cli_deny (line 131) | def test_dangerous_only_cli_deny(self, mock_tirith): class TestTirithWarnSafe (line 145) | class TestTirithWarnSafe: method test_warn_cli_prompts_user (line 150) | def test_warn_cli_prompts_user(self, mock_tirith): method test_warn_session_approved (line 164) | def test_warn_session_approved(self, mock_tirith): method test_warn_non_interactive_auto_allow (line 175) | def test_warn_non_interactive_auto_allow(self, mock_tirith): class TestCombinedWarnings (line 185) | class TestCombinedWarnings: method test_combined_gateway (line 190) | def test_combined_gateway(self, mock_tirith): method test_combined_cli_deny (line 205) | def test_combined_cli_deny(self, mock_tirith): method test_combined_cli_session_approves_both (line 219) | def test_combined_cli_session_approves_both(self, mock_tirith): class TestAlwaysVisibility (line 233) | class TestAlwaysVisibility: method test_dangerous_only_allows_permanent (line 235) | def test_dangerous_only_allows_permanent(self, mock_tirith): class TestTirithImportError (line 249) | class TestTirithImportError: method test_import_error_allows (line 250) | def test_import_error_allows(self): class TestWarnEmptyFindings (line 270) | class TestWarnEmptyFindings: method test_warn_empty_findings_cli_prompts (line 273) | def test_warn_empty_findings_cli_prompts(self, mock_tirith): method test_warn_empty_findings_gateway (line 285) | def test_warn_empty_findings_gateway(self, mock_tirith): class TestGatewayPatternKeys (line 296) | class TestGatewayPatternKeys: method test_gateway_stores_pattern_keys (line 301) | def test_gateway_stores_pattern_keys(self, mock_tirith): class TestProgrammingErrorsPropagateFromWrapper (line 319) | class TestProgrammingErrorsPropagateFromWrapper: method test_attribute_error_propagates (line 321) | def test_attribute_error_propagates(self, mock_tirith): FILE: tests/tools/test_cron_prompt_injection.py class TestMultiWordInjectionBypass (line 13) | class TestMultiWordInjectionBypass: method test_ignore_all_prior_instructions (line 16) | def test_ignore_all_prior_instructions(self): method test_ignore_all_previous_instructions (line 19) | def test_ignore_all_previous_instructions(self): method test_ignore_every_prior_instructions (line 22) | def test_ignore_every_prior_instructions(self): method test_ignore_your_all_instructions (line 27) | def test_ignore_your_all_instructions(self): method test_ignore_the_above_instructions (line 30) | def test_ignore_the_above_instructions(self): method test_case_insensitive (line 33) | def test_case_insensitive(self): method test_single_word_still_works (line 36) | def test_single_word_still_works(self): method test_clean_prompts_not_blocked (line 43) | def test_clean_prompts_not_blocked(self): FILE: tests/tools/test_cronjob_tools.py class TestScanCronPrompt (line 21) | class TestScanCronPrompt: method test_clean_prompt_passes (line 22) | def test_clean_prompt_passes(self): method test_prompt_injection_blocked (line 26) | def test_prompt_injection_blocked(self): method test_disregard_rules_blocked (line 31) | def test_disregard_rules_blocked(self): method test_system_override_blocked (line 34) | def test_system_override_blocked(self): method test_exfiltration_curl_blocked (line 37) | def test_exfiltration_curl_blocked(self): method test_exfiltration_wget_blocked (line 40) | def test_exfiltration_wget_blocked(self): method test_read_secrets_blocked (line 43) | def test_read_secrets_blocked(self): method test_ssh_backdoor_blocked (line 47) | def test_ssh_backdoor_blocked(self): method test_sudoers_blocked (line 50) | def test_sudoers_blocked(self): method test_destructive_rm_blocked (line 53) | def test_destructive_rm_blocked(self): method test_invisible_unicode_blocked (line 56) | def test_invisible_unicode_blocked(self): method test_deception_blocked (line 60) | def test_deception_blocked(self): class TestCronjobRequirements (line 64) | class TestCronjobRequirements: method test_requires_no_crontab_binary (line 65) | def test_requires_no_crontab_binary(self, monkeypatch): method test_accepts_interactive_mode (line 74) | def test_accepts_interactive_mode(self, monkeypatch): method test_accepts_gateway_session (line 81) | def test_accepts_gateway_session(self, monkeypatch): method test_accepts_exec_ask (line 88) | def test_accepts_exec_ask(self, monkeypatch): method test_rejects_when_no_session_env (line 95) | def test_rejects_when_no_session_env(self, monkeypatch): class TestScheduleCronjob (line 108) | class TestScheduleCronjob: method _setup_cron_dir (line 110) | def _setup_cron_dir(self, tmp_path, monkeypatch): method test_schedule_success (line 115) | def test_schedule_success(self): method test_injection_blocked (line 125) | def test_injection_blocked(self): method test_invalid_schedule (line 133) | def test_invalid_schedule(self): method test_repeat_display_once (line 140) | def test_repeat_display_once(self): method test_repeat_display_forever (line 147) | def test_repeat_display_forever(self): method test_repeat_display_n_times (line 154) | def test_repeat_display_n_times(self): method test_schedule_persists_runtime_overrides (line 162) | def test_schedule_persists_runtime_overrides(self): method test_thread_id_captured_in_origin (line 178) | def test_thread_id_captured_in_origin(self, monkeypatch): method test_thread_id_absent_when_not_set (line 193) | def test_thread_id_absent_when_not_set(self, monkeypatch): class TestListCronjobs (line 213) | class TestListCronjobs: method _setup_cron_dir (line 215) | def _setup_cron_dir(self, tmp_path, monkeypatch): method test_empty_list (line 220) | def test_empty_list(self): method test_lists_created_jobs (line 226) | def test_lists_created_jobs(self): method test_job_fields_present (line 235) | def test_job_fields_present(self): class TestRemoveCronjob (line 250) | class TestRemoveCronjob: method _setup_cron_dir (line 252) | def _setup_cron_dir(self, tmp_path, monkeypatch): method test_remove_existing (line 257) | def test_remove_existing(self): method test_remove_nonexistent (line 267) | def test_remove_nonexistent(self): class TestUnifiedCronjobTool (line 273) | class TestUnifiedCronjobTool: method _setup_cron_dir (line 275) | def _setup_cron_dir(self, tmp_path, monkeypatch): method test_create_and_list (line 280) | def test_create_and_list(self): method test_pause_and_resume (line 297) | def test_pause_and_resume(self): method test_update_schedule_recomputes_display (line 309) | def test_update_schedule_recomputes_display(self): method test_update_runtime_overrides_can_set_and_clear (line 320) | def test_update_runtime_overrides_can_set_and_clear(self): method test_create_skill_backed_job (line 347) | def test_create_skill_backed_job(self): method test_create_multi_skill_job (line 363) | def test_create_multi_skill_job(self): method test_multi_skill_default_name_prefers_prompt_when_present (line 379) | def test_multi_skill_default_name_prefers_prompt_when_present(self): method test_update_can_clear_skills (line 391) | def test_update_can_clear_skills(self): FILE: tests/tools/test_daytona_environment.py function _make_exec_response (line 14) | def _make_exec_response(result="", exit_code=0): function _make_sandbox (line 18) | def _make_sandbox(sandbox_id="sb-123", state="started"): function _patch_daytona_imports (line 26) | def _patch_daytona_imports(monkeypatch): function daytona_sdk (line 54) | def daytona_sdk(monkeypatch): function make_env (line 60) | def make_env(daytona_sdk, monkeypatch): class TestCwdResolution (line 112) | class TestCwdResolution: method test_default_cwd_resolves_home (line 113) | def test_default_cwd_resolves_home(self, make_env): method test_tilde_cwd_resolves_home (line 117) | def test_tilde_cwd_resolves_home(self, make_env): method test_explicit_cwd_not_overridden (line 121) | def test_explicit_cwd_not_overridden(self, make_env): method test_home_detection_failure_keeps_default_cwd (line 125) | def test_home_detection_failure_keeps_default_cwd(self, make_env): method test_empty_home_keeps_default_cwd (line 131) | def test_empty_home_keeps_default_cwd(self, make_env): class TestPersistence (line 140) | class TestPersistence: method test_persistent_resumes_via_get (line 141) | def test_persistent_resumes_via_get(self, make_env): method test_persistent_resumes_legacy_via_list (line 150) | def test_persistent_resumes_legacy_via_list(self, make_env, daytona_sdk): method test_persistent_creates_new_when_none_found (line 164) | def test_persistent_creates_new_when_none_found(self, make_env, dayton... method test_non_persistent_skips_lookup (line 177) | def test_non_persistent_skips_lookup(self, make_env): class TestCleanup (line 188) | class TestCleanup: method test_persistent_cleanup_stops_sandbox (line 189) | def test_persistent_cleanup_stops_sandbox(self, make_env): method test_non_persistent_cleanup_deletes_sandbox (line 195) | def test_non_persistent_cleanup_deletes_sandbox(self, make_env): method test_cleanup_idempotent (line 201) | def test_cleanup_idempotent(self, make_env): method test_cleanup_swallows_errors (line 206) | def test_cleanup_swallows_errors(self, make_env): class TestExecute (line 217) | class TestExecute: method test_basic_command (line 218) | def test_basic_command(self, make_env): method test_command_wrapped_with_shell_timeout (line 232) | def test_command_wrapped_with_shell_timeout(self, make_env): method test_timeout_returns_exit_code_124 (line 249) | def test_timeout_returns_exit_code_124(self, make_env): method test_nonzero_exit_code (line 262) | def test_nonzero_exit_code(self, make_env): method test_stdin_data_wraps_heredoc (line 274) | def test_stdin_data_wraps_heredoc(self, make_env): method test_custom_cwd_passed_through (line 292) | def test_custom_cwd_passed_through(self, make_env): method test_daytona_error_triggers_retry (line 305) | def test_daytona_error_triggers_retry(self, make_env, daytona_sdk): class TestResourceConversion (line 324) | class TestResourceConversion: method _get_resources_kwargs (line 325) | def _get_resources_kwargs(self, daytona_sdk): method test_memory_converted_to_gib (line 328) | def test_memory_converted_to_gib(self, make_env, daytona_sdk): method test_disk_converted_to_gib (line 332) | def test_disk_converted_to_gib(self, make_env, daytona_sdk): method test_small_values_clamped_to_1 (line 336) | def test_small_values_clamped_to_1(self, make_env, daytona_sdk): class TestInterrupt (line 347) | class TestInterrupt: method test_interrupt_stops_sandbox_and_returns_130 (line 348) | def test_interrupt_stops_sandbox_and_returns_130(self, make_env, monke... class TestRetryExhausted (line 379) | class TestRetryExhausted: method test_both_attempts_fail (line 380) | def test_both_attempts_fail(self, make_env, daytona_sdk): class TestEnsureSandboxReady (line 399) | class TestEnsureSandboxReady: method test_restarts_stopped_sandbox (line 400) | def test_restarts_stopped_sandbox(self, make_env): method test_no_restart_when_running (line 406) | def test_no_restart_when_running(self, make_env): FILE: tests/tools/test_debug_helpers.py class TestDebugSessionDisabled (line 10) | class TestDebugSessionDisabled: method test_not_active_by_default (line 13) | def test_not_active_by_default(self): method test_session_id_empty_when_disabled (line 18) | def test_session_id_empty_when_disabled(self): method test_log_call_noop (line 22) | def test_log_call_noop(self): method test_save_noop (line 27) | def test_save_noop(self, tmp_path): method test_get_session_info_disabled (line 35) | def test_get_session_info_disabled(self): class TestDebugSessionEnabled (line 44) | class TestDebugSessionEnabled: method _make_enabled (line 47) | def _make_enabled(self, tmp_path): method test_active_when_env_set (line 53) | def test_active_when_env_set(self, tmp_path): method test_session_id_generated (line 58) | def test_session_id_generated(self, tmp_path): method test_log_call_appends (line 62) | def test_log_call_appends(self, tmp_path): method test_save_creates_json_file (line 71) | def test_save_creates_json_file(self, tmp_path): method test_get_session_info_enabled (line 86) | def test_get_session_info_enabled(self, tmp_path): method test_env_var_case_insensitive (line 96) | def test_env_var_case_insensitive(self, tmp_path): method test_env_var_false_disables (line 105) | def test_env_var_false_disables(self): method test_save_empty_log (line 110) | def test_save_empty_log(self, tmp_path): FILE: tests/tools/test_delegate.py function _make_mock_parent (line 33) | def _make_mock_parent(depth=0): class TestDelegateRequirements (line 53) | class TestDelegateRequirements(unittest.TestCase): method test_always_available (line 54) | def test_always_available(self): method test_schema_valid (line 57) | def test_schema_valid(self): class TestChildSystemPrompt (line 68) | class TestChildSystemPrompt(unittest.TestCase): method test_goal_only (line 69) | def test_goal_only(self): method test_goal_with_context (line 75) | def test_goal_with_context(self): method test_empty_context_ignored (line 81) | def test_empty_context_ignored(self): class TestStripBlockedTools (line 86) | class TestStripBlockedTools(unittest.TestCase): method test_removes_blocked_toolsets (line 87) | def test_removes_blocked_toolsets(self): method test_preserves_allowed_toolsets (line 91) | def test_preserves_allowed_toolsets(self): method test_empty_input (line 95) | def test_empty_input(self): class TestDelegateTask (line 100) | class TestDelegateTask(unittest.TestCase): method test_no_parent_agent (line 101) | def test_no_parent_agent(self): method test_depth_limit (line 106) | def test_depth_limit(self): method test_no_goal_or_tasks (line 112) | def test_no_goal_or_tasks(self): method test_empty_goal (line 117) | def test_empty_goal(self): method test_task_missing_goal (line 122) | def test_task_missing_goal(self): method test_single_task_mode (line 128) | def test_single_task_mode(self, mock_run): method test_batch_mode (line 142) | def test_batch_mode(self, mock_run): method test_batch_capped_at_3 (line 160) | def test_batch_capped_at_3(self, mock_run): method test_batch_ignores_toplevel_goal (line 172) | def test_batch_ignores_toplevel_goal(self, mock_run): method test_failed_child_included_in_results (line 189) | def test_failed_child_included_in_results(self, mock_run): method test_depth_increments (line 200) | def test_depth_increments(self): method test_active_children_tracking (line 214) | def test_active_children_tracking(self): method test_child_inherits_runtime_credentials (line 228) | def test_child_inherits_runtime_credentials(self): class TestToolNamePreservation (line 253) | class TestToolNamePreservation(unittest.TestCase): method test_global_tool_names_restored_after_delegation (line 256) | def test_global_tool_names_restored_after_delegation(self): method test_global_tool_names_restored_after_child_failure (line 277) | def test_global_tool_names_restored_after_child_failure(self): method test_build_child_agent_does_not_raise_name_error (line 295) | def test_build_child_agent_does_not_raise_name_error(self): method test_saved_tool_names_set_on_child_before_run (line 322) | def test_saved_tool_names_set_on_child_before_run(self): class TestDelegateObservability (line 348) | class TestDelegateObservability(unittest.TestCase): method test_observability_fields_present (line 351) | def test_observability_fields_present(self): method test_tool_trace_detects_error (line 392) | def test_tool_trace_detects_error(self): method test_parallel_tool_calls_paired_correctly (line 419) | def test_parallel_tool_calls_paired_correctly(self): method test_exit_reason_interrupted (line 468) | def test_exit_reason_interrupted(self): method test_exit_reason_max_iterations (line 489) | def test_exit_reason_max_iterations(self): class TestBlockedTools (line 511) | class TestBlockedTools(unittest.TestCase): method test_blocked_tools_constant (line 512) | def test_blocked_tools_constant(self): method test_constants (line 516) | def test_constants(self): class TestDelegationCredentialResolution (line 521) | class TestDelegationCredentialResolution(unittest.TestCase): method test_no_provider_returns_none_credentials (line 524) | def test_no_provider_returns_none_credentials(self): method test_model_only_no_provider (line 535) | def test_model_only_no_provider(self): method test_provider_resolves_full_credentials (line 546) | def test_provider_resolves_full_credentials(self, mock_resolve): method test_direct_endpoint_uses_configured_base_url_and_api_key (line 564) | def test_direct_endpoint_uses_configured_base_url_and_api_key(self): method test_direct_endpoint_falls_back_to_openai_api_key_env (line 579) | def test_direct_endpoint_falls_back_to_openai_api_key_env(self): method test_direct_endpoint_does_not_fall_back_to_openrouter_api_key_env (line 590) | def test_direct_endpoint_does_not_fall_back_to_openrouter_api_key_env(... method test_nous_provider_resolves_nous_credentials (line 602) | def test_nous_provider_resolves_nous_credentials(self, mock_resolve): method test_provider_resolution_failure_raises_valueerror (line 619) | def test_provider_resolution_failure_raises_valueerror(self, mock_reso... method test_provider_resolves_but_no_api_key_raises (line 630) | def test_provider_resolves_but_no_api_key_raises(self, mock_resolve): method test_missing_config_keys_inherit_parent (line 644) | def test_missing_config_keys_inherit_parent(self): class TestDelegationProviderIntegration (line 653) | class TestDelegationProviderIntegration(unittest.TestCase): method test_config_provider_credentials_reach_child_agent (line 658) | def test_config_provider_credentials_reach_child_agent(self, mock_cred... method test_cross_provider_delegation (line 692) | def test_cross_provider_delegation(self, mock_creds, mock_cfg): method test_direct_endpoint_credentials_reach_child_agent (line 730) | def test_direct_endpoint_credentials_reach_child_agent(self, mock_cred... method test_empty_config_inherits_parent (line 764) | def test_empty_config_inherits_parent(self, mock_creds, mock_cfg): method test_credential_error_returns_json_error (line 792) | def test_credential_error_returns_json_error(self, mock_creds, mock_cfg): method test_batch_mode_all_children_get_credentials (line 807) | def test_batch_mode_all_children_get_credentials(self, mock_creds, moc... method test_model_only_no_provider_inherits_parent_credentials (line 847) | def test_model_only_no_provider_inherits_parent_credentials(self, mock... FILE: tests/tools/test_docker_environment.py function _install_fake_minisweagent (line 12) | def _install_fake_minisweagent(monkeypatch, captured_run_args): function _make_dummy_env (line 33) | def _make_dummy_env(**kwargs): function test_ensure_docker_available_logs_and_raises_when_not_found (line 51) | def test_ensure_docker_available_logs_and_raises_when_not_found(monkeypa... function test_ensure_docker_available_logs_and_raises_on_timeout (line 73) | def test_ensure_docker_available_logs_and_raises_on_timeout(monkeypatch,... function test_ensure_docker_available_uses_resolved_executable (line 93) | def test_ensure_docker_available_uses_resolved_executable(monkeypatch): function test_auto_mount_host_cwd_adds_volume (line 116) | def test_auto_mount_host_cwd_adds_volume(monkeypatch, tmp_path): function test_auto_mount_disabled_by_default (line 140) | def test_auto_mount_disabled_by_default(monkeypatch, tmp_path): function test_auto_mount_skipped_when_workspace_already_mounted (line 164) | def test_auto_mount_skipped_when_workspace_already_mounted(monkeypatch, ... function test_auto_mount_replaces_persistent_workspace_bind (line 192) | def test_auto_mount_replaces_persistent_workspace_bind(monkeypatch, tmp_... function test_non_persistent_cleanup_removes_container (line 219) | def test_non_persistent_cleanup_removes_container(monkeypatch): class _FakePopen (line 247) | class _FakePopen: method __init__ (line 248) | def __init__(self, cmd, **kwargs): method poll (line 255) | def poll(self): function _make_execute_only_env (line 259) | def _make_execute_only_env(forward_env=None): function test_execute_uses_hermes_dotenv_for_allowlisted_env (line 273) | def test_execute_uses_hermes_dotenv_for_allowlisted_env(monkeypatch): function test_execute_prefers_shell_env_over_hermes_dotenv (line 291) | def test_execute_prefers_shell_env_over_hermes_dotenv(monkeypatch): function test_non_persistent_cleanup_removes_container (line 309) | def test_non_persistent_cleanup_removes_container(monkeypatch): FILE: tests/tools/test_docker_find.py function _reset_cache (line 12) | def _reset_cache(): class TestFindDocker (line 19) | class TestFindDocker: method test_found_via_shutil_which (line 20) | def test_found_via_shutil_which(self): method test_not_in_path_falls_back_to_known_locations (line 25) | def test_not_in_path_falls_back_to_known_locations(self, tmp_path): method test_returns_none_when_not_found (line 36) | def test_returns_none_when_not_found(self): method test_caches_result (line 42) | def test_caches_result(self): FILE: tests/tools/test_file_operations.py class TestIsWriteDenied (line 29) | class TestIsWriteDenied: method test_ssh_authorized_keys_denied (line 30) | def test_ssh_authorized_keys_denied(self): method test_ssh_id_rsa_denied (line 34) | def test_ssh_id_rsa_denied(self): method test_netrc_denied (line 38) | def test_netrc_denied(self): method test_aws_prefix_denied (line 42) | def test_aws_prefix_denied(self): method test_kube_prefix_denied (line 46) | def test_kube_prefix_denied(self): method test_normal_file_allowed (line 50) | def test_normal_file_allowed(self, tmp_path): method test_project_file_allowed (line 54) | def test_project_file_allowed(self): method test_tilde_expansion (line 57) | def test_tilde_expansion(self): class TestReadResult (line 66) | class TestReadResult: method test_to_dict_omits_defaults (line 67) | def test_to_dict_omits_defaults(self): method test_to_dict_preserves_empty_content (line 73) | def test_to_dict_preserves_empty_content(self): method test_to_dict_includes_values (line 82) | def test_to_dict_includes_values(self): method test_binary_fields (line 89) | def test_binary_fields(self): class TestWriteResult (line 97) | class TestWriteResult: method test_to_dict_omits_none (line 98) | def test_to_dict_omits_none(self): method test_to_dict_includes_error (line 105) | def test_to_dict_includes_error(self): class TestPatchResult (line 111) | class TestPatchResult: method test_to_dict_success (line 112) | def test_to_dict_success(self): method test_to_dict_error (line 119) | def test_to_dict_error(self): class TestSearchResult (line 126) | class TestSearchResult: method test_to_dict_with_matches (line 127) | def test_to_dict_with_matches(self): method test_to_dict_empty (line 135) | def test_to_dict_empty(self): method test_to_dict_files_mode (line 141) | def test_to_dict_files_mode(self): method test_to_dict_count_mode (line 146) | def test_to_dict_count_mode(self): method test_truncated_flag (line 151) | def test_truncated_flag(self): class TestLintResult (line 157) | class TestLintResult: method test_skipped (line 158) | def test_skipped(self): method test_success (line 164) | def test_success(self): method test_error (line 169) | def test_error(self): function mock_env (line 181) | def mock_env(): function file_ops (line 190) | def file_ops(mock_env): class TestShellFileOpsHelpers (line 194) | class TestShellFileOpsHelpers: method test_escape_shell_arg_simple (line 195) | def test_escape_shell_arg_simple(self, file_ops): method test_escape_shell_arg_with_quotes (line 198) | def test_escape_shell_arg_with_quotes(self, file_ops): method test_is_likely_binary_by_extension (line 204) | def test_is_likely_binary_by_extension(self, file_ops): method test_is_likely_binary_by_content (line 210) | def test_is_likely_binary_by_content(self, file_ops): method test_is_image (line 218) | def test_is_image(self, file_ops): method test_add_line_numbers (line 225) | def test_add_line_numbers(self, file_ops): method test_add_line_numbers_with_offset (line 232) | def test_add_line_numbers_with_offset(self, file_ops): method test_add_line_numbers_truncates_long_lines (line 238) | def test_add_line_numbers_truncates_long_lines(self, file_ops): method test_unified_diff (line 243) | def test_unified_diff(self, file_ops): method test_cwd_from_env (line 251) | def test_cwd_from_env(self, mock_env): method test_cwd_fallback_to_slash (line 256) | def test_cwd_fallback_to_slash(self): class TestSearchPathValidation (line 262) | class TestSearchPathValidation: method test_search_nonexistent_path_returns_error (line 265) | def test_search_nonexistent_path_returns_error(self, mock_env): method test_search_nonexistent_path_files_mode (line 279) | def test_search_nonexistent_path_files_mode(self, mock_env): method test_search_existing_path_proceeds (line 293) | def test_search_existing_path_proceeds(self, mock_env): method test_search_rg_error_exit_code (line 308) | def test_search_rg_error_exit_code(self, mock_env): class TestShellFileOpsWriteDenied (line 326) | class TestShellFileOpsWriteDenied: method test_write_file_denied_path (line 327) | def test_write_file_denied_path(self, file_ops): method test_patch_replace_denied_path (line 332) | def test_patch_replace_denied_path(self, file_ops): FILE: tests/tools/test_file_tools.py class TestFileToolsList (line 20) | class TestFileToolsList: method test_has_expected_entries (line 21) | def test_has_expected_entries(self): method test_each_entry_has_callable_function (line 25) | def test_each_entry_has_callable_function(self): method test_schemas_have_required_fields (line 29) | def test_schemas_have_required_fields(self): class TestReadFileHandler (line 37) | class TestReadFileHandler: method test_returns_file_content (line 39) | def test_returns_file_content(self, mock_get): method test_custom_offset_and_limit (line 54) | def test_custom_offset_and_limit(self, mock_get): method test_exception_returns_error_json (line 67) | def test_exception_returns_error_json(self, mock_get): class TestWriteFileHandler (line 76) | class TestWriteFileHandler: method test_writes_content (line 78) | def test_writes_content(self, mock_get): method test_permission_error_returns_error_json_without_error_log (line 91) | def test_permission_error_returns_error_json_without_error_log(self, m... method test_unexpected_exception_still_logs_error (line 103) | def test_unexpected_exception_still_logs_error(self, mock_get, caplog): class TestPatchHandler (line 113) | class TestPatchHandler: method test_replace_mode_calls_patch_replace (line 115) | def test_replace_mode_calls_patch_replace(self, mock_get): method test_replace_mode_replace_all_flag (line 131) | def test_replace_mode_replace_all_flag(self, mock_get): method test_replace_mode_missing_path_errors (line 144) | def test_replace_mode_missing_path_errors(self, mock_get): method test_replace_mode_missing_strings_errors (line 150) | def test_replace_mode_missing_strings_errors(self, mock_get): method test_patch_mode_calls_patch_v4a (line 156) | def test_patch_mode_calls_patch_v4a(self, mock_get): method test_patch_mode_missing_content_errors (line 169) | def test_patch_mode_missing_content_errors(self, mock_get): method test_unknown_mode_errors (line 175) | def test_unknown_mode_errors(self, mock_get): class TestSearchHandler (line 182) | class TestSearchHandler: method test_search_calls_file_ops (line 184) | def test_search_calls_file_ops(self, mock_get): method test_search_passes_all_params (line 197) | def test_search_passes_all_params(self, mock_get): method test_search_exception_returns_error (line 213) | def test_search_exception_returns_error(self, mock_get): class TestPatchHints (line 225) | class TestPatchHints: method test_no_match_includes_hint (line 229) | def test_no_match_includes_hint(self, mock_get): method test_success_no_hint (line 244) | def test_success_no_hint(self, mock_get): class TestSearchHints (line 256) | class TestSearchHints: method setup_method (line 259) | def setup_method(self): method test_truncated_results_hint (line 265) | def test_truncated_results_hint(self, mock_get): method test_non_truncated_no_hint (line 282) | def test_non_truncated_no_hint(self, mock_get): method test_truncated_hint_with_nonzero_offset (line 297) | def test_truncated_hint_with_nonzero_offset(self, mock_get): FILE: tests/tools/test_file_tools_live.py function _assert_clean (line 46) | def _assert_clean(text: str, context: str = "output"): function env (line 70) | def env(tmp_path): function ops (line 76) | def ops(env, tmp_path): function populated_dir (line 82) | def populated_dir(tmp_path): class TestCleanShellNoise (line 93) | class TestCleanShellNoise: method test_single_noise_line (line 94) | def test_single_noise_line(self): method test_double_noise_lines (line 99) | def test_double_noise_lines(self): method test_tcsetattr_noise (line 109) | def test_tcsetattr_noise(self): method test_triple_noise_lines (line 118) | def test_triple_noise_lines(self): method test_no_noise_untouched (line 128) | def test_no_noise_untouched(self): method test_empty_string (line 131) | def test_empty_string(self): method test_only_noise_produces_empty (line 134) | def test_only_noise_produces_empty(self): method test_noise_in_middle_not_stripped (line 139) | def test_noise_in_middle_not_stripped(self): method test_zsh_restored_session (line 145) | def test_zsh_restored_session(self): method test_zsh_saving_session_trailing (line 150) | def test_zsh_saving_session_trailing(self): method test_zsh_oh_my_zsh_banner (line 155) | def test_zsh_oh_my_zsh_banner(self): method test_zsh_full_noise_sandwich (line 160) | def test_zsh_full_noise_sandwich(self): method test_last_login_stripped (line 172) | def test_last_login_stripped(self): class TestExtractFencedOutput (line 180) | class TestExtractFencedOutput: method test_normal_fenced_output (line 181) | def test_normal_fenced_output(self): method test_no_trailing_newline (line 185) | def test_no_trailing_newline(self): method test_no_fences_falls_back (line 190) | def test_no_fences_falls_back(self): method test_only_start_fence (line 196) | def test_only_start_fence(self): method test_user_outputs_fence_string (line 202) | def test_user_outputs_fence_string(self): method test_empty_command_output (line 210) | def test_empty_command_output(self): method test_multiline_output (line 214) | def test_multiline_output(self): class TestLocalEnvironmentExecute (line 221) | class TestLocalEnvironmentExecute: method test_echo_exact_output (line 222) | def test_echo_exact_output(self, env): method test_printf_no_trailing_newline (line 228) | def test_printf_no_trailing_newline(self, env): method test_exit_code_propagated (line 234) | def test_exit_code_propagated(self, env): method test_stderr_captured_in_output (line 238) | def test_stderr_captured_in_output(self, env): method test_cwd_respected (line 243) | def test_cwd_respected(self, env, tmp_path): method test_multiline_exact (line 251) | def test_multiline_exact(self, env): method test_env_var_home (line 257) | def test_env_var_home(self, env): method test_pipe_exact (line 264) | def test_pipe_exact(self, env): method test_cat_deterministic_content (line 270) | def test_cat_deterministic_content(self, env, tmp_path): class TestHasCommand (line 281) | class TestHasCommand: method test_finds_echo (line 282) | def test_finds_echo(self, ops): method test_finds_cat (line 285) | def test_finds_cat(self, ops): method test_finds_sed (line 288) | def test_finds_sed(self, ops): method test_finds_wc (line 291) | def test_finds_wc(self, ops): method test_finds_find (line 294) | def test_finds_find(self, ops): method test_missing_command (line 297) | def test_missing_command(self, ops): method test_rg_or_grep_available (line 300) | def test_rg_or_grep_available(self, ops): class TestReadFile (line 307) | class TestReadFile: method test_exact_content (line 308) | def test_exact_content(self, ops, tmp_path): method test_absolute_path (line 320) | def test_absolute_path(self, ops, tmp_path): method test_tilde_expansion (line 328) | def test_tilde_expansion(self, ops): method test_nonexistent_returns_error (line 339) | def test_nonexistent_returns_error(self, ops, tmp_path): method test_pagination_exact_window (line 343) | def test_pagination_exact_window(self, ops, tmp_path): method test_no_noise_in_content (line 355) | def test_no_noise_in_content(self, ops, tmp_path): class TestWriteFile (line 365) | class TestWriteFile: method test_write_and_verify (line 366) | def test_write_and_verify(self, ops, tmp_path): method test_creates_nested_dirs (line 373) | def test_creates_nested_dirs(self, ops, tmp_path): method test_overwrites_exact (line 380) | def test_overwrites_exact(self, ops, tmp_path): method test_large_content_via_stdin (line 387) | def test_large_content_via_stdin(self, ops, tmp_path): method test_special_characters_preserved (line 394) | def test_special_characters_preserved(self, ops, tmp_path): method test_roundtrip_read_write (line 400) | def test_roundtrip_read_write(self, ops, tmp_path): class TestPatchReplace (line 413) | class TestPatchReplace: method test_exact_replacement (line 414) | def test_exact_replacement(self, ops, tmp_path): method test_not_found_error (line 421) | def test_not_found_error(self, ops, tmp_path): method test_multiline_patch (line 428) | def test_multiline_patch(self, ops, tmp_path): class TestSearch (line 438) | class TestSearch: method test_content_search_finds_exact_match (line 439) | def test_content_search_finds_exact_match(self, ops, populated_dir): method test_content_search_no_false_positives (line 448) | def test_content_search_no_false_positives(self, ops, populated_dir): method test_file_search_finds_py_files (line 454) | def test_file_search_finds_py_files(self, ops, populated_dir): method test_file_search_no_false_file_entries (line 468) | def test_file_search_no_false_file_entries(self, ops, populated_dir): method test_content_search_with_glob_filter (line 476) | def test_content_search_with_glob_filter(self, ops, populated_dir): method test_search_output_has_zero_noise (line 484) | def test_search_output_has_zero_noise(self, ops, populated_dir): class TestExpandPath (line 495) | class TestExpandPath: method test_tilde_exact (line 496) | def test_tilde_exact(self, ops): method test_absolute_unchanged (line 502) | def test_absolute_unchanged(self, ops): method test_relative_unchanged (line 505) | def test_relative_unchanged(self, ops): method test_bare_tilde (line 508) | def test_bare_tilde(self, ops): method test_tilde_injection_blocked (line 513) | def test_tilde_injection_blocked(self, ops): method test_tilde_username_with_subpath (line 524) | def test_tilde_username_with_subpath(self, ops): class TestTerminalOutputCleanliness (line 535) | class TestTerminalOutputCleanliness: method test_echo (line 538) | def test_echo(self, env): method test_cat (line 543) | def test_cat(self, env, tmp_path): method test_ls (line 550) | def test_ls(self, env, tmp_path): method test_wc (line 558) | def test_wc(self, env, tmp_path): method test_head (line 565) | def test_head(self, env, tmp_path): method test_env_var_expansion (line 573) | def test_env_var_expansion(self, env): method test_command_substitution (line 578) | def test_command_substitution(self, env): method test_command_v_detection (line 583) | def test_command_v_detection(self, env): FILE: tests/tools/test_file_write_safety.py class TestStaticDenyList (line 14) | class TestStaticDenyList: method test_temp_file_not_denied_by_default (line 17) | def test_temp_file_not_denied_by_default(self, tmp_path: Path): method test_ssh_key_is_denied (line 21) | def test_ssh_key_is_denied(self): method test_etc_shadow_is_denied (line 24) | def test_etc_shadow_is_denied(self): class TestSafeWriteRoot (line 28) | class TestSafeWriteRoot: method test_writes_inside_safe_root_are_allowed (line 31) | def test_writes_inside_safe_root_are_allowed(self, tmp_path: Path, mon... method test_writes_to_safe_root_itself_are_allowed (line 39) | def test_writes_to_safe_root_itself_are_allowed(self, tmp_path: Path, ... method test_writes_outside_safe_root_are_denied (line 46) | def test_writes_outside_safe_root_are_denied(self, tmp_path: Path, mon... method test_safe_root_env_ignores_empty_value (line 55) | def test_safe_root_env_ignores_empty_value(self, tmp_path: Path, monke... method test_safe_root_unset_allows_all (line 60) | def test_safe_root_unset_allows_all(self, tmp_path: Path, monkeypatch): method test_safe_root_with_tilde_expansion (line 65) | def test_safe_root_with_tilde_expansion(self, tmp_path: Path, monkeypa... method test_safe_root_does_not_override_static_deny (line 75) | def test_safe_root_does_not_override_static_deny(self, tmp_path: Path,... FILE: tests/tools/test_force_dangerous_override.py function _old_should_allow (line 9) | def _old_should_allow(verdict, trust_level, force): function _new_should_allow (line 35) | def _new_should_allow(verdict, trust_level, force): class TestPolicyPrecedenceForDangerousVerdicts (line 57) | class TestPolicyPrecedenceForDangerousVerdicts: method test_builtin_dangerous_is_allowed_by_policy (line 58) | def test_builtin_dangerous_is_allowed_by_policy(self): method test_trusted_dangerous_is_blocked_without_force (line 61) | def test_trusted_dangerous_is_blocked_without_force(self): method test_force_overrides_dangerous_for_community (line 64) | def test_force_overrides_dangerous_for_community(self): method test_force_overrides_dangerous_for_trusted (line 67) | def test_force_overrides_dangerous_for_trusted(self): method test_force_still_overrides_caution (line 70) | def test_force_still_overrides_caution(self): method test_caution_community_blocked_without_force (line 73) | def test_caution_community_blocked_without_force(self): method test_safe_always_allowed (line 76) | def test_safe_always_allowed(self): method test_old_code_happened_to_allow_forced_dangerous_community (line 80) | def test_old_code_happened_to_allow_forced_dangerous_community(self): FILE: tests/tools/test_fuzzy_match.py class TestExactMatch (line 6) | class TestExactMatch: method test_single_replacement (line 7) | def test_single_replacement(self): method test_no_match (line 14) | def test_no_match(self): method test_empty_old_string (line 21) | def test_empty_old_string(self): method test_identical_strings (line 26) | def test_identical_strings(self): method test_multiline_exact (line 31) | def test_multiline_exact(self): class TestWhitespaceDifference (line 39) | class TestWhitespaceDifference: method test_extra_spaces_match (line 40) | def test_extra_spaces_match(self): class TestIndentDifference (line 47) | class TestIndentDifference: method test_different_indentation (line 48) | def test_different_indentation(self): class TestReplaceAll (line 55) | class TestReplaceAll: method test_multiple_matches_without_flag_errors (line 56) | def test_multiple_matches_without_flag_errors(self): method test_multiple_matches_with_flag (line 62) | def test_multiple_matches_with_flag(self): FILE: tests/tools/test_hidden_dir_filter.py function _old_filter_matches (line 14) | def _old_filter_matches(path_str: str) -> bool: function _new_filter_matches (line 22) | def _new_filter_matches(path: Path) -> bool: class TestOldFilterBrokenOnWindows (line 30) | class TestOldFilterBrokenOnWindows: method test_old_filter_misses_hub_on_windows_path (line 33) | def test_old_filter_misses_hub_on_windows_path(self): method test_old_filter_misses_git_on_windows_path (line 38) | def test_old_filter_misses_git_on_windows_path(self): method test_old_filter_works_on_unix_path (line 43) | def test_old_filter_works_on_unix_path(self): class TestNewFilterCrossPlatform (line 49) | class TestNewFilterCrossPlatform: method test_hub_quarantine_filtered (line 52) | def test_hub_quarantine_filtered(self, tmp_path): method test_git_dir_filtered (line 57) | def test_git_dir_filtered(self, tmp_path): method test_github_dir_filtered (line 62) | def test_github_dir_filtered(self, tmp_path): method test_normal_skill_not_filtered (line 67) | def test_normal_skill_not_filtered(self, tmp_path): method test_nested_skill_not_filtered (line 72) | def test_nested_skill_not_filtered(self, tmp_path): method test_dot_prefix_not_false_positive (line 77) | def test_dot_prefix_not_false_positive(self, tmp_path): class TestWindowsPathParts (line 83) | class TestWindowsPathParts: method test_parts_contains_hidden_dir (line 86) | def test_parts_contains_hidden_dir(self, tmp_path): method test_parts_does_not_contain_combined_string (line 91) | def test_parts_does_not_contain_combined_string(self, tmp_path): FILE: tests/tools/test_homeassistant_tool.py class TestFilterAndSummarize (line 44) | class TestFilterAndSummarize: method test_no_filters_returns_all (line 45) | def test_no_filters_returns_all(self): method test_domain_filter_lights (line 52) | def test_domain_filter_lights(self): method test_domain_filter_sensor (line 58) | def test_domain_filter_sensor(self): method test_domain_filter_no_matches (line 64) | def test_domain_filter_no_matches(self): method test_area_filter_by_friendly_name (line 69) | def test_area_filter_by_friendly_name(self): method test_area_filter_by_area_attribute (line 76) | def test_area_filter_by_area_attribute(self): method test_area_filter_case_insensitive (line 83) | def test_area_filter_case_insensitive(self): method test_combined_domain_and_area (line 87) | def test_combined_domain_and_area(self): method test_summary_includes_friendly_name (line 92) | def test_summary_includes_friendly_name(self): method test_empty_states_list (line 97) | def test_empty_states_list(self): method test_missing_attributes_handled (line 101) | def test_missing_attributes_handled(self): class TestBuildServicePayload (line 113) | class TestBuildServicePayload: method test_entity_id_only (line 114) | def test_entity_id_only(self): method test_data_only (line 118) | def test_data_only(self): method test_entity_id_and_data (line 122) | def test_entity_id_and_data(self): method test_no_args_returns_empty (line 131) | def test_no_args_returns_empty(self): method test_entity_id_param_takes_precedence_over_data (line 135) | def test_entity_id_param_takes_precedence_over_data(self): class TestParseServiceResponse (line 149) | class TestParseServiceResponse: method test_list_response_extracts_entities (line 150) | def test_list_response_extracts_entities(self): method test_empty_list_response (line 161) | def test_empty_list_response(self): method test_non_list_response (line 166) | def test_non_list_response(self): method test_none_response (line 172) | def test_none_response(self): method test_service_name_format (line 177) | def test_service_name_format(self): class TestHandlerValidation (line 187) | class TestHandlerValidation: method test_get_state_missing_entity_id (line 188) | def test_get_state_missing_entity_id(self): method test_get_state_empty_entity_id (line 193) | def test_get_state_empty_entity_id(self): method test_call_service_missing_domain (line 197) | def test_call_service_missing_domain(self): method test_call_service_missing_service (line 202) | def test_call_service_missing_service(self): method test_call_service_missing_both (line 207) | def test_call_service_missing_both(self): method test_call_service_empty_strings (line 211) | def test_call_service_empty_strings(self): class TestDomainBlocklist (line 221) | class TestDomainBlocklist: method test_blocked_domain_rejected (line 225) | def test_blocked_domain_rejected(self, domain): method test_safe_domain_not_blocked (line 232) | def test_safe_domain_not_blocked(self): method test_blocked_domains_include_shell_command (line 243) | def test_blocked_domains_include_shell_command(self): method test_blocked_domains_include_hassio (line 246) | def test_blocked_domains_include_hassio(self): method test_blocked_domains_include_rest_command (line 249) | def test_blocked_domains_include_rest_command(self): class TestEntityIdValidation (line 258) | class TestEntityIdValidation: method test_valid_entity_id_accepted (line 261) | def test_valid_entity_id_accepted(self): method test_path_traversal_rejected (line 267) | def test_path_traversal_rejected(self): method test_special_chars_rejected (line 272) | def test_special_chars_rejected(self): method test_missing_domain_rejected (line 278) | def test_missing_domain_rejected(self): method test_get_state_rejects_invalid_entity_id (line 282) | def test_get_state_rejects_invalid_entity_id(self): method test_call_service_rejects_invalid_entity_id (line 287) | def test_call_service_rejects_invalid_entity_id(self): method test_call_service_allows_no_entity_id (line 296) | def test_call_service_allows_no_entity_id(self): class TestCheckAvailable (line 311) | class TestCheckAvailable: method test_unavailable_without_token (line 312) | def test_unavailable_without_token(self, monkeypatch): method test_available_with_token (line 316) | def test_available_with_token(self, monkeypatch): method test_empty_token_is_unavailable (line 320) | def test_empty_token_is_unavailable(self, monkeypatch): class TestGetHeaders (line 330) | class TestGetHeaders: method test_bearer_token_format (line 331) | def test_bearer_token_format(self, monkeypatch): class TestRegistration (line 343) | class TestRegistration: method test_tools_registered_in_registry (line 344) | def test_tools_registered_in_registry(self): method test_tools_in_homeassistant_toolset (line 352) | def test_tools_in_homeassistant_toolset(self): method test_check_fn_gates_availability (line 359) | def test_check_fn_gates_availability(self, monkeypatch): method test_check_fn_includes_when_token_set (line 367) | def test_check_fn_includes_when_token_set(self, monkeypatch): FILE: tests/tools/test_honcho_tools.py class TestHonchoToolSessionContext (line 9) | class TestHonchoToolSessionContext: method setup_method (line 10) | def setup_method(self): method teardown_method (line 14) | def teardown_method(self): method test_explicit_call_context_wins_over_module_global_state (line 18) | def test_explicit_call_context_wins_over_module_global_state(self): FILE: tests/tools/test_interrupt.py class TestInterruptModule (line 16) | class TestInterruptModule: method test_set_and_check (line 19) | def test_set_and_check(self): method test_thread_safety (line 30) | def test_thread_safety(self): class TestPreToolCheck (line 59) | class TestPreToolCheck: method test_all_tools_skipped_when_interrupted (line 62) | def test_all_tools_skipped_when_interrupted(self): class TestMessageCombining (line 115) | class TestMessageCombining: method test_cli_interrupt_queue_drain (line 118) | def test_cli_interrupt_queue_drain(self): method test_gateway_pending_messages_append (line 140) | def test_gateway_pending_messages_append(self): class TestSIGKILLEscalation (line 164) | class TestSIGKILLEscalation: method test_sigterm_trap_killed_within_2s (line 171) | def test_sigterm_trap_killed_within_2s(self): FILE: tests/tools/test_local_env_blocklist.py function _make_fake_popen (line 22) | def _make_fake_popen(captured: dict): function _run_with_env (line 35) | def _run_with_env(extra_os_env=None, self_env=None): class TestProviderEnvBlocklist (line 59) | class TestProviderEnvBlocklist: method test_blocked_vars_are_stripped (line 62) | def test_blocked_vars_are_stripped(self): method test_registry_derived_vars_are_stripped (line 76) | def test_registry_derived_vars_are_stripped(self): method test_non_registry_provider_vars_are_stripped (line 95) | def test_non_registry_provider_vars_are_stripped(self): method test_tool_and_gateway_vars_are_stripped (line 113) | def test_tool_and_gateway_vars_are_stripped(self): method test_safe_vars_are_preserved (line 140) | def test_safe_vars_are_preserved(self): method test_self_env_blocked_vars_also_stripped (line 149) | def test_self_env_blocked_vars_also_stripped(self): class TestForceEnvOptIn (line 161) | class TestForceEnvOptIn: method test_force_prefix_passes_blocked_var (line 164) | def test_force_prefix_passes_blocked_var(self): method test_force_prefix_overrides_os_environ_block (line 175) | def test_force_prefix_overrides_os_environ_block(self): class TestBlocklistCoverage (line 185) | class TestBlocklistCoverage: method test_issue_1002_offenders (line 188) | def test_issue_1002_offenders(self): method test_registry_vars_are_in_blocklist (line 199) | def test_registry_vars_are_in_blocklist(self): method test_extra_auth_vars_covered (line 215) | def test_extra_auth_vars_covered(self): method test_non_registry_provider_vars_are_in_blocklist (line 221) | def test_non_registry_provider_vars_are_in_blocklist(self): method test_optional_tool_and_messaging_vars_are_in_blocklist (line 236) | def test_optional_tool_and_messaging_vars_are_in_blocklist(self): method test_gateway_runtime_vars_are_in_blocklist (line 251) | def test_gateway_runtime_vars_are_in_blocklist(self): FILE: tests/tools/test_local_persistent.py class TestLocalConfig (line 11) | class TestLocalConfig: method test_local_persistent_default_false (line 12) | def test_local_persistent_default_false(self, monkeypatch): method test_local_persistent_true (line 17) | def test_local_persistent_true(self, monkeypatch): method test_local_persistent_yes (line 22) | def test_local_persistent_yes(self, monkeypatch): class TestMergeOutput (line 28) | class TestMergeOutput: method test_stdout_only (line 29) | def test_stdout_only(self): method test_stderr_only (line 32) | def test_stderr_only(self): method test_both (line 35) | def test_both(self): method test_empty (line 38) | def test_empty(self): method test_strips_trailing_newlines (line 41) | def test_strips_trailing_newlines(self): class TestLocalOneShotRegression (line 45) | class TestLocalOneShotRegression: method test_echo (line 46) | def test_echo(self): method test_exit_code (line 53) | def test_exit_code(self): method test_state_does_not_persist (line 59) | def test_state_does_not_persist(self): class TestLocalPersistent (line 67) | class TestLocalPersistent: method env (line 69) | def env(self): method test_echo (line 74) | def test_echo(self, env): method test_env_var_persists (line 79) | def test_env_var_persists(self, env): method test_cwd_persists (line 84) | def test_cwd_persists(self, env): method test_exit_code (line 89) | def test_exit_code(self, env): method test_stderr (line 93) | def test_stderr(self, env): method test_multiline_output (line 98) | def test_multiline_output(self, env): method test_timeout_then_recovery (line 103) | def test_timeout_then_recovery(self, env): method test_large_output (line 110) | def test_large_output(self, env): method test_shell_variable_persists (line 118) | def test_shell_variable_persists(self, env): method test_cleanup_removes_temp_files (line 123) | def test_cleanup_removes_temp_files(self, env): method test_state_does_not_leak_between_instances (line 131) | def test_state_does_not_leak_between_instances(self): method test_special_characters_in_command (line 142) | def test_special_characters_in_command(self, env): method test_pipe_command (line 146) | def test_pipe_command(self, env): method test_multiple_commands_semicolon (line 150) | def test_multiple_commands_semicolon(self, env): FILE: tests/tools/test_mcp_probe.py function _reset_mcp_state (line 11) | def _reset_mcp_state(): class TestProbeMcpServerTools (line 24) | class TestProbeMcpServerTools: method test_returns_empty_when_mcp_not_available (line 27) | def test_returns_empty_when_mcp_not_available(self): method test_returns_empty_when_no_config (line 33) | def test_returns_empty_when_no_config(self): method test_returns_empty_when_all_servers_disabled (line 39) | def test_returns_empty_when_all_servers_disabled(self): method test_returns_tools_from_successful_server (line 49) | def test_returns_tools_from_successful_server(self): method test_failed_server_omitted_from_results (line 89) | def test_failed_server_omitted_from_results(self): method test_handles_tool_without_description (line 126) | def test_handles_tool_without_description(self): method test_cleanup_called_even_on_failure (line 158) | def test_cleanup_called_even_on_failure(self): method test_skips_disabled_servers (line 173) | def test_skips_disabled_servers(self): FILE: tests/tools/test_mcp_tool.py function _make_mcp_tool (line 19) | def _make_mcp_tool(name="read_file", description="Read a file", input_sc... function _make_call_result (line 34) | def _make_call_result(text="file contents here", is_error=False): function _make_mock_server (line 40) | def _make_mock_server(name, session=None, tools=None): class TestLoadMCPConfig (line 53) | class TestLoadMCPConfig: method test_no_config_returns_empty (line 54) | def test_no_config_returns_empty(self): method test_valid_config_parsed (line 61) | def test_valid_config_parsed(self): method test_mcp_servers_not_dict_returns_empty (line 76) | def test_mcp_servers_not_dict_returns_empty(self): class TestSchemaConversion (line 88) | class TestSchemaConversion: method test_converts_mcp_tool_to_hermes_schema (line 89) | def test_converts_mcp_tool_to_hermes_schema(self): method test_empty_input_schema_gets_default (line 99) | def test_empty_input_schema_gets_default(self): method test_object_schema_without_properties_gets_normalized (line 109) | def test_object_schema_without_properties_gets_normalized(self): method test_tool_name_prefix_format (line 121) | def test_tool_name_prefix_format(self): method test_hyphens_sanitized_to_underscores (line 129) | def test_hyphens_sanitized_to_underscores(self): class TestCheckFunction (line 144) | class TestCheckFunction: method test_disconnected_returns_false (line 145) | def test_disconnected_returns_false(self): method test_connected_returns_true (line 152) | def test_connected_returns_true(self): method test_session_none_returns_false (line 163) | def test_session_none_returns_false(self): class TestToolHandler (line 179) | class TestToolHandler: method _patch_mcp_loop (line 182) | def _patch_mcp_loop(self, coro_side_effect=None): method test_successful_call (line 194) | def test_successful_call(self): method test_mcp_error_result (line 213) | def test_mcp_error_result(self): method test_disconnected_server (line 232) | def test_disconnected_server(self): method test_exception_during_call (line 241) | def test_exception_during_call(self): class TestDiscoverAndRegister (line 263) | class TestDiscoverAndRegister: method test_tools_registered_in_registry (line 264) | def test_tools_registered_in_registry(self): method test_toolset_created (line 295) | def test_toolset_created(self): method test_schema_format_correct (line 321) | def test_schema_format_correct(self): class TestMCPServerTask (line 356) | class TestMCPServerTask: method _mock_stdio_and_session (line 359) | def _mock_stdio_and_session(self, session): method test_start_connects_and_discovers_tools (line 377) | def test_start_connects_and_discovers_tools(self): method test_no_command_raises (line 405) | def test_no_command_raises(self): method test_empty_env_gets_safe_defaults (line 416) | def test_empty_env_gets_safe_defaults(self): method test_shutdown_signals_task_exit (line 447) | def test_shutdown_signals_task_exit(self): class TestToolsetInjection (line 479) | class TestToolsetInjection: method test_mcp_tools_added_to_all_hermes_toolsets (line 480) | def test_mcp_tools_added_to_all_hermes_toolsets(self): method test_server_toolset_skips_builtin_collision (line 525) | def test_server_toolset_skips_builtin_collision(self): method test_server_connection_failure_skipped (line 557) | def test_server_connection_failure_skipped(self): method test_partial_failure_retry_on_second_call (line 597) | def test_partial_failure_retry_on_second_call(self): class TestGracefulFallback (line 655) | class TestGracefulFallback: method test_mcp_unavailable_returns_empty (line 656) | def test_mcp_unavailable_returns_empty(self): method test_no_servers_returns_empty (line 663) | def test_no_servers_returns_empty(self): class TestShutdown (line 677) | class TestShutdown: method test_no_servers_safe (line 678) | def test_no_servers_safe(self): method test_shutdown_clears_servers (line 685) | def test_shutdown_clears_servers(self): method test_shutdown_handles_errors (line 706) | def test_shutdown_handles_errors(self): method test_shutdown_is_parallel (line 726) | def test_shutdown_is_parallel(self): class TestBuildSafeEnv (line 761) | class TestBuildSafeEnv: method test_only_safe_vars_passed (line 764) | def test_only_safe_vars_passed(self): method test_user_env_merged (line 794) | def test_user_env_merged(self): method test_user_env_overrides_safe (line 804) | def test_user_env_overrides_safe(self): method test_none_user_env (line 813) | def test_none_user_env(self): method test_secret_vars_excluded (line 824) | def test_secret_vars_excluded(self): class TestSanitizeError (line 851) | class TestSanitizeError: method test_strips_github_pat (line 854) | def test_strips_github_pat(self): method test_strips_openai_key (line 859) | def test_strips_openai_key(self): method test_strips_bearer_token (line 864) | def test_strips_bearer_token(self): method test_strips_token_param (line 869) | def test_strips_token_param(self): method test_no_credentials_unchanged (line 874) | def test_no_credentials_unchanged(self): method test_multiple_credentials (line 879) | def test_multiple_credentials(self): class TestHTTPConfig (line 892) | class TestHTTPConfig: method test_is_http_with_url (line 895) | def test_is_http_with_url(self): method test_is_stdio_with_command (line 901) | def test_is_stdio_with_command(self): method test_conflicting_url_and_command_warns (line 907) | def test_conflicting_url_and_command_warns(self): method test_http_unavailable_raises (line 916) | def test_http_unavailable_raises(self): class TestReconnection (line 934) | class TestReconnection: method test_reconnect_on_disconnect (line 937) | def test_reconnect_on_disconnect(self): method test_no_reconnect_on_shutdown (line 976) | def test_no_reconnect_on_shutdown(self): method test_no_reconnect_on_initial_failure (line 1010) | def test_no_reconnect_on_initial_failure(self): class TestConfigurableTimeouts (line 1047) | class TestConfigurableTimeouts: method test_default_timeout (line 1050) | def test_default_timeout(self): method test_custom_timeout (line 1058) | def test_custom_timeout(self): method test_timeout_passed_to_handler (line 1090) | def test_timeout_passed_to_handler(self): class TestUtilitySchemas (line 1120) | class TestUtilitySchemas: method test_builds_four_utility_schemas (line 1123) | def test_builds_four_utility_schemas(self): method test_hyphens_sanitized_in_utility_names (line 1134) | def test_hyphens_sanitized_in_utility_names(self): method test_list_resources_schema_no_required_params (line 1143) | def test_list_resources_schema_no_required_params(self): method test_read_resource_schema_requires_uri (line 1153) | def test_read_resource_schema_requires_uri(self): method test_list_prompts_schema_no_required_params (line 1163) | def test_list_prompts_schema_no_required_params(self): method test_get_prompt_schema_requires_name (line 1173) | def test_get_prompt_schema_requires_name(self): method test_schemas_have_descriptions (line 1185) | def test_schemas_have_descriptions(self): class TestUtilityHandlers (line 1199) | class TestUtilityHandlers: method _patch_mcp_loop (line 1202) | def _patch_mcp_loop(self): method test_list_resources_success (line 1214) | def test_list_resources_success(self): method test_list_resources_empty (line 1239) | def test_list_resources_empty(self): method test_list_resources_disconnected (line 1257) | def test_list_resources_disconnected(self): method test_read_resource_success (line 1267) | def test_read_resource_success(self): method test_read_resource_missing_uri (line 1287) | def test_read_resource_missing_uri(self): method test_read_resource_disconnected (line 1301) | def test_read_resource_disconnected(self): method test_list_prompts_success (line 1311) | def test_list_prompts_success(self): method test_list_prompts_empty (line 1338) | def test_list_prompts_empty(self): method test_list_prompts_disconnected (line 1356) | def test_list_prompts_disconnected(self): method test_get_prompt_success (line 1366) | def test_get_prompt_success(self): method test_get_prompt_missing_name (line 1394) | def test_get_prompt_missing_name(self): method test_get_prompt_disconnected (line 1408) | def test_get_prompt_disconnected(self): method test_get_prompt_default_arguments (line 1416) | def test_get_prompt_default_arguments(self): class TestUtilityToolRegistration (line 1442) | class TestUtilityToolRegistration: method test_utility_tools_registered (line 1445) | def test_utility_tools_registered(self): method test_utility_tools_in_same_toolset (line 1481) | def test_utility_tools_in_same_toolset(self): method test_utility_tools_have_check_fn (line 1510) | def test_utility_tools_have_check_fn(self): function _make_sampling_params (line 1566) | def _make_sampling_params( function _make_llm_response (line 1600) | def _make_llm_response( function _make_llm_tool_response (line 1616) | def _make_llm_tool_response(tool_calls_data=None, model="test-model"): class TestSafeNumeric (line 1643) | class TestSafeNumeric: method test_int_passthrough (line 1644) | def test_int_passthrough(self): method test_string_coercion (line 1647) | def test_string_coercion(self): method test_none_returns_default (line 1650) | def test_none_returns_default(self): method test_inf_returns_default (line 1653) | def test_inf_returns_default(self): method test_nan_returns_default (line 1656) | def test_nan_returns_default(self): method test_below_minimum_clamps (line 1659) | def test_below_minimum_clamps(self): method test_minimum_zero_allowed (line 1662) | def test_minimum_zero_allowed(self): method test_non_numeric_string_returns_default (line 1665) | def test_non_numeric_string_returns_default(self): method test_float_coercion (line 1668) | def test_float_coercion(self): class TestSamplingHandlerInit (line 1676) | class TestSamplingHandlerInit: method test_defaults (line 1677) | def test_defaults(self): method test_custom_config (line 1688) | def test_custom_config(self): method test_string_numeric_config_values (line 1706) | def test_string_numeric_config_values(self): class TestRateLimit (line 1719) | class TestRateLimit: method setup_method (line 1720) | def setup_method(self): method test_allows_under_limit (line 1723) | def test_allows_under_limit(self): method test_rejects_over_limit (line 1728) | def test_rejects_over_limit(self): method test_window_expiry (line 1733) | def test_window_expiry(self): class TestResolveModel (line 1746) | class TestResolveModel: method setup_method (line 1747) | def setup_method(self): method test_no_preference_no_override (line 1750) | def test_no_preference_no_override(self): method test_config_override_wins (line 1753) | def test_config_override_wins(self): method test_hint_used_when_no_override (line 1758) | def test_hint_used_when_no_override(self): method test_empty_hints (line 1762) | def test_empty_hints(self): method test_hint_without_name (line 1766) | def test_hint_without_name(self): class TestConvertMessages (line 1775) | class TestConvertMessages: method setup_method (line 1776) | def setup_method(self): method test_single_text_message (line 1779) | def test_single_text_message(self): method test_image_message (line 1787) | def test_image_message(self): method test_tool_result_message (line 1804) | def test_tool_result_message(self): method test_tool_use_message (line 1819) | def test_tool_use_message(self): method test_mixed_text_and_tool_use (line 1836) | def test_mixed_text_and_tool_use(self): method test_fallback_without_content_as_list (line 1853) | def test_fallback_without_content_as_list(self): class TestSamplingCallbackText (line 1867) | class TestSamplingCallbackText: method setup_method (line 1868) | def setup_method(self): method test_text_response (line 1871) | def test_text_response(self): method test_system_prompt_prepended (line 1892) | def test_system_prompt_prepended(self): method test_server_tools_with_object_schema_are_normalized (line 1908) | def test_server_tools_with_object_schema_are_normalized(self): method test_length_stop_reason (line 1935) | def test_length_stop_reason(self): class TestSamplingCallbackToolUse (line 1957) | class TestSamplingCallbackToolUse: method setup_method (line 1958) | def setup_method(self): method test_tool_use_response (line 1961) | def test_tool_use_response(self): method test_multiple_tool_calls (line 1983) | def test_multiple_tool_calls(self): class TestToolLoopGovernance (line 2009) | class TestToolLoopGovernance: method test_max_tool_rounds_enforcement (line 2010) | def test_max_tool_rounds_enforcement(self): method test_text_response_resets_counter (line 2031) | def test_text_response_resets_counter(self): method test_max_tool_rounds_zero_disables (line 2057) | def test_max_tool_rounds_zero_disables(self): class TestSamplingErrors (line 2076) | class TestSamplingErrors: method test_rate_limit_error (line 2077) | def test_rate_limit_error(self): method test_timeout_error (line 2095) | def test_timeout_error(self): method test_no_provider_error (line 2113) | def test_no_provider_error(self): method test_empty_choices_returns_error (line 2124) | def test_empty_choices_returns_error(self): method test_none_choices_returns_error (line 2144) | def test_none_choices_returns_error(self): method test_missing_choices_attr_returns_error (line 2164) | def test_missing_choices_attr_returns_error(self): class TestModelWhitelist (line 2188) | class TestModelWhitelist: method test_allowed_model_passes (line 2189) | def test_allowed_model_passes(self): method test_disallowed_model_rejected (line 2201) | def test_disallowed_model_rejected(self): method test_empty_whitelist_allows_all (line 2214) | def test_empty_whitelist_allows_all(self): class TestMalformedToolCallArgs (line 2231) | class TestMalformedToolCallArgs: method test_invalid_json_wrapped_as_raw (line 2232) | def test_invalid_json_wrapped_as_raw(self): method test_dict_args_pass_through (line 2251) | def test_dict_args_pass_through(self): class TestMetricsTracking (line 2282) | class TestMetricsTracking: method test_request_and_token_metrics (line 2283) | def test_request_and_token_metrics(self): method test_tool_use_count_metric (line 2298) | def test_tool_use_count_metric(self): method test_error_metric_incremented (line 2312) | def test_error_metric_incremented(self): class TestSessionKwargs (line 2329) | class TestSessionKwargs: method test_returns_correct_keys (line 2330) | def test_returns_correct_keys(self): method test_sampling_capabilities_type (line 2337) | def test_sampling_capabilities_type(self): class TestMCPServerTaskSamplingIntegration (line 2349) | class TestMCPServerTaskSamplingIntegration: method test_sampling_handler_created_when_enabled (line 2350) | def test_sampling_handler_created_when_enabled(self): method test_sampling_handler_none_when_disabled (line 2374) | def test_sampling_handler_none_when_disabled(self): method test_session_kwargs_used_in_stdio (line 2392) | def test_session_kwargs_used_in_stdio(self): class TestDiscoveryFailedCount (line 2407) | class TestDiscoveryFailedCount: method test_failed_server_increments_failed_count (line 2410) | def test_failed_server_increments_failed_count(self): method test_all_servers_fail_still_prints_summary (line 2454) | def test_all_servers_fail_still_prints_summary(self): method test_ok_servers_excludes_failures (line 2484) | def test_ok_servers_excludes_failures(self): class TestMCPSelectiveToolLoading (line 2527) | class TestMCPSelectiveToolLoading: method _make_server (line 2530) | def _make_server(self, name, tool_names, session=None): method _run_discover (line 2538) | def _run_discover(self, name, tool_names, config, session=None): method test_include_takes_precedence_over_exclude (line 2560) | def test_include_takes_precedence_over_exclude(self): method test_exclude_filter_registers_all_except_listed_tools (line 2576) | def test_exclude_filter_registers_all_except_listed_tools(self): method test_include_filter_skips_utility_tools_without_capabilities (line 2592) | def test_include_filter_skips_utility_tools_without_capabilities(self): method test_no_filter_registers_all_server_tools_when_no_utilities_supported (line 2606) | def test_no_filter_registers_all_server_tools_when_no_utilities_suppor... method test_resources_and_prompts_can_be_disabled_explicitly (line 2619) | def test_resources_and_prompts_can_be_disabled_explicitly(self): method test_registers_only_utility_tools_supported_by_server_capabilities (line 2641) | def test_registers_only_utility_tools_supported_by_server_capabilities... method test_existing_tool_names_reflect_registered_subset (line 2658) | def test_existing_tool_names_reflect_registered_subset(self): method test_no_toolset_created_when_everything_is_filtered_out (line 2690) | def test_no_toolset_created_when_everything_is_filtered_out(self): method test_enabled_false_skips_connection_attempt (line 2725) | def test_enabled_false_skips_connection_attempt(self): FILE: tests/tools/test_mcp_tool_issue_948.py function test_resolve_stdio_command_falls_back_to_hermes_node_bin (line 11) | def test_resolve_stdio_command_falls_back_to_hermes_node_bin(tmp_path): function test_resolve_stdio_command_respects_explicit_empty_path (line 26) | def test_resolve_stdio_command_respects_explicit_empty_path(): function test_format_connect_error_unwraps_exception_group (line 41) | def test_format_connect_error_unwraps_exception_group(): function test_run_stdio_uses_resolved_command_and_prepended_path (line 52) | def test_run_stdio_uses_resolved_command_and_prepended_path(tmp_path): FILE: tests/tools/test_memory_tool.py class TestMemorySchema (line 20) | class TestMemorySchema: method test_discourages_diary_style_task_logs (line 21) | def test_discourages_diary_style_task_logs(self): class TestScanMemoryContent (line 34) | class TestScanMemoryContent: method test_clean_content_passes (line 35) | def test_clean_content_passes(self): method test_prompt_injection_blocked (line 39) | def test_prompt_injection_blocked(self): method test_exfiltration_blocked (line 50) | def test_exfiltration_blocked(self): method test_ssh_backdoor_blocked (line 61) | def test_ssh_backdoor_blocked(self): method test_invisible_unicode_blocked (line 69) | def test_invisible_unicode_blocked(self): method test_role_hijack_blocked (line 77) | def test_role_hijack_blocked(self): method test_system_override_blocked (line 82) | def test_system_override_blocked(self): function store (line 93) | def store(tmp_path, monkeypatch): class TestMemoryStoreAdd (line 101) | class TestMemoryStoreAdd: method test_add_entry (line 102) | def test_add_entry(self, store): method test_add_to_user (line 107) | def test_add_to_user(self, store): method test_add_empty_rejected (line 112) | def test_add_empty_rejected(self, store): method test_add_duplicate_rejected (line 116) | def test_add_duplicate_rejected(self, store): method test_add_exceeding_limit_rejected (line 122) | def test_add_exceeding_limit_rejected(self, store): method test_add_injection_blocked (line 129) | def test_add_injection_blocked(self, store): class TestMemoryStoreReplace (line 135) | class TestMemoryStoreReplace: method test_replace_entry (line 136) | def test_replace_entry(self, store): method test_replace_no_match (line 143) | def test_replace_no_match(self, store): method test_replace_ambiguous_match (line 148) | def test_replace_ambiguous_match(self, store): method test_replace_empty_old_text_rejected (line 155) | def test_replace_empty_old_text_rejected(self, store): method test_replace_empty_new_content_rejected (line 159) | def test_replace_empty_new_content_rejected(self, store): method test_replace_injection_blocked (line 164) | def test_replace_injection_blocked(self, store): class TestMemoryStoreRemove (line 170) | class TestMemoryStoreRemove: method test_remove_entry (line 171) | def test_remove_entry(self, store): method test_remove_no_match (line 177) | def test_remove_no_match(self, store): method test_remove_empty_old_text (line 181) | def test_remove_empty_old_text(self, store): class TestMemoryStorePersistence (line 186) | class TestMemoryStorePersistence: method test_save_and_load_roundtrip (line 187) | def test_save_and_load_roundtrip(self, tmp_path, monkeypatch): method test_deduplication_on_load (line 200) | def test_deduplication_on_load(self, tmp_path, monkeypatch): class TestMemoryStoreSnapshot (line 211) | class TestMemoryStoreSnapshot: method test_snapshot_frozen_at_load (line 212) | def test_snapshot_frozen_at_load(self, store): method test_empty_snapshot_returns_none (line 225) | def test_empty_snapshot_returns_none(self, store): class TestMemoryToolDispatcher (line 233) | class TestMemoryToolDispatcher: method test_no_store_returns_error (line 234) | def test_no_store_returns_error(self): method test_invalid_target (line 239) | def test_invalid_target(self, store): method test_unknown_action (line 243) | def test_unknown_action(self, store): method test_add_via_tool (line 247) | def test_add_via_tool(self, store): method test_replace_requires_old_text (line 251) | def test_replace_requires_old_text(self, store): method test_remove_requires_old_text (line 255) | def test_remove_requires_old_text(self, store): FILE: tests/tools/test_mixture_of_agents_tool.py function test_moa_defaults_track_current_openrouter_frontier_models (line 11) | def test_moa_defaults_track_current_openrouter_frontier_models(): function test_reference_model_retry_warnings_avoid_exc_info_until_terminal_failure (line 22) | async def test_reference_model_retry_warnings_avoid_exc_info_until_termi... function test_moa_top_level_error_logs_single_traceback_on_aggregator_failure (line 51) | async def test_moa_top_level_error_logs_single_traceback_on_aggregator_f... FILE: tests/tools/test_modal_sandbox_fixes.py class TestToolResolution (line 36) | class TestToolResolution: method _has_minisweagent (line 39) | def _has_minisweagent(self): method test_terminal_and_file_toolsets_resolve_all_tools (line 46) | def test_terminal_and_file_toolsets_resolve_all_tools(self): method test_terminal_tool_present (line 59) | def test_terminal_tool_present(self): class TestCwdHandling (line 79) | class TestCwdHandling: method test_home_path_replaced_for_modal (line 82) | def test_home_path_replaced_for_modal(self): method test_users_path_replaced_for_docker_by_default (line 94) | def test_users_path_replaced_for_docker_by_default(self): method test_users_path_maps_to_workspace_for_docker_when_enabled (line 108) | def test_users_path_maps_to_workspace_for_docker_when_enabled(self): method test_windows_path_replaced_for_modal (line 120) | def test_windows_path_replaced_for_modal(self): method test_default_cwd_is_root_for_container_backends (line 129) | def test_default_cwd_is_root_for_container_backends(self): method test_docker_default_cwd_maps_current_directory_when_enabled (line 143) | def test_docker_default_cwd_maps_current_directory_when_enabled(self): method test_local_backend_uses_getcwd (line 157) | def test_local_backend_uses_getcwd(self): method test_create_environment_passes_docker_host_cwd_and_flag (line 166) | def test_create_environment_passes_docker_host_cwd_and_flag(self, monk... method test_ssh_preserves_home_paths (line 191) | def test_ssh_preserves_home_paths(self): class TestEphemeralDiskCheck (line 209) | class TestEphemeralDiskCheck: method test_ephemeral_disk_skipped_when_unsupported (line 212) | def test_ephemeral_disk_skipped_when_unsupported(self): class TestModalEnvironmentDefaults (line 252) | class TestModalEnvironmentDefaults: method test_default_cwd_is_root (line 255) | def test_default_cwd_is_root(self): class TestEnsurepipFix (line 271) | class TestEnsurepipFix: method test_patched_init_creates_image_with_setup_commands (line 274) | def test_patched_init_creates_image_with_setup_commands(self): method test_patched_init_uses_install_pipx_from_config (line 293) | def test_patched_init_uses_install_pipx_from_config(self): class TestHostPrefixList (line 311) | class TestHostPrefixList: method test_all_common_host_prefixes_caught (line 314) | def test_all_common_host_prefixes_caught(self): FILE: tests/tools/test_parse_env_var.py class TestParseEnvVar (line 14) | class TestParseEnvVar: method test_valid_int (line 19) | def test_valid_int(self): method test_valid_float (line 23) | def test_valid_float(self): method test_valid_json (line 27) | def test_valid_json(self): method test_get_env_config_parses_docker_forward_env_json (line 33) | def test_get_env_config_parses_docker_forward_env_json(self): method test_create_environment_passes_docker_forward_env (line 41) | def test_create_environment_passes_docker_forward_env(self): method test_falls_back_to_default (line 55) | def test_falls_back_to_default(self): method test_invalid_int_raises_with_var_name (line 66) | def test_invalid_int_raises_with_var_name(self): method test_invalid_int_includes_bad_value (line 71) | def test_invalid_int_includes_bad_value(self): method test_invalid_json_raises_with_var_name (line 78) | def test_invalid_json_raises_with_var_name(self): method test_invalid_json_includes_type_label (line 83) | def test_invalid_json_includes_type_label(self): FILE: tests/tools/test_patch_parser.py class TestParseUpdateFile (line 12) | class TestParseUpdateFile: method test_basic_update (line 13) | def test_basic_update(self): method test_multiple_hunks (line 38) | def test_multiple_hunks(self): class TestParseAddFile (line 59) | class TestParseAddFile: method test_add_file (line 60) | def test_add_file(self): class TestParseDeleteFile (line 82) | class TestParseDeleteFile: method test_delete_file (line 83) | def test_delete_file(self): class TestParseMoveFile (line 95) | class TestParseMoveFile: method test_move_file (line 96) | def test_move_file(self): class TestParseInvalidPatch (line 109) | class TestParseInvalidPatch: method test_empty_patch_returns_empty_ops (line 110) | def test_empty_patch_returns_empty_ops(self): method test_no_begin_marker_still_parses (line 115) | def test_no_begin_marker_still_parses(self): method test_multiple_operations (line 126) | def test_multiple_operations(self): class TestApplyUpdate (line 145) | class TestApplyUpdate: method test_preserves_non_prefix_pipe_characters_in_unmodified_lines (line 146) | def test_preserves_non_prefix_pipe_characters_in_unmodified_lines(self): FILE: tests/tools/test_process_registry.py function registry (line 21) | def registry(): function _make_session (line 26) | def _make_session( class TestGetAndPoll (line 52) | class TestGetAndPoll: method test_get_not_found (line 53) | def test_get_not_found(self, registry): method test_get_running (line 56) | def test_get_running(self, registry): method test_get_finished (line 61) | def test_get_finished(self, registry): method test_poll_not_found (line 66) | def test_poll_not_found(self, registry): method test_poll_running (line 70) | def test_poll_running(self, registry): method test_poll_exited (line 78) | def test_poll_exited(self, registry): class TestReadLog (line 90) | class TestReadLog: method test_not_found (line 91) | def test_not_found(self, registry): method test_read_full_log (line 95) | def test_read_full_log(self, registry): method test_read_with_limit (line 102) | def test_read_with_limit(self, registry): method test_read_with_offset (line 110) | def test_read_with_offset(self, registry): class TestListSessions (line 122) | class TestListSessions: method test_empty (line 123) | def test_empty(self, registry): method test_lists_running_and_finished (line 126) | def test_lists_running_and_finished(self, registry): method test_filter_by_task_id (line 134) | def test_filter_by_task_id(self, registry): method test_list_entry_fields (line 143) | def test_list_entry_fields(self, registry): class TestActiveQueries (line 158) | class TestActiveQueries: method test_has_active_processes (line 159) | def test_has_active_processes(self, registry): method test_has_active_for_session (line 165) | def test_has_active_for_session(self, registry): method test_exited_not_active (line 172) | def test_exited_not_active(self, registry): class TestPruning (line 182) | class TestPruning: method test_prune_expired_finished (line 183) | def test_prune_expired_finished(self, registry): method test_prune_keeps_recent (line 193) | def test_prune_keeps_recent(self, registry): method test_prune_over_max_removes_oldest (line 199) | def test_prune_over_max_removes_oldest(self, registry): class TestSpawnEnvSanitization (line 222) | class TestSpawnEnvSanitization: method test_spawn_local_strips_blocked_vars_from_background_env (line 223) | def test_spawn_local_strips_blocked_vars_from_background_env(self, reg... class TestCheckpoint (line 270) | class TestCheckpoint: method test_write_checkpoint (line 271) | def test_write_checkpoint(self, registry, tmp_path): method test_recover_no_file (line 281) | def test_recover_no_file(self, registry, tmp_path): method test_recover_dead_pid (line 285) | def test_recover_dead_pid(self, registry, tmp_path): method test_write_checkpoint_includes_watcher_metadata (line 297) | def test_write_checkpoint_includes_watcher_metadata(self, registry, tm... method test_recover_enqueues_watchers (line 314) | def test_recover_enqueues_watchers(self, registry, tmp_path): method test_recover_skips_watcher_when_no_interval (line 338) | def test_recover_skips_watcher_when_no_interval(self, registry, tmp_pa... class TestKillProcess (line 357) | class TestKillProcess: method test_kill_not_found (line 358) | def test_kill_not_found(self, registry): method test_kill_already_exited (line 362) | def test_kill_already_exited(self, registry): class TestProcessToolHandler (line 373) | class TestProcessToolHandler: method test_list_action (line 374) | def test_list_action(self): method test_poll_missing_session_id (line 379) | def test_poll_missing_session_id(self): method test_unknown_action (line 384) | def test_unknown_action(self): FILE: tests/tools/test_read_loop_detection.py class _FakeReadResult (line 32) | class _FakeReadResult: method __init__ (line 34) | def __init__(self, content="line1\nline2\n", total_lines=2): method to_dict (line 38) | def to_dict(self): function _fake_read_file (line 42) | def _fake_read_file(path, offset=1, limit=500): class _FakeSearchResult (line 46) | class _FakeSearchResult: method __init__ (line 48) | def __init__(self): method to_dict (line 51) | def to_dict(self): function _make_fake_file_ops (line 55) | def _make_fake_file_ops(): class TestReadLoopDetection (line 62) | class TestReadLoopDetection(unittest.TestCase): method setUp (line 65) | def setUp(self): method tearDown (line 68) | def tearDown(self): method test_first_read_has_no_warning (line 72) | def test_first_read_has_no_warning(self, _mock_ops): method test_second_consecutive_read_no_warning (line 78) | def test_second_consecutive_read_no_warning(self, _mock_ops): method test_third_consecutive_read_has_warning (line 88) | def test_third_consecutive_read_has_warning(self, _mock_ops): method test_fourth_consecutive_read_is_blocked (line 99) | def test_fourth_consecutive_read_is_blocked(self, _mock_ops): method test_fifth_consecutive_read_still_blocked (line 110) | def test_fifth_consecutive_read_still_blocked(self, _mock_ops): method test_different_region_resets_consecutive (line 119) | def test_different_region_resets_consecutive(self, _mock_ops): method test_different_file_resets_consecutive (line 130) | def test_different_file_resets_consecutive(self, _mock_ops): method test_different_tasks_isolated (line 138) | def test_different_tasks_isolated(self, _mock_ops): method test_warning_still_returns_content (line 147) | def test_warning_still_returns_content(self, _mock_ops): class TestNotifyOtherToolCall (line 157) | class TestNotifyOtherToolCall(unittest.TestCase): method setUp (line 160) | def setUp(self): method tearDown (line 163) | def tearDown(self): method test_other_tool_resets_consecutive (line 167) | def test_other_tool_resets_consecutive(self, _mock_ops): method test_other_tool_prevents_block (line 179) | def test_other_tool_prevents_block(self, _mock_ops): method test_notify_on_unknown_task_is_safe (line 191) | def test_notify_on_unknown_task_is_safe(self, _mock_ops): method test_history_survives_notify (line 196) | def test_history_survives_notify(self, _mock_ops): class TestReadFilesSummary (line 205) | class TestReadFilesSummary(unittest.TestCase): method setUp (line 208) | def setUp(self): method tearDown (line 211) | def tearDown(self): method test_empty_when_no_reads (line 215) | def test_empty_when_no_reads(self, _mock_ops): method test_single_file_single_region (line 220) | def test_single_file_single_region(self, _mock_ops): method test_single_file_multiple_regions (line 228) | def test_single_file_multiple_regions(self, _mock_ops): method test_multiple_files (line 236) | def test_multiple_files(self, _mock_ops): method test_different_task_has_separate_summary (line 246) | def test_different_task_has_separate_summary(self, _mock_ops): method test_summary_unaffected_by_searches (line 257) | def test_summary_unaffected_by_searches(self, _mock_ops): class TestClearReadTracker (line 266) | class TestClearReadTracker(unittest.TestCase): method setUp (line 269) | def setUp(self): method tearDown (line 272) | def tearDown(self): method test_clear_specific_task (line 276) | def test_clear_specific_task(self, _mock_ops): method test_clear_all (line 284) | def test_clear_all(self, _mock_ops): method test_clear_then_reread_no_warning (line 292) | def test_clear_then_reread_no_warning(self, _mock_ops): class TestSearchLoopDetection (line 301) | class TestSearchLoopDetection(unittest.TestCase): method setUp (line 304) | def setUp(self): method tearDown (line 307) | def tearDown(self): method test_first_search_no_warning (line 311) | def test_first_search_no_warning(self, _mock_ops): method test_second_consecutive_search_no_warning (line 317) | def test_second_consecutive_search_no_warning(self, _mock_ops): method test_third_consecutive_search_has_warning (line 325) | def test_third_consecutive_search_has_warning(self, _mock_ops): method test_fourth_consecutive_search_is_blocked (line 336) | def test_fourth_consecutive_search_is_blocked(self, _mock_ops): method test_different_pattern_resets_consecutive (line 346) | def test_different_pattern_resets_consecutive(self, _mock_ops): method test_different_task_isolated (line 355) | def test_different_task_isolated(self, _mock_ops): method test_other_tool_resets_search_consecutive (line 362) | def test_other_tool_resets_search_consecutive(self, _mock_ops): method test_pagination_offset_does_not_count_as_repeat (line 372) | def test_pagination_offset_does_not_count_as_repeat(self, _mock_ops): method test_read_between_searches_resets_consecutive (line 380) | def test_read_between_searches_resets_consecutive(self, _mock_ops): class TestTodoInjectionFiltering (line 391) | class TestTodoInjectionFiltering(unittest.TestCase): method test_filters_completed_and_cancelled (line 394) | def test_filters_completed_and_cancelled(self): method test_all_completed_returns_none (line 409) | def test_all_completed_returns_none(self): method test_empty_store_returns_none (line 418) | def test_empty_store_returns_none(self): method test_all_active_included (line 423) | def test_all_active_included(self): FILE: tests/tools/test_registry.py function _dummy_handler (line 8) | def _dummy_handler(args, **kwargs): function _make_schema (line 12) | def _make_schema(name="test_tool"): class TestRegisterAndDispatch (line 20) | class TestRegisterAndDispatch: method test_register_and_dispatch (line 21) | def test_register_and_dispatch(self): method test_dispatch_passes_args (line 32) | def test_dispatch_passes_args(self): class TestGetDefinitions (line 48) | class TestGetDefinitions: method test_returns_openai_format (line 49) | def test_returns_openai_format(self): method test_skips_unavailable_tools (line 64) | def test_skips_unavailable_tools(self): class TestUnknownToolDispatch (line 85) | class TestUnknownToolDispatch: method test_returns_error_json (line 86) | def test_returns_error_json(self): class TestToolsetAvailability (line 93) | class TestToolsetAvailability: method test_no_check_fn_is_available (line 94) | def test_no_check_fn_is_available(self): method test_check_fn_controls_availability (line 101) | def test_check_fn_controls_availability(self): method test_check_toolset_requirements (line 112) | def test_check_toolset_requirements(self): method test_get_all_tool_names (line 133) | def test_get_all_tool_names(self): method test_handler_exception_returns_error (line 143) | def test_handler_exception_returns_error(self): class TestCheckFnExceptionHandling (line 157) | class TestCheckFnExceptionHandling: method test_is_toolset_available_catches_exception (line 160) | def test_is_toolset_available_catches_exception(self): method test_check_toolset_requirements_survives_raising_check (line 172) | def test_check_toolset_requirements_survives_raising_check(self): method test_get_definitions_skips_raising_check (line 193) | def test_get_definitions_skips_raising_check(self): method test_check_tool_availability_survives_raising_check (line 213) | def test_check_tool_availability_survives_raising_check(self): class TestEmojiMetadata (line 235) | class TestEmojiMetadata: method test_emoji_stored_on_entry (line 238) | def test_emoji_stored_on_entry(self): method test_get_emoji_returns_registered (line 246) | def test_get_emoji_returns_registered(self): method test_get_emoji_returns_default_when_unset (line 254) | def test_get_emoji_returns_default_when_unset(self): method test_get_emoji_returns_default_for_unknown_tool (line 263) | def test_get_emoji_returns_default_for_unknown_tool(self): method test_emoji_empty_string_treated_as_unset (line 268) | def test_emoji_empty_string_treated_as_unset(self): class TestSecretCaptureResultContract (line 277) | class TestSecretCaptureResultContract: method test_secret_request_result_does_not_include_secret_value (line 278) | def test_secret_request_result_does_not_include_secret_value(self): FILE: tests/tools/test_rl_training_tool.py function _make_run_state (line 15) | def _make_run_state(**overrides) -> RunState: class TestStopTrainingRunFileHandles (line 26) | class TestStopTrainingRunFileHandles: method test_closes_all_log_file_handles (line 29) | def test_closes_all_log_file_handles(self): method test_clears_file_attrs_to_none (line 43) | def test_clears_file_attrs_to_none(self): method test_close_exception_does_not_propagate (line 51) | def test_close_exception_does_not_propagate(self): method test_handles_missing_file_attrs (line 65) | def test_handles_missing_file_attrs(self): class TestStopTrainingRunProcesses (line 72) | class TestStopTrainingRunProcesses: method test_terminates_running_processes (line 75) | def test_terminates_running_processes(self): method test_does_not_terminate_exited_processes (line 87) | def test_does_not_terminate_exited_processes(self): method test_handles_none_processes (line 97) | def test_handles_none_processes(self): method test_handles_mixed_running_and_exited_processes (line 102) | def test_handles_mixed_running_and_exited_processes(self): class TestStopTrainingRunStatus (line 121) | class TestStopTrainingRunStatus: method test_sets_status_to_stopped_when_running (line 124) | def test_sets_status_to_stopped_when_running(self): method test_does_not_change_status_when_failed (line 129) | def test_does_not_change_status_when_failed(self): method test_does_not_change_status_when_pending (line 134) | def test_does_not_change_status_when_pending(self): method test_no_crash_with_no_processes_and_no_files (line 139) | def test_no_crash_with_no_processes_and_no_files(self): FILE: tests/tools/test_search_hidden_dirs.py function searchable_tree (line 23) | def searchable_tree(tmp_path): class TestFindExcludesHiddenDirs (line 45) | class TestFindExcludesHiddenDirs: method test_find_skips_hub_cache_files (line 48) | def test_find_skips_hub_cache_files(self, searchable_tree): method test_find_skips_git_internals (line 57) | def test_find_skips_git_internals(self, searchable_tree): method test_find_still_returns_visible_files (line 66) | def test_find_still_returns_visible_files(self, searchable_tree): class TestGrepExcludesHiddenDirs (line 75) | class TestGrepExcludesHiddenDirs: method test_grep_skips_hub_cache (line 78) | def test_grep_skips_hub_cache(self, searchable_tree): method test_grep_still_finds_visible_content (line 88) | def test_grep_still_finds_visible_content(self, searchable_tree): class TestRipgrepAlreadyExcludesHidden (line 97) | class TestRipgrepAlreadyExcludesHidden: method test_rg_skips_hub_by_default (line 104) | def test_rg_skips_hub_by_default(self, searchable_tree): method test_rg_finds_visible_content (line 117) | def test_rg_finds_visible_content(self, searchable_tree): class TestIgnoreFileWritten (line 126) | class TestIgnoreFileWritten: method test_write_index_cache_creates_ignore_file (line 129) | def test_write_index_cache_creates_ignore_file(self, tmp_path, monkeyp... method test_write_index_cache_does_not_overwrite_existing_ignore (line 149) | def test_write_index_cache_does_not_overwrite_existing_ignore( FILE: tests/tools/test_send_message_tool.py function _run_async_immediately (line 15) | def _run_async_immediately(coro): function _make_config (line 19) | def _make_config(): function _install_telegram_mock (line 27) | def _install_telegram_mock(monkeypatch, bot): class TestSendMessageTool (line 35) | class TestSendMessageTool: method test_cron_duplicate_target_is_skipped_and_explained (line 36) | def test_cron_duplicate_target_is_skipped_and_explained(self): method test_cron_different_target_still_sends (line 71) | def test_cron_different_target_still_sends(self): method test_cron_same_chat_different_thread_still_sends (line 109) | def test_cron_same_chat_different_thread_still_sends(self): method test_sends_to_explicit_telegram_topic_target (line 148) | def test_sends_to_explicit_telegram_topic_target(self): method test_resolved_telegram_topic_name_preserves_thread_id (line 177) | def test_resolved_telegram_topic_name_preserves_thread_id(self): method test_media_only_message_uses_placeholder_for_mirroring (line 206) | def test_media_only_message_uses_placeholder_for_mirroring(self): class TestSendTelegramMediaDelivery (line 242) | class TestSendTelegramMediaDelivery: method test_sends_text_then_photo_for_media_tag (line 243) | def test_sends_text_then_photo_for_media_tag(self, tmp_path, monkeypat... method test_sends_voice_for_ogg_with_voice_directive (line 273) | def test_sends_voice_for_ogg_with_voice_directive(self, tmp_path, monk... method test_sends_audio_for_mp3 (line 300) | def test_sends_audio_for_mp3(self, tmp_path, monkeypatch): method test_missing_media_returns_error_without_leaking_raw_tag (line 326) | def test_missing_media_returns_error_without_leaking_raw_tag(self, mon... class TestSendToPlatformChunking (line 355) | class TestSendToPlatformChunking: method test_long_message_is_chunked (line 356) | def test_long_message_is_chunked(self): method test_telegram_media_attaches_to_last_chunk (line 373) | def test_telegram_media_attaches_to_last_chunk(self): class TestSendToPlatformWhatsapp (line 401) | class TestSendToPlatformWhatsapp: method test_whatsapp_routes_via_local_bridge_sender (line 402) | def test_whatsapp_routes_via_local_bridge_sender(self): class TestSendTelegramHtmlDetection (line 420) | class TestSendTelegramHtmlDetection: method _make_bot (line 424) | def _make_bot(self): method test_html_message_uses_html_parse_mode (line 434) | def test_html_message_uses_html_parse_mode(self, monkeypatch): method test_plain_text_uses_markdown_v2 (line 447) | def test_plain_text_uses_markdown_v2(self, monkeypatch): method test_html_with_code_and_pre_tags (line 459) | def test_html_with_code_and_pre_tags(self, monkeypatch): method test_closing_tag_detected (line 469) | def test_closing_tag_detected(self, monkeypatch): method test_angle_brackets_in_math_not_detected (line 478) | def test_angle_brackets_in_math_not_detected(self, monkeypatch): method test_html_parse_failure_falls_back_to_plain (line 488) | def test_html_parse_failure_falls_back_to_plain(self, monkeypatch): FILE: tests/tools/test_session_search.py class TestSessionSearchSchema (line 20) | class TestSessionSearchSchema: method test_keeps_cross_session_recall_guidance_without_current_session_nudge (line 21) | def test_keeps_cross_session_recall_guidance_without_current_session_n... class TestFormatTimestamp (line 31) | class TestFormatTimestamp: method test_unix_float (line 32) | def test_unix_float(self): method test_unix_int (line 37) | def test_unix_int(self): method test_iso_string (line 42) | def test_iso_string(self): method test_none_returns_unknown (line 46) | def test_none_returns_unknown(self): method test_numeric_string (line 49) | def test_numeric_string(self): class TestFormatConversation (line 59) | class TestFormatConversation: method test_basic_messages (line 60) | def test_basic_messages(self): method test_tool_message (line 69) | def test_tool_message(self): method test_long_tool_output_truncated (line 76) | def test_long_tool_output_truncated(self): method test_assistant_with_tool_calls (line 83) | def test_assistant_with_tool_calls(self): method test_empty_messages (line 98) | def test_empty_messages(self): class TestTruncateAroundMatches (line 107) | class TestTruncateAroundMatches: method test_short_text_unchanged (line 108) | def test_short_text_unchanged(self): method test_long_text_truncated (line 113) | def test_long_text_truncated(self): method test_truncation_adds_markers (line 121) | def test_truncation_adds_markers(self): method test_no_match_takes_from_start (line 126) | def test_no_match_takes_from_start(self): method test_match_at_beginning (line 132) | def test_match_at_beginning(self): class TestSessionSearch (line 142) | class TestSessionSearch: method test_no_db_returns_error (line 143) | def test_no_db_returns_error(self): method test_empty_query_returns_error (line 149) | def test_empty_query_returns_error(self): method test_whitespace_query_returns_error (line 155) | def test_whitespace_query_returns_error(self): method test_current_session_excluded (line 161) | def test_current_session_excluded(self): method test_current_session_excluded_keeps_others (line 183) | def test_current_session_excluded_keeps_others(self): method test_current_child_session_excludes_parent_lineage (line 218) | def test_current_child_session_excludes_parent_lineage(self): method test_current_root_session_excludes_child_lineage (line 247) | def test_current_root_session_excludes_child_lineage(self): FILE: tests/tools/test_singularity_preflight.py class TestFindSingularityExecutable (line 20) | class TestFindSingularityExecutable: method test_prefers_apptainer (line 23) | def test_prefers_apptainer(self): method test_falls_back_to_singularity (line 31) | def test_falls_back_to_singularity(self): method test_raises_when_neither_found (line 39) | def test_raises_when_neither_found(self): class TestEnsureSingularityAvailable (line 46) | class TestEnsureSingularityAvailable: method test_returns_executable_on_success (line 49) | def test_returns_executable_on_success(self): method test_raises_on_version_failure (line 57) | def test_raises_on_version_failure(self): method test_raises_on_timeout (line 66) | def test_raises_on_timeout(self): method test_raises_when_not_installed (line 73) | def test_raises_when_not_installed(self): FILE: tests/tools/test_skill_manager_tool.py class TestValidateName (line 54) | class TestValidateName: method test_valid_names (line 55) | def test_valid_names(self): method test_empty_name (line 61) | def test_empty_name(self): method test_too_long (line 64) | def test_too_long(self): method test_uppercase_rejected (line 68) | def test_uppercase_rejected(self): method test_starts_with_hyphen_rejected (line 72) | def test_starts_with_hyphen_rejected(self): method test_special_chars_rejected (line 76) | def test_special_chars_rejected(self): class TestValidateFrontmatter (line 90) | class TestValidateFrontmatter: method test_valid_content (line 91) | def test_valid_content(self): method test_empty_content (line 94) | def test_empty_content(self): method test_no_frontmatter (line 98) | def test_no_frontmatter(self): method test_unclosed_frontmatter (line 102) | def test_unclosed_frontmatter(self): method test_missing_name_field (line 106) | def test_missing_name_field(self): method test_missing_description_field (line 110) | def test_missing_description_field(self): method test_no_body_after_frontmatter (line 114) | def test_no_body_after_frontmatter(self): method test_invalid_yaml (line 118) | def test_invalid_yaml(self): class TestValidateFilePath (line 128) | class TestValidateFilePath: method test_valid_paths (line 129) | def test_valid_paths(self): method test_empty_path (line 135) | def test_empty_path(self): method test_path_traversal_blocked (line 138) | def test_path_traversal_blocked(self): method test_disallowed_subdirectory (line 142) | def test_disallowed_subdirectory(self): method test_directory_only_rejected (line 147) | def test_directory_only_rejected(self): method test_root_level_file_rejected (line 152) | def test_root_level_file_rejected(self): class TestCreateSkill (line 163) | class TestCreateSkill: method test_create_skill (line 164) | def test_create_skill(self, tmp_path): method test_create_with_category (line 170) | def test_create_with_category(self, tmp_path): method test_create_duplicate_blocked (line 177) | def test_create_duplicate_blocked(self, tmp_path): method test_create_invalid_name (line 184) | def test_create_invalid_name(self, tmp_path): method test_create_invalid_content (line 189) | def test_create_invalid_content(self, tmp_path): class TestEditSkill (line 195) | class TestEditSkill: method test_edit_existing_skill (line 196) | def test_edit_existing_skill(self, tmp_path): method test_edit_nonexistent_skill (line 204) | def test_edit_nonexistent_skill(self, tmp_path): method test_edit_invalid_content_rejected (line 210) | def test_edit_invalid_content_rejected(self, tmp_path): class TestPatchSkill (line 220) | class TestPatchSkill: method test_patch_unique_match (line 221) | def test_patch_unique_match(self, tmp_path): method test_patch_nonexistent_string (line 229) | def test_patch_nonexistent_string(self, tmp_path): method test_patch_ambiguous_match_rejected (line 236) | def test_patch_ambiguous_match_rejected(self, tmp_path): method test_patch_replace_all (line 253) | def test_patch_replace_all(self, tmp_path): method test_patch_supporting_file (line 269) | def test_patch_supporting_file(self, tmp_path): method test_patch_skill_not_found (line 276) | def test_patch_skill_not_found(self, tmp_path): class TestDeleteSkill (line 282) | class TestDeleteSkill: method test_delete_existing (line 283) | def test_delete_existing(self, tmp_path): method test_delete_nonexistent (line 290) | def test_delete_nonexistent(self, tmp_path): method test_delete_cleans_empty_category_dir (line 295) | def test_delete_cleans_empty_category_dir(self, tmp_path): class TestWriteFile (line 307) | class TestWriteFile: method test_write_reference_file (line 308) | def test_write_reference_file(self, tmp_path): method test_write_to_nonexistent_skill (line 315) | def test_write_to_nonexistent_skill(self, tmp_path): method test_write_to_disallowed_path (line 320) | def test_write_to_disallowed_path(self, tmp_path): class TestRemoveFile (line 327) | class TestRemoveFile: method test_remove_existing_file (line 328) | def test_remove_existing_file(self, tmp_path): method test_remove_nonexistent_file (line 336) | def test_remove_nonexistent_file(self, tmp_path): class TestSkillManageDispatcher (line 348) | class TestSkillManageDispatcher: method test_unknown_action (line 349) | def test_unknown_action(self, tmp_path): method test_create_without_content (line 356) | def test_create_without_content(self, tmp_path): method test_patch_without_old_string (line 363) | def test_patch_without_old_string(self, tmp_path): method test_full_create_via_dispatcher (line 369) | def test_full_create_via_dispatcher(self, tmp_path): FILE: tests/tools/test_skill_view_path_check.py function _path_escapes_skill_dir (line 13) | def _path_escapes_skill_dir(resolved: Path, skill_dir_resolved: Path) ->... class TestSkillViewPathBoundaryCheck (line 21) | class TestSkillViewPathBoundaryCheck: method test_valid_subpath_allowed (line 24) | def test_valid_subpath_allowed(self, tmp_path): method test_deeply_nested_subpath_allowed (line 37) | def test_deeply_nested_subpath_allowed(self, tmp_path): method test_outside_path_blocked (line 50) | def test_outside_path_blocked(self, tmp_path): method test_sibling_skill_dir_blocked (line 62) | def test_sibling_skill_dir_blocked(self, tmp_path): method test_skill_dir_itself_allowed (line 80) | def test_skill_dir_itself_allowed(self, tmp_path): class TestOldCheckWouldFail (line 91) | class TestOldCheckWouldFail: method _old_path_escapes (line 94) | def _old_path_escapes(self, resolved: Path, skill_dir_resolved: Path) ... method test_old_check_false_positive_on_windows (line 102) | def test_old_check_false_positive_on_windows(self, tmp_path): FILE: tests/tools/test_skill_view_traversal.py function fake_skills (line 16) | def fake_skills(tmp_path): class TestPathTraversalBlocked (line 37) | class TestPathTraversalBlocked: method test_dotdot_in_file_path (line 38) | def test_dotdot_in_file_path(self, fake_skills): method test_dotdot_nested (line 44) | def test_dotdot_nested(self, fake_skills): method test_legitimate_file_still_works (line 50) | def test_legitimate_file_still_works(self, fake_skills): method test_no_file_path_shows_skill (line 56) | def test_no_file_path_shows_skill(self, fake_skills): method test_symlink_escape_blocked (line 61) | def test_symlink_escape_blocked(self, fake_skills): method test_sensitive_file_not_leaked (line 78) | def test_sensitive_file_not_leaked(self, fake_skills): FILE: tests/tools/test_skills_guard.py function _can_symlink (line 11) | def _can_symlink(): class TestResolveTrustLevel (line 48) | class TestResolveTrustLevel: method test_official_sources_resolve_to_builtin (line 49) | def test_official_sources_resolve_to_builtin(self): method test_trusted_repos (line 53) | def test_trusted_repos(self): method test_community_default (line 58) | def test_community_default(self): class TestDetermineVerdict (line 68) | class TestDetermineVerdict: method test_no_findings_safe (line 69) | def test_no_findings_safe(self): method test_critical_finding_dangerous (line 72) | def test_critical_finding_dangerous(self): method test_high_finding_caution (line 76) | def test_high_finding_caution(self): method test_medium_finding_caution (line 80) | def test_medium_finding_caution(self): method test_low_finding_caution (line 84) | def test_low_finding_caution(self): class TestShouldAllowInstall (line 94) | class TestShouldAllowInstall: method _result (line 95) | def _result(self, trust, verdict, findings=None): method test_safe_community_allowed (line 104) | def test_safe_community_allowed(self): method test_caution_community_blocked (line 108) | def test_caution_community_blocked(self): method test_caution_trusted_allowed (line 114) | def test_caution_trusted_allowed(self): method test_trusted_dangerous_blocked_without_force (line 119) | def test_trusted_dangerous_blocked_without_force(self): method test_builtin_dangerous_allowed_without_force (line 124) | def test_builtin_dangerous_allowed_without_force(self): method test_force_overrides_caution (line 130) | def test_force_overrides_caution(self): method test_dangerous_blocked_without_force (line 136) | def test_dangerous_blocked_without_force(self): method test_force_overrides_dangerous_for_community (line 141) | def test_force_overrides_dangerous_for_community(self): method test_force_overrides_dangerous_for_trusted (line 149) | def test_force_overrides_dangerous_for_trusted(self): method test_safe_agent_created_allowed (line 159) | def test_safe_agent_created_allowed(self): method test_caution_agent_created_allowed (line 163) | def test_caution_agent_created_allowed(self): method test_dangerous_agent_created_blocked (line 170) | def test_dangerous_agent_created_blocked(self): method test_force_overrides_dangerous_for_agent_created (line 177) | def test_force_overrides_dangerous_for_agent_created(self): class TestScanFile (line 191) | class TestScanFile: method test_safe_file (line 192) | def test_safe_file(self, tmp_path): method test_detect_curl_env_exfil (line 198) | def test_detect_curl_env_exfil(self, tmp_path): method test_detect_prompt_injection (line 204) | def test_detect_prompt_injection(self, tmp_path): method test_detect_rm_rf_root (line 210) | def test_detect_rm_rf_root(self, tmp_path): method test_detect_reverse_shell (line 216) | def test_detect_reverse_shell(self, tmp_path): method test_detect_invisible_unicode (line 222) | def test_detect_invisible_unicode(self, tmp_path): method test_nonscannable_extension_skipped (line 228) | def test_nonscannable_extension_skipped(self, tmp_path): method test_detect_hardcoded_secret (line 234) | def test_detect_hardcoded_secret(self, tmp_path): method test_detect_eval_string (line 240) | def test_detect_eval_string(self, tmp_path): method test_deduplication_per_pattern_per_line (line 246) | def test_deduplication_per_pattern_per_line(self, tmp_path): class TestScanSkill (line 260) | class TestScanSkill: method test_safe_skill (line 261) | def test_safe_skill(self, tmp_path): method test_dangerous_skill (line 273) | def test_dangerous_skill(self, tmp_path): method test_trusted_source (line 283) | def test_trusted_source(self, tmp_path): method test_single_file_scan (line 291) | def test_single_file_scan(self, tmp_path): class TestCheckStructure (line 305) | class TestCheckStructure: method test_too_many_files (line 306) | def test_too_many_files(self, tmp_path): method test_oversized_single_file (line 312) | def test_oversized_single_file(self, tmp_path): method test_binary_file_detected (line 318) | def test_binary_file_detected(self, tmp_path): method test_symlink_escape (line 324) | def test_symlink_escape(self, tmp_path): method test_symlink_prefix_confusion_blocked (line 336) | def test_symlink_prefix_confusion_blocked(self, tmp_path): method test_symlink_within_skill_dir_allowed (line 360) | def test_symlink_within_skill_dir_allowed(self, tmp_path): method test_clean_structure (line 372) | def test_clean_structure(self, tmp_path): class TestFormatScanReport (line 384) | class TestFormatScanReport: method test_clean_report (line 385) | def test_clean_report(self): method test_dangerous_report (line 392) | def test_dangerous_report(self): class TestContentHash (line 406) | class TestContentHash: method test_hash_directory (line 407) | def test_hash_directory(self, tmp_path): method test_hash_single_file (line 414) | def test_hash_single_file(self, tmp_path): method test_hash_deterministic (line 420) | def test_hash_deterministic(self, tmp_path): method test_hash_changes_with_content (line 426) | def test_hash_changes_with_content(self, tmp_path): class TestUnicodeCharName (line 440) | class TestUnicodeCharName: method test_known_chars (line 441) | def test_known_chars(self): method test_unknown_char (line 445) | def test_unknown_char(self): class TestSymlinkPrefixConfusionRegression (line 455) | class TestSymlinkPrefixConfusionRegression: method test_old_startswith_misses_prefix_confusion (line 464) | def test_old_startswith_misses_prefix_confusion(self, tmp_path): method test_is_relative_to_catches_prefix_confusion (line 479) | def test_is_relative_to_catches_prefix_confusion(self, tmp_path): method test_legitimate_subpath_passes_both (line 494) | def test_legitimate_subpath_passes_both(self, tmp_path): FILE: tests/tools/test_skills_hub.py class TestParseFrontmatterQuick (line 33) | class TestParseFrontmatterQuick: method test_valid_frontmatter (line 34) | def test_valid_frontmatter(self): method test_no_frontmatter (line 40) | def test_no_frontmatter(self): method test_no_closing_delimiter (line 45) | def test_no_closing_delimiter(self): method test_empty_content (line 50) | def test_empty_content(self): method test_nested_yaml (line 54) | def test_nested_yaml(self): method test_invalid_yaml_returns_empty (line 59) | def test_invalid_yaml_returns_empty(self): method test_non_dict_yaml_returns_empty (line 64) | def test_non_dict_yaml_returns_empty(self): class TestTrustLevelFor (line 75) | class TestTrustLevelFor: method _source (line 76) | def _source(self): method test_trusted_repo (line 80) | def test_trusted_repo(self): method test_community_repo (line 88) | def test_community_repo(self): method test_short_identifier (line 92) | def test_short_identifier(self): method test_two_part_identifier (line 96) | def test_two_part_identifier(self): class TestSkillsShSource (line 108) | class TestSkillsShSource: method _source (line 109) | def _source(self): method test_search_maps_skills_sh_results_to_prefixed_identifiers (line 116) | def test_search_maps_skills_sh_results_to_prefixed_identifiers(self, m... method test_empty_search_uses_featured_homepage_links (line 145) | def test_empty_search_uses_featured_homepage_links(self, mock_get, _mo... method test_fetch_delegates_to_github_source_and_relabels_bundle (line 164) | def test_fetch_delegates_to_github_source_and_relabels_bundle(self, mo... method test_inspect_delegates_to_github_source_and_relabels_meta (line 184) | def test_inspect_delegates_to_github_source_and_relabels_meta(self, mo... method test_inspect_falls_back_to_repo_skill_catalog_when_slug_differs (line 216) | def test_inspect_falls_back_to_repo_skill_catalog_when_slug_differs(se... method test_inspect_uses_detail_page_to_resolve_alias_skill (line 240) | def test_inspect_uses_detail_page_to_resolve_alias_skill(self, mock_in... method test_fetch_uses_detail_page_to_resolve_alias_skill (line 273) | def test_fetch_uses_detail_page_to_resolve_alias_skill(self, mock_fetc... class TestWellKnownSkillSource (line 309) | class TestWellKnownSkillSource: method _source (line 310) | def _source(self): method test_search_reads_index_from_well_known_url (line 316) | def test_search_reads_index_from_well_known_url(self, mock_get, _mock_... method test_search_accepts_domain_root_and_resolves_index (line 338) | def test_search_accepts_domain_root_and_resolves_index(self, mock_get,... method test_inspect_fetches_skill_md_from_well_known_endpoint (line 353) | def test_inspect_fetches_skill_md_from_well_known_endpoint(self, mock_... method test_fetch_downloads_skill_files_from_well_known_endpoint (line 375) | def test_fetch_downloads_skill_files_from_well_known_endpoint(self, mo... class TestCheckForSkillUpdates (line 401) | class TestCheckForSkillUpdates: method test_bundle_content_hash_matches_installed_content_hash (line 402) | def test_bundle_content_hash_matches_installed_content_hash(self, tmp_... method test_reports_update_when_remote_hash_differs (line 423) | def test_reports_update_when_remote_hash_differs(self): method test_reports_up_to_date_when_hash_matches (line 449) | def test_reports_up_to_date_when_hash_matches(self): class TestCreateSourceRouter (line 474) | class TestCreateSourceRouter: method test_includes_skills_sh_source (line 475) | def test_includes_skills_sh_source(self): method test_includes_well_known_source (line 479) | def test_includes_well_known_source(self): class TestHubLockFile (line 489) | class TestHubLockFile: method test_load_missing_file (line 490) | def test_load_missing_file(self, tmp_path): method test_load_valid_file (line 495) | def test_load_valid_file(self, tmp_path): method test_load_corrupt_json (line 505) | def test_load_corrupt_json(self, tmp_path): method test_save_creates_parent_dir (line 512) | def test_save_creates_parent_dir(self, tmp_path): method test_record_install (line 518) | def test_record_install(self, tmp_path): method test_record_uninstall (line 538) | def test_record_uninstall(self, tmp_path): method test_record_uninstall_nonexistent (line 549) | def test_record_uninstall_nonexistent(self, tmp_path): method test_get_installed (line 555) | def test_get_installed(self, tmp_path): method test_list_installed (line 565) | def test_list_installed(self, tmp_path): method test_is_hub_installed (line 582) | def test_is_hub_installed(self, tmp_path): class TestTapsManager (line 598) | class TestTapsManager: method test_load_missing_file (line 599) | def test_load_missing_file(self, tmp_path): method test_load_valid_file (line 603) | def test_load_valid_file(self, tmp_path): method test_load_corrupt_json (line 611) | def test_load_corrupt_json(self, tmp_path): method test_add_new_tap (line 617) | def test_add_new_tap(self, tmp_path): method test_add_duplicate_tap (line 624) | def test_add_duplicate_tap(self, tmp_path): method test_remove_existing_tap (line 630) | def test_remove_existing_tap(self, tmp_path): method test_remove_nonexistent_tap (line 636) | def test_remove_nonexistent_tap(self, tmp_path): method test_list_taps (line 640) | def test_list_taps(self, tmp_path): class TestConvertToSkillMd (line 653) | class TestConvertToSkillMd: method test_basic_conversion (line 654) | def test_basic_conversion(self): method test_missing_system_role (line 674) | def test_missing_system_role(self): method test_missing_meta (line 682) | def test_missing_meta(self): class TestUnifiedSearchDedup (line 693) | class TestUnifiedSearchDedup: method _make_source (line 694) | def _make_source(self, source_id, results): method test_dedup_keeps_first_seen (line 701) | def test_dedup_keeps_first_seen(self): method test_dedup_prefers_trusted_over_community (line 712) | def test_dedup_prefers_trusted_over_community(self): method test_dedup_prefers_builtin_over_trusted (line 723) | def test_dedup_prefers_builtin_over_trusted(self): method test_dedup_trusted_not_overwritten_by_community (line 735) | def test_dedup_trusted_not_overwritten_by_community(self): method test_source_filter (line 745) | def test_source_filter(self): method test_limit_respected (line 756) | def test_limit_respected(self): method test_source_error_handled (line 766) | def test_source_error_handled(self): class TestAppendAuditLog (line 783) | class TestAppendAuditLog: method test_creates_log_entry (line 784) | def test_creates_log_entry(self, tmp_path): method test_appends_multiple_entries (line 794) | def test_appends_multiple_entries(self, tmp_path): method test_extra_field_included (line 802) | def test_extra_field_included(self, tmp_path): class TestSkillMetaToDict (line 815) | class TestSkillMetaToDict: method test_roundtrip (line 816) | def test_roundtrip(self): class TestOptionalSkillSourceBinaryAssets (line 836) | class TestOptionalSkillSourceBinaryAssets: method test_fetch_preserves_binary_assets (line 837) | def test_fetch_preserves_binary_assets(self, tmp_path): class TestQuarantineBundleBinaryAssets (line 867) | class TestQuarantineBundleBinaryAssets: method test_quarantine_bundle_writes_binary_files (line 868) | def test_quarantine_bundle_writes_binary_files(self, tmp_path): FILE: tests/tools/test_skills_hub_clawhub.py class _MockResponse (line 9) | class _MockResponse: method __init__ (line 10) | def __init__(self, status_code=200, json_data=None, text=""): method json (line 15) | def json(self): class TestClawHubSource (line 19) | class TestClawHubSource(unittest.TestCase): method setUp (line 20) | def setUp(self): method test_search_uses_listing_endpoint_as_fallback (line 27) | def test_search_uses_listing_endpoint_as_fallback( method test_search_falls_back_to_exact_slug_when_search_results_are_irrelevant (line 71) | def test_search_falls_back_to_exact_slug_when_search_results_are_irrel... method test_search_repairs_poisoned_cache_with_exact_slug_lookup (line 113) | def test_search_repairs_poisoned_cache_with_exact_slug_lookup(self, mo... method test_search_matches_space_separated_query_to_hyphenated_slug (line 156) | def test_search_matches_space_separated_query_to_hyphenated_slug( method test_inspect_maps_display_name_and_summary (line 165) | def test_inspect_maps_display_name_and_summary(self, mock_get): method test_inspect_handles_nested_skill_payload (line 184) | def test_inspect_handles_nested_skill_payload(self, mock_get): method test_fetch_resolves_latest_version_and_downloads_raw_files (line 207) | def test_fetch_resolves_latest_version_and_downloads_raw_files(self, m... method test_fetch_falls_back_to_versions_list (line 242) | def test_fetch_falls_back_to_versions_list(self, mock_get): FILE: tests/tools/test_skills_sync.py class TestReadWriteManifest (line 18) | class TestReadWriteManifest: method test_read_missing_manifest (line 19) | def test_read_missing_manifest(self, tmp_path): method test_write_and_read_roundtrip_v2 (line 27) | def test_write_and_read_roundtrip_v2(self, tmp_path): method test_write_manifest_sorted (line 37) | def test_write_manifest_sorted(self, tmp_path): method test_read_v1_manifest_migration (line 48) | def test_read_v1_manifest_migration(self, tmp_path): method test_read_manifest_ignores_blank_lines (line 58) | def test_read_manifest_ignores_blank_lines(self, tmp_path): method test_read_manifest_mixed_v1_v2 (line 67) | def test_read_manifest_mixed_v1_v2(self, tmp_path): class TestDirHash (line 78) | class TestDirHash: method test_same_content_same_hash (line 79) | def test_same_content_same_hash(self, tmp_path): method test_different_content_different_hash (line 88) | def test_different_content_different_hash(self, tmp_path): method test_empty_dir (line 97) | def test_empty_dir(self, tmp_path): method test_nonexistent_dir (line 103) | def test_nonexistent_dir(self, tmp_path): class TestDiscoverBundledSkills (line 108) | class TestDiscoverBundledSkills: method test_finds_skills_with_skill_md (line 109) | def test_finds_skills_with_skill_md(self, tmp_path): method test_ignores_git_directories (line 123) | def test_ignores_git_directories(self, tmp_path): method test_nonexistent_dir_returns_empty (line 129) | def test_nonexistent_dir_returns_empty(self, tmp_path): class TestComputeRelativeDest (line 134) | class TestComputeRelativeDest: method test_preserves_category_structure (line 135) | def test_preserves_category_structure(self): method test_flat_skill (line 141) | def test_flat_skill(self): class TestSyncSkills (line 148) | class TestSyncSkills: method _setup_bundled (line 149) | def _setup_bundled(self, tmp_path): method _patches (line 160) | def _patches(self, bundled, skills_dir, manifest_file): method test_fresh_install_copies_all (line 169) | def test_fresh_install_copies_all(self, tmp_path): method test_fresh_install_records_origin_hashes (line 186) | def test_fresh_install_records_origin_hashes(self, tmp_path): method test_user_deleted_skill_not_re_added (line 202) | def test_user_deleted_skill_not_re_added(self, tmp_path): method test_unmodified_skill_gets_updated (line 220) | def test_unmodified_skill_gets_updated(self, tmp_path): method test_user_modified_skill_not_overwritten (line 243) | def test_user_modified_skill_not_overwritten(self, tmp_path): method test_unchanged_skill_not_updated (line 269) | def test_unchanged_skill_not_updated(self, tmp_path): method test_v1_manifest_migration_sets_baseline (line 289) | def test_v1_manifest_migration_sets_baseline(self, tmp_path): method test_v1_migration_then_bundled_update_detected (line 313) | def test_v1_migration_then_bundled_update_detected(self, tmp_path): method test_stale_manifest_entries_cleaned (line 340) | def test_stale_manifest_entries_cleaned(self, tmp_path): method test_does_not_overwrite_existing_unmanifested_skill (line 356) | def test_does_not_overwrite_existing_unmanifested_skill(self, tmp_path): method test_nonexistent_bundled_dir (line 371) | def test_nonexistent_bundled_dir(self, tmp_path): method test_failed_copy_does_not_poison_manifest (line 379) | def test_failed_copy_does_not_poison_manifest(self, tmp_path): method test_failed_update_does_not_destroy_user_copy (line 415) | def test_failed_update_does_not_destroy_user_copy(self, tmp_path): method test_update_records_new_origin_hash (line 449) | def test_update_records_new_origin_hash(self, tmp_path): FILE: tests/tools/test_skills_tool.py function _make_skill (line 26) | def _make_skill( class TestParseFrontmatter (line 54) | class TestParseFrontmatter: method test_valid_frontmatter (line 55) | def test_valid_frontmatter(self): method test_no_frontmatter (line 62) | def test_no_frontmatter(self): method test_empty_frontmatter (line 68) | def test_empty_frontmatter(self): method test_nested_yaml (line 73) | def test_nested_yaml(self): method test_malformed_yaml_fallback (line 80) | def test_malformed_yaml_fallback(self): class TestParseTags (line 93) | class TestParseTags: method test_list_input (line 94) | def test_list_input(self): method test_comma_separated_string (line 97) | def test_comma_separated_string(self): method test_bracket_wrapped_string (line 100) | def test_bracket_wrapped_string(self): method test_empty_input (line 103) | def test_empty_input(self): method test_strips_quotes (line 108) | def test_strips_quotes(self): method test_filters_empty_items (line 113) | def test_filters_empty_items(self): class TestRequiredEnvironmentVariablesNormalization (line 117) | class TestRequiredEnvironmentVariablesNormalization: method test_parses_new_required_environment_variables_metadata (line 118) | def test_parses_new_required_environment_variables_metadata(self): method test_normalizes_legacy_prerequisites_env_vars (line 141) | def test_normalizes_legacy_prerequisites_env_vars(self): method test_empty_env_file_value_is_treated_as_missing (line 153) | def test_empty_env_file_value_is_treated_as_missing(self, monkeypatch): class TestGetCategoryFromPath (line 172) | class TestGetCategoryFromPath: method test_categorized_skill (line 173) | def test_categorized_skill(self, tmp_path): method test_uncategorized_skill (line 180) | def test_uncategorized_skill(self, tmp_path): method test_outside_skills_dir (line 187) | def test_outside_skills_dir(self, tmp_path): class TestEstimateTokens (line 198) | class TestEstimateTokens: method test_estimate (line 199) | def test_estimate(self): class TestFindAllSkills (line 210) | class TestFindAllSkills: method test_finds_skills (line 211) | def test_finds_skills(self, tmp_path): method test_empty_directory (line 221) | def test_empty_directory(self, tmp_path): method test_nonexistent_directory (line 226) | def test_nonexistent_directory(self, tmp_path): method test_categorized_skills (line 231) | def test_categorized_skills(self, tmp_path): method test_description_from_body_when_missing (line 238) | def test_description_from_body_when_missing(self, tmp_path): method test_long_description_truncated (line 249) | def test_long_description_truncated(self, tmp_path): method test_skips_git_directories (line 260) | def test_skips_git_directories(self, tmp_path): class TestSkillsList (line 278) | class TestSkillsList: method test_empty_creates_directory (line 279) | def test_empty_creates_directory(self, tmp_path): method test_lists_skills (line 288) | def test_lists_skills(self, tmp_path): method test_category_filter (line 296) | def test_category_filter(self, tmp_path): class TestSkillView (line 311) | class TestSkillView: method test_view_existing_skill (line 312) | def test_view_existing_skill(self, tmp_path): method test_view_nonexistent_skill (line 321) | def test_view_nonexistent_skill(self, tmp_path): method test_view_reference_file (line 330) | def test_view_reference_file(self, tmp_path): method test_view_nonexistent_file (line 341) | def test_view_nonexistent_file(self, tmp_path): method test_view_shows_linked_files (line 348) | def test_view_shows_linked_files(self, tmp_path): method test_view_tags_from_metadata (line 359) | def test_view_tags_from_metadata(self, tmp_path): method test_view_nonexistent_skills_dir (line 371) | def test_view_nonexistent_skills_dir(self, tmp_path): method test_view_disabled_skill_blocked (line 377) | def test_view_disabled_skill_blocked(self, tmp_path): method test_view_enabled_skill_allowed (line 392) | def test_view_enabled_skill_allowed(self, tmp_path): class TestSkillViewSecureSetupOnLoad (line 407) | class TestSkillViewSecureSetupOnLoad: method test_requests_missing_required_env_and_continues (line 408) | def test_requests_missing_required_env_and_continues(self, tmp_path, m... method test_allows_skipping_secure_setup_and_still_loads (line 466) | def test_allows_skipping_secure_setup_and_still_loads(self, tmp_path, ... method test_gateway_load_returns_guidance_without_secret_capture (line 501) | def test_gateway_load_returns_guidance_without_secret_capture( class TestSkillsCategories (line 552) | class TestSkillsCategories: method test_lists_categories (line 553) | def test_lists_categories(self, tmp_path): method test_empty_skills_dir (line 564) | def test_empty_skills_dir(self, tmp_path): class TestSkillMatchesPlatform (line 578) | class TestSkillMatchesPlatform: method test_no_platforms_field_matches_everything (line 581) | def test_no_platforms_field_matches_everything(self): method test_empty_platforms_matches_everything (line 586) | def test_empty_platforms_matches_everything(self): method test_macos_on_darwin (line 591) | def test_macos_on_darwin(self): method test_macos_on_linux (line 596) | def test_macos_on_linux(self): method test_linux_on_linux (line 601) | def test_linux_on_linux(self): method test_linux_on_darwin (line 606) | def test_linux_on_darwin(self): method test_windows_on_win32 (line 611) | def test_windows_on_win32(self): method test_windows_on_linux (line 616) | def test_windows_on_linux(self): method test_multi_platform_match (line 621) | def test_multi_platform_match(self): method test_string_instead_of_list (line 631) | def test_string_instead_of_list(self): method test_case_insensitive (line 639) | def test_case_insensitive(self): method test_unknown_platform_no_match (line 645) | def test_unknown_platform_no_match(self): class TestFindAllSkillsPlatformFiltering (line 656) | class TestFindAllSkillsPlatformFiltering: method test_excludes_incompatible_platform (line 659) | def test_excludes_incompatible_platform(self, tmp_path): method test_includes_matching_platform (line 672) | def test_includes_matching_platform(self, tmp_path): method test_no_platforms_always_included (line 683) | def test_no_platforms_always_included(self, tmp_path): method test_multi_platform_skill (line 695) | def test_multi_platform_skill(self, tmp_path): class TestFindAllSkillsSecureSetup (line 719) | class TestFindAllSkillsSecureSetup: method test_skills_with_missing_env_vars_remain_listed (line 720) | def test_skills_with_missing_env_vars_remain_listed(self, tmp_path, mo... method test_skills_with_met_prereqs_have_same_listing_shape (line 734) | def test_skills_with_met_prereqs_have_same_listing_shape( method test_skills_without_prereqs_have_same_listing_shape (line 749) | def test_skills_without_prereqs_have_same_listing_shape(self, tmp_path): method test_skill_listing_does_not_probe_backend_for_env_vars (line 757) | def test_skill_listing_does_not_probe_backend_for_env_vars( class TestSkillViewPrerequisites (line 779) | class TestSkillViewPrerequisites: method test_legacy_prerequisites_expose_required_env_setup_metadata (line 780) | def test_legacy_prerequisites_expose_required_env_setup_metadata( method test_no_setup_needed_when_legacy_prereqs_are_met (line 802) | def test_no_setup_needed_when_legacy_prereqs_are_met(self, tmp_path, m... method test_no_setup_metadata_when_no_required_envs (line 816) | def test_no_setup_metadata_when_no_required_envs(self, tmp_path): method test_skill_view_treats_backend_only_env_as_setup_needed (line 825) | def test_skill_view_treats_backend_only_env_as_setup_needed( method test_local_env_missing_keeps_setup_needed (line 842) | def test_local_env_missing_keeps_setup_needed(self, tmp_path, monkeypa... method test_gateway_load_keeps_setup_guidance_for_backend_only_env (line 860) | def test_gateway_load_keeps_setup_guidance_for_backend_only_env( method test_remote_backend_keeps_setup_needed_after_local_secret_capture (line 890) | def test_remote_backend_keeps_setup_needed_after_local_secret_capture( method test_skill_view_surfaces_skill_read_errors (line 934) | def test_skill_view_surfaces_skill_read_errors(self, tmp_path, monkeyp... method test_legacy_flat_md_skill_preserves_frontmatter_metadata (line 954) | def test_legacy_flat_md_skill_preserves_frontmatter_metadata(self, tmp... method test_successful_secret_capture_reloads_empty_env_placeholder (line 988) | def test_successful_secret_capture_reloads_empty_env_placeholder( FILE: tests/tools/test_ssh_environment.py function _run (line 26) | def _run(command, task_id="ssh_test", **kwargs): function _cleanup (line 31) | def _cleanup(task_id="ssh_test"): class TestBuildSSHCommand (line 36) | class TestBuildSSHCommand: method _mock_connection (line 39) | def _mock_connection(self, monkeypatch): method test_base_flags (line 48) | def test_base_flags(self): method test_custom_port (line 55) | def test_custom_port(self): method test_key_path (line 60) | def test_key_path(self): method test_user_host_suffix (line 65) | def test_user_host_suffix(self): class TestTerminalToolConfig (line 70) | class TestTerminalToolConfig: method test_ssh_persistent_default_true (line 71) | def test_ssh_persistent_default_true(self, monkeypatch): method test_ssh_persistent_explicit_false (line 78) | def test_ssh_persistent_explicit_false(self, monkeypatch): method test_ssh_persistent_explicit_true (line 84) | def test_ssh_persistent_explicit_true(self, monkeypatch): method test_ssh_persistent_respects_config (line 89) | def test_ssh_persistent_respects_config(self, monkeypatch): class TestSSHPreflight (line 97) | class TestSSHPreflight: method test_ensure_ssh_available_raises_clear_error_when_missing (line 98) | def test_ensure_ssh_available_raises_clear_error_when_missing(self, mo... method test_ssh_environment_checks_availability_before_connect (line 104) | def test_ssh_environment_checks_availability_before_connect(self, monk... method test_ssh_environment_connects_when_ssh_exists (line 115) | def test_ssh_environment_connects_when_ssh_exists(self, monkeypatch): function _setup_ssh_env (line 132) | def _setup_ssh_env(monkeypatch, persistent: bool): class TestOneShotSSH (line 144) | class TestOneShotSSH: method _setup (line 147) | def _setup(self, monkeypatch): method test_echo (line 152) | def test_echo(self): method test_exit_code (line 157) | def test_exit_code(self): method test_state_does_not_persist (line 161) | def test_state_does_not_persist(self): class TestPersistentSSH (line 168) | class TestPersistentSSH: method _setup (line 171) | def _setup(self, monkeypatch): method test_echo (line 176) | def test_echo(self): method test_env_var_persists (line 181) | def test_env_var_persists(self): method test_cwd_persists (line 186) | def test_cwd_persists(self): method test_exit_code (line 191) | def test_exit_code(self): method test_stderr (line 195) | def test_stderr(self): method test_multiline_output (line 200) | def test_multiline_output(self): method test_timeout_then_recovery (line 205) | def test_timeout_then_recovery(self): method test_large_output (line 212) | def test_large_output(self): FILE: tests/tools/test_symlink_prefix_confusion.py function _old_check_escapes (line 14) | def _old_check_escapes(resolved: Path, skill_dir_resolved: Path) -> bool: function _new_check_escapes (line 25) | def _new_check_escapes(resolved: Path, skill_dir_resolved: Path) -> bool: class TestPrefixConfusionRegression (line 33) | class TestPrefixConfusionRegression: method test_old_check_misses_sibling_with_shared_prefix (line 36) | def test_old_check_misses_sibling_with_shared_prefix(self, tmp_path): method test_new_check_catches_sibling_with_shared_prefix (line 50) | def test_new_check_catches_sibling_with_shared_prefix(self, tmp_path): method test_both_agree_on_real_subpath (line 64) | def test_both_agree_on_real_subpath(self, tmp_path): method test_both_agree_on_completely_outside_path (line 78) | def test_both_agree_on_completely_outside_path(self, tmp_path): method test_skill_dir_itself_allowed (line 92) | def test_skill_dir_itself_allowed(self, tmp_path): function _can_symlink (line 105) | def _can_symlink(): class TestSymlinkEscapeWithActualSymlinks (line 120) | class TestSymlinkEscapeWithActualSymlinks: method test_symlink_to_sibling_prefix_dir_detected (line 123) | def test_symlink_to_sibling_prefix_dir_detected(self, tmp_path): method test_symlink_within_skill_dir_allowed (line 145) | def test_symlink_within_skill_dir_allowed(self, tmp_path): method test_symlink_to_parent_dir_blocked (line 159) | def test_symlink_to_parent_dir_blocked(self, tmp_path): FILE: tests/tools/test_terminal_disk_usage.py function fake_scratch (line 21) | def fake_scratch(tmp_path): class TestDiskUsageGlob (line 36) | class TestDiskUsageGlob: method test_only_counts_matching_task_dirs (line 37) | def test_only_counts_matching_task_dirs(self, fake_scratch): method test_multiple_tasks_no_double_counting (line 51) | def test_multiple_tasks_no_double_counting(self, fake_scratch): FILE: tests/tools/test_terminal_requirements.py function _clear_terminal_env (line 7) | def _clear_terminal_env(monkeypatch): function test_local_terminal_requirements_do_not_depend_on_minisweagent (line 21) | def test_local_terminal_requirements_do_not_depend_on_minisweagent(monke... function test_unknown_terminal_env_logs_error_and_returns_false (line 34) | def test_unknown_terminal_env_logs_error_and_returns_false(monkeypatch, ... function test_ssh_backend_without_host_or_user_logs_and_returns_false (line 48) | def test_ssh_backend_without_host_or_user_logs_and_returns_false(monkeyp... function test_modal_backend_without_token_or_config_logs_specific_error (line 62) | def test_modal_backend_without_token_or_config_logs_specific_error(monke... FILE: tests/tools/test_terminal_tool_requirements.py class TestTerminalRequirements (line 10) | class TestTerminalRequirements: method test_local_backend_does_not_require_minisweagent_package (line 11) | def test_local_backend_does_not_require_minisweagent_package(self, mon... method test_terminal_and_file_tools_resolve_for_local_backend (line 19) | def test_terminal_and_file_tools_resolve_for_local_backend(self, monke... FILE: tests/tools/test_tirith_security.py function _reset_resolved_path (line 16) | def _reset_resolved_path(): function _mock_run (line 35) | def _mock_run(returncode=0, stdout="", stderr=""): function _json_stdout (line 44) | def _json_stdout(findings=None, summary=""): class TestExitCodeMapping (line 52) | class TestExitCodeMapping: method test_exit_0_allow (line 55) | def test_exit_0_allow(self, mock_cfg, mock_run): method test_exit_1_block_with_findings (line 65) | def test_exit_1_block_with_findings(self, mock_cfg, mock_run): method test_exit_2_warn_with_findings (line 77) | def test_exit_2_warn_with_findings(self, mock_cfg, mock_run): class TestJsonParseFailure (line 92) | class TestJsonParseFailure: method test_exit_1_invalid_json_still_blocks (line 95) | def test_exit_1_invalid_json_still_blocks(self, mock_cfg, mock_run): method test_exit_2_invalid_json_still_warns (line 105) | def test_exit_2_invalid_json_still_warns(self, mock_cfg, mock_run): method test_exit_0_invalid_json_allows (line 115) | def test_exit_0_invalid_json_allows(self, mock_cfg, mock_run): class TestOSErrorFailOpen (line 127) | class TestOSErrorFailOpen: method test_file_not_found_fail_open (line 130) | def test_file_not_found_fail_open(self, mock_cfg, mock_run): method test_permission_error_fail_open (line 140) | def test_permission_error_fail_open(self, mock_cfg, mock_run): method test_os_error_fail_closed (line 150) | def test_os_error_fail_closed(self, mock_cfg, mock_run): class TestTimeoutFailOpen (line 159) | class TestTimeoutFailOpen: method test_timeout_fail_open (line 162) | def test_timeout_fail_open(self, mock_cfg, mock_run): method test_timeout_fail_closed (line 172) | def test_timeout_fail_closed(self, mock_cfg, mock_run): class TestUnknownExitCode (line 181) | class TestUnknownExitCode: method test_unknown_exit_code_fail_open (line 184) | def test_unknown_exit_code_fail_open(self, mock_cfg, mock_run): method test_unknown_exit_code_fail_closed (line 194) | def test_unknown_exit_code_fail_closed(self, mock_cfg, mock_run): class TestDisabled (line 207) | class TestDisabled: method test_disabled_returns_allow (line 209) | def test_disabled_returns_allow(self, mock_cfg): class TestPathExpansion (line 216) | class TestPathExpansion: method test_tilde_expanded_in_resolve (line 217) | def test_tilde_expanded_in_resolve(self): class TestCaps (line 231) | class TestCaps: method test_findings_capped_at_50 (line 234) | def test_findings_capped_at_50(self, mock_cfg, mock_run): method test_summary_capped_at_500 (line 244) | def test_summary_capped_at_500(self, mock_cfg, mock_run): class TestProgrammingErrors (line 257) | class TestProgrammingErrors: method test_attribute_error_propagates (line 260) | def test_attribute_error_propagates(self, mock_cfg, mock_run): method test_type_error_propagates (line 269) | def test_type_error_propagates(self, mock_cfg, mock_run): class TestEnsureInstalled (line 281) | class TestEnsureInstalled: method test_disabled_returns_none (line 283) | def test_disabled_returns_none(self, mock_cfg): method test_found_on_path_returns_immediately (line 291) | def test_found_on_path_returns_immediately(self, mock_cfg, mock_which): method test_not_found_returns_none (line 302) | def test_not_found_returns_none(self, mock_cfg): method test_startup_prefetch_can_suppress_install_failure_logs (line 319) | def test_startup_prefetch_can_suppress_install_failure_logs(self, mock... class TestFailedDownloadCaching (line 340) | class TestFailedDownloadCaching: method test_failed_install_cached_no_retry (line 345) | def test_failed_install_cached_no_retry(self, mock_which, mock_install, method test_failed_install_scan_uses_fail_open (line 369) | def test_failed_install_scan_uses_fail_open(self, mock_cfg, mock_run, class TestExplicitPathNoAutoDownload (line 394) | class TestExplicitPathNoAutoDownload: method test_explicit_path_missing_no_download (line 397) | def test_explicit_path_missing_no_download(self, mock_which, mock_inst... method test_tilde_explicit_path_missing_no_download (line 412) | def test_tilde_explicit_path_missing_no_download(self, mock_which, moc... method test_default_path_does_auto_download (line 428) | def test_default_path_does_auto_download(self, mock_which, mock_install, class TestCosignVerification (line 445) | class TestCosignVerification: method test_cosign_pass (line 448) | def test_cosign_pass(self, mock_which, mock_run): method test_cosign_identity_pinned_to_release_workflow (line 462) | def test_cosign_identity_pinned_to_release_workflow(self, mock_which, ... method test_cosign_fail_aborts (line 477) | def test_cosign_fail_aborts(self, mock_which, mock_run): method test_cosign_not_found_returns_none (line 486) | def test_cosign_not_found_returns_none(self, mock_which): method test_cosign_timeout_returns_none (line 496) | def test_cosign_timeout_returns_none(self, mock_which, mock_run): method test_cosign_os_error_returns_none (line 506) | def test_cosign_os_error_returns_none(self, mock_which, mock_run): method test_install_aborts_on_cosign_rejection (line 517) | def test_install_aborts_on_cosign_rejection(self, mock_target, mock_dl, method test_install_proceeds_without_cosign (line 530) | def test_install_proceeds_without_cosign(self, mock_target, mock_dl, method test_install_proceeds_when_cosign_exec_fails (line 553) | def test_install_proceeds_when_cosign_exec_fails(self, mock_target, mo... method test_install_proceeds_when_cosign_artifacts_missing (line 574) | def test_install_proceeds_when_cosign_artifacts_missing(self, mock_tar... method test_install_proceeds_when_cosign_passes (line 603) | def test_install_proceeds_when_cosign_passes(self, mock_target, mock_dl, class TestBackgroundInstall (line 626) | class TestBackgroundInstall: method test_ensure_installed_non_blocking (line 627) | def test_ensure_installed_non_blocking(self): method test_ensure_installed_skips_on_disk_marker (line 649) | def test_ensure_installed_skips_on_disk_marker(self): method test_resolve_returns_default_when_thread_alive (line 668) | def test_resolve_returns_default_when_thread_alive(self): method test_resolve_picks_up_background_result (line 684) | def test_resolve_picks_up_background_result(self): class TestDiskFailureMarker (line 700) | class TestDiskFailureMarker: method test_mark_and_check (line 701) | def test_mark_and_check(self): method test_expired_marker_ignored (line 716) | def test_expired_marker_ignored(self): method test_cosign_missing_marker_clears_when_cosign_appears (line 729) | def test_cosign_missing_marker_clears_when_cosign_appears(self): method test_cosign_missing_marker_stays_when_cosign_still_absent (line 745) | def test_cosign_missing_marker_stays_when_cosign_still_absent(self): method test_non_cosign_marker_not_affected_by_cosign_presence (line 756) | def test_non_cosign_marker_not_affected_by_cosign_presence(self): method test_sync_resolve_persists_failure (line 771) | def test_sync_resolve_persists_failure(self, mock_which, mock_install, method test_sync_resolve_clears_marker_on_success (line 786) | def test_sync_resolve_clears_marker_on_success(self, mock_which, mock_... method test_sync_resolve_skips_install_on_disk_marker (line 798) | def test_sync_resolve_skips_install_on_disk_marker(self): method test_install_failed_still_checks_local_paths (line 815) | def test_install_failed_still_checks_local_paths(self): method test_install_failed_recovers_from_hermes_bin (line 829) | def test_install_failed_recovers_from_hermes_bin(self): method test_install_failed_skips_network_when_local_absent (line 852) | def test_install_failed_skips_network_when_local_absent(self): method test_cosign_missing_disk_marker_allows_retry (line 866) | def test_cosign_missing_disk_marker_allows_retry(self): method test_in_memory_cosign_missing_retries_when_cosign_appears (line 883) | def test_in_memory_cosign_missing_retries_when_cosign_appears(self): method test_in_memory_cosign_exec_failed_not_retried (line 907) | def test_in_memory_cosign_exec_failed_not_retried(self): method test_in_memory_cosign_missing_stays_when_cosign_still_absent (line 922) | def test_in_memory_cosign_missing_stays_when_cosign_still_absent(self): method test_disk_marker_reason_preserved_in_memory (line 937) | def test_disk_marker_reason_preserved_in_memory(self): class TestHermesHomeIsolation (line 975) | class TestHermesHomeIsolation: method test_hermes_bin_dir_respects_hermes_home (line 976) | def test_hermes_bin_dir_respects_hermes_home(self): method test_failure_marker_respects_hermes_home (line 986) | def test_failure_marker_respects_hermes_home(self): method test_conftest_isolation_prevents_real_home_writes (line 993) | def test_conftest_isolation_prevents_real_home_writes(self): method test_get_hermes_home_fallback (line 999) | def test_get_hermes_home_fallback(self): FILE: tests/tools/test_todo_tool.py class TestWriteAndRead (line 8) | class TestWriteAndRead: method test_write_replaces_list (line 9) | def test_write_replaces_list(self): method test_read_returns_copy (line 20) | def test_read_returns_copy(self): class TestHasItems (line 28) | class TestHasItems: method test_empty_store (line 29) | def test_empty_store(self): method test_non_empty_store (line 33) | def test_non_empty_store(self): class TestFormatForInjection (line 39) | class TestFormatForInjection: method test_empty_returns_none (line 40) | def test_empty_returns_none(self): method test_non_empty_has_markers (line 44) | def test_non_empty_has_markers(self): class TestMergeMode (line 63) | class TestMergeMode: method test_update_existing_by_id (line 64) | def test_update_existing_by_id(self): method test_merge_appends_new (line 78) | def test_merge_appends_new(self): class TestTodoToolFunction (line 89) | class TestTodoToolFunction: method test_read_mode (line 90) | def test_read_mode(self): method test_write_mode (line 97) | def test_write_mode(self): method test_no_store_returns_error (line 105) | def test_no_store_returns_error(self): FILE: tests/tools/test_transcription.py class TestGetProvider (line 21) | class TestGetProvider: method test_local_when_available (line 24) | def test_local_when_available(self): method test_explicit_local_no_cloud_fallback (line 29) | def test_explicit_local_no_cloud_fallback(self, monkeypatch): method test_local_nothing_available (line 38) | def test_local_nothing_available(self, monkeypatch): method test_openai_when_key_set (line 45) | def test_openai_when_key_set(self, monkeypatch): method test_explicit_openai_no_key_returns_none (line 51) | def test_explicit_openai_no_key_returns_none(self, monkeypatch): method test_default_provider_is_local (line 59) | def test_default_provider_is_local(self): method test_disabled_config_returns_none (line 64) | def test_disabled_config_returns_none(self): class TestValidateAudioFile (line 74) | class TestValidateAudioFile: method test_missing_file (line 76) | def test_missing_file(self, tmp_path): method test_unsupported_format (line 82) | def test_unsupported_format(self, tmp_path): method test_valid_file_returns_none (line 90) | def test_valid_file_returns_none(self, tmp_path): method test_too_large (line 96) | def test_too_large(self, tmp_path): class TestTranscribeLocal (line 118) | class TestTranscribeLocal: method test_successful_transcription (line 120) | def test_successful_transcription(self, tmp_path): method test_not_installed (line 142) | def test_not_installed(self): class TestTranscribeOpenAI (line 155) | class TestTranscribeOpenAI: method test_no_key (line 157) | def test_no_key(self, monkeypatch): method test_successful_transcription (line 164) | def test_successful_transcription(self, monkeypatch, tmp_path): class TestTranscribeAudio (line 186) | class TestTranscribeAudio: method test_dispatches_to_local (line 188) | def test_dispatches_to_local(self, tmp_path): method test_dispatches_to_openai (line 201) | def test_dispatches_to_openai(self, tmp_path): method test_no_provider_returns_error (line 214) | def test_no_provider_returns_error(self, tmp_path): method test_disabled_config_returns_disabled_error (line 226) | def test_disabled_config_returns_disabled_error(self, tmp_path): method test_invalid_file_returns_error (line 238) | def test_invalid_file_returns_error(self): FILE: tests/tools/test_transcription_tools.py function sample_wav (line 22) | def sample_wav(tmp_path): function sample_ogg (line 38) | def sample_ogg(tmp_path): function clean_env (line 46) | def clean_env(monkeypatch): class TestGetProviderGroq (line 59) | class TestGetProviderGroq: method test_groq_when_key_set (line 62) | def test_groq_when_key_set(self, monkeypatch): method test_groq_explicit_no_fallback (line 69) | def test_groq_explicit_no_fallback(self, monkeypatch): method test_groq_nothing_available (line 76) | def test_groq_nothing_available(self, monkeypatch): class TestGetProviderFallbackPriority (line 85) | class TestGetProviderFallbackPriority: method test_auto_detect_prefers_local (line 88) | def test_auto_detect_prefers_local(self): method test_auto_detect_prefers_groq_over_openai (line 94) | def test_auto_detect_prefers_groq_over_openai(self, monkeypatch): method test_explicit_openai_no_key_returns_none (line 103) | def test_explicit_openai_no_key_returns_none(self, monkeypatch): method test_unknown_provider_passed_through (line 112) | def test_unknown_provider_passed_through(self): method test_empty_config_defaults_to_local (line 116) | def test_empty_config_defaults_to_local(self): class TestExplicitProviderRespected (line 126) | class TestExplicitProviderRespected: method test_explicit_local_no_fallback_to_openai (line 130) | def test_explicit_local_no_fallback_to_openai(self, monkeypatch): method test_explicit_local_no_fallback_to_groq (line 141) | def test_explicit_local_no_fallback_to_groq(self, monkeypatch): method test_explicit_local_uses_local_command_fallback (line 149) | def test_explicit_local_uses_local_command_fallback(self, monkeypatch): method test_explicit_groq_no_fallback_to_openai (line 160) | def test_explicit_groq_no_fallback_to_openai(self, monkeypatch): method test_explicit_openai_no_fallback_to_groq (line 169) | def test_explicit_openai_no_fallback_to_groq(self, monkeypatch): method test_auto_detect_still_falls_back_to_cloud (line 179) | def test_auto_detect_still_falls_back_to_cloud(self, monkeypatch): method test_auto_detect_prefers_groq_over_openai (line 190) | def test_auto_detect_prefers_groq_over_openai(self, monkeypatch): class TestTranscribeGroq (line 204) | class TestTranscribeGroq: method test_no_key (line 205) | def test_no_key(self, monkeypatch): method test_openai_package_not_installed (line 212) | def test_openai_package_not_installed(self, monkeypatch): method test_successful_transcription (line 220) | def test_successful_transcription(self, monkeypatch, sample_wav): method test_whitespace_stripped (line 235) | def test_whitespace_stripped(self, monkeypatch, sample_wav): method test_uses_groq_base_url (line 248) | def test_uses_groq_base_url(self, monkeypatch, sample_wav): method test_api_error_returns_failure (line 262) | def test_api_error_returns_failure(self, monkeypatch, sample_wav): method test_permission_error (line 276) | def test_permission_error(self, monkeypatch, sample_wav): class TestTranscribeOpenAIExtended (line 295) | class TestTranscribeOpenAIExtended: method test_openai_package_not_installed (line 296) | def test_openai_package_not_installed(self, monkeypatch): method test_uses_openai_base_url (line 304) | def test_uses_openai_base_url(self, monkeypatch, sample_wav): method test_whitespace_stripped (line 318) | def test_whitespace_stripped(self, monkeypatch, sample_wav): method test_permission_error (line 331) | def test_permission_error(self, monkeypatch, sample_wav): class TestTranscribeLocalCommand (line 346) | class TestTranscribeLocalCommand: method test_auto_detects_local_whisper_binary (line 347) | def test_auto_detects_local_whisper_binary(self, monkeypatch): method test_command_fallback_with_template (line 360) | def test_command_fallback_with_template(self, monkeypatch, sample_ogg,... class TestTranscribeLocalExtended (line 407) | class TestTranscribeLocalExtended: method test_model_reuse_on_second_call (line 408) | def test_model_reuse_on_second_call(self, tmp_path): method test_model_reloaded_on_change (line 434) | def test_model_reloaded_on_change(self, tmp_path): method test_exception_returns_failure (line 459) | def test_exception_returns_failure(self, tmp_path): method test_multiple_segments_joined (line 474) | def test_multiple_segments_joined(self, tmp_path): class TestModelAutoCorrection (line 503) | class TestModelAutoCorrection: method test_groq_corrects_openai_model (line 504) | def test_groq_corrects_openai_model(self, monkeypatch, sample_wav): method test_groq_corrects_gpt4o_transcribe (line 518) | def test_groq_corrects_gpt4o_transcribe(self, monkeypatch, sample_wav): method test_openai_corrects_groq_model (line 532) | def test_openai_corrects_groq_model(self, monkeypatch, sample_wav): method test_openai_corrects_distil_whisper (line 546) | def test_openai_corrects_distil_whisper(self, monkeypatch, sample_wav): method test_compatible_groq_model_not_overridden (line 560) | def test_compatible_groq_model_not_overridden(self, monkeypatch, sampl... method test_compatible_openai_model_not_overridden (line 574) | def test_compatible_openai_model_not_overridden(self, monkeypatch, sam... method test_unknown_model_passes_through_groq (line 588) | def test_unknown_model_passes_through_groq(self, monkeypatch, sample_w... method test_unknown_model_passes_through_openai (line 603) | def test_unknown_model_passes_through_openai(self, monkeypatch, sample... class TestLoadSttConfig (line 622) | class TestLoadSttConfig: method test_returns_dict_when_import_fails (line 623) | def test_returns_dict_when_import_fails(self): method test_real_load_returns_dict (line 629) | def test_real_load_returns_dict(self): class TestValidateAudioFileEdgeCases (line 641) | class TestValidateAudioFileEdgeCases: method test_directory_is_not_a_file (line 642) | def test_directory_is_not_a_file(self, tmp_path): method test_stat_oserror (line 652) | def test_stat_oserror(self, tmp_path): method test_all_supported_formats_accepted (line 672) | def test_all_supported_formats_accepted(self, tmp_path): method test_case_insensitive_extension (line 679) | def test_case_insensitive_extension(self, tmp_path): class TestTranscribeAudioDispatch (line 690) | class TestTranscribeAudioDispatch: method test_dispatches_to_groq (line 691) | def test_dispatches_to_groq(self, sample_ogg): method test_dispatches_to_local (line 703) | def test_dispatches_to_local(self, sample_ogg): method test_dispatches_to_openai (line 714) | def test_dispatches_to_openai(self, sample_ogg): method test_no_provider_returns_error (line 725) | def test_no_provider_returns_error(self, sample_ogg): method test_explicit_openai_no_key_returns_error (line 736) | def test_explicit_openai_no_key_returns_error(self, monkeypatch, sampl... method test_invalid_file_short_circuits (line 750) | def test_invalid_file_short_circuits(self): method test_model_override_passed_to_groq (line 756) | def test_model_override_passed_to_groq(self, sample_ogg): method test_model_override_passed_to_local (line 767) | def test_model_override_passed_to_local(self, sample_ogg): method test_default_model_used_when_none (line 777) | def test_default_model_used_when_none(self, sample_ogg): method test_config_local_model_used (line 787) | def test_config_local_model_used(self, sample_ogg): method test_config_openai_model_used (line 798) | def test_config_openai_model_used(self, sample_ogg): class TestGetSttModelFromConfig (line 814) | class TestGetSttModelFromConfig: method test_returns_model_from_config (line 815) | def test_returns_model_from_config(self, tmp_path, monkeypatch): method test_returns_none_when_no_stt_section (line 823) | def test_returns_none_when_no_stt_section(self, tmp_path, monkeypatch): method test_returns_none_when_no_config_file (line 831) | def test_returns_none_when_no_config_file(self, tmp_path, monkeypatch): method test_returns_none_on_invalid_yaml (line 837) | def test_returns_none_on_invalid_yaml(self, tmp_path, monkeypatch): method test_returns_none_when_model_key_missing (line 845) | def test_returns_none_when_model_key_missing(self, tmp_path, monkeypat... FILE: tests/tools/test_vision_tools.py class TestValidateImageUrl (line 29) | class TestValidateImageUrl: method test_valid_https_url (line 32) | def test_valid_https_url(self): method test_valid_http_url (line 35) | def test_valid_http_url(self): method test_valid_url_without_extension (line 38) | def test_valid_url_without_extension(self): method test_valid_url_with_query_params (line 42) | def test_valid_url_with_query_params(self): method test_valid_url_with_port (line 45) | def test_valid_url_with_port(self): method test_valid_url_with_path_only (line 48) | def test_valid_url_with_path_only(self): method test_rejects_empty_string (line 51) | def test_rejects_empty_string(self): method test_rejects_none (line 54) | def test_rejects_none(self): method test_rejects_non_string (line 57) | def test_rejects_non_string(self): method test_rejects_ftp_scheme (line 60) | def test_rejects_ftp_scheme(self): method test_rejects_file_scheme (line 63) | def test_rejects_file_scheme(self): method test_rejects_no_scheme (line 66) | def test_rejects_no_scheme(self): method test_rejects_javascript_scheme (line 69) | def test_rejects_javascript_scheme(self): method test_rejects_http_without_netloc (line 72) | def test_rejects_http_without_netloc(self): method test_rejects_https_without_netloc (line 76) | def test_rejects_https_without_netloc(self): method test_rejects_http_colon_only (line 79) | def test_rejects_http_colon_only(self): method test_rejects_data_url (line 82) | def test_rejects_data_url(self): method test_rejects_whitespace_only (line 85) | def test_rejects_whitespace_only(self): method test_rejects_boolean (line 88) | def test_rejects_boolean(self): method test_rejects_list (line 91) | def test_rejects_list(self): class TestDetermineMimeType (line 100) | class TestDetermineMimeType: method test_jpg (line 101) | def test_jpg(self): method test_jpeg (line 104) | def test_jpeg(self): method test_png (line 107) | def test_png(self): method test_gif (line 110) | def test_gif(self): method test_webp (line 113) | def test_webp(self): method test_unknown_extension_defaults_to_jpeg (line 116) | def test_unknown_extension_defaults_to_jpeg(self): class TestImageToBase64DataUrl (line 125) | class TestImageToBase64DataUrl: method test_returns_data_url (line 126) | def test_returns_data_url(self, tmp_path): method test_custom_mime_type (line 132) | def test_custom_mime_type(self, tmp_path): method test_file_not_found_raises (line 138) | def test_file_not_found_raises(self, tmp_path): class TestHandleVisionAnalyze (line 148) | class TestHandleVisionAnalyze: method test_returns_awaitable (line 151) | def test_returns_awaitable(self): method test_prompt_contains_question (line 168) | def test_prompt_contains_question(self): method test_uses_auxiliary_vision_model_env (line 187) | def test_uses_auxiliary_vision_model_env(self): method test_falls_back_to_default_model (line 204) | def test_falls_back_to_default_model(self): method test_empty_args_graceful (line 225) | def test_empty_args_graceful(self): class TestErrorLoggingExcInfo (line 241) | class TestErrorLoggingExcInfo: method test_download_failure_logs_exc_info (line 245) | async def test_download_failure_logs_exc_info(self, tmp_path, caplog): method test_analysis_error_logs_exc_info (line 271) | async def test_analysis_error_logs_exc_info(self, caplog): method test_cleanup_error_logs_exc_info (line 293) | async def test_cleanup_error_logs_exc_info(self, tmp_path, caplog): class TestVisionRequirements (line 349) | class TestVisionRequirements: method test_check_requirements_returns_bool (line 350) | def test_check_requirements_returns_bool(self): method test_check_requirements_accepts_codex_auth (line 354) | def test_check_requirements_accepts_codex_auth(self, monkeypatch, tmp_... method test_debug_session_info_returns_dict (line 367) | def test_debug_session_info_returns_dict(self): class TestVisionRegistration (line 381) | class TestVisionRegistration: method test_vision_analyze_registered (line 382) | def test_vision_analyze_registered(self): method test_schema_has_required_fields (line 390) | def test_schema_has_required_fields(self): method test_handler_is_callable (line 401) | def test_handler_is_callable(self): FILE: tests/tools/test_voice_cli_integration.py function _make_voice_cli (line 14) | def _make_voice_cli(**overrides): class TestMarkdownStripping (line 48) | class TestMarkdownStripping: method test_strips_bold (line 49) | def test_strips_bold(self): method test_strips_italic (line 52) | def test_strips_italic(self): method test_strips_inline_code (line 55) | def test_strips_inline_code(self): method test_strips_fenced_code_blocks (line 58) | def test_strips_fenced_code_blocks(self): method test_strips_headers (line 64) | def test_strips_headers(self): method test_strips_list_markers (line 67) | def test_strips_list_markers(self): method test_strips_urls (line 74) | def test_strips_urls(self): method test_strips_markdown_links (line 80) | def test_strips_markdown_links(self): method test_strips_horizontal_rules (line 87) | def test_strips_horizontal_rules(self): method test_empty_after_stripping_returns_empty (line 94) | def test_empty_after_stripping_returns_empty(self): method test_long_text_not_truncated (line 99) | def test_long_text_not_truncated(self): method test_complex_response (line 105) | def test_complex_response(self): class TestVoiceCommandParsing (line 130) | class TestVoiceCommandParsing: method test_parse_subcommands (line 133) | def test_parse_subcommands(self): class TestVoiceStateLock (line 153) | class TestVoiceStateLock: method test_lock_protects_state (line 154) | def test_lock_protects_state(self): class TestStreamingTTSActivation (line 178) | class TestStreamingTTSActivation: method test_activates_when_elevenlabs_and_sounddevice_available (line 181) | def test_activates_when_elevenlabs_and_sounddevice_available(self): method test_does_not_activate_when_elevenlabs_missing (line 219) | def test_does_not_activate_when_elevenlabs_missing(self): method test_does_not_activate_when_sounddevice_missing (line 242) | def test_does_not_activate_when_sounddevice_missing(self): method test_does_not_activate_for_non_elevenlabs_provider (line 266) | def test_does_not_activate_for_non_elevenlabs_provider(self): method test_stale_boolean_imports_no_longer_exist (line 288) | def test_stale_boolean_imports_no_longer_exist(self): class TestVoiceMessagePrefix (line 301) | class TestVoiceMessagePrefix: method test_prefix_added_when_voice_mode_active (line 305) | def test_prefix_added_when_voice_mode_active(self): method test_no_prefix_when_voice_mode_inactive (line 322) | def test_no_prefix_when_voice_mode_inactive(self): method test_no_prefix_for_multimodal_content (line 337) | def test_no_prefix_for_multimodal_content(self): method test_history_stays_clean (line 352) | def test_history_stays_clean(self): method test_enable_voice_mode_does_not_modify_system_prompt (line 373) | def test_enable_voice_mode_does_not_modify_system_prompt(self): class TestVprintForceParameter (line 398) | class TestVprintForceParameter: method _make_agent_with_stream (line 401) | def _make_agent_with_stream(self, stream_active: bool): method test_suppressed_during_streaming (line 415) | def test_suppressed_during_streaming(self, capsys): method test_shown_when_not_streaming (line 422) | def test_shown_when_not_streaming(self, capsys): method test_force_shown_during_streaming (line 429) | def test_force_shown_during_streaming(self, capsys): method test_force_shown_when_not_streaming (line 436) | def test_force_shown_when_not_streaming(self, capsys): method test_error_messages_use_force_in_run_agent (line 443) | def test_error_messages_use_force_in_run_agent(self): class TestEdgeTTSLazyImport (line 494) | class TestEdgeTTSLazyImport: method test_generate_edge_tts_calls_lazy_import (line 497) | def test_generate_edge_tts_calls_lazy_import(self): class TestStreamingTTSOutputStreamCleanup (line 532) | class TestStreamingTTSOutputStreamCleanup: method test_output_stream_closed_in_finally (line 535) | def test_output_stream_closed_in_finally(self): class TestCtrlCResetsContinuousMode (line 559) | class TestCtrlCResetsContinuousMode: method test_ctrl_c_handler_resets_voice_continuous (line 562) | def test_ctrl_c_handler_resets_voice_continuous(self): class TestDisableVoiceModeStopsTTS (line 588) | class TestDisableVoiceModeStopsTTS: method test_disable_voice_mode_calls_stop_playback (line 591) | def test_disable_voice_mode_calls_stop_playback(self): class TestVoiceStatusUsesConfigKey (line 605) | class TestVoiceStatusUsesConfigKey: method test_show_voice_status_not_hardcoded (line 608) | def test_show_voice_status_not_hardcoded(self): method test_show_voice_status_reads_config (line 626) | def test_show_voice_status_reads_config(self): class TestChatTTSCleanupOnException (line 648) | class TestChatTTSCleanupOnException: method test_chat_has_finally_for_tts_cleanup (line 651) | def test_chat_has_finally_for_tts_cleanup(self): class TestBrowserToolSignalHandlerRemoved (line 681) | class TestBrowserToolSignalHandlerRemoved: method test_no_signal_handler_registration (line 686) | def test_no_signal_handler_registration(self): class TestKeyHandlerNeverBlocks (line 708) | class TestKeyHandlerNeverBlocks: method test_start_recording_not_called_directly_in_handler (line 716) | def test_start_recording_not_called_directly_in_handler(self): method test_processing_guard_in_start_path (line 738) | def test_processing_guard_in_start_path(self): method test_processing_set_atomically_with_recording_false (line 764) | def test_processing_set_atomically_with_recording_false(self): class TestHandleVoiceCommandReal (line 802) | class TestHandleVoiceCommandReal: method _cli (line 805) | def _cli(self): method test_on_calls_enable (line 814) | def test_on_calls_enable(self, _cp): method test_off_calls_disable (line 820) | def test_off_calls_disable(self, _cp): method test_tts_calls_toggle (line 826) | def test_tts_calls_toggle(self, _cp): method test_status_calls_show (line 832) | def test_status_calls_show(self, _cp): method test_toggle_off_when_enabled (line 838) | def test_toggle_off_when_enabled(self, _cp): method test_toggle_on_when_disabled (line 845) | def test_toggle_on_when_disabled(self, _cp): method test_unknown_subcommand (line 852) | def test_unknown_subcommand(self, mock_cp): class TestEnableVoiceModeReal (line 862) | class TestEnableVoiceModeReal: method test_success_sets_voice_mode (line 871) | def test_success_sets_voice_mode(self, _env, _req, _cfg, _cp): method test_already_enabled_noop (line 877) | def test_already_enabled_noop(self, _cp): method test_env_check_fails (line 885) | def test_env_check_fails(self, _env, _cp): method test_requirements_fail (line 896) | def test_requirements_fail(self, _env, _req, _cp): method test_auto_tts_from_config (line 907) | def test_auto_tts_from_config(self, _env, _req, _cfg, _cp): method test_no_auto_tts_default (line 918) | def test_no_auto_tts_default(self, _env, _req, _cfg, _cp): method test_config_exception_still_enables (line 929) | def test_config_exception_still_enables(self, _env, _req, _cfg, _cp): class TestDisableVoiceModeReal (line 935) | class TestDisableVoiceModeReal: method test_all_flags_reset (line 940) | def test_all_flags_reset(self, _sp, _cp): method test_active_recording_cancelled (line 950) | def test_active_recording_cancelled(self, _sp, _cp): method test_stop_playback_called (line 959) | def test_stop_playback_called(self, mock_sp, _cp): method test_tts_done_event_set (line 966) | def test_tts_done_event_set(self, _sp, _cp): method test_no_recorder_no_crash (line 974) | def test_no_recorder_no_crash(self, _sp, _cp): method test_stop_playback_exception_swallowed (line 981) | def test_stop_playback_exception_swallowed(self, _sp, _cp): class TestVoiceSpeakResponseReal (line 987) | class TestVoiceSpeakResponseReal: method test_early_return_when_tts_off (line 991) | def test_early_return_when_tts_off(self, _cp): method test_markdown_stripped (line 1004) | def test_markdown_stripped(self, mock_tts, _play, _mkd, _isf, _gsz, _u... method test_code_blocks_removed (line 1015) | def test_code_blocks_removed(self, mock_tts, _mkd, _cp): method test_empty_after_strip_returns_early (line 1025) | def test_empty_after_strip_returns_early(self, _mkd, _cp): method test_long_text_truncated (line 1034) | def test_long_text_truncated(self, mock_tts, _mkd, _cp): method test_exception_sets_done_event (line 1043) | def test_exception_sets_done_event(self, _tts, _mkd, _cp): method test_play_audio_called (line 1056) | def test_play_audio_called(self, _tts, mock_play, _mkd, _isf, _gsz, _u... class TestVoiceStopAndTranscribeReal (line 1062) | class TestVoiceStopAndTranscribeReal: method test_guard_not_recording (line 1066) | def test_guard_not_recording(self, _cp): method test_no_recorder_returns_early (line 1073) | def test_no_recorder_returns_early(self, _cp): method test_no_speech_detected (line 1082) | def test_no_speech_detected(self, _beep, _cp): method test_successful_transcription_queues_input (line 1096) | def test_successful_transcription_queues_input( method test_empty_transcript_not_queued (line 1112) | def test_empty_transcript_not_queued(self, _beep, _tr, _cfg, _isf, _un... method test_transcription_failure (line 1126) | def test_transcription_failure(self, _beep, _tr, _cfg, _isf, _unl, _cp): method test_exception_caught (line 1140) | def test_exception_caught(self, _beep, _tr, _cfg, _isf, _unl, _cp): method test_processing_flag_cleared (line 1148) | def test_processing_flag_cleared(self, _beep, _cp): method test_continuous_restarts_on_no_speech (line 1157) | def test_continuous_restarts_on_no_speech(self, _beep, _cp): method test_continuous_no_restart_on_success (line 1173) | def test_continuous_no_restart_on_success( method test_stt_model_from_config (line 1191) | def test_stt_model_from_config(self, _beep, mock_tr, _cfg, _isf, _unl,... class TestRefreshLevelLock (line 1204) | class TestRefreshLevelLock: method test_refresh_stops_when_recording_false (line 1207) | def test_refresh_stops_when_recording_false(self): FILE: tests/tools/test_voice_mode.py function sample_wav (line 18) | def sample_wav(tmp_path): function temp_voice_dir (line 34) | def temp_voice_dir(tmp_path, monkeypatch): function mock_sd (line 43) | def mock_sd(monkeypatch): class TestCheckVoiceRequirements (line 63) | class TestCheckVoiceRequirements: method test_all_requirements_met (line 64) | def test_all_requirements_met(self, monkeypatch): method test_missing_audio_packages (line 78) | def test_missing_audio_packages(self, monkeypatch): method test_missing_stt_provider (line 92) | def test_missing_stt_provider(self, monkeypatch): class TestAudioRecorderStart (line 110) | class TestAudioRecorderStart: method test_start_raises_without_audio (line 111) | def test_start_raises_without_audio(self, monkeypatch): method test_start_creates_and_starts_stream (line 122) | def test_start_creates_and_starts_stream(self, mock_sd): method test_double_start_is_noop (line 135) | def test_double_start_is_noop(self, mock_sd): class TestAudioRecorderStop (line 148) | class TestAudioRecorderStop: method test_stop_returns_none_when_not_recording (line 149) | def test_stop_returns_none_when_not_recording(self): method test_stop_writes_wav_file (line 155) | def test_stop_writes_wav_file(self, mock_sd, temp_voice_dir): method test_stop_returns_none_for_very_short_recording (line 184) | def test_stop_returns_none_for_very_short_recording(self, mock_sd, tem... method test_stop_returns_none_for_silent_recording (line 202) | def test_stop_returns_none_for_silent_recording(self, mock_sd, temp_vo... class TestAudioRecorderCancel (line 222) | class TestAudioRecorderCancel: method test_cancel_discards_frames (line 223) | def test_cancel_discards_frames(self, mock_sd): method test_cancel_when_not_recording_is_safe (line 241) | def test_cancel_when_not_recording_is_safe(self): class TestAudioRecorderProperties (line 249) | class TestAudioRecorderProperties: method test_elapsed_seconds_when_not_recording (line 250) | def test_elapsed_seconds_when_not_recording(self): method test_elapsed_seconds_when_recording (line 256) | def test_elapsed_seconds_when_recording(self, mock_sd): class TestTranscribeRecording (line 277) | class TestTranscribeRecording: method test_delegates_to_transcribe_audio (line 278) | def test_delegates_to_transcribe_audio(self): method test_filters_whisper_hallucination (line 292) | def test_filters_whisper_hallucination(self): method test_does_not_filter_real_speech (line 306) | def test_does_not_filter_real_speech(self): class TestWhisperHallucinationFilter (line 320) | class TestWhisperHallucinationFilter: method test_known_hallucinations (line 321) | def test_known_hallucinations(self): method test_real_speech_not_filtered (line 331) | def test_real_speech_not_filtered(self): class TestPlayAudioFile (line 343) | class TestPlayAudioFile: method test_play_wav_via_sounddevice (line 344) | def test_play_wav_via_sounddevice(self, monkeypatch, sample_wav): method test_returns_false_when_no_player (line 366) | def test_returns_false_when_no_player(self, monkeypatch, sample_wav): method test_returns_false_for_missing_file (line 377) | def test_returns_false_for_missing_file(self): class TestCleanupTempRecordings (line 388) | class TestCleanupTempRecordings: method test_old_files_deleted (line 389) | def test_old_files_deleted(self, temp_voice_dir): method test_recent_files_preserved (line 403) | def test_recent_files_preserved(self, temp_voice_dir): method test_nonexistent_dir_returns_zero (line 414) | def test_nonexistent_dir_returns_zero(self, monkeypatch): method test_non_recording_files_ignored (line 421) | def test_non_recording_files_ignored(self, temp_voice_dir): class TestPlayBeep (line 439) | class TestPlayBeep: method test_beep_calls_sounddevice_play (line 440) | def test_beep_calls_sounddevice_play(self, mock_sd): method test_beep_double_produces_longer_audio (line 459) | def test_beep_double_produces_longer_audio(self, mock_sd): method test_beep_noop_without_audio (line 471) | def test_beep_noop_without_audio(self, monkeypatch): method test_beep_handles_playback_error (line 481) | def test_beep_handles_playback_error(self, mock_sd): class TestSilenceDetection (line 494) | class TestSilenceDetection: method test_silence_callback_fires_after_speech_then_silence (line 495) | def test_silence_callback_fires_after_speech_then_silence(self, mock_sd): method test_silence_without_speech_does_not_fire (line 541) | def test_silence_without_speech_does_not_fire(self, mock_sd): method test_micro_pause_tolerance_during_speech (line 570) | def test_micro_pause_tolerance_during_speech(self, mock_sd): method test_no_callback_means_no_silence_detection (line 611) | def test_no_callback_means_no_silence_detection(self, mock_sd): class TestPlaybackInterrupt (line 641) | class TestPlaybackInterrupt: method test_stop_playback_terminates_process (line 644) | def test_stop_playback_terminates_process(self): method test_stop_playback_noop_when_nothing_playing (line 661) | def test_stop_playback_noop_when_nothing_playing(self): method test_play_audio_file_sets_active_playback (line 669) | def test_play_audio_file_sets_active_playback(self, monkeypatch, sampl... class TestContinuousModeFlow (line 694) | class TestContinuousModeFlow: method test_continuous_restart_on_no_speech (line 697) | def test_continuous_restart_on_no_speech(self, mock_sd, temp_voice_dir): method test_recorder_reusable_after_stop (line 737) | def test_recorder_reusable_after_stop(self, mock_sd, temp_voice_dir): class TestAudioLevelIndicator (line 767) | class TestAudioLevelIndicator: method test_rms_updates_with_audio_chunks (line 770) | def test_rms_updates_with_audio_chunks(self, mock_sd): method test_peak_rms_tracks_maximum (line 796) | def test_peak_rms_tracks_maximum(self, mock_sd): class TestConfigurableSilenceParams (line 829) | class TestConfigurableSilenceParams: method test_custom_threshold_and_duration (line 832) | def test_custom_threshold_and_duration(self, mock_sd): class TestSubprocessTimeoutKill (line 876) | class TestSubprocessTimeoutKill: method test_timeout_kills_process (line 879) | def test_timeout_kills_process(self): class TestStreamLeakOnStartFailure (line 895) | class TestStreamLeakOnStartFailure: method test_stream_closed_on_start_failure (line 898) | def test_stream_closed_on_start_failure(self, mock_sd): class TestSilenceCallbackLock (line 912) | class TestSilenceCallbackLock: method test_fire_block_acquires_lock (line 915) | def test_fire_block_acquires_lock(self): method test_cancel_clears_callback_under_lock (line 927) | def test_cancel_clears_callback_under_lock(self, mock_sd): FILE: tests/tools/test_web_tools_config.py class TestFirecrawlClientConfig (line 16) | class TestFirecrawlClientConfig: method setup_method (line 19) | def setup_method(self): method teardown_method (line 26) | def teardown_method(self): method test_cloud_mode_key_only (line 35) | def test_cloud_mode_key_only(self): method test_self_hosted_with_key (line 44) | def test_self_hosted_with_key(self): method test_self_hosted_no_key (line 58) | def test_self_hosted_no_key(self): method test_no_config_raises_with_helpful_message (line 67) | def test_no_config_raises_with_helpful_message(self): method test_singleton_returns_same_instance (line 76) | def test_singleton_returns_same_instance(self): method test_constructor_failure_allows_retry (line 86) | def test_constructor_failure_allows_retry(self): method test_empty_string_key_treated_as_absent (line 104) | def test_empty_string_key_treated_as_absent(self): method test_empty_string_key_no_url_raises (line 116) | def test_empty_string_key_no_url_raises(self): class TestBackendSelection (line 125) | class TestBackendSelection: method setup_method (line 135) | def setup_method(self): method teardown_method (line 139) | def teardown_method(self): method test_config_parallel (line 145) | def test_config_parallel(self): method test_config_firecrawl (line 151) | def test_config_firecrawl(self): method test_config_tavily (line 158) | def test_config_tavily(self): method test_config_tavily_overrides_env_keys (line 164) | def test_config_tavily_overrides_env_keys(self): method test_config_case_insensitive (line 171) | def test_config_case_insensitive(self): method test_config_tavily_case_insensitive (line 177) | def test_config_tavily_case_insensitive(self): method test_fallback_parallel_only_key (line 185) | def test_fallback_parallel_only_key(self): method test_fallback_tavily_only_key (line 192) | def test_fallback_tavily_only_key(self): method test_fallback_tavily_with_firecrawl_prefers_firecrawl (line 199) | def test_fallback_tavily_with_firecrawl_prefers_firecrawl(self): method test_fallback_tavily_with_parallel_prefers_parallel (line 206) | def test_fallback_tavily_with_parallel_prefers_parallel(self): method test_fallback_both_keys_defaults_to_firecrawl (line 214) | def test_fallback_both_keys_defaults_to_firecrawl(self): method test_fallback_firecrawl_only_key (line 221) | def test_fallback_firecrawl_only_key(self): method test_fallback_no_keys_defaults_to_firecrawl (line 228) | def test_fallback_no_keys_defaults_to_firecrawl(self): method test_invalid_config_falls_through_to_fallback (line 234) | def test_invalid_config_falls_through_to_fallback(self): class TestParallelClientConfig (line 242) | class TestParallelClientConfig: method setup_method (line 245) | def setup_method(self): method teardown_method (line 250) | def teardown_method(self): method test_creates_client_with_key (line 255) | def test_creates_client_with_key(self): method test_no_key_raises_with_helpful_message (line 264) | def test_no_key_raises_with_helpful_message(self): method test_singleton_returns_same_instance (line 270) | def test_singleton_returns_same_instance(self): class TestCheckWebApiKey (line 279) | class TestCheckWebApiKey: method setup_method (line 284) | def setup_method(self): method teardown_method (line 288) | def teardown_method(self): method test_parallel_key_only (line 292) | def test_parallel_key_only(self): method test_firecrawl_key_only (line 297) | def test_firecrawl_key_only(self): method test_firecrawl_url_only (line 302) | def test_firecrawl_url_only(self): method test_tavily_key_only (line 307) | def test_tavily_key_only(self): method test_no_keys_returns_false (line 312) | def test_no_keys_returns_false(self): method test_both_keys_returns_true (line 316) | def test_both_keys_returns_true(self): method test_all_three_keys_returns_true (line 324) | def test_all_three_keys_returns_true(self): FILE: tests/tools/test_web_tools_tavily.py class TestTavilyRequest (line 19) | class TestTavilyRequest: method test_raises_without_api_key (line 22) | def test_raises_without_api_key(self): method test_posts_with_api_key_in_body (line 30) | def test_posts_with_api_key_in_body(self): method test_raises_on_http_error (line 48) | def test_raises_on_http_error(self): class TestNormalizeTavilySearchResults (line 65) | class TestNormalizeTavilySearchResults: method test_basic_normalization (line 68) | def test_basic_normalization(self): method test_empty_results (line 86) | def test_empty_results(self): method test_missing_fields (line 92) | def test_missing_fields(self): class TestNormalizeTavilyDocuments (line 103) | class TestNormalizeTavilyDocuments: method test_basic_document (line 106) | def test_basic_document(self): method test_falls_back_to_content_when_no_raw_content (line 123) | def test_falls_back_to_content_when_no_raw_content(self): method test_failed_results_included (line 129) | def test_failed_results_included(self): method test_failed_urls_included (line 143) | def test_failed_urls_included(self): method test_fallback_url (line 154) | def test_fallback_url(self): class TestWebSearchTavily (line 163) | class TestWebSearchTavily: method test_search_dispatches_to_tavily (line 166) | def test_search_dispatches_to_tavily(self): class TestWebExtractTavily (line 186) | class TestWebExtractTavily: method test_extract_dispatches_to_tavily (line 189) | def test_extract_dispatches_to_tavily(self): class TestWebCrawlTavily (line 211) | class TestWebCrawlTavily: method test_crawl_dispatches_to_tavily (line 214) | def test_crawl_dispatches_to_tavily(self): method test_crawl_sends_instructions (line 237) | def test_crawl_sends_instructions(self): FILE: tests/tools/test_website_policy.py function test_load_website_blocklist_merges_config_and_shared_file (line 10) | def test_load_website_blocklist_merges_config_and_shared_file(tmp_path): function test_check_website_access_matches_parent_domain_subdomains (line 42) | def test_check_website_access_matches_parent_domain_subdomains(tmp_path): function test_check_website_access_supports_wildcard_subdomains_only (line 66) | def test_check_website_access_supports_wildcard_subdomains_only(tmp_path): function test_default_config_exposes_website_blocklist_shape (line 88) | def test_default_config_exposes_website_blocklist_shape(): function test_load_website_blocklist_uses_enabled_default_when_section_missing (line 97) | def test_load_website_blocklist_uses_enabled_default_when_section_missin... function test_load_website_blocklist_raises_clean_error_for_invalid_domains_type (line 106) | def test_load_website_blocklist_raises_clean_error_for_invalid_domains_t... function test_load_website_blocklist_raises_clean_error_for_invalid_shared_files_type (line 127) | def test_load_website_blocklist_raises_clean_error_for_invalid_shared_fi... function test_load_website_blocklist_raises_clean_error_for_invalid_top_level_config_type (line 148) | def test_load_website_blocklist_raises_clean_error_for_invalid_top_level... function test_load_website_blocklist_raises_clean_error_for_invalid_security_type (line 156) | def test_load_website_blocklist_raises_clean_error_for_invalid_security_... function test_load_website_blocklist_raises_clean_error_for_invalid_website_blocklist_type (line 164) | def test_load_website_blocklist_raises_clean_error_for_invalid_website_b... function test_load_website_blocklist_raises_clean_error_for_invalid_enabled_type (line 182) | def test_load_website_blocklist_raises_clean_error_for_invalid_enabled_t... function test_load_website_blocklist_raises_clean_error_for_malformed_yaml (line 202) | def test_load_website_blocklist_raises_clean_error_for_malformed_yaml(tm... function test_load_website_blocklist_wraps_shared_file_read_errors (line 210) | def test_load_website_blocklist_wraps_shared_file_read_errors(tmp_path, ... function test_check_website_access_uses_dynamic_hermes_home (line 242) | def test_check_website_access_uses_dynamic_hermes_home(monkeypatch, tmp_... function test_check_website_access_blocks_scheme_less_urls (line 268) | def test_check_website_access_blocks_scheme_less_urls(tmp_path): function test_browser_navigate_returns_policy_block (line 292) | def test_browser_navigate_returns_policy_block(monkeypatch): function test_browser_navigate_allows_when_shared_file_missing (line 317) | def test_browser_navigate_allows_when_shared_file_missing(monkeypatch, t... function test_web_extract_short_circuits_blocked_url (line 343) | async def test_web_extract_short_circuits_blocked_url(monkeypatch): function test_check_website_access_fails_open_on_malformed_config (line 369) | def test_check_website_access_fails_open_on_malformed_config(tmp_path, m... function test_web_extract_blocks_redirected_final_url (line 389) | async def test_web_extract_blocks_redirected_final_url(monkeypatch): function test_web_crawl_short_circuits_blocked_url (line 426) | async def test_web_crawl_short_circuits_blocked_url(monkeypatch): function test_web_crawl_blocks_redirected_final_url (line 455) | async def test_web_crawl_blocks_redirected_final_url(monkeypatch): FILE: tests/tools/test_windows_compat.py function _get_preexec_fn_values (line 22) | def _get_preexec_fn_values(filepath: Path) -> list: class TestNoUnconditionalSetsid (line 33) | class TestNoUnconditionalSetsid: method test_preexec_fn_is_guarded (line 37) | def test_preexec_fn_is_guarded(self, relpath): class TestIsWindowsConstant (line 49) | class TestIsWindowsConstant: method test_has_is_windows (line 53) | def test_has_is_windows(self, relpath): class TestKillpgGuarded (line 63) | class TestKillpgGuarded: method test_no_unguarded_killpg (line 67) | def test_no_unguarded_killpg(self, relpath): FILE: tests/tools/test_write_deny.py class TestWriteDenyExactPaths (line 10) | class TestWriteDenyExactPaths: method test_etc_shadow (line 11) | def test_etc_shadow(self): method test_etc_passwd (line 14) | def test_etc_passwd(self): method test_etc_sudoers (line 17) | def test_etc_sudoers(self): method test_ssh_authorized_keys (line 20) | def test_ssh_authorized_keys(self): method test_ssh_id_rsa (line 23) | def test_ssh_id_rsa(self): method test_ssh_id_ed25519 (line 27) | def test_ssh_id_ed25519(self): method test_netrc (line 31) | def test_netrc(self): method test_hermes_env (line 35) | def test_hermes_env(self): method test_shell_profiles (line 39) | def test_shell_profiles(self): method test_package_manager_configs (line 44) | def test_package_manager_configs(self): class TestWriteDenyPrefixes (line 50) | class TestWriteDenyPrefixes: method test_ssh_prefix (line 51) | def test_ssh_prefix(self): method test_aws_prefix (line 55) | def test_aws_prefix(self): method test_gnupg_prefix (line 59) | def test_gnupg_prefix(self): method test_kube_prefix (line 63) | def test_kube_prefix(self): method test_sudoers_d_prefix (line 67) | def test_sudoers_d_prefix(self): method test_systemd_prefix (line 70) | def test_systemd_prefix(self): class TestWriteAllowed (line 74) | class TestWriteAllowed: method test_tmp_file (line 75) | def test_tmp_file(self): method test_project_file (line 78) | def test_project_file(self): method test_hermes_config_not_env (line 81) | def test_hermes_config_not_env(self): FILE: tests/tools/test_yolo_mode.py function _clear_approval_state (line 17) | def _clear_approval_state(): class TestYoloMode (line 27) | class TestYoloMode: method test_dangerous_command_blocked_normally (line 30) | def test_dangerous_command_blocked_normally(self, monkeypatch): method test_dangerous_command_approved_in_yolo_mode (line 48) | def test_dangerous_command_approved_in_yolo_mode(self, monkeypatch): method test_yolo_mode_works_for_all_patterns (line 58) | def test_yolo_mode_works_for_all_patterns(self, monkeypatch): method test_combined_guard_bypasses_yolo_mode (line 76) | def test_combined_guard_bypasses_yolo_mode(self, monkeypatch): method test_yolo_mode_not_set_by_default (line 94) | def test_yolo_mode_not_set_by_default(self): method test_yolo_mode_empty_string_does_not_bypass (line 100) | def test_yolo_mode_empty_string_does_not_bypass(self, monkeypatch): FILE: tools/__init__.py function check_file_requirements (line 158) | def check_file_requirements(): FILE: tools/approval.py function _legacy_pattern_key (line 55) | def _legacy_pattern_key(pattern: str) -> str: function _approval_key_aliases (line 68) | def _approval_key_aliases(pattern_key: str) -> set[str]: function detect_dangerous_command (line 82) | def detect_dangerous_command(command: str) -> tuple: function submit_pending (line 106) | def submit_pending(session_key: str, approval: dict): function pop_pending (line 112) | def pop_pending(session_key: str) -> Optional[dict]: function has_pending (line 118) | def has_pending(session_key: str) -> bool: function approve_session (line 124) | def approve_session(session_key: str, pattern_key: str): function is_approved (line 130) | def is_approved(session_key: str, pattern_key: str) -> bool: function approve_permanent (line 144) | def approve_permanent(pattern_key: str): function load_permanent (line 150) | def load_permanent(patterns: set): function clear_session (line 156) | def clear_session(session_key: str): function load_permanent_allowlist (line 167) | def load_permanent_allowlist() -> set: function save_permanent_allowlist (line 184) | def save_permanent_allowlist(patterns: set): function prompt_dangerous_approval (line 199) | def prompt_dangerous_approval(command: str, description: str, function _get_approval_mode (line 280) | def _get_approval_mode() -> str: function _smart_approve (line 290) | def _smart_approve(command: str, description: str) -> str: function check_dangerous_command (line 342) | def check_dangerous_command(command: str, env_type: str, function check_all_command_guards (line 421) | def check_all_command_guards(command: str, env_type: str, FILE: tools/browser_providers/base.py class CloudBrowserProvider (line 7) | class CloudBrowserProvider(ABC): method provider_name (line 17) | def provider_name(self) -> str: method is_configured (line 21) | def is_configured(self) -> bool: method create_session (line 29) | def create_session(self, task_id: str) -> Dict[str, object]: method close_session (line 47) | def close_session(self, session_id: str) -> bool: method emergency_cleanup (line 54) | def emergency_cleanup(self, session_id: str) -> None: FILE: tools/browser_providers/browser_use.py class BrowserUseProvider (line 17) | class BrowserUseProvider(CloudBrowserProvider): method provider_name (line 20) | def provider_name(self) -> str: method is_configured (line 23) | def is_configured(self) -> bool: method _headers (line 30) | def _headers(self) -> Dict[str, str]: method create_session (line 42) | def create_session(self, task_id: str) -> Dict[str, object]: method close_session (line 68) | def close_session(self, session_id: str) -> bool: method emergency_cleanup (line 91) | def emergency_cleanup(self, session_id: str) -> None: FILE: tools/browser_providers/browserbase.py class BrowserbaseProvider (line 15) | class BrowserbaseProvider(CloudBrowserProvider): method provider_name (line 18) | def provider_name(self) -> str: method is_configured (line 21) | def is_configured(self) -> bool: method _get_config (line 31) | def _get_config(self) -> Dict[str, str]: method create_session (line 42) | def create_session(self, task_id: str) -> Dict[str, object]: method close_session (line 151) | def close_session(self, session_id: str) -> bool: method emergency_cleanup (line 186) | def emergency_cleanup(self, session_id: str) -> None: FILE: tools/browser_tool.py function _get_vision_model (line 99) | def _get_vision_model() -> Optional[str]: function _get_extraction_model (line 104) | def _get_extraction_model() -> Optional[str]: function _resolve_cdp_override (line 109) | def _resolve_cdp_override(cdp_url: str) -> str: function _get_cdp_override (line 158) | def _get_cdp_override() -> str: function _get_cloud_provider (line 181) | def _get_cloud_provider() -> Optional[CloudBrowserProvider]: function _socket_safe_tmpdir (line 207) | def _socket_safe_tmpdir() -> str: function _emergency_cleanup_all_sessions (line 252) | def _emergency_cleanup_all_sessions(): function _cleanup_inactive_browser_sessions (line 292) | def _cleanup_inactive_browser_sessions(): function _browser_cleanup_thread_worker (line 320) | def _browser_cleanup_thread_worker(): function _start_browser_cleanup_thread (line 342) | def _start_browser_cleanup_thread(): function _stop_browser_cleanup_thread (line 358) | def _stop_browser_cleanup_thread(): function _update_session_activity (line 366) | def _update_session_activity(task_id: str): function _create_local_session (line 539) | def _create_local_session(task_id: str) -> Dict[str, str]: function _create_cdp_session (line 552) | def _create_cdp_session(task_id: str, cdp_url: str) -> Dict[str, str]: function _get_session_info (line 566) | def _get_session_info(task_id: Optional[str] = None) -> Dict[str, str]: function _get_session_name (line 617) | def _get_session_name(task_id: Optional[str] = None) -> str: function _find_agent_browser (line 631) | def _find_agent_browser() -> str: function _extract_screenshot_path_from_text (line 667) | def _extract_screenshot_path_from_text(text: str) -> Optional[str]: function _run_browser_command (line 688) | def _run_browser_command( function _extract_relevant_content (line 884) | def _extract_relevant_content( function _truncate_snapshot (line 931) | def _truncate_snapshot(snapshot_text: str, max_chars: int = 8000) -> str: function browser_navigate (line 952) | def browser_navigate(url: str, task_id: Optional[str] = None) -> str: function browser_snapshot (line 1034) | def browser_snapshot( function browser_click (line 1084) | def browser_click(ref: str, task_id: Optional[str] = None) -> str: function browser_type (line 1115) | def browser_type(ref: str, text: str, task_id: Optional[str] = None) -> ... function browser_scroll (line 1149) | def browser_scroll(direction: str, task_id: Optional[str] = None) -> str: function browser_back (line 1183) | def browser_back(task_id: Optional[str] = None) -> str: function browser_press (line 1209) | def browser_press(key: str, task_id: Optional[str] = None) -> str: function browser_close (line 1235) | def browser_close(task_id: Optional[str] = None) -> str: function browser_console (line 1260) | def browser_console(clear: bool = False, task_id: Optional[str] = None) ... function _maybe_start_recording (line 1307) | def _maybe_start_recording(task_id: str): function _maybe_stop_recording (line 1342) | def _maybe_stop_recording(task_id: str): function browser_get_images (line 1357) | def browser_get_images(task_id: Optional[str] = None) -> str: function browser_vision (line 1411) | def browser_vision(question: str, annotate: bool = False, task_id: Optio... function _cleanup_old_screenshots (line 1548) | def _cleanup_old_screenshots(screenshots_dir, max_age_hours=24): function _cleanup_old_recordings (line 1572) | def _cleanup_old_recordings(max_age_hours=72): function cleanup_browser (line 1595) | def cleanup_browser(task_id: Optional[str] = None) -> None: function cleanup_all_browsers (line 1665) | def cleanup_all_browsers() -> None: function get_active_browser_sessions (line 1677) | def get_active_browser_sessions() -> Dict[str, Dict[str, str]]: function check_browser_requirements (line 1692) | def check_browser_requirements() -> bool: FILE: tools/checkpoint_manager.py function _shadow_repo_path (line 72) | def _shadow_repo_path(working_dir: str) -> Path: function _git_env (line 79) | def _git_env(shadow_repo: Path, working_dir: str) -> dict: function _run_git (line 90) | def _run_git( function _init_shadow_repo (line 136) | def _init_shadow_repo(shadow_repo: Path, working_dir: str) -> Optional[s... function _dir_file_count (line 164) | def _dir_file_count(path: str) -> int: class CheckpointManager (line 181) | class CheckpointManager: method __init__ (line 197) | def __init__(self, enabled: bool = False, max_snapshots: int = 50): method new_turn (line 207) | def new_turn(self) -> None: method ensure_checkpoint (line 215) | def ensure_checkpoint(self, working_dir: str, reason: str = "auto") ->... method list_checkpoints (line 251) | def list_checkpoints(self, working_dir: str) -> List[Dict]: method _parse_shortstat (line 296) | def _parse_shortstat(stat_line: str, entry: Dict) -> None: method diff (line 309) | def diff(self, working_dir: str, commit_hash: str) -> Dict: method restore (line 354) | def restore(self, working_dir: str, commit_hash: str, file_path: str =... method get_working_dir_for_path (line 409) | def get_working_dir_for_path(self, file_path: str) -> str: method _take (line 438) | def _take(self, working_dir: str, reason: str) -> bool: method _prune (line 489) | def _prune(self, shadow_repo: Path, working_dir: str) -> None: function format_checkpoint_list (line 520) | def format_checkpoint_list(checkpoints: List[Dict], directory: str) -> str: FILE: tools/clarify_tool.py function clarify_tool (line 23) | def clarify_tool( function check_clarify_requirements (line 78) | def check_clarify_requirements() -> bool: FILE: tools/code_execution_tool.py function check_sandbox_requirements (line 60) | def check_sandbox_requirements() -> bool: function generate_hermes_tools_module (line 117) | def generate_hermes_tools_module(enabled_tools: List[str]) -> str: function _rpc_server_loop (line 222) | def _rpc_server_loop( function execute_code (line 346) | def execute_code( function _kill_process_group (line 632) | def _kill_process_group(proc, escalate: bool = False): function _load_config (line 664) | def _load_config() -> dict: function build_execute_code_schema (line 704) | def build_execute_code_schema(enabled_sandbox_tools: set = None) -> dict: FILE: tools/cronjob_tools.py function _scan_cron_prompt (line 55) | def _scan_cron_prompt(prompt: str) -> str: function _origin_from_env (line 66) | def _origin_from_env() -> Optional[Dict[str, str]]: function _repeat_display (line 79) | def _repeat_display(job: Dict[str, Any]) -> str: function _canonical_skills (line 89) | def _canonical_skills(skill: Optional[str] = None, skills: Optional[Any]... function _normalize_optional_job_value (line 106) | def _normalize_optional_job_value(value: Optional[Any], *, strip_trailin... function _format_job (line 116) | def _format_job(job: Dict[str, Any]) -> Dict[str, Any]: function cronjob (line 141) | def cronjob( function schedule_cronjob (line 294) | def schedule_cronjob( function list_cronjobs (line 319) | def list_cronjobs(include_disabled: bool = False, task_id: str = None) -... function remove_cronjob (line 323) | def remove_cronjob(job_id: str, task_id: str = None) -> str: function check_cronjob_requirements (line 410) | def check_cronjob_requirements() -> bool: function get_cronjob_tool_definitions (line 425) | def get_cronjob_tool_definitions(): FILE: tools/debug_helpers.py class DebugSession (line 35) | class DebugSession: method __init__ (line 42) | def __init__(self, tool_name: str, *, env_var: str) -> None: method active (line 56) | def active(self) -> bool: method log_call (line 59) | def log_call(self, call_name: str, call_data: Dict[str, Any]) -> None: method save (line 69) | def save(self) -> None: method get_session_info (line 90) | def get_session_info(self) -> Dict[str, Any]: FILE: tools/delegate_tool.py function check_delegate_requirements (line 43) | def check_delegate_requirements() -> bool: function _build_child_system_prompt (line 48) | def _build_child_system_prompt(goal: str, context: Optional[str] = None)... function _strip_blocked_tools (line 70) | def _strip_blocked_tools(toolsets: List[str]) -> List[str]: function _build_child_progress_callback (line 78) | def _build_child_progress_callback(task_index: int, parent_agent, task_c... function _build_child_agent (line 150) | def _build_child_agent( function _run_single_child (line 249) | def _run_single_child( function delegate_task (line 398) | def delegate_task( function _resolve_delegation_credentials (line 565) | def _resolve_delegation_credentials(cfg: dict, parent_agent) -> dict: function _load_config (line 654) | def _load_config() -> dict: FILE: tools/environments/base.py function get_sandbox_dir (line 11) | def get_sandbox_dir() -> Path: class BaseEnvironment (line 26) | class BaseEnvironment(ABC): method __init__ (line 33) | def __init__(self, cwd: str, timeout: int, env: dict = None): method execute (line 39) | def execute(self, command: str, cwd: str = "", *, method cleanup (line 46) | def cleanup(self): method stop (line 50) | def stop(self): method __del__ (line 54) | def __del__(self): method _prepare_command (line 64) | def _prepare_command(self, command: str) -> tuple[str, str | None]: method _build_run_kwargs (line 77) | def _build_run_kwargs(self, timeout: int | None, method _timeout_result (line 94) | def _timeout_result(self, timeout: int | None) -> dict: FILE: tools/environments/daytona.py class DaytonaEnvironment (line 23) | class DaytonaEnvironment(BaseEnvironment): method __init__ (line 30) | def __init__( method _ensure_sandbox_ready (line 126) | def _ensure_sandbox_ready(self): method _exec_in_thread (line 133) | def _exec_in_thread(self, exec_command: str, cwd: Optional[str], timeo... method execute (line 189) | def execute(self, command: str, cwd: str = "", *, method cleanup (line 236) | def cleanup(self): FILE: tools/environments/docker.py function _normalize_forward_env_names (line 37) | def _normalize_forward_env_names(forward_env: list[str] | None) -> list[... function _load_hermes_env_vars (line 62) | def _load_hermes_env_vars() -> dict[str, str]: function find_docker (line 72) | def find_docker() -> Optional[str]: function _ensure_docker_available (line 122) | def _ensure_docker_available() -> None: class DockerEnvironment (line 188) | class DockerEnvironment(BaseEnvironment): method __init__ (line 200) | def __init__( method _storage_opt_supported (line 333) | def _storage_opt_supported() -> bool: method execute (line 372) | def execute(self, command: str, cwd: str = "", *, method cleanup (line 457) | def cleanup(self): FILE: tools/environments/local.py function _build_provider_env_blocklist (line 32) | def _build_provider_env_blocklist() -> frozenset: function _sanitize_subprocess_env (line 134) | def _sanitize_subprocess_env(base_env: dict | None, extra_env: dict | No... function _find_bash (line 158) | def _find_bash() -> str: function _clean_shell_noise (line 224) | def _clean_shell_noise(output: str) -> str: function _make_run_env (line 260) | def _make_run_env(env: dict) -> dict: function _extract_fenced_output (line 276) | def _extract_fenced_output(raw: str) -> str: class LocalEnvironment (line 300) | class LocalEnvironment(PersistentShellMixin, BaseEnvironment): method __init__ (line 312) | def __init__(self, cwd: str = "", timeout: int = 60, env: dict = None, method _temp_prefix (line 320) | def _temp_prefix(self) -> str: method _spawn_shell_process (line 323) | def _spawn_shell_process(self) -> subprocess.Popen: method _read_temp_files (line 336) | def _read_temp_files(self, *paths: str) -> list[str]: method _kill_shell_children (line 346) | def _kill_shell_children(self): method _cleanup_temp_files (line 357) | def _cleanup_temp_files(self): method _execute_oneshot (line 362) | def _execute_oneshot(self, command: str, cwd: str = "", *, FILE: tools/environments/modal.py function _load_snapshots (line 25) | def _load_snapshots() -> Dict[str, str]: function _save_snapshots (line 35) | def _save_snapshots(data: Dict[str, str]) -> None: class ModalEnvironment (line 41) | class ModalEnvironment(BaseEnvironment): method __init__ (line 51) | def __init__( method execute (line 102) | def execute(self, command: str, cwd: str = "", *, method cleanup (line 153) | def cleanup(self): FILE: tools/environments/persistent_shell.py class PersistentShellMixin (line 16) | class PersistentShellMixin: method _spawn_shell_process (line 26) | def _spawn_shell_process(self) -> subprocess.Popen: ... method _read_temp_files (line 29) | def _read_temp_files(self, *paths: str) -> list[str]: ... method _kill_shell_children (line 32) | def _kill_shell_children(self): ... method _execute_oneshot (line 35) | def _execute_oneshot(self, command: str, cwd: str, *, method _cleanup_temp_files (line 40) | def _cleanup_temp_files(self): ... method _temp_prefix (line 46) | def _temp_prefix(self) -> str: method _init_persistent_shell (line 53) | def _init_persistent_shell(self): method _cleanup_persistent_shell (line 105) | def _cleanup_persistent_shell(self): method execute (line 132) | def execute(self, command: str, cwd: str = "", *, method cleanup (line 143) | def cleanup(self): method _drain_shell_output (line 151) | def _drain_shell_output(self): method _send_to_shell (line 159) | def _send_to_shell(self, text: str): method _read_persistent_output (line 168) | def _read_persistent_output(self) -> tuple[str, int, str]: method _execute_persistent (line 187) | def _execute_persistent(self, command: str, cwd: str, *, method _execute_persistent_locked (line 206) | def _execute_persistent_locked(self, command: str, cwd: str, method _merge_output (line 266) | def _merge_output(stdout: str, stderr: str) -> str: FILE: tools/environments/singularity.py function _find_singularity_executable (line 28) | def _find_singularity_executable() -> str: function _ensure_singularity_available (line 45) | def _ensure_singularity_available() -> str: function _load_snapshots (line 79) | def _load_snapshots() -> Dict[str, str]: function _save_snapshots (line 88) | def _save_snapshots(data: Dict[str, str]) -> None: function _get_scratch_dir (line 97) | def _get_scratch_dir() -> Path: function _get_apptainer_cache_dir (line 126) | def _get_apptainer_cache_dir() -> Path: function _get_or_build_sif (line 142) | def _get_or_build_sif(image: str, executable: str = "apptainer") -> str: class SingularityEnvironment (line 200) | class SingularityEnvironment(BaseEnvironment): method __init__ (line 211) | def __init__( method _start_instance (line 244) | def _start_instance(self): method execute (line 275) | def execute(self, command: str, cwd: str = "", *, method cleanup (line 352) | def cleanup(self): FILE: tools/environments/ssh.py function _ensure_ssh_available (line 18) | def _ensure_ssh_available() -> None: class SSHEnvironment (line 26) | class SSHEnvironment(PersistentShellMixin, BaseEnvironment): method __init__ (line 43) | def __init__(self, host: str, user: str, cwd: str = "~", method _build_ssh_command (line 62) | def _build_ssh_command(self, extra_args: list | None = None) -> list: method _establish_connection (line 79) | def _establish_connection(self): method _temp_prefix (line 93) | def _temp_prefix(self) -> str: method _spawn_shell_process (line 96) | def _spawn_shell_process(self) -> subprocess.Popen: method _read_temp_files (line 107) | def _read_temp_files(self, *paths: str) -> list[str]: method _kill_shell_children (line 134) | def _kill_shell_children(self): method _cleanup_temp_files (line 144) | def _cleanup_temp_files(self): method _execute_oneshot (line 152) | def _execute_oneshot(self, command: str, cwd: str = "", *, method cleanup (line 220) | def cleanup(self): FILE: tools/file_operations.py function _get_safe_write_root (line 78) | def _get_safe_write_root() -> Optional[str]: function _is_write_denied (line 95) | def _is_write_denied(path: str) -> bool: class ReadResult (line 120) | class ReadResult: method to_dict (line 135) | def to_dict(self) -> dict: class WriteResult (line 140) | class WriteResult: method to_dict (line 147) | def to_dict(self) -> dict: class PatchResult (line 152) | class PatchResult: method to_dict (line 162) | def to_dict(self) -> dict: class SearchMatch (line 180) | class SearchMatch: class SearchResult (line 189) | class SearchResult: method to_dict (line 198) | def to_dict(self) -> dict: class LintResult (line 217) | class LintResult: method to_dict (line 224) | def to_dict(self) -> dict: class ExecuteResult (line 234) | class ExecuteResult: class FileOperations (line 244) | class FileOperations(ABC): method read_file (line 248) | def read_file(self, path: str, offset: int = 1, limit: int = 500) -> R... method write_file (line 253) | def write_file(self, path: str, content: str) -> WriteResult: method patch_replace (line 258) | def patch_replace(self, path: str, old_string: str, new_string: str, method patch_v4a (line 264) | def patch_v4a(self, patch_content: str) -> PatchResult: method search (line 269) | def search(self, pattern: str, path: str = ".", target: str = "content", class ShellFileOperations (line 318) | class ShellFileOperations(FileOperations): method __init__ (line 326) | def __init__(self, terminal_env, cwd: str = None): method _exec (line 346) | def _exec(self, command: str, cwd: str = None, timeout: int = None, method _has_command (line 366) | def _has_command(self, cmd: str) -> bool: method _is_likely_binary (line 373) | def _is_likely_binary(self, path: str, content_sample: str = None) -> ... method _is_image (line 393) | def _is_image(self, path: str) -> bool: method _add_line_numbers (line 398) | def _add_line_numbers(self, content: str, start_line: int = 1) -> str: method _expand_path (line 409) | def _expand_path(self, path: str) -> str: method _escape_shell_arg (line 442) | def _escape_shell_arg(self, arg: str) -> str: method _unified_diff (line 447) | def _unified_diff(self, old_content: str, new_content: str, filename: ... method read_file (line 462) | def read_file(self, path: str, offset: int = 1, limit: int = 500) -> R... method _read_image (line 555) | def _read_image(self, path: str) -> ReadResult: method _suggest_similar_files (line 618) | def _suggest_similar_files(self, path: str) -> ReadResult: method write_file (line 647) | def write_file(self, path: str, content: str) -> WriteResult: method patch_replace (line 705) | def patch_replace(self, path: str, old_string: str, new_string: str, method patch_v4a (line 766) | def patch_v4a(self, patch_content: str) -> PatchResult: method _check_lint (line 796) | def _check_lint(self, path: str) -> LintResult: method search (line 832) | def search(self, pattern: str, path: str = ".", target: str = "content", method _search_files (line 868) | def _search_files(self, pattern: str, path: str, limit: int, offset: i... method _search_files_rg (line 919) | def _search_files_rg(self, pattern: str, path: str, limit: int, offset... method _search_content (line 950) | def _search_content(self, pattern: str, path: str, file_glob: Optional... method _search_with_rg (line 967) | def _search_with_rg(self, pattern: str, path: str, file_glob: Optional... method _search_with_grep (line 1066) | def _search_with_grep(self, pattern: str, path: str, file_glob: Option... FILE: tools/file_tools.py function _is_expected_write_exception (line 18) | def _is_expected_write_exception(exc: Exception) -> bool: function _get_file_ops (line 39) | def _get_file_ops(task_id: str = "default") -> ShellFileOperations: function clear_file_ops_cache (line 160) | def clear_file_ops_cache(task_id: str = None): function read_file_tool (line 169) | def read_file_tool(path: str, offset: int = 1, limit: int = 500, task_id... function get_read_files_summary (line 238) | def get_read_files_summary(task_id: str = "default") -> list: function clear_read_tracker (line 258) | def clear_read_tracker(task_id: str = None): function notify_other_tool_call (line 272) | def notify_other_tool_call(task_id: str = "default"): function write_file_tool (line 288) | def write_file_tool(path: str, content: str, task_id: str = "default") -... function patch_tool (line 302) | def patch_tool(mode: str = "replace", path: str = None, old_string: str ... function search_tool (line 333) | def search_tool(pattern: str, target: str = "content", path: str = ".", function get_file_tools (line 409) | def get_file_tools(): function _check_file_reqs (line 420) | def _check_file_reqs(): function _handle_read_file (line 489) | def _handle_read_file(args, **kw): function _handle_write_file (line 494) | def _handle_write_file(args, **kw): function _handle_patch (line 499) | def _handle_patch(args, **kw): function _handle_search_files (line 507) | def _handle_search_files(args, **kw): FILE: tools/fuzzy_match.py function _unicode_normalize (line 43) | def _unicode_normalize(text: str) -> str: function fuzzy_find_and_replace (line 50) | def fuzzy_find_and_replace(content: str, old_string: str, new_string: str, function _apply_replacements (line 103) | def _apply_replacements(content: str, matches: List[Tuple[int, int]], ne... function _strategy_exact (line 130) | def _strategy_exact(content: str, pattern: str) -> List[Tuple[int, int]]: function _strategy_line_trimmed (line 143) | def _strategy_line_trimmed(content: str, pattern: str) -> List[Tuple[int... function _strategy_whitespace_normalized (line 163) | def _strategy_whitespace_normalized(content: str, pattern: str) -> List[... function _strategy_indentation_flexible (line 184) | def _strategy_indentation_flexible(content: str, pattern: str) -> List[T... function _strategy_escape_normalized (line 205) | def _strategy_escape_normalized(content: str, pattern: str) -> List[Tupl... function _strategy_trimmed_boundary (line 224) | def _strategy_trimmed_boundary(content: str, pattern: str) -> List[Tuple... function _strategy_block_anchor (line 266) | def _strategy_block_anchor(content: str, pattern: str) -> List[Tuple[int... function _strategy_context_aware (line 320) | def _strategy_context_aware(content: str, pattern: str) -> List[Tuple[in... function _calculate_line_positions (line 359) | def _calculate_line_positions(content_lines: List[str], start_line: int, function _find_normalized_matches (line 379) | def _find_normalized_matches(content: str, content_lines: List[str], function _map_normalized_positions (line 414) | def _map_normalized_positions(original: str, normalized: str, FILE: tools/homeassistant_tool.py function _get_config (line 31) | def _get_config(): function _get_headers (line 54) | def _get_headers(token: str = "") -> Dict[str, str]: function _filter_and_summarize (line 68) | def _filter_and_summarize( function _async_list_entities (line 96) | async def _async_list_entities( function _async_get_state (line 113) | async def _async_get_state(entity_id: str) -> Dict[str, Any]: function _build_service_payload (line 133) | def _build_service_payload( function _parse_service_response (line 147) | def _parse_service_response( function _async_call_service (line 168) | async def _async_call_service( function _run_async (line 198) | def _run_async(coro): function _handle_list_entities (line 215) | def _handle_list_entities(args: dict, **kw) -> str: function _handle_get_state (line 227) | def _handle_get_state(args: dict, **kw) -> str: function _handle_call_service (line 242) | def _handle_call_service(args: dict, **kw) -> str: function _async_list_services (line 272) | async def _async_list_services(domain: Optional[str] = None) -> Dict[str... function _handle_list_services (line 306) | def _handle_list_services(args: dict, **kw) -> str: function _check_ha_available (line 321) | def _check_ha_available() -> bool: FILE: tools/honcho_tools.py function set_session_context (line 28) | def set_session_context(session_manager, session_key: str) -> None: function clear_session_context (line 38) | def clear_session_context() -> None: function _check_honcho_available (line 47) | def _check_honcho_available() -> bool: function _resolve_session_context (line 52) | def _resolve_session_context(**kwargs): function _handle_honcho_profile (line 78) | def _handle_honcho_profile(args: dict, **kw) -> str: function _handle_honcho_search (line 120) | def _handle_honcho_search(args: dict, **kw) -> str: function _handle_honcho_context (line 166) | def _handle_honcho_context(args: dict, **kw) -> str: function _handle_honcho_conclude (line 209) | def _handle_honcho_conclude(args: dict, **kw) -> str: FILE: tools/image_generation_tool.py function _validate_parameters (line 82) | def _validate_parameters( function _upscale_image (line 155) | def _upscale_image(image_url: str, original_prompt: str) -> Dict[str, Any]: function image_generate_tool (line 216) | def image_generate_tool( function check_fal_api_key (line 396) | def check_fal_api_key() -> bool: function check_image_generation_requirements (line 406) | def check_image_generation_requirements() -> bool: function get_debug_session_info (line 426) | def get_debug_session_info() -> Dict[str, Any]: function _handle_image_generate (line 538) | def _handle_image_generate(args, **kw): FILE: tools/interrupt.py function set_interrupt (line 18) | def set_interrupt(active: bool) -> None: function is_interrupted (line 26) | def is_interrupted() -> bool: FILE: tools/mcp_tool.py function _build_safe_env (line 152) | def _build_safe_env(user_env: Optional[dict]) -> dict: function _sanitize_error (line 171) | def _sanitize_error(text: str) -> str: function _prepend_path (line 180) | def _prepend_path(env: dict, directory: str) -> dict: function _resolve_stdio_command (line 194) | def _resolve_stdio_command(command: str, env: dict) -> tuple[str, dict]: function _format_connect_error (line 230) | def _format_connect_error(exc: BaseException) -> str: function _safe_numeric (line 294) | def _safe_numeric(value, default, coerce=int, minimum=1): class SamplingHandler (line 309) | class SamplingHandler: method __init__ (line 324) | def __init__(self, server_name: str, config: dict): method _check_rate_limit (line 347) | def _check_rate_limit(self) -> bool: method _resolve_model (line 359) | def _resolve_model(self, preferences) -> Optional[str]: method _extract_tool_result_text (line 372) | def _extract_tool_result_text(block) -> str: method _convert_messages (line 379) | def _convert_messages(self, params) -> List[dict]: method _error (line 451) | def _error(message: str, code: int = -1): method _build_tool_use_result (line 459) | def _build_tool_use_result(self, choice, response): method _build_text_result (line 516) | def _build_text_result(self, choice, response): method session_kwargs (line 537) | def session_kwargs(self) -> dict: method __call__ (line 548) | async def __call__(self, context, params): class MCPServerTask (line 680) | class MCPServerTask: method __init__ (line 696) | def __init__(self, name: str): method _is_http (line 709) | def _is_http(self) -> bool: method _run_stdio (line 713) | async def _run_stdio(self, config: dict): method _run_http (line 741) | async def _run_http(self, config: dict): method _discover_tools (line 767) | async def _discover_tools(self): method run (line 778) | async def run(self, config: dict): method start (line 854) | async def start(self, config: dict): method shutdown (line 861) | async def shutdown(self): function _ensure_mcp_loop (line 894) | def _ensure_mcp_loop(): function _run_on_mcp_loop (line 909) | def _run_on_mcp_loop(coro, timeout: float = 30): function _load_mcp_config (line 923) | def _load_mcp_config() -> Dict[str, dict]: function _connect_server (line 947) | async def _connect_server(name: str, config: dict) -> MCPServerTask: function _make_tool_handler (line 967) | def _make_tool_handler(server_name: str, tool_name: str, tool_timeout: f... function _make_list_resources_handler (line 1019) | def _make_list_resources_handler(server_name: str, tool_timeout: float): function _make_read_resource_handler (line 1061) | def _make_read_resource_handler(server_name: str, tool_timeout: float): function _make_list_prompts_handler (line 1103) | def _make_list_prompts_handler(server_name: str, tool_timeout: float): function _make_get_prompt_handler (line 1150) | def _make_get_prompt_handler(server_name: str, tool_timeout: float): function _make_check_fn (line 1203) | def _make_check_fn(server_name: str): function _normalize_mcp_input_schema (line 1218) | def _normalize_mcp_input_schema(schema: dict | None) -> dict: function _convert_mcp_schema (line 1229) | def _convert_mcp_schema(server_name: str, mcp_tool) -> dict: function _sync_mcp_toolsets (line 1251) | def _sync_mcp_toolsets(server_names: Optional[List[str]] = None) -> None: function _build_utility_schemas (line 1302) | def _build_utility_schemas(server_name: str) -> List[dict]: function _normalize_name_filter (line 1373) | def _normalize_name_filter(value: Any, label: str) -> set[str]: function _parse_boolish (line 1385) | def _parse_boolish(value: Any, default: bool = True) -> bool: function _select_utility_schemas (line 1409) | def _select_utility_schemas(server_name: str, server: MCPServerTask, con... function _existing_tool_names (line 1438) | def _existing_tool_names() -> List[str]: function _discover_and_register_server (line 1451) | async def _discover_and_register_server(name: str, config: dict) -> List... function discover_mcp_tools (line 1556) | def discover_mcp_tools() -> List[str]: function get_mcp_status (line 1642) | def get_mcp_status() -> List[dict]: function probe_mcp_server_tools (line 1682) | def probe_mcp_server_tools() -> Dict[str, List[tuple]]: function shutdown_mcp_servers (line 1748) | def shutdown_mcp_servers(): function _stop_mcp_loop (line 1788) | def _stop_mcp_loop(): FILE: tools/memory_tool.py function _scan_memory_content (line 74) | def _scan_memory_content(content: str) -> Optional[str]: class MemoryStore (line 89) | class MemoryStore: method __init__ (line 100) | def __init__(self, memory_char_limit: int = 2200, user_char_limit: int... method load_from_disk (line 108) | def load_from_disk(self): method _file_lock (line 127) | def _file_lock(path: Path): method _path_for (line 144) | def _path_for(target: str) -> Path: method _reload_target (line 149) | def _reload_target(self, target: str): method save_to_disk (line 158) | def save_to_disk(self, target: str): method _entries_for (line 163) | def _entries_for(self, target: str) -> List[str]: method _set_entries (line 168) | def _set_entries(self, target: str, entries: List[str]): method _char_count (line 174) | def _char_count(self, target: str) -> int: method _char_limit (line 180) | def _char_limit(self, target: str) -> int: method add (line 185) | def add(self, target: str, content: str) -> Dict[str, Any]: method replace (line 230) | def replace(self, target: str, old_text: str, new_content: str) -> Dic... method remove (line 288) | def remove(self, target: str, old_text: str) -> Dict[str, Any]: method format_for_system_prompt (line 322) | def format_for_system_prompt(self, target: str) -> Optional[str]: method _success_response (line 337) | def _success_response(self, target: str, message: str = None) -> Dict[... method _render_block (line 354) | def _render_block(self, target: str, entries: List[str]) -> str: method _read_file (line 373) | def _read_file(path: Path) -> List[str]: method _write_file (line 395) | def _write_file(path: Path, entries: List[str]): function memory_tool (line 426) | def memory_tool( function check_memory_requirements (line 467) | def check_memory_requirements() -> bool: FILE: tools/mixture_of_agents_tool.py function _construct_aggregator_prompt (line 88) | def _construct_aggregator_prompt(system_prompt: str, responses: List[str... function _run_reference_model_safe (line 103) | async def _run_reference_model_safe( function _run_aggregator_model (line 172) | async def _run_aggregator_model( function mixture_of_agents_tool (line 219) | async def mixture_of_agents_tool( function check_moa_requirements (line 395) | def check_moa_requirements() -> bool: function get_debug_session_info (line 405) | def get_debug_session_info() -> Dict[str, Any]: function get_available_models (line 415) | def get_available_models() -> Dict[str, List[str]]: function get_moa_configuration (line 429) | def get_moa_configuration() -> Dict[str, Any]: FILE: tools/neutts_synth.py function _write_wav (line 21) | def _write_wav(path: str, samples, sample_rate: int = 24000) -> None: function main (line 51) | def main(): FILE: tools/openrouter_client.py function get_async_client (line 14) | def get_async_client(): function check_api_key (line 31) | def check_api_key() -> bool: FILE: tools/patch_parser.py class OperationType (line 37) | class OperationType(Enum): class HunkLine (line 45) | class HunkLine: class Hunk (line 52) | class Hunk: class PatchOperation (line 59) | class PatchOperation: function parse_v4a_patch (line 68) | def parse_v4a_patch(patch_content: str) -> Tuple[List[PatchOperation], O... function apply_v4a_operations (line 209) | def apply_v4a_operations(operations: List[PatchOperation], function _apply_add (line 297) | def _apply_add(op: PatchOperation, file_ops: Any) -> Tuple[bool, str]: function _apply_delete (line 318) | def _apply_delete(op: PatchOperation, file_ops: Any) -> Tuple[bool, str]: function _apply_move (line 337) | def _apply_move(op: PatchOperation, file_ops: Any) -> Tuple[bool, str]: function _apply_update (line 351) | def _apply_update(op: PatchOperation, file_ops: Any) -> Tuple[bool, str]: FILE: tools/process_registry.py class ProcessSession (line 65) | class ProcessSession: class ProcessRegistry (line 91) | class ProcessRegistry: method __init__ (line 109) | def __init__(self): method _clean_shell_noise (line 118) | def _clean_shell_noise(text: str) -> str: method spawn_local (line 127) | def spawn_local( method spawn_via_env (line 239) | def spawn_via_env( method _reader_loop (line 312) | def _reader_loop(self, session: ProcessSession): method _env_poller_loop (line 339) | def _env_poller_loop( method _pty_reader_loop (line 383) | def _pty_reader_loop(self, session: ProcessSession): method _move_to_finished (line 413) | def _move_to_finished(self, session: ProcessSession): method get (line 422) | def get(self, session_id: str) -> Optional[ProcessSession]: method poll (line 427) | def poll(self, session_id: str) -> dict: method read_log (line 451) | def read_log(self, session_id: str, offset: int = 0, limit: int = 200)... method wait (line 477) | def wait(self, session_id: str, timeout: int = None) -> dict: method kill_process (line 544) | def kill_process(self, session_id: str) -> dict: method write_stdin (line 585) | def write_stdin(self, session_id: str, data: str) -> dict: method submit_stdin (line 612) | def submit_stdin(self, session_id: str, data: str = "") -> dict: method list_sessions (line 616) | def list_sessions(self, task_id: str = None) -> list: method has_active_processes (line 645) | def has_active_processes(self, task_id: str) -> bool: method has_active_for_session (line 653) | def has_active_for_session(self, session_key: str) -> bool: method kill_all (line 661) | def kill_all(self, task_id: str = None) -> int: method _prune_if_needed (line 678) | def _prune_if_needed(self): method cleanup_expired (line 695) | def cleanup_expired(self): method _write_checkpoint (line 702) | def _write_checkpoint(self): method recover_from_checkpoint (line 729) | def recover_from_checkpoint(self) -> int: function _handle_process (line 852) | def _handle_process(args, **kw): FILE: tools/registry.py class ToolEntry (line 24) | class ToolEntry: method __init__ (line 32) | def __init__(self, name, toolset, schema, handler, check_fn, class ToolRegistry (line 45) | class ToolRegistry: method __init__ (line 48) | def __init__(self): method register (line 56) | def register( method get_definitions (line 87) | def get_definitions(self, tool_names: Set[str], quiet: bool = False) -... method dispatch (line 115) | def dispatch(self, name: str, args: dict, **kwargs) -> str: method get_all_tool_names (line 138) | def get_all_tool_names(self) -> List[str]: method get_toolset_for_tool (line 142) | def get_toolset_for_tool(self, name: str) -> Optional[str]: method get_emoji (line 147) | def get_emoji(self, name: str, default: str = "⚡") -> str: method get_tool_to_toolset_map (line 152) | def get_tool_to_toolset_map(self) -> Dict[str, str]: method is_toolset_available (line 156) | def is_toolset_available(self, toolset: str) -> bool: method check_toolset_requirements (line 171) | def check_toolset_requirements(self) -> Dict[str, bool]: method get_available_toolsets (line 176) | def get_available_toolsets(self) -> Dict[str, dict]: method get_toolset_requirements (line 195) | def get_toolset_requirements(self) -> Dict[str, dict]: method check_tool_availability (line 215) | def check_tool_availability(self, quiet: bool = False): FILE: tools/rl_training_tool.py function _ensure_logs_dir (line 57) | def _ensure_logs_dir(): class EnvironmentInfo (line 111) | class EnvironmentInfo: class RunState (line 121) | class RunState: function _scan_environments (line 153) | def _scan_environments() -> List[EnvironmentInfo]: function _get_env_config_fields (line 214) | def _get_env_config_fields(env_file_path: str) -> Dict[str, Dict[str, An... function _initialize_environments (line 298) | def _initialize_environments(): function _spawn_training_run (line 309) | async def _spawn_training_run(run_state: RunState, config_path: Path): function _monitor_training_run (line 426) | async def _monitor_training_run(run_state: RunState): function _stop_training_run (line 459) | def _stop_training_run(run_state: RunState): function rl_list_environments (line 504) | async def rl_list_environments() -> str: function rl_select_environment (line 549) | async def rl_select_environment(name: str) -> str: function rl_get_current_config (line 608) | async def rl_get_current_config() -> str: function rl_edit_config (line 655) | async def rl_edit_config(field: str, value: Any) -> str: function rl_start_training (line 707) | async def rl_start_training() -> str: function rl_check_status (line 814) | async def rl_check_status(run_id: str) -> str: function rl_stop_training (line 905) | async def rl_stop_training(run_id: str) -> str: function rl_get_results (line 937) | async def rl_get_results(run_id: str) -> str: function rl_list_runs (line 981) | async def rl_list_runs() -> str: function rl_test_inference (line 1020) | async def rl_test_inference( function check_rl_python_version (line 1320) | def check_rl_python_version() -> bool: function check_rl_api_keys (line 1329) | def check_rl_api_keys() -> bool: function get_missing_keys (line 1345) | def get_missing_keys() -> List[str]: FILE: tools/send_message_tool.py function send_message_tool (line 56) | def send_message_tool(args, **kw): function _handle_list (line 66) | def _handle_list(): function _handle_send (line 75) | def _handle_send(args): function _parse_target_ref (line 195) | def _parse_target_ref(platform_name: str, target_ref: str): function _describe_media_for_mirror (line 206) | def _describe_media_for_mirror(media_files): function _get_cron_auto_delivery_target (line 225) | def _get_cron_auto_delivery_target(): function _maybe_skip_cron_duplicate_send (line 239) | def _maybe_skip_cron_duplicate_send(platform_name: str, chat_id: str, th... function _send_to_platform (line 270) | async def _send_to_platform(platform, pconfig, chat_id, message, thread_... function _send_telegram (line 360) | async def _send_telegram(token, chat_id, message, media_files=None, thre... function _send_discord (line 481) | async def _send_discord(token, chat_id, message): function _send_slack (line 504) | async def _send_slack(token, chat_id, message): function _send_whatsapp (line 523) | async def _send_whatsapp(extra, chat_id, message): function _send_signal (line 551) | async def _send_signal(extra, chat_id, message): function _send_email (line 587) | async def _send_email(extra, chat_id, message): function _send_sms (line 616) | async def _send_sms(auth_token, chat_id, message): function _check_send_message (line 669) | def _check_send_message(): FILE: tools/session_search_tool.py function _format_timestamp (line 30) | def _format_timestamp(ts: Union[int, float, str, None]) -> str: function _format_conversation (line 56) | def _format_conversation(messages: List[Dict[str, Any]]) -> str: function _truncate_around_matches (line 90) | def _truncate_around_matches( function _summarize_session (line 126) | async def _summarize_session( function session_search (line 182) | def session_search( function check_session_search_requirements (line 355) | def check_session_search_requirements() -> bool: FILE: tools/skill_manager_tool.py function _security_scan_skill (line 55) | def _security_scan_skill(skill_dir: Path) -> Optional[str]: function check_skill_manage_requirements (line 86) | def check_skill_manage_requirements() -> bool: function _validate_name (line 95) | def _validate_name(name: str) -> Optional[str]: function _validate_frontmatter (line 109) | def _validate_frontmatter(content: str) -> Optional[str]: function _resolve_skill_dir (line 148) | def _resolve_skill_dir(name: str, category: str = None) -> Path: function _find_skill (line 155) | def _find_skill(name: str) -> Optional[Dict[str, Any]]: function _validate_file_path (line 168) | def _validate_file_path(file_path: str) -> Optional[str]: function _atomic_write_text (line 194) | def _atomic_write_text(file_path: Path, content: str, encoding: str = "u... function _create_skill (line 230) | def _create_skill(name: str, content: str, category: str = None) -> Dict... function _edit_skill (line 279) | def _edit_skill(name: str, content: str) -> Dict[str, Any]: function _patch_skill (line 308) | def _patch_skill( function _delete_skill (line 393) | def _delete_skill(name: str) -> Dict[str, Any]: function _write_file (line 413) | def _write_file(name: str, file_path: str, file_content: str) -> Dict[st... function _remove_file (line 448) | def _remove_file(name: str, file_path: str) -> Dict[str, Any]: function skill_manage (line 492) | def skill_manage( FILE: tools/skills_guard.py class Finding (line 57) | class Finding: class ScanResult (line 68) | class ScanResult: function scan_file (line 530) | def scan_file(file_path: Path, rel_path: str = "") -> List[Finding]: function scan_skill (line 595) | def scan_skill(skill_path: Path, source: str = "community") -> ScanResult: function should_allow_install (line 642) | def should_allow_install(result: ScanResult, force: bool = False) -> Tup... function format_scan_report (line 672) | def format_scan_report(result: ScanResult) -> str: function content_hash (line 703) | def content_hash(skill_path: Path) -> str: function _check_structure (line 722) | def _check_structure(skill_dir: Path) -> List[Finding]: function _unicode_char_name (line 839) | def _unicode_char_name(char: str) -> str: function llm_audit_skill (line 885) | def llm_audit_skill(skill_path: Path, static_result: ScanResult, function _parse_llm_response (line 985) | def _parse_llm_response(text: str, skill_name: str) -> List[Finding]: function _get_configured_model (line 1025) | def _get_configured_model() -> str: function _resolve_trust_level (line 1039) | def _resolve_trust_level(source: str) -> str: function _determine_verdict (line 1051) | def _determine_verdict(findings: List[Finding]) -> str: function _build_summary (line 1066) | def _build_summary(name: str, source: str, trust: str, verdict: str, fin... FILE: tools/skills_hub.py class SkillMeta (line 63) | class SkillMeta: class SkillBundle (line 77) | class SkillBundle: class GitHubAuth (line 91) | class GitHubAuth: method __init__ (line 100) | def __init__(self): method get_headers (line 105) | def get_headers(self) -> Dict[str, str]: method is_authenticated (line 113) | def is_authenticated(self) -> bool: method auth_method (line 116) | def auth_method(self) -> str: method _resolve_token (line 121) | def _resolve_token(self) -> Optional[str]: method _try_gh_cli (line 152) | def _try_gh_cli(self) -> Optional[str]: method _try_github_app (line 165) | def _try_github_app(self) -> Optional[str]: class SkillSource (line 214) | class SkillSource(ABC): method search (line 218) | def search(self, query: str, limit: int = 10) -> List[SkillMeta]: method fetch (line 223) | def fetch(self, identifier: str) -> Optional[SkillBundle]: method inspect (line 228) | def inspect(self, identifier: str) -> Optional[SkillMeta]: method source_id (line 233) | def source_id(self) -> str: method trust_level_for (line 237) | def trust_level_for(self, identifier: str) -> str: class GitHubSource (line 246) | class GitHubSource(SkillSource): method __init__ (line 255) | def __init__(self, auth: GitHubAuth, extra_taps: Optional[List[Dict]] ... method source_id (line 261) | def source_id(self) -> str: method trust_level_for (line 264) | def trust_level_for(self, identifier: str) -> str: method search (line 273) | def search(self, query: str, limit: int = 10) -> List[SkillMeta]: method fetch (line 301) | def fetch(self, identifier: str) -> Optional[SkillBundle]: method inspect (line 328) | def inspect(self, identifier: str) -> Optional[SkillMeta]: method _list_skills_in_repo (line 369) | def _list_skills_in_repo(self, repo: str, path: str) -> List[SkillMeta]: method _download_directory (line 406) | def _download_directory(self, repo: str, path: str) -> Dict[str, str]: method _fetch_file_content (line 437) | def _fetch_file_content(self, repo: str, path: str) -> Optional[str]: method _read_cache (line 452) | def _read_cache(self, key: str) -> Optional[list]: method _write_cache (line 465) | def _write_cache(self, key: str, data: list) -> None: method _meta_to_dict (line 475) | def _meta_to_dict(meta: SkillMeta) -> dict: method _parse_frontmatter_quick (line 488) | def _parse_frontmatter_quick(content: str) -> dict: class WellKnownSkillSource (line 507) | class WellKnownSkillSource(SkillSource): method source_id (line 512) | def source_id(self) -> str: method trust_level_for (line 515) | def trust_level_for(self, identifier: str) -> str: method search (line 518) | def search(self, query: str, limit: int = 10) -> List[SkillMeta]: method inspect (line 549) | def inspect(self, identifier: str) -> Optional[SkillMeta]: method fetch (line 580) | def fetch(self, identifier: str) -> Optional[SkillBundle]: method _query_to_index_url (line 619) | def _query_to_index_url(self, query: str) -> Optional[str]: method _parse_identifier (line 630) | def _parse_identifier(self, identifier: str) -> Optional[dict]: method _parse_index (line 668) | def _parse_index(self, index_url: str) -> Optional[dict]: method _index_entry (line 694) | def _index_entry(self, index_url: str, skill_name: str) -> Optional[di... method _fetch_text (line 704) | def _fetch_text(url: str) -> Optional[str]: method _wrap_identifier (line 714) | def _wrap_identifier(base_url: str, skill_name: str) -> str: class SkillsShSource (line 722) | class SkillsShSource(SkillSource): method __init__ (line 744) | def __init__(self, auth: GitHubAuth): method source_id (line 748) | def source_id(self) -> str: method trust_level_for (line 751) | def trust_level_for(self, identifier: str) -> str: method search (line 754) | def search(self, query: str, limit: int = 10) -> List[SkillMeta]: method fetch (line 788) | def fetch(self, identifier: str) -> Optional[SkillBundle]: method inspect (line 809) | def inspect(self, identifier: str) -> Optional[SkillMeta]: method _featured_skills (line 826) | def _featured_skills(self, limit: int) -> List[SkillMeta]: method _meta_from_search_item (line 866) | def _meta_from_search_item(self, item: dict) -> Optional[SkillMeta]: method _fetch_detail_page (line 902) | def _fetch_detail_page(self, identifier: str) -> Optional[dict]: method _parse_detail_page (line 920) | def _parse_detail_page(self, identifier: str, html: str) -> Optional[d... method _discover_identifier (line 957) | def _discover_identifier(self, identifier: str, detail: Optional[dict]... method _finalize_inspect_meta (line 983) | def _finalize_inspect_meta(self, meta: SkillMeta, canonical: str, deta... method _matches_skill_tokens (line 1001) | def _matches_skill_tokens(cls, meta: SkillMeta, skill_tokens: List[str... method _token_variants (line 1014) | def _token_variants(value: Optional[str]) -> set[str]: method _extract_repo_slug (line 1045) | def _extract_repo_slug(repo_value: str) -> Optional[str]: method _extract_first_match (line 1056) | def _extract_first_match(pattern: re.Pattern, text: str) -> Optional[s... method _detail_to_metadata (line 1065) | def _detail_to_metadata(self, canonical: str, detail: Optional[dict]) ... method _extract_weekly_installs (line 1081) | def _extract_weekly_installs(html: str) -> Optional[str]: method _extract_security_audits (line 1088) | def _extract_security_audits(html: str, identifier: str) -> Dict[str, ... method _strip_html (line 1101) | def _strip_html(value: str) -> str: method _normalize_identifier (line 1105) | def _normalize_identifier(identifier: str) -> str: method _candidate_identifiers (line 1113) | def _candidate_identifiers(identifier: str) -> List[str]: method _wrap_identifier (line 1136) | def _wrap_identifier(identifier: str) -> str: class ClawHubSource (line 1144) | class ClawHubSource(SkillSource): method source_id (line 1153) | def source_id(self) -> str: method trust_level_for (line 1156) | def trust_level_for(self, identifier: str) -> str: method _normalize_tags (line 1160) | def _normalize_tags(tags: Any) -> List[str]: method _coerce_skill_payload (line 1168) | def _coerce_skill_payload(data: Any) -> Optional[Dict[str, Any]]: method _query_terms (line 1181) | def _query_terms(query: str) -> List[str]: method _search_score (line 1185) | def _search_score(cls, query: str, meta: SkillMeta) -> int: method _dedupe_results (line 1234) | def _dedupe_results(results: List[SkillMeta]) -> List[SkillMeta]: method _exact_slug_meta (line 1245) | def _exact_slug_meta(self, query: str) -> Optional[SkillMeta]: method _finalize_search_results (line 1278) | def _finalize_search_results(self, query: str, results: List[SkillMeta... method search (line 1306) | def search(self, query: str, limit: int = 10) -> List[SkillMeta]: method fetch (line 1367) | def fetch(self, identifier: str) -> Optional[SkillBundle]: method inspect (line 1409) | def inspect(self, identifier: str) -> Optional[SkillMeta]: method _search_catalog (line 1426) | def _search_catalog(self, query: str, limit: int = 10) -> List[SkillMe... method _load_catalog_index (line 1440) | def _load_catalog_index(self) -> List[SkillMeta]: method _get_json (line 1492) | def _get_json(self, url: str, timeout: int = 20) -> Optional[Any]: method _resolve_latest_version (line 1501) | def _resolve_latest_version(self, slug: str, skill_data: Dict[str, Any... method _extract_files (line 1523) | def _extract_files(self, version_data: Dict[str, Any]) -> Dict[str, str]: method _download_zip (line 1554) | def _download_zip(self, slug: str, version: str) -> Dict[str, str]: method _fetch_text (line 1613) | def _fetch_text(self, url: str) -> Optional[str]: class ClaudeMarketplaceSource (line 1627) | class ClaudeMarketplaceSource(SkillSource): method __init__ (line 1638) | def __init__(self, auth: GitHubAuth): method source_id (line 1641) | def source_id(self) -> str: method trust_level_for (line 1644) | def trust_level_for(self, identifier: str) -> str: method search (line 1652) | def search(self, query: str, limit: int = 10) -> List[SkillMeta]: method fetch (line 1680) | def fetch(self, identifier: str) -> Optional[SkillBundle]: method inspect (line 1688) | def inspect(self, identifier: str) -> Optional[SkillMeta]: method _fetch_marketplace_index (line 1696) | def _fetch_marketplace_index(self, repo: str) -> List[dict]: class LobeHubSource (line 1725) | class LobeHubSource(SkillSource): method source_id (line 1735) | def source_id(self) -> str: method trust_level_for (line 1738) | def trust_level_for(self, identifier: str) -> str: method search (line 1741) | def search(self, query: str, limit: int = 10) -> List[SkillMeta]: method fetch (line 1776) | def fetch(self, identifier: str) -> Optional[SkillBundle]: method inspect (line 1793) | def inspect(self, identifier: str) -> Optional[SkillMeta]: method _fetch_index (line 1816) | def _fetch_index(self) -> Optional[Any]: method _fetch_agent (line 1834) | def _fetch_agent(self, agent_id: str) -> Optional[dict]: method _convert_to_skill_md (line 1846) | def _convert_to_skill_md(agent_data: dict) -> str: class OptionalSkillSource (line 1885) | class OptionalSkillSource(SkillSource): method __init__ (line 1895) | def __init__(self): method source_id (line 1898) | def source_id(self) -> str: method trust_level_for (line 1901) | def trust_level_for(self, identifier: str) -> str: method search (line 1906) | def search(self, query: str, limit: int = 10) -> List[SkillMeta]: method fetch (line 1921) | def fetch(self, identifier: str) -> Optional[SkillBundle]: method inspect (line 1973) | def inspect(self, identifier: str) -> Optional[SkillMeta]: method _find_skill_dir (line 1984) | def _find_skill_dir(self, name: str) -> Optional[Path]: method _scan_all (line 1993) | def _scan_all(self) -> List[SkillMeta]: method _parse_frontmatter (line 2035) | def _parse_frontmatter(content: str) -> dict: function _read_index_cache (line 2054) | def _read_index_cache(key: str) -> Optional[Any]: function _write_index_cache (line 2068) | def _write_index_cache(key: str, data: Any) -> None: function _skill_meta_to_dict (line 2087) | def _skill_meta_to_dict(meta: SkillMeta) -> dict: class HubLockFile (line 2106) | class HubLockFile: method __init__ (line 2109) | def __init__(self, path: Path = LOCK_FILE): method load (line 2112) | def load(self) -> dict: method save (line 2120) | def save(self, data: dict) -> None: method record_install (line 2124) | def record_install( method record_uninstall (line 2151) | def record_uninstall(self, name: str) -> None: method get_installed (line 2156) | def get_installed(self, name: str) -> Optional[dict]: method list_installed (line 2160) | def list_installed(self) -> List[dict]: method is_hub_installed (line 2167) | def is_hub_installed(self, name: str) -> bool: class TapsManager (line 2176) | class TapsManager: method __init__ (line 2179) | def __init__(self, path: Path = TAPS_FILE): method load (line 2182) | def load(self) -> List[dict]: method save (line 2191) | def save(self, taps: List[dict]) -> None: method add (line 2195) | def add(self, repo: str, path: str = "skills/") -> bool: method remove (line 2204) | def remove(self, repo: str) -> bool: method list_taps (line 2213) | def list_taps(self) -> List[dict]: function append_audit_log (line 2221) | def append_audit_log(action: str, skill_name: str, source: str, function ensure_hub_dirs (line 2241) | def ensure_hub_dirs() -> None: function quarantine_bundle (line 2254) | def quarantine_bundle(bundle: SkillBundle) -> Path: function install_from_quarantine (line 2273) | def install_from_quarantine( function uninstall_skill (line 2315) | def uninstall_skill(skill_name: str) -> Tuple[bool, str]: function bundle_content_hash (line 2332) | def bundle_content_hash(bundle: SkillBundle) -> str: function _source_matches (line 2340) | def _source_matches(source: SkillSource, source_name: str) -> bool: function check_for_skill_updates (line 2348) | def check_for_skill_updates( function create_source_router (line 2404) | def create_source_router(auth: Optional[GitHubAuth] = None) -> List[Skil... function unified_search (line 2428) | def unified_search(query: str, sources: List[SkillSource], FILE: tools/skills_sync.py function _get_bundled_dir (line 39) | def _get_bundled_dir() -> Path: function _read_manifest (line 44) | def _read_manifest() -> Dict[str, str]: function _write_manifest (line 71) | def _write_manifest(entries: Dict[str, str]): function _discover_bundled_skills (line 104) | def _discover_bundled_skills(bundled_dir: Path) -> List[Tuple[str, Path]]: function _compute_relative_dest (line 124) | def _compute_relative_dest(skill_dir: Path, bundled_dir: Path) -> Path: function _dir_hash (line 133) | def _dir_hash(directory: Path) -> str: function sync_skills (line 147) | def sync_skills(quiet: bool = False) -> dict: FILE: tools/skills_tool.py class SkillReadinessStatus (line 107) | class SkillReadinessStatus(str, Enum): function set_secret_capture_callback (line 113) | def set_secret_capture_callback(callback) -> None: function skill_matches_platform (line 118) | def skill_matches_platform(frontmatter: Dict[str, Any]) -> bool: function _normalize_prerequisite_values (line 145) | def _normalize_prerequisite_values(value: Any) -> List[str]: function _collect_prerequisite_values (line 153) | def _collect_prerequisite_values( function _normalize_setup_metadata (line 165) | def _normalize_setup_metadata(frontmatter: Dict[str, Any]) -> Dict[str, ... function _get_required_environment_variables (line 210) | def _get_required_environment_variables( function _capture_required_environment_variables (line 276) | def _capture_required_environment_variables( function _is_gateway_surface (line 348) | def _is_gateway_surface() -> bool: function _get_terminal_backend_name (line 354) | def _get_terminal_backend_name() -> str: function _is_env_var_persisted (line 358) | def _is_env_var_persisted( function _remaining_required_environment_names (line 368) | def _remaining_required_environment_names( function _gateway_setup_hint (line 391) | def _gateway_setup_hint() -> str: function _build_setup_note (line 400) | def _build_setup_note( function check_skills_requirements (line 414) | def check_skills_requirements() -> bool: function _parse_frontmatter (line 419) | def _parse_frontmatter(content: str) -> Tuple[Dict[str, Any], str]: function _get_category_from_path (line 456) | def _get_category_from_path(skill_path: Path) -> Optional[str]: function _estimate_tokens (line 472) | def _estimate_tokens(content: str) -> int: function _parse_tags (line 485) | def _parse_tags(tags_value) -> List[str]: function _get_disabled_skill_names (line 516) | def _get_disabled_skill_names() -> Set[str]: function _is_skill_disabled (line 537) | def _is_skill_disabled(name: str, platform: str = None) -> bool: function _find_all_skills (line 554) | def _find_all_skills(*, skip_disabled: bool = False) -> List[Dict[str, A... function _load_category_description (line 622) | def _load_category_description(category_dir: Path) -> Optional[str]: function skills_categories (line 665) | def skills_categories(verbose: bool = False, task_id: str = None) -> str: function skills_list (line 736) | def skills_list(category: str = None, task_id: str = None) -> str: function skill_view (line 804) | def skill_view(name: str, file_path: str = None, task_id: str = None) ->... FILE: tools/terminal_tool.py function _check_disk_usage_warning (line 76) | def _check_disk_usage_warning(): function set_sudo_password_callback (line 116) | def set_sudo_password_callback(cb): function set_approval_callback (line 122) | def set_approval_callback(cb): function _check_dangerous_command (line 141) | def _check_dangerous_command(command: str, env_type: str) -> dict: function _check_all_guards (line 147) | def _check_all_guards(command: str, env_type: str) -> dict: function _handle_sudo_failure (line 153) | def _handle_sudo_failure(output: str, env_type: str) -> str: function _prompt_for_sudo_password (line 178) | def _prompt_for_sudo_password(timeout_seconds: int = 45) -> str: function _transform_sudo_command (line 303) | def _transform_sudo_command(command: str) -> tuple[str, str | None]: function register_task_env_overrides (line 418) | def register_task_env_overrides(task_id: str, overrides: Dict[str, Any]): function clear_task_env_overrides (line 437) | def clear_task_env_overrides(task_id: str): function _parse_env_var (line 447) | def _parse_env_var(name: str, default: str, converter=int, type_label: s... function _get_env_config (line 463) | def _get_env_config() -> Dict[str, Any]: function _create_environment (line 539) | def _create_environment(env_type: str, image: str, cwd: str, timeout: int, function _cleanup_inactive_envs (line 637) | def _cleanup_inactive_envs(lifetime_seconds: int = 300): function _cleanup_thread_worker (line 701) | def _cleanup_thread_worker(): function _start_cleanup_thread (line 718) | def _start_cleanup_thread(): function _stop_cleanup_thread (line 729) | def _stop_cleanup_thread(): function get_active_environments_info (line 740) | def get_active_environments_info() -> Dict[str, Any]: function cleanup_all_environments (line 765) | def cleanup_all_environments(): function cleanup_vm (line 794) | def cleanup_vm(task_id: str): function _atexit_cleanup (line 838) | def _atexit_cleanup(): function terminal_tool (line 849) | def terminal_tool( function check_terminal_requirements (line 1190) | def check_terminal_requirements() -> bool: function _handle_terminal (line 1357) | def _handle_terminal(args, **kw): FILE: tools/tirith_security.py function _env_bool (line 49) | def _env_bool(key: str, default: bool) -> bool: function _env_int (line 56) | def _env_int(key: str, default: int) -> int: function _load_security_config (line 66) | def _load_security_config() -> dict: function _get_hermes_home (line 106) | def _get_hermes_home() -> str: function _failure_marker_path (line 117) | def _failure_marker_path() -> str: function _read_failure_reason (line 122) | def _read_failure_reason() -> str | None: function _is_install_failed_on_disk (line 139) | def _is_install_failed_on_disk() -> bool: function _mark_install_failed (line 156) | def _mark_install_failed(reason: str = ""): function _clear_install_failed (line 173) | def _clear_install_failed(): function _hermes_bin_dir (line 181) | def _hermes_bin_dir() -> str: function _detect_target (line 188) | def _detect_target() -> str | None: function _download_file (line 210) | def _download_file(url: str, dest: str, timeout: int = 10): function _verify_cosign (line 220) | def _verify_cosign(checksums_path: str, sig_path: str, cert_path: str) -... function _verify_checksum (line 260) | def _verify_checksum(archive_path: str, checksums_path: str, archive_nam... function _install_tirith (line 285) | def _install_tirith(*, log_failures: bool = True) -> tuple[str | None, s... function _is_explicit_path (line 378) | def _is_explicit_path(configured_path: str) -> bool: function _resolve_tirith_path (line 383) | def _resolve_tirith_path(configured_path: str) -> str: function _background_install (line 482) | def _background_install(*, log_failures: bool = True): function ensure_installed (line 514) | def ensure_installed(*, log_failures: bool = True): function check_command_security (line 604) | def check_command_security(command: str) -> dict: FILE: tools/todo_tool.py class TodoStore (line 25) | class TodoStore: method __init__ (line 35) | def __init__(self): method write (line 38) | def write(self, todos: List[Dict[str, Any]], merge: bool = False) -> L... method read (line 82) | def read(self) -> List[Dict[str, str]]: method has_items (line 86) | def has_items(self) -> bool: method format_for_injection (line 90) | def format_for_injection(self) -> Optional[str]: method _validate (line 125) | def _validate(item: Dict[str, Any]) -> Dict[str, str]: function todo_tool (line 147) | def todo_tool( function check_todo_requirements (line 189) | def check_todo_requirements() -> bool: FILE: tools/transcription_tools.py function get_stt_model_from_config (line 78) | def get_stt_model_from_config() -> Optional[str]: function _load_stt_config (line 96) | def _load_stt_config() -> dict: function is_stt_enabled (line 105) | def is_stt_enabled(stt_config: Optional[dict] = None) -> bool: function _resolve_openai_api_key (line 117) | def _resolve_openai_api_key() -> str: function _find_binary (line 122) | def _find_binary(binary_name: str) -> Optional[str]: function _find_ffmpeg_binary (line 131) | def _find_ffmpeg_binary() -> Optional[str]: function _find_whisper_binary (line 135) | def _find_whisper_binary() -> Optional[str]: function _get_local_command_template (line 139) | def _get_local_command_template() -> Optional[str]: function _has_local_command (line 154) | def _has_local_command() -> bool: function _normalize_local_command_model (line 158) | def _normalize_local_command_model(model_name: Optional[str]) -> str: function _get_provider (line 164) | def _get_provider(stt_config: dict) -> str: function _validate_audio_file (line 239) | def _validate_audio_file(file_path: str) -> Optional[Dict[str, Any]]: function _transcribe_local (line 271) | def _transcribe_local(file_path: str, model_name: str) -> Dict[str, Any]: function _prepare_local_audio (line 301) | def _prepare_local_audio(file_path: str, work_dir: str) -> tuple[Optiona... function _transcribe_local_command (line 323) | def _transcribe_local_command(file_path: str, model_name: str) -> Dict[s... function _transcribe_groq (line 388) | def _transcribe_groq(file_path: str, model_name: str) -> Dict[str, Any]: function _transcribe_openai (line 436) | def _transcribe_openai(file_path: str, model_name: str) -> Dict[str, Any]: function transcribe_audio (line 488) | def transcribe_audio(file_path: str, model: Optional[str] = None) -> Dic... FILE: tools/tts_tool.py function _import_edge_tts (line 45) | def _import_edge_tts(): function _import_elevenlabs (line 50) | def _import_elevenlabs(): function _import_openai_client (line 55) | def _import_openai_client(): function _import_sounddevice (line 60) | def _import_sounddevice(): function _load_tts_config (line 83) | def _load_tts_config() -> Dict[str, Any]: function _get_provider (line 102) | def _get_provider(tts_config: Dict[str, Any]) -> str: function _has_ffmpeg (line 110) | def _has_ffmpeg() -> bool: function _convert_to_opus (line 115) | def _convert_to_opus(mp3_path: str) -> Optional[str]: function _generate_edge_tts (line 153) | async def _generate_edge_tts(text: str, output_path: str, tts_config: Di... function _generate_elevenlabs (line 177) | def _generate_elevenlabs(text: str, output_path: str, tts_config: Dict[s... function _generate_openai_tts (line 223) | def _generate_openai_tts(text: str, output_path: str, tts_config: Dict[s... function _check_neutts_available (line 267) | def _check_neutts_available() -> bool: function _default_neutts_ref_audio (line 276) | def _default_neutts_ref_audio() -> str: function _default_neutts_ref_text (line 281) | def _default_neutts_ref_text() -> str: function _generate_neutts (line 286) | def _generate_neutts(text: str, output_path: str, tts_config: Dict[str, ... function text_to_speech_tool (line 342) | def text_to_speech_tool( function check_tts_requirements (line 518) | def check_tts_requirements() -> bool: function _strip_markdown_for_tts (line 569) | def _strip_markdown_for_tts(text: str) -> str: function stream_tts_to_speaker (line 584) | def stream_tts_to_speaker( function _check (line 793) | def _check(importer, label): FILE: tools/vision_tools.py function _validate_image_url (line 49) | def _validate_image_url(url: str) -> bool: function _download_image (line 75) | async def _download_image(image_url: str, destination: Path, max_retries... function _determine_mime_type (line 132) | def _determine_mime_type(image_path: Path) -> str: function _image_to_base64_data_url (line 155) | def _image_to_base64_data_url(image_path: Path, mime_type: Optional[str]... function vision_analyze_tool (line 181) | async def vision_analyze_tool( function check_vision_requirements (line 380) | def check_vision_requirements() -> bool: function get_debug_session_info (line 391) | def get_debug_session_info() -> Dict[str, Any]: function _handle_vision_analyze (line 478) | def _handle_vision_analyze(args: Dict[str, Any], **kw: Any) -> Awaitable... FILE: tools/voice_mode.py function _import_audio (line 32) | def _import_audio(): function _audio_available (line 43) | def _audio_available() -> bool: function detect_audio_environment (line 52) | def detect_audio_environment() -> dict: function play_beep (line 112) | def play_beep(frequency: int = 880, duration: float = 0.12, count: int =... class AudioRecorder (line 156) | class AudioRecorder: method __init__ (line 172) | def __init__(self) -> None: method is_recording (line 199) | def is_recording(self) -> bool: method elapsed_seconds (line 203) | def elapsed_seconds(self) -> float: method current_rms (line 209) | def current_rms(self) -> int: method _ensure_stream (line 215) | def _ensure_stream(self) -> None: method start (line 346) | def start(self, on_silence_stop=None) -> None: method _close_stream_with_timeout (line 393) | def _close_stream_with_timeout(self, timeout: float = 3.0) -> None: method stop (line 417) | def stop(self) -> Optional[str]: method cancel (line 460) | def cancel(self) -> None: method shutdown (line 472) | def shutdown(self) -> None: method _write_wav (line 485) | def _write_wav(audio_data) -> str: function is_whisper_hallucination (line 546) | def is_whisper_hallucination(transcript: str) -> bool: function transcribe_recording (line 563) | def transcribe_recording(wav_path: str, model: Optional[str] = None) -> ... function stop_playback (line 597) | def stop_playback() -> None: function play_audio_file (line 617) | def play_audio_file(file_path: str) -> bool: function check_voice_requirements (line 698) | def check_voice_requirements() -> Dict[str, Any]: function cleanup_temp_recordings (line 759) | def cleanup_temp_recordings(max_age_seconds: int = 3600) -> int: FILE: tools/web_tools.py function _load_web_config (line 60) | def _load_web_config() -> dict: function _get_backend (line 69) | def _get_backend() -> str: function _get_firecrawl_client (line 95) | def _get_firecrawl_client(): function _get_parallel_client (line 127) | def _get_parallel_client(): function _get_async_parallel_client (line 145) | def _get_async_parallel_client(): function _tavily_request (line 167) | def _tavily_request(endpoint: str, payload: dict) -> dict: function _normalize_tavily_search_results (line 187) | def _normalize_tavily_search_results(response: dict) -> dict: function _normalize_tavily_documents (line 204) | def _normalize_tavily_documents(response: dict, fallback_url: str = "") ... function process_content_with_llm (line 252) | async def process_content_with_llm( function _call_summarizer_llm (line 336) | async def _call_summarizer_llm( function _process_large_content_chunked (line 434) | async def _process_large_content_chunked( function clean_base64_images (line 558) | def clean_base64_images(text: str) -> str: function _parallel_search (line 593) | def _parallel_search(query: str, limit: int = 5) -> dict: function _parallel_extract (line 624) | async def _parallel_extract(urls: List[str]) -> List[Dict[str, Any]]: function web_search_tool (line 667) | def web_search_tool(query: str, limit: int = 5) -> str: function web_extract_tool (line 816) | async def web_extract_tool( function web_crawl_tool (line 1118) | async def web_crawl_tool( function check_firecrawl_api_key (line 1513) | def check_firecrawl_api_key() -> bool: function check_web_api_key (line 1523) | def check_web_api_key() -> bool: function check_auxiliary_model (line 1533) | def check_auxiliary_model() -> bool: function get_debug_session_info (line 1546) | def get_debug_session_info() -> Dict[str, Any]: FILE: tools/website_policy.py function _get_hermes_home (line 39) | def _get_hermes_home() -> Path: function _get_default_config_path (line 43) | def _get_default_config_path() -> Path: class WebsitePolicyError (line 47) | class WebsitePolicyError(Exception): function _normalize_host (line 51) | def _normalize_host(host: str) -> str: function _normalize_rule (line 55) | def _normalize_rule(rule: Any) -> Optional[str]: function _iter_blocklist_file_rules (line 70) | def _iter_blocklist_file_rules(path: Path) -> List[str]: function _load_policy_config (line 96) | def _load_policy_config(config_path: Optional[Path] = None) -> Dict[str,... function load_website_blocklist (line 134) | def load_website_blocklist(config_path: Optional[Path] = None) -> Dict[s... function invalidate_cache (line 205) | def invalidate_cache() -> None: function _match_host_against_rule (line 212) | def _match_host_against_rule(host: str, pattern: str) -> bool: function _extract_host_from_urlish (line 220) | def _extract_host_from_urlish(url: str) -> str: function check_website_access (line 235) | def check_website_access(url: str, config_path: Optional[Path] = None) -... FILE: toolset_distributions.py function get_distribution (line 223) | def get_distribution(name: str) -> Optional[Dict[str, any]]: function list_distributions (line 237) | def list_distributions() -> Dict[str, Dict]: function sample_toolsets_from_distribution (line 247) | def sample_toolsets_from_distribution(distribution_name: str) -> List[str]: function validate_distribution (line 291) | def validate_distribution(distribution_name: str) -> bool: function print_distribution_info (line 304) | def print_distribution_info(distribution_name: str) -> None: FILE: toolsets.py function get_toolset (line 316) | def get_toolset(name: str) -> Optional[Dict[str, Any]]: function resolve_toolset (line 331) | def resolve_toolset(name: str, visited: Set[str] = None) -> List[str]: function resolve_multiple_toolsets (line 381) | def resolve_multiple_toolsets(toolset_names: List[str]) -> List[str]: function get_all_toolsets (line 400) | def get_all_toolsets() -> Dict[str, Dict[str, Any]]: function get_toolset_names (line 410) | def get_toolset_names() -> List[str]: function validate_toolset (line 422) | def validate_toolset(name: str) -> bool: function create_custom_toolset (line 438) | def create_custom_toolset( function get_toolset_info (line 462) | def get_toolset_info(name: str) -> Dict[str, Any]: function print_toolset_tree (line 489) | def print_toolset_tree(name: str, indent: int = 0) -> None: FILE: trajectory_compressor.py class CompressionConfig (line 55) | class CompressionConfig: method from_yaml (line 98) | def from_yaml(cls, yaml_path: str) -> "CompressionConfig": class TrajectoryMetrics (line 155) | class TrajectoryMetrics: method to_dict (line 177) | def to_dict(self) -> Dict[str, Any]: class AggregateMetrics (line 200) | class AggregateMetrics: method add_trajectory_metrics (line 228) | def add_trajectory_metrics(self, metrics: TrajectoryMetrics): method to_dict (line 252) | def to_dict(self) -> Dict[str, Any]: class TrajectoryCompressor (line 304) | class TrajectoryCompressor: method __init__ (line 316) | def __init__(self, config: CompressionConfig): method _init_tokenizer (line 334) | def _init_tokenizer(self): method _init_summarizer (line 346) | def _init_summarizer(self): method _detect_provider (line 387) | def _detect_provider(self) -> str: method count_tokens (line 407) | def count_tokens(self, text: str) -> int: method count_trajectory_tokens (line 417) | def count_trajectory_tokens(self, trajectory: List[Dict[str, str]]) ->... method count_turn_tokens (line 421) | def count_turn_tokens(self, trajectory: List[Dict[str, str]]) -> List[... method _find_protected_indices (line 425) | def _find_protected_indices(self, trajectory: List[Dict[str, str]]) ->... method _extract_turn_content_for_summary (line 473) | def _extract_turn_content_for_summary(self, trajectory: List[Dict[str,... method _coerce_summary_content (line 500) | def _coerce_summary_content(content: Any) -> str: method _ensure_summary_prefix (line 507) | def _ensure_summary_prefix(summary: str) -> str: method _generate_summary (line 514) | def _generate_summary(self, content: str, metrics: TrajectoryMetrics) ... method _generate_summary_async (line 576) | async def _generate_summary_async(self, content: str, metrics: Traject... method compress_trajectory (line 638) | def compress_trajectory( method compress_trajectory_async (line 758) | async def compress_trajectory_async( method process_entry_async (line 856) | async def process_entry_async(self, entry: Dict[str, Any]) -> Tuple[Di... method process_entry (line 877) | def process_entry(self, entry: Dict[str, Any]) -> Tuple[Dict[str, Any]... method process_file (line 904) | def process_file( method process_directory (line 966) | def process_directory(self, input_dir: Path, output_dir: Path): method _process_directory_async (line 977) | async def _process_directory_async(self, input_dir: Path, output_dir: ... method _print_summary (line 1172) | def _print_summary(self): function main (line 1281) | def main( FILE: utils.py function atomic_json_write (line 12) | def atomic_json_write( function atomic_yaml_write (line 62) | def atomic_yaml_write(