tunacode-cli 0.0.47__tar.gz → 0.0.48__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.47/src/tunacode_cli.egg-info → tunacode_cli-0.0.48}/PKG-INFO +3 -3
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/README.md +2 -2
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/pyproject.toml +1 -1
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/main.py +0 -4
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/repl.py +7 -14
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/configuration/defaults.py +1 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/constants.py +1 -6
- tunacode_cli-0.0.48/src/tunacode/core/agents/dspy_integration.py +223 -0
- tunacode_cli-0.0.48/src/tunacode/core/agents/dspy_tunacode.py +458 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/agents/main.py +237 -311
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/agents/utils.py +6 -54
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/state.py +0 -41
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/exceptions.py +0 -23
- tunacode_cli-0.0.48/src/tunacode/prompts/dspy_task_planning.md +45 -0
- tunacode_cli-0.0.48/src/tunacode/prompts/dspy_tool_selection.md +58 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/input.py +1 -2
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/keybindings.py +1 -17
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/panels.py +2 -9
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/token_counter.py +2 -1
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48/src/tunacode_cli.egg-info}/PKG-INFO +3 -3
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode_cli.egg-info/SOURCES.txt +6 -12
- tunacode_cli-0.0.48/tests/characterization/repl/test_repl_initialization.py +59 -0
- tunacode_cli-0.0.48/tests/test_dspy_integration.py +127 -0
- tunacode_cli-0.0.47/src/tunacode/core/recursive/__init__.py +0 -18
- tunacode_cli-0.0.47/src/tunacode/core/recursive/aggregator.py +0 -467
- tunacode_cli-0.0.47/src/tunacode/core/recursive/budget.py +0 -414
- tunacode_cli-0.0.47/src/tunacode/core/recursive/decomposer.py +0 -398
- tunacode_cli-0.0.47/src/tunacode/core/recursive/executor.py +0 -470
- tunacode_cli-0.0.47/src/tunacode/core/recursive/hierarchy.py +0 -487
- tunacode_cli-0.0.47/src/tunacode/ui/recursive_progress.py +0 -380
- tunacode_cli-0.0.47/src/tunacode/utils/retry.py +0 -163
- tunacode_cli-0.0.47/tests/characterization/repl/test_repl_initialization.py +0 -114
- tunacode_cli-0.0.47/tests/test_json_retry.py +0 -230
- tunacode_cli-0.0.47/tests/test_tool_batching_retry.py +0 -287
- tunacode_cli-0.0.47/tests/unit/test_recursive_executor.py +0 -218
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/CLAUDE.md +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/LICENSE +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/MANIFEST.in +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/TUNACODE.md +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/setup.cfg +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/setup.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/base.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/implementations/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/implementations/conversation.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/implementations/debug.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/implementations/development.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/implementations/model.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/implementations/system.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/implementations/todo.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/cli/commands/registry.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/configuration/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/configuration/models.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/configuration/settings.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/context.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/agents/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/background/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/background/manager.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/code_index.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/llm/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/setup/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/setup/agent_setup.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/setup/base.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/setup/config_setup.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/setup/coordinator.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/setup/environment_setup.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/setup/git_safety_setup.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/token_usage/api_response_parser.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/token_usage/cost_calculator.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/token_usage/usage_tracker.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/core/tool_handler.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/prompts/system.md +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/py.typed +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/services/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/services/mcp.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/setup.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/base.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/bash.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/glob.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/grep.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/list_dir.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/read_file.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/read_file_async_poc.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/run_command.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/todo.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/update_file.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/tools/write_file.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/types.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/completers.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/console.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/constants.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/decorators.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/lexers.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/output.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/prompt_manager.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/tool_ui.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/utils.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/ui/validators.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/bm25.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/diff_utils.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/file_utils.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/import_cache.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/message_utils.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/ripgrep.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/security.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/system.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/text_utils.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode/utils/user_configuration.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode_cli.egg-info/dependency_links.txt +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode_cli.egg-info/entry_points.txt +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode_cli.egg-info/requires.txt +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/src/tunacode_cli.egg-info/top_level.txt +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/agent/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/agent/conftest.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/agent/test_agent_creation.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/agent/test_json_tool_parsing.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/agent/test_process_node.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/agent/test_process_request.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/agent/test_tool_message_patching.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/background/test_background_edge_cases.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/background/test_cleanup.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/background/test_task_cancellation.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/background/test_task_creation.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/background/test_task_execution.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/code_index/test_cache_management.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/code_index/test_file_scanning.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/code_index/test_index_building.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/code_index/test_search_operations.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/code_index/test_symbol_extraction.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/commands/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/commands/test_init_command.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/conftest.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/context/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/context/test_context_acceptance.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/context/test_context_integration.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/context/test_context_loading.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/context/test_tunacode_logging.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/repl/test_command_parsing.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/repl/test_error_handling.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/repl/test_input_handling.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/repl/test_keyboard_interrupts.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/repl/test_multiline_input.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/repl/test_output_display_logic.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/repl/test_session_flow.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/services/test_error_recovery.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/services/test_llm_routing.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/services/test_mcp_integration.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/services/test_service_lifecycle.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/state/test_agent_tracking.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/state/test_message_history.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/state/test_permissions.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/state/test_session_management.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/state/test_state_initialization.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/state/test_user_config.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/test_characterization_commands.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/ui/test_async_ui.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/ui/test_console_output.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/ui/test_diff_display.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/ui/test_prompt_rendering.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/ui/test_tool_confirmations.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/utils/conftest.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/utils/test_expand_file_refs.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/utils/test_file_operations.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/utils/test_git_commands.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/utils/test_token_counting.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/characterization/utils/test_utils_edge_cases.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/conftest.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/crud/test_core_file_operations.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/fixtures/__init__.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/fixtures/file_operations.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/integration/test_error_recovery_flow.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/integration/test_full_session_flow.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/integration/test_mcp_tool_flow.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/integration/test_multi_tool_operations.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/integration/test_performance_scenarios.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/integration/test_usage_tracking_integration.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_actual_parallelism.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_agent_initialization.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_agent_output_formatting.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_api_response_parser.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_background_manager.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_agent_main.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_bash.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_commands_system.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_glob.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_grep.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_grep_performance.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_iteration_limits.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_list_dir.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_read_file.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_repl_utils.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_run_command.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_setup_system.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_tool_ui_behavior.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_update_file.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_utilities.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_characterization_write_file.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_cli_command_flow.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_cli_file_operations_integration.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_config_directory_creation.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_config_setup_async.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_cost_calculator.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_enhanced_visual_feedback.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_fallback_responses.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_fast_glob_search.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_file_operations_edge_cases.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_file_operations_stress.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_file_reference_context_tracking.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_file_reference_expansion.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_grep_fast_glob.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_grep_legacy_compat.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_grep_timeout.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_json_tool_parsing.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_list_dir.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_parallel_execution_demo.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_parallel_execution_freeze_fix.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_parallel_execution_integration.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_parallel_read_only_tools.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_parallel_tool_execution.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_prompt_changes_validation.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_read_only_confirmation.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_security.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_streaming_panel_tool_confirmation.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_streaming_spinner_conflict.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_todo_functionality.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_tool_categorization.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_tool_combinations.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_tool_handler_ui_messages.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_update_command.py +0 -0
- {tunacode_cli-0.0.47 → tunacode_cli-0.0.48}/tests/test_visual_parallel_feedback.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.48
|
|
4
4
|
Summary: Your agentic CLI developer.
|
|
5
5
|
Author-email: larock22 <noreply@github.com>
|
|
6
6
|
License: MIT
|
|
@@ -37,7 +37,7 @@ Requires-Dist: textual-dev; extra == "dev"
|
|
|
37
37
|
Requires-Dist: pre-commit; extra == "dev"
|
|
38
38
|
Dynamic: license-file
|
|
39
39
|
|
|
40
|
-
# TunaCode
|
|
40
|
+
# TunaCode CLI
|
|
41
41
|
|
|
42
42
|
<div align="center">
|
|
43
43
|
|
|
@@ -48,7 +48,7 @@ Dynamic: license-file
|
|
|
48
48
|
|
|
49
49
|
**AI-powered CLI coding assistant**
|
|
50
50
|
|
|
51
|
-

