tunacode-cli 0.0.44__tar.gz → 0.0.45__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tunacode-cli might be problematic. Click here for more details.
- {tunacode_cli-0.0.44/src/tunacode_cli.egg-info → tunacode_cli-0.0.45}/PKG-INFO +1 -3
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/pyproject.toml +1 -3
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/repl.py +13 -5
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/configuration/defaults.py +0 -1
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/constants.py +1 -1
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/agents/main.py +3 -72
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/recursive/aggregator.py +2 -2
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/recursive/decomposer.py +1 -1
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/recursive/executor.py +11 -8
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/panels.py +9 -2
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45/src/tunacode_cli.egg-info}/PKG-INFO +1 -3
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode_cli.egg-info/SOURCES.txt +0 -5
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode_cli.egg-info/requires.txt +0 -2
- tunacode_cli-0.0.45/tests/characterization/repl/test_repl_initialization.py +114 -0
- tunacode_cli-0.0.44/src/tunacode/core/agents/dspy_integration.py +0 -223
- tunacode_cli-0.0.44/src/tunacode/core/agents/dspy_tunacode.py +0 -458
- tunacode_cli-0.0.44/src/tunacode/prompts/dspy_task_planning.md +0 -45
- tunacode_cli-0.0.44/src/tunacode/prompts/dspy_tool_selection.md +0 -58
- tunacode_cli-0.0.44/tests/characterization/repl/test_repl_initialization.py +0 -59
- tunacode_cli-0.0.44/tests/test_dspy_integration.py +0 -127
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/CLAUDE.md +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/LICENSE +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/MANIFEST.in +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/README.md +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/TUNACODE.md +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/setup.cfg +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/setup.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/base.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/implementations/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/implementations/conversation.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/implementations/debug.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/implementations/development.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/implementations/model.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/implementations/system.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/implementations/todo.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/commands/registry.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/cli/main.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/configuration/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/configuration/models.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/configuration/settings.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/context.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/agents/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/agents/utils.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/background/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/background/manager.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/code_index.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/llm/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/recursive/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/recursive/budget.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/recursive/hierarchy.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/setup/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/setup/agent_setup.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/setup/base.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/setup/config_setup.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/setup/coordinator.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/setup/environment_setup.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/setup/git_safety_setup.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/state.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/token_usage/api_response_parser.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/token_usage/cost_calculator.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/token_usage/usage_tracker.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/core/tool_handler.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/exceptions.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/prompts/system.md +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/py.typed +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/services/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/services/mcp.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/setup.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/base.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/bash.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/glob.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/grep.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/list_dir.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/read_file.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/read_file_async_poc.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/run_command.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/todo.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/update_file.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/tools/write_file.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/types.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/completers.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/console.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/constants.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/decorators.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/input.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/keybindings.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/lexers.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/output.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/prompt_manager.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/recursive_progress.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/tool_ui.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/utils.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/ui/validators.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/bm25.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/diff_utils.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/file_utils.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/import_cache.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/message_utils.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/retry.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/ripgrep.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/security.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/system.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/text_utils.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/token_counter.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode/utils/user_configuration.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode_cli.egg-info/dependency_links.txt +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode_cli.egg-info/entry_points.txt +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/src/tunacode_cli.egg-info/top_level.txt +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/agent/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/agent/conftest.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/agent/test_agent_creation.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/agent/test_json_tool_parsing.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/agent/test_process_node.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/agent/test_process_request.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/agent/test_tool_message_patching.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/background/test_background_edge_cases.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/background/test_cleanup.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/background/test_task_cancellation.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/background/test_task_creation.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/background/test_task_execution.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/code_index/test_cache_management.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/code_index/test_file_scanning.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/code_index/test_index_building.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/code_index/test_search_operations.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/code_index/test_symbol_extraction.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/commands/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/commands/test_init_command.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/conftest.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/context/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/context/test_context_acceptance.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/context/test_context_integration.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/context/test_context_loading.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/context/test_tunacode_logging.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/repl/test_command_parsing.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/repl/test_error_handling.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/repl/test_input_handling.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/repl/test_keyboard_interrupts.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/repl/test_multiline_input.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/repl/test_output_display_logic.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/repl/test_session_flow.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/services/test_error_recovery.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/services/test_llm_routing.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/services/test_mcp_integration.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/services/test_service_lifecycle.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/state/test_agent_tracking.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/state/test_message_history.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/state/test_permissions.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/state/test_session_management.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/state/test_state_initialization.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/state/test_user_config.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/test_characterization_commands.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/ui/test_async_ui.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/ui/test_console_output.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/ui/test_diff_display.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/ui/test_prompt_rendering.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/ui/test_tool_confirmations.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/utils/conftest.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/utils/test_expand_file_refs.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/utils/test_file_operations.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/utils/test_git_commands.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/utils/test_token_counting.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/characterization/utils/test_utils_edge_cases.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/conftest.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/crud/test_core_file_operations.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/fixtures/__init__.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/fixtures/file_operations.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/integration/test_error_recovery_flow.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/integration/test_full_session_flow.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/integration/test_mcp_tool_flow.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/integration/test_multi_tool_operations.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/integration/test_performance_scenarios.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/integration/test_usage_tracking_integration.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_actual_parallelism.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_agent_initialization.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_agent_output_formatting.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_api_response_parser.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_background_manager.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_agent_main.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_bash.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_commands_system.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_glob.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_grep.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_grep_performance.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_iteration_limits.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_list_dir.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_read_file.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_repl_utils.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_run_command.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_setup_system.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_tool_ui_behavior.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_update_file.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_utilities.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_characterization_write_file.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_cli_command_flow.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_cli_file_operations_integration.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_config_directory_creation.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_config_setup_async.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_cost_calculator.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_enhanced_visual_feedback.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_fallback_responses.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_fast_glob_search.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_file_operations_edge_cases.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_file_operations_stress.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_file_reference_context_tracking.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_file_reference_expansion.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_grep_fast_glob.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_grep_legacy_compat.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_grep_timeout.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_json_retry.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_json_tool_parsing.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_list_dir.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_parallel_execution_demo.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_parallel_execution_freeze_fix.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_parallel_execution_integration.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_parallel_read_only_tools.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_parallel_tool_execution.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_prompt_changes_validation.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_read_only_confirmation.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_security.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_streaming_panel_tool_confirmation.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_streaming_spinner_conflict.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_todo_functionality.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_tool_batching_retry.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_tool_categorization.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_tool_combinations.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_tool_handler_ui_messages.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_update_command.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/test_visual_parallel_feedback.py +0 -0
- {tunacode_cli-0.0.44 → tunacode_cli-0.0.45}/tests/unit/test_recursive_executor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tunacode-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.45
|
|
4
4
|
Summary: Your agentic CLI developer.
|
|
5
5
|
Author-email: larock22 <noreply@github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -25,8 +25,6 @@ Requires-Dist: pydantic-ai[logfire]==0.2.6
|
|
|
25
25
|
Requires-Dist: pygments==2.19.1
|
|
26
26
|
Requires-Dist: rich==14.0.0
|
|
27
27
|
Requires-Dist: tiktoken>=0.5.2
|
|
28
|
-
Requires-Dist: dspy-ai>=0.1.0
|
|
29
|
-
Requires-Dist: python-dotenv>=1.0.0
|
|
30
28
|
Provides-Extra: dev
|
|
31
29
|
Requires-Dist: build; extra == "dev"
|
|
32
30
|
Requires-Dist: ruff; extra == "dev"
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tunacode-cli"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.45"
|
|
8
8
|
description = "Your agentic CLI developer."
|
|
9
9
|
keywords = ["cli", "agent", "development", "automation"]
|
|
10
10
|
readme = "README.md"
|
|
@@ -31,8 +31,6 @@ dependencies = [
|
|
|
31
31
|
"pygments==2.19.1",
|
|
32
32
|
"rich==14.0.0",
|
|
33
33
|
"tiktoken>=0.5.2",
|
|
34
|
-
"dspy-ai>=0.1.0",
|
|
35
|
-
"python-dotenv>=1.0.0",
|
|
36
34
|
]
|
|
37
35
|
|
|
38
36
|
[project.scripts]
|
|
@@ -385,9 +385,13 @@ async def repl(state_manager: StateManager):
|
|
|
385
385
|
|
|
386
386
|
state_manager.session.update_token_count()
|
|
387
387
|
context_display = get_context_window_display(state_manager.session.total_tokens, max_tokens)
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
388
|
+
|
|
389
|
+
# Only show startup info if thoughts are enabled or on first run
|
|
390
|
+
if state_manager.session.show_thoughts or not hasattr(state_manager.session, "_startup_shown"):
|
|
391
|
+
await ui.muted(f"• Model: {model_name} • {context_display}")
|
|
392
|
+
await ui.success("Ready to assist")
|
|
393
|
+
await ui.line()
|
|
394
|
+
state_manager.session._startup_shown = True
|
|
391
395
|
|
|
392
396
|
instance = agent.get_or_create_agent(state_manager.session.current_model, state_manager)
|
|
393
397
|
|
|
@@ -465,7 +469,11 @@ async def repl(state_manager: StateManager):
|
|
|
465
469
|
context_display = get_context_window_display(
|
|
466
470
|
state_manager.session.total_tokens, state_manager.session.max_tokens
|
|
467
471
|
)
|
|
468
|
-
|
|
472
|
+
# Only show model/context info if thoughts are enabled
|
|
473
|
+
if state_manager.session.show_thoughts:
|
|
474
|
+
await ui.muted(
|
|
475
|
+
f"• Model: {state_manager.session.current_model} • {context_display}"
|
|
476
|
+
)
|
|
469
477
|
|
|
470
478
|
if action == "restart":
|
|
471
479
|
await repl(state_manager)
|
|
@@ -480,7 +488,7 @@ async def repl(state_manager: StateManager):
|
|
|
480
488
|
total_cost = float(session_total.get("cost", 0) or 0)
|
|
481
489
|
|
|
482
490
|
# Only show summary if we have actual token usage
|
|
483
|
-
if total_tokens > 0 or total_cost > 0:
|
|
491
|
+
if state_manager.session.show_thoughts and (total_tokens > 0 or total_cost > 0):
|
|
484
492
|
summary = (
|
|
485
493
|
f"\n[bold cyan]TunaCode Session Summary[/bold cyan]\n"
|
|
486
494
|
f" - Total Tokens: {total_tokens:,}\n"
|
|
@@ -24,7 +24,6 @@ DEFAULT_USER_CONFIG: UserConfig = {
|
|
|
24
24
|
"fallback_response": True,
|
|
25
25
|
"fallback_verbosity": "normal", # Options: minimal, normal, detailed
|
|
26
26
|
"context_window_size": 200000,
|
|
27
|
-
"use_dspy_optimization": True, # Enable DSPy tool selection optimization
|
|
28
27
|
},
|
|
29
28
|
"mcpServers": {},
|
|
30
29
|
}
|
|
@@ -30,7 +30,6 @@ except ImportError:
|
|
|
30
30
|
STREAMING_AVAILABLE = False
|
|
31
31
|
|
|
32
32
|
from tunacode.constants import READ_ONLY_TOOLS
|
|
33
|
-
from tunacode.core.agents.dspy_integration import DSPyIntegration
|
|
34
33
|
from tunacode.core.recursive import RecursiveTaskExecutor
|
|
35
34
|
from tunacode.core.state import StateManager
|
|
36
35
|
from tunacode.core.token_usage.api_response_parser import ApiResponseParser
|
|
@@ -519,18 +518,6 @@ def get_or_create_agent(model: ModelName, state_manager: StateManager) -> Pydant
|
|
|
519
518
|
# Use a default system prompt if neither file exists
|
|
520
519
|
system_prompt = "You are a helpful AI assistant for software development tasks."
|
|
521
520
|
|
|
522
|
-
# Enhance with DSPy optimization if enabled
|
|
523
|
-
use_dspy = state_manager.session.user_config.get("settings", {}).get(
|
|
524
|
-
"use_dspy_optimization", True
|
|
525
|
-
)
|
|
526
|
-
if use_dspy:
|
|
527
|
-
try:
|
|
528
|
-
dspy_integration = DSPyIntegration(state_manager)
|
|
529
|
-
system_prompt = dspy_integration.enhance_system_prompt(system_prompt)
|
|
530
|
-
logger.info("Enhanced system prompt with DSPy optimizations")
|
|
531
|
-
except Exception as e:
|
|
532
|
-
logger.warning(f"Failed to enhance prompt with DSPy: {e}")
|
|
533
|
-
|
|
534
521
|
# Load TUNACODE.md context
|
|
535
522
|
# Use sync version of get_code_style to avoid nested event loop issues
|
|
536
523
|
try:
|
|
@@ -773,13 +760,6 @@ async def process_request(
|
|
|
773
760
|
"fallback_response", True
|
|
774
761
|
)
|
|
775
762
|
|
|
776
|
-
# Check if DSPy optimization is enabled and if this is a complex task
|
|
777
|
-
use_dspy = state_manager.session.user_config.get("settings", {}).get(
|
|
778
|
-
"use_dspy_optimization", True
|
|
779
|
-
)
|
|
780
|
-
dspy_integration = None
|
|
781
|
-
task_breakdown = None
|
|
782
|
-
|
|
783
763
|
# Check if recursive execution is enabled
|
|
784
764
|
use_recursive = state_manager.session.user_config.get("settings", {}).get(
|
|
785
765
|
"use_recursive_execution", True
|
|
@@ -788,39 +768,6 @@ async def process_request(
|
|
|
788
768
|
"recursive_complexity_threshold", 0.7
|
|
789
769
|
)
|
|
790
770
|
|
|
791
|
-
if use_dspy:
|
|
792
|
-
try:
|
|
793
|
-
dspy_integration = DSPyIntegration(state_manager)
|
|
794
|
-
|
|
795
|
-
# Check if this is a complex task that needs planning
|
|
796
|
-
if dspy_integration.should_use_task_planner(message):
|
|
797
|
-
task_breakdown = dspy_integration.get_task_breakdown(message)
|
|
798
|
-
if task_breakdown and task_breakdown.get("requires_todo"):
|
|
799
|
-
# Auto-create todos for complex tasks
|
|
800
|
-
from tunacode.tools.todo import TodoTool
|
|
801
|
-
|
|
802
|
-
todo_tool = TodoTool(state_manager=state_manager)
|
|
803
|
-
|
|
804
|
-
if state_manager.session.show_thoughts:
|
|
805
|
-
from tunacode.ui import console as ui
|
|
806
|
-
|
|
807
|
-
await ui.muted("DSPy: Detected complex task - creating todo list")
|
|
808
|
-
|
|
809
|
-
# Create todos from subtasks
|
|
810
|
-
todos = []
|
|
811
|
-
for subtask in task_breakdown["subtasks"][:5]: # Limit to first 5
|
|
812
|
-
todos.append(
|
|
813
|
-
{
|
|
814
|
-
"content": subtask["task"],
|
|
815
|
-
"priority": subtask.get("priority", "medium"),
|
|
816
|
-
}
|
|
817
|
-
)
|
|
818
|
-
|
|
819
|
-
if todos:
|
|
820
|
-
await todo_tool._execute(action="add_multiple", todos=todos)
|
|
821
|
-
except Exception as e:
|
|
822
|
-
logger.warning(f"DSPy task planning failed: {e}")
|
|
823
|
-
|
|
824
771
|
# Check if recursive execution should be used
|
|
825
772
|
if use_recursive and state_manager.session.current_recursion_depth == 0:
|
|
826
773
|
try:
|
|
@@ -853,25 +800,9 @@ async def process_request(
|
|
|
853
800
|
request=message, parent_task_id=None, depth=0
|
|
854
801
|
)
|
|
855
802
|
|
|
856
|
-
#
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
if success:
|
|
860
|
-
return AgentRun(
|
|
861
|
-
messages=[{"role": "assistant", "content": str(result)}],
|
|
862
|
-
timestamp=datetime.now(),
|
|
863
|
-
model=model,
|
|
864
|
-
iterations=1,
|
|
865
|
-
status="success",
|
|
866
|
-
)
|
|
867
|
-
else:
|
|
868
|
-
return AgentRun(
|
|
869
|
-
messages=[{"role": "assistant", "content": f"Task failed: {error}"}],
|
|
870
|
-
timestamp=datetime.now(),
|
|
871
|
-
model=model,
|
|
872
|
-
iterations=1,
|
|
873
|
-
status="error",
|
|
874
|
-
)
|
|
803
|
+
# For now, fall back to normal execution
|
|
804
|
+
# TODO: Properly integrate recursive execution results
|
|
805
|
+
pass
|
|
875
806
|
except Exception as e:
|
|
876
807
|
logger.warning(f"Recursive execution failed, falling back to normal: {e}")
|
|
877
808
|
# Continue with normal execution
|
|
@@ -39,7 +39,7 @@ class TaskResult:
|
|
|
39
39
|
|
|
40
40
|
task_id: str
|
|
41
41
|
task_title: str
|
|
42
|
-
result_data:
|
|
42
|
+
result_data: object
|
|
43
43
|
status: str # completed, failed, partial
|
|
44
44
|
timestamp: datetime = field(default_factory=datetime.now)
|
|
45
45
|
error: Optional[str] = None
|
|
@@ -50,7 +50,7 @@ class TaskResult:
|
|
|
50
50
|
class AggregatedResult:
|
|
51
51
|
"""Aggregated result from multiple tasks."""
|
|
52
52
|
|
|
53
|
-
primary_result:
|
|
53
|
+
primary_result: object
|
|
54
54
|
task_results: List[TaskResult]
|
|
55
55
|
strategy_used: AggregationStrategy
|
|
56
56
|
conflicts_resolved: int = 0
|
|
@@ -73,7 +73,7 @@ class TaskDecomposer:
|
|
|
73
73
|
# Get the main agent
|
|
74
74
|
agent = self.state_manager.session.agents.get("main")
|
|
75
75
|
if not agent:
|
|
76
|
-
logger.
|
|
76
|
+
logger.debug("Main agent not available, using heuristic decomposition")
|
|
77
77
|
return self._heuristic_decomposition(task_description)
|
|
78
78
|
|
|
79
79
|
# Build context-aware prompt
|
|
@@ -32,7 +32,7 @@ class TaskNode:
|
|
|
32
32
|
iteration_budget: int = 10
|
|
33
33
|
subtasks: List["TaskNode"] = field(default_factory=list)
|
|
34
34
|
status: str = "pending" # pending, in_progress, completed, failed
|
|
35
|
-
result: Optional[
|
|
35
|
+
result: Optional[object] = None
|
|
36
36
|
error: Optional[str] = None
|
|
37
37
|
context: Dict[str, Any] = field(default_factory=dict)
|
|
38
38
|
depth: int = 0
|
|
@@ -128,15 +128,17 @@ class RecursiveTaskExecutor:
|
|
|
128
128
|
and depth < self.max_depth - 1
|
|
129
129
|
):
|
|
130
130
|
# Decompose into subtasks
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
if self.state_manager.session.show_thoughts:
|
|
132
|
+
logger.info(
|
|
133
|
+
f"Decomposing complex task (score: {complexity_result.complexity_score:.2f})"
|
|
134
|
+
)
|
|
134
135
|
return await self._execute_with_decomposition(task_node, complexity_result)
|
|
135
136
|
else:
|
|
136
137
|
# Execute directly
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
if self.state_manager.session.show_thoughts:
|
|
139
|
+
logger.info(
|
|
140
|
+
f"Executing task directly (score: {complexity_result.complexity_score:.2f})"
|
|
141
|
+
)
|
|
140
142
|
return await self._execute_directly(task_node)
|
|
141
143
|
|
|
142
144
|
except Exception as e:
|
|
@@ -255,7 +257,8 @@ Respond in JSON format:
|
|
|
255
257
|
)
|
|
256
258
|
|
|
257
259
|
for i, (subtask_desc, budget) in enumerate(zip(subtasks, subtask_budgets)):
|
|
258
|
-
|
|
260
|
+
if self.state_manager.session.show_thoughts:
|
|
261
|
+
logger.info(f"Executing subtask {i + 1}/{len(subtasks)}: {subtask_desc[:50]}...")
|
|
259
262
|
|
|
260
263
|
# Create subtask context
|
|
261
264
|
subtask_context = {
|
|
@@ -9,6 +9,7 @@ from rich.padding import Padding
|
|
|
9
9
|
from rich.panel import Panel
|
|
10
10
|
from rich.pretty import Pretty
|
|
11
11
|
from rich.table import Table
|
|
12
|
+
from rich.text import Text
|
|
12
13
|
|
|
13
14
|
from tunacode.configuration.models import ModelRegistry
|
|
14
15
|
from tunacode.constants import (
|
|
@@ -89,9 +90,15 @@ class StreamingAgentPanel:
|
|
|
89
90
|
# Use the UI_THINKING_MESSAGE constant instead of hardcoded text
|
|
90
91
|
from tunacode.constants import UI_THINKING_MESSAGE
|
|
91
92
|
|
|
92
|
-
|
|
93
|
+
# If no content, show thinking message with Rich markup
|
|
94
|
+
if not self.content:
|
|
95
|
+
content_to_display = Text.from_markup(UI_THINKING_MESSAGE)
|
|
96
|
+
else:
|
|
97
|
+
# Normal content is markdown
|
|
98
|
+
content_to_display = Markdown(self.content)
|
|
99
|
+
|
|
93
100
|
panel_obj = Panel(
|
|
94
|
-
Padding(
|
|
101
|
+
Padding(content_to_display, (0, 1, 0, 1)),
|
|
95
102
|
title=f"[bold]{self.title}[/bold]",
|
|
96
103
|
title_align="left",
|
|
97
104
|
border_style=colors.primary,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tunacode-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.45
|
|
4
4
|
Summary: Your agentic CLI developer.
|
|
5
5
|
Author-email: larock22 <noreply@github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -25,8 +25,6 @@ Requires-Dist: pydantic-ai[logfire]==0.2.6
|
|
|
25
25
|
Requires-Dist: pygments==2.19.1
|
|
26
26
|
Requires-Dist: rich==14.0.0
|
|
27
27
|
Requires-Dist: tiktoken>=0.5.2
|
|
28
|
-
Requires-Dist: dspy-ai>=0.1.0
|
|
29
|
-
Requires-Dist: python-dotenv>=1.0.0
|
|
30
28
|
Provides-Extra: dev
|
|
31
29
|
Requires-Dist: build; extra == "dev"
|
|
32
30
|
Requires-Dist: ruff; extra == "dev"
|
|
@@ -34,8 +34,6 @@ src/tunacode/core/code_index.py
|
|
|
34
34
|
src/tunacode/core/state.py
|
|
35
35
|
src/tunacode/core/tool_handler.py
|
|
36
36
|
src/tunacode/core/agents/__init__.py
|
|
37
|
-
src/tunacode/core/agents/dspy_integration.py
|
|
38
|
-
src/tunacode/core/agents/dspy_tunacode.py
|
|
39
37
|
src/tunacode/core/agents/main.py
|
|
40
38
|
src/tunacode/core/agents/utils.py
|
|
41
39
|
src/tunacode/core/background/__init__.py
|
|
@@ -57,8 +55,6 @@ src/tunacode/core/setup/git_safety_setup.py
|
|
|
57
55
|
src/tunacode/core/token_usage/api_response_parser.py
|
|
58
56
|
src/tunacode/core/token_usage/cost_calculator.py
|
|
59
57
|
src/tunacode/core/token_usage/usage_tracker.py
|
|
60
|
-
src/tunacode/prompts/dspy_task_planning.md
|
|
61
|
-
src/tunacode/prompts/dspy_tool_selection.md
|
|
62
58
|
src/tunacode/prompts/system.md
|
|
63
59
|
src/tunacode/services/__init__.py
|
|
64
60
|
src/tunacode/services/mcp.py
|
|
@@ -135,7 +131,6 @@ tests/test_cli_file_operations_integration.py
|
|
|
135
131
|
tests/test_config_directory_creation.py
|
|
136
132
|
tests/test_config_setup_async.py
|
|
137
133
|
tests/test_cost_calculator.py
|
|
138
|
-
tests/test_dspy_integration.py
|
|
139
134
|
tests/test_enhanced_visual_feedback.py
|
|
140
135
|
tests/test_fallback_responses.py
|
|
141
136
|
tests/test_fast_glob_search.py
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from unittest.mock import AsyncMock, MagicMock, patch
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
import tunacode.cli.repl as repl_mod
|
|
6
|
+
from tunacode.constants import UI_COLORS
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.mark.asyncio
|
|
10
|
+
async def test_repl_initialization_basic(monkeypatch):
|
|
11
|
+
"""Test REPL startup: prints model, success, and line, and initializes agent/session."""
|
|
12
|
+
|
|
13
|
+
# Mock StateManager and session
|
|
14
|
+
state_manager = MagicMock()
|
|
15
|
+
state_manager.session.current_model = "gpt-test"
|
|
16
|
+
state_manager.session.input_sessions = {}
|
|
17
|
+
state_manager.session.show_thoughts = True # Enable thoughts to see startup messages
|
|
18
|
+
state_manager.session.total_tokens = 0
|
|
19
|
+
state_manager.session.max_tokens = 200000
|
|
20
|
+
state_manager.session.user_config = {"context_window_size": 200000}
|
|
21
|
+
|
|
22
|
+
def mock_update_token_count():
|
|
23
|
+
state_manager.session.total_tokens = 100
|
|
24
|
+
|
|
25
|
+
state_manager.session.update_token_count = MagicMock(side_effect=mock_update_token_count)
|
|
26
|
+
|
|
27
|
+
# Patch UI methods
|
|
28
|
+
with (
|
|
29
|
+
patch.object(repl_mod.ui, "muted", new=AsyncMock()) as muted,
|
|
30
|
+
patch.object(repl_mod.ui, "success", new=AsyncMock()) as success,
|
|
31
|
+
patch.object(repl_mod.ui, "line", new=AsyncMock()),
|
|
32
|
+
patch.object(repl_mod.agent, "get_or_create_agent") as get_agent,
|
|
33
|
+
):
|
|
34
|
+
# Mock agent instance and MCP context
|
|
35
|
+
agent_instance = MagicMock()
|
|
36
|
+
mcp_context = AsyncMock()
|
|
37
|
+
mcp_context.__aenter__ = AsyncMock(return_value=None)
|
|
38
|
+
mcp_context.__aexit__ = AsyncMock(return_value=None)
|
|
39
|
+
agent_instance.run_mcp_servers = MagicMock(return_value=mcp_context)
|
|
40
|
+
get_agent.return_value = agent_instance
|
|
41
|
+
|
|
42
|
+
# Patch the REPL loop to exit immediately
|
|
43
|
+
async def fake_multiline_input(*a, **kw):
|
|
44
|
+
return "exit"
|
|
45
|
+
|
|
46
|
+
with (
|
|
47
|
+
patch.object(repl_mod.ui, "multiline_input", new=fake_multiline_input),
|
|
48
|
+
patch.object(repl_mod.ui, "info", new=AsyncMock()) as info,
|
|
49
|
+
):
|
|
50
|
+
await repl_mod.repl(state_manager)
|
|
51
|
+
|
|
52
|
+
# Check that startup UI was called since show_thoughts is True
|
|
53
|
+
muted.assert_any_await(
|
|
54
|
+
f"• Model: gpt-test • [b]Context:[/] [{UI_COLORS['success']}]100/200,000 (0%)[/]"
|
|
55
|
+
)
|
|
56
|
+
success.assert_awaited()
|
|
57
|
+
get_agent.assert_called_once_with("gpt-test", state_manager)
|
|
58
|
+
info.assert_awaited_with("Session ended. Happy coding!")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@pytest.mark.asyncio
|
|
62
|
+
async def test_repl_initialization_no_thoughts_no_startup_messages(monkeypatch):
|
|
63
|
+
"""Test REPL startup: no startup messages shown when show_thoughts is False."""
|
|
64
|
+
|
|
65
|
+
# Mock StateManager and session
|
|
66
|
+
state_manager = MagicMock()
|
|
67
|
+
state_manager.session.current_model = "gpt-test"
|
|
68
|
+
state_manager.session.input_sessions = {}
|
|
69
|
+
state_manager.session.show_thoughts = False # Disable thoughts
|
|
70
|
+
state_manager.session.total_tokens = 0
|
|
71
|
+
state_manager.session.max_tokens = 200000
|
|
72
|
+
state_manager.session.user_config = {"context_window_size": 200000}
|
|
73
|
+
state_manager.session._startup_shown = True # Simulate not first run
|
|
74
|
+
|
|
75
|
+
def mock_update_token_count():
|
|
76
|
+
state_manager.session.total_tokens = 100
|
|
77
|
+
|
|
78
|
+
state_manager.session.update_token_count = MagicMock(side_effect=mock_update_token_count)
|
|
79
|
+
|
|
80
|
+
# Patch UI methods
|
|
81
|
+
with (
|
|
82
|
+
patch.object(repl_mod.ui, "muted", new=AsyncMock()) as muted,
|
|
83
|
+
patch.object(repl_mod.ui, "success", new=AsyncMock()) as success,
|
|
84
|
+
patch.object(repl_mod.ui, "line", new=AsyncMock()),
|
|
85
|
+
patch.object(repl_mod.agent, "get_or_create_agent") as get_agent,
|
|
86
|
+
):
|
|
87
|
+
# Mock agent instance and MCP context
|
|
88
|
+
agent_instance = MagicMock()
|
|
89
|
+
mcp_context = AsyncMock()
|
|
90
|
+
mcp_context.__aenter__ = AsyncMock(return_value=None)
|
|
91
|
+
mcp_context.__aexit__ = AsyncMock(return_value=None)
|
|
92
|
+
agent_instance.run_mcp_servers = MagicMock(return_value=mcp_context)
|
|
93
|
+
get_agent.return_value = agent_instance
|
|
94
|
+
|
|
95
|
+
# Patch the REPL loop to exit immediately
|
|
96
|
+
async def fake_multiline_input(*a, **kw):
|
|
97
|
+
return "exit"
|
|
98
|
+
|
|
99
|
+
with (
|
|
100
|
+
patch.object(repl_mod.ui, "multiline_input", new=fake_multiline_input),
|
|
101
|
+
patch.object(repl_mod.ui, "info", new=AsyncMock()) as info,
|
|
102
|
+
):
|
|
103
|
+
await repl_mod.repl(state_manager)
|
|
104
|
+
|
|
105
|
+
# Check that startup UI was NOT called since show_thoughts is False and not first run
|
|
106
|
+
assert not any("Model:" in str(call) for call in muted.await_args_list), (
|
|
107
|
+
"Startup model message should not be shown when show_thoughts is False"
|
|
108
|
+
)
|
|
109
|
+
assert not any("Ready to assist" in str(call) for call in success.await_args_list), (
|
|
110
|
+
"Startup success message should not be shown when show_thoughts is False"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
get_agent.assert_called_once_with("gpt-test", state_manager)
|
|
114
|
+
info.assert_awaited_with("Session ended. Happy coding!")
|