SYMBOL INDEX (355 symbols across 68 files) FILE: src/sidekick/agent.py function _get_prompt (line 23) | def _get_prompt(name: str) -> str: function _process_node (line 31) | async def _process_node(node, message_history): function create_agent (line 63) | def create_agent(): function _create_confirmation_callback (line 75) | def _create_confirmation_callback(): function _create_display_tool_status_callback (line 112) | def _create_display_tool_status_callback(): function process_request (line 139) | async def process_request(message: str, message_history): FILE: src/sidekick/commands/__init__.py function handle_command (line 22) | async def handle_command(user_input: str, message_history=None) -> bool: FILE: src/sidekick/commands/clear.py function handle_clear (line 6) | async def handle_clear(message_history): FILE: src/sidekick/commands/dump.py function recursive_expand (line 8) | def recursive_expand(obj, indent=0): function handle_dump (line 82) | async def handle_dump(message_history): FILE: src/sidekick/commands/help.py function handle_help (line 6) | async def handle_help(): FILE: src/sidekick/commands/model.py function handle_model (line 16) | async def handle_model(args: list[str]): FILE: src/sidekick/commands/usage.py function handle_usage (line 9) | async def handle_usage(): FILE: src/sidekick/commands/yolo.py function handle_yolo (line 7) | async def handle_yolo(): FILE: src/sidekick/config.py class ConfigError (line 11) | class ConfigError(Exception): class ConfigValidationError (line 17) | class ConfigValidationError(ConfigError): function get_config_path (line 23) | def get_config_path() -> Path: function config_exists (line 28) | def config_exists() -> bool: function read_config_file (line 33) | def read_config_file() -> Dict[str, Any]: function validate_config_structure (line 57) | def validate_config_structure(config: Dict[str, Any]) -> None: function parse_mcp_servers (line 82) | def parse_mcp_servers(config: Dict[str, Any]) -> Dict[str, Any]: function set_env_vars (line 129) | def set_env_vars(env_dict: Dict[str, str]) -> None: function update_config_file (line 140) | def update_config_file(updates: Dict[str, Any]) -> None: function deep_merge_dicts (line 175) | def deep_merge_dicts(base: Dict[str, Any], update: Dict[str, Any]) -> Di... function ensure_config_structure (line 196) | def ensure_config_structure() -> Dict[str, Any]: FILE: src/sidekick/deps.py class ToolDeps (line 6) | class ToolDeps: FILE: src/sidekick/main.py function _setup_and_run_event_loop (line 29) | def _setup_and_run_event_loop(coro): function _initialize_config (line 48) | def _initialize_config(): function main (line 74) | def main( FILE: src/sidekick/mcp/agent.py class MCPAgent (line 10) | class MCPAgent: method __init__ (line 28) | def __init__(self, agent: Agent): method agent (line 40) | def agent(self) -> Agent: method __aenter__ (line 52) | async def __aenter__(self): method __aexit__ (line 75) | async def __aexit__(self, exc_type, exc_val, exc_tb): FILE: src/sidekick/mcp/servers.py function mcp_tool_confirmation_callback (line 25) | async def mcp_tool_confirmation_callback( class SilentMCPServerStdio (line 57) | class SilentMCPServerStdio(MCPServerStdio): method __init__ (line 64) | def __init__(self, *args, display_name: str = None, **kwargs): method client_streams (line 70) | async def client_streams(self): function create_mcp_server (line 87) | def create_mcp_server(key: str, config: Dict[str, Any]) -> SilentMCPServ... function load_mcp_servers (line 109) | def load_mcp_servers() -> List[SilentMCPServerStdio]: FILE: src/sidekick/messages.py class MessageHistory (line 13) | class MessageHistory: method add_request (line 19) | def add_request(self, request: messages.ModelRequest) -> None: method add_response (line 24) | def add_response(self, response: messages.ModelResponse) -> None: method add_cancellation_note (line 33) | def add_cancellation_note(self) -> None: method patch_on_error (line 44) | def patch_on_error(self, error_message: str) -> None: method clear (line 83) | def clear(self) -> None: method get_messages (line 88) | def get_messages(self) -> List[messages.ModelMessage]: method get_messages_for_agent (line 92) | def get_messages_for_agent(self) -> List[messages.ModelMessage]: method set_project_guide (line 105) | def set_project_guide(self, guide: Optional[str]) -> None: method __len__ (line 109) | def __len__(self) -> int: method __iter__ (line 113) | def __iter__(self): method __getitem__ (line 117) | def __getitem__(self, index): FILE: src/sidekick/repl.py function _restore_default_signal_handler (line 21) | def _restore_default_signal_handler(): function _should_exit (line 26) | def _should_exit(user_input: str) -> bool: function _display_server_info (line 31) | async def _display_server_info(): class Repl (line 42) | class Repl: method __init__ (line 45) | def __init__(self, project_guide=None): method _kill_child_processes (line 54) | def _kill_child_processes(self): method _setup_signal_handler (line 75) | def _setup_signal_handler(self): method _handle_user_request (line 89) | async def _handle_user_request(self, user_input: str): method run (line 116) | async def run(self): FILE: src/sidekick/session.py class Session (line 6) | class Session: method init (line 13) | def init(self, config: Dict[str, Any], model: str): FILE: src/sidekick/setup.py function validate_json_file (line 15) | def validate_json_file(config_path: Path) -> Optional[Dict]: function collect_api_keys (line 24) | def collect_api_keys() -> Dict[str, str]: function select_default_model (line 44) | def select_default_model(api_keys: Dict[str, str]) -> str: function create_config (line 87) | def create_config(config_path: Path) -> Dict: function handle_invalid_config (line 126) | def handle_invalid_config(config_path: Path) -> Dict: function run_setup (line 149) | def run_setup() -> Dict: FILE: src/sidekick/tools/find.py function _run_external_tool (line 15) | async def _run_external_tool(tool_name: str, cmd: List[str]) -> Optional... function _get_gitignore_patterns (line 36) | def _get_gitignore_patterns() -> Set[str]: function _find_files_with_fd (line 54) | async def _find_files_with_fd(pattern: str, dirs: bool, max_depth: Optio... function _find_files_with_rg (line 69) | async def _find_files_with_rg(pattern: str, max_depth: Optional[int]) ->... function _find_content_with_rg (line 83) | async def _find_content_with_rg( function _find_content_with_ag (line 105) | async def _find_content_with_ag( function _find_files_python (line 127) | def _find_files_python(pattern: str, dirs: bool, max_depth: Optional[int... function _find_content_python (line 157) | def _find_content_python( function find (line 216) | async def find( FILE: src/sidekick/tools/git.py function git_add (line 9) | async def git_add(ctx: RunContext[ToolDeps], files: str) -> str: function git_commit (line 79) | async def git_commit(ctx: RunContext[ToolDeps], message: str) -> str: FILE: src/sidekick/tools/list.py function _should_exclude (line 14) | def _should_exclude(path: str, gitignore_patterns: List[str]) -> bool: function _read_gitignore (line 42) | def _read_gitignore(base_path: str) -> List[str]: function _format_tree (line 54) | def _format_tree(items: List[Tuple[str, bool, int]], prefix: str = "") -... function _run_rg_files (line 71) | async def _run_rg_files(path: str, max_depth: int) -> str: function _build_tree_from_files (line 92) | def _build_tree_from_files(files: List[str], base_path: str) -> str: function _walk_directory (line 99) | def _walk_directory( function list_directory (line 181) | async def list_directory(ctx: RunContext[ToolDeps], path: str = ".", max... FILE: src/sidekick/tools/read_file.py function read_file (line 10) | async def read_file(ctx: RunContext[ToolDeps], filepath: str) -> str: FILE: src/sidekick/tools/run_command.py function run_command (line 12) | async def run_command(ctx: RunContext[ToolDeps], command: str) -> str: FILE: src/sidekick/tools/update_file.py function update_file (line 9) | async def update_file( FILE: src/sidekick/tools/wrapper.py function create_tools (line 14) | def create_tools(): FILE: src/sidekick/tools/write_file.py function write_file (line 13) | async def write_file(ctx: RunContext[ToolDeps], filepath: str, content: ... FILE: src/sidekick/ui/__init__.py function version (line 50) | def version(): function update_available (line 55) | def update_available(latest_version: str): function usage (line 60) | def usage(usage_data: dict): function banner (line 65) | def banner(): function start_spinner (line 80) | def start_spinner(message: str = "", style: str = SpinnerStyle.DEFAULT): function stop_spinner (line 90) | def stop_spinner(): FILE: src/sidekick/ui/colors.py class Colors (line 4) | class Colors: FILE: src/sidekick/ui/core.py class SpinnerStyle (line 22) | class SpinnerStyle: function banner (line 29) | def banner(): function start_spinner (line 38) | def start_spinner(message: str = "", style: str = SpinnerStyle.DEFAULT): function stop_spinner (line 43) | def stop_spinner(): FILE: src/sidekick/ui/formatting.py function get_file_language (line 12) | def get_file_language(filepath: str) -> str: function create_syntax_highlighted (line 109) | def create_syntax_highlighted(content: str, filepath: str, theme: str = ... function create_shell_syntax (line 133) | def create_shell_syntax(command: str, theme: str = None) -> Syntax: function create_unified_diff (line 155) | def create_unified_diff( function create_inline_diff (line 192) | def create_inline_diff(old_content: str, new_content: str) -> tuple[Text... function format_server_name (line 223) | def format_server_name(key: str) -> str: function get_command_display_name (line 256) | def get_command_display_name(command_string: str) -> str: FILE: src/sidekick/ui/manager.py class OutputType (line 18) | class OutputType(Enum): class PanelType (line 28) | class PanelType(Enum): class MessageType (line 41) | class MessageType(Enum): class UIManager (line 77) | class UIManager: method __init__ (line 83) | def __init__(self): method _prepare_spacing (line 88) | def _prepare_spacing(self, new_type: OutputType): method _prepare_panel_content (line 104) | def _prepare_panel_content(self, content, markdown, syntax): method _determine_panel_title (line 121) | def _determine_panel_title(self, title, panel_type, config): method panel (line 140) | def panel( method message (line 182) | def message( method line (line 224) | def line(self): method reset_context (line 228) | def reset_context(self): method set_spinner_active (line 232) | def set_spinner_active(self, active: bool): method agent (line 242) | def agent(self, content: str, has_footer: bool = False): method tool (line 252) | def tool(self, content: Union[str, Text], title: str, footer: Optional... method error_panel (line 261) | def error_panel(self, message: str, detail: Optional[str] = None, titl... method info (line 270) | def info(self, text: str): method error (line 274) | def error(self, text: str, detail: Optional[str] = None): method warning (line 278) | def warning(self, text: str): method success (line 282) | def success(self, text: str): method bullet (line 286) | def bullet(self, text: str): method muted (line 290) | def muted(self, text: str, indent: int = 0): method thinking (line 294) | def thinking(self, text: str): method thinking_panel (line 298) | def thinking_panel(self, content: str): method confirmation_panel (line 302) | def confirmation_panel(self, content: str): method info_panel (line 306) | def info_panel(self, content, title: str): method dump (line 310) | def dump(self, data): method help (line 318) | def help(self): FILE: src/sidekick/ui/special.py function version (line 12) | def version(ui_manager): function update_available (line 17) | def update_available(ui_manager, latest_version: str): function usage (line 22) | def usage(ui_manager, usage_data: dict): FILE: src/sidekick/ui/spinner.py class SpinnerManager (line 10) | class SpinnerManager: method __init__ (line 31) | def __init__(self, console: Console): method _get_thinking_message (line 36) | def _get_thinking_message(self) -> str: method _rotate_messages (line 40) | async def _rotate_messages(self, style: str, interval: float = 5.0): method start (line 54) | def start(self, message: str = "", style: str = None): method stop (line 82) | def stop(self): FILE: src/sidekick/usage.py class ModelUsage (line 10) | class ModelUsage: method add_usage (line 19) | def add_usage( class UsageTracker (line 31) | class UsageTracker: method record_usage (line 40) | def record_usage(self, model: str, usage: Any) -> None: method total_tokens (line 87) | def total_tokens(self) -> int: method total_cost (line 92) | def total_cost(self) -> float: method total_requests (line 97) | def total_requests(self) -> int: FILE: src/sidekick/utils/command.py function extract_commands (line 7) | def extract_commands(command_string: str) -> List[str]: function is_command_allowed (line 97) | def is_command_allowed(command_string: str, allowed_commands: Set[str]) ... FILE: src/sidekick/utils/error.py function handle_error (line 14) | async def handle_error(error: Exception, display_func) -> None: function extract_error_message (line 30) | def extract_error_message(error: Exception) -> str: function should_log_error (line 66) | def should_log_error(error: Exception) -> bool: function save_error_log (line 72) | def save_error_log(error: Exception) -> Path: function _get_api_message (line 93) | def _get_api_message(error: ModelHTTPError) -> str: function _extract_provider_message (line 105) | def _extract_provider_message(error: Exception) -> str: function _get_provider_name (line 122) | def _get_provider_name(module_name: str) -> str: class ErrorContext (line 133) | class ErrorContext: method __init__ (line 136) | def __init__(self, operation: str, ui: Any): method add_cleanup (line 141) | def add_cleanup(self, callback: Callable) -> None: method handle (line 144) | async def handle(self, error: Exception) -> Optional[Any]: FILE: src/sidekick/utils/guide.py function load_guide (line 4) | def load_guide(): FILE: src/sidekick/utils/input.py function create_multiline_keybindings (line 19) | def create_multiline_keybindings() -> KeyBindings: function create_prompt_style (line 35) | def create_prompt_style() -> Style: function prompt_continuation (line 48) | def prompt_continuation(width: int, line_number: int, is_soft_wrap: bool... function create_multiline_prompt_session (line 62) | def create_multiline_prompt_session() -> PromptSession: function get_multiline_input (line 83) | async def get_multiline_input(session: Optional[PromptSession] = None) -... FILE: src/sidekick/utils/logger.py class UILogHandler (line 8) | class UILogHandler(logging.Handler): method emit (line 11) | def emit(self, record): function _is_allowed_module (line 26) | def _is_allowed_module(name: str) -> bool: function setup_logging (line 33) | def setup_logging(debug_enabled: bool): FILE: tests/agent/test_process_node.py function test_process_node_with_request (line 10) | async def test_process_node_with_request(): function test_process_node_with_model_response_no_tools (line 26) | async def test_process_node_with_model_response_no_tools(): function test_process_node_with_tool_call (line 45) | async def test_process_node_with_tool_call(): function test_process_node_with_tool_return (line 67) | async def test_process_node_with_tool_return(): function test_process_node_with_retry_prompt (line 87) | async def test_process_node_with_retry_prompt(): FILE: tests/commands/test_handle_command.py function test_handle_command_routes (line 20) | async def test_handle_command_routes(monkeypatch, user_input, patch_targ... function test_handle_command_non_command (line 39) | async def test_handle_command_non_command(): function test_handle_command_unknown (line 45) | async def test_handle_command_unknown(): FILE: tests/commands/test_handle_dump.py function test_handle_dump_writes_to_file_and_pretty_prints (line 11) | async def test_handle_dump_writes_to_file_and_pretty_prints(mock_ui, tmp... FILE: tests/commands/test_handle_model.py function test_handle_model_list (line 11) | async def test_handle_model_list(mock_ui, mock_session, mock_models): function test_handle_model_switch (line 26) | async def test_handle_model_switch(mock_ui, mock_session, mock_models): function test_handle_model_invalid_number (line 41) | async def test_handle_model_invalid_number(mock_ui): function test_handle_model_set_default (line 52) | async def test_handle_model_set_default(mock_ui): FILE: tests/commands/test_handle_yolo.py function test_handle_yolo_disables_confirmation (line 11) | async def test_handle_yolo_disables_confirmation(mock_ui, mock_session): function test_handle_yolo_enables_confirmation (line 25) | async def test_handle_yolo_enables_confirmation(mock_ui, mock_session): FILE: tests/config/test_config_exists.py function test_returns_true_when_exists (line 8) | def test_returns_true_when_exists(): function test_returns_false_when_not_exists (line 14) | def test_returns_false_when_not_exists(): FILE: tests/config/test_deep_merge_dicts.py function test_simple_merge (line 4) | def test_simple_merge(): function test_nested_dict_merge (line 14) | def test_nested_dict_merge(): function test_deep_nested_merge (line 30) | def test_deep_nested_merge(): function test_list_override (line 40) | def test_list_override(): function test_mixed_types_override (line 50) | def test_mixed_types_override(): function test_empty_dicts (line 60) | def test_empty_dicts(): function test_none_values (line 67) | def test_none_values(): function test_preserves_update_values (line 77) | def test_preserves_update_values(): FILE: tests/config/test_ensure_config_structure.py function test_preserves_user_settings (line 13) | def test_preserves_user_settings(): function test_adds_missing_defaults (line 48) | def test_adds_missing_defaults(): function test_does_not_add_tool_ignore_field (line 87) | def test_does_not_add_tool_ignore_field(): function test_empty_config_gets_full_defaults (line 118) | def test_empty_config_gets_full_defaults(): function test_no_file_update_when_no_changes (line 139) | def test_no_file_update_when_no_changes(): function test_raises_config_error_on_missing_file (line 206) | def test_raises_config_error_on_missing_file(): FILE: tests/config/test_get_config_path.py function test_returns_correct_path (line 8) | def test_returns_correct_path(): FILE: tests/config/test_parse_mcp_servers.py function test_returns_empty_dict_when_no_mcp_servers (line 8) | def test_returns_empty_dict_when_no_mcp_servers(): function test_returns_valid_mcp_servers (line 14) | def test_returns_valid_mcp_servers(): function test_accepts_server_with_name_field (line 21) | def test_accepts_server_with_name_field(): function test_accepts_server_with_env (line 32) | def test_accepts_server_with_env(): function test_raises_for_non_dict_mcp_servers (line 47) | def test_raises_for_non_dict_mcp_servers(): function test_raises_for_invalid_server_config (line 54) | def test_raises_for_invalid_server_config(): function test_raises_for_missing_command (line 61) | def test_raises_for_missing_command(): function test_raises_for_missing_args (line 68) | def test_raises_for_missing_args(): function test_raises_for_non_string_command (line 75) | def test_raises_for_non_string_command(): function test_raises_for_non_list_args (line 82) | def test_raises_for_non_list_args(): function test_raises_for_empty_args (line 89) | def test_raises_for_empty_args(): function test_raises_for_non_dict_env (line 98) | def test_raises_for_non_dict_env(): FILE: tests/config/test_read_config_file.py function test_reads_valid_json (line 10) | def test_reads_valid_json(): function test_raises_file_not_found (line 19) | def test_raises_file_not_found(): function test_raises_permission_error (line 27) | def test_raises_permission_error(): function test_raises_json_decode_error (line 36) | def test_raises_json_decode_error(): FILE: tests/config/test_set_env_vars.py function test_sets_string_env_vars (line 9) | def test_sets_string_env_vars(): function test_skips_empty_values (line 19) | def test_skips_empty_values(): function test_skips_non_string_values (line 29) | def test_skips_non_string_values(): function test_handles_empty_dict (line 41) | def test_handles_empty_dict(): FILE: tests/config/test_update_config_file.py function test_update_config_file_success (line 13) | def test_update_config_file_success(): function test_update_config_file_no_config (line 34) | def test_update_config_file_no_config(): function test_update_config_file_merge_nested (line 41) | def test_update_config_file_merge_nested(): FILE: tests/config/test_validate_config_structure.py function test_valid_config_passes (line 8) | def test_valid_config_passes(): function test_valid_config_with_empty_env (line 15) | def test_valid_config_with_empty_env(): function test_raises_for_non_dict (line 22) | def test_raises_for_non_dict(): function test_raises_for_missing_default_model (line 29) | def test_raises_for_missing_default_model(): function test_raises_for_non_string_default_model (line 36) | def test_raises_for_non_string_default_model(): function test_raises_for_missing_env (line 43) | def test_raises_for_missing_env(): function test_raises_for_non_dict_env (line 50) | def test_raises_for_non_dict_env(): FILE: tests/conftest.py function mock_ui (line 14) | def mock_ui(): function mock_session (line 20) | def mock_session(): function mock_models (line 26) | def mock_models(): function mock_config (line 32) | def mock_config(): function mock_usage (line 42) | def mock_usage(): function make_mock_process (line 59) | def make_mock_process(): function make_tool_call (line 72) | def make_tool_call(): function patched_commands_env (line 91) | def patched_commands_env(monkeypatch, mock_ui, mock_session): FILE: tests/main/test_error_handling.py function mock_repl (line 13) | def mock_repl(): function test_handle_user_request_with_error (line 21) | async def test_handle_user_request_with_error(mock_repl): function test_handle_user_request_with_model_http_error (line 42) | async def test_handle_user_request_with_model_http_error(mock_repl): function test_handle_user_request_success (line 60) | async def test_handle_user_request_success(mock_repl): function test_handle_user_request_cancellation (line 76) | async def test_handle_user_request_cancellation(mock_repl): FILE: tests/mcp/test_create_mcp_server.py function test_creates_server_with_minimal_config (line 6) | def test_creates_server_with_minimal_config(): function test_creates_server_with_custom_name (line 19) | def test_creates_server_with_custom_name(): function test_creates_server_with_env_vars (line 28) | def test_creates_server_with_env_vars(): function test_formats_display_name_from_key (line 42) | def test_formats_display_name_from_key(): FILE: tests/mcp/test_format_display_name.py function test_converts_simple_lowercase (line 6) | def test_converts_simple_lowercase(): function test_converts_hyphenated_names (line 11) | def test_converts_hyphenated_names(): function test_converts_underscored_names (line 17) | def test_converts_underscored_names(): function test_converts_mixed_separators (line 23) | def test_converts_mixed_separators(): function test_handles_already_capitalized (line 29) | def test_handles_already_capitalized(): function test_handles_empty_string (line 35) | def test_handles_empty_string(): FILE: tests/mcp/test_load_mcp_servers.py function test_loads_valid_servers (line 10) | def test_loads_valid_servers(): function test_returns_empty_list_when_no_mcp_servers (line 33) | def test_returns_empty_list_when_no_mcp_servers(): function test_returns_empty_list_on_config_error (line 43) | def test_returns_empty_list_on_config_error(): function test_handles_server_creation_failure (line 51) | def test_handles_server_creation_failure(caplog): function test_warns_when_all_servers_fail (line 82) | def test_warns_when_all_servers_fail(caplog): function test_handles_unexpected_errors (line 107) | def test_handles_unexpected_errors(caplog): FILE: tests/mcp/test_validate_server_config.py function test_valid_config_passes (line 8) | def test_valid_config_passes(): function test_valid_config_with_multiple_args (line 16) | def test_valid_config_with_multiple_args(): function test_raises_for_non_dict (line 31) | def test_raises_for_non_dict(): function test_raises_for_missing_command (line 39) | def test_raises_for_missing_command(): function test_raises_for_empty_command (line 47) | def test_raises_for_empty_command(): function test_raises_for_missing_args (line 55) | def test_raises_for_missing_args(): function test_raises_for_non_list_args (line 63) | def test_raises_for_non_list_args(): function test_raises_for_empty_args (line 71) | def test_raises_for_empty_args(): function test_accepts_optional_fields (line 81) | def test_accepts_optional_fields(): function test_raises_for_non_dict_mcpservers (line 99) | def test_raises_for_non_dict_mcpservers(): function test_returns_empty_dict_when_no_mcpservers (line 107) | def test_returns_empty_dict_when_no_mcpservers(): function test_raises_for_non_dict_env (line 114) | def test_raises_for_non_dict_env(): FILE: tests/setup/test_create_config.py function test_create_config_includes_all_defaults (line 10) | def test_create_config_includes_all_defaults(): function test_create_config_with_no_api_keys (line 57) | def test_create_config_with_no_api_keys(): function test_create_config_filters_empty_api_keys (line 80) | def test_create_config_filters_empty_api_keys(): FILE: tests/tools/conftest.py function mock_ctx (line 8) | def mock_ctx(): FILE: tests/tools/test_find.py function mock_context (line 13) | def mock_context(): function test_find_files_with_fd (line 25) | async def test_find_files_with_fd( function test_find_dirs_with_fd (line 43) | async def test_find_dirs_with_fd(mock_subprocess_exec, mock_which, make_... function test_find_content_with_rg (line 59) | async def test_find_content_with_rg( function test_find_content_case_insensitive (line 77) | async def test_find_content_case_insensitive( function test_find_content_with_include_pattern (line 94) | async def test_find_content_with_include_pattern( function test_find_content_with_ag_fallback (line 113) | async def test_find_content_with_ag_fallback( function test_find_content_python_fallback (line 132) | async def test_find_content_python_fallback(mock_open, mock_walk, mock_w... function test_find_no_results (line 151) | async def test_find_no_results(mock_subprocess_exec, mock_which, make_mo... function test_find_files_python_fallback (line 163) | async def test_find_files_python_fallback(mock_walk, mock_which, mock_co... FILE: tests/tools/test_read_file.py function mock_context (line 13) | def mock_context(): function test_read_file_success (line 23) | async def test_read_file_success(mock_context): function test_read_file_errors (line 39) | async def test_read_file_errors(side_effect, expected, mock_context): function test_read_file_real_file (line 45) | async def test_read_file_real_file(tmp_path, mock_context): function test_read_file_empty_file (line 52) | async def test_read_file_empty_file(mock_context): function test_read_file_large_content (line 58) | async def test_read_file_large_content(mock_context): FILE: tests/tools/test_update_file.py function test_update_file_success (line 14) | async def test_update_file_success(mock_ctx): function test_update_file_content_not_found (line 37) | async def test_update_file_content_not_found(mock_ctx): function test_update_file_content_not_found_long_content (line 54) | async def test_update_file_content_not_found_long_content(mock_ctx): function test_update_file_not_found (line 71) | async def test_update_file_not_found(mock_ctx): function test_update_file_read_error (line 83) | async def test_update_file_read_error(mock_ctx): function test_update_file_write_error (line 95) | async def test_update_file_write_error(mock_ctx): function test_update_file_with_real_file (line 120) | async def test_update_file_with_real_file(mock_ctx): function test_update_file_only_first_occurrence (line 147) | async def test_update_file_only_first_occurrence(mock_ctx): function test_update_file_preserves_encoding (line 165) | async def test_update_file_preserves_encoding(mock_ctx): function test_update_file_identical_content (line 187) | async def test_update_file_identical_content(mock_ctx): FILE: tests/usage/test_usage_tracker.py function test_model_usage_initial_state (line 12) | def test_model_usage_initial_state(): function test_model_usage_add_usage (line 22) | def test_model_usage_add_usage(): function test_usage_tracker_initial_state (line 46) | def test_usage_tracker_initial_state(): function test_record_usage_basic (line 56) | def test_record_usage_basic(): function test_record_usage_with_cached_tokens (line 87) | def test_record_usage_with_cached_tokens(): function test_record_usage_multiple_models (line 110) | def test_record_usage_multiple_models(): function test_record_usage_same_model_multiple_times (line 140) | def test_record_usage_same_model_multiple_times(): function test_cost_calculation (line 170) | def test_cost_calculation(): function test_unknown_model_fallback (line 192) | def test_unknown_model_fallback(): FILE: tests/utils/test_command_parser.py function test_simple_command (line 7) | def test_simple_command(): function test_commands_with_paths (line 13) | def test_commands_with_paths(): function test_chained_commands_with_and (line 19) | def test_chained_commands_with_and(): function test_chained_commands_with_or (line 24) | def test_chained_commands_with_or(): function test_piped_commands (line 28) | def test_piped_commands(): function test_semicolon_separated (line 33) | def test_semicolon_separated(): function test_mixed_separators (line 38) | def test_mixed_separators(): function test_quoted_arguments (line 42) | def test_quoted_arguments(): function test_empty_and_whitespace (line 48) | def test_empty_and_whitespace(): function test_single_command_allowed (line 54) | def test_single_command_allowed(): function test_all_commands_must_be_allowed (line 60) | def test_all_commands_must_be_allowed(): function test_empty_allowed_set (line 66) | def test_empty_allowed_set(): function test_command_with_path (line 71) | def test_command_with_path(): function test_single_command_display (line 76) | def test_single_command_display(): function test_multiple_commands_display (line 80) | def test_multiple_commands_display(): FILE: tests/utils/test_error_handler.py function test_extract_error_message_model_http_error (line 16) | def test_extract_error_message_model_http_error(): function test_extract_error_message_model_http_error_direct_message (line 28) | def test_extract_error_message_model_http_error_direct_message(): function test_extract_error_message_malformed_function_call (line 40) | def test_extract_error_message_malformed_function_call(): function test_extract_error_message_content_field_missing (line 48) | def test_extract_error_message_content_field_missing(): function test_extract_error_message_long_error (line 59) | def test_extract_error_message_long_error(): function test_extract_error_message_provider_error_openai (line 70) | def test_extract_error_message_provider_error_openai(): function test_extract_error_message_provider_error_anthropic (line 86) | def test_extract_error_message_provider_error_anthropic(): function test_extract_error_message_provider_error_google (line 102) | def test_extract_error_message_provider_error_google(): function test_should_log_error_known_errors (line 118) | def test_should_log_error_known_errors(): function test_should_log_error_unknown_errors (line 134) | def test_should_log_error_unknown_errors(): function test_save_error_log (line 141) | def test_save_error_log(): function test_handle_error_with_logging (line 164) | async def test_handle_error_with_logging(): function test_handle_error_without_logging (line 186) | async def test_handle_error_without_logging(): function test_extract_error_message_with_regex_extraction (line 201) | def test_extract_error_message_with_regex_extraction(): FILE: tests/utils/test_guide.py function test_load_guide_with_file (line 6) | def test_load_guide_with_file(tmp_path, monkeypatch): function test_load_guide_without_file (line 19) | def test_load_guide_without_file(tmp_path, monkeypatch): FILE: tests/utils/test_input.py function test_create_multiline_keybindings (line 19) | def test_create_multiline_keybindings(): function test_create_prompt_style (line 26) | def test_create_prompt_style(): function test_prompt_continuation (line 35) | def test_prompt_continuation(): function test_create_multiline_prompt_session (line 43) | def test_create_multiline_prompt_session(): function test_constants (line 51) | def test_constants():