|
|
52
52
|
|
|
53
53
|
</div>
|
|
54
54
|
|
|
@@ -5,7 +5,6 @@ Enhanced CLI entry point with better styling while staying CLI-based.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import asyncio
|
|
8
|
-
import logging
|
|
9
8
|
|
|
10
9
|
import typer
|
|
11
10
|
|
|
@@ -37,9 +36,6 @@ def main(
|
|
|
37
36
|
):
|
|
38
37
|
"""Start TunaCode - Your AI-powered development assistant"""
|
|
39
38
|
|
|
40
|
-
# Configure logging to suppress INFO messages by default
|
|
41
|
-
logging.basicConfig(level=logging.WARNING, force=True)
|
|
42
|
-
|
|
43
39
|
async def async_main():
|
|
44
40
|
if version:
|
|
45
41
|
await ui.version()
|
|
@@ -344,7 +344,7 @@ async def process_request(text: str, state_manager: StateManager, output: bool =
|
|
|
344
344
|
except CancelledError:
|
|
345
345
|
await ui.muted(MSG_REQUEST_CANCELLED)
|
|
346
346
|
except UserAbortError:
|
|
347
|
-
await ui.muted(
|
|
347
|
+
await ui.muted(MSG_OPERATION_ABORTED)
|
|
348
348
|
except UnexpectedModelBehavior as e:
|
|
349
349
|
error_message = str(e)
|
|
350
350
|
await ui.muted(error_message)
|
|
@@ -385,13 +385,9 @@ 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
|
-
|
|
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
|
|
388
|
+
await ui.muted(f"• Model: {model_name} • {context_display}")
|
|
389
|
+
await ui.success("Ready to assist")
|
|
390
|
+
await ui.line()
|
|
395
391
|
|
|
396
392
|
instance = agent.get_or_create_agent(state_manager.session.current_model, state_manager)
|
|
397
393
|
|
|
@@ -463,16 +459,13 @@ async def repl(state_manager: StateManager):
|
|
|
463
459
|
state_manager.session.current_task = get_app().create_background_task(
|
|
464
460
|
process_request(line, state_manager)
|
|
465
461
|
)
|
|
462
|
+
await state_manager.session.current_task
|
|
466
463
|
|
|
467
464
|
state_manager.session.update_token_count()
|
|
468
465
|
context_display = get_context_window_display(
|
|
469
466
|
state_manager.session.total_tokens, state_manager.session.max_tokens
|
|
470
467
|
)
|
|
471
|
-
|
|
472
|
-
if state_manager.session.show_thoughts:
|
|
473
|
-
await ui.muted(
|
|
474
|
-
f"• Model: {state_manager.session.current_model} • {context_display}"
|
|
475
|
-
)
|
|
468
|
+
await ui.muted(f"• Model: {state_manager.session.current_model} • {context_display}")
|
|
476
469
|
|
|
477
470
|
if action == "restart":
|
|
478
471
|
await repl(state_manager)
|
|
@@ -487,7 +480,7 @@ async def repl(state_manager: StateManager):
|
|
|
487
480
|
total_cost = float(session_total.get("cost", 0) or 0)
|
|
488
481
|
|
|
489
482
|
# Only show summary if we have actual token usage
|
|
490
|
-
if
|
|
483
|
+
if total_tokens > 0 or total_cost > 0:
|
|
491
484
|
summary = (
|
|
492
485
|
f"\n[bold cyan]TunaCode Session Summary[/bold cyan]\n"
|
|
493
486
|
f" - Total Tokens: {total_tokens:,}\n"
|
|
@@ -24,6 +24,7 @@ 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
|
|
27
28
|
},
|
|
28
29
|
"mcpServers": {},
|
|
29
30
|
}
|
|
@@ -7,7 +7,7 @@ Centralizes all magic strings, UI text, error messages, and application constant
|
|
|
7
7
|
|
|
8
8
|
# Application info
|
|
9
9
|
APP_NAME = "TunaCode"
|
|
10
|
-
APP_VERSION = "0.0.
|
|
10
|
+
APP_VERSION = "0.0.48"
|
|
11
11
|
|
|
12
12
|
# File patterns
|
|
13
13
|
GUIDE_FILE_PATTERN = "{name}.md"
|
|
@@ -157,8 +157,3 @@ MAX_TODOS_PER_SESSION = 100
|
|
|
157
157
|
|
|
158
158
|
# Maximum length for todo content
|
|
159
159
|
MAX_TODO_CONTENT_LENGTH = 500
|
|
160
|
-
|
|
161
|
-
# JSON parsing retry configuration
|
|
162
|
-
JSON_PARSE_MAX_RETRIES = 10
|
|
163
|
-
JSON_PARSE_BASE_DELAY = 0.1 # Initial delay in seconds
|
|
164
|
-
JSON_PARSE_MAX_DELAY = 5.0 # Maximum delay in seconds
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""DSPy Integration for TunaCode - Enhanced Tool Selection and Task Planning.
|
|
2
|
+
|
|
3
|
+
This module integrates DSPy's optimized prompts and tool selection logic
|
|
4
|
+
into TunaCode's agent system for 3x performance improvements.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
import re
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
from tunacode.core.state import StateManager
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DSPyIntegration:
|
|
19
|
+
"""Integrates DSPy optimization into TunaCode's agent system."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, state_manager: StateManager):
|
|
22
|
+
self.state_manager = state_manager
|
|
23
|
+
self._dspy_agent = None
|
|
24
|
+
self._tool_selection_prompt = None
|
|
25
|
+
self._task_planning_prompt = None
|
|
26
|
+
self._load_prompts()
|
|
27
|
+
|
|
28
|
+
def _load_prompts(self):
|
|
29
|
+
"""Load DSPy-optimized prompts from files."""
|
|
30
|
+
prompts_dir = Path(__file__).parent.parent.parent / "prompts"
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
# Load tool selection prompt
|
|
34
|
+
tool_selection_path = prompts_dir / "dspy_tool_selection.md"
|
|
35
|
+
if tool_selection_path.exists():
|
|
36
|
+
self._tool_selection_prompt = tool_selection_path.read_text(encoding="utf-8")
|
|
37
|
+
logger.debug("Loaded DSPy tool selection prompt")
|
|
38
|
+
|
|
39
|
+
# Load task planning prompt
|
|
40
|
+
task_planning_path = prompts_dir / "dspy_task_planning.md"
|
|
41
|
+
if task_planning_path.exists():
|
|
42
|
+
self._task_planning_prompt = task_planning_path.read_text(encoding="utf-8")
|
|
43
|
+
logger.debug("Loaded DSPy task planning prompt")
|
|
44
|
+
except Exception as e:
|
|
45
|
+
logger.error(f"Failed to load DSPy prompts: {e}")
|
|
46
|
+
|
|
47
|
+
def get_dspy_agent(self, api_key: Optional[str] = None):
|
|
48
|
+
"""Get or create the DSPy agent instance."""
|
|
49
|
+
if self._dspy_agent is None:
|
|
50
|
+
try:
|
|
51
|
+
# Import DSPy components
|
|
52
|
+
from tunacode.core.agents.dspy_tunacode import create_optimized_agent
|
|
53
|
+
|
|
54
|
+
# Use API key from environment or config
|
|
55
|
+
if not api_key:
|
|
56
|
+
api_key = os.getenv(
|
|
57
|
+
"OPENROUTER_API_KEY"
|
|
58
|
+
) or self.state_manager.session.user_config.get("env", {}).get(
|
|
59
|
+
"OPENROUTER_API_KEY"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if api_key:
|
|
63
|
+
self._dspy_agent = create_optimized_agent(api_key)
|
|
64
|
+
logger.info("DSPy agent initialized successfully")
|
|
65
|
+
else:
|
|
66
|
+
logger.warning("No OpenRouter API key found for DSPy optimization")
|
|
67
|
+
except Exception as e:
|
|
68
|
+
logger.error(f"Failed to initialize DSPy agent: {e}")
|
|
69
|
+
|
|
70
|
+
return self._dspy_agent
|
|
71
|
+
|
|
72
|
+
def enhance_system_prompt(self, base_prompt: str) -> str:
|
|
73
|
+
"""Enhance the system prompt with DSPy optimizations."""
|
|
74
|
+
if not self._tool_selection_prompt:
|
|
75
|
+
return base_prompt
|
|
76
|
+
|
|
77
|
+
# Extract the learned patterns from DSPy prompts
|
|
78
|
+
enhanced_sections = []
|
|
79
|
+
|
|
80
|
+
# Add DSPy tool selection insights
|
|
81
|
+
enhanced_sections.append("\n\n# DSPy-Optimized Tool Selection Patterns\n")
|
|
82
|
+
enhanced_sections.append("**Based on learned optimization patterns:**\n")
|
|
83
|
+
enhanced_sections.append("- Always batch 3-4 read-only tools for parallel execution")
|
|
84
|
+
enhanced_sections.append("- Group grep, list_dir, glob, read_file operations together")
|
|
85
|
+
enhanced_sections.append("- Execute write/modify operations sequentially")
|
|
86
|
+
enhanced_sections.append("- Use Chain of Thought reasoning for tool selection\n")
|
|
87
|
+
|
|
88
|
+
# Add specific examples from DSPy prompt
|
|
89
|
+
if "Example" in self._tool_selection_prompt:
|
|
90
|
+
enhanced_sections.append("\n## Optimal Tool Batching Examples:\n")
|
|
91
|
+
# Extract examples section
|
|
92
|
+
examples_match = re.search(
|
|
93
|
+
r"### Example.*?(?=###|\Z)", self._tool_selection_prompt, re.DOTALL
|
|
94
|
+
)
|
|
95
|
+
if examples_match:
|
|
96
|
+
enhanced_sections.append(examples_match.group(0))
|
|
97
|
+
|
|
98
|
+
return base_prompt + "".join(enhanced_sections)
|
|
99
|
+
|
|
100
|
+
def should_use_task_planner(self, user_request: str) -> bool:
|
|
101
|
+
"""Determine if the request is complex enough for task planning."""
|
|
102
|
+
complex_indicators = [
|
|
103
|
+
"implement",
|
|
104
|
+
"create",
|
|
105
|
+
"build",
|
|
106
|
+
"refactor",
|
|
107
|
+
"add feature",
|
|
108
|
+
"fix all",
|
|
109
|
+
"update multiple",
|
|
110
|
+
"migrate",
|
|
111
|
+
"integrate",
|
|
112
|
+
"debug",
|
|
113
|
+
"optimize performance",
|
|
114
|
+
"authentication",
|
|
115
|
+
"setup",
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
request_lower = user_request.lower()
|
|
119
|
+
|
|
120
|
+
# Check for multiple files
|
|
121
|
+
file_pattern = r"\b\w+\.\w+\b"
|
|
122
|
+
files_mentioned = len(re.findall(file_pattern, user_request)) > 2
|
|
123
|
+
|
|
124
|
+
# Check for complex keywords
|
|
125
|
+
has_complex_keyword = any(indicator in request_lower for indicator in complex_indicators)
|
|
126
|
+
|
|
127
|
+
# Check for multiple operations
|
|
128
|
+
operation_words = ["and", "then", "also", "after", "before", "plus"]
|
|
129
|
+
has_multiple_ops = sum(1 for word in operation_words if word in request_lower) >= 2
|
|
130
|
+
|
|
131
|
+
return files_mentioned or has_complex_keyword or has_multiple_ops
|
|
132
|
+
|
|
133
|
+
def optimize_tool_selection(
|
|
134
|
+
self, user_request: str, tools_to_execute: List[Dict[str, Any]]
|
|
135
|
+
) -> List[List[Dict[str, Any]]]:
|
|
136
|
+
"""Optimize tool selection using DSPy patterns.
|
|
137
|
+
|
|
138
|
+
Returns tool calls organized in optimal batches for parallel execution.
|
|
139
|
+
"""
|
|
140
|
+
if not tools_to_execute:
|
|
141
|
+
return []
|
|
142
|
+
|
|
143
|
+
# Try to use DSPy agent if available
|
|
144
|
+
dspy_agent = self.get_dspy_agent()
|
|
145
|
+
if dspy_agent:
|
|
146
|
+
try:
|
|
147
|
+
result = dspy_agent(user_request, self.state_manager.session.cwd or ".")
|
|
148
|
+
if hasattr(result, "tool_batches") and result.tool_batches:
|
|
149
|
+
return result.tool_batches
|
|
150
|
+
except Exception as e:
|
|
151
|
+
logger.debug(f"DSPy optimization failed, using fallback: {e}")
|
|
152
|
+
|
|
153
|
+
# Fallback: Apply DSPy-learned patterns manually
|
|
154
|
+
return self._apply_dspy_patterns(tools_to_execute)
|
|
155
|
+
|
|
156
|
+
def _apply_dspy_patterns(self, tools: List[Dict[str, Any]]) -> List[List[Dict[str, Any]]]:
|
|
157
|
+
"""Apply DSPy-learned batching patterns manually."""
|
|
158
|
+
from tunacode.constants import READ_ONLY_TOOLS
|
|
159
|
+
|
|
160
|
+
batches = []
|
|
161
|
+
current_batch = []
|
|
162
|
+
|
|
163
|
+
for tool in tools:
|
|
164
|
+
tool_name = tool.get("tool", "")
|
|
165
|
+
|
|
166
|
+
if tool_name in READ_ONLY_TOOLS:
|
|
167
|
+
current_batch.append(tool)
|
|
168
|
+
# Optimal batch size is 3-4 tools
|
|
169
|
+
if len(current_batch) >= 4:
|
|
170
|
+
batches.append(current_batch)
|
|
171
|
+
current_batch = []
|
|
172
|
+
else:
|
|
173
|
+
# Flush current batch if any
|
|
174
|
+
if current_batch:
|
|
175
|
+
batches.append(current_batch)
|
|
176
|
+
current_batch = []
|
|
177
|
+
# Add write/execute tool as single batch
|
|
178
|
+
batches.append([tool])
|
|
179
|
+
|
|
180
|
+
# Add remaining tools
|
|
181
|
+
if current_batch:
|
|
182
|
+
batches.append(current_batch)
|
|
183
|
+
|
|
184
|
+
return batches
|
|
185
|
+
|
|
186
|
+
def get_task_breakdown(self, complex_request: str) -> Optional[Dict[str, Any]]:
|
|
187
|
+
"""Get task breakdown for complex requests using DSPy."""
|
|
188
|
+
dspy_agent = self.get_dspy_agent()
|
|
189
|
+
if not dspy_agent:
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
result = dspy_agent(complex_request, self.state_manager.session.cwd or ".")
|
|
194
|
+
if result.get("is_complex") and result.get("subtasks"):
|
|
195
|
+
return {
|
|
196
|
+
"subtasks": result["subtasks"],
|
|
197
|
+
"total_tool_calls": result.get("total_tool_calls", 0),
|
|
198
|
+
"requires_todo": result.get("requires_todo", False),
|
|
199
|
+
"parallelization_opportunities": result.get("parallelization_opportunities", 0),
|
|
200
|
+
}
|
|
201
|
+
except Exception as e:
|
|
202
|
+
logger.error(f"Failed to get task breakdown: {e}")
|
|
203
|
+
|
|
204
|
+
return None
|
|
205
|
+
|
|
206
|
+
def format_chain_of_thought(self, request: str, tools: List[str]) -> str:
|
|
207
|
+
"""Format a Chain of Thought reasoning for tool selection."""
|
|
208
|
+
reasoning = f"Let's think step by step about '{request}':\n"
|
|
209
|
+
|
|
210
|
+
if "search" in request.lower() or "find" in request.lower():
|
|
211
|
+
reasoning += "1. This requires searching for information\n"
|
|
212
|
+
reasoning += "2. I'll use grep for content search and glob for file patterns\n"
|
|
213
|
+
reasoning += "3. These read-only tools can be executed in parallel\n"
|
|
214
|
+
elif "read" in request.lower() or "show" in request.lower():
|
|
215
|
+
reasoning += "1. This requires reading file contents\n"
|
|
216
|
+
reasoning += "2. I'll batch multiple read_file operations together\n"
|
|
217
|
+
reasoning += "3. All reads can happen in parallel for speed\n"
|
|
218
|
+
elif "fix" in request.lower() or "update" in request.lower():
|
|
219
|
+
reasoning += "1. First, I need to understand the current state\n"
|
|
220
|
+
reasoning += "2. I'll search and read relevant files in parallel\n"
|
|
221
|
+
reasoning += "3. Then make modifications sequentially for safety\n"
|
|
222
|
+
|
|
223
|
+
return reasoning
